Browse Source

Fix peer replacement logic

- drop the IP address peer
- update the remaining peer with fresh info
master
Neil Booth 8 years ago
parent
commit
9f27ea875c
  1. 18
      lib/peer.py
  2. 15
      server/peers.py

18
lib/peer.py

@ -94,12 +94,14 @@ class Peer(object):
return tuple(int(part) for part in vstr.split('.')) return tuple(int(part) for part in vstr.split('.'))
def matches(self, peers): def matches(self, peers):
'''Return peers whose host matches the given peer's host or IP '''Return peers whose host matches our hostname or IP address.
address. This results in our favouring host names over IP Additionally include all peers whose IP address matches our
addresses. hostname if that is an IP address.
''' '''
candidates = (self.host.lower(), self.ip_addr) candidates = (self.host.lower(), self.ip_addr)
return [peer for peer in peers if peer.host.lower() in candidates] return [peer for peer in peers
if peer.host.lower() in candidates
or peer.ip_addr == self.host]
def __str__(self): def __str__(self):
return self.host return self.host
@ -111,9 +113,13 @@ class Peer(object):
except Exception: except Exception:
pass pass
else: else:
self.features = tmp.features self.update_features_from_peer(tmp)
def update_features_from_peer(self, peer):
if peer != self:
self.features = peer.features
for feature in self.FEATURES: for feature in self.FEATURES:
setattr(self, feature, getattr(tmp, feature)) setattr(self, feature, getattr(peer, feature))
def connection_port_pairs(self): def connection_port_pairs(self):
'''Return a list of (kind, port) pairs to try when making a '''Return a list of (kind, port) pairs to try when making a

15
server/peers.py

@ -555,15 +555,20 @@ class PeerManager(util.LoggedClass):
how = 'via {} at {}'.format(kind, peer.ip_addr) how = 'via {} at {}'.format(kind, peer.ip_addr)
status = 'verified' if good else 'failed to verify' status = 'verified' if good else 'failed to verify'
elapsed = time.time() - peer.last_try elapsed = time.time() - peer.last_try
self.log_info('{} {} in {:.1f}s'.format(status, how, elapsed)) self.log_info('{} {} {} in {:.1f}s'.format(status, peer, how, elapsed))
if good: if good:
peer.try_count = 0 peer.try_count = 0
peer.source = 'peer' peer.source = 'peer'
# Remove matching IP addresses # At most 2 matches if we're a host name, potentially several if
for match in peer.matches(self.peers): # we're an IP address (several instances can share a NAT).
if match != peer and peer.host == peer.ip_addr: matches = peer.matches(self.peers)
self.peers.remove(match) for match in matches:
if match.ip_address:
if len(matches) > 1:
self.peers.remove(match)
elif peer.host in match.features['hosts']:
match.update_features_from_peer(peer)
else: else:
self.maybe_forget_peer(peer) self.maybe_forget_peer(peer)

Loading…
Cancel
Save