2019-08-16 20:03:11 +00:00
|
|
|
package p2p
|
|
|
|
|
|
|
|
import (
|
2019-08-29 16:32:52 +00:00
|
|
|
"context"
|
2019-12-01 01:37:42 +00:00
|
|
|
"fmt"
|
2019-09-03 01:10:58 +00:00
|
|
|
"io"
|
2019-12-08 05:12:56 +00:00
|
|
|
"time"
|
2019-08-16 20:03:11 +00:00
|
|
|
|
2019-08-29 16:32:52 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/network"
|
2019-08-16 20:03:11 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
2019-10-22 00:43:44 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/sync/peerstatus"
|
2019-12-08 05:12:56 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2019-08-16 20:03:11 +00:00
|
|
|
)
|
|
|
|
|
2019-08-29 16:32:52 +00:00
|
|
|
// AddConnectionHandler adds a callback function which handles the connection with a
|
|
|
|
// newly added peer. It performs a handshake with that peer by sending a hello request
|
|
|
|
// and validating the response from the peer.
|
2019-09-01 22:29:58 +00:00
|
|
|
func (s *Service) AddConnectionHandler(reqFunc func(ctx context.Context, id peer.ID) error) {
|
|
|
|
s.host.Network().Notify(&network.NotifyBundle{
|
2019-08-29 16:32:52 +00:00
|
|
|
ConnectedF: func(net network.Network, conn network.Conn) {
|
2019-12-08 05:12:56 +00:00
|
|
|
if peerCount(s.host) > int(s.cfg.MaxPeers) {
|
|
|
|
if err := s.Disconnect(conn.RemotePeer()); err != nil {
|
|
|
|
log.WithError(err).Errorf("Unable to close peer %s", conn.RemotePeer())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2019-12-01 01:37:42 +00:00
|
|
|
multiAddr := fmt.Sprintf("%s/p2p/%s", conn.RemoteMultiaddr().String(), conn.RemotePeer().String())
|
2019-12-08 05:12:56 +00:00
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"direction": conn.Stat().Direction,
|
|
|
|
"multiAddr": multiAddr,
|
|
|
|
"peerCount": peerCount(s.host),
|
|
|
|
}).Debug("Connection")
|
2019-10-30 05:32:53 +00:00
|
|
|
if peerstatus.IsBadPeer(conn.RemotePeer()) {
|
|
|
|
// Add Peer to gossipsub blacklist
|
|
|
|
s.pubsub.BlacklistPeer(conn.RemotePeer())
|
|
|
|
log.WithField("peerID", conn.RemotePeer().Pretty()).Trace("Disconnecting with bad peer")
|
|
|
|
if err := s.Disconnect(conn.RemotePeer()); err != nil {
|
|
|
|
log.WithError(err).Errorf("Unable to close peer %s", conn.RemotePeer())
|
2019-10-22 00:43:44 +00:00
|
|
|
return
|
|
|
|
}
|
2019-10-30 05:32:53 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-12-08 05:12:56 +00:00
|
|
|
// ConnectedF must be non-blocking as part of libp2p design.
|
2019-10-30 05:32:53 +00:00
|
|
|
go func() {
|
2019-12-08 05:12:56 +00:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
log := log.WithField("peer", conn.RemotePeer().Pretty())
|
|
|
|
log.Debug("Performing handshake with peer")
|
|
|
|
if err := reqFunc(ctx, conn.RemotePeer()); err != nil && err != io.EOF {
|
|
|
|
log.WithError(err).Debug("Could not send successful hello rpc request")
|
|
|
|
if err.Error() == "protocol not supported" {
|
|
|
|
// This is only to ensure the smooth running of our testnets. This will not be
|
|
|
|
// used in production.
|
|
|
|
log.Debug("Not disconnecting peer with unsupported protocol. This may be the DHT node or relay.")
|
|
|
|
s.host.ConnManager().Protect(conn.RemotePeer(), "relay/bootnode")
|
2019-10-07 23:59:08 +00:00
|
|
|
return
|
|
|
|
}
|
2019-12-08 05:12:56 +00:00
|
|
|
if err := s.Disconnect(conn.RemotePeer()); err != nil {
|
|
|
|
log.WithError(err).Errorf("Unable to close peer %s", conn.RemotePeer())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return
|
2019-08-29 16:32:52 +00:00
|
|
|
}
|
2019-10-01 20:05:17 +00:00
|
|
|
log.WithField("peer", conn.RemotePeer().Pretty()).Info("New peer connected")
|
2019-08-29 16:32:52 +00:00
|
|
|
}()
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
2019-09-01 22:29:58 +00:00
|
|
|
|
2019-09-18 20:02:34 +00:00
|
|
|
// AddDisconnectionHandler ensures that previously disconnected peers aren't dialed again. Due
|
|
|
|
// to either their ports being closed, nodes are no longer active,etc. This also calls the handler
|
|
|
|
// responsible for maintaining other parts of the sync or p2p system.
|
|
|
|
func (s *Service) AddDisconnectionHandler(handler func(ctx context.Context, id peer.ID) error) {
|
2019-09-01 22:29:58 +00:00
|
|
|
s.host.Network().Notify(&network.NotifyBundle{
|
|
|
|
DisconnectedF: func(net network.Network, conn network.Conn) {
|
|
|
|
// Must be handled in a goroutine as this callback cannot be blocking.
|
|
|
|
go func() {
|
2019-12-06 20:06:37 +00:00
|
|
|
s.exclusionList.Set(conn.RemotePeer().String(), true, 1)
|
2019-09-18 20:02:34 +00:00
|
|
|
log := log.WithField("peer", conn.RemotePeer())
|
|
|
|
log.Debug("Peer is added to exclusion list")
|
|
|
|
ctx := context.Background()
|
|
|
|
if err := handler(ctx, conn.RemotePeer()); err != nil {
|
|
|
|
log.WithError(err).Error("Failed to handle disconnecting peer")
|
|
|
|
}
|
2019-09-01 22:29:58 +00:00
|
|
|
}()
|
2019-09-18 20:02:34 +00:00
|
|
|
|
2019-09-01 22:29:58 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|