From f61bbefa95ee43c485b44f0fc0e1a8af92e2a452 Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Mon, 23 Oct 2017 14:18:58 +0800 Subject: [PATCH 01/14] Add cache flag --- shadowsocks/encrypt.py | 19 ++++++++++++------- shadowsocks/obfsplugin/auth_chain.py | 7 ++----- shadowsocks/tcprelay.py | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/shadowsocks/encrypt.py b/shadowsocks/encrypt.py index 29a9e6d..a9fd02a 100644 --- a/shadowsocks/encrypt.py +++ b/shadowsocks/encrypt.py @@ -46,7 +46,7 @@ def try_cipher(key, method=None): Encryptor(key, method) -def EVP_BytesToKey(password, key_len, iv_len): +def EVP_BytesToKey(password, key_len, iv_len, cache): # equivalent to OpenSSL's EVP_BytesToKey() with count 1 # so that we make the same key and iv as nodejs version cached_key = '%s-%d-%d' % (password, key_len, iv_len) @@ -66,13 +66,14 @@ def EVP_BytesToKey(password, key_len, iv_len): ms = b''.join(m) key = ms[:key_len] iv = ms[key_len:key_len + iv_len] - cached_keys[cached_key] = (key, iv) - cached_keys.sweep() + if cache: + cached_keys[cached_key] = (key, iv) + cached_keys.sweep() return key, iv class Encryptor(object): - def __init__(self, key, method, iv = None): + def __init__(self, key, method, iv = None, cache = False): self.key = key self.method = method self.iv = None @@ -81,6 +82,7 @@ class Encryptor(object): self.iv_buf = b'' self.cipher_key = b'' self.decipher = None + self.cache = cache method = method.lower() self._method_info = self.get_method_info(method) if self._method_info: @@ -105,7 +107,7 @@ class Encryptor(object): password = common.to_bytes(password) m = self._method_info if m[0] > 0: - key, iv_ = EVP_BytesToKey(password, m[0], m[1]) + key, iv_ = EVP_BytesToKey(password, m[0], m[1], self.cache) else: # key_length == 0 indicates we should use the key directly key, iv = password, b'' @@ -119,6 +121,9 @@ class Encryptor(object): def encrypt(self, buf): if len(buf) == 0: + if not self.iv_sent: + self.iv_sent = True + return self.cipher_iv return buf if self.iv_sent: return self.cipher.update(buf) @@ -155,7 +160,7 @@ def encrypt_all(password, method, op, data): method = method.lower() (key_len, iv_len, m) = method_supported[method] if key_len > 0: - key, _ = EVP_BytesToKey(password, key_len, iv_len) + key, _ = EVP_BytesToKey(password, key_len, iv_len, True) else: key = password if op: @@ -172,7 +177,7 @@ def encrypt_key(password, method): method = method.lower() (key_len, iv_len, m) = method_supported[method] if key_len > 0: - key, _ = EVP_BytesToKey(password, key_len, iv_len) + key, _ = EVP_BytesToKey(password, key_len, iv_len, True) else: key = password return key diff --git a/shadowsocks/obfsplugin/auth_chain.py b/shadowsocks/obfsplugin/auth_chain.py index 6619f4f..2860655 100644 --- a/shadowsocks/obfsplugin/auth_chain.py +++ b/shadowsocks/obfsplugin/auth_chain.py @@ -349,7 +349,6 @@ class auth_chain_a(auth_base): def pack_client_data(self, buf): buf = self.encryptor.encrypt(buf) data = self.rnd_data(len(buf), buf, self.last_client_hash, self.random_client) - data_len = len(data) + 8 mac_key = self.user_key + struct.pack('= 4096: self.raw_trans = True self.recv_buf = b'' - if self.recv_id == 0: + if self.recv_id == 1: logging.info(self.no_compatible_method + ': over size') return (b'E' * 2048, False) else: @@ -581,7 +578,7 @@ class auth_chain_a(auth_base): )) self.raw_trans = True self.recv_buf = b'' - if self.recv_id == 0: + if self.recv_id == 1: return (b'E' * 2048, False) else: raise Exception('server_post_decrype data uncorrect checksum') diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index ce84d84..e4b8fbe 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -266,7 +266,7 @@ class TCPRelayHandler(object): def _create_encryptor(self, config): try: self._encryptor = encrypt.Encryptor(config['password'], - config['method']) + config['method'], None, True) return True except Exception: self._stage = STAGE_DESTROYED From 99cd2d5c315169175fb088a725a3e769332516d8 Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Wed, 8 Nov 2017 15:46:11 +0800 Subject: [PATCH 02/14] auth_chain_f sync from client time --- shadowsocks/obfsplugin/auth_chain.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/shadowsocks/obfsplugin/auth_chain.py b/shadowsocks/obfsplugin/auth_chain.py index 2860655..49bafdc 100644 --- a/shadowsocks/obfsplugin/auth_chain.py +++ b/shadowsocks/obfsplugin/auth_chain.py @@ -414,6 +414,9 @@ class auth_chain_a(auth_base): self.server_info.data.local_client_id, struct.pack('> (8 * i)) & 0xFF) - self.server_info.data.set_max_client(max_client) self.init_data_size(self.server_info.key) def init_data_size(self, key): @@ -893,9 +899,13 @@ class auth_chain_f(auth_chain_e): random = xorshift128plus() # key xor with key_change_datetime_key new_key = bytearray(key) + new_key_str = '' for i in range(0, 8): new_key[i] ^= self.key_change_datetime_key_bytes[i] - random.init_from_bin(new_key) + new_key_str += chr(new_key[i]) + for i in range(8, len(new_key)): + new_key_str += chr(new_key[i]) + random.init_from_bin(to_bytes(new_key_str)) # 补全数组长为12~24-1 list_len = random.next() % (8 + 16) + (4 + 8) for i in range(0, list_len): From ca740c8c9bc9c6adccca69a9c2f1a4aa7e2e7258 Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Thu, 9 Nov 2017 14:19:31 +0800 Subject: [PATCH 03/14] optimize --- shadowsocks/obfsplugin/auth_chain.py | 11 ++++++----- shadowsocks/tcprelay.py | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/shadowsocks/obfsplugin/auth_chain.py b/shadowsocks/obfsplugin/auth_chain.py index 49bafdc..bed2ffa 100644 --- a/shadowsocks/obfsplugin/auth_chain.py +++ b/shadowsocks/obfsplugin/auth_chain.py @@ -87,19 +87,20 @@ class xorshift128plus(object): y = self.v1 self.v0 = y x ^= ((x & xorshift128plus.mov_mask) << 23) - x ^= (y ^ (x >> 17) ^ (y >> 26)) & xorshift128plus.max_int + x ^= (y ^ (x >> 17) ^ (y >> 26)) self.v1 = x return (x + y) & xorshift128plus.max_int def init_from_bin(self, bin): - bin += b'\0' * 16 + if len(bin) < 16: + bin += b'\0' * 16 self.v0 = struct.unpack(' 0: From 199755552d8cd21867c30b9a4a97fdbaaa992ced Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Thu, 9 Nov 2017 17:54:22 +0800 Subject: [PATCH 04/14] fix coding --- configloader.py | 2 +- db_transfer.py | 2 +- importloader.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configloader.py b/configloader.py index cf9d619..1794641 100644 --- a/configloader.py +++ b/configloader.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- import importloader g_config = None diff --git a/db_transfer.py b/db_transfer.py index 67bda60..61a21dc 100644 --- a/db_transfer.py +++ b/db_transfer.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- import logging import time diff --git a/importloader.py b/importloader.py index c917cb7..cedc526 100644 --- a/importloader.py +++ b/importloader.py @@ -1,5 +1,5 @@ #!/usr/bin/python -# -*- coding: UTF-8 -*- +# -*- coding: utf-8 -*- def load(name): try: From a9e49b77f208cdee41fb7b8e3085f8acb418fd06 Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Tue, 14 Nov 2017 11:07:36 +0800 Subject: [PATCH 05/14] optimize --- shadowsocks/obfsplugin/auth_chain.py | 29 +++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/shadowsocks/obfsplugin/auth_chain.py b/shadowsocks/obfsplugin/auth_chain.py index bed2ffa..ce7ad35 100644 --- a/shadowsocks/obfsplugin/auth_chain.py +++ b/shadowsocks/obfsplugin/auth_chain.py @@ -18,8 +18,6 @@ from __future__ import absolute_import, division, print_function, \ with_statement -import os -import sys import hashlib import logging import binascii @@ -29,16 +27,16 @@ import datetime import random import math import struct -import zlib import hmac -import hashlib import bisect import shadowsocks from shadowsocks import common, lru_cache, encrypt from shadowsocks.obfsplugin import plain from shadowsocks.common import to_bytes, to_str, ord, chr +from shadowsocks.crypto import openssl +rand_bytes = openssl.rand_bytes def create_auth_chain_a(method): return auth_chain_a(method) @@ -106,7 +104,6 @@ class xorshift128plus(object): for i in range(4): self.next() - def match_begin(str1, str2): if len(str1) >= len(str2): if str1[:len(str2)] == str2: @@ -336,7 +333,7 @@ class auth_chain_a(auth_base): def rnd_data(self, buf_size, buf, last_hash, random): rand_len = self.rnd_data_len(buf_size, last_hash, random) - rnd_data_buf = os.urandom(rand_len) + rnd_data_buf = rand_bytes(rand_len) if buf_size == 0: return rnd_data_buf @@ -374,7 +371,7 @@ class auth_chain_a(auth_base): data = data + (struct.pack(' 0xFF000000: self.server_info.data.local_client_id = b'' if not self.server_info.data.local_client_id: - self.server_info.data.local_client_id = os.urandom(4) + self.server_info.data.local_client_id = rand_bytes(4) logging.debug("local_client_id %s" % (binascii.hexlify(self.server_info.data.local_client_id),)) - self.server_info.data.connection_id = struct.unpack(' Date: Mon, 20 Nov 2017 23:29:59 +0800 Subject: [PATCH 06/14] fix PyMySQL source --- setup_cymysql.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup_cymysql.sh b/setup_cymysql.sh index 4113885..cc1ba35 100755 --- a/setup_cymysql.sh +++ b/setup_cymysql.sh @@ -1,6 +1,6 @@ #!/bin/bash rm -rf CyMySQL rm -rf cymysql -git clone https://github.com/nakagami/CyMySQL.git +git clone https://github.com/PyMySQL/CyMySQL.git mv CyMySQL/cymysql ./ rm -rf CyMySQL From 119defdf4bcaeb6741742c13f355838e0efc59e2 Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Tue, 21 Nov 2017 12:48:58 +0800 Subject: [PATCH 07/14] fix 'server_ipv6' value type revert pymysql --- server_pool.py | 8 ++++---- setup_cymysql.sh | 2 +- shadowsocks/server.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server_pool.py b/server_pool.py index d159817..b96bfeb 100644 --- a/server_pool.py +++ b/server_pool.py @@ -119,12 +119,12 @@ class ServerPool(object): a_config.update(user_config) if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] - a_config['server'] = a_config['server_ipv6'] + a_config['server'] = common.to_str(a_config['server_ipv6']) a_config['server_port'] = port a_config['max_connect'] = 128 a_config['method'] = common.to_str(a_config['method']) try: - logging.info("starting server at [%s]:%d" % (common.to_str(a_config['server']), port)) + logging.info("starting server at [%s]:%d" % (a_config['server'], port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False, stat_counter=self.stat_counter) tcp_server.add_to_loop(self.loop) @@ -134,7 +134,7 @@ class ServerPool(object): udp_server.add_to_loop(self.loop) self.udp_ipv6_servers_pool.update({port: udp_server}) - if common.to_str(a_config['server_ipv6']) == "::": + if a_config['server_ipv6'] == "::": ipv6_ok = True except Exception as e: logging.warn("IPV6 %s " % (e,)) @@ -150,7 +150,7 @@ class ServerPool(object): a_config['max_connect'] = 128 a_config['method'] = common.to_str(a_config['method']) try: - logging.info("starting server at %s:%d" % (common.to_str(a_config['server']), port)) + 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) diff --git a/setup_cymysql.sh b/setup_cymysql.sh index cc1ba35..4113885 100755 --- a/setup_cymysql.sh +++ b/setup_cymysql.sh @@ -1,6 +1,6 @@ #!/bin/bash rm -rf CyMySQL rm -rf cymysql -git clone https://github.com/PyMySQL/CyMySQL.git +git clone https://github.com/nakagami/CyMySQL.git mv CyMySQL/cymysql ./ rm -rf CyMySQL diff --git a/shadowsocks/server.py b/shadowsocks/server.py index 0815389..9af80d7 100755 --- a/shadowsocks/server.py +++ b/shadowsocks/server.py @@ -120,7 +120,7 @@ def main(): a_config['obfs_param'] = obfs_param a_config['out_bind'] = bind a_config['out_bindv6'] = bindv6 - a_config['server'] = a_config['server_ipv6'] + a_config['server'] = common.to_str(a_config['server_ipv6']) logging.info("starting server at [%s]:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) From 23fea5e329d74c9e2d20604a7777e4ada18a23e3 Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Tue, 21 Nov 2017 12:58:28 +0800 Subject: [PATCH 08/14] fix str type --- server_pool.py | 2 +- shadowsocks/server.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server_pool.py b/server_pool.py index b96bfeb..fcf6caf 100644 --- a/server_pool.py +++ b/server_pool.py @@ -117,7 +117,7 @@ class ServerPool(object): else: a_config = self.config.copy() a_config.update(user_config) - if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": + if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == b"[" and a_config['server_ipv6'][-1] == b"]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] a_config['server'] = common.to_str(a_config['server_ipv6']) a_config['server_port'] = port diff --git a/shadowsocks/server.py b/shadowsocks/server.py index 9af80d7..dced0a3 100755 --- a/shadowsocks/server.py +++ b/shadowsocks/server.py @@ -108,8 +108,8 @@ def main(): (protocol, password, method, obfs, obfs_param)) if 'server_ipv6' in a_config: try: - if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][ - -1] == "]": + if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == b"[" and a_config['server_ipv6'][ + -1] == b"]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] a_config['server_port'] = int(port) a_config['password'] = password From 096a27cf36eff2ba381bac1e22238963956a999b Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Thu, 4 Jan 2018 21:10:58 +0800 Subject: [PATCH 09/14] add row map --- db_transfer.py | 28 +++++++++++++++++++++++----- switchrule.py | 3 +++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/db_transfer.py b/db_transfer.py index 61a21dc..e1a404c 100644 --- a/db_transfer.py +++ b/db_transfer.py @@ -9,6 +9,7 @@ import traceback from shadowsocks import common, shell, lru_cache, obfs from configloader import load_config, get_config import importloader +import copy switchrule = None db_instance = None @@ -80,8 +81,10 @@ class TransferBase(object): def del_server_out_of_bound_safe(self, last_rows, rows): #停止超流量的服务 #启动没超流量的服务 + keymap = {} try: switchrule = importloader.load('switchrule') + keymap = switchrule.getRowMap() except Exception as e: logging.error('load switchrule.py fail') cur_servers = {} @@ -106,7 +109,10 @@ class TransferBase(object): read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'speed_limit_per_con', 'speed_limit_per_user'] for name in read_config_keys: if name in row and row[name]: - cfg[name] = row[name] + if name in keymap: + cfg[keymap[name]] = row[name] + else: + cfg[name] = row[name] merge_config_keys = ['password'] + read_config_keys for name in cfg.keys(): @@ -392,11 +398,17 @@ class DbTransfer(TransferBase): return rows def pull_db_users(self, conn): + keys = copy.copy(self.key_list) try: switchrule = importloader.load('switchrule') - keys = switchrule.getKeys(self.key_list) + keymap = switchrule.getRowMap() + for key in keymap: + if keymap[key] in keys: + keys.remove(keymap[key]) + keys.append(key) + keys = switchrule.getKeys(keys) except Exception as e: - keys = self.key_list + logging.error('load switchrule.py fail') cur = conn.cursor() cur.execute("SELECT " + ','.join(keys) + " FROM user") @@ -520,11 +532,17 @@ class Dbv3Transfer(DbTransfer): return update_transfer def pull_db_users(self, conn): + keys = copy.copy(self.key_list) try: switchrule = importloader.load('switchrule') - keys = switchrule.getKeys(self.key_list) + keymap = switchrule.getRowMap() + for key in keymap: + if keymap[key] in keys: + keys.remove(keymap[key]) + keys.append(key) + keys = switchrule.getKeys(keys) except Exception as e: - keys = self.key_list + logging.error('load switchrule.py fail') cur = conn.cursor() diff --git a/switchrule.py b/switchrule.py index 6687e12..56ed995 100644 --- a/switchrule.py +++ b/switchrule.py @@ -1,3 +1,6 @@ +def getRowMap(): + return {} # if your db row "encrypt" means "method", write {"encrypt": "method"} + def getKeys(key_list): return key_list #return key_list + ['plan'] # append the column name 'plan' From b31885113aa95e0ba96cf9fa6a5b91d6c359364c Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Sat, 20 Jan 2018 11:05:11 +0800 Subject: [PATCH 10/14] fix auth_chain_e & auth_chain_f --- shadowsocks/obfsplugin/auth_chain.py | 1 + 1 file changed, 1 insertion(+) diff --git a/shadowsocks/obfsplugin/auth_chain.py b/shadowsocks/obfsplugin/auth_chain.py index ce7ad35..9a2ce80 100644 --- a/shadowsocks/obfsplugin/auth_chain.py +++ b/shadowsocks/obfsplugin/auth_chain.py @@ -854,6 +854,7 @@ class auth_chain_e(auth_chain_d): self.no_compatible_method = 'auth_chain_e' def rnd_data_len(self, buf_size, last_hash, random): + random.init_from_bin_len(last_hash, buf_size) other_data_size = buf_size + self.server_info.overhead # if other_data_size > the bigest item in data_size_list0, not padding any data if other_data_size >= self.data_size_list0[-1]: From d2f3900f680fd6df5d5050664db15a637a606fd3 Mon Sep 17 00:00:00 2001 From: Akkariiin Date: Wed, 28 Feb 2018 16:21:28 +0800 Subject: [PATCH 11/14] fix libsodium.so.23 cannot find on some strange linux environment that case by ```ctypes.util.find_library()``` have different find path from ```CDLL()``` --- shadowsocks/crypto/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shadowsocks/crypto/util.py b/shadowsocks/crypto/util.py index 679540d..12d9b7e 100644 --- a/shadowsocks/crypto/util.py +++ b/shadowsocks/crypto/util.py @@ -68,7 +68,9 @@ def find_library(possible_lib_names, search_symbol, library_name): if path: paths.append(path) - if not paths: + # always find lib on extend path that to avoid ```CDLL()``` failed on some strange linux environment + # in that case ```ctypes.util.find_library()``` have different find path from ```CDLL()``` + if True: # We may get here when find_library fails because, for example, # the user does not have sufficient privileges to access those # tools underlying find_library on linux. From 063ce5d0ef526b01566f678b81964bfbb7097d2a Mon Sep 17 00:00:00 2001 From: AkaneAkaza Date: Wed, 7 Mar 2018 12:30:40 +0800 Subject: [PATCH 12/14] increase UDP buffer --- shadowsocks/udprelay.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shadowsocks/udprelay.py b/shadowsocks/udprelay.py index b9606cd..cebe974 100644 --- a/shadowsocks/udprelay.py +++ b/shadowsocks/udprelay.py @@ -213,6 +213,8 @@ class UDPRelay(object): server_socket = socket.socket(af, socktype, proto) server_socket.bind((self._listen_addr, self._listen_port)) server_socket.setblocking(False) + server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024 * 1024) + server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024 * 1024) self._server_socket = server_socket self._stat_callback = stat_callback From 55c0e5780673dcff53bd3356a871b40ce9509d92 Mon Sep 17 00:00:00 2001 From: Akkariiin Date: Thu, 26 Apr 2018 13:07:22 +0800 Subject: [PATCH 13/14] fix 'cannot use a string pattern on a bytes-like object' on common.match_regex add test case for match_regex fix test case for parse_header --- shadowsocks/common.py | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/shadowsocks/common.py b/shadowsocks/common.py index c4484c0..d022f3a 100644 --- a/shadowsocks/common.py +++ b/shadowsocks/common.py @@ -121,7 +121,19 @@ def is_ip(address): return False +def sync_str_bytes(obj, target_example): + """sync (obj)'s type to (target_example)'s type""" + if type(obj) != type(target_example): + if type(target_example) == str: + obj = to_str(obj) + if type(target_example) == bytes: + obj = to_bytes(obj) + return obj + + def match_regex(regex, text): + # avoid 'cannot use a string pattern on a bytes-like object' + regex = sync_str_bytes(regex, text) regex = re.compile(regex) for item in regex.findall(text): return True @@ -381,12 +393,12 @@ def test_inet_conv(): def test_parse_header(): assert parse_header(b'\x03\x0ewww.google.com\x00\x50') == \ - (0, b'www.google.com', 80, 18) + (0, ADDRTYPE_HOST, b'www.google.com', 80, 18) assert parse_header(b'\x01\x08\x08\x08\x08\x00\x35') == \ - (0, b'8.8.8.8', 53, 7) + (0, ADDRTYPE_IPV4, b'8.8.8.8', 53, 7) assert parse_header((b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00' b'\x00\x10\x11\x00\x50')) == \ - (0, b'2404:6800:4005:805::1011', 80, 19) + (0, ADDRTYPE_IPV6, b'2404:6800:4005:805::1011', 80, 19) def test_pack_header(): @@ -411,7 +423,25 @@ def test_ip_network(): assert 'www.google.com' not in ip_network +def test_sync_str_bytes(): + assert sync_str_bytes(b'a\.b', b'a\.b') == b'a\.b' + assert sync_str_bytes('a\.b', b'a\.b') == b'a\.b' + assert sync_str_bytes(b'a\.b', 'a\.b') == 'a\.b' + assert sync_str_bytes('a\.b', 'a\.b') == 'a\.b' + pass + + +def test_match_regex(): + assert match_regex(br'a\.b', b'abc,aaa,aaa,b,aaa.b,a.b') + assert match_regex(r'a\.b', b'abc,aaa,aaa,b,aaa.b,a.b') + assert match_regex(br'a\.b', b'abc,aaa,aaa,b,aaa.b,a.b') + assert match_regex(r'a\.b', b'abc,aaa,aaa,b,aaa.b,a.b') + assert match_regex(r'\bgoogle\.com\b', b' google.com ') + pass + if __name__ == '__main__': + test_sync_str_bytes() + test_match_regex() test_inet_conv() test_parse_header() test_pack_header() From e0867eae561c57ddabad313186dc4a14b1d39e0c Mon Sep 17 00:00:00 2001 From: Akkariiin Date: Tue, 22 May 2018 17:00:16 +0800 Subject: [PATCH 14/14] bump version --- shadowsocks/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks/version.py b/shadowsocks/version.py index 9681022..7454f3f 100644 --- a/shadowsocks/version.py +++ b/shadowsocks/version.py @@ -16,5 +16,5 @@ # under the License. def version(): - return 'SSRR 3.2.1 2017-10-15' + return 'SSRR 3.2.2 2018-05-22'