From add7a122ac2b3515ce38c852ff3c0a855eabd922 Mon Sep 17 00:00:00 2001 From: ayanamist Date: Thu, 28 Feb 2013 11:01:32 +0800 Subject: [PATCH] Rewrite with Tornado --- server.py | 202 +++++++++++++++++++++++++++--------------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/server.py b/server.py index 14dac1f..9ca8b38 100755 --- a/server.py +++ b/server.py @@ -22,8 +22,6 @@ import sys import socket -import select -import SocketServer import struct import string import hashlib @@ -32,122 +30,124 @@ import json import logging import getopt - -def get_table(key): - m = hashlib.md5() - m.update(key) - s = m.digest() - (a, b) = struct.unpack('H', self.decrypt(self.rfile.read(2))) - try: - logging.info('connecting %s:%d' % (addr, port[0])) - remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - remote.connect((addr, port[0])) - except socket.error, e: - # Connection refused - logging.warn(e) - return - self.handle_tcp(sock, remote) - except socket.error, e: - logging.warn(e) + return data.translate(self._decrypt_table) -if __name__ == '__main__': - os.chdir(os.path.dirname(__file__) or '.') +class Socks5Server(netutil.TCPServer): + def handle_stream(self, stream, address): + soc = stream.socket + soc.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) + ConnHandler(soc).wait_for_data() - print 'shadowsocks v0.9.3' - with open('config.json', 'rb') as f: +class PairedStream(iostream.IOStream): + def on_close(self): + remote = getattr(self, "remote") + if isinstance(remote, PairedStream) and not remote.closed(): + remote.close() + + +class ConnHandler(PairedStream): + def wait_for_data(self): + self.read_bytes(1, self.on_addrtype) + + def on_addrtype(self, addrtype): + addrtype = ord(crypto.decrypt(addrtype)) + if addrtype == 1: + self.read_bytes(4, self.on_addr1) + elif addrtype == 3: + self.read_bytes(1, self.on_addr3_length) + else: + # not support + logging.warn('addr_type not support') + self.close() + + def on_addr1(self, addr): + self.remote_addr = socket.inet_ntoa(crypto.decrypt(addr)) + self.read_bytes(2, self.on_port) + + def on_addr3_length(self, length): + length = ord(crypto.decrypt(length)) + self.read_bytes(length, self.on_addr3) + + def on_addr3(self, addr): + self.remote_addr = crypto.decrypt(addr) + self.read_bytes(2, self.on_port) + + def on_port(self, port): + self.remote_port = struct.unpack('>H', crypto.decrypt(port))[0] + logging.debug("Connecting to %s:%d" % (self.remote_addr, self.remote_port)) + remote_soc = socket.socket() + remote_soc.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) + self.remote = PairedStream(remote_soc) + self.set_close_callback(self.remote.on_close) + self.remote.set_close_callback(self.on_close) + + self.remote.connect((self.remote_addr, self.remote_port), self.on_remote_connected) + + def on_remote_connected(self): + self.read_until_close(callback=self.on_client_read, streaming_callback=self.on_client_read) + self.remote.read_until_close(callback=self.on_remote_read, streaming_callback=self.on_remote_read) + + def on_client_read(self, data): + self.remote.write(crypto.encrypt(data)) + + def on_remote_read(self, data): + self.write(crypto.decrypt(data)) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') + with open(os.path.join(os.path.dirname(__file__), "config.json"), "rb") as f: config = json.load(f) - SERVER = config['server'] - PORT = config['server_port'] - KEY = config['password'] + server_port = config['server_port'] + server_password = config['password'] optlist, args = getopt.getopt(sys.argv[1:], 'p:k:') for key, value in optlist: if key == '-p': - PORT = int(value) + server_port = int(value) elif key == '-k': - KEY = value + server_password = value - logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') - - encrypt_table = ''.join(get_table(KEY)) - decrypt_table = string.maketrans(encrypt_table, string.maketrans('', '')) if '-6' in sys.argv[1:]: - ThreadingTCPServer.address_family = socket.AF_INET6 - try: - server = ThreadingTCPServer(('', PORT), Socks5Server) - logging.info("starting server at port %d ..." % PORT) - server.serve_forever() - except socket.error, e: - logging.error(e) + address_family = socket.AF_INET6 + else: + address_family = socket.AF_INET + crypto = Crypto(server_password) + + logging.info("starting server at port %d ..." % server_port) + server = Socks5Server() + server.bind(port=server_port, family=address_family) + server.start() + try: + ioloop.IOLoop.instance().start() + except KeyboardInterrupt: + pass + except Exception: + logging.exception("Uncaught Exception")