From c2f6bc369cc3642c5810539857da2116a9f0d40c Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sun, 1 Jun 2014 11:01:11 +0800 Subject: [PATCH] more work --- shadowsocks/common.py | 46 ++++++++++++++++++++++++++++++++++++++++- shadowsocks/server.py | 11 ++++++---- shadowsocks/tcprelay.py | 26 +++++++++++++++++++---- shadowsocks/udprelay.py | 8 ++++--- shadowsocks/utils.py | 44 --------------------------------------- 5 files changed, 79 insertions(+), 56 deletions(-) diff --git a/shadowsocks/common.py b/shadowsocks/common.py index 256fbef..ca5fb21 100644 --- a/shadowsocks/common.py +++ b/shadowsocks/common.py @@ -26,6 +26,50 @@ import struct import logging +def inet_ntop(family, ipstr): + if family == socket.AF_INET: + return socket.inet_ntoa(ipstr) + elif family == socket.AF_INET6: + v6addr = ':'.join(('%02X%02X' % (ord(i), ord(j))) + for i, j in zip(ipstr[::2], ipstr[1::2])) + return v6addr + + +def inet_pton(family, addr): + if family == socket.AF_INET: + return socket.inet_aton(addr) + elif family == socket.AF_INET6: + if '.' in addr: # a v4 addr + v4addr = addr[addr.rindex(':') + 1:] + v4addr = socket.inet_aton(v4addr) + v4addr = map(lambda x: ('%02X' % ord(x)), v4addr) + v4addr.insert(2, ':') + newaddr = addr[:addr.rindex(':') + 1] + ''.join(v4addr) + return inet_pton(family, newaddr) + dbyts = [0] * 8 # 8 groups + grps = addr.split(':') + for i, v in enumerate(grps): + if v: + dbyts[i] = int(v, 16) + else: + for j, w in enumerate(grps[::-1]): + if w: + dbyts[7 - j] = int(w, 16) + else: + break + break + return ''.join((chr(i // 256) + chr(i % 256)) for i in dbyts) + else: + raise RuntimeError("What family?") + + +if not hasattr(socket, 'inet_pton'): + socket.inet_pton = inet_pton + +if not hasattr(socket, 'inet_ntop'): + socket.inet_ntop = inet_ntop + + def parse_header(data): addrtype = ord(data[0]) dest_addr = None @@ -61,4 +105,4 @@ def parse_header(data): logging.warn('unsupported addrtype %d, maybe wrong password' % addrtype) if dest_addr is None: return None - return (addrtype, dest_addr, dest_port, header_length) + return addrtype, dest_addr, dest_port, header_length diff --git a/shadowsocks/server.py b/shadowsocks/server.py index 43fac82..d7fd215 100755 --- a/shadowsocks/server.py +++ b/shadowsocks/server.py @@ -243,9 +243,12 @@ def main(): ThreadingTCPServer.address_family = addrs[0][0] tcp_servers = [] udp_servers = [] - for port, key in config['port_password'].items(): + for port, password in config['port_password'].items(): + a_config = config.copy() + a_config['server_port'] = port + a_config['password'] = password logging.info("starting server at %s:%d" % - tuple(tcp_server.server_address[:2])) + (a_config['server'], port)) tcp_server = tcprelay.TCPRelay(config, False) tcp_servers.append(tcp_server) udp_server = udprelay.UDPRelay(config, False) @@ -257,11 +260,11 @@ def main(): for udp_server in udp_servers: udp_server.start() - if int(config_workers) > 1: + if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False - for i in xrange(0, int(config_workers)): + for i in xrange(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index 3ce8b54..039eed9 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -26,6 +26,7 @@ import socket import logging import encrypt import errno +import threading import eventloop from common import parse_header @@ -121,8 +122,8 @@ class TCPRelayHandler(object): # forward address to remote self._data_to_write_to_remote.append(data[:header_length]) self.write_all_to_sock('\x05\x00\x00\x01' + - '\x00\x00\x00\x00\x10\x10', - self._local_sock) + '\x00\x00\x00\x00\x10\x10', + self._local_sock) else: remote_addr = self._config['server'] remote_port = self._config['server_port'] @@ -230,6 +231,7 @@ class TCPRelay(object): self._config = config self._is_local = is_local self._closed = False + self._thread = None self._fd_to_handlers = {} if is_local: @@ -270,8 +272,8 @@ class TCPRelay(object): if sock == self._server_socket: try: conn = self._server_socket.accept() - TCPRelayHandler(self._eventloop, conn, self._config, - self._is_local) + TCPRelayHandler(self._fd_to_handlers, self._eventloop, + conn, self._config, self._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in [errno.EAGAIN, errno.EINPROGRESS]: @@ -287,3 +289,19 @@ class TCPRelay(object): if now - last_time > 5: # TODO sweep timeouts last_time = now + + def start(self): + if self._closed: + raise Exception('closed') + t = threading.Thread(target=self._run) + t.setName('UDPThread') + t.setDaemon(False) + t.start() + self._thread = t + + def close(self): + self._closed = True + self._server_socket.close() + + def thread(self): + return self._thread \ No newline at end of file diff --git a/shadowsocks/udprelay.py b/shadowsocks/udprelay.py index 68f6474..8950de4 100644 --- a/shadowsocks/udprelay.py +++ b/shadowsocks/udprelay.py @@ -101,10 +101,12 @@ class UDPRelay(object): self._method = config['method'] self._timeout = config['timeout'] self._is_local = is_local - self._cache = lru_cache.LRUCache(timeout=timeout, + self._cache = lru_cache.LRUCache(timeout=config['timeout'], close_callback=self._close_client) - self._client_fd_to_server_addr = lru_cache.LRUCache(timeout=timeout) + self._client_fd_to_server_addr = \ + lru_cache.LRUCache(timeout=config['timeout']) self._closed = False + self._thread = None addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) @@ -206,7 +208,7 @@ class UDPRelay(object): return # addrtype, dest_addr, dest_port, header_length = header_result response = '\x00\x00\x00' + data - client_addr = self._client_fd_to_server_addr.get(sock.fileno(), None) + client_addr = self._client_fd_to_server_addr.get(sock.fileno()) if client_addr: self._server_socket.sendto(response, client_addr) else: diff --git a/shadowsocks/utils.py b/shadowsocks/utils.py index f37eed9..05e45b4 100644 --- a/shadowsocks/utils.py +++ b/shadowsocks/utils.py @@ -22,53 +22,9 @@ # SOFTWARE. import os -import socket import logging -def inet_ntop(family, ipstr): - if family == socket.AF_INET: - return socket.inet_ntoa(ipstr) - elif family == socket.AF_INET6: - v6addr = ':'.join(('%02X%02X' % (ord(i), ord(j))) - for i, j in zip(ipstr[::2], ipstr[1::2])) - return v6addr - - -def inet_pton(family, addr): - if family == socket.AF_INET: - return socket.inet_aton(addr) - elif family == socket.AF_INET6: - if '.' in addr: # a v4 addr - v4addr = addr[addr.rindex(':') + 1:] - v4addr = socket.inet_aton(v4addr) - v4addr = map(lambda x: ('%02X' % ord(x)), v4addr) - v4addr.insert(2, ':') - newaddr = addr[:addr.rindex(':') + 1] + ''.join(v4addr) - return inet_pton(family, newaddr) - dbyts = [0] * 8 # 8 groups - grps = addr.split(':') - for i, v in enumerate(grps): - if v: - dbyts[i] = int(v, 16) - else: - for j, w in enumerate(grps[::-1]): - if w: - dbyts[7 - j] = int(w, 16) - else: - break - break - return ''.join((chr(i // 256) + chr(i % 256)) for i in dbyts) - else: - raise RuntimeError("What family?") - - -if not hasattr(socket, 'inet_pton'): - socket.inet_pton = inet_pton - -if not hasattr(socket, 'inet_ntop'): - socket.inet_ntop = inet_ntop - def find_config(): config_path = 'config.json' if os.path.exists(config_path):