From 4825c5a136450656932f8157677d221c55953d2e Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Sat, 20 Jul 2019 11:41:49 +0300 Subject: [PATCH] Universal bootstrap procedure for any connection type --- src/network/connectionpool.py | 29 ++++++++++++++++++++++++++--- src/network/tcp.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/network/connectionpool.py b/src/network/connectionpool.py index 05358c28..1554a585 100644 --- a/src/network/connectionpool.py +++ b/src/network/connectionpool.py @@ -18,7 +18,8 @@ from debug import logger from proxy import Proxy from singleton import Singleton from tcp import ( - TCPServer, Socks5BMConnection, Socks4aBMConnection, TCPConnection) + bootstrap, Socks4aBMConnection, Socks5BMConnection, + TCPConnection, TCPServer) from udp import UDPSocket @@ -159,7 +160,28 @@ class BMConnectionPool(object): udpSocket = UDPSocket(host=bind, announcing=True) self.udpSockets[udpSocket.listening.host] = udpSocket - def loop(self): # pylint: disable=too-many-branches, too-many-statements + def startBootstrappers(self): + """Run the process of resolving bootstrap hostnames""" + proxy_type = BMConfigParser().safeGet( + 'bitmessagesettings', 'socksproxytype') + # A plugins may be added here + if not proxy_type or proxy_type == 'none': + connection_base = TCPConnection + elif proxy_type == 'SOCKS5': + connection_base = Socks5BMConnection + elif proxy_type == 'SOCKS4a': + connection_base = Socks4aBMConnection # FIXME: I cannot test + else: + # This should never happen because socksproxytype setting + # is handled in bitmessagemain before starting the connectionpool + return + + bootstrapper = bootstrap(connection_base) + port = helper_random.randomchoice([8080, 8444]) + hostname = 'bootstrap%s.bitmessage.org' % port + self.addConnection(bootstrapper(hostname, port)) + + def loop(self): # pylint: disable=too-many-branches,too-many-statements """Main Connectionpool's loop""" # defaults to empty loop if outbound connections are maxed spawnConnections = False @@ -184,7 +206,8 @@ class BMConnectionPool(object): # pylint: disable=too-many-nested-blocks if spawnConnections: if not knownnodes.knownNodesActual: - knownnodes.dns() + self.startBootstrappers() + knownnodes.knownNodesActual = True if not self.bootstrapped: self.bootstrapped = True Proxy.proxy = ( diff --git a/src/network/tcp.py b/src/network/tcp.py index 9b92cb52..da02df2f 100644 --- a/src/network/tcp.py +++ b/src/network/tcp.py @@ -325,6 +325,39 @@ class Socks4aBMConnection(Socks4aConnection, TCPConnection): return True +def bootstrap(connection_class): + """Make bootstrapper class for connection type (connection_class)""" + class Bootstrapper(connection_class): + """Base class for bootstrappers""" + _connection_base = connection_class + + def __init__(self, host, port): + self._connection_base.__init__(self, state.Peer(host, port)) + self.close_reason = self._succeed = False + + def bm_command_addr(self): + """ + Got addr message - the bootstrap succeed. + Let BMProto process the addr message and switch state to 'close' + """ + BMProto.bm_command_addr(self) + self._succeed = True + # pylint: disable=attribute-defined-outside-init + self.close_reason = "Thanks for bootstrapping!" + self.set_state("close") + + def handle_close(self): + """ + After closing the connection switch knownnodes.knownNodesActual + back to False if the bootstrapper failed. + """ + self._connection_base.handle_close(self) + if not self._succeed: + knownnodes.knownNodesActual = False + + return Bootstrapper + + class TCPServer(AdvancedDispatcher): """TCP connection server for Bitmessage protocol"""