|
|
@ -30,6 +30,7 @@ import ( |
|
|
|
"sync" |
|
|
|
"sync" |
|
|
|
"time" |
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common/lru" |
|
|
|
"github.com/ethereum/go-ethereum/common/mclock" |
|
|
|
"github.com/ethereum/go-ethereum/common/mclock" |
|
|
|
"github.com/ethereum/go-ethereum/log" |
|
|
|
"github.com/ethereum/go-ethereum/log" |
|
|
|
"github.com/ethereum/go-ethereum/p2p/discover/v5wire" |
|
|
|
"github.com/ethereum/go-ethereum/p2p/discover/v5wire" |
|
|
@ -62,15 +63,16 @@ type codecV5 interface { |
|
|
|
// UDPv5 is the implementation of protocol version 5.
|
|
|
|
// UDPv5 is the implementation of protocol version 5.
|
|
|
|
type UDPv5 struct { |
|
|
|
type UDPv5 struct { |
|
|
|
// static fields
|
|
|
|
// static fields
|
|
|
|
conn UDPConn |
|
|
|
conn UDPConn |
|
|
|
tab *Table |
|
|
|
tab *Table |
|
|
|
netrestrict *netutil.Netlist |
|
|
|
netrestrict *netutil.Netlist |
|
|
|
priv *ecdsa.PrivateKey |
|
|
|
priv *ecdsa.PrivateKey |
|
|
|
localNode *enode.LocalNode |
|
|
|
localNode *enode.LocalNode |
|
|
|
db *enode.DB |
|
|
|
db *enode.DB |
|
|
|
log log.Logger |
|
|
|
log log.Logger |
|
|
|
clock mclock.Clock |
|
|
|
clock mclock.Clock |
|
|
|
validSchemes enr.IdentityScheme |
|
|
|
validSchemes enr.IdentityScheme |
|
|
|
|
|
|
|
cacheIdToNode *lru.Cache[enode.ID, *enode.Node] |
|
|
|
|
|
|
|
|
|
|
|
// misc buffers used during message handling
|
|
|
|
// misc buffers used during message handling
|
|
|
|
logcontext []interface{} |
|
|
|
logcontext []interface{} |
|
|
@ -150,14 +152,15 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) { |
|
|
|
cfg = cfg.withDefaults() |
|
|
|
cfg = cfg.withDefaults() |
|
|
|
t := &UDPv5{ |
|
|
|
t := &UDPv5{ |
|
|
|
// static fields
|
|
|
|
// static fields
|
|
|
|
conn: newMeteredConn(conn), |
|
|
|
conn: newMeteredConn(conn), |
|
|
|
localNode: ln, |
|
|
|
localNode: ln, |
|
|
|
db: ln.Database(), |
|
|
|
db: ln.Database(), |
|
|
|
netrestrict: cfg.NetRestrict, |
|
|
|
netrestrict: cfg.NetRestrict, |
|
|
|
priv: cfg.PrivateKey, |
|
|
|
priv: cfg.PrivateKey, |
|
|
|
log: cfg.Log, |
|
|
|
log: cfg.Log, |
|
|
|
validSchemes: cfg.ValidSchemes, |
|
|
|
validSchemes: cfg.ValidSchemes, |
|
|
|
clock: cfg.Clock, |
|
|
|
clock: cfg.Clock, |
|
|
|
|
|
|
|
cacheIdToNode: lru.NewCache[enode.ID, *enode.Node](1024), |
|
|
|
// channels into dispatch
|
|
|
|
// channels into dispatch
|
|
|
|
packetInCh: make(chan ReadPacket, 1), |
|
|
|
packetInCh: make(chan ReadPacket, 1), |
|
|
|
readNextCh: make(chan struct{}, 1), |
|
|
|
readNextCh: make(chan struct{}, 1), |
|
|
@ -705,6 +708,7 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr netip.AddrPort) error { |
|
|
|
if fromNode != nil { |
|
|
|
if fromNode != nil { |
|
|
|
// Handshake succeeded, add to table.
|
|
|
|
// Handshake succeeded, add to table.
|
|
|
|
t.tab.addInboundNode(fromNode) |
|
|
|
t.tab.addInboundNode(fromNode) |
|
|
|
|
|
|
|
t.cacheNode(fromNode) |
|
|
|
} |
|
|
|
} |
|
|
|
if packet.Kind() != v5wire.WhoareyouPacket { |
|
|
|
if packet.Kind() != v5wire.WhoareyouPacket { |
|
|
|
// WHOAREYOU logged separately to report errors.
|
|
|
|
// WHOAREYOU logged separately to report errors.
|
|
|
@ -737,16 +741,30 @@ func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr netip.AddrPort, p v |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// getNode looks for a node record in table and database.
|
|
|
|
// getNode looks for a node record in table and database.
|
|
|
|
func (t *UDPv5) getNode(id enode.ID) *enode.Node { |
|
|
|
func (t *UDPv5) GetNode(id enode.ID) (n *enode.Node) { |
|
|
|
if n := t.tab.getNode(id); n != nil { |
|
|
|
if node, ok := t.cacheIdToNode.Get(id); ok { |
|
|
|
return n |
|
|
|
return node |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
t.cacheNode(n) |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
if n = t.tab.getNode(id); n != nil { |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
if n := t.localNode.Database().Node(id); n != nil { |
|
|
|
if n = t.localNode.Database().Node(id); n != nil { |
|
|
|
return n |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// cacheNode cache addr to node
|
|
|
|
|
|
|
|
func (t *UDPv5) cacheNode(node *enode.Node) { |
|
|
|
|
|
|
|
if node == nil { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
t.cacheIdToNode.Add(node.ID(), node) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// handle processes incoming packets according to their message type.
|
|
|
|
// handle processes incoming packets according to their message type.
|
|
|
|
func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort) { |
|
|
|
func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort) { |
|
|
|
switch p := p.(type) { |
|
|
|
switch p := p.(type) { |
|
|
@ -776,7 +794,7 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort |
|
|
|
func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr netip.AddrPort) { |
|
|
|
func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr netip.AddrPort) { |
|
|
|
challenge := &v5wire.Whoareyou{Nonce: p.Nonce} |
|
|
|
challenge := &v5wire.Whoareyou{Nonce: p.Nonce} |
|
|
|
crand.Read(challenge.IDNonce[:]) |
|
|
|
crand.Read(challenge.IDNonce[:]) |
|
|
|
if n := t.getNode(fromID); n != nil { |
|
|
|
if n := t.GetNode(fromID); n != nil { |
|
|
|
challenge.Node = n |
|
|
|
challenge.Node = n |
|
|
|
challenge.RecordSeq = n.Seq() |
|
|
|
challenge.RecordSeq = n.Seq() |
|
|
|
} |
|
|
|
} |
|
|
|