fix: make processing signed address records atomic

Previously, two calls to ConsumePeerRecord could interleave and cause us to keep
_old_ addresses with a _new_ record.
This commit is contained in:
Steven Allen 2020-06-05 18:04:22 -07:00
parent 56ebb42d5f
commit 095da5537d

View File

@ -159,7 +159,7 @@ func (mab *memoryAddrBook) AddAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Du
// if peerRec != nil { // if peerRec != nil {
// return // return
// } // }
mab.addAddrs(p, addrs, ttl, false) mab.addAddrs(p, addrs, ttl)
} }
// ConsumePeerRecord adds addresses from a signed peer.PeerRecord (contained in // ConsumePeerRecord adds addresses from a signed peer.PeerRecord (contained in
@ -181,35 +181,38 @@ func (mab *memoryAddrBook) ConsumePeerRecord(recordEnvelope *record.Envelope, tt
// ensure seq is greater than, or equal to, the last received // ensure seq is greater than, or equal to, the last received
s := mab.segments.get(rec.PeerID) s := mab.segments.get(rec.PeerID)
s.Lock() s.Lock()
defer s.Unlock()
lastState, found := s.signedPeerRecords[rec.PeerID] lastState, found := s.signedPeerRecords[rec.PeerID]
if found && lastState.Seq > rec.Seq { if found && lastState.Seq > rec.Seq {
s.Unlock()
return false, nil return false, nil
} }
s.signedPeerRecords[rec.PeerID] = &peerRecordState{ s.signedPeerRecords[rec.PeerID] = &peerRecordState{
Envelope: recordEnvelope, Envelope: recordEnvelope,
Seq: rec.Seq, Seq: rec.Seq,
} }
s.Unlock() // need to release the lock, since addAddrs will try to take it mab.addAddrsUnlocked(s, rec.PeerID, rec.Addrs, ttl, true)
mab.addAddrs(rec.PeerID, rec.Addrs, ttl, true)
return true, nil return true, nil
} }
func (mab *memoryAddrBook) addAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, signed bool) { func (mab *memoryAddrBook) addAddrs(p peer.ID, addrs []ma.Multiaddr, ttl time.Duration) {
if err := p.Validate(); err != nil { if err := p.Validate(); err != nil {
log.Warningf("tried to set addrs for invalid peer ID %s: %s", p, err) log.Warningf("tried to set addrs for invalid peer ID %s: %s", p, err)
return return
} }
// if ttl is zero, exit. nothing to do.
if ttl <= 0 {
return
}
s := mab.segments.get(p) s := mab.segments.get(p)
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
mab.addAddrsUnlocked(s, p, addrs, ttl, false)
}
func (mab *memoryAddrBook) addAddrsUnlocked(s *addrSegment, p peer.ID, addrs []ma.Multiaddr, ttl time.Duration, signed bool) {
// if ttl is zero, exit. nothing to do.
if ttl <= 0 {
return
}
amap, ok := s.addrs[p] amap, ok := s.addrs[p]
if !ok { if !ok {
amap = make(map[string]*expiringAddr) amap = make(map[string]*expiringAddr)