kaspad/protocol/receiveversion/receiveversion.go
Ori Newman 9939671ccc
[NOD-1147] Implement address exchange (#795)
* [NOD-1147] Implement address exchange

* [NOD-1147] Put placeholder for source address

* [NOD-1147] Fix tests

* [NOD-1147] Add comment

* [NOD-1147] Remove needAddresses from MsgGetAddr

* [NOD-1147] Use rand.Shuffle

* [NOD-1147] Remove redundant const

* [NOD-1147] Move defer to its correct place

* [NOD-1147] Fix typo

* [NOD-1147] Use EnqueueWithTimeout for outgoingRoute

* [NOD-1147] Rename MsgGetAddr->MsgGetAddresses

* [NOD-1147] Rename MsgGetAddr->MsgGetAddresses

* [NOD-1147] Rename MsgAddr->MsgAddresses

* [NOD-1147] Rename fakeSrcAddr->fakeSourceAddress

* [NOD-1147] Remove redundant files

* [NOD-1147] CmdAddr -> CmdAddress

* [NOD-1147] Rename addr to address in protocol package
2020-07-15 17:19:46 +03:00

89 lines
3.1 KiB
Go

package receiveversion
import (
"github.com/kaspanet/kaspad/blockdag"
"github.com/kaspanet/kaspad/netadapter"
"github.com/kaspanet/kaspad/netadapter/router"
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
"github.com/kaspanet/kaspad/protocol/protocolerrors"
"github.com/kaspanet/kaspad/wire"
"time"
)
var (
// allowSelfConnections is only used to allow the tests to bypass the self
// connection detecting and disconnect logic since they intentionally
// do so for testing purposes.
allowSelfConnections bool
// minAcceptableProtocolVersion is the lowest protocol version that a
// connected peer may support.
minAcceptableProtocolVersion = wire.ProtocolVersion
)
const timeout = 30 * time.Second
// ReceiveVersion waits for the peer to send a version message, sends a
// verack in response, and updates its info accordingly.
func ReceiveVersion(incomingRoute *router.Route, outgoingRoute *router.Route, netAdapter *netadapter.NetAdapter,
peer *peerpkg.Peer, dag *blockdag.BlockDAG) (address *wire.NetAddress, routeClosed bool, err error) {
message, isOpen, err := incomingRoute.DequeueWithTimeout(timeout)
if err != nil {
return nil, false, err
}
if !isOpen {
return nil, true, nil
}
msgVersion, ok := message.(*wire.MsgVersion)
if !ok {
return nil, false, protocolerrors.New(true, "a version message must precede all others")
}
if !allowSelfConnections && netAdapter.ID().IsEqual(msgVersion.ID) {
return nil, false, protocolerrors.New(true, "connected to self")
}
// Notify and disconnect clients that have a protocol version that is
// too old.
//
// NOTE: If minAcceptableProtocolVersion is raised to be higher than
// wire.RejectVersion, this should send a reject packet before
// disconnecting.
if msgVersion.ProtocolVersion < minAcceptableProtocolVersion {
//TODO(libp2p) create error type for disconnect but don't ban
return nil, false, protocolerrors.Errorf(false, "protocol version must be %d or greater",
minAcceptableProtocolVersion)
}
// Disconnect from partial nodes in networks that don't allow them
if !dag.Params.EnableNonNativeSubnetworks && msgVersion.SubnetworkID != nil {
return nil, false, protocolerrors.New(true, "partial nodes are not allowed")
}
// TODO(libp2p)
//// Disconnect if:
//// - we are a full node and the outbound connection we've initiated is a partial node
//// - the remote node is partial and our subnetwork doesn't match their subnetwork
//localSubnetworkID := config.ActiveConfig().SubnetworkID
//isLocalNodeFull := localSubnetworkID == nil
//isRemoteNodeFull := msgVersion.SubnetworkID == nil
//if (isLocalNodeFull && !isRemoteNodeFull && !connection.IsInbound()) ||
// (!isLocalNodeFull && !isRemoteNodeFull && !msgVersion.SubnetworkID.IsEqual(localSubnetworkID)) {
//
// return nil, false, errors.New("incompatible subnetworks")
//}
peer.UpdateFieldsFromMsgVersion(msgVersion)
isOpen, err = outgoingRoute.EnqueueWithTimeout(wire.NewMsgVerAck(), timeout)
if err != nil {
return nil, false, err
}
if !isOpen {
return nil, true, nil
}
// TODO(libp2p) Register peer ID
return msgVersion.Address, false, nil
}