예제 #1
0
    def del_server_out_of_bound_safe(self, last_rows, rows):
        # 停止超流量的服务
        # 启动没超流量的服务
        # 需要动态载入switchrule,以便实时修改规则

        try:
            switchrule = importloader.load('switchrule')
        except Exception as e:
            logging.error('load switchrule.py fail')
        cur_servers = {}
        new_servers = {}

        md5_users = {}

        self.mu_port_list = []

        for row in rows:
            if row['is_multi_user'] != 0:
                self.mu_port_list.append(int(row['port']))
                continue

            md5_users[row['id']] = row.copy()
            del md5_users[row['id']]['u']
            del md5_users[row['id']]['d']
            if md5_users[row['id']]['disconnect_ip'] is None:
                md5_users[row['id']]['disconnect_ip'] = ''

            if md5_users[row['id']]['forbidden_ip'] is None:
                md5_users[row['id']]['forbidden_ip'] = ''

            if md5_users[row['id']]['forbidden_port'] is None:
                md5_users[row['id']]['forbidden_port'] = ''
            md5_users[row['id']]['md5'] = common.get_md5(
                str(row['id']) + row['passwd'] + row['method'] + row['obfs'] +
                row['protocol'])

        for row in rows:
            self.port_uid_table[row['port']] = row['id']
            self.uid_port_table[row['id']] = row['port']

        if self.mu_only == 1 or self.mu_only == 2:
            i = 0
            while i < len(rows):
                if rows[i]['is_multi_user'] == 0:
                    rows.pop(i)
                    i -= 1
                else:
                    pass
                i += 1

        if self.mu_only == -1:
            i = 0
            while i < len(rows):
                if rows[i]['is_multi_user'] != 0:
                    rows.pop(i)
                    i -= 1
                else:
                    pass
                i += 1

        for row in rows:
            port = row['port']
            user_id = row['id']
            passwd = common.to_bytes(row['passwd'])
            cfg = {'password': passwd}

            read_config_keys = [
                'method', 'obfs', 'obfs_param', 'protocol', 'protocol_param',
                'forbidden_ip', 'forbidden_port', 'node_speedlimit',
                'disconnect_ip', 'is_multi_user'
            ]

            for name in read_config_keys:
                if name in row and row[name]:
                    cfg[name] = row[name]

            merge_config_keys = ['password'] + read_config_keys
            for name in cfg.keys():
                if hasattr(cfg[name], 'encode'):
                    try:
                        cfg[name] = cfg[name].encode('utf-8')
                    except Exception as e:
                        logging.warning('encode cfg key "%s" fail, val "%s"' %
                                        (name, cfg[name]))

            if 'node_speedlimit' in cfg:
                if float(self.node_speedlimit) > 0.0 or float(
                        cfg['node_speedlimit']) > 0.0:
                    cfg['node_speedlimit'] = max(float(self.node_speedlimit),
                                                 float(cfg['node_speedlimit']))
            else:
                cfg['node_speedlimit'] = max(float(self.node_speedlimit),
                                             float(0.00))

            if 'disconnect_ip' not in cfg:
                cfg['disconnect_ip'] = ''

            if 'forbidden_ip' not in cfg:
                cfg['forbidden_ip'] = ''

            if 'forbidden_port' not in cfg:
                cfg['forbidden_port'] = ''

            if 'protocol_param' not in cfg:
                cfg['protocol_param'] = ''

            if 'obfs_param' not in cfg:
                cfg['obfs_param'] = ''

            if 'is_multi_user' not in cfg:
                cfg['is_multi_user'] = 0

            if port not in cur_servers:
                cur_servers[port] = passwd
            else:
                logging.error('more than one user use the same port [%s]' %
                              (port, ))
                continue

            if cfg['is_multi_user'] != 0:
                cfg['users_table'] = md5_users.copy()

            cfg['detect_hex_list'] = self.detect_hex_list.copy()
            cfg['detect_text_list'] = self.detect_text_list.copy()

            if self.is_relay and row['is_multi_user'] != 2:
                temp_relay_rules = {}
                for id in self.relay_rule_list:
                    if ((self.relay_rule_list[id]['user_id'] == user_id
                         or self.relay_rule_list[id]['user_id'] == 0)
                            or row['is_multi_user'] != 0) and (
                                self.relay_rule_list[id]['port'] == 0
                                or self.relay_rule_list[id]['port'] == port):
                        has_higher_priority = False
                        for priority_id in self.relay_rule_list:
                            if (
                                (self.relay_rule_list[priority_id]['priority']
                                 > self.relay_rule_list[id]['priority']
                                 and self.relay_rule_list[id]['id'] !=
                                 self.relay_rule_list[priority_id]['id']) or
                                (self.relay_rule_list[priority_id]['priority']
                                 == self.relay_rule_list[id]['priority']
                                 and self.relay_rule_list[id]['id'] >
                                 self.relay_rule_list[priority_id]['id'])
                            ) and (self.relay_rule_list[priority_id]['user_id']
                                   == user_id or
                                   self.relay_rule_list[priority_id]['user_id']
                                   == 0) and (self.relay_rule_list[priority_id]
                                              ['port'] == port or
                                              self.relay_rule_list[priority_id]
                                              ['port'] == 0):
                                has_higher_priority = True
                                continue

                        if has_higher_priority:
                            continue

                        if self.relay_rule_list[id][
                                'dist_ip'] == '0.0.0.0' and row[
                                    'is_multi_user'] == 0:
                            continue

                        temp_relay_rules[id] = self.relay_rule_list[id]

                cfg['relay_rules'] = temp_relay_rules.copy()
            else:
                temp_relay_rules = {}

                cfg['relay_rules'] = temp_relay_rules.copy()

            if ServerPool.get_instance().server_is_run(port) > 0:
                cfgchange = False

                if port in ServerPool.get_instance().tcp_servers_pool:
                    ServerPool.get_instance(
                    ).tcp_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).tcp_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)
                if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                    ServerPool.get_instance(
                    ).tcp_ipv6_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).tcp_ipv6_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)
                if port in ServerPool.get_instance().udp_servers_pool:
                    ServerPool.get_instance(
                    ).udp_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).udp_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)
                if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                    ServerPool.get_instance(
                    ).udp_ipv6_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).udp_ipv6_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)

                if row['is_multi_user'] != 0:
                    if port in ServerPool.get_instance().tcp_servers_pool:
                        ServerPool.get_instance().tcp_servers_pool[
                            port].modify_multi_user_table(md5_users)
                    if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                        ServerPool.get_instance().tcp_ipv6_servers_pool[
                            port].modify_multi_user_table(md5_users)
                    if port in ServerPool.get_instance().udp_servers_pool:
                        ServerPool.get_instance().udp_servers_pool[
                            port].modify_multi_user_table(md5_users)
                    if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                        ServerPool.get_instance().udp_ipv6_servers_pool[
                            port].modify_multi_user_table(md5_users)

                if self.is_relay and row['is_multi_user'] != 2:
                    temp_relay_rules = {}
                    for id in self.relay_rule_list:
                        if ((self.relay_rule_list[id]['user_id'] == user_id
                             or self.relay_rule_list[id]['user_id'] == 0)
                                or row['is_multi_user'] != 0) and (
                                    self.relay_rule_list[id]['port'] == 0 or
                                    self.relay_rule_list[id]['port'] == port):
                            has_higher_priority = False
                            for priority_id in self.relay_rule_list:
                                if ((self.relay_rule_list[priority_id]
                                     ['priority'] >
                                     self.relay_rule_list[id]['priority']
                                     and self.relay_rule_list[id]['id'] !=
                                     self.relay_rule_list[priority_id]['id'])
                                        or
                                    (self.relay_rule_list[priority_id]
                                     ['priority']
                                     == self.relay_rule_list[id]['priority']
                                     and self.relay_rule_list[id]['id'] > self.
                                     relay_rule_list[priority_id]['id'])) and (
                                         self.relay_rule_list[priority_id]
                                         ['user_id'] == user_id
                                         or self.relay_rule_list[priority_id]
                                         ['user_id'] == 0) and (
                                             self.relay_rule_list[priority_id]
                                             ['port'] == port or
                                             self.relay_rule_list[priority_id]
                                             ['port'] == 0):
                                    has_higher_priority = True
                                    continue

                            if has_higher_priority:
                                continue

                            if self.relay_rule_list[id][
                                    'dist_ip'] == '0.0.0.0' and row[
                                        'is_multi_user'] == 0:
                                continue

                            temp_relay_rules[id] = self.relay_rule_list[id]

                    if port in ServerPool.get_instance().tcp_servers_pool:
                        ServerPool.get_instance().tcp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                        ServerPool.get_instance().tcp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_servers_pool:
                        ServerPool.get_instance().udp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                        ServerPool.get_instance().udp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)

                else:
                    temp_relay_rules = {}

                    if port in ServerPool.get_instance().tcp_servers_pool:
                        ServerPool.get_instance().tcp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                        ServerPool.get_instance().tcp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_servers_pool:
                        ServerPool.get_instance().udp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                        ServerPool.get_instance().udp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)

                if port in ServerPool.get_instance().tcp_servers_pool:
                    relay = ServerPool.get_instance().tcp_servers_pool[port]
                    for name in merge_config_keys:
                        if name in cfg and not self.cmp(
                                cfg[name], relay._config[name]):
                            cfgchange = True
                            break
                if not cfgchange and port in ServerPool.get_instance(
                ).tcp_ipv6_servers_pool:
                    relay = ServerPool.get_instance(
                    ).tcp_ipv6_servers_pool[port]
                    for name in merge_config_keys:
                        if name in cfg and not self.cmp(
                                cfg[name], relay._config[name]):
                            cfgchange = True
                            break
                # config changed
                if cfgchange:
                    self.del_server(port, "config changed")
                    new_servers[port] = (passwd, cfg)
            elif ServerPool.get_instance().server_run_status(port) is False:
                # new_servers[port] = passwd
                self.new_server(port, passwd, cfg)

        for row in last_rows:
            if row['port'] in cur_servers:
                pass
            else:
                self.del_server(row['port'], "port not exist")

        if len(new_servers) > 0:
            from shadowsocks import eventloop
            self.event.wait(eventloop.TIMEOUT_PRECISION +
                            eventloop.TIMEOUT_PRECISION / 2)
            for port in new_servers.keys():
                passwd, cfg = new_servers[port]
                self.new_server(port, passwd, cfg)

        ServerPool.get_instance().push_uid_port_table(self.uid_port_table)
예제 #2
0
	def del_server_out_of_bound_safe(self, last_rows, rows):
		#停止超流量的服务
		#启动没超流量的服务
		#需要动态载入switchrule,以便实时修改规则


		try:
			switchrule = importloader.load('switchrule')
		except Exception as e:
			logging.error('load switchrule.py fail')
		cur_servers = {}
		new_servers = {}

		md5_users = {}

		for row in rows:
			if row['is_multi_user'] == 1:
				continue
			
			md5_users[row['id']] = row.copy()
			del md5_users[row['id']]['u']
			del md5_users[row['id']]['d']
			if md5_users[row['id']]['disconnect_ip'] == None:
				md5_users[row['id']]['disconnect_ip'] = ''

			if md5_users[row['id']]['forbidden_ip'] == None:
				md5_users[row['id']]['forbidden_ip'] = ''

			if md5_users[row['id']]['forbidden_port'] == None:
				md5_users[row['id']]['forbidden_port'] = ''
			md5_users[row['id']]['md5'] = common.get_md5(str(row['id']) + row['passwd'] + row['method'] + row['obfs'] + row['protocol'])

		for row in rows:

			port = row['port']
			passwd = common.to_bytes(row['passwd'])
			cfg = {'password': passwd}

			self.port_uid_table[row['port']] = row['id']
			self.uid_port_table[row['id']] = row['port']

			read_config_keys = ['method', 'obfs','obfs_param' , 'protocol', 'protocol_param' ,'forbidden_ip', 'forbidden_port' , 'node_speedlimit','forbidden_ip','forbidden_port','disconnect_ip','is_multi_user']

			for name in read_config_keys:
				if name in row and row[name]:
					cfg[name] = row[name]



			merge_config_keys = ['password'] + read_config_keys
			for name in cfg.keys():
				if hasattr(cfg[name], 'encode'):
					cfg[name] = cfg[name].encode('utf-8')

			if 'node_speedlimit' in cfg:
				if float(self.node_speedlimit) > 0.0 or float(cfg['node_speedlimit']) > 0.0 :
					cfg['node_speedlimit'] = max(float(self.node_speedlimit),float(cfg['node_speedlimit']))
			else:
				cfg['node_speedlimit'] = max(float(self.node_speedlimit),float(0.00))

			if 'disconnect_ip' not in cfg:
				cfg['disconnect_ip'] = ''

			if 'forbidden_ip' not in cfg:
				cfg['forbidden_ip'] = ''

			if 'forbidden_port' not in cfg:
				cfg['forbidden_port'] = ''

			if 'protocol_param' not in cfg:
				cfg['protocol_param'] = ''

			if 'obfs_param' not in cfg:
				cfg['obfs_param'] = ''

			if 'is_multi_user' not in cfg:
				cfg['is_multi_user'] = 0

			if port not in cur_servers:
				cur_servers[port] = passwd
			else:
				logging.error('more than one user use the same port [%s]' % (port,))
				continue

			if get_config().MULTI_THREAD == 0:
				cfg['node_speedlimit'] = 0.00

			cfg['detect_text_list'] = self.detect_text_list.copy()
			cfg['detect_hex_list'] = self.detect_hex_list.copy()

			if cfg['is_multi_user'] == 1:
				cfg['users_table'] = md5_users.copy()


			if ServerPool.get_instance().server_is_run(port) > 0:
				cfgchange = False
				if self.detect_text_ischanged == True or self.detect_hex_ischanged == True:
					cfgchange = True
				if row['is_multi_user'] == 1:
					if port in ServerPool.get_instance().tcp_servers_pool:
						ServerPool.get_instance().tcp_servers_pool[port].modify_multi_user_table(md5_users)
					if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
						ServerPool.get_instance().tcp_ipv6_servers_pool[port].modify_multi_user_table(md5_users)
					if port in ServerPool.get_instance().udp_servers_pool:
						ServerPool.get_instance().udp_servers_pool[port].modify_multi_user_table(md5_users)
					if port in ServerPool.get_instance().udp_ipv6_servers_pool:
						ServerPool.get_instance().udp_ipv6_servers_pool[port].modify_multi_user_table(md5_users)

				if port in ServerPool.get_instance().tcp_servers_pool:
					relay = ServerPool.get_instance().tcp_servers_pool[port]
					for name in merge_config_keys:
						if name in cfg and not self.cmp(cfg[name], relay._config[name]):
							cfgchange = True
							break;
				if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool:
					relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port]
					for name in merge_config_keys:
						if name in cfg and not self.cmp(cfg[name], relay._config[name]):
							cfgchange = True
							break;
				#config changed
				if cfgchange:
					logging.info('db stop server at port [%s] reason: config changed!' % (port))
					ServerPool.get_instance().cb_del_server(port)
					if port in self.last_update_transfer:
						del self.last_update_transfer[port]
					new_servers[port] = (passwd, cfg)
			elif ServerPool.get_instance().server_run_status(port) is False:
				#new_servers[port] = passwd
				protocol = cfg.get('protocol', ServerPool.get_instance().config.get('protocol', 'origin'))
				obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain'))
				logging.info('db start server at port [%s] pass [%s] protocol [%s] obfs [%s]' % (port, passwd, protocol, obfs))
				ServerPool.get_instance().new_server(port, cfg)

		ServerPool.get_instance().push_uid_port_table(self.uid_port_table)

		for row in last_rows:
			if row['port'] in cur_servers:
				pass
			else:
				logging.info('db stop server at port [%s] reason: port not exist' % (row['port']))
				ServerPool.get_instance().cb_del_server(row['port'])
				if row['port'] in self.last_update_transfer:
					del self.last_update_transfer[row['port']]
				del self.port_uid_table[row['port']]

		if len(new_servers) > 0:
			from shadowsocks import eventloop
			self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2)
			for port in new_servers.keys():
				passwd, cfg = new_servers[port]
				protocol = cfg.get('protocol', ServerPool.get_instance().config.get('protocol', 'origin'))
				obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain'))
				logging.info('db start server at port [%s] pass [%s] protocol [%s] obfs [%s]' % (port, passwd, protocol, obfs))
				self.port_uid_table[row['port']] = row['id']
				ServerPool.get_instance().new_server(port, cfg)
예제 #3
0
    def del_server_out_of_bound_safe(self, last_rows, rows):
        # 停止超流量的服务
        # 启动没超流量的服务
        # 需要动态载入switchrule,以便实时修改规则

        try:
            switchrule = importloader.load("switchrule")
        except Exception as e:
            logging.error("load switchrule.py fail")
        cur_servers = {}
        new_servers = {}

        md5_users = {}

        self.mu_port_list = []

        for row in rows:
            if row["is_multi_user"] != 0:
                self.mu_port_list.append(int(row["port"]))
                continue

            md5_users[row["id"]] = row.copy()
            del md5_users[row["id"]]["u"]
            del md5_users[row["id"]]["d"]
            if md5_users[row["id"]]["disconnect_ip"] is None:
                md5_users[row["id"]]["disconnect_ip"] = ""

            if md5_users[row["id"]]["forbidden_ip"] is None:
                md5_users[row["id"]]["forbidden_ip"] = ""

            if md5_users[row["id"]]["forbidden_port"] is None:
                md5_users[row["id"]]["forbidden_port"] = ""
            md5_users[row["id"]]["md5"] = common.get_md5(
                str(row["id"]) + row["passwd"] + row["method"] + row["obfs"] +
                row["protocol"])

        for row in rows:
            self.port_uid_table[row["port"]] = row["id"]
            self.uid_port_table[row["id"]] = row["port"]

        if self.mu_only == 1:
            i = 0
            while i < len(rows):
                if rows[i]["is_multi_user"] == 0:
                    rows.pop(i)
                    i -= 1
                else:
                    pass
                i += 1

        if self.mu_only == -1:
            i = 0
            while i < len(rows):
                if rows[i]["is_multi_user"] != 0:
                    rows.pop(i)
                    i -= 1
                else:
                    pass
                i += 1

        for row in rows:
            port = row["port"]
            user_id = row["id"]
            passwd = common.to_bytes(row["passwd"])
            cfg = {"password": passwd}

            read_config_keys = [
                "method",
                "obfs",
                "obfs_param",
                "protocol",
                "protocol_param",
                "forbidden_ip",
                "forbidden_port",
                "node_speedlimit",
                "disconnect_ip",
                "is_multi_user",
            ]

            for name in read_config_keys:
                if name in row and row[name]:
                    cfg[name] = row[name]

            merge_config_keys = ["password"] + read_config_keys
            for name in cfg.keys():
                if hasattr(cfg[name], "encode"):
                    try:
                        cfg[name] = cfg[name].encode("utf-8")
                    except Exception as e:
                        logging.warning('encode cfg key "%s" fail, val "%s"' %
                                        (name, cfg[name]))

            if "node_speedlimit" in cfg:
                if float(self.node_speedlimit) > 0.0 or float(
                        cfg["node_speedlimit"]) > 0.0:
                    cfg["node_speedlimit"] = min(
                        float(self.node_speedlimit),
                        float(cfg["node_speedlimit"]),
                    )
            else:
                cfg["node_speedlimit"] = max(float(self.node_speedlimit),
                                             float(0.00))

            if "disconnect_ip" not in cfg:
                cfg["disconnect_ip"] = ""

            if "forbidden_ip" not in cfg:
                cfg["forbidden_ip"] = ""

            if "forbidden_port" not in cfg:
                cfg["forbidden_port"] = ""

            if "protocol_param" not in cfg:
                cfg["protocol_param"] = ""

            if "obfs_param" not in cfg:
                cfg["obfs_param"] = ""

            if "is_multi_user" not in cfg:
                cfg["is_multi_user"] = 0

            if port not in cur_servers:
                cur_servers[port] = passwd
            else:
                logging.error("more than one user use the same port [%s]" %
                              (port, ))
                continue

            if cfg["is_multi_user"] != 0:
                cfg["users_table"] = md5_users.copy()

            cfg["detect_hex_list"] = self.detect_hex_list.copy()
            cfg["detect_text_list"] = self.detect_text_list.copy()

            if self.is_relay and row["is_multi_user"] != 2:
                temp_relay_rules = {}
                for id in self.relay_rule_list:
                    if ((self.relay_rule_list[id]["user_id"] == user_id
                         or self.relay_rule_list[id]["user_id"] == 0)
                            or row["is_multi_user"] != 0) and (
                                self.relay_rule_list[id]["port"] == 0
                                or self.relay_rule_list[id]["port"] == port):
                        has_higher_priority = False
                        for priority_id in self.relay_rule_list:
                            if (((self.relay_rule_list[priority_id]["priority"]
                                  > self.relay_rule_list[id]["priority"]
                                  and self.relay_rule_list[id]["id"] !=
                                  self.relay_rule_list[priority_id]["id"]) or
                                 (self.relay_rule_list[priority_id]["priority"]
                                  == self.relay_rule_list[id]["priority"]
                                  and self.relay_rule_list[id]["id"] >
                                  self.relay_rule_list[priority_id]["id"])) and
                                (self.relay_rule_list[priority_id]["user_id"]
                                 == user_id or
                                 self.relay_rule_list[priority_id]["user_id"]
                                 == 0) and
                                (self.relay_rule_list[priority_id]["port"]
                                 == port
                                 or self.relay_rule_list[priority_id]["port"]
                                 == 0)):
                                has_higher_priority = True
                                continue

                        if has_higher_priority:
                            continue

                        if self.relay_rule_list[id][
                                "dist_ip"] == "0.0.0.0" and row[
                                    "is_multi_user"] == 0:
                            continue

                        temp_relay_rules[id] = self.relay_rule_list[id]

                cfg["relay_rules"] = temp_relay_rules.copy()
            else:
                temp_relay_rules = {}

                cfg["relay_rules"] = temp_relay_rules.copy()

            if ServerPool.get_instance().server_is_run(port) > 0:
                cfgchange = False

                if port in ServerPool.get_instance().tcp_servers_pool:
                    ServerPool.get_instance(
                    ).tcp_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).tcp_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)
                if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                    ServerPool.get_instance(
                    ).tcp_ipv6_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).tcp_ipv6_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)
                if port in ServerPool.get_instance().udp_servers_pool:
                    ServerPool.get_instance(
                    ).udp_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).udp_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)
                if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                    ServerPool.get_instance(
                    ).udp_ipv6_servers_pool[port].modify_detect_text_list(
                        self.detect_text_list)
                    ServerPool.get_instance(
                    ).udp_ipv6_servers_pool[port].modify_detect_hex_list(
                        self.detect_hex_list)

                if row["is_multi_user"] != 0:
                    if port in ServerPool.get_instance().tcp_servers_pool:
                        ServerPool.get_instance().tcp_servers_pool[
                            port].modify_multi_user_table(md5_users)
                    if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                        ServerPool.get_instance().tcp_ipv6_servers_pool[
                            port].modify_multi_user_table(md5_users)
                    if port in ServerPool.get_instance().udp_servers_pool:
                        ServerPool.get_instance().udp_servers_pool[
                            port].modify_multi_user_table(md5_users)
                    if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                        ServerPool.get_instance().udp_ipv6_servers_pool[
                            port].modify_multi_user_table(md5_users)

                if self.is_relay and row["is_multi_user"] != 2:
                    temp_relay_rules = {}
                    for id in self.relay_rule_list:
                        if ((self.relay_rule_list[id]["user_id"] == user_id
                             or self.relay_rule_list[id]["user_id"] == 0)
                                or row["is_multi_user"] != 0) and (
                                    self.relay_rule_list[id]["port"] == 0 or
                                    self.relay_rule_list[id]["port"] == port):
                            has_higher_priority = False
                            for priority_id in self.relay_rule_list:
                                if (((self.relay_rule_list[priority_id]
                                      ["priority"] >
                                      self.relay_rule_list[id]["priority"]
                                      and self.relay_rule_list[id]["id"] !=
                                      self.relay_rule_list[priority_id]["id"])
                                     or
                                     (self.relay_rule_list[priority_id]
                                      ["priority"]
                                      == self.relay_rule_list[id]["priority"]
                                      and self.relay_rule_list[id]["id"] >
                                      self.relay_rule_list[priority_id]["id"]))
                                        and
                                    (self.relay_rule_list[priority_id]
                                     ["user_id"] == user_id
                                     or self.relay_rule_list[priority_id]
                                     ["user_id"] == 0) and
                                    (self.relay_rule_list[priority_id]["port"]
                                     == port or
                                     self.relay_rule_list[priority_id]["port"]
                                     == 0)):
                                    has_higher_priority = True
                                    continue

                            if has_higher_priority:
                                continue

                            if self.relay_rule_list[id][
                                    "dist_ip"] == "0.0.0.0" and row[
                                        "is_multi_user"] == 0:
                                continue

                            temp_relay_rules[id] = self.relay_rule_list[id]

                    if port in ServerPool.get_instance().tcp_servers_pool:
                        ServerPool.get_instance().tcp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                        ServerPool.get_instance().tcp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_servers_pool:
                        ServerPool.get_instance().udp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                        ServerPool.get_instance().udp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)

                else:
                    temp_relay_rules = {}

                    if port in ServerPool.get_instance().tcp_servers_pool:
                        ServerPool.get_instance().tcp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().tcp_ipv6_servers_pool:
                        ServerPool.get_instance().tcp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_servers_pool:
                        ServerPool.get_instance().udp_servers_pool[
                            port].push_relay_rules(temp_relay_rules)
                    if port in ServerPool.get_instance().udp_ipv6_servers_pool:
                        ServerPool.get_instance().udp_ipv6_servers_pool[
                            port].push_relay_rules(temp_relay_rules)

                if port in ServerPool.get_instance().tcp_servers_pool:
                    relay = ServerPool.get_instance().tcp_servers_pool[port]
                    for name in merge_config_keys:
                        if name in cfg and not self.cmp(
                                cfg[name], relay._config[name]):
                            cfgchange = True
                            break
                if not cfgchange and port in ServerPool.get_instance(
                ).tcp_ipv6_servers_pool:
                    relay = ServerPool.get_instance(
                    ).tcp_ipv6_servers_pool[port]
                    for name in merge_config_keys:
                        if name in cfg and not self.cmp(
                                cfg[name], relay._config[name]):
                            cfgchange = True
                            break
                # config changed
                if cfgchange:
                    self.del_server(port, "config changed")
                    new_servers[port] = (passwd, cfg)
            elif ServerPool.get_instance().server_run_status(port) is False:
                # new_servers[port] = passwd
                self.new_server(port, passwd, cfg)

        for row in last_rows:
            if row["port"] in cur_servers:
                pass
            else:
                self.del_server(row["port"], "port not exist")

        if len(new_servers) > 0:
            from shadowsocks import eventloop

            self.event.wait(eventloop.TIMEOUT_PRECISION +
                            eventloop.TIMEOUT_PRECISION / 2)
            for port in new_servers.keys():
                passwd, cfg = new_servers[port]
                self.new_server(port, passwd, cfg)

        ServerPool.get_instance().push_uid_port_table(self.uid_port_table)