-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
151 lines (126 loc) · 5.14 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env python
# coding:utf-8
from lib.socket_engine import TCPSocketEngine, Connection
import lib.io_poll as io_poll
from lib.log import Log
import mod.proto as proto
import mod.crypter as crypter
import socket
import lib.daemon as daemon
import signal
import sys
import os
import config_server as config
from mod.common import TransWarpBase
class TransWarpServer (TransWarpBase):
def __init__(self):
TransWarpBase.__init__(self)
self.logger = Log("server", config=config)
self.engine.set_logger(self.logger)
self.addr = config.SERVER_ADDR
self.auth_keys = config.ACCEPT_KEYS
self.passive_sock = None
def _new_client(self, sock):
conn = Connection(sock)
print "new %s" % (str(conn.peer))
self.engine.read_unblock(
conn, self.head_len, self._on_recv_head, None, cb_args=(self._auth, ))
def _auth(self, cli_conn):
auth_data = None
try:
auth_data = proto.AuthData.deserialize(
cli_conn.get_readbuf(), self.auth_keys)
except Exception, e:
self.logger.exception("peer %s %s" % (cli_conn.peer, str(e)))
if not auth_data:
self.logger.warn("peer %s not authorized" % (str(cli_conn.peer)))
self.engine.close_conn(cli_conn)
return
client = proto.ClientData(
auth_data.r_host, auth_data.r_port, cli_conn,
auth_data.seed, auth_data.key)
self.engine.remove_conn(cli_conn)
self.client_conn[client.client_id] = client
self.logger.info("client %s auth" % (client.client_id))
client.cli_state = proto.ClientState.CONNECTING
self.engine.connect_unblock(
(client.r_host, client.r_port), self._on_remote_conn, self._on_remote_conn_err, cb_args=(client, ))
resp = proto.ServerResponse(0, "")
buf = client.crypter_w.encrypt(resp.serialize())
def _write_ok(cli_conn, *args):
client.cli_state = proto.ClientState.CONNECTED
self._check_client_state(client)
return
self.engine.write_unblock(client.cli_conn, proto.pack_head(
len(buf)) + buf, _write_ok, self._on_err, cb_args=(client, ))
def _check_client_state(self, client):
if client.cli_state == proto.ClientState.CONNECTED and client.r_state == proto.ClientState.CONNECTED:
self.engine.put_sock(
client.cli_conn.sock, readable_cb=self._on_client_readable, readable_cb_args=(
client,),
idle_timeout_cb=self._on_idle)
self.engine.put_sock(
client.r_conn.sock, readable_cb=self._on_remote_readable, readable_cb_args=(
client,),
idle_timeout_cb=self._on_idle)
self.logger.info(
"client %s establish both connection" % (client.client_id))
def _on_remote_readable(self, r_conn, client):
print "remote %s readable" % (client.client_id)
self.stream_to_fix(r_conn, client.cli_conn, client)
def _on_client_readable(self, cli_conn, client):
print "client %s readable" % (client.client_id)
self.fix_to_stream(cli_conn, client.r_conn, client)
def _on_remote_conn(self, sock, client):
client.r_state = proto.ClientState.CONNECTED
client.r_conn = Connection(sock)
self._check_client_state(client)
def _on_remote_conn_err(self, error, client):
self.logger.warn("client %s: connection failed, %s" %
(client.client_id, str(error)))
self.close_client(client)
def start(self):
if self.is_running:
return
self.passive_sock = self.engine.listen_addr(
self.addr, readable_cb=None, new_conn_cb=self._new_client, backlog=50)
self.is_running = True
self.logger.info("started")
def stop(self):
if not self.is_running:
return
if self.passive_sock:
self.engine.unlisten(self.passive_sock)
self.is_running = False
self.logger.info("stopped")
stop_signal_flag = False
def main():
server = TransWarpServer()
def exit_sig_handler(sig_num, frm):
global stop_signal_flag
if stop_signal_flag:
return
stop_signal_flag = True
server.stop()
return
server.start()
signal.signal(signal.SIGTERM, exit_sig_handler)
signal.signal(signal.SIGINT, exit_sig_handler)
server.loop()
return
def usage():
print "usage:\t%s star/stop/restart\t#manage forked daemon" % (sys.argv[0])
print "\t%s run\t\t# run without daemon, for test purpose" % (sys.argv[0])
os._exit(1)
if __name__ == '__main__':
if len(sys.argv) <= 1:
usage()
else:
logger = Log("daemon", config=config)
# to ensure log is permitted to write
pid_file = "transwarp_srv.pid"
mon_pid_file = "transwarp_srv_mon.pid"
action = sys.argv[1]
daemon.cmd_wrapper(action, main, usage, logger,
config.log_dir, config.RUN_DIR, pid_file, mon_pid_file)
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 :