From 7f1096ae530b464677481b91e358dd0a774f3bcd Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Fri, 23 Nov 2018 19:06:16 +0000 Subject: [PATCH] Peer discovery: loop address families too Works around a Python bug https://bugs.python.org/issue35302 --- electrumx/lib/peer.py | 20 +++++++++++++++----- electrumx/server/peers.py | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/electrumx/lib/peer.py b/electrumx/lib/peer.py index e35481e..4427e30 100644 --- a/electrumx/lib/peer.py +++ b/electrumx/lib/peer.py @@ -25,7 +25,8 @@ '''Representation of a peer server.''' -from ipaddress import ip_address +from ipaddress import ip_address, IPv4Address, IPv6Address +from socket import AF_INET, AF_INET6 from electrumx.lib.util import cachedproperty import electrumx.lib.util as util @@ -112,15 +113,24 @@ class Peer(object): for feature in self.FEATURES: setattr(self, feature, getattr(peer, feature)) - def connection_port_pairs(self): - '''Return a list of (kind, port) pairs to try when making a - connection.''' + def connection_tuples(self): + '''Return a list of (kind, port, family) tuples to try when making a + connection. + ''' # Use a list not a set - it's important to try the registered # ports first. pairs = [('SSL', self.ssl_port), ('TCP', self.tcp_port)] while self.other_port_pairs: pairs.append(self.other_port_pairs.pop()) - return [pair for pair in pairs if pair[1]] + if isinstance(self.ip_address, IPv4Address): + families = [AF_INET] + elif isinstance(self.ip_address, IPv6Address): + families = [AF_INET6] + else: + families = [AF_INET, AF_INET6] + return [(kind, port, family) + for kind, port in pairs if port + for family in families] def mark_bad(self): '''Mark as bad to avoid reconnects but also to remember for a diff --git a/electrumx/server/peers.py b/electrumx/server/peers.py index 1fde73a..8e040b4 100644 --- a/electrumx/server/peers.py +++ b/electrumx/server/peers.py @@ -202,10 +202,10 @@ class PeerManager(object): async def _should_drop_peer(self, peer): peer.try_count += 1 is_good = False - for kind, port in peer.connection_port_pairs(): + for kind, port, family in peer.connection_tuples(): peer.last_try = time.time() - kwargs = {} + kwargs = {'family': family} if kind == 'SSL': kwargs['ssl'] = ssl.SSLContext(ssl.PROTOCOL_TLS)