2020-03-10 12:20:34 -07:00
|
|
|
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
|
|
|
|
package networking
|
|
|
|
|
|
|
|
// #include "salticidae/network.h"
|
2020-04-18 18:02:40 -07:00
|
|
|
// bool connHandler(msgnetwork_conn_t *, bool, void *);
|
2020-03-10 12:20:34 -07:00
|
|
|
// void unknownPeerHandler(netaddr_t *, x509_t *, void *);
|
|
|
|
// void peerHandler(peernetwork_conn_t *, bool, void *);
|
|
|
|
// void ping(msg_t *, msgnetwork_conn_t *, void *);
|
|
|
|
// void pong(msg_t *, msgnetwork_conn_t *, void *);
|
|
|
|
// void getVersion(msg_t *, msgnetwork_conn_t *, void *);
|
|
|
|
// void version(msg_t *, msgnetwork_conn_t *, void *);
|
|
|
|
// void getPeerList(msg_t *, msgnetwork_conn_t *, void *);
|
|
|
|
// void peerList(msg_t *, msgnetwork_conn_t *, void *);
|
|
|
|
import "C"
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"math"
|
2020-04-24 11:44:04 -07:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2020-03-10 12:20:34 -07:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
|
|
|
|
"github.com/ava-labs/salticidae-go"
|
|
|
|
|
|
|
|
"github.com/ava-labs/gecko/ids"
|
|
|
|
"github.com/ava-labs/gecko/snow/networking"
|
|
|
|
"github.com/ava-labs/gecko/snow/validators"
|
|
|
|
"github.com/ava-labs/gecko/utils"
|
|
|
|
"github.com/ava-labs/gecko/utils/hashing"
|
|
|
|
"github.com/ava-labs/gecko/utils/logging"
|
|
|
|
"github.com/ava-labs/gecko/utils/random"
|
|
|
|
"github.com/ava-labs/gecko/utils/timer"
|
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
|
|
Receive a new connection.
|
|
|
|
- Send version message.
|
|
|
|
Receive version message.
|
|
|
|
- Validate data
|
|
|
|
- Send peer list
|
|
|
|
- Mark this node as being connected
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Periodically gossip peerlists.
|
|
|
|
- Only connected stakers should be gossiped.
|
|
|
|
- Gossip to a caped number of peers.
|
|
|
|
- The peers to gossip to should be at least half full of stakers (or all the
|
|
|
|
stakers should be in the set).
|
|
|
|
*/
|
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
/*
|
|
|
|
Attempt reconnections
|
|
|
|
- If a non-staker disconnects, delete the connection
|
|
|
|
- If a staker disconnects, attempt to reconnect to the node for awhile. If the
|
|
|
|
node isn't connected to after awhile delete the connection.
|
|
|
|
*/
|
|
|
|
|
2020-04-24 11:44:04 -07:00
|
|
|
// Version this avalanche instance is executing.
|
|
|
|
var (
|
|
|
|
VersionPrefix = "avalanche/"
|
|
|
|
VersionSeparator = "."
|
|
|
|
MajorVersion = 0
|
2020-04-28 13:30:48 -07:00
|
|
|
MinorVersion = 2
|
2020-04-30 20:46:37 -07:00
|
|
|
PatchVersion = 1
|
2020-04-24 11:44:04 -07:00
|
|
|
ClientVersion = fmt.Sprintf("%s%d%s%d%s%d",
|
|
|
|
VersionPrefix,
|
|
|
|
MajorVersion,
|
|
|
|
VersionSeparator,
|
|
|
|
MinorVersion,
|
|
|
|
VersionSeparator,
|
|
|
|
PatchVersion)
|
|
|
|
)
|
|
|
|
|
2020-03-10 12:20:34 -07:00
|
|
|
const (
|
|
|
|
// MaxClockDifference allowed between connected nodes.
|
|
|
|
MaxClockDifference = time.Minute
|
|
|
|
// PeerListGossipSpacing is the amount of time to wait between pushing this
|
|
|
|
// node's peer list to other nodes.
|
|
|
|
PeerListGossipSpacing = time.Minute
|
|
|
|
// PeerListGossipSize is the number of peers to gossip each period.
|
|
|
|
PeerListGossipSize = 100
|
|
|
|
// PeerListStakerGossipFraction calculates the fraction of stakers that are
|
|
|
|
// gossiped to. If set to 1, then only stakers will be gossiped to.
|
|
|
|
PeerListStakerGossipFraction = 2
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
// ConnectTimeout is the amount of time to wait before attempt to connect to
|
|
|
|
// an unknown peer
|
2020-04-21 11:32:00 -07:00
|
|
|
ConnectTimeout = 6 * time.Second
|
2020-03-10 12:20:34 -07:00
|
|
|
// GetVersionTimeout is the amount of time to wait before sending a
|
|
|
|
// getVersion message to a partially connected peer
|
|
|
|
GetVersionTimeout = 2 * time.Second
|
2020-04-03 16:14:13 -07:00
|
|
|
// ReconnectTimeout is the amount of time to wait to reconnect to a staker
|
|
|
|
// before giving up
|
2020-04-15 14:49:08 -07:00
|
|
|
ReconnectTimeout = 10 * time.Minute
|
2020-03-10 12:20:34 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// Manager is the struct that will be accessed on event calls
|
|
|
|
var (
|
|
|
|
HandshakeNet = Handshake{}
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
errDSValidators = errors.New("couldn't get validator set of default subnet")
|
|
|
|
)
|
|
|
|
|
|
|
|
// Handshake handles the authentication of new peers. Only valid stakers
|
|
|
|
// will appear connected.
|
|
|
|
type Handshake struct {
|
|
|
|
handshakeMetrics
|
|
|
|
|
2020-04-20 17:00:36 -07:00
|
|
|
networkID uint32 // ID of the network I'm running, used to prevent connecting to the wrong network
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
log logging.Logger
|
2020-04-20 17:00:36 -07:00
|
|
|
vdrs validators.Set // set of current validators in the AVAnet
|
|
|
|
myAddr salticidae.NetAddr // IP I communicate to peers
|
|
|
|
myID ids.ShortID // ID that identifies myself as a staker or not
|
|
|
|
net salticidae.PeerNetwork // C messaging network
|
|
|
|
enableStaking bool // Should only be false for local tests
|
|
|
|
|
|
|
|
clock timer.Clock
|
|
|
|
|
|
|
|
// Connections that I have added by IP, but haven't gotten an ID from
|
|
|
|
requestedLock sync.Mutex
|
|
|
|
requested map[string]struct{}
|
2020-04-20 19:33:33 -07:00
|
|
|
requestedTimeout timer.TimeoutManager // keys are hashes of the ip:port string
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
// Connections that I have added as a peer, but haven't gotten a version
|
|
|
|
// message from
|
|
|
|
pending Connections
|
2020-04-20 19:33:33 -07:00
|
|
|
versionTimeout timer.TimeoutManager // keys are the peer IDs
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
// Connections that I have gotten a valid version message from
|
|
|
|
connections Connections
|
2020-04-20 19:33:33 -07:00
|
|
|
reconnectTimeout timer.TimeoutManager // keys are the peer IDs
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
// IPs of nodes I'm connected to will be repeatedly gossiped throughout the network
|
2020-03-10 12:20:34 -07:00
|
|
|
peerListGossiper *timer.Repeater
|
|
|
|
|
2020-04-20 17:00:36 -07:00
|
|
|
// If any chain is blocked on connecting to peers, track these blockers here
|
2020-03-10 12:20:34 -07:00
|
|
|
awaitingLock sync.Mutex
|
|
|
|
awaiting []*networking.AwaitingConnections
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize to the c networking library. This should only be done once during
|
|
|
|
// node setup.
|
|
|
|
func (nm *Handshake) Initialize(
|
|
|
|
log logging.Logger,
|
|
|
|
vdrs validators.Set,
|
|
|
|
myAddr salticidae.NetAddr,
|
|
|
|
myID ids.ShortID,
|
|
|
|
peerNet salticidae.PeerNetwork,
|
|
|
|
registerer prometheus.Registerer,
|
|
|
|
enableStaking bool,
|
|
|
|
networkID uint32,
|
|
|
|
) {
|
|
|
|
log.AssertTrue(nm.net == nil, "Should only register network handlers once")
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
nm.handshakeMetrics.Initialize(log, registerer)
|
|
|
|
|
|
|
|
nm.networkID = networkID
|
|
|
|
|
2020-03-10 12:20:34 -07:00
|
|
|
nm.log = log
|
|
|
|
nm.vdrs = vdrs
|
|
|
|
nm.myAddr = myAddr
|
|
|
|
nm.myID = myID
|
|
|
|
nm.net = peerNet
|
|
|
|
nm.enableStaking = enableStaking
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
nm.requested = make(map[string]struct{})
|
|
|
|
nm.requestedTimeout.Initialize(ConnectTimeout)
|
|
|
|
go nm.log.RecoverAndPanic(nm.requestedTimeout.Dispatch)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.pending = NewConnections()
|
2020-04-20 17:00:36 -07:00
|
|
|
nm.versionTimeout.Initialize(GetVersionTimeout)
|
|
|
|
go nm.log.RecoverAndPanic(nm.versionTimeout.Dispatch)
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.connections = NewConnections()
|
2020-04-20 17:00:36 -07:00
|
|
|
nm.reconnectTimeout.Initialize(ReconnectTimeout)
|
|
|
|
go nm.log.RecoverAndPanic(nm.reconnectTimeout.Dispatch)
|
2020-04-18 17:34:19 -07:00
|
|
|
|
2020-04-20 17:00:36 -07:00
|
|
|
nm.peerListGossiper = timer.NewRepeater(nm.gossipPeerList, PeerListGossipSpacing)
|
|
|
|
go nm.log.RecoverAndPanic(nm.peerListGossiper.Dispatch)
|
2020-04-18 19:47:53 -07:00
|
|
|
|
2020-04-20 17:00:36 -07:00
|
|
|
// register c message callbacks
|
2020-03-10 12:20:34 -07:00
|
|
|
net := peerNet.AsMsgNetwork()
|
|
|
|
|
2020-04-18 18:02:40 -07:00
|
|
|
net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), nil)
|
2020-03-10 12:20:34 -07:00
|
|
|
peerNet.RegPeerHandler(salticidae.PeerNetworkPeerCallback(C.peerHandler), nil)
|
|
|
|
peerNet.RegUnknownPeerHandler(salticidae.PeerNetworkUnknownPeerCallback(C.unknownPeerHandler), nil)
|
|
|
|
net.RegHandler(Ping, salticidae.MsgNetworkMsgCallback(C.ping), nil)
|
|
|
|
net.RegHandler(Pong, salticidae.MsgNetworkMsgCallback(C.pong), nil)
|
|
|
|
net.RegHandler(GetVersion, salticidae.MsgNetworkMsgCallback(C.getVersion), nil)
|
|
|
|
net.RegHandler(Version, salticidae.MsgNetworkMsgCallback(C.version), nil)
|
|
|
|
net.RegHandler(GetPeerList, salticidae.MsgNetworkMsgCallback(C.getPeerList), nil)
|
|
|
|
net.RegHandler(PeerList, salticidae.MsgNetworkMsgCallback(C.peerList), nil)
|
2020-04-20 17:00:36 -07:00
|
|
|
}
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-20 17:25:22 -07:00
|
|
|
// ConnectTo add the peer as a connection and connects to them.
|
|
|
|
func (nm *Handshake) ConnectTo(peer salticidae.PeerID, stakerID ids.ShortID, addr salticidae.NetAddr) {
|
|
|
|
if nm.pending.ContainsPeerID(peer) || nm.connections.ContainsPeerID(peer) {
|
|
|
|
return
|
2020-04-20 17:00:36 -07:00
|
|
|
}
|
2020-04-03 16:14:13 -07:00
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.log.Info("Attempting to connect to %s", stakerID)
|
|
|
|
|
2020-04-20 17:25:22 -07:00
|
|
|
nm.net.AddPeer(peer)
|
|
|
|
nm.net.SetPeerAddr(peer, addr)
|
|
|
|
nm.net.ConnPeer(peer, 600, 1)
|
|
|
|
|
|
|
|
ip := toIPDesc(addr)
|
|
|
|
nm.pending.Add(peer, stakerID, ip)
|
|
|
|
|
|
|
|
peerBytes := toID(peer)
|
|
|
|
peerID := ids.NewID(peerBytes)
|
|
|
|
|
|
|
|
nm.reconnectTimeout.Put(peerID, func() {
|
|
|
|
nm.pending.Remove(peer, stakerID)
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.connections.Remove(peer, stakerID)
|
2020-04-20 17:25:22 -07:00
|
|
|
nm.net.DelPeer(peer)
|
2020-04-20 19:33:33 -07:00
|
|
|
|
|
|
|
nm.numPeers.Set(float64(nm.connections.Len()))
|
2020-04-20 17:25:22 -07:00
|
|
|
})
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
// Connect ...
|
|
|
|
func (nm *Handshake) Connect(addr salticidae.NetAddr) {
|
2020-04-20 17:00:36 -07:00
|
|
|
ip := toIPDesc(addr)
|
|
|
|
ipStr := ip.String()
|
|
|
|
if nm.pending.ContainsIP(ip) || nm.connections.ContainsIP(ip) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
if !nm.enableStaking {
|
2020-04-21 11:32:00 -07:00
|
|
|
nm.log.Info("Adding peer %s", ip)
|
|
|
|
|
2020-04-20 17:25:22 -07:00
|
|
|
peer := salticidae.NewPeerIDFromNetAddr(addr, true)
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.ConnectTo(peer, toShortID(ip), addr)
|
2020-04-20 17:25:22 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-21 11:32:00 -07:00
|
|
|
nm.requestedLock.Lock()
|
|
|
|
_, exists := nm.requested[ipStr]
|
|
|
|
nm.requestedLock.Unlock()
|
|
|
|
|
|
|
|
if exists {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
nm.log.Info("Adding peer %s", ip)
|
|
|
|
|
2020-04-20 17:25:22 -07:00
|
|
|
count := new(int)
|
2020-04-21 11:32:00 -07:00
|
|
|
*count = 100
|
2020-04-20 17:25:22 -07:00
|
|
|
handler := new(func())
|
|
|
|
*handler = func() {
|
|
|
|
nm.requestedLock.Lock()
|
|
|
|
defer nm.requestedLock.Unlock()
|
|
|
|
|
2020-04-21 11:32:00 -07:00
|
|
|
if *count == 100 {
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.requested[ipStr] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, exists := nm.requested[ipStr]; !exists {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-20 17:25:22 -07:00
|
|
|
if *count <= 0 {
|
|
|
|
delete(nm.requested, ipStr)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
*count--
|
|
|
|
|
|
|
|
if nm.pending.ContainsIP(ip) || nm.connections.ContainsIP(ip) {
|
|
|
|
return
|
|
|
|
}
|
2020-04-20 17:00:36 -07:00
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.log.Info("Attempting to discover peer at %s", ipStr)
|
2020-04-20 17:25:22 -07:00
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
msgNet := nm.net.AsMsgNetwork()
|
|
|
|
msgNet.Connect(addr)
|
2020-04-20 19:33:33 -07:00
|
|
|
|
|
|
|
ipID := ids.NewID(hashing.ComputeHash256Array([]byte(ipStr)))
|
|
|
|
nm.requestedTimeout.Put(ipID, *handler)
|
2020-04-18 19:47:53 -07:00
|
|
|
}
|
2020-04-20 17:25:22 -07:00
|
|
|
(*handler)()
|
2020-04-18 19:47:53 -07:00
|
|
|
}
|
|
|
|
|
2020-03-10 12:20:34 -07:00
|
|
|
// AwaitConnections ...
|
|
|
|
func (nm *Handshake) AwaitConnections(awaiting *networking.AwaitingConnections) {
|
|
|
|
nm.awaitingLock.Lock()
|
|
|
|
defer nm.awaitingLock.Unlock()
|
|
|
|
|
|
|
|
awaiting.Add(nm.myID)
|
|
|
|
for _, cert := range nm.connections.IDs().List() {
|
|
|
|
awaiting.Add(cert)
|
|
|
|
}
|
|
|
|
if awaiting.Ready() {
|
|
|
|
go awaiting.Finish()
|
|
|
|
} else {
|
|
|
|
nm.awaiting = append(nm.awaiting, awaiting)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (nm *Handshake) gossipPeerList() {
|
|
|
|
stakers := []ids.ShortID{}
|
|
|
|
nonStakers := []ids.ShortID{}
|
|
|
|
for _, id := range nm.connections.IDs().List() {
|
|
|
|
if nm.vdrs.Contains(id) {
|
|
|
|
stakers = append(stakers, id)
|
|
|
|
} else {
|
|
|
|
nonStakers = append(nonStakers, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
numStakersToSend := (PeerListGossipSize + PeerListStakerGossipFraction - 1) / PeerListStakerGossipFraction
|
|
|
|
if len(stakers) < numStakersToSend {
|
|
|
|
numStakersToSend = len(stakers)
|
|
|
|
}
|
|
|
|
numNonStakersToSend := PeerListGossipSize - numStakersToSend
|
|
|
|
if len(nonStakers) < numNonStakersToSend {
|
|
|
|
numNonStakersToSend = len(nonStakers)
|
|
|
|
}
|
|
|
|
|
|
|
|
idsToSend := []ids.ShortID{}
|
|
|
|
sampler := random.Uniform{N: len(stakers)}
|
|
|
|
for i := 0; i < numStakersToSend; i++ {
|
|
|
|
idsToSend = append(idsToSend, stakers[sampler.Sample()])
|
|
|
|
}
|
|
|
|
sampler.N = len(nonStakers)
|
|
|
|
sampler.Replace()
|
|
|
|
for i := 0; i < numNonStakersToSend; i++ {
|
|
|
|
idsToSend = append(idsToSend, nonStakers[sampler.Sample()])
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
peers := []salticidae.PeerID{}
|
2020-03-10 12:20:34 -07:00
|
|
|
for _, id := range idsToSend {
|
2020-04-18 17:34:19 -07:00
|
|
|
if peer, exists := nm.connections.GetPeerID(id); exists {
|
|
|
|
peers = append(peers, peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.SendPeerList(peers...)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Connections returns the object that tracks the nodes that are currently
|
|
|
|
// connected to this node.
|
2020-04-18 17:34:19 -07:00
|
|
|
func (nm *Handshake) Connections() Connections { return nm.connections }
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
// Shutdown the network
|
|
|
|
func (nm *Handshake) Shutdown() {
|
|
|
|
nm.versionTimeout.Stop()
|
|
|
|
nm.peerListGossiper.Stop()
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendGetVersion to the requested peer
|
2020-04-18 17:34:19 -07:00
|
|
|
func (nm *Handshake) SendGetVersion(peer salticidae.PeerID) {
|
2020-03-10 12:20:34 -07:00
|
|
|
build := Builder{}
|
|
|
|
gv, err := build.GetVersion()
|
|
|
|
nm.log.AssertNoError(err)
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.send(gv, peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
nm.numGetVersionSent.Inc()
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendVersion to the requested peer
|
2020-04-18 17:34:19 -07:00
|
|
|
func (nm *Handshake) SendVersion(peer salticidae.PeerID) error {
|
2020-03-10 12:20:34 -07:00
|
|
|
build := Builder{}
|
2020-04-24 11:44:04 -07:00
|
|
|
v, err := build.Version(nm.networkID, nm.clock.Unix(), toIPDesc(nm.myAddr), ClientVersion)
|
2020-03-10 12:20:34 -07:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("packing Version failed due to %s", err)
|
|
|
|
}
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.send(v, peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
nm.numVersionSent.Inc()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendPeerList to the requested peer
|
2020-04-18 17:34:19 -07:00
|
|
|
func (nm *Handshake) SendPeerList(peers ...salticidae.PeerID) error {
|
|
|
|
if len(peers) == 0 {
|
2020-03-10 12:20:34 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
_, ids, ips := nm.connections.Conns()
|
2020-03-10 12:20:34 -07:00
|
|
|
ipsToSend := []utils.IPDesc(nil)
|
|
|
|
for i, id := range ids {
|
2020-04-18 17:34:19 -07:00
|
|
|
ip := ips[i]
|
2020-04-18 19:47:53 -07:00
|
|
|
if !ip.IsZero() && nm.vdrs.Contains(id) {
|
2020-04-18 17:34:19 -07:00
|
|
|
ipsToSend = append(ipsToSend, ip)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(ipsToSend) == 0 {
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.log.Debug("No IPs to send to %d peer(s)", len(peers))
|
2020-03-10 12:20:34 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.log.Verbo("Sending %d ips to %d peer(s)", len(ipsToSend), len(peers))
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
build := Builder{}
|
|
|
|
pl, err := build.PeerList(ipsToSend)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Packing Peerlist failed due to %w", err)
|
|
|
|
}
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.send(pl, peers...)
|
|
|
|
nm.numPeerlistSent.Add(float64(len(peers)))
|
2020-03-10 12:20:34 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
func (nm *Handshake) send(msg Msg, peers ...salticidae.PeerID) {
|
2020-03-10 12:20:34 -07:00
|
|
|
ds := msg.DataStream()
|
|
|
|
defer ds.Free()
|
|
|
|
ba := salticidae.NewByteArrayMovedFromDataStream(ds, false)
|
|
|
|
defer ba.Free()
|
|
|
|
cMsg := salticidae.NewMsgMovedFromByteArray(msg.Op(), ba, false)
|
|
|
|
defer cMsg.Free()
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
switch len(peers) {
|
2020-03-10 12:20:34 -07:00
|
|
|
case 0:
|
|
|
|
case 1:
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.net.SendMsg(cMsg, peers[0])
|
2020-03-10 12:20:34 -07:00
|
|
|
default:
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.net.MulticastMsgByMove(cMsg, peers)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-18 18:02:40 -07:00
|
|
|
// connHandler notifies of a new inbound connection
|
|
|
|
//export connHandler
|
2020-04-18 19:47:53 -07:00
|
|
|
func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.Pointer) C.bool {
|
|
|
|
if !HandshakeNet.enableStaking || !bool(connected) {
|
|
|
|
return connected
|
|
|
|
}
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.requestedLock.Lock()
|
|
|
|
defer HandshakeNet.requestedLock.Unlock()
|
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn))
|
|
|
|
addr := conn.GetAddr()
|
2020-03-10 12:20:34 -07:00
|
|
|
ip := toIPDesc(addr)
|
2020-04-18 19:47:53 -07:00
|
|
|
ipStr := ip.String()
|
2020-04-20 19:33:33 -07:00
|
|
|
|
|
|
|
ipID := ids.NewID(hashing.ComputeHash256Array([]byte(ipStr)))
|
|
|
|
HandshakeNet.requestedTimeout.Remove(ipID)
|
|
|
|
|
|
|
|
if _, exists := HandshakeNet.requested[ipStr]; !exists {
|
2020-04-18 19:47:53 -07:00
|
|
|
HandshakeNet.log.Debug("connHandler called with %s", ip)
|
|
|
|
return true
|
|
|
|
}
|
2020-04-20 19:33:33 -07:00
|
|
|
delete(HandshakeNet.requested, ipStr)
|
2020-04-18 19:47:53 -07:00
|
|
|
|
|
|
|
cert := conn.GetPeerCert()
|
2020-04-20 17:25:22 -07:00
|
|
|
peer := salticidae.NewPeerIDFromX509(cert, true)
|
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.ConnectTo(peer, getCert(cert), addr)
|
2020-04-18 19:47:53 -07:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (nm *Handshake) connectedToPeer(conn *C.struct_peernetwork_conn_t, peer salticidae.PeerID) {
|
|
|
|
peerBytes := toID(peer)
|
|
|
|
peerID := ids.NewID(peerBytes)
|
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
// If we're enforcing staking, use a peer's certificate to uniquely identify them
|
|
|
|
// Otherwise, use a hash of their ip to identify them
|
|
|
|
cert := ids.ShortID{}
|
|
|
|
if nm.enableStaking {
|
|
|
|
cert = getPeerCert(conn)
|
|
|
|
} else {
|
2020-04-18 19:47:53 -07:00
|
|
|
key := [20]byte{}
|
|
|
|
copy(key[:], peerID.Bytes())
|
|
|
|
cert = ids.NewShortID(key)
|
2020-04-03 16:14:13 -07:00
|
|
|
}
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
nm.log.Debug("Connected to %s", cert)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
nm.reconnectTimeout.Remove(peerID)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
handler := new(func())
|
|
|
|
*handler = func() {
|
2020-04-18 17:34:19 -07:00
|
|
|
if nm.pending.ContainsPeerID(peer) {
|
|
|
|
nm.SendGetVersion(peer)
|
2020-04-18 19:47:53 -07:00
|
|
|
nm.versionTimeout.Put(peerID, *handler)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
2020-04-03 16:14:13 -07:00
|
|
|
}
|
|
|
|
(*handler)()
|
|
|
|
}
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
func (nm *Handshake) disconnectedFromPeer(peer salticidae.PeerID) {
|
2020-04-03 16:14:13 -07:00
|
|
|
cert := ids.ShortID{}
|
2020-04-18 17:34:19 -07:00
|
|
|
if pendingCert, exists := nm.pending.GetID(peer); exists {
|
2020-04-03 16:14:13 -07:00
|
|
|
cert = pendingCert
|
2020-04-20 17:00:36 -07:00
|
|
|
nm.log.Info("Disconnected from pending peer %s", cert)
|
2020-04-18 17:34:19 -07:00
|
|
|
} else if connectedCert, exists := nm.connections.GetID(peer); exists {
|
2020-04-03 16:14:13 -07:00
|
|
|
cert = connectedCert
|
2020-04-20 17:00:36 -07:00
|
|
|
nm.log.Info("Disconnected from peer %s", cert)
|
2020-04-03 16:14:13 -07:00
|
|
|
} else {
|
2020-03-10 12:20:34 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
peerBytes := toID(peer)
|
|
|
|
peerID := ids.NewID(peerBytes)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.versionTimeout.Remove(peerID)
|
|
|
|
nm.connections.Remove(peer, cert)
|
|
|
|
nm.numPeers.Set(float64(nm.connections.Len()))
|
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
if nm.vdrs.Contains(cert) {
|
2020-04-18 19:47:53 -07:00
|
|
|
nm.reconnectTimeout.Put(peerID, func() {
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.pending.Remove(peer, cert)
|
|
|
|
nm.connections.Remove(peer, cert)
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.net.DelPeer(peer)
|
2020-04-20 19:33:33 -07:00
|
|
|
|
|
|
|
nm.numPeers.Set(float64(nm.connections.Len()))
|
2020-04-03 16:14:13 -07:00
|
|
|
})
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.pending.Add(peer, cert, utils.IPDesc{})
|
2020-03-10 12:20:34 -07:00
|
|
|
} else {
|
2020-04-20 19:33:33 -07:00
|
|
|
nm.pending.Remove(peer, cert)
|
2020-04-18 17:34:19 -07:00
|
|
|
nm.net.DelPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
if !nm.enableStaking {
|
|
|
|
nm.vdrs.Remove(cert)
|
|
|
|
}
|
|
|
|
|
|
|
|
nm.awaitingLock.Lock()
|
|
|
|
defer nm.awaitingLock.Unlock()
|
|
|
|
for _, awaiting := range HandshakeNet.awaiting {
|
|
|
|
awaiting.Remove(cert)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-24 11:44:04 -07:00
|
|
|
// checkCompatibility Check to make sure that the peer and I speak the same language.
|
|
|
|
func (nm *Handshake) checkCompatibility(peerVersion string) bool {
|
|
|
|
if !strings.HasPrefix(peerVersion, VersionPrefix) {
|
|
|
|
nm.log.Warn("Peer attempted to connect with an invalid version prefix")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
peerVersion = peerVersion[len(VersionPrefix):]
|
|
|
|
splitPeerVersion := strings.SplitN(peerVersion, VersionSeparator, 3)
|
|
|
|
if len(splitPeerVersion) != 3 {
|
|
|
|
nm.log.Warn("Peer attempted to connect with an invalid number of subversions")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
major, err := strconv.Atoi(splitPeerVersion[0])
|
|
|
|
if err != nil {
|
|
|
|
nm.log.Warn("Peer attempted to connect with an invalid major version")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
minor, err := strconv.Atoi(splitPeerVersion[1])
|
|
|
|
if err != nil {
|
|
|
|
nm.log.Warn("Peer attempted to connect with an invalid minor version")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
patch, err := strconv.Atoi(splitPeerVersion[2])
|
|
|
|
if err != nil {
|
|
|
|
nm.log.Warn("Peer attempted to connect with an invalid patch version")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case major < MajorVersion:
|
|
|
|
// peers major version is too low
|
|
|
|
return false
|
|
|
|
case major > MajorVersion:
|
|
|
|
nm.log.Warn("Peer attempted to connect with a higher major version, this client may need to be updated")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case minor < MinorVersion:
|
|
|
|
// peers minor version is too low
|
|
|
|
return false
|
|
|
|
case minor > MinorVersion:
|
|
|
|
nm.log.Warn("Peer attempted to connect with a higher minor version, this client may need to be updated")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if patch > PatchVersion {
|
|
|
|
nm.log.Warn("Peer is connecting with a higher patch version, this client may need to be updated")
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
// peerHandler notifies a change to the set of connected peers
|
|
|
|
// connected is true if a new peer is connected
|
|
|
|
// connected is false if a formerly connected peer has disconnected
|
|
|
|
//export peerHandler
|
|
|
|
func peerHandler(_conn *C.struct_peernetwork_conn_t, connected C.bool, _ unsafe.Pointer) {
|
2020-04-18 19:47:53 -07:00
|
|
|
HandshakeNet.log.Debug("peerHandler called")
|
2020-04-18 18:02:40 -07:00
|
|
|
|
2020-04-03 16:14:13 -07:00
|
|
|
pConn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
2020-04-18 17:34:19 -07:00
|
|
|
peer := pConn.GetPeerID(true)
|
2020-04-03 16:14:13 -07:00
|
|
|
|
|
|
|
if connected {
|
2020-04-18 19:47:53 -07:00
|
|
|
HandshakeNet.connectedToPeer(_conn, peer)
|
2020-04-03 16:14:13 -07:00
|
|
|
} else {
|
2020-04-18 19:47:53 -07:00
|
|
|
HandshakeNet.disconnectedFromPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// unknownPeerHandler notifies of an unknown peer connection attempt
|
|
|
|
//export unknownPeerHandler
|
|
|
|
func unknownPeerHandler(_addr *C.netaddr_t, _cert *C.x509_t, _ unsafe.Pointer) {
|
2020-04-18 19:47:53 -07:00
|
|
|
HandshakeNet.log.Debug("unknownPeerHandler called")
|
2020-04-18 18:02:40 -07:00
|
|
|
|
2020-04-03 21:30:28 -07:00
|
|
|
addr := salticidae.NetAddrFromC(salticidae.CNetAddr(_addr)).Copy(true)
|
2020-03-10 12:20:34 -07:00
|
|
|
ip := toIPDesc(addr)
|
2020-04-18 17:34:19 -07:00
|
|
|
|
2020-03-10 12:20:34 -07:00
|
|
|
HandshakeNet.log.Info("Adding peer %s", ip)
|
2020-04-03 21:30:28 -07:00
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
var peer salticidae.PeerID
|
2020-04-20 19:33:33 -07:00
|
|
|
var id ids.ShortID
|
2020-04-03 21:30:28 -07:00
|
|
|
if HandshakeNet.enableStaking {
|
2020-04-18 17:34:19 -07:00
|
|
|
cert := salticidae.X509FromC(salticidae.CX509(_cert))
|
|
|
|
peer = salticidae.NewPeerIDFromX509(cert, true)
|
2020-04-20 19:33:33 -07:00
|
|
|
id = getCert(cert)
|
2020-04-03 21:30:28 -07:00
|
|
|
} else {
|
2020-04-18 17:34:19 -07:00
|
|
|
peer = salticidae.NewPeerIDFromNetAddr(addr, true)
|
2020-04-20 19:33:33 -07:00
|
|
|
id = toShortID(ip)
|
2020-04-03 21:30:28 -07:00
|
|
|
}
|
|
|
|
|
2020-04-18 19:47:53 -07:00
|
|
|
peerBytes := toID(peer)
|
|
|
|
peerID := ids.NewID(peerBytes)
|
|
|
|
|
|
|
|
HandshakeNet.reconnectTimeout.Put(peerID, func() {
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.pending.Remove(peer, id)
|
|
|
|
HandshakeNet.connections.Remove(peer, id)
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.net.DelPeer(peer)
|
2020-04-20 19:33:33 -07:00
|
|
|
|
|
|
|
HandshakeNet.numPeers.Set(float64(HandshakeNet.connections.Len()))
|
2020-04-03 21:30:28 -07:00
|
|
|
})
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.pending.Add(peer, id, utils.IPDesc{})
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.net.AddPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// ping handles the recept of a ping message
|
|
|
|
//export ping
|
|
|
|
func ping(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) {
|
|
|
|
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
2020-04-18 17:34:19 -07:00
|
|
|
peer := conn.GetPeerID(false)
|
|
|
|
defer peer.Free()
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
build := Builder{}
|
|
|
|
pong, err := build.Pong()
|
|
|
|
HandshakeNet.log.AssertNoError(err)
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.send(pong, peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// pong handles the recept of a pong message
|
|
|
|
//export pong
|
|
|
|
func pong(*C.struct_msg_t, *C.struct_msgnetwork_conn_t, unsafe.Pointer) {}
|
|
|
|
|
|
|
|
// getVersion handles the recept of a getVersion message
|
|
|
|
//export getVersion
|
|
|
|
func getVersion(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) {
|
|
|
|
HandshakeNet.numGetVersionReceived.Inc()
|
|
|
|
|
|
|
|
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
2020-04-18 17:34:19 -07:00
|
|
|
peer := conn.GetPeerID(false)
|
|
|
|
defer peer.Free()
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.SendVersion(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// version handles the recept of a version message
|
|
|
|
//export version
|
|
|
|
func version(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) {
|
|
|
|
HandshakeNet.numVersionReceived.Inc()
|
|
|
|
|
|
|
|
msg := salticidae.MsgFromC(salticidae.CMsg(_msg))
|
|
|
|
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
2020-04-18 17:34:19 -07:00
|
|
|
peer := conn.GetPeerID(true)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
peerBytes := toID(peer)
|
|
|
|
peerID := ids.NewID(peerBytes)
|
|
|
|
|
|
|
|
HandshakeNet.versionTimeout.Remove(peerID)
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
id, exists := HandshakeNet.pending.GetID(peer)
|
|
|
|
if !exists {
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.log.Warn("Dropping Version message because the peer isn't pending")
|
2020-04-18 17:34:19 -07:00
|
|
|
return
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.pending.Remove(peer, id)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
build := Builder{}
|
|
|
|
pMsg, err := build.Parse(Version, msg.GetPayloadByMove())
|
|
|
|
if err != nil {
|
|
|
|
HandshakeNet.log.Warn("Failed to parse Version message")
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.net.DelPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if networkID := pMsg.Get(NetworkID).(uint32); networkID != HandshakeNet.networkID {
|
|
|
|
HandshakeNet.log.Warn("Peer's network ID doesn't match our networkID: Peer's = %d ; Ours = %d", networkID, HandshakeNet.networkID)
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.net.DelPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
myTime := float64(HandshakeNet.clock.Unix())
|
|
|
|
if peerTime := float64(pMsg.Get(MyTime).(uint64)); math.Abs(peerTime-myTime) > MaxClockDifference.Seconds() {
|
|
|
|
HandshakeNet.log.Warn("Peer's clock is too far out of sync with mine. His = %d, Mine = %d (seconds)", uint64(peerTime), uint64(myTime))
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.net.DelPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-24 11:44:04 -07:00
|
|
|
if peerVersion := pMsg.Get(VersionStr).(string); !HandshakeNet.checkCompatibility(peerVersion) {
|
2020-04-24 12:03:29 -07:00
|
|
|
HandshakeNet.log.Debug("Dropping connection due to an incompatible version from peer")
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.net.DelPeer(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
ip := pMsg.Get(IP).(utils.IPDesc)
|
|
|
|
|
|
|
|
HandshakeNet.log.Debug("Finishing handshake with %s", ip)
|
2020-03-10 12:20:34 -07:00
|
|
|
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.SendPeerList(peer)
|
|
|
|
HandshakeNet.connections.Add(peer, id, ip)
|
2020-04-20 19:33:33 -07:00
|
|
|
HandshakeNet.numPeers.Set(float64(HandshakeNet.connections.Len()))
|
2020-03-10 12:20:34 -07:00
|
|
|
|
|
|
|
if !HandshakeNet.enableStaking {
|
2020-04-18 17:34:19 -07:00
|
|
|
HandshakeNet.vdrs.Add(validators.NewValidator(id, 1))
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
HandshakeNet.awaitingLock.Lock()
|
|
|
|
defer HandshakeNet.awaitingLock.Unlock()
|
|
|
|
|
|
|
|
for i := 0; i < len(HandshakeNet.awaiting); i++ {
|
|
|
|
awaiting := HandshakeNet.awaiting[i]
|
2020-04-18 17:34:19 -07:00
|
|
|
awaiting.Add(id)
|
2020-03-10 12:20:34 -07:00
|
|
|
if !awaiting.Ready() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
newLen := len(HandshakeNet.awaiting) - 1
|
|
|
|
HandshakeNet.awaiting[i] = HandshakeNet.awaiting[newLen]
|
|
|
|
HandshakeNet.awaiting = HandshakeNet.awaiting[:newLen]
|
|
|
|
|
|
|
|
i--
|
|
|
|
|
|
|
|
go awaiting.Finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// getPeerList handles the recept of a getPeerList message
|
|
|
|
//export getPeerList
|
|
|
|
func getPeerList(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) {
|
|
|
|
HandshakeNet.numGetPeerlistReceived.Inc()
|
|
|
|
|
|
|
|
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
2020-04-18 17:34:19 -07:00
|
|
|
peer := conn.GetPeerID(false)
|
|
|
|
defer peer.Free()
|
|
|
|
|
|
|
|
HandshakeNet.SendPeerList(peer)
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// peerList handles the recept of a peerList message
|
|
|
|
//export peerList
|
|
|
|
func peerList(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) {
|
|
|
|
HandshakeNet.numPeerlistReceived.Inc()
|
|
|
|
|
|
|
|
msg := salticidae.MsgFromC(salticidae.CMsg(_msg))
|
|
|
|
build := Builder{}
|
|
|
|
pMsg, err := build.Parse(PeerList, msg.GetPayloadByMove())
|
|
|
|
if err != nil {
|
|
|
|
HandshakeNet.log.Warn("Failed to parse PeerList message due to %s", err)
|
|
|
|
// TODO: What should we do here?
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ips := pMsg.Get(Peers).([]utils.IPDesc)
|
|
|
|
cErr := salticidae.NewError()
|
|
|
|
for _, ip := range ips {
|
2020-04-03 21:30:28 -07:00
|
|
|
addr := salticidae.NewNetAddrFromIPPortString(ip.String(), true, &cErr)
|
|
|
|
|
2020-04-20 17:00:36 -07:00
|
|
|
if cErr.GetCode() != 0 || HandshakeNet.myAddr.IsEq(addr) {
|
|
|
|
// Make sure not to connect to myself
|
|
|
|
continue
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
2020-04-20 17:00:36 -07:00
|
|
|
HandshakeNet.Connect(addr)
|
|
|
|
}
|
2020-03-10 12:20:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func getPeerCert(_conn *C.struct_peernetwork_conn_t) ids.ShortID {
|
|
|
|
conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn))
|
|
|
|
return getCert(conn.GetPeerCert())
|
|
|
|
}
|
|
|
|
|
|
|
|
func getCert(cert salticidae.X509) ids.ShortID {
|
|
|
|
der := cert.GetDer(false)
|
|
|
|
certDS := salticidae.NewDataStreamMovedFromByteArray(der, false)
|
|
|
|
certBytes := certDS.GetDataInPlace(certDS.Size()).Get()
|
|
|
|
certID, err := ids.ToShortID(hashing.PubkeyBytesToAddress(certBytes))
|
2020-04-20 17:00:36 -07:00
|
|
|
|
|
|
|
certDS.Free()
|
|
|
|
der.Free()
|
2020-03-10 12:20:34 -07:00
|
|
|
HandshakeNet.log.AssertNoError(err)
|
|
|
|
return certID
|
|
|
|
}
|
|
|
|
|
2020-04-20 19:33:33 -07:00
|
|
|
func toShortID(ip utils.IPDesc) ids.ShortID {
|
|
|
|
return ids.NewShortID(hashing.ComputeHash160Array([]byte(ip.String())))
|
|
|
|
}
|