Commit c85e55ad authored by Petar Radovic's avatar Petar Radovic Committed by GitHub

Clean addressbook after failed connection attempts (#309)

* Forget about non connectable peers in kademlia
parent 3c0c02e2
...@@ -19,6 +19,7 @@ var _ Interface = (*store)(nil) ...@@ -19,6 +19,7 @@ var _ Interface = (*store)(nil)
type Interface interface { type Interface interface {
GetPutter GetPutter
Remover
Overlays() ([]swarm.Address, error) Overlays() ([]swarm.Address, error)
Addresses() ([]bzz.Address, error) Addresses() ([]bzz.Address, error)
} }
...@@ -36,6 +37,10 @@ type Putter interface { ...@@ -36,6 +37,10 @@ type Putter interface {
Put(overlay swarm.Address, addr bzz.Address) (err error) Put(overlay swarm.Address, addr bzz.Address) (err error)
} }
type Remover interface {
Remove(overlay swarm.Address) error
}
type store struct { type store struct {
store storage.StateStorer store storage.StateStorer
} }
...@@ -61,6 +66,10 @@ func (s *store) Put(overlay swarm.Address, addr bzz.Address) (err error) { ...@@ -61,6 +66,10 @@ func (s *store) Put(overlay swarm.Address, addr bzz.Address) (err error) {
return s.store.Put(key, &addr) return s.store.Put(key, &addr)
} }
func (s *store) Remove(overlay swarm.Address) error {
return s.store.Delete(keyPrefix + overlay.String())
}
func (s *store) Overlays() (overlays []swarm.Address, err error) { func (s *store) Overlays() (overlays []swarm.Address, err error) {
err = s.store.Iterate(keyPrefix, func(key, _ []byte) (stop bool, err error) { err = s.store.Iterate(keyPrefix, func(key, _ []byte) (stop bool, err error) {
k := string(key) k := string(key)
......
...@@ -23,8 +23,9 @@ import ( ...@@ -23,8 +23,9 @@ import (
) )
const ( const (
maxBins = 16 maxBins = 16
nnLowWatermark = 2 // the number of peers in consecutive deepest bins that constitute as nearest neighbours nnLowWatermark = 2 // the number of peers in consecutive deepest bins that constitute as nearest neighbours
maxConnAttempts = 3 // when there is maxConnAttempts failed connect calls for a given peer it is considered non-connectable
) )
var ( var (
...@@ -56,13 +57,18 @@ type Kad struct { ...@@ -56,13 +57,18 @@ type Kad struct {
depth uint8 // current neighborhood depth depth uint8 // current neighborhood depth
depthMu sync.RWMutex // protect depth changes depthMu sync.RWMutex // protect depth changes
manageC chan struct{} // trigger the manage forever loop to connect to new peers manageC chan struct{} // trigger the manage forever loop to connect to new peers
waitNext map[string]time.Time // sanction connections to a peer, key is overlay string and value is time to next retry waitNext map[string]retryInfo // sanction connections to a peer, key is overlay string and value is a retry information
waitNextMu sync.Mutex // synchronize map waitNextMu sync.Mutex // synchronize map
logger logging.Logger // logger logger logging.Logger // logger
quit chan struct{} // quit channel quit chan struct{} // quit channel
done chan struct{} // signal that `manage` has quit done chan struct{} // signal that `manage` has quit
} }
type retryInfo struct {
tryAfter time.Time
failedAttempts int
}
// New returns a new Kademlia. // New returns a new Kademlia.
func New(o Options) *Kad { func New(o Options) *Kad {
if o.SaturationFunc == nil { if o.SaturationFunc == nil {
...@@ -78,7 +84,7 @@ func New(o Options) *Kad { ...@@ -78,7 +84,7 @@ func New(o Options) *Kad {
connectedPeers: pslice.New(maxBins), connectedPeers: pslice.New(maxBins),
knownPeers: pslice.New(maxBins), knownPeers: pslice.New(maxBins),
manageC: make(chan struct{}, 1), manageC: make(chan struct{}, 1),
waitNext: make(map[string]time.Time), waitNext: make(map[string]retryInfo),
logger: o.Logger, logger: o.Logger,
quit: make(chan struct{}), quit: make(chan struct{}),
done: make(chan struct{}), done: make(chan struct{}),
...@@ -115,7 +121,7 @@ func (k *Kad) manage() { ...@@ -115,7 +121,7 @@ func (k *Kad) manage() {
} }
k.waitNextMu.Lock() k.waitNextMu.Lock()
if next, ok := k.waitNext[peer.String()]; ok && time.Now().Before(next) { if next, ok := k.waitNext[peer.String()]; ok && time.Now().Before(next.tryAfter) {
k.waitNextMu.Unlock() k.waitNextMu.Unlock()
return false, false, nil return false, false, nil
} }
...@@ -248,12 +254,33 @@ func (k *Kad) connect(ctx context.Context, peer swarm.Address, ma ma.Multiaddr, ...@@ -248,12 +254,33 @@ func (k *Kad) connect(ctx context.Context, peer swarm.Address, ma ma.Multiaddr,
if errors.Is(err, p2p.ErrAlreadyConnected) { if errors.Is(err, p2p.ErrAlreadyConnected) {
return nil return nil
} }
k.logger.Debugf("error connecting to peer %s: %v", peer, err) k.logger.Debugf("error connecting to peer %s: %v", peer, err)
retryTime := time.Now().Add(timeToRetry)
var e *p2p.ConnectionBackoffError
k.waitNextMu.Lock() k.waitNextMu.Lock()
k.waitNext[peer.String()] = time.Now().Add(timeToRetry) failedAttempts := 0
k.waitNextMu.Unlock() if errors.As(err, &e) {
retryTime = e.TryAfter()
} else {
info, ok := k.waitNext[peer.String()]
if ok {
failedAttempts = info.failedAttempts
}
// TODO: somehow keep track of attempts and at some point forget about the peer failedAttempts++
}
if failedAttempts > maxConnAttempts {
delete(k.waitNext, peer.String())
if err := k.addressBook.Remove(peer); err != nil {
k.logger.Debugf("could not remove peer from addressbook: %s", peer.String())
}
} else {
k.waitNext[peer.String()] = retryInfo{tryAfter: retryTime, failedAttempts: failedAttempts}
}
k.waitNextMu.Unlock()
return err return err
} }
...@@ -335,7 +362,7 @@ func (k *Kad) Disconnected(addr swarm.Address) { ...@@ -335,7 +362,7 @@ func (k *Kad) Disconnected(addr swarm.Address) {
k.connectedPeers.Remove(addr, po) k.connectedPeers.Remove(addr, po)
k.waitNextMu.Lock() k.waitNextMu.Lock()
k.waitNext[addr.String()] = time.Now().Add(timeToRetry) k.waitNext[addr.String()] = retryInfo{tryAfter: time.Now().Add(timeToRetry), failedAttempts: 0}
k.waitNextMu.Unlock() k.waitNextMu.Unlock()
k.depthMu.Lock() k.depthMu.Lock()
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment