From 270f655300c6506723918111887a994ac37476bb Mon Sep 17 00:00:00 2001 From: mengskysama Date: Sun, 14 Sep 2014 17:12:32 +0800 Subject: [PATCH 01/11] manyuser branch --- README.md | 55 +++++++++++++++ shadowsocks/Config.py | 12 ++++ shadowsocks/asyncmgr.py | 100 ++++++++++++++++++++++++++ shadowsocks/config.json | 11 +++ shadowsocks/db_transfer.py | 119 +++++++++++++++++++++++++++++++ shadowsocks/eventloop.py | 3 + shadowsocks/server.py | 130 +++------------------------------- shadowsocks/server_pool.py | 136 ++++++++++++++++++++++++++++++++++++ shadowsocks/shadowsocks.sql | 24 +++++++ shadowsocks/tcprelay.py | 15 ++++ 10 files changed, 486 insertions(+), 119 deletions(-) create mode 100644 shadowsocks/Config.py create mode 100644 shadowsocks/asyncmgr.py create mode 100644 shadowsocks/config.json create mode 100644 shadowsocks/db_transfer.py create mode 100644 shadowsocks/server_pool.py create mode 100644 shadowsocks/shadowsocks.sql diff --git a/README.md b/README.md index 9f78680..473e84f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,58 @@ +shadowsocks manyuser branch +=========== +Install +------- +install MySQL 5.x.x + +`pip install cymysql` + +create a database named `shadowsocks` + +import `shadowsocks.sql` + +edit Config.py +Example: + + #Config + MYSQL_HOST = 'mdss.mengsky.net' + MYSQL_PORT = 3306 + MYSQL_USER = 'ss' + MYSQL_PASS = 'ss' + MYSQL_DB = 'shadowsocks' + + MANAGE_PASS = 'ss233333333' + #if you want manage in other server you should set this value to global ip + MANAGE_BIND_IP = '127.0.0.1' + #make sure this port is idle + MANAGE_PORT = 23333 + +TestRun `cd shadowsocks` ` python server.py` + +if no exception server will startup. you will see such like +Example: + + db start server at port [%s] pass [%s] + +User table colum +------------------ +`passwd` server pass +`port` server port +`t` last keepalive time +`u` upload transfer +`d` download transer +`transfer_enable` if u + d > transfer_enable this server will be stop (db_transfer.py del_server_out_of_bound_safe) + +Manage socket +------------------ +Manage server work in UDP at `MANAGE_BIND_IP` `MANAGE_PORT` + +use `MANAGE_PASS:port:passwd:0` to del a server at port `port` + +use `MANAGE_PASS:port:passwd:1` to run a server at port `port` password is `passwd` +eg: + + udpCliSock.sendto('MANAGE_PASS:65535:123456:1', (MANAGE_BIND_IP, MANAGE_PORT)) + shadowsocks =========== diff --git a/shadowsocks/Config.py b/shadowsocks/Config.py new file mode 100644 index 0000000..cb3ad45 --- /dev/null +++ b/shadowsocks/Config.py @@ -0,0 +1,12 @@ +#Config +MYSQL_HOST = 'mdss.mengsky.net' +MYSQL_PORT = 3306 +MYSQL_USER = 'ss' +MYSQL_PASS = 'ss' +MYSQL_DB = 'shadowsocks' + +MANAGE_PASS = 'ss233333333' +#if you want manage in other server you should set this value to global ip +MANAGE_BIND_IP = '127.0.0.1' +#make sure this port is idle +MANAGE_PORT = 23333 \ No newline at end of file diff --git a/shadowsocks/asyncmgr.py b/shadowsocks/asyncmgr.py new file mode 100644 index 0000000..cf23e7b --- /dev/null +++ b/shadowsocks/asyncmgr.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2014 clowwindy +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import time +import os +import socket +import struct +import re +import logging +import common +import lru_cache +import eventloop +import server_pool +import Config + +class ServerMgr(object): + + def __init__(self): + self._loop = None + self._request_id = 1 + self._hosts = {} + self._hostname_status = {} + self._hostname_to_cb = {} + self._cb_to_hostname = {} + self._last_time = time.time() + self._sock = None + self._servers = None + + def add_to_loop(self, loop): + if self._loop: + raise Exception('already add to loop') + self._loop = loop + # TODO when dns server is IPv6 + self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, + socket.SOL_UDP) + self._sock.bind((Config.MANAGE_BIND_IP, Config.MANAGE_PORT)) + self._sock.setblocking(False) + loop.add(self._sock, eventloop.POLL_IN) + loop.add_handler(self.handle_events) + + def _handle_data(self, sock): + data, addr = sock.recvfrom(128) + #manage pwd:port:passwd:action + args = data.split(':') + if len(args) < 4: + return + if args[0] == Config.MANAGE_PASS: + if args[3] == '0': + server_pool.ServerPool.get_instance().cb_del_server(args[1]) + elif args[3] == '1': + server_pool.ServerPool.get_instance().new_server(args[1], args[2]) + + def handle_events(self, events): + for sock, fd, event in events: + if sock != self._sock: + continue + if event & eventloop.POLL_ERR: + logging.error('mgr socket err') + self._loop.remove(self._sock) + self._sock.close() + # TODO when dns server is IPv6 + self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, + socket.SOL_UDP) + self._sock.setblocking(False) + self._loop.add(self._sock, eventloop.POLL_IN) + else: + self._handle_data(sock) + break + + def close(self): + if self._sock: + self._sock.close() + self._sock = None + + +def test(): + pass + +if __name__ == '__main__': + test() diff --git a/shadowsocks/config.json b/shadowsocks/config.json new file mode 100644 index 0000000..1607364 --- /dev/null +++ b/shadowsocks/config.json @@ -0,0 +1,11 @@ +{ + "server":"127.0.0.1", + "server_port":8388, + "local_address": "127.0.0.1", + "local_port":1080, + "password":"m", + "timeout":300, + "method":"aes-256-cfb", + "fast_open": false, + "workers": 1 +} \ No newline at end of file diff --git a/shadowsocks/db_transfer.py b/shadowsocks/db_transfer.py new file mode 100644 index 0000000..4ce72fe --- /dev/null +++ b/shadowsocks/db_transfer.py @@ -0,0 +1,119 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +import logging +import cymysql +import time +import sys +from server_pool import ServerPool +import Config + +class DbTransfer(object): + + instance = None + + def __init__(self): + self.last_get_transfer = {} + + @staticmethod + def get_instance(): + if DbTransfer.instance is None: + DbTransfer.instance = DbTransfer() + return DbTransfer.instance + + def push_db_all_user(self): + #更新用户流量到数据库 + last_transfer = self.last_get_transfer + curr_transfer = ServerPool.get_instance().get_servers_transfer() + #上次和本次的增量 + dt_transfer = {} + for id in curr_transfer.keys(): + if id in last_transfer: + if last_transfer[id][0] == curr_transfer[id][0] and \ + last_transfer[id][1] == curr_transfer[id][1]: + continue + elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: + continue + elif last_transfer[id][0] <= curr_transfer[id][0] and \ + last_transfer[id][1] <= curr_transfer[id][1]: + dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0] ,curr_transfer[id][1] - last_transfer[id][1]] + else: + dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] + else: + if curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: + continue + dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] + + self.last_get_transfer = curr_transfer + query_head = 'UPDATE user' + query_sub_when = '' + query_sub_when2 = '' + query_sub_in = None + last_time = time.time() + for id in dt_transfer.keys(): + query_sub_when += ' WHEN %s THEN u+%s' % (id, dt_transfer[id][0]) + query_sub_when2 += ' WHEN %s THEN d+%s' % (id, dt_transfer[id][1]) + if query_sub_in is not None: + query_sub_in += ',%s' % id + else: + query_sub_in = '%s' % id + if query_sub_when == '': + return + query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ + ' END, d = CASE port' + query_sub_when2 + \ + ' END, t = ' + str(int(last_time)) + \ + ' WHERE port IN (%s)' % query_sub_in + #print query_sql + conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') + cur = conn.cursor() + cur.execute(query_sql) + cur.close() + conn.commit() + conn.close() + + @staticmethod + def pull_db_all_user(): + #数据库所有用户信息 + conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') + cur = conn.cursor() + cur.execute("SELECT port, u, d, transfer_enable, passwd, switch, enable FROM user") + rows = [] + for r in cur.fetchall(): + rows.append(list(r)) + cur.close() + conn.close() + return rows + + @staticmethod + def del_server_out_of_bound_safe(rows): + #停止超流量的服务 + for row in rows: + if ServerPool.get_instance().server_is_run(row[0]) is True: + if row[1] + row[2] >= row[3]: + logging.info('db stop server at port [%s]' % (row[0])) + ServerPool.get_instance().del_server(row[0]) + else: + if row[5] == 1 and row[6] == 1 and row[1] + row[2] < row[3]: + logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) + ServerPool.get_instance().new_server(row[0], row[4]) + + @staticmethod + def thread_db(): + import socket + import time + timeout = 60 + socket.setdefaulttimeout(timeout) + while True: + #logging.warn('db loop') + try: + DbTransfer.get_instance().push_db_all_user() + rows = DbTransfer.get_instance().pull_db_all_user() + DbTransfer.del_server_out_of_bound_safe(rows) + except Exception as e: + logging.warn('db thread except:%s' % e) + finally: + time.sleep(15) + + +#SQLData.pull_db_all_user() +#print DbTransfer.get_instance().test() diff --git a/shadowsocks/eventloop.py b/shadowsocks/eventloop.py index 0b628e0..52d890b 100644 --- a/shadowsocks/eventloop.py +++ b/shadowsocks/eventloop.py @@ -192,6 +192,9 @@ class EventLoop(object): def add_handler(self, handler): self._handlers.append(handler) + def remove_handler(self, handler): + self._handlers.remove(handler) + def run(self): while not self.stopping: try: diff --git a/shadowsocks/server.py b/shadowsocks/server.py index d5648bc..2ca3186 100755 --- a/shadowsocks/server.py +++ b/shadowsocks/server.py @@ -1,123 +1,15 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 clowwindy -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - +import time import sys -import os -import logging -import utils -import encrypt -import eventloop -import tcprelay -import udprelay -import asyncdns - - -def main(): - utils.check_python() - - config = utils.get_config(False) - - utils.print_shadowsocks() - - if config['port_password']: - if config['server_port'] or config['password']: - logging.warn('warning: port_password should not be used with ' - 'server_port and password. server_port and password ' - 'will be ignored') - else: - config['port_password'] = {} - server_port = config['server_port'] - if type(server_port) == list: - for a_server_port in server_port: - config['port_password'][a_server_port] = config['password'] - else: - config['port_password'][str(server_port)] = config['password'] - - encrypt.init_table(config['password'], config['method']) - tcp_servers = [] - udp_servers = [] - dns_resolver = asyncdns.DNSResolver() - for port, password in config['port_password'].items(): - a_config = config.copy() - a_config['server_port'] = int(port) - a_config['password'] = password - logging.info("starting server at %s:%d" % - (a_config['server'], int(port))) - tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) - udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) - - def run_server(): - try: - loop = eventloop.EventLoop() - dns_resolver.add_to_loop(loop) - for tcp_server in tcp_servers: - tcp_server.add_to_loop(loop) - for udp_server in udp_servers: - udp_server.add_to_loop(loop) - loop.run() - except (KeyboardInterrupt, IOError, OSError) as e: - logging.error(e) - import traceback - traceback.print_exc() - os._exit(0) - - if int(config['workers']) > 1: - if os.name == 'posix': - children = [] - is_child = False - for i in xrange(0, int(config['workers'])): - r = os.fork() - if r == 0: - logging.info('worker started') - is_child = True - run_server() - break - else: - children.append(r) - if not is_child: - def handler(signum, _): - for pid in children: - os.kill(pid, signum) - os.waitpid(pid, 0) - sys.exit() - import signal - signal.signal(signal.SIGTERM, handler) - - # master - for a_tcp_server in tcp_servers: - a_tcp_server.close() - for a_udp_server in udp_servers: - a_udp_server.close() - dns_resolver.close() - - for child in children: - os.waitpid(child, 0) - else: - logging.warn('worker is only available on Unix/Linux') - run_server() - else: - run_server() +import thread +import server_pool +import db_transfer +#def test(): +# thread.start_new_thread(DbTransfer.thread_db, ()) +# Api.web_server() if __name__ == '__main__': - main() + #server_pool.ServerPool.get_instance() + thread.start_new_thread(db_transfer.DbTransfer.thread_db, ()) + while True: + time.sleep(99999) diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py new file mode 100644 index 0000000..61f5ca0 --- /dev/null +++ b/shadowsocks/server_pool.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2014 clowwindy +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +import logging +import utils +import time +import eventloop +import tcprelay +import udprelay +import asyncdns +import thread +import threading +import sys +import asyncmgr + + +class ServerPool(object): + + instance = None + + def __init__(self): + utils.check_python() + self.config = utils.get_config(False) + utils.print_shadowsocks() + self.dns_resolver = asyncdns.DNSResolver() + + self.tcp_servers_pool = {} + #self.udp_servers_pool = {} + + self.loop = eventloop.EventLoop() + thread.start_new_thread(ServerPool.run_server, (self.loop, self.dns_resolver)) + + @staticmethod + def get_instance(): + if ServerPool.instance is None: + ServerPool.instance = ServerPool() + return ServerPool.instance + + @staticmethod + def run_server(loop, dns_resolver): + try: + mgr = asyncmgr.ServerMgr() + mgr.add_to_loop(loop) + dns_resolver.add_to_loop(loop) + loop.run() + except (KeyboardInterrupt, IOError, OSError) as e: + logging.error(e) + import traceback + traceback.print_exc() + os.exit(0) + + def server_is_run(self, port): + port = int(port) + if port in self.tcp_servers_pool: + return True + return False + + def new_server(self, port, password): + ret = True + port = int(port) + if self.server_is_run(port): + logging.info("server already at %s:%d" %(self.config['server'], port)) + return 'this port server is already running' + + a_config = self.config.copy() + a_config['server_port'] = port + a_config['password'] = password + logging.info("starting server at %s:%d" %(a_config['server'], port)) + try: + tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) + #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + except Exception, e: + logging.warn(e) + return e + try: + #add is safe + tcp_server.add_to_loop(self.loop) + self.tcp_servers_pool.update({port: tcp_server}) + #self.udp_servers_pool.update({port: tcp_server}) + except Exception, e: + logging.warn(e) + ret = e + return ret + + def cb_del_server(self, port): + port = int(port) + ret = True + if port not in self.tcp_servers_pool: + logging.info("stopped server at %s:%d already stop" % (self.config['server'], int(port))) + return True + logging.info("stopped server at %s:%d" % (self.config['server'], int(port))) + try: + self.tcp_servers_pool[int(port)].destroy() + del self.tcp_servers_pool[int(port)] + #del self.udp_servers_pool[int(port)] + except Exception, e: + ret = e + logging.warn(e) + import traceback + traceback.print_exc() + return ret + + def get_server_transfer(self, port): + port = int(port) + if port in self.tcp_servers_pool: + return [self.tcp_servers_pool[port].server_transfer_ul, self.tcp_servers_pool[port].server_transfer_dl] + return [0,0] + + def get_servers_transfer(self): + ret = {} + for server_port in self.tcp_servers_pool.keys(): + ret[server_port] = [self.tcp_servers_pool[server_port].server_transfer_ul + ,self.tcp_servers_pool[server_port].server_transfer_dl] + return ret + diff --git a/shadowsocks/shadowsocks.sql b/shadowsocks/shadowsocks.sql new file mode 100644 index 0000000..b828eaa --- /dev/null +++ b/shadowsocks/shadowsocks.sql @@ -0,0 +1,24 @@ +SET FOREIGN_KEY_CHECKS=0; + +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `email` varchar(32) NOT NULL, + `pass` varchar(16) NOT NULL, + `passwd` varchar(16) NOT NULL, + `t` int(11) NOT NULL DEFAULT '0', + `u` int(20) NOT NULL, + `d` int(20) NOT NULL, + `transfer_enable` bigint(20) NOT NULL, + `port` int(11) NOT NULL, + `switch` tinyint(4) NOT NULL DEFAULT '1', + `enable` tinyint(4) NOT NULL DEFAULT '1', + `type` tinyint(4) NOT NULL DEFAULT '1', + `last_get_gitf_time` int(11) NOT NULL DEFAULT '0', + `last_rest_pass_time` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`,`port`) +) ENGINE=InnoDB AUTO_INCREMENT=415 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of user +-- ---------------------------- +INSERT INTO `user` VALUES ('7', 'test@test.com', '123456', '0000000', '1410609560', '0', '0', '9320666234', '50000', '1', '1', '7', '0', '0'); \ No newline at end of file diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index 36b1c56..b2bc44d 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -539,6 +539,21 @@ class TCPRelay(object): self._eventloop.add(self._server_socket, eventloop.POLL_IN | eventloop.POLL_ERR) + def remove_to_loop(self): + self._eventloop.remove(self._server_socket) + self._eventloop.remove_handler(self._handle_events) + + def destroy(self): + #destroy all conn and server conn at this tcprelay + self.remove_to_loop() + for fd in self._fd_to_handlers.keys(): + try: + self._fd_to_handlers[fd].destroy() + except Exception, e: + #already destroy + pass + self.close() + def remove_handler(self, handler): index = self._handler_to_timeouts.get(hash(handler), -1) if index >= 0: From 7f8621f15363bcb67733e8eba0376b31ec4dbbbb Mon Sep 17 00:00:00 2001 From: mengskysama Date: Sun, 14 Sep 2014 18:26:10 +0800 Subject: [PATCH 02/11] merge mdss --- README.md | 30 ++++++++++++++++++++++++++---- shadowsocks/server_pool.py | 28 +++++++++++++++++++++++----- shadowsocks/tcprelay.py | 4 ++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 473e84f..44b5ad7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ shadowsocks manyuser branch =========== +Which people need this branch +------------------ +1.share shadowsocks server + +2.create multi server by shadowsocks + +3.manage server (transfer / account) + Install ------- install MySQL 5.x.x @@ -8,7 +16,7 @@ install MySQL 5.x.x create a database named `shadowsocks` -import `shadowsocks.sql` +import `shadowsocks.sql` into `shadowsocks` edit Config.py Example: @@ -33,13 +41,18 @@ Example: db start server at port [%s] pass [%s] -User table colum +Database user table column ------------------ `passwd` server pass + `port` server port + `t` last keepalive time + `u` upload transfer + `d` download transer + `transfer_enable` if u + d > transfer_enable this server will be stop (db_transfer.py del_server_out_of_bound_safe) Manage socket @@ -49,9 +62,18 @@ Manage server work in UDP at `MANAGE_BIND_IP` `MANAGE_PORT` use `MANAGE_PASS:port:passwd:0` to del a server at port `port` use `MANAGE_PASS:port:passwd:1` to run a server at port `port` password is `passwd` -eg: - udpCliSock.sendto('MANAGE_PASS:65535:123456:1', (MANAGE_BIND_IP, MANAGE_PORT)) +Python Eg: + + udpsock.sendto('MANAGE_PASS:65535:123456:1', (MANAGE_BIND_IP, MANAGE_PORT)) + +PHP Eg: + + $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + $msg = 'MANAGE_PASS:65535:123456:1'; + $len = strlen($msg); + socket_sendto($sock, $msg, $len, 0, MANAGE_BIND_IP, MANAGE_PORT); + socket_close($sock); shadowsocks =========== diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index 61f5ca0..beb1c0f 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -33,7 +33,8 @@ import thread import threading import sys import asyncmgr - +import Config +from socket import * class ServerPool(object): @@ -44,12 +45,12 @@ class ServerPool(object): self.config = utils.get_config(False) utils.print_shadowsocks() self.dns_resolver = asyncdns.DNSResolver() - + self.mgr = asyncmgr.ServerMgr() self.tcp_servers_pool = {} #self.udp_servers_pool = {} self.loop = eventloop.EventLoop() - thread.start_new_thread(ServerPool.run_server, (self.loop, self.dns_resolver)) + thread.start_new_thread(ServerPool._loop, (self.loop, self.dns_resolver, self.mgr)) @staticmethod def get_instance(): @@ -58,9 +59,8 @@ class ServerPool(object): return ServerPool.instance @staticmethod - def run_server(loop, dns_resolver): + def _loop(loop, dns_resolver, mgr): try: - mgr = asyncmgr.ServerMgr() mgr.add_to_loop(loop) dns_resolver.add_to_loop(loop) loop.run() @@ -103,6 +103,24 @@ class ServerPool(object): ret = e return ret + def del_server(self, port): + port = int(port) + ret = True + if port not in self.tcp_servers_pool: + logging.info("stopped server at %s:%d already stop" % (self.config['server'], int(port))) + return True + logging.info("stopping server at %s:%d" % (self.config['server'], int(port))) + try: + udpsock = socket(AF_INET, SOCK_DGRAM) + udpsock.sendto('%s:%s:0:0' % (Config.MANAGE_PASS, port), (Config.MANAGE_BIND_IP, Config.MANAGE_PORT)) + udpsock.close() + except Exception, e: + import traceback + traceback.print_exc() + ret = e + logging.warn(e) + return ret + def cb_del_server(self, port): port = int(port) ret = True diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index b2bc44d..bb9872a 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -356,6 +356,7 @@ class TCPRelayHandler(object): if not data: self.destroy() return + self._server.server_transfer_ul += len(data) if not is_local: data = self._encryptor.decrypt(data) if not data: @@ -388,6 +389,7 @@ class TCPRelayHandler(object): if not data: self.destroy() return + self._server.server_transfer_dl += len(data) if self._is_local: data = self._encryptor.decrypt(data) else: @@ -495,6 +497,8 @@ class TCPRelay(object): self._eventloop = None self._fd_to_handlers = {} self._last_time = time.time() + self.server_transfer_ul = 0L + self.server_transfer_dl = 0L self._timeout = config['timeout'] self._timeouts = [] # a list for all the handlers From 1f05b378ac08c2d2c34e7a51afc3eedb69edfd18 Mon Sep 17 00:00:00 2001 From: mengskysama Date: Wed, 17 Sep 2014 20:37:16 +0800 Subject: [PATCH 03/11] add ipv6 eth in server pool --- shadowsocks/config.json | 3 +- shadowsocks/db_transfer.py | 14 ++-- shadowsocks/server.py | 1 + shadowsocks/server_pool.py | 132 ++++++++++++++++++++++--------------- 4 files changed, 89 insertions(+), 61 deletions(-) diff --git a/shadowsocks/config.json b/shadowsocks/config.json index 1607364..7f1fa87 100644 --- a/shadowsocks/config.json +++ b/shadowsocks/config.json @@ -1,5 +1,6 @@ { - "server":"127.0.0.1", + "server":"0.0.0.0", + "server_ipv6": "[::]", "server_port":8388, "local_address": "127.0.0.1", "local_port":1080, diff --git a/shadowsocks/db_transfer.py b/shadowsocks/db_transfer.py index 4ce72fe..5c35d98 100644 --- a/shadowsocks/db_transfer.py +++ b/shadowsocks/db_transfer.py @@ -29,14 +29,14 @@ class DbTransfer(object): dt_transfer = {} for id in curr_transfer.keys(): if id in last_transfer: - if last_transfer[id][0] == curr_transfer[id][0] and \ - last_transfer[id][1] == curr_transfer[id][1]: + if last_transfer[id][0] == curr_transfer[id][0] and last_transfer[id][1] == curr_transfer[id][1]: continue elif curr_transfer[id][0] == 0 and curr_transfer[id][1] == 0: continue elif last_transfer[id][0] <= curr_transfer[id][0] and \ last_transfer[id][1] <= curr_transfer[id][1]: - dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0] ,curr_transfer[id][1] - last_transfer[id][1]] + dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], + curr_transfer[id][1] - last_transfer[id][1]] else: dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] else: @@ -64,7 +64,8 @@ class DbTransfer(object): ' END, t = ' + str(int(last_time)) + \ ' WHERE port IN (%s)' % query_sub_in #print query_sql - conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') + conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, + passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') cur = conn.cursor() cur.execute(query_sql) cur.close() @@ -74,7 +75,8 @@ class DbTransfer(object): @staticmethod def pull_db_all_user(): #数据库所有用户信息 - conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') + conn = cymysql.connect(host=Config.MYSQL_HOST, port=Config.MYSQL_PORT, user=Config.MYSQL_USER, + passwd=Config.MYSQL_PASS, db=Config.MYSQL_DB, charset='utf8') cur = conn.cursor() cur.execute("SELECT port, u, d, transfer_enable, passwd, switch, enable FROM user") rows = [] @@ -88,7 +90,7 @@ class DbTransfer(object): def del_server_out_of_bound_safe(rows): #停止超流量的服务 for row in rows: - if ServerPool.get_instance().server_is_run(row[0]) is True: + if ServerPool.get_instance().server_is_run(row[0]) > 0: if row[1] + row[2] >= row[3]: logging.info('db stop server at port [%s]' % (row[0])) ServerPool.get_instance().del_server(row[0]) diff --git a/shadowsocks/server.py b/shadowsocks/server.py index 2ca3186..ab7cc8e 100755 --- a/shadowsocks/server.py +++ b/shadowsocks/server.py @@ -10,6 +10,7 @@ import db_transfer if __name__ == '__main__': #server_pool.ServerPool.get_instance() + #server_pool.ServerPool.get_instance().new_server(2333, '2333') thread.start_new_thread(db_transfer.DbTransfer.thread_db, ()) while True: time.sleep(99999) diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index beb1c0f..eecd86d 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -47,6 +47,7 @@ class ServerPool(object): self.dns_resolver = asyncdns.DNSResolver() self.mgr = asyncmgr.ServerMgr() self.tcp_servers_pool = {} + self.tcp_ipv6_servers_pool = {} #self.udp_servers_pool = {} self.loop = eventloop.EventLoop() @@ -72,83 +73,106 @@ class ServerPool(object): def server_is_run(self, port): port = int(port) + ret = 0 if port in self.tcp_servers_pool: - return True - return False + ret = 1 + if port in self.tcp_ipv6_servers_pool: + ret |= 2 + return ret def new_server(self, port, password): ret = True port = int(port) - if self.server_is_run(port): - logging.info("server already at %s:%d" %(self.config['server'], port)) - return 'this port server is already running' - a_config = self.config.copy() - a_config['server_port'] = port - a_config['password'] = password - logging.info("starting server at %s:%d" %(a_config['server'], port)) - try: - tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) - #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) - except Exception, e: - logging.warn(e) - return e - try: - #add is safe - tcp_server.add_to_loop(self.loop) - self.tcp_servers_pool.update({port: tcp_server}) - #self.udp_servers_pool.update({port: tcp_server}) - except Exception, e: - logging.warn(e) - ret = e - return ret + if 'server' in self.config: + if port in self.tcp_servers_pool: + logging.info("server already at %s:%d" % (self.config['server'], port)) + return 'this port server is already running' + else: + a_config = self.config.copy() + a_config['server_port'] = port + a_config['password'] = password + try: + logging.info("starting server at %s:%d" % (a_config['server'], port)) + tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) + tcp_server.add_to_loop(self.loop) + self.tcp_servers_pool.update({port: tcp_server}) + #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + except Exception, e: + logging.warn(e) + + if 'server_ipv6' in self.config: + if port in self.tcp_ipv6_servers_pool: + logging.info("server already at %s:%d" % (self.config['server_ipv6'], port)) + return 'this port server is already running' + else: + a_config = self.config.copy() + a_config['server'] = a_config['server_ipv6'] + a_config['server_port'] = port + a_config['password'] = password + try: + logging.info("starting server at %s:%d" % (a_config['server'], port)) + tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) + tcp_server.add_to_loop(self.loop) + self.tcp_ipv6_servers_pool.update({port: tcp_server}) + #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + except Exception, e: + logging.warn(e) + return True def del_server(self, port): port = int(port) - ret = True - if port not in self.tcp_servers_pool: - logging.info("stopped server at %s:%d already stop" % (self.config['server'], int(port))) - return True - logging.info("stopping server at %s:%d" % (self.config['server'], int(port))) + logging.info("del server at %d" % int(port)) try: udpsock = socket(AF_INET, SOCK_DGRAM) udpsock.sendto('%s:%s:0:0' % (Config.MANAGE_PASS, port), (Config.MANAGE_BIND_IP, Config.MANAGE_PORT)) udpsock.close() except Exception, e: - import traceback - traceback.print_exc() - ret = e logging.warn(e) - return ret + return True def cb_del_server(self, port): port = int(port) - ret = True + if port not in self.tcp_servers_pool: logging.info("stopped server at %s:%d already stop" % (self.config['server'], int(port))) - return True - logging.info("stopped server at %s:%d" % (self.config['server'], int(port))) - try: - self.tcp_servers_pool[int(port)].destroy() - del self.tcp_servers_pool[int(port)] - #del self.udp_servers_pool[int(port)] - except Exception, e: - ret = e - logging.warn(e) - import traceback - traceback.print_exc() - return ret + else: + logging.info("stopped server at %s:%d" % (self.config['server'], int(port))) + try: + self.tcp_servers_pool[int(port)].destroy() + del self.tcp_servers_pool[int(port)] + #del self.udp_servers_pool[int(port)] + except Exception, e: + logging.warn(e) + + if port not in self.tcp_ipv6_servers_pool: + logging.info("stopped server at %s:%d already stop" % (self.config['server_ipv6'], int(port))) + else: + logging.info("stopped server at %s:%d" % (self.config['server_ipv6'], int(port))) + try: + self.tcp_servers_pool[int(port)].destroy() + del self.tcp_servers_pool[int(port)] + except Exception, e: + logging.warn(e) + + return True def get_server_transfer(self, port): port = int(port) + ret = [0, 0] if port in self.tcp_servers_pool: - return [self.tcp_servers_pool[port].server_transfer_ul, self.tcp_servers_pool[port].server_transfer_dl] - return [0,0] - - def get_servers_transfer(self): - ret = {} - for server_port in self.tcp_servers_pool.keys(): - ret[server_port] = [self.tcp_servers_pool[server_port].server_transfer_ul - ,self.tcp_servers_pool[server_port].server_transfer_dl] + ret[0] = self.tcp_servers_pool[port].server_transfer_ul + ret[1] = self.tcp_servers_pool[port].server_transfer_dl + if port in self.tcp_ipv6_servers_pool: + ret[0] += self.tcp_ipv6_servers_pool[port].server_transfer_ul + ret[1] += self.tcp_ipv6_servers_pool[port].server_transfer_dl + return ret + + def get_servers_transfer(self): + servers = self.tcp_servers_pool.copy() + servers.update(self.tcp_ipv6_servers_pool) + ret = {} + for port in servers.keys(): + ret[port] = self.get_server_transfer(port) return ret From a5ddc3289a3398eb1ae460a840143ea3b4fc76ce Mon Sep 17 00:00:00 2001 From: mengskysama Date: Thu, 18 Sep 2014 11:08:43 +0800 Subject: [PATCH 04/11] README.md [Errno 24] Too many open files --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 44b5ad7..13179c1 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,17 @@ PHP Eg: socket_sendto($sock, $msg, $len, 0, MANAGE_BIND_IP, MANAGE_PORT); socket_close($sock); +NOTICE +------------------ +If error such like `2014-09-18 09:02:37 ERROR [Errno 24] Too many open files` + +edit /etc/security/limits.conf + +Add: + + * soft nofile 8192 + * hard nofile 65535 + shadowsocks =========== From 7c991e9d7f8d35bcbc06f3a7176f8188828a4bb5 Mon Sep 17 00:00:00 2001 From: mengskysama Date: Thu, 18 Sep 2014 17:40:08 +0800 Subject: [PATCH 05/11] ipv6 fix --- shadowsocks/db_transfer.py | 4 ++-- shadowsocks/server_pool.py | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/shadowsocks/db_transfer.py b/shadowsocks/db_transfer.py index 5c35d98..d356be7 100644 --- a/shadowsocks/db_transfer.py +++ b/shadowsocks/db_transfer.py @@ -89,16 +89,16 @@ class DbTransfer(object): @staticmethod def del_server_out_of_bound_safe(rows): #停止超流量的服务 + #启动没超流量的服务 for row in rows: if ServerPool.get_instance().server_is_run(row[0]) > 0: if row[1] + row[2] >= row[3]: logging.info('db stop server at port [%s]' % (row[0])) ServerPool.get_instance().del_server(row[0]) - else: + elif ServerPool.get_instance().server_run_status(row[0]) is False: if row[5] == 1 and row[6] == 1 and row[1] + row[2] < row[3]: logging.info('db start server at port [%s] pass [%s]' % (row[0], row[4])) ServerPool.get_instance().new_server(row[0], row[4]) - @staticmethod def thread_db(): import socket diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index eecd86d..f33a5a3 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -80,6 +80,15 @@ class ServerPool(object): ret |= 2 return ret + def server_run_status(self, port): + if 'server' in self.config: + if port not self.tcp_servers_pool: + return False + if 'server_ipv6' in self.config: + if port not self.tcp_ipv6_servers_pool: + return False + return True + def new_server(self, port, password): ret = True port = int(port) From efdf6ac5efed3f19ae629e59cf6f07ad2afb7b11 Mon Sep 17 00:00:00 2001 From: mengskysama Date: Fri, 19 Sep 2014 17:46:12 +0800 Subject: [PATCH 06/11] ipv6 bugfix --- shadowsocks/server_pool.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index f33a5a3..d1624d4 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -82,10 +82,10 @@ class ServerPool(object): def server_run_status(self, port): if 'server' in self.config: - if port not self.tcp_servers_pool: + if port not in self.tcp_servers_pool: return False if 'server_ipv6' in self.config: - if port not self.tcp_ipv6_servers_pool: + if port not in self.tcp_ipv6_servers_pool: return False return True From 509ce78e276c53a8df6f4829122dac161703a6cb Mon Sep 17 00:00:00 2001 From: Makedie233 Date: Mon, 29 Sep 2014 21:20:55 +0800 Subject: [PATCH 07/11] Update server_pool.py ipv6 del can't play --- shadowsocks/server_pool.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index d1624d4..286471c 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -159,8 +159,8 @@ class ServerPool(object): else: logging.info("stopped server at %s:%d" % (self.config['server_ipv6'], int(port))) try: - self.tcp_servers_pool[int(port)].destroy() - del self.tcp_servers_pool[int(port)] + self.tcp_ipv6_servers_pool[int(port)].destroy() + del self.tcp_ipv6_servers_pool[int(port)] except Exception, e: logging.warn(e) From bb860bb364efcdcea2aeb276f6ddf7e392b788af Mon Sep 17 00:00:00 2001 From: mengskysama Date: Tue, 30 Sep 2014 10:40:16 +0800 Subject: [PATCH 08/11] add udp support but transfer --- shadowsocks/lru_cache.py | 2 +- shadowsocks/server_pool.py | 34 +++++++++++++++++++++------------- shadowsocks/udprelay.py | 11 +++++++++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/shadowsocks/lru_cache.py b/shadowsocks/lru_cache.py index 1313af5..bb28870 100644 --- a/shadowsocks/lru_cache.py +++ b/shadowsocks/lru_cache.py @@ -62,4 +62,4 @@ class LRUCache(collections.MutableMapping): c += 1 del self._time_to_keys[least] if c: - logging.debug('%d keys swept' % c) + logging.debug('%d keys swept' % c) \ No newline at end of file diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index 286471c..31f54bd 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -48,7 +48,8 @@ class ServerPool(object): self.mgr = asyncmgr.ServerMgr() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} - #self.udp_servers_pool = {} + self.udp_servers_pool = {} + self.udp_ipv6_servers_pool = {} self.loop = eventloop.EventLoop() thread.start_new_thread(ServerPool._loop, (self.loop, self.dns_resolver, self.mgr)) @@ -106,7 +107,9 @@ class ServerPool(object): tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_servers_pool.update({port: tcp_server}) - #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + udp_server.add_to_loop(self.loop) + self.udp_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e) @@ -124,14 +127,16 @@ class ServerPool(object): tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_ipv6_servers_pool.update({port: tcp_server}) - #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + udp_server.add_to_loop(self.loop) + self.udp_ipv6_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e) return True def del_server(self, port): port = int(port) - logging.info("del server at %d" % int(port)) + logging.info("del server at %d" % port) try: udpsock = socket(AF_INET, SOCK_DGRAM) udpsock.sendto('%s:%s:0:0' % (Config.MANAGE_PASS, port), (Config.MANAGE_BIND_IP, Config.MANAGE_PORT)) @@ -144,23 +149,26 @@ class ServerPool(object): port = int(port) if port not in self.tcp_servers_pool: - logging.info("stopped server at %s:%d already stop" % (self.config['server'], int(port))) + logging.info("stopped server at %s:%d already stop" % (self.config['server'], port)) else: - logging.info("stopped server at %s:%d" % (self.config['server'], int(port))) + logging.info("stopped server at %s:%d" % (self.config['server'], port)) try: - self.tcp_servers_pool[int(port)].destroy() - del self.tcp_servers_pool[int(port)] - #del self.udp_servers_pool[int(port)] + self.tcp_servers_pool[port].destroy() + del self.tcp_servers_pool[port] + self.udp_servers_pool[port].destroy() + del self.udp_servers_pool[port] except Exception, e: logging.warn(e) if port not in self.tcp_ipv6_servers_pool: - logging.info("stopped server at %s:%d already stop" % (self.config['server_ipv6'], int(port))) + logging.info("stopped server at %s:%d already stop" % (self.config['server_ipv6'], port)) else: - logging.info("stopped server at %s:%d" % (self.config['server_ipv6'], int(port))) + logging.info("stopped server at %s:%d" % (self.config['server_ipv6'], port)) try: - self.tcp_ipv6_servers_pool[int(port)].destroy() - del self.tcp_ipv6_servers_pool[int(port)] + self.tcp_ipv6_servers_pool[port].destroy() + del self.tcp_ipv6_servers_pool[port] + self.udp_ipv6_servers_pool[port].destroy() + del self.udp_ipv6_servers_pool[port] except Exception, e: logging.warn(e) diff --git a/shadowsocks/udprelay.py b/shadowsocks/udprelay.py index d7e3d4c..6302b8c 100644 --- a/shadowsocks/udprelay.py +++ b/shadowsocks/udprelay.py @@ -249,6 +249,17 @@ class UDPRelay(object): self._eventloop.add(server_socket, eventloop.POLL_IN | eventloop.POLL_ERR) + def remove_to_loop(self): + self._eventloop.remove(self._server_socket) + self._eventloop.remove_handler(self._handle_events) + + def destroy(self): + #destroy all conn and server conn + self.remove_to_loop() + self.close() + #GC + self._cache = None + def _handle_events(self, events): for sock, fd, event in events: if sock == self._server_socket: From 7b0e01722a23fdf9e48acebfb7d96a6973637e82 Mon Sep 17 00:00:00 2001 From: mengskysama Date: Tue, 30 Sep 2014 12:16:45 +0800 Subject: [PATCH 09/11] disable udp normal --- shadowsocks/server_pool.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index 31f54bd..ab22d56 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -48,8 +48,8 @@ class ServerPool(object): self.mgr = asyncmgr.ServerMgr() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} - self.udp_servers_pool = {} - self.udp_ipv6_servers_pool = {} + #self.udp_servers_pool = {} + #self.udp_ipv6_servers_pool = {} self.loop = eventloop.EventLoop() thread.start_new_thread(ServerPool._loop, (self.loop, self.dns_resolver, self.mgr)) @@ -107,9 +107,9 @@ class ServerPool(object): tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_servers_pool.update({port: tcp_server}) - udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) - udp_server.add_to_loop(self.loop) - self.udp_servers_pool.update({port: udp_server}) + #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + #udp_server.add_to_loop(self.loop) + #self.udp_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e) @@ -127,9 +127,9 @@ class ServerPool(object): tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_ipv6_servers_pool.update({port: tcp_server}) - udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) - udp_server.add_to_loop(self.loop) - self.udp_ipv6_servers_pool.update({port: udp_server}) + #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) + #udp_server.add_to_loop(self.loop) + #self.udp_ipv6_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e) return True @@ -155,8 +155,8 @@ class ServerPool(object): try: self.tcp_servers_pool[port].destroy() del self.tcp_servers_pool[port] - self.udp_servers_pool[port].destroy() - del self.udp_servers_pool[port] + #self.udp_servers_pool[port].destroy() + #del self.udp_servers_pool[port] except Exception, e: logging.warn(e) @@ -167,8 +167,8 @@ class ServerPool(object): try: self.tcp_ipv6_servers_pool[port].destroy() del self.tcp_ipv6_servers_pool[port] - self.udp_ipv6_servers_pool[port].destroy() - del self.udp_ipv6_servers_pool[port] + #self.udp_ipv6_servers_pool[port].destroy() + #del self.udp_ipv6_servers_pool[port] except Exception, e: logging.warn(e) From 5f8ca072d7e91d11d5297d09441ed597603aa747 Mon Sep 17 00:00:00 2001 From: mengskysama Date: Wed, 8 Oct 2014 13:56:38 +0800 Subject: [PATCH 10/11] sql bug fix --- shadowsocks/server_pool.py | 25 +++++++++++++------------ shadowsocks/shadowsocks.sql | 4 ++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/shadowsocks/server_pool.py b/shadowsocks/server_pool.py index ab22d56..d1d5353 100644 --- a/shadowsocks/server_pool.py +++ b/shadowsocks/server_pool.py @@ -160,19 +160,20 @@ class ServerPool(object): except Exception, e: logging.warn(e) - if port not in self.tcp_ipv6_servers_pool: - logging.info("stopped server at %s:%d already stop" % (self.config['server_ipv6'], port)) - else: - logging.info("stopped server at %s:%d" % (self.config['server_ipv6'], port)) - try: - self.tcp_ipv6_servers_pool[port].destroy() - del self.tcp_ipv6_servers_pool[port] - #self.udp_ipv6_servers_pool[port].destroy() - #del self.udp_ipv6_servers_pool[port] - except Exception, e: - logging.warn(e) + if 'server_ipv6' in self.config: + if port not in self.tcp_ipv6_servers_pool: + logging.info("stopped server at %s:%d already stop" % (self.config['server_ipv6'], port)) + else: + logging.info("stopped server at %s:%d" % (self.config['server_ipv6'], port)) + try: + self.tcp_ipv6_servers_pool[port].destroy() + del self.tcp_ipv6_servers_pool[port] + #self.udp_ipv6_servers_pool[port].destroy() + #del self.udp_ipv6_servers_pool[port] + except Exception, e: + logging.warn(e) - return True + return True def get_server_transfer(self, port): port = int(port) diff --git a/shadowsocks/shadowsocks.sql b/shadowsocks/shadowsocks.sql index b828eaa..5ce63a6 100644 --- a/shadowsocks/shadowsocks.sql +++ b/shadowsocks/shadowsocks.sql @@ -6,8 +6,8 @@ CREATE TABLE `user` ( `pass` varchar(16) NOT NULL, `passwd` varchar(16) NOT NULL, `t` int(11) NOT NULL DEFAULT '0', - `u` int(20) NOT NULL, - `d` int(20) NOT NULL, + `u` bigint(20) NOT NULL, + `d` bigint(20) NOT NULL, `transfer_enable` bigint(20) NOT NULL, `port` int(11) NOT NULL, `switch` tinyint(4) NOT NULL DEFAULT '1', From 43628cec19ffccf499466cb57695d9c76e7c0505 Mon Sep 17 00:00:00 2001 From: orvice Date: Mon, 24 Nov 2014 00:04:14 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E6=9B=B4=E6=AD=A3gift=E6=8B=BC=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shadowsocks/shadowsocks.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks/shadowsocks.sql b/shadowsocks/shadowsocks.sql index 5ce63a6..8d84992 100644 --- a/shadowsocks/shadowsocks.sql +++ b/shadowsocks/shadowsocks.sql @@ -13,7 +13,7 @@ CREATE TABLE `user` ( `switch` tinyint(4) NOT NULL DEFAULT '1', `enable` tinyint(4) NOT NULL DEFAULT '1', `type` tinyint(4) NOT NULL DEFAULT '1', - `last_get_gitf_time` int(11) NOT NULL DEFAULT '0', + `last_get_gift_time` int(11) NOT NULL DEFAULT '0', `last_rest_pass_time` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`,`port`) ) ENGINE=InnoDB AUTO_INCREMENT=415 DEFAULT CHARSET=utf8;