|
@@ -20,6 +20,7 @@ import (
|
|
|
"errors"
|
|
"errors"
|
|
|
"math/big"
|
|
"math/big"
|
|
|
"sync"
|
|
"sync"
|
|
|
|
|
+ "time"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
|
@@ -38,19 +39,28 @@ var (
|
|
|
// to the peer set, but one with the same id already exists.
|
|
// to the peer set, but one with the same id already exists.
|
|
|
errPeerAlreadyRegistered = errors.New("peer already registered")
|
|
errPeerAlreadyRegistered = errors.New("peer already registered")
|
|
|
|
|
|
|
|
|
|
+ // errPeerWaitTimeout is returned if a peer waits extension for too long
|
|
|
|
|
+ errPeerWaitTimeout = errors.New("peer wait timeout")
|
|
|
|
|
+
|
|
|
// errPeerNotRegistered is returned if a peer is attempted to be removed from
|
|
// errPeerNotRegistered is returned if a peer is attempted to be removed from
|
|
|
// a peer set, but no peer with the given id exists.
|
|
// a peer set, but no peer with the given id exists.
|
|
|
errPeerNotRegistered = errors.New("peer not registered")
|
|
errPeerNotRegistered = errors.New("peer not registered")
|
|
|
|
|
|
|
|
// errSnapWithoutEth is returned if a peer attempts to connect only on the
|
|
// errSnapWithoutEth is returned if a peer attempts to connect only on the
|
|
|
- // snap protocol without advertizing the eth main protocol.
|
|
|
|
|
|
|
+ // snap protocol without advertising the eth main protocol.
|
|
|
errSnapWithoutEth = errors.New("peer connected on snap without compatible eth support")
|
|
errSnapWithoutEth = errors.New("peer connected on snap without compatible eth support")
|
|
|
|
|
|
|
|
// errDiffWithoutEth is returned if a peer attempts to connect only on the
|
|
// errDiffWithoutEth is returned if a peer attempts to connect only on the
|
|
|
- // diff protocol without advertizing the eth main protocol.
|
|
|
|
|
|
|
+ // diff protocol without advertising the eth main protocol.
|
|
|
errDiffWithoutEth = errors.New("peer connected on diff without compatible eth support")
|
|
errDiffWithoutEth = errors.New("peer connected on diff without compatible eth support")
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+const (
|
|
|
|
|
+ // extensionWaitTimeout is the maximum allowed time for the extension wait to
|
|
|
|
|
+ // complete before dropping the connection as malicious.
|
|
|
|
|
+ extensionWaitTimeout = 10 * time.Second
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
// peerSet represents the collection of active peers currently participating in
|
|
// peerSet represents the collection of active peers currently participating in
|
|
|
// the `eth` protocol, with or without the `snap` extension.
|
|
// the `eth` protocol, with or without the `snap` extension.
|
|
|
type peerSet struct {
|
|
type peerSet struct {
|
|
@@ -169,7 +179,16 @@ func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
|
|
|
ps.snapWait[id] = wait
|
|
ps.snapWait[id] = wait
|
|
|
ps.lock.Unlock()
|
|
ps.lock.Unlock()
|
|
|
|
|
|
|
|
- return <-wait, nil
|
|
|
|
|
|
|
+ select {
|
|
|
|
|
+ case peer := <-wait:
|
|
|
|
|
+ return peer, nil
|
|
|
|
|
+
|
|
|
|
|
+ case <-time.After(extensionWaitTimeout):
|
|
|
|
|
+ ps.lock.Lock()
|
|
|
|
|
+ delete(ps.snapWait, id)
|
|
|
|
|
+ ps.lock.Unlock()
|
|
|
|
|
+ return nil, errPeerWaitTimeout
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// waitDiffExtension blocks until all satellite protocols are connected and tracked
|
|
// waitDiffExtension blocks until all satellite protocols are connected and tracked
|
|
@@ -203,7 +222,16 @@ func (ps *peerSet) waitDiffExtension(peer *eth.Peer) (*diff.Peer, error) {
|
|
|
ps.diffWait[id] = wait
|
|
ps.diffWait[id] = wait
|
|
|
ps.lock.Unlock()
|
|
ps.lock.Unlock()
|
|
|
|
|
|
|
|
- return <-wait, nil
|
|
|
|
|
|
|
+ select {
|
|
|
|
|
+ case peer := <-wait:
|
|
|
|
|
+ return peer, nil
|
|
|
|
|
+
|
|
|
|
|
+ case <-time.After(extensionWaitTimeout):
|
|
|
|
|
+ ps.lock.Lock()
|
|
|
|
|
+ delete(ps.diffWait, id)
|
|
|
|
|
+ ps.lock.Unlock()
|
|
|
|
|
+ return nil, errPeerWaitTimeout
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (ps *peerSet) GetDiffPeer(pid string) downloader.IDiffPeer {
|
|
func (ps *peerSet) GetDiffPeer(pid string) downloader.IDiffPeer {
|