From c41cff67ac0d34a945b15706bf66172ecdd490e5 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Fri, 16 Jul 2021 23:25:56 +0530 Subject: [PATCH 01/12] python 3 port --- src/bmconfigparser.py | 4 ++-- src/highlevelcrypto.py | 14 ++++++++---- src/protocol.py | 45 +++++++++++++++++++++++++++----------- src/tests/test_protocol.py | 9 +++----- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index 7e82ae89cc..8c7abae60c 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -14,8 +14,8 @@ import state from singleton import Singleton except ImportError: - from pybitmessage import state - from pybitmessage.singleton import Singleton + from . import state + from .singleton import Singleton SafeConfigParser = configparser.SafeConfigParser diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py index f89a31c8c0..995c5d00e0 100644 --- a/src/highlevelcrypto.py +++ b/src/highlevelcrypto.py @@ -9,10 +9,16 @@ from binascii import hexlify -import pyelliptic -from bmconfigparser import BMConfigParser -from pyelliptic import OpenSSL -from pyelliptic import arithmetic as a +try: + import pyelliptic + from bmconfigparser import BMConfigParser + from pyelliptic import OpenSSL + from pyelliptic import arithmetic as a +except ImportError: + from . import pyelliptic + from .bmconfigparser import BMConfigParser + from .pyelliptic import OpenSSL + from .pyelliptic import arithmetic as a def makeCryptor(privkey): diff --git a/src/protocol.py b/src/protocol.py index 4f2d08568f..e62007454e 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -13,16 +13,30 @@ from binascii import hexlify from struct import Struct, pack, unpack -import defaults -import highlevelcrypto -import state -from addresses import ( - encodeVarint, decodeVarint, decodeAddress, varintDecodeError) -from bmconfigparser import BMConfigParser -from debug import logger -from fallback import RIPEMD160Hash -from helper_sql import sqlExecute -from version import softwareVersion +try: + import defaults + import highlevelcrypto + import state + from addresses import ( + encodeVarint, decodeVarint, decodeAddress, varintDecodeError) + from bmconfigparser import BMConfigParser + from debug import logger + from fallback import RIPEMD160Hash + from helper_sql import sqlExecute + from version import softwareVersion +except ImportError: + from . import defaults + from . import highlevelcrypto + from . import state + from .addresses import ( + encodeVarint, decodeVarint, decodeAddress, varintDecodeError) + from .bmconfigparser import BMConfigParser + from .debug import logger + from .fallback import RIPEMD160Hash + from .helper_sql import sqlExecute + from .version import softwareVersion + +PY3 = sys.version_info[0] >= 3 # Service flags #: This is a normal network node @@ -100,8 +114,13 @@ def encodeHost(host): return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( host.split(".")[0], True) elif host.find(':') == -1: - return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ - socket.inet_aton(host) + import pdb; pdb.set_trace() + if PY3: + return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ + socket.inet_aton(host).decode('utf-8') + else: + return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ + socket.inet_aton(host) return socket.inet_pton(socket.AF_INET6, host) @@ -210,7 +229,7 @@ def checkIPv6Address(host, hostStandardFormat, private=False): if not private: logger.debug('Ignoring local address: %s', hostStandardFormat) return hostStandardFormat if private else False - if (ord(host[0]) & 0xfe) == 0xfc: + if (ord(str(host[0])) & 0xfe) == 0xfc: if not private: logger.debug( 'Ignoring unique local address: %s', hostStandardFormat) diff --git a/src/tests/test_protocol.py b/src/tests/test_protocol.py index a3c73a73f0..e5cb3b3a12 100644 --- a/src/tests/test_protocol.py +++ b/src/tests/test_protocol.py @@ -4,10 +4,6 @@ import unittest -from .common import skip_python3 - -skip_python3() - class TestProtocol(unittest.TestCase): """Main protocol test case""" @@ -15,11 +11,12 @@ class TestProtocol(unittest.TestCase): def test_check_local(self): """Check the logic of TCPConnection.local""" from pybitmessage import protocol, state + # import pdb; pdb.set_trace() self.assertTrue( - protocol.checkIPAddress(protocol.encodeHost('127.0.0.1'), True)) + protocol.checkIPAddress(protocol.encodeHost('127.0.0.1').decode('ISO-8859-1'), True)) self.assertTrue( - protocol.checkIPAddress(protocol.encodeHost('192.168.0.1'), True)) + protocol.checkIPAddress(protocol.encodeHost('192.168.0.1').decode('ISO-8859-1'), True)) self.assertTrue( not protocol.checkSocksIP('127.0.0.1') From bf6426376e6b862cc38f23c759936e5dd47f2dbf Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Tue, 20 Jul 2021 16:44:43 +0530 Subject: [PATCH 02/12] Fixed errors & Py2/3 compatibility --- src/protocol.py | 130 +++++++++++++++++++++++++------------ src/tests/test_protocol.py | 4 +- 2 files changed, 89 insertions(+), 45 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index e62007454e..eb106e24cc 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -114,10 +114,9 @@ def encodeHost(host): return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( host.split(".")[0], True) elif host.find(':') == -1: - import pdb; pdb.set_trace() if PY3: - return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ - socket.inet_aton(host).decode('utf-8') + return b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ + socket.inet_aton(host) else: return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ socket.inet_aton(host) @@ -166,25 +165,46 @@ def checkIPAddress(host, private=False): Returns hostStandardFormat if it is a valid IP address, otherwise returns False """ - if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': - hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) - return checkIPv4Address(host[12:], hostStandardFormat, private) - elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43': - # Onion, based on BMD/bitcoind - hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" - if private: - return False - return hostStandardFormat + if not isinstance(host, str): + if host[0:12] == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': + hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) + return checkIPv4Address(host[12:], hostStandardFormat, private) + elif host[0:6] == b'\xfd\x87\xd8\x7e\xeb\x43': + # Onion, based on BMD/bitcoind + hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" + if private: + return False + return hostStandardFormat + else: + try: + hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) + except ValueError: + return False + if hostStandardFormat == "": + # This can happen on Windows systems which are + # not 64-bit compatible so let us drop the IPv6 address. + return False + return checkIPv6Address(host, hostStandardFormat, private) else: - try: - hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) - except ValueError: - return False - if hostStandardFormat == "": - # This can happen on Windows systems which are - # not 64-bit compatible so let us drop the IPv6 address. - return False - return checkIPv6Address(host, hostStandardFormat, private) + if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': + hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) + return checkIPv4Address(host[12:], hostStandardFormat, private) + elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43': + # Onion, based on BMD/bitcoind + hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" + if private: + return False + return hostStandardFormat + else: + try: + hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) + except ValueError: + return False + if hostStandardFormat == "": + # This can happen on Windows systems which are + # not 64-bit compatible so let us drop the IPv6 address. + return False + return checkIPv6Address(host, hostStandardFormat, private) def checkIPv4Address(host, hostStandardFormat, private=False): @@ -192,28 +212,52 @@ def checkIPv4Address(host, hostStandardFormat, private=False): Returns hostStandardFormat if it is an IPv4 address, otherwise returns False """ - if host[0] == '\x7F': # 127/8 - if not private: - logger.debug( - 'Ignoring IP address in loopback range: %s', - hostStandardFormat) - return hostStandardFormat if private else False - if host[0] == '\x0A': # 10/8 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - if host[0:2] == '\xC0\xA8': # 192.168/16 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - return False if private else hostStandardFormat + if not isinstance(host, str): + if host[0] == 127: # 127/8 + if not private: + logger.debug( + 'Ignoring IP address in loopback range: %s', + hostStandardFormat) + return hostStandardFormat if private else False + if host[0] == 10: # 10/8 + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + if host[0:2] == b'\xC0\xA8': # 192.168/16 + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + if host[0:2] >= b'\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12 + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + return False if private else hostStandardFormat + else: + if host[0] == '\x7F': # 127/8 + if not private: + logger.debug( + 'Ignoring IP address in loopback range: %s', + hostStandardFormat) + return hostStandardFormat if private else False + if host[0] == '\x0A': # 10/8 + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + if host[0:2] == '\xC0\xA8': # 192.168/16 + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12 + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + return False if private else hostStandardFormat def checkIPv6Address(host, hostStandardFormat, private=False): diff --git a/src/tests/test_protocol.py b/src/tests/test_protocol.py index e5cb3b3a12..d6a8da0213 100644 --- a/src/tests/test_protocol.py +++ b/src/tests/test_protocol.py @@ -14,9 +14,9 @@ def test_check_local(self): # import pdb; pdb.set_trace() self.assertTrue( - protocol.checkIPAddress(protocol.encodeHost('127.0.0.1').decode('ISO-8859-1'), True)) + protocol.checkIPAddress(protocol.encodeHost('127.0.0.1'), True)) self.assertTrue( - protocol.checkIPAddress(protocol.encodeHost('192.168.0.1').decode('ISO-8859-1'), True)) + protocol.checkIPAddress(protocol.encodeHost('192.168.0.1'), True)) self.assertTrue( not protocol.checkSocksIP('127.0.0.1') From baf5f621dd64a4a4f256fcae075188df1a8a9ad5 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Wed, 21 Jul 2021 17:37:19 +0530 Subject: [PATCH 03/12] few changes in bmconfigparser import --- src/bmconfigparser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index 8c7abae60c..7e82ae89cc 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -14,8 +14,8 @@ import state from singleton import Singleton except ImportError: - from . import state - from .singleton import Singleton + from pybitmessage import state + from pybitmessage.singleton import Singleton SafeConfigParser = configparser.SafeConfigParser From 9a860f32dc08ec90b2947ad4a5b78f2750480438 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Wed, 21 Jul 2021 17:43:47 +0530 Subject: [PATCH 04/12] modified imports --- src/helper_random.py | 2 +- src/highlevelcrypto.py | 8 ++++---- src/protocol.py | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/helper_random.py b/src/helper_random.py index 2e6a151bba..2ef4f78ccc 100644 --- a/src/helper_random.py +++ b/src/helper_random.py @@ -6,7 +6,7 @@ try: from pyelliptic.openssl import OpenSSL except ImportError: - from .pyelliptic.openssl import OpenSSL + from pybitmessage.pyelliptic.openssl import OpenSSL NoneType = type(None) diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py index 995c5d00e0..ebfeff7ca1 100644 --- a/src/highlevelcrypto.py +++ b/src/highlevelcrypto.py @@ -15,10 +15,10 @@ from pyelliptic import OpenSSL from pyelliptic import arithmetic as a except ImportError: - from . import pyelliptic - from .bmconfigparser import BMConfigParser - from .pyelliptic import OpenSSL - from .pyelliptic import arithmetic as a + from pybitmessage import pyelliptic + from pybitmessage.bmconfigparser import BMConfigParser + from pybitmessage.pyelliptic import OpenSSL + from pybitmessage.pyelliptic import arithmetic as a def makeCryptor(privkey): diff --git a/src/protocol.py b/src/protocol.py index eb106e24cc..f3db21342c 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -25,16 +25,16 @@ from helper_sql import sqlExecute from version import softwareVersion except ImportError: - from . import defaults - from . import highlevelcrypto - from . import state - from .addresses import ( + from pybitmessage import defaults + from pybitmessage import highlevelcrypto + from pybitmessage import state + from pybitmessage.addresses import ( encodeVarint, decodeVarint, decodeAddress, varintDecodeError) - from .bmconfigparser import BMConfigParser - from .debug import logger - from .fallback import RIPEMD160Hash - from .helper_sql import sqlExecute - from .version import softwareVersion + from pybitmessage.bmconfigparser import BMConfigParser + from pybitmessage.debug import logger + from pybitmessage.fallback import RIPEMD160Hash + from pybitmessage.helper_sql import sqlExecute + from pybitmessage.version import softwareVersion PY3 = sys.version_info[0] >= 3 From 9b0d12deac0cb865e8f91e0d8bd216babb9af572 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Wed, 21 Jul 2021 18:01:24 +0530 Subject: [PATCH 05/12] fixed R0912 / too-many-branches --- src/protocol.py | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index f3db21342c..9fcae39853 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -160,12 +160,12 @@ def network_group(host): return network_type -def checkIPAddress(host, private=False): - """ - Returns hostStandardFormat if it is a valid IP address, - otherwise returns False - """ - if not isinstance(host, str): +if PY3: + def checkIPAddress(host, private=False): + """ + Returns hostStandardFormat if it is a valid IP address, + otherwise returns False + """ if host[0:12] == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) return checkIPv4Address(host[12:], hostStandardFormat, private) @@ -185,7 +185,13 @@ def checkIPAddress(host, private=False): # not 64-bit compatible so let us drop the IPv6 address. return False return checkIPv6Address(host, hostStandardFormat, private) - else: + +else: + def checkIPAddress(host, private=False): + """ + Returns hostStandardFormat if it is a valid IP address, + otherwise returns False + """ if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) return checkIPv4Address(host[12:], hostStandardFormat, private) @@ -207,12 +213,12 @@ def checkIPAddress(host, private=False): return checkIPv6Address(host, hostStandardFormat, private) -def checkIPv4Address(host, hostStandardFormat, private=False): - """ - Returns hostStandardFormat if it is an IPv4 address, - otherwise returns False - """ - if not isinstance(host, str): +if PY3: + def checkIPv4Address(host, hostStandardFormat, private=False): + """ + Returns hostStandardFormat if it is an IPv4 address, + otherwise returns False + """ if host[0] == 127: # 127/8 if not private: logger.debug( @@ -235,7 +241,13 @@ def checkIPv4Address(host, hostStandardFormat, private=False): 'Ignoring IP address in private range: %s', hostStandardFormat) return hostStandardFormat if private else False return False if private else hostStandardFormat - else: + +else: + def checkIPv4Address(host, hostStandardFormat, private=False): + """ + Returns hostStandardFormat if it is an IPv4 address, + otherwise returns False + """ if host[0] == '\x7F': # 127/8 if not private: logger.debug( From f2b3645cc20951da375b04f7a148e01c163c2128 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Fri, 23 Jul 2021 19:36:59 +0530 Subject: [PATCH 06/12] cleaned code --- src/tests/test_protocol.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/test_protocol.py b/src/tests/test_protocol.py index d6a8da0213..84d87a0f0f 100644 --- a/src/tests/test_protocol.py +++ b/src/tests/test_protocol.py @@ -11,7 +11,6 @@ class TestProtocol(unittest.TestCase): def test_check_local(self): """Check the logic of TCPConnection.local""" from pybitmessage import protocol, state - # import pdb; pdb.set_trace() self.assertTrue( protocol.checkIPAddress(protocol.encodeHost('127.0.0.1'), True)) From 3c074b9b75fec14222b2e7d527e312cc5584b97d Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Mon, 26 Jul 2021 19:45:26 +0530 Subject: [PATCH 07/12] added tearDown() for cleanup application files --- src/tests/common.py | 5 ++++- src/tests/test_protocol.py | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/tests/common.py b/src/tests/common.py index 2d60c7168b..4c2168b0d4 100644 --- a/src/tests/common.py +++ b/src/tests/common.py @@ -13,7 +13,10 @@ def cleanup(home=None, files=_files): """Cleanup application files""" if not home: - import state + try: + import state + except ImportError: + from pybitmessage import state home = state.appdata for pfile in files: try: diff --git a/src/tests/test_protocol.py b/src/tests/test_protocol.py index 84d87a0f0f..4ec4a1e723 100644 --- a/src/tests/test_protocol.py +++ b/src/tests/test_protocol.py @@ -3,11 +3,18 @@ """ import unittest +try: + from .common import cleanup +except ImportError: + from common import cleanup class TestProtocol(unittest.TestCase): """Main protocol test case""" + def tearDown(self): + cleanup() + def test_check_local(self): """Check the logic of TCPConnection.local""" from pybitmessage import protocol, state From 28d172bec7760afc8e4305bb82102e79d8925b72 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Tue, 27 Jul 2021 17:01:39 +0530 Subject: [PATCH 08/12] few changes --- src/protocol.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index 9fcae39853..d3acc1b245 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -104,23 +104,30 @@ def isBitSetWithinBitfield(fourByteString, n): x, = unpack('>L', fourByteString) return x & 2**n != 0 - # ip addresses -def encodeHost(host): - """Encode a given host to be used in low-level socket operations""" - if host.find('.onion') > -1: - return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( - host.split(".")[0], True) - elif host.find(':') == -1: - if PY3: +if PY3: + def encodeHost(host): + """Encode a given host to be used in low-level socket operations""" + if host.find('.onion') > -1: + return b'\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( + host.split(".")[0], True) + elif host.find(':') == -1: return b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ socket.inet_aton(host) - else: + return socket.inet_pton(socket.AF_INET6, host) + +else: + def encodeHost(host): + """Encode a given host to be used in low-level socket operations""" + if host.find('.onion') > -1: + return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( + host.split(".")[0], True) + elif host.find(':') == -1: return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ socket.inet_aton(host) - return socket.inet_pton(socket.AF_INET6, host) + return socket.inet_pton(socket.AF_INET6, host) def networkType(host): From 4a5645d9aab07b9a9c361bce854d39fdf4c8e90b Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Wed, 28 Jul 2021 17:14:04 +0530 Subject: [PATCH 09/12] fixed imports --- src/helper_random.py | 2 +- src/highlevelcrypto.py | 8 ++++---- src/protocol.py | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/helper_random.py b/src/helper_random.py index 2ef4f78ccc..2e6a151bba 100644 --- a/src/helper_random.py +++ b/src/helper_random.py @@ -6,7 +6,7 @@ try: from pyelliptic.openssl import OpenSSL except ImportError: - from pybitmessage.pyelliptic.openssl import OpenSSL + from .pyelliptic.openssl import OpenSSL NoneType = type(None) diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py index ebfeff7ca1..995c5d00e0 100644 --- a/src/highlevelcrypto.py +++ b/src/highlevelcrypto.py @@ -15,10 +15,10 @@ from pyelliptic import OpenSSL from pyelliptic import arithmetic as a except ImportError: - from pybitmessage import pyelliptic - from pybitmessage.bmconfigparser import BMConfigParser - from pybitmessage.pyelliptic import OpenSSL - from pybitmessage.pyelliptic import arithmetic as a + from . import pyelliptic + from .bmconfigparser import BMConfigParser + from .pyelliptic import OpenSSL + from .pyelliptic import arithmetic as a def makeCryptor(privkey): diff --git a/src/protocol.py b/src/protocol.py index d3acc1b245..c28fccfc73 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -25,16 +25,16 @@ from helper_sql import sqlExecute from version import softwareVersion except ImportError: - from pybitmessage import defaults - from pybitmessage import highlevelcrypto - from pybitmessage import state - from pybitmessage.addresses import ( + from . import defaults + from . import highlevelcrypto + from . import state + from .addresses import ( encodeVarint, decodeVarint, decodeAddress, varintDecodeError) - from pybitmessage.bmconfigparser import BMConfigParser - from pybitmessage.debug import logger - from pybitmessage.fallback import RIPEMD160Hash - from pybitmessage.helper_sql import sqlExecute - from pybitmessage.version import softwareVersion + from .bmconfigparser import BMConfigParser + from .debug import logger + from .fallback import RIPEMD160Hash + from .helper_sql import sqlExecute + from .version import softwareVersion PY3 = sys.version_info[0] >= 3 From 078c183ae94c4696dde6f9d60793ef920aa536ce Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Wed, 28 Jul 2021 18:32:27 +0530 Subject: [PATCH 10/12] formatted, refactored & cleaned code --- src/protocol.py | 222 +++++++++++++++++++----------------------------- 1 file changed, 89 insertions(+), 133 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index c28fccfc73..1cdf99489e 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -9,6 +9,7 @@ import random import socket import sys +import six import time from binascii import hexlify from struct import Struct, pack, unpack @@ -36,8 +37,6 @@ from .helper_sql import sqlExecute from .version import softwareVersion -PY3 = sys.version_info[0] >= 3 - # Service flags #: This is a normal network node NODE_NETWORK = 1 @@ -107,27 +106,21 @@ def isBitSetWithinBitfield(fourByteString, n): # ip addresses -if PY3: - def encodeHost(host): - """Encode a given host to be used in low-level socket operations""" - if host.find('.onion') > -1: - return b'\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( - host.split(".")[0], True) - elif host.find(':') == -1: - return b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ - socket.inet_aton(host) - return socket.inet_pton(socket.AF_INET6, host) - -else: - def encodeHost(host): - """Encode a given host to be used in low-level socket operations""" - if host.find('.onion') > -1: - return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( - host.split(".")[0], True) - elif host.find(':') == -1: - return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ - socket.inet_aton(host) - return socket.inet_pton(socket.AF_INET6, host) +def encodeHost(host): + """Encode a given host to be used in low-level socket operations""" + if six.PY2: + ONION_PREFIX = '\xfd\x87\xd8\x7e\xeb\x43' + IP_PREFIX = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + else: + ONION_PREFIX = b'\xfd\x87\xd8\x7e\xeb\x43' + IP_PREFIX = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + + if host.find('.onion') > -1: + return ONION_PREFIX + base64.b32decode( + host.split(".")[0], True) + elif host.find(':') == -1: + return IP_PREFIX + socket.inet_aton(host) + return socket.inet_pton(socket.AF_INET6, host) def networkType(host): @@ -167,116 +160,79 @@ def network_group(host): return network_type -if PY3: - def checkIPAddress(host, private=False): - """ - Returns hostStandardFormat if it is a valid IP address, - otherwise returns False - """ - if host[0:12] == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': - hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) - return checkIPv4Address(host[12:], hostStandardFormat, private) - elif host[0:6] == b'\xfd\x87\xd8\x7e\xeb\x43': - # Onion, based on BMD/bitcoind - hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" - if private: - return False - return hostStandardFormat - else: - try: - hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) - except ValueError: - return False - if hostStandardFormat == "": - # This can happen on Windows systems which are - # not 64-bit compatible so let us drop the IPv6 address. - return False - return checkIPv6Address(host, hostStandardFormat, private) - -else: - def checkIPAddress(host, private=False): - """ - Returns hostStandardFormat if it is a valid IP address, - otherwise returns False - """ - if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': - hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) - return checkIPv4Address(host[12:], hostStandardFormat, private) - elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43': - # Onion, based on BMD/bitcoind - hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" - if private: - return False - return hostStandardFormat - else: - try: - hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) - except ValueError: - return False - if hostStandardFormat == "": - # This can happen on Windows systems which are - # not 64-bit compatible so let us drop the IPv6 address. - return False - return checkIPv6Address(host, hostStandardFormat, private) - - -if PY3: - def checkIPv4Address(host, hostStandardFormat, private=False): - """ - Returns hostStandardFormat if it is an IPv4 address, - otherwise returns False - """ - if host[0] == 127: # 127/8 - if not private: - logger.debug( - 'Ignoring IP address in loopback range: %s', - hostStandardFormat) - return hostStandardFormat if private else False - if host[0] == 10: # 10/8 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - if host[0:2] == b'\xC0\xA8': # 192.168/16 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - if host[0:2] >= b'\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - return False if private else hostStandardFormat - -else: - def checkIPv4Address(host, hostStandardFormat, private=False): - """ - Returns hostStandardFormat if it is an IPv4 address, - otherwise returns False - """ - if host[0] == '\x7F': # 127/8 - if not private: - logger.debug( - 'Ignoring IP address in loopback range: %s', - hostStandardFormat) - return hostStandardFormat if private else False - if host[0] == '\x0A': # 10/8 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - if host[0:2] == '\xC0\xA8': # 192.168/16 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12 - if not private: - logger.debug( - 'Ignoring IP address in private range: %s', hostStandardFormat) - return hostStandardFormat if private else False - return False if private else hostStandardFormat +def checkIPAddress(host, private=False): + """ + Returns hostStandardFormat if it is a valid IP address, + otherwise returns False + """ + if six.PY3: + IP_PREFIX1 = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + IP_PREFIX2 = b'\xfd\x87\xd8\x7e\xeb\x43' + else: + IP_PREFIX1 = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + IP_PREFIX2 = '\xfd\x87\xd8\x7e\xeb\x43' + + if host[0:12] == IP_PREFIX1: + hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) + return checkIPv4Address(host[12:], hostStandardFormat, private) + elif host[0:6] == IP_PREFIX2: + # Onion, based on BMD/bitcoind + hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" + if private: + return False + return hostStandardFormat + else: + try: + hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) + except ValueError: + return False + if hostStandardFormat == "": + # This can happen on Windows systems which are + # not 64-bit compatible so let us drop the IPv6 address. + return False + return checkIPv6Address(host, hostStandardFormat, private) + + +def checkIPv4Address(host, hostStandardFormat, private=False): + """ + Returns hostStandardFormat if it is an IPv4 address, + otherwise returns False + """ + if six.PY2: + IP_OCT1 = '\x7F' # 127/8 + IP_OCT2 = '\x0A' # 10/8 + IP_OCT3 = '\xC0\xA8' # 192.168/16 + IP_OCT4 = '\xAC\x10' # 172.16 + IP_OCT5 = '\xAC\x20' # 12 + else: + IP_OCT1 = 127 # 127/8 + IP_OCT2 = 10 # 10/8 + IP_OCT3 = b'\xC0\xA8' # 192.168/16 + IP_OCT4 = b'\xAC\x10' # 172.16 + IP_OCT5 = b'\xAC\x20' # 12 + + if host[0] == IP_OCT1: + if not private: + logger.debug( + 'Ignoring IP address in loopback range: %s', + hostStandardFormat) + return hostStandardFormat if private else False + if host[0] == IP_OCT2: + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + if host[0:2] == IP_OCT3: + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + if host[0:2] >= IP_OCT4 and host[0:2] < IP_OCT5: + if not private: + logger.debug( + 'Ignoring IP address in private range: %s', hostStandardFormat) + return hostStandardFormat if private else False + return False if private else hostStandardFormat def checkIPv6Address(host, hostStandardFormat, private=False): From 975775852d5bb47900928545a95c470b787736b8 Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Wed, 28 Jul 2021 18:40:35 +0530 Subject: [PATCH 11/12] fixed code quality --- src/protocol.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index 1cdf99489e..27cd785488 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -3,6 +3,7 @@ """ # pylint: disable=too-many-boolean-expressions,too-many-return-statements # pylint: disable=too-many-locals,too-many-statements +# pylint: disable=R0204 import base64 import hashlib @@ -199,18 +200,18 @@ def checkIPv4Address(host, hostStandardFormat, private=False): otherwise returns False """ if six.PY2: - IP_OCT1 = '\x7F' # 127/8 - IP_OCT2 = '\x0A' # 10/8 - IP_OCT3 = '\xC0\xA8' # 192.168/16 - IP_OCT4 = '\xAC\x10' # 172.16 - IP_OCT5 = '\xAC\x20' # 12 + IP_OCT1 = '\x7F' # 127/8 + IP_OCT2 = '\x0A' # 10/8 + IP_OCT3 = '\xC0\xA8' # 192.168/16 + IP_OCT4 = '\xAC\x10' # 172.16 + IP_OCT5 = '\xAC\x20' # 12 else: - IP_OCT1 = 127 # 127/8 - IP_OCT2 = 10 # 10/8 - IP_OCT3 = b'\xC0\xA8' # 192.168/16 - IP_OCT4 = b'\xAC\x10' # 172.16 - IP_OCT5 = b'\xAC\x20' # 12 - + IP_OCT1 = 127 # 127/8 + IP_OCT2 = 10 # 10/8 + IP_OCT3 = b'\xC0\xA8' # 192.168/16 + IP_OCT4 = b'\xAC\x10' # 172.16 + IP_OCT5 = b'\xAC\x20' # 12 + if host[0] == IP_OCT1: if not private: logger.debug( From 38cdb6a9d381d4b7871b66632b97c733dc22605a Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Thu, 29 Jul 2021 17:49:00 +0530 Subject: [PATCH 12/12] merged glitch's changes --- src/protocol.py | 113 +++++++++++++------------------------ src/tests/test_protocol.py | 85 +++++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 82 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index 27cd785488..2de51221b1 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -3,40 +3,26 @@ """ # pylint: disable=too-many-boolean-expressions,too-many-return-statements # pylint: disable=too-many-locals,too-many-statements -# pylint: disable=R0204 import base64 import hashlib import random import socket import sys -import six import time from binascii import hexlify from struct import Struct, pack, unpack -try: - import defaults - import highlevelcrypto - import state - from addresses import ( - encodeVarint, decodeVarint, decodeAddress, varintDecodeError) - from bmconfigparser import BMConfigParser - from debug import logger - from fallback import RIPEMD160Hash - from helper_sql import sqlExecute - from version import softwareVersion -except ImportError: - from . import defaults - from . import highlevelcrypto - from . import state - from .addresses import ( - encodeVarint, decodeVarint, decodeAddress, varintDecodeError) - from .bmconfigparser import BMConfigParser - from .debug import logger - from .fallback import RIPEMD160Hash - from .helper_sql import sqlExecute - from .version import softwareVersion +import defaults +import highlevelcrypto +import state +from addresses import ( + encodeVarint, decodeVarint, decodeAddress, varintDecodeError) +from bmconfigparser import BMConfigParser +from debug import logger +from fallback import RIPEMD160Hash +from helper_sql import sqlExecute +from version import softwareVersion # Service flags #: This is a normal network node @@ -104,23 +90,18 @@ def isBitSetWithinBitfield(fourByteString, n): x, = unpack('>L', fourByteString) return x & 2**n != 0 -# ip addresses + +# IP addresses def encodeHost(host): """Encode a given host to be used in low-level socket operations""" - if six.PY2: - ONION_PREFIX = '\xfd\x87\xd8\x7e\xeb\x43' - IP_PREFIX = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' - else: - ONION_PREFIX = b'\xfd\x87\xd8\x7e\xeb\x43' - IP_PREFIX = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' - if host.find('.onion') > -1: - return ONION_PREFIX + base64.b32decode( + return b'\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode( host.split(".")[0], True) elif host.find(':') == -1: - return IP_PREFIX + socket.inet_aton(host) + return b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \ + socket.inet_aton(host) return socket.inet_pton(socket.AF_INET6, host) @@ -166,17 +147,10 @@ def checkIPAddress(host, private=False): Returns hostStandardFormat if it is a valid IP address, otherwise returns False """ - if six.PY3: - IP_PREFIX1 = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' - IP_PREFIX2 = b'\xfd\x87\xd8\x7e\xeb\x43' - else: - IP_PREFIX1 = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' - IP_PREFIX2 = '\xfd\x87\xd8\x7e\xeb\x43' - - if host[0:12] == IP_PREFIX1: + if host[0:12] == b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF': hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:]) return checkIPv4Address(host[12:], hostStandardFormat, private) - elif host[0:6] == IP_PREFIX2: + elif host[0:6] == b'\xfd\x87\xd8\x7e\xeb\x43': # Onion, based on BMD/bitcoind hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion" if private: @@ -187,7 +161,7 @@ def checkIPAddress(host, private=False): hostStandardFormat = socket.inet_ntop(socket.AF_INET6, host) except ValueError: return False - if hostStandardFormat == "": + if len(hostStandardFormat) == 0: # This can happen on Windows systems which are # not 64-bit compatible so let us drop the IPv6 address. return False @@ -199,36 +173,23 @@ def checkIPv4Address(host, hostStandardFormat, private=False): Returns hostStandardFormat if it is an IPv4 address, otherwise returns False """ - if six.PY2: - IP_OCT1 = '\x7F' # 127/8 - IP_OCT2 = '\x0A' # 10/8 - IP_OCT3 = '\xC0\xA8' # 192.168/16 - IP_OCT4 = '\xAC\x10' # 172.16 - IP_OCT5 = '\xAC\x20' # 12 - else: - IP_OCT1 = 127 # 127/8 - IP_OCT2 = 10 # 10/8 - IP_OCT3 = b'\xC0\xA8' # 192.168/16 - IP_OCT4 = b'\xAC\x10' # 172.16 - IP_OCT5 = b'\xAC\x20' # 12 - - if host[0] == IP_OCT1: + if host[0:1] == b'\x7F': # 127/8 if not private: logger.debug( 'Ignoring IP address in loopback range: %s', hostStandardFormat) return hostStandardFormat if private else False - if host[0] == IP_OCT2: + if host[0:1] == b'\x0A': # 10/8 if not private: logger.debug( 'Ignoring IP address in private range: %s', hostStandardFormat) return hostStandardFormat if private else False - if host[0:2] == IP_OCT3: + if host[0:2] == b'\xC0\xA8': # 192.168/16 if not private: logger.debug( 'Ignoring IP address in private range: %s', hostStandardFormat) return hostStandardFormat if private else False - if host[0:2] >= IP_OCT4 and host[0:2] < IP_OCT5: + if host[0:2] >= b'\xAC\x10' and host[0:2] < b'\xAC\x20': # 172.16/12 if not private: logger.debug( 'Ignoring IP address in private range: %s', hostStandardFormat) @@ -241,15 +202,19 @@ def checkIPv6Address(host, hostStandardFormat, private=False): Returns hostStandardFormat if it is an IPv6 address, otherwise returns False """ - if host == ('\x00' * 15) + '\x01': + if host == b'\x00' * 15 + b'\x01': if not private: logger.debug('Ignoring loopback address: %s', hostStandardFormat) return False - if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80: + try: + host = [ord(c) for c in host[:2]] + except TypeError: # python3 has ints already + pass + if host[0:1] == b'\xFE' and host[1] & 0xc0 == 0x80: if not private: logger.debug('Ignoring local address: %s', hostStandardFormat) return hostStandardFormat if private else False - if (ord(str(host[0])) & 0xfe) == 0xfc: + if host[0] & 0xfe == 0xfc: if not private: logger.debug( 'Ignoring unique local address: %s', hostStandardFormat) @@ -319,7 +284,7 @@ def isProofOfWorkSufficient( # Packet creation -def CreatePacket(command, payload=''): +def CreatePacket(command, payload=b''): """Construct and return a packet""" payload_length = len(payload) checksum = hashlib.sha512(payload).digest()[0:4] @@ -337,14 +302,14 @@ def assembleVersionMessage( Construct the payload of a version message, return the resulting bytes of running `CreatePacket` on it """ - payload = '' + payload = b'' payload += pack('>L', 3) # protocol version. # bitflags of the services I offer. payload += pack( '>q', - NODE_NETWORK | - (NODE_SSL if haveSSL(server) else 0) | - (NODE_DANDELION if state.dandelion else 0) + NODE_NETWORK + | (NODE_SSL if haveSSL(server) else 0) + | (NODE_DANDELION if state.dandelion else 0) ) payload += pack('>q', int(time.time())) @@ -366,13 +331,13 @@ def assembleVersionMessage( # bitflags of the services I offer. payload += pack( '>q', - NODE_NETWORK | - (NODE_SSL if haveSSL(server) else 0) | - (NODE_DANDELION if state.dandelion else 0) + NODE_NETWORK + | (NODE_SSL if haveSSL(server) else 0) + | (NODE_DANDELION if state.dandelion else 0) ) # = 127.0.0.1. This will be ignored by the remote host. # The actual remote connected IP will be used. - payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack( + payload += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack( '>L', 2130706433) # we have a separate extPort and incoming over clearnet # or outgoing through clearnet @@ -394,7 +359,7 @@ def assembleVersionMessage( payload += nodeid[0:8] else: payload += eightBytesOfRandomDataUsedToDetectConnectionsToSelf - userAgent = '/PyBitmessage:' + softwareVersion + '/' + userAgent = ('/PyBitmessage:%s/' % softwareVersion).encode('utf-8') payload += encodeVarint(len(userAgent)) payload += userAgent diff --git a/src/tests/test_protocol.py b/src/tests/test_protocol.py index 4ec4a1e723..521c90c731 100644 --- a/src/tests/test_protocol.py +++ b/src/tests/test_protocol.py @@ -2,28 +2,97 @@ Tests for common protocol functions """ +import sys import unittest -try: - from .common import cleanup -except ImportError: - from common import cleanup + +from pybitmessage import protocol, state class TestProtocol(unittest.TestCase): """Main protocol test case""" - def tearDown(self): - cleanup() + def test_checkIPv4Address(self): + """Check the results of protocol.checkIPv4Address()""" + token = 'HELLO' + # checking protocol.encodeHost()[12:] + self.assertEqual( # 127.0.0.1 + token, protocol.checkIPv4Address(b'\x7f\x00\x00\x01', token, True)) + self.assertEqual( # 10.42.43.1 + token, protocol.checkIPv4Address(b'\n*+\x01', token, True)) + self.assertEqual( # 192.168.0.254 + token, protocol.checkIPv4Address(b'\xc0\xa8\x00\xfe', token, True)) + self.assertEqual( # 172.31.255.254 + token, protocol.checkIPv4Address(b'\xac\x1f\xff\xfe', token, True)) + self.assertFalse( # 8.8.8.8 + protocol.checkIPv4Address(b'\x08\x08\x08\x08', token, True)) + + def test_checkIPv6Address(self): + """Check the results of protocol.checkIPv6Address()""" + test_ip = '2001:db8::ff00:42:8329' + self.assertEqual( + 'test', protocol.checkIPv6Address( + protocol.encodeHost(test_ip), 'test')) + self.assertFalse( + protocol.checkIPv6Address( + protocol.encodeHost(test_ip), 'test', True)) def test_check_local(self): """Check the logic of TCPConnection.local""" - from pybitmessage import protocol, state - self.assertTrue( protocol.checkIPAddress(protocol.encodeHost('127.0.0.1'), True)) self.assertTrue( protocol.checkIPAddress(protocol.encodeHost('192.168.0.1'), True)) + self.assertTrue( + protocol.checkIPAddress(protocol.encodeHost('10.42.43.1'), True)) + self.assertTrue( + protocol.checkIPAddress(protocol.encodeHost('172.31.255.2'), True)) + self.assertFalse(protocol.checkIPAddress( + protocol.encodeHost('2001:db8::ff00:42:8329'), True)) + + globalhost = protocol.encodeHost('8.8.8.8') + self.assertFalse(protocol.checkIPAddress(globalhost, True)) + self.assertEqual(protocol.checkIPAddress(globalhost), '8.8.8.8') + @unittest.skipIf( + sys.hexversion >= 0x3000000, 'this is still not working with python3') + def test_check_local_socks(self): + """The SOCKS part of the local check""" self.assertTrue( not protocol.checkSocksIP('127.0.0.1') or state.socksIP) + + def test_network_group(self): + """Test various types of network groups""" + + test_ip = '1.2.3.4' + self.assertEqual(b'\x01\x02', protocol.network_group(test_ip)) + + test_ip = '127.0.0.1' + self.assertEqual('IPv4', protocol.network_group(test_ip)) + + self.assertEqual( + protocol.network_group('8.8.8.8'), + protocol.network_group('8.8.4.4')) + self.assertNotEqual( + protocol.network_group('1.1.1.1'), + protocol.network_group('8.8.8.8')) + + test_ip = '0102:0304:0506:0708:090A:0B0C:0D0E:0F10' + self.assertEqual( + b'\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C', + protocol.network_group(test_ip)) + + test_ip = 'bootstrap8444.bitmessage.org' + self.assertEqual( + 'bootstrap8444.bitmessage.org', + protocol.network_group(test_ip)) + + test_ip = 'quzwelsuziwqgpt2.onion' + self.assertEqual( + test_ip, + protocol.network_group(test_ip)) + + test_ip = None + self.assertEqual( + None, + protocol.network_group(test_ip))