From 0b07b1c89a31ae3fcf6b26512498a30b89a5be62 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Wed, 9 Aug 2017 17:34:47 +0200 Subject: [PATCH] Peer discovery updates - allow loopback addresses, now you can bind different loopback IP addresses on a single system and they will auto-cross-connect - always listen for discovery on 0.0.0.0 - [network] - bind now also applies for the TCP socket as well as UDP socket - closing socket iterator fix --- src/bmconfigparser.py | 2 +- src/network/announcethread.py | 2 ++ src/network/connectionchooser.py | 7 ++++++- src/network/connectionpool.py | 16 ++++++++++------ src/network/udp.py | 3 ++- src/protocol.py | 4 +++- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index 094cd73d..b8bf790f 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -20,7 +20,7 @@ BMConfigDefaults = { }, "network": { "asyncore": True, - "bind": None, + "bind": '', }, "inventory": { "storage": "sqlite", diff --git a/src/network/announcethread.py b/src/network/announcethread.py index 26d9f9cf..a94eeb36 100644 --- a/src/network/announcethread.py +++ b/src/network/announcethread.py @@ -28,6 +28,8 @@ class AnnounceThread(threading.Thread, StoppableThread): def announceSelf(self): for connection in BMConnectionPool().udpSockets.values(): + if not connection.announcing: + continue for stream in state.streamsInWhichIAmParticipating: addr = (stream, state.Peer('127.0.0.1', BMConfigParser().safeGetInt("bitmessagesettings", "port")), time.time()) connection.append_write_buf(BMProto.assembleAddr([addr])) diff --git a/src/network/connectionchooser.py b/src/network/connectionchooser.py index 616a80f6..681291ad 100644 --- a/src/network/connectionchooser.py +++ b/src/network/connectionchooser.py @@ -8,9 +8,14 @@ import state def getDiscoveredPeer(stream): try: - return random.choice(state.discoveredPeers.keys()) + peer = random.choice(state.discoveredPeers.keys()) except (IndexError, KeyError): raise ValueError + try: + del state.discoveredPeers[peer] + except KeyError: + pass + return peer def chooseConnection(stream): haveOnion = BMConfigParser().safeGet("bitmessagesettings", "socksproxytype")[0:5] == 'SOCKS' diff --git a/src/network/connectionpool.py b/src/network/connectionpool.py index 96c6a6b6..3adc1772 100644 --- a/src/network/connectionpool.py +++ b/src/network/connectionpool.py @@ -113,7 +113,7 @@ class BMConnectionPool(object): BMConfigParser().get("bitmessagesettings", "socksproxytype") == "none": # python doesn't like bind + INADDR_ANY? #host = socket.INADDR_ANY - host = '' + host = BMConfigParser().get("network", "bind") return host def startListening(self): @@ -126,9 +126,12 @@ class BMConnectionPool(object): def startUDPSocket(self, bind=None): if bind is None: host = self.getListeningIP() - udpSocket = network.udp.UDPSocket(host=host) + udpSocket = network.udp.UDPSocket(host=host, announcing=True) else: - udpSocket = network.udp.UDPSocket(host=bind) + if bind is False: + udpSocket = network.udp.UDPSocket(announcing=False) + else: + udpSocket = network.udp.UDPSocket(host=bind, announcing=True) self.udpSockets[udpSocket.listening.host] = udpSocket def loop(self): @@ -192,19 +195,20 @@ class BMConnectionPool(object): self.startListening() logger.info('Listening for incoming connections.') if not self.udpSockets: - if BMConfigParser().safeGet("network", "bind") is None: + if BMConfigParser().safeGet("network", "bind") == '': self.startUDPSocket() else: for bind in re.sub("[^\w.]+", " ", BMConfigParser().safeGet("network", "bind")).split(): self.startUDPSocket(bind) + self.startUDPSocket(False) logger.info('Starting UDP socket(s).') else: if self.listeningSockets: - for i in self.listeningSockets: + for i in self.listeningSockets.values(): i.handle_close() logger.info('Stopped listening for incoming connections.') if self.udpSockets: - for i in self.udpSockets: + for i in self.udpSockets.values(): i.handle_close() logger.info('Stopped udp sockets.') diff --git a/src/network/udp.py b/src/network/udp.py index 8448da16..27cf0abb 100644 --- a/src/network/udp.py +++ b/src/network/udp.py @@ -17,7 +17,7 @@ class UDPSocket(BMProto): port = 8444 announceInterval = 60 - def __init__(self, host=None, sock=None): + def __init__(self, host=None, sock=None, announcing=False): super(BMProto, self).__init__(sock=sock) self.verackReceived = True self.verackSent = True @@ -49,6 +49,7 @@ class UDPSocket(BMProto): ObjectTracker.__init__(self) self.connecting = False self.connected = True + self.announcing = announcing self.set_state("bm_header", expectBytes=protocol.Header.size) def set_socket_reuse(self): diff --git a/src/protocol.py b/src/protocol.py index c2a58de8..7ad0db17 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -37,6 +37,8 @@ OBJECT_GETPUBKEY = 0 OBJECT_PUBKEY = 1 OBJECT_MSG = 2 OBJECT_BROADCAST = 3 +OBJECT_I2P = 0x493250 +OBJECT_ADDR = 0x61646472 eightBytesOfRandomDataUsedToDetectConnectionsToSelf = pack( '>Q', random.randrange(1, 18446744073709551615)) @@ -108,7 +110,7 @@ def checkIPv4Address(host, hostStandardFormat, private=False): if host[0] == '\x7F': # 127/8 if not private: logger.debug('Ignoring IP address in loopback range: ' + hostStandardFormat) - return False + return hostStandardFormat if private else False if host[0] == '\x0A': # 10/8 if not private: logger.debug('Ignoring IP address in private range: ' + hostStandardFormat)