From ffffbd4542404e51d7d5844c69c4fe7814c7250a Mon Sep 17 00:00:00 2001 From: thomashuang Date: Sat, 22 Feb 2014 02:03:56 +0800 Subject: [PATCH] main: refact the main method to class, make it easy to read and modify --- shadowsocks/local.py | 194 ++++++++++++++++++++++++++---------------- shadowsocks/server.py | 186 ++++++++++++++++++++++++++-------------- 2 files changed, 239 insertions(+), 141 deletions(-) diff --git a/shadowsocks/local.py b/shadowsocks/local.py index b3061e6..8170558 100755 --- a/shadowsocks/local.py +++ b/shadowsocks/local.py @@ -64,6 +64,7 @@ class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): class Socks5Server(SocketServer.StreamRequestHandler): + def getServer(self): aPort = REMOTE_PORT aServer = SERVER @@ -77,7 +78,8 @@ class Socks5Server(SocketServer.StreamRequestHandler): r = re.match(r'^(.*)\:(\d+)$', aServer) if r: # support config like "server": "123.123.123.1:8381" - # or "server": ["123.123.123.1:8381", "123.123.123.2:8381", "123.123.123.2:8382"] + # or "server": ["123.123.123.1:8381", "123.123.123.2:8381", + # "123.123.123.2:8382"] aServer = r.group(1) aPort = int(r.group(2)) return (aServer, aPort) @@ -164,90 +166,132 @@ class Socks5Server(SocketServer.StreamRequestHandler): logging.warn(e) -def main(): - global SERVER, REMOTE_PORT, KEY, METHOD +class ShadowSocksServer(object): - logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(levelname)-8s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') + def __init__(self): - # fix py2exe - if hasattr(sys, "frozen") and sys.frozen in \ - ("windows_exe", "console_exe"): - p = os.path.dirname(os.path.abspath(sys.executable)) - os.chdir(p) - version = '' - try: - import pkg_resources - version = pkg_resources.get_distribution('shadowsocks').version - except: - pass - print 'shadowsocks %s' % version + self.options = self.default_options() - KEY = None - METHOD = None - LOCAL = '' - IPv6 = False + def default_options(self): + return { + "server":"127.0.0.1", + "server_port":8388, + "local_port":1081, + "password":"Keep Your Password", + "timeout":60, + "method":"aes-128-cfb", + "IPv6": False + } - config_path = utils.find_config() - optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6') - for key, value in optlist: - if key == '-c': - config_path = value - if config_path: - logging.info('loading config from %s' % config_path) - with open(config_path, 'rb') as f: - try: - config = json.load(f) - except ValueError as e: - logging.error('found an error in config.json: %s', e.message) - sys.exit(1) - else: - config = {} - optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6') - for key, value in optlist: - if key == '-p': - config['server_port'] = int(value) - elif key == '-k': - config['password'] = value - elif key == '-l': - config['local_port'] = int(value) - elif key == '-s': - config['server'] = value - elif key == '-m': - config['method'] = value - elif key == '-b': - config['local'] = value - elif key == '-6': - IPv6 = True + def serve_forever(self): + self.set_logging() + self.run_info() + self.set_options() + self.check_config() - SERVER = config['server'] - REMOTE_PORT = config['server_port'] - PORT = config['local_port'] - KEY = config['password'] - METHOD = config.get('method', None) - LOCAL = config.get('local', '') + SERVER = self.options['server'] + REMOTE_PORT = self.options['server_port'] + PORT = self.options['local_port'] + KEY = self.options['password'] + METHOD = self.options.get('method', None) + LOCAL = self.options.get('local', '') + + encrypt.init_table(KEY, METHOD) - if not KEY and not config_path: - sys.exit('config not specified, please read https://github.com/clowwindy/shadowsocks') + try: + if self.options['IPv6']: + ThreadingTCPServer.address_family = socket.AF_INET6 + server = ThreadingTCPServer((LOCAL, PORT), Socks5Server) + logging.info("starting local at %s:%d" % + tuple(server.server_address[:2])) + server.serve_forever() + except socket.error, e: + logging.error(e) + except KeyboardInterrupt: + server.shutdown() + sys.exit(0) + self.server.serve_forever() - utils.check_config(config) + def check_config(self): + utils.check_config(self.options) + + def set_logging(self): + logfmt = '[%%(levelname)s] %s%%(message)s' % '%(name)s - ' + config = lambda x: logging.basicConfig(level=x, format='[%(asctime)s] ' + logfmt, datefmt='%Y%m%d %H:%M:%S') + if self.options.get('debug'): + config(logging.DEBUG) + else: + config(logging.INFO) + # logging.basicConfig(level=logging.DEBUG, + # format='%(asctime)s %(levelname)-8s %(message)s', + # datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') + + def set_options(self): + config_path = self._find_options() + config = self._parse_file_options(config_path) + config = self._parse_cmd_options(config) + self.options.update(config) + + def _parse_file_options(self, config_path): + if config_path: + logging.info('loading config from %s' % config_path) + with open(config_path, 'rb') as f: + try: + config = json.load(f) + except ValueError as e: + logging.error( + 'found an error in config.json: %s', e.message) + sys.exit(1) + else: + config = {} + + return config + + def _find_options(self): + config_path = utils.find_config() + print config_path + optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6') + for key, value in optlist: + if key == '-c': + config_path = value + return config_path + + def _parse_cmd_options(self, config): + optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6') + for key, value in optlist: + if key == '-p': + config['server_port'] = int(value) + elif key == '-k': + self.options['password'] = value + elif key == '-l': + config['local_port'] = int(value) + elif key == '-s': + config['server'] = value + elif key == '-m': + config['method'] = value + elif key == '-b': + config['local'] = value + elif key == '-6': + config['IPv6'] = True + return config + + def run_info(self): + + if hasattr(sys, "frozen") and sys.frozen in \ + ("windows_exe", "console_exe"): + p = os.path.dirname(os.path.abspath(sys.executable)) + os.chdir(p) + version = '' + try: + import pkg_resources + version = pkg_resources.get_distribution('shadowsocks').version + except: + pass + logging.info('shadowsocks %s' % version) - encrypt.init_table(KEY, METHOD) - try: - if IPv6: - ThreadingTCPServer.address_family = socket.AF_INET6 - server = ThreadingTCPServer((LOCAL, PORT), Socks5Server) - logging.info("starting local at %s:%d" % tuple(server.server_address[:2])) - server.serve_forever() - except socket.error, e: - logging.error(e) - except KeyboardInterrupt: - server.shutdown() - sys.exit(0) if __name__ == '__main__': - main() + ShadowSocksServer().serve_forever() diff --git a/shadowsocks/server.py b/shadowsocks/server.py index d045d5e..168a98c 100755 --- a/shadowsocks/server.py +++ b/shadowsocks/server.py @@ -125,85 +125,139 @@ class Socks5Server(SocketServer.StreamRequestHandler): except socket.error, e: logging.warn(e) -def main(): - logging.basicConfig(level=logging.DEBUG, - format='%(asctime)s %(levelname)-8s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') +class ShadowSocksServer(object): + + def __init__(self): + + self.options = self.default_options() + + def default_options(self): + return { + "server":"127.0.0.1", + "server_port":8388, + "local_port":1081, + "password":"Keep Your Password", + "timeout":60, + "method":"aes-128-cfb", + "IPv6": False + } - version = '' - try: - import pkg_resources - version = pkg_resources.get_distribution('shadowsocks').version - except: - pass - print 'shadowsocks %s' % version - KEY = None - METHOD = None - IPv6 = False + def serve_forever(self): - config_path = utils.find_config() - optlist, args = getopt.getopt(sys.argv[1:], 's:p:k:m:c:6') - for key, value in optlist: - if key == '-c': - config_path = value + self.set_logging() + self.run_info() + self.set_options() + self.check_config() - if config_path: - logging.info('loading config from %s' % config_path) - with open(config_path, 'rb') as f: - try: - config = json.load(f) - except ValueError as e: - logging.error('found an error in config.json: %s', e.message) - sys.exit(1) - logging.info('loading config from %s' % config_path) - else: - config = {} + SERVER = self.options['server'] + PORT = self.options['server_port'] + KEY = self.options['password'] + METHOD = self.options.get('method', None) + PORTPASSWORD = self.options.get('port_password', None) + TIMEOUT = self.options.get('timeout', 600) - optlist, args = getopt.getopt(sys.argv[1:], 's:p:k:m:c:6') - for key, value in optlist: - if key == '-p': - config['server_port'] = int(value) - elif key == '-k': - config['password'] = value - elif key == '-s': - config['server'] = value - elif key == '-m': - config['method'] = value - elif key == '-6': - IPv6 = True + if PORTPASSWORD: + if PORT or KEY: + logging.warn('warning: port_password should not be used with server_port and password. server_port and password will be ignored') + else: + PORTPASSWORD = {} + PORTPASSWORD[str(PORT)] = KEY - SERVER = config['server'] - PORT = config['server_port'] - KEY = config['password'] - METHOD = config.get('method', None) - PORTPASSWORD = config.get('port_password', None) - TIMEOUT = config.get('timeout', 600) - if not KEY and not config_path: - sys.exit('config not specified, please read https://github.com/clowwindy/shadowsocks') + encrypt.init_table(KEY, METHOD) + if self.options['IPv6']: + ThreadingTCPServer.address_family = socket.AF_INET6 + for port, key in PORTPASSWORD.items(): + server = ThreadingTCPServer((SERVER, int(port)), Socks5Server) + server.key, server.method, server.timeout = key, METHOD, int(TIMEOUT) + logging.info("starting server at %s:%d" % tuple(server.server_address[:2])) + threading.Thread(target=server.serve_forever).start() + + def check_config(self): + utils.check_config(self.options) + + def set_logging(self): + logfmt = '[%%(levelname)s] %s%%(message)s' % '%(name)s - ' + config = lambda x: logging.basicConfig(level=x, format='[%(asctime)s] ' + logfmt, datefmt='%Y%m%d %H:%M:%S') + if self.options.get('debug'): + config(logging.DEBUG) + else: + config(logging.INFO) + # logging.basicConfig(level=logging.DEBUG, + # format='%(asctime)s %(levelname)-8s %(message)s', + # datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') + + def set_options(self): + config_path = self._find_options() + config = self._parse_file_options(config_path) + config = self._parse_cmd_options(config) + self.options.update(config) + + def _parse_file_options(self, config_path): + if config_path: + logging.info('loading config from %s' % config_path) + with open(config_path, 'rb') as f: + try: + config = json.load(f) + except ValueError as e: + logging.error( + 'found an error in config.json: %s', e.message) + sys.exit(1) + else: + config = {} + + return config + + def _find_options(self): + config_path = utils.find_config() + print config_path + optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6') + for key, value in optlist: + if key == '-c': + config_path = value + return config_path + + def _parse_cmd_options(self, config): + optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6') + for key, value in optlist: + if key == '-p': + config['server_port'] = int(value) + elif key == '-k': + self.options['password'] = value + elif key == '-l': + config['local_port'] = int(value) + elif key == '-s': + config['server'] = value + elif key == '-m': + config['method'] = value + elif key == '-b': + config['local'] = value + elif key == '-6': + config['IPv6'] = True + return config + + def run_info(self): + + if hasattr(sys, "frozen") and sys.frozen in \ + ("windows_exe", "console_exe"): + p = os.path.dirname(os.path.abspath(sys.executable)) + os.chdir(p) + version = '' + try: + import pkg_resources + version = pkg_resources.get_distribution('shadowsocks').version + except: + pass + logging.info('shadowsocks %s' % version) + - utils.check_config(config) - if PORTPASSWORD: - if PORT or KEY: - logging.warn('warning: port_password should not be used with server_port and password. server_port and password will be ignored') - else: - PORTPASSWORD = {} - PORTPASSWORD[str(PORT)] = KEY - encrypt.init_table(KEY, METHOD) - if IPv6: - ThreadingTCPServer.address_family = socket.AF_INET6 - for port, key in PORTPASSWORD.items(): - server = ThreadingTCPServer((SERVER, int(port)), Socks5Server) - server.key, server.method, server.timeout = key, METHOD, int(TIMEOUT) - logging.info("starting server at %s:%d" % tuple(server.server_address[:2])) - threading.Thread(target=server.serve_forever).start() if __name__ == '__main__': try: - main() + ShadowSocksServer().serve_forever() except socket.error, e: logging.error(e)