mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
p2p/discover: WIP node refactoring part 2
This commit is contained in:
parent
b168d82446
commit
c0a1f1dfe1
8 changed files with 183 additions and 176 deletions
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -34,8 +35,8 @@ import (
|
||||||
|
|
||||||
// UDPConn is a network connection on which discovery can operate.
|
// UDPConn is a network connection on which discovery can operate.
|
||||||
type UDPConn interface {
|
type UDPConn interface {
|
||||||
ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error)
|
ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error)
|
||||||
WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error)
|
WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (n int, err error)
|
||||||
Close() error
|
Close() error
|
||||||
LocalAddr() net.Addr
|
LocalAddr() net.Addr
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +95,7 @@ func ListenUDP(c UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv4, error) {
|
||||||
// channel if configured.
|
// channel if configured.
|
||||||
type ReadPacket struct {
|
type ReadPacket struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
Addr *net.UDPAddr
|
Addr netip.AddrPort
|
||||||
}
|
}
|
||||||
|
|
||||||
type randomSource interface {
|
type randomSource interface {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ package discover
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
)
|
)
|
||||||
|
|
@ -59,15 +59,15 @@ func newMeteredConn(conn UDPConn) UDPConn {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFromUDP delegates a network read to the underlying connection, bumping the udp ingress traffic meter along the way.
|
// ReadFromUDP delegates a network read to the underlying connection, bumping the udp ingress traffic meter along the way.
|
||||||
func (c *meteredUdpConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
|
func (c *meteredUdpConn) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error) {
|
||||||
n, addr, err = c.UDPConn.ReadFromUDP(b)
|
n, addr, err = c.UDPConn.ReadFromUDPAddrPort(b)
|
||||||
ingressTrafficMeter.Mark(int64(n))
|
ingressTrafficMeter.Mark(int64(n))
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write delegates a network write to the underlying connection, bumping the udp egress traffic meter along the way.
|
// Write delegates a network write to the underlying connection, bumping the udp egress traffic meter along the way.
|
||||||
func (c *meteredUdpConn) WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) {
|
func (c *meteredUdpConn) WriteToUDP(b []byte, addr netip.AddrPort) (n int, err error) {
|
||||||
n, err = c.UDPConn.WriteToUDP(b, addr)
|
n, err = c.UDPConn.WriteToUDPAddrPort(b, addr)
|
||||||
egressTrafficMeter.Mark(int64(n))
|
egressTrafficMeter.Mark(int64(n))
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ type UDPv4 struct {
|
||||||
type replyMatcher struct {
|
type replyMatcher struct {
|
||||||
// these fields must match in the reply.
|
// these fields must match in the reply.
|
||||||
from enode.ID
|
from enode.ID
|
||||||
ip net.IP
|
ip netip.Addr
|
||||||
ptype byte
|
ptype byte
|
||||||
|
|
||||||
// time when the request must complete
|
// time when the request must complete
|
||||||
|
|
@ -121,7 +121,7 @@ type replyMatchFunc func(v4wire.Packet) (matched bool, requestDone bool)
|
||||||
// reply is a reply packet from a certain node.
|
// reply is a reply packet from a certain node.
|
||||||
type reply struct {
|
type reply struct {
|
||||||
from enode.ID
|
from enode.ID
|
||||||
ip net.IP
|
ip netip.Addr
|
||||||
data v4wire.Packet
|
data v4wire.Packet
|
||||||
// loop indicates whether there was
|
// loop indicates whether there was
|
||||||
// a matching request by sending on this channel.
|
// a matching request by sending on this channel.
|
||||||
|
|
@ -204,8 +204,8 @@ func (t *UDPv4) Resolve(n *enode.Node) *enode.Node {
|
||||||
|
|
||||||
func (t *UDPv4) ourEndpoint() v4wire.Endpoint {
|
func (t *UDPv4) ourEndpoint() v4wire.Endpoint {
|
||||||
n := t.Self()
|
n := t.Self()
|
||||||
a := &net.UDPAddr{IP: n.IP(), Port: n.UDP()}
|
addr, _ := n.UDPEndpoint()
|
||||||
return v4wire.NewEndpoint(a, uint16(n.TCP()))
|
return v4wire.NewEndpoint(addr, uint16(n.TCP()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ping sends a ping message to the given node.
|
// Ping sends a ping message to the given node.
|
||||||
|
|
@ -216,7 +216,11 @@ func (t *UDPv4) Ping(n *enode.Node) error {
|
||||||
|
|
||||||
// ping sends a ping message to the given node and waits for a reply.
|
// ping sends a ping message to the given node and waits for a reply.
|
||||||
func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
|
func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
|
||||||
rm := t.sendPing(n.ID(), &net.UDPAddr{IP: n.IP(), Port: n.UDP()}, nil)
|
addr, ok := n.UDPEndpoint()
|
||||||
|
if !ok {
|
||||||
|
return 0, errNoUDPEndpoint
|
||||||
|
}
|
||||||
|
rm := t.sendPing(n.ID(), addr, nil)
|
||||||
if err = <-rm.errc; err == nil {
|
if err = <-rm.errc; err == nil {
|
||||||
seq = rm.reply.(*v4wire.Pong).ENRSeq
|
seq = rm.reply.(*v4wire.Pong).ENRSeq
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +229,7 @@ func (t *UDPv4) ping(n *enode.Node) (seq uint64, err error) {
|
||||||
|
|
||||||
// sendPing sends a ping message to the given node and invokes the callback
|
// sendPing sends a ping message to the given node and invokes the callback
|
||||||
// when the reply arrives.
|
// when the reply arrives.
|
||||||
func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *replyMatcher {
|
func (t *UDPv4) sendPing(toid enode.ID, toaddr netip.AddrPort, callback func()) *replyMatcher {
|
||||||
req := t.makePing(toaddr)
|
req := t.makePing(toaddr)
|
||||||
packet, hash, err := v4wire.Encode(t.priv, req)
|
packet, hash, err := v4wire.Encode(t.priv, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -235,7 +239,7 @@ func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *r
|
||||||
}
|
}
|
||||||
// Add a matcher for the reply to the pending reply queue. Pongs are matched if they
|
// Add a matcher for the reply to the pending reply queue. Pongs are matched if they
|
||||||
// reference the ping we're about to send.
|
// reference the ping we're about to send.
|
||||||
rm := t.pending(toid, toaddr.IP, v4wire.PongPacket, func(p v4wire.Packet) (matched bool, requestDone bool) {
|
rm := t.pending(toid, toaddr.Addr(), v4wire.PongPacket, func(p v4wire.Packet) (matched bool, requestDone bool) {
|
||||||
matched = bytes.Equal(p.(*v4wire.Pong).ReplyTok, hash)
|
matched = bytes.Equal(p.(*v4wire.Pong).ReplyTok, hash)
|
||||||
if matched && callback != nil {
|
if matched && callback != nil {
|
||||||
callback()
|
callback()
|
||||||
|
|
@ -243,12 +247,13 @@ func (t *UDPv4) sendPing(toid enode.ID, toaddr *net.UDPAddr, callback func()) *r
|
||||||
return matched, matched
|
return matched, matched
|
||||||
})
|
})
|
||||||
// Send the packet.
|
// Send the packet.
|
||||||
t.localNode.UDPContact(toaddr)
|
udpAddr := &net.UDPAddr{IP: toaddr.Addr().AsSlice()}
|
||||||
|
t.localNode.UDPContact(udpAddr)
|
||||||
t.write(toaddr, toid, req.Name(), packet)
|
t.write(toaddr, toid, req.Name(), packet)
|
||||||
return rm
|
return rm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) makePing(toaddr *net.UDPAddr) *v4wire.Ping {
|
func (t *UDPv4) makePing(toaddr netip.AddrPort) *v4wire.Ping {
|
||||||
return &v4wire.Ping{
|
return &v4wire.Ping{
|
||||||
Version: 4,
|
Version: 4,
|
||||||
From: t.ourEndpoint(),
|
From: t.ourEndpoint(),
|
||||||
|
|
@ -305,27 +310,26 @@ func (t *UDPv4) newLookup(ctx context.Context, targetKey encPubkey) *lookup {
|
||||||
// findnode sends a findnode request to the given node and waits until
|
// findnode sends a findnode request to the given node and waits until
|
||||||
// the node has sent up to k neighbors.
|
// the node has sent up to k neighbors.
|
||||||
func (t *UDPv4) findnode(toid enode.ID, toAddrPort netip.AddrPort, target v4wire.Pubkey) ([]*enode.Node, error) {
|
func (t *UDPv4) findnode(toid enode.ID, toAddrPort netip.AddrPort, target v4wire.Pubkey) ([]*enode.Node, error) {
|
||||||
toaddr := &net.UDPAddr{IP: toAddrPort.Addr().AsSlice(), Port: int(toAddrPort.Port())}
|
t.ensureBond(toid, toAddrPort)
|
||||||
t.ensureBond(toid, toaddr)
|
|
||||||
|
|
||||||
// Add a matcher for 'neighbours' replies to the pending reply queue. The matcher is
|
// Add a matcher for 'neighbours' replies to the pending reply queue. The matcher is
|
||||||
// active until enough nodes have been received.
|
// active until enough nodes have been received.
|
||||||
nodes := make([]*enode.Node, 0, bucketSize)
|
nodes := make([]*enode.Node, 0, bucketSize)
|
||||||
nreceived := 0
|
nreceived := 0
|
||||||
rm := t.pending(toid, toaddr.IP, v4wire.NeighborsPacket, func(r v4wire.Packet) (matched bool, requestDone bool) {
|
rm := t.pending(toid, toAddrPort.Addr(), v4wire.NeighborsPacket, func(r v4wire.Packet) (matched bool, requestDone bool) {
|
||||||
reply := r.(*v4wire.Neighbors)
|
reply := r.(*v4wire.Neighbors)
|
||||||
for _, rn := range reply.Nodes {
|
for _, rn := range reply.Nodes {
|
||||||
nreceived++
|
nreceived++
|
||||||
n, err := t.nodeFromRPC(toaddr, rn)
|
n, err := t.nodeFromRPC(toAddrPort, rn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err)
|
t.log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toAddrPort, "err", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
}
|
}
|
||||||
return true, nreceived >= bucketSize
|
return true, nreceived >= bucketSize
|
||||||
})
|
})
|
||||||
t.send(toaddr, toid, &v4wire.Findnode{
|
t.send(toAddrPort, toid, &v4wire.Findnode{
|
||||||
Target: target,
|
Target: target,
|
||||||
Expiration: uint64(time.Now().Add(expiration).Unix()),
|
Expiration: uint64(time.Now().Add(expiration).Unix()),
|
||||||
})
|
})
|
||||||
|
|
@ -343,7 +347,7 @@ func (t *UDPv4) findnode(toid enode.ID, toAddrPort netip.AddrPort, target v4wire
|
||||||
|
|
||||||
// RequestENR sends ENRRequest to the given node and waits for a response.
|
// RequestENR sends ENRRequest to the given node and waits for a response.
|
||||||
func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
addr := &net.UDPAddr{IP: n.IP(), Port: n.UDP()}
|
addr, _ := n.UDPEndpoint()
|
||||||
t.ensureBond(n.ID(), addr)
|
t.ensureBond(n.ID(), addr)
|
||||||
|
|
||||||
req := &v4wire.ENRRequest{
|
req := &v4wire.ENRRequest{
|
||||||
|
|
@ -356,7 +360,7 @@ func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
|
|
||||||
// Add a matcher for the reply to the pending reply queue. Responses are matched if
|
// Add a matcher for the reply to the pending reply queue. Responses are matched if
|
||||||
// they reference the request we're about to send.
|
// they reference the request we're about to send.
|
||||||
rm := t.pending(n.ID(), addr.IP, v4wire.ENRResponsePacket, func(r v4wire.Packet) (matched bool, requestDone bool) {
|
rm := t.pending(n.ID(), addr.Addr(), v4wire.ENRResponsePacket, func(r v4wire.Packet) (matched bool, requestDone bool) {
|
||||||
matched = bytes.Equal(r.(*v4wire.ENRResponse).ReplyTok, hash)
|
matched = bytes.Equal(r.(*v4wire.ENRResponse).ReplyTok, hash)
|
||||||
return matched, matched
|
return matched, matched
|
||||||
})
|
})
|
||||||
|
|
@ -376,7 +380,7 @@ func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
|
||||||
if respN.Seq() < n.Seq() {
|
if respN.Seq() < n.Seq() {
|
||||||
return n, nil // response record is older
|
return n, nil // response record is older
|
||||||
}
|
}
|
||||||
if err := netutil.CheckRelayIP(addr.IP, respN.IP()); err != nil {
|
if err := netutil.CheckRelayIP(addr.Addr().AsSlice(), respN.IP()); err != nil {
|
||||||
return nil, fmt.Errorf("invalid IP in response record: %v", err)
|
return nil, fmt.Errorf("invalid IP in response record: %v", err)
|
||||||
}
|
}
|
||||||
return respN, nil
|
return respN, nil
|
||||||
|
|
@ -388,7 +392,7 @@ func (t *UDPv4) TableBuckets() [][]BucketNode {
|
||||||
|
|
||||||
// pending adds a reply matcher to the pending reply queue.
|
// pending adds a reply matcher to the pending reply queue.
|
||||||
// see the documentation of type replyMatcher for a detailed explanation.
|
// see the documentation of type replyMatcher for a detailed explanation.
|
||||||
func (t *UDPv4) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchFunc) *replyMatcher {
|
func (t *UDPv4) pending(id enode.ID, ip netip.Addr, ptype byte, callback replyMatchFunc) *replyMatcher {
|
||||||
ch := make(chan error, 1)
|
ch := make(chan error, 1)
|
||||||
p := &replyMatcher{from: id, ip: ip, ptype: ptype, callback: callback, errc: ch}
|
p := &replyMatcher{from: id, ip: ip, ptype: ptype, callback: callback, errc: ch}
|
||||||
select {
|
select {
|
||||||
|
|
@ -402,7 +406,7 @@ func (t *UDPv4) pending(id enode.ID, ip net.IP, ptype byte, callback replyMatchF
|
||||||
|
|
||||||
// handleReply dispatches a reply packet, invoking reply matchers. It returns
|
// handleReply dispatches a reply packet, invoking reply matchers. It returns
|
||||||
// whether any matcher considered the packet acceptable.
|
// whether any matcher considered the packet acceptable.
|
||||||
func (t *UDPv4) handleReply(from enode.ID, fromIP net.IP, req v4wire.Packet) bool {
|
func (t *UDPv4) handleReply(from enode.ID, fromIP netip.Addr, req v4wire.Packet) bool {
|
||||||
matched := make(chan bool, 1)
|
matched := make(chan bool, 1)
|
||||||
select {
|
select {
|
||||||
case t.gotreply <- reply{from, fromIP, req, matched}:
|
case t.gotreply <- reply{from, fromIP, req, matched}:
|
||||||
|
|
@ -468,7 +472,7 @@ func (t *UDPv4) loop() {
|
||||||
var matched bool // whether any replyMatcher considered the reply acceptable.
|
var matched bool // whether any replyMatcher considered the reply acceptable.
|
||||||
for el := plist.Front(); el != nil; el = el.Next() {
|
for el := plist.Front(); el != nil; el = el.Next() {
|
||||||
p := el.Value.(*replyMatcher)
|
p := el.Value.(*replyMatcher)
|
||||||
if p.from == r.from && p.ptype == r.data.Kind() && p.ip.Equal(r.ip) {
|
if p.from == r.from && p.ptype == r.data.Kind() && p.ip == r.ip {
|
||||||
ok, requestDone := p.callback(r.data)
|
ok, requestDone := p.callback(r.data)
|
||||||
matched = matched || ok
|
matched = matched || ok
|
||||||
p.reply = r.data
|
p.reply = r.data
|
||||||
|
|
@ -507,7 +511,7 @@ func (t *UDPv4) loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) send(toaddr *net.UDPAddr, toid enode.ID, req v4wire.Packet) ([]byte, error) {
|
func (t *UDPv4) send(toaddr netip.AddrPort, toid enode.ID, req v4wire.Packet) ([]byte, error) {
|
||||||
packet, hash, err := v4wire.Encode(t.priv, req)
|
packet, hash, err := v4wire.Encode(t.priv, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hash, err
|
return hash, err
|
||||||
|
|
@ -515,8 +519,8 @@ func (t *UDPv4) send(toaddr *net.UDPAddr, toid enode.ID, req v4wire.Packet) ([]b
|
||||||
return hash, t.write(toaddr, toid, req.Name(), packet)
|
return hash, t.write(toaddr, toid, req.Name(), packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) write(toaddr *net.UDPAddr, toid enode.ID, what string, packet []byte) error {
|
func (t *UDPv4) write(toaddr netip.AddrPort, toid enode.ID, what string, packet []byte) error {
|
||||||
_, err := t.conn.WriteToUDP(packet, toaddr)
|
_, err := t.conn.WriteToUDPAddrPort(packet, toaddr)
|
||||||
t.log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err)
|
t.log.Trace(">> "+what, "id", toid, "addr", toaddr, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -530,7 +534,7 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) {
|
||||||
|
|
||||||
buf := make([]byte, maxPacketSize)
|
buf := make([]byte, maxPacketSize)
|
||||||
for {
|
for {
|
||||||
nbytes, from, err := t.conn.ReadFromUDP(buf)
|
nbytes, from, err := t.conn.ReadFromUDPAddrPort(buf)
|
||||||
if netutil.IsTemporaryError(err) {
|
if netutil.IsTemporaryError(err) {
|
||||||
// Ignore temporary read errors.
|
// Ignore temporary read errors.
|
||||||
t.log.Debug("Temporary UDP read error", "err", err)
|
t.log.Debug("Temporary UDP read error", "err", err)
|
||||||
|
|
@ -551,7 +555,7 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error {
|
func (t *UDPv4) handlePacket(from netip.AddrPort, buf []byte) error {
|
||||||
rawpacket, fromKey, hash, err := v4wire.Decode(buf)
|
rawpacket, fromKey, hash, err := v4wire.Decode(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.log.Debug("Bad discv4 packet", "addr", from, "err", err)
|
t.log.Debug("Bad discv4 packet", "addr", from, "err", err)
|
||||||
|
|
@ -570,15 +574,16 @@ func (t *UDPv4) handlePacket(from *net.UDPAddr, buf []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkBond checks if the given node has a recent enough endpoint proof.
|
// checkBond checks if the given node has a recent enough endpoint proof.
|
||||||
func (t *UDPv4) checkBond(id enode.ID, ip net.IP) bool {
|
func (t *UDPv4) checkBond(id enode.ID, ip netip.AddrPort) bool {
|
||||||
return time.Since(t.db.LastPongReceived(id, ip)) < bondExpiration
|
return time.Since(t.db.LastPongReceived(id, ip.Addr().AsSlice())) < bondExpiration
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureBond solicits a ping from a node if we haven't seen a ping from it for a while.
|
// ensureBond solicits a ping from a node if we haven't seen a ping from it for a while.
|
||||||
// This ensures there is a valid endpoint proof on the remote end.
|
// This ensures there is a valid endpoint proof on the remote end.
|
||||||
func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) {
|
func (t *UDPv4) ensureBond(toid enode.ID, toaddr netip.AddrPort) {
|
||||||
tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.IP)) > bondExpiration
|
ip := toaddr.Addr().AsSlice()
|
||||||
if tooOld || t.db.FindFails(toid, toaddr.IP) > maxFindnodeFailures {
|
tooOld := time.Since(t.db.LastPingReceived(toid, ip)) > bondExpiration
|
||||||
|
if tooOld || t.db.FindFails(toid, ip) > maxFindnodeFailures {
|
||||||
rm := t.sendPing(toid, toaddr, nil)
|
rm := t.sendPing(toid, toaddr, nil)
|
||||||
<-rm.errc
|
<-rm.errc
|
||||||
// Wait for them to ping back and process our pong.
|
// Wait for them to ping back and process our pong.
|
||||||
|
|
@ -586,11 +591,11 @@ func (t *UDPv4) ensureBond(toid enode.ID, toaddr *net.UDPAddr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) nodeFromRPC(sender *net.UDPAddr, rn v4wire.Node) (*enode.Node, error) {
|
func (t *UDPv4) nodeFromRPC(sender netip.AddrPort, rn v4wire.Node) (*enode.Node, error) {
|
||||||
if rn.UDP <= 1024 {
|
if rn.UDP <= 1024 {
|
||||||
return nil, errLowPort
|
return nil, errLowPort
|
||||||
}
|
}
|
||||||
if err := netutil.CheckRelayIP(sender.IP, rn.IP); err != nil {
|
if err := netutil.CheckRelayIP(sender.Addr().AsSlice(), rn.IP); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
|
if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
|
||||||
|
|
@ -644,14 +649,14 @@ type packetHandlerV4 struct {
|
||||||
senderKey *ecdsa.PublicKey // used for ping
|
senderKey *ecdsa.PublicKey // used for ping
|
||||||
|
|
||||||
// preverify checks whether the packet is valid and should be handled at all.
|
// preverify checks whether the packet is valid and should be handled at all.
|
||||||
preverify func(p *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error
|
preverify func(p *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error
|
||||||
// handle handles the packet.
|
// handle handles the packet.
|
||||||
handle func(req *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, mac []byte)
|
handle func(req *packetHandlerV4, from netip.AddrPort, fromID enode.ID, mac []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PING/v4
|
// PING/v4
|
||||||
|
|
||||||
func (t *UDPv4) verifyPing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
func (t *UDPv4) verifyPing(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
||||||
req := h.Packet.(*v4wire.Ping)
|
req := h.Packet.(*v4wire.Ping)
|
||||||
|
|
||||||
if v4wire.Expired(req.Expiration) {
|
if v4wire.Expired(req.Expiration) {
|
||||||
|
|
@ -665,7 +670,7 @@ func (t *UDPv4) verifyPing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, mac []byte) {
|
func (t *UDPv4) handlePing(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, mac []byte) {
|
||||||
req := h.Packet.(*v4wire.Ping)
|
req := h.Packet.(*v4wire.Ping)
|
||||||
|
|
||||||
// Reply.
|
// Reply.
|
||||||
|
|
@ -677,8 +682,9 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
|
||||||
})
|
})
|
||||||
|
|
||||||
// Ping back if our last pong on file is too far in the past.
|
// Ping back if our last pong on file is too far in the past.
|
||||||
n := enode.NewV4(h.senderKey, from.IP, int(req.From.TCP), from.Port)
|
ip := from.Addr().AsSlice()
|
||||||
if time.Since(t.db.LastPongReceived(n.ID(), from.IP)) > bondExpiration {
|
n := enode.NewV4(h.senderKey, ip, int(req.From.TCP), int(from.Port()))
|
||||||
|
if time.Since(t.db.LastPongReceived(n.ID(), ip)) > bondExpiration {
|
||||||
t.sendPing(fromID, from, func() {
|
t.sendPing(fromID, from, func() {
|
||||||
t.tab.addInboundNode(n)
|
t.tab.addInboundNode(n)
|
||||||
})
|
})
|
||||||
|
|
@ -687,35 +693,40 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from *net.UDPAddr, fromID enode.I
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update node database and endpoint predictor.
|
// Update node database and endpoint predictor.
|
||||||
t.db.UpdateLastPingReceived(n.ID(), from.IP, time.Now())
|
t.db.UpdateLastPingReceived(n.ID(), ip, time.Now())
|
||||||
t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)})
|
fromUDPAddr := &net.UDPAddr{IP: ip, Port: int(from.Port())}
|
||||||
|
toUDPAddr := &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}
|
||||||
|
t.localNode.UDPEndpointStatement(fromUDPAddr, toUDPAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PONG/v4
|
// PONG/v4
|
||||||
|
|
||||||
func (t *UDPv4) verifyPong(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
func (t *UDPv4) verifyPong(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
||||||
req := h.Packet.(*v4wire.Pong)
|
req := h.Packet.(*v4wire.Pong)
|
||||||
|
|
||||||
if v4wire.Expired(req.Expiration) {
|
if v4wire.Expired(req.Expiration) {
|
||||||
return errExpired
|
return errExpired
|
||||||
}
|
}
|
||||||
if !t.handleReply(fromID, from.IP, req) {
|
if !t.handleReply(fromID, from.Addr(), req) {
|
||||||
return errUnsolicitedReply
|
return errUnsolicitedReply
|
||||||
}
|
}
|
||||||
t.localNode.UDPEndpointStatement(from, &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)})
|
fromIP := from.Addr().AsSlice()
|
||||||
t.db.UpdateLastPongReceived(fromID, from.IP, time.Now())
|
fromUDPAddr := &net.UDPAddr{IP: fromIP, Port: int(from.Port())}
|
||||||
|
toUDPAddr := &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}
|
||||||
|
t.localNode.UDPEndpointStatement(fromUDPAddr, toUDPAddr)
|
||||||
|
t.db.UpdateLastPongReceived(fromID, fromIP, time.Now())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FINDNODE/v4
|
// FINDNODE/v4
|
||||||
|
|
||||||
func (t *UDPv4) verifyFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
func (t *UDPv4) verifyFindnode(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
||||||
req := h.Packet.(*v4wire.Findnode)
|
req := h.Packet.(*v4wire.Findnode)
|
||||||
|
|
||||||
if v4wire.Expired(req.Expiration) {
|
if v4wire.Expired(req.Expiration) {
|
||||||
return errExpired
|
return errExpired
|
||||||
}
|
}
|
||||||
if !t.checkBond(fromID, from.IP) {
|
if !t.checkBond(fromID, from) {
|
||||||
// No endpoint proof pong exists, we don't process the packet. This prevents an
|
// No endpoint proof pong exists, we don't process the packet. This prevents an
|
||||||
// attack vector where the discovery protocol could be used to amplify traffic in a
|
// attack vector where the discovery protocol could be used to amplify traffic in a
|
||||||
// DDOS attack. A malicious actor would send a findnode request with the IP address
|
// DDOS attack. A malicious actor would send a findnode request with the IP address
|
||||||
|
|
@ -727,7 +738,7 @@ func (t *UDPv4) verifyFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) handleFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, mac []byte) {
|
func (t *UDPv4) handleFindnode(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, mac []byte) {
|
||||||
req := h.Packet.(*v4wire.Findnode)
|
req := h.Packet.(*v4wire.Findnode)
|
||||||
|
|
||||||
// Determine closest nodes.
|
// Determine closest nodes.
|
||||||
|
|
@ -739,7 +750,8 @@ func (t *UDPv4) handleFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno
|
||||||
p := v4wire.Neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())}
|
p := v4wire.Neighbors{Expiration: uint64(time.Now().Add(expiration).Unix())}
|
||||||
var sent bool
|
var sent bool
|
||||||
for _, n := range closest {
|
for _, n := range closest {
|
||||||
if netutil.CheckRelayIP(from.IP, n.IP()) == nil {
|
fromIP := from.Addr().AsSlice()
|
||||||
|
if netutil.CheckRelayIP(fromIP, n.IP()) == nil {
|
||||||
p.Nodes = append(p.Nodes, nodeToRPC(n))
|
p.Nodes = append(p.Nodes, nodeToRPC(n))
|
||||||
}
|
}
|
||||||
if len(p.Nodes) == v4wire.MaxNeighbors {
|
if len(p.Nodes) == v4wire.MaxNeighbors {
|
||||||
|
|
@ -755,13 +767,13 @@ func (t *UDPv4) handleFindnode(h *packetHandlerV4, from *net.UDPAddr, fromID eno
|
||||||
|
|
||||||
// NEIGHBORS/v4
|
// NEIGHBORS/v4
|
||||||
|
|
||||||
func (t *UDPv4) verifyNeighbors(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
func (t *UDPv4) verifyNeighbors(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
||||||
req := h.Packet.(*v4wire.Neighbors)
|
req := h.Packet.(*v4wire.Neighbors)
|
||||||
|
|
||||||
if v4wire.Expired(req.Expiration) {
|
if v4wire.Expired(req.Expiration) {
|
||||||
return errExpired
|
return errExpired
|
||||||
}
|
}
|
||||||
if !t.handleReply(fromID, from.IP, h.Packet) {
|
if !t.handleReply(fromID, from.Addr(), h.Packet) {
|
||||||
return errUnsolicitedReply
|
return errUnsolicitedReply
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -769,19 +781,19 @@ func (t *UDPv4) verifyNeighbors(h *packetHandlerV4, from *net.UDPAddr, fromID en
|
||||||
|
|
||||||
// ENRREQUEST/v4
|
// ENRREQUEST/v4
|
||||||
|
|
||||||
func (t *UDPv4) verifyENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
func (t *UDPv4) verifyENRRequest(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
||||||
req := h.Packet.(*v4wire.ENRRequest)
|
req := h.Packet.(*v4wire.ENRRequest)
|
||||||
|
|
||||||
if v4wire.Expired(req.Expiration) {
|
if v4wire.Expired(req.Expiration) {
|
||||||
return errExpired
|
return errExpired
|
||||||
}
|
}
|
||||||
if !t.checkBond(fromID, from.IP) {
|
if !t.checkBond(fromID, from) {
|
||||||
return errUnknownNode
|
return errUnknownNode
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) handleENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, mac []byte) {
|
func (t *UDPv4) handleENRRequest(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, mac []byte) {
|
||||||
t.send(from, fromID, &v4wire.ENRResponse{
|
t.send(from, fromID, &v4wire.ENRResponse{
|
||||||
ReplyTok: mac,
|
ReplyTok: mac,
|
||||||
Record: *t.localNode.Node().Record(),
|
Record: *t.localNode.Node().Record(),
|
||||||
|
|
@ -790,8 +802,8 @@ func (t *UDPv4) handleENRRequest(h *packetHandlerV4, from *net.UDPAddr, fromID e
|
||||||
|
|
||||||
// ENRRESPONSE/v4
|
// ENRRESPONSE/v4
|
||||||
|
|
||||||
func (t *UDPv4) verifyENRResponse(h *packetHandlerV4, from *net.UDPAddr, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
func (t *UDPv4) verifyENRResponse(h *packetHandlerV4, from netip.AddrPort, fromID enode.ID, fromKey v4wire.Pubkey) error {
|
||||||
if !t.handleReply(fromID, from.IP, h.Packet) {
|
if !t.handleReply(fromID, from.Addr(), h.Packet) {
|
||||||
return errUnsolicitedReply
|
return errUnsolicitedReply
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ func newUDPTest(t *testing.T) *udpTest {
|
||||||
pipe: newpipe(),
|
pipe: newpipe(),
|
||||||
localkey: newkey(),
|
localkey: newkey(),
|
||||||
remotekey: newkey(),
|
remotekey: newkey(),
|
||||||
remoteaddr: netip.AddrPortFrom(netip.MustParseAddr("10.0.1.99"), 30303),
|
remoteaddr: netip.MustParseAddrPort("10.0.1.99:30303"),
|
||||||
}
|
}
|
||||||
|
|
||||||
test.db, _ = enode.OpenDB("")
|
test.db, _ = enode.OpenDB("")
|
||||||
|
|
@ -101,14 +101,13 @@ func (test *udpTest) packetInFrom(wantError error, key *ecdsa.PrivateKey, addr n
|
||||||
test.t.Errorf("%s encode error: %v", data.Name(), err)
|
test.t.Errorf("%s encode error: %v", data.Name(), err)
|
||||||
}
|
}
|
||||||
test.sent = append(test.sent, enc)
|
test.sent = append(test.sent, enc)
|
||||||
udpaddr := &net.UDPAddr{IP: addr.Addr().AsSlice(), Port: int(addr.Port())}
|
if err = test.udp.handlePacket(addr, enc); err != wantError {
|
||||||
if err = test.udp.handlePacket(udpaddr, enc); err != wantError {
|
|
||||||
test.t.Errorf("error mismatch: got %q, want %q", err, wantError)
|
test.t.Errorf("error mismatch: got %q, want %q", err, wantError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// waits for a packet to be sent by the transport.
|
// waits for a packet to be sent by the transport.
|
||||||
// validate should have type func(X, *net.UDPAddr, []byte), where X is a packet type.
|
// validate should have type func(X, netip.AddrPort, []byte), where X is a packet type.
|
||||||
func (test *udpTest) waitPacketOut(validate interface{}) (closed bool) {
|
func (test *udpTest) waitPacketOut(validate interface{}) (closed bool) {
|
||||||
test.t.Helper()
|
test.t.Helper()
|
||||||
|
|
||||||
|
|
@ -130,7 +129,7 @@ func (test *udpTest) waitPacketOut(validate interface{}) (closed bool) {
|
||||||
test.t.Errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
|
test.t.Errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fn.Call([]reflect.Value{reflect.ValueOf(p), reflect.ValueOf(&dgram.to), reflect.ValueOf(hash)})
|
fn.Call([]reflect.Value{reflect.ValueOf(p), reflect.ValueOf(dgram.to), reflect.ValueOf(hash)})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,7 +280,7 @@ func TestUDPv4_findnode(t *testing.T) {
|
||||||
expected := test.table.findnodeByID(testTarget.ID(), bucketSize, true)
|
expected := test.table.findnodeByID(testTarget.ID(), bucketSize, true)
|
||||||
test.packetIn(nil, &v4wire.Findnode{Target: testTarget, Expiration: futureExp})
|
test.packetIn(nil, &v4wire.Findnode{Target: testTarget, Expiration: futureExp})
|
||||||
waitNeighbors := func(want []*enode.Node) {
|
waitNeighbors := func(want []*enode.Node) {
|
||||||
test.waitPacketOut(func(p *v4wire.Neighbors, to *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Neighbors, to netip.AddrPort, hash []byte) {
|
||||||
if len(p.Nodes) != len(want) {
|
if len(p.Nodes) != len(want) {
|
||||||
t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), len(want))
|
t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), len(want))
|
||||||
return
|
return
|
||||||
|
|
@ -326,7 +325,7 @@ func TestUDPv4_findnodeMultiReply(t *testing.T) {
|
||||||
|
|
||||||
// wait for the findnode to be sent.
|
// wait for the findnode to be sent.
|
||||||
// after it is sent, the transport is waiting for a reply
|
// after it is sent, the transport is waiting for a reply
|
||||||
test.waitPacketOut(func(p *v4wire.Findnode, to *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Findnode, to netip.AddrPort, hash []byte) {
|
||||||
if p.Target != testTarget {
|
if p.Target != testTarget {
|
||||||
t.Errorf("wrong target: got %v, want %v", p.Target, testTarget)
|
t.Errorf("wrong target: got %v, want %v", p.Target, testTarget)
|
||||||
}
|
}
|
||||||
|
|
@ -369,8 +368,8 @@ func TestUDPv4_pingMatch(t *testing.T) {
|
||||||
crand.Read(randToken)
|
crand.Read(randToken)
|
||||||
|
|
||||||
test.packetIn(nil, &v4wire.Ping{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp})
|
test.packetIn(nil, &v4wire.Ping{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp})
|
||||||
test.waitPacketOut(func(*v4wire.Pong, *net.UDPAddr, []byte) {})
|
test.waitPacketOut(func(*v4wire.Pong, netip.AddrPort, []byte) {})
|
||||||
test.waitPacketOut(func(*v4wire.Ping, *net.UDPAddr, []byte) {})
|
test.waitPacketOut(func(*v4wire.Ping, netip.AddrPort, []byte) {})
|
||||||
test.packetIn(errUnsolicitedReply, &v4wire.Pong{ReplyTok: randToken, To: testLocalAnnounced, Expiration: futureExp})
|
test.packetIn(errUnsolicitedReply, &v4wire.Pong{ReplyTok: randToken, To: testLocalAnnounced, Expiration: futureExp})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,7 +379,7 @@ func TestUDPv4_pingMatchIP(t *testing.T) {
|
||||||
defer test.close()
|
defer test.close()
|
||||||
|
|
||||||
test.packetIn(nil, &v4wire.Ping{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp})
|
test.packetIn(nil, &v4wire.Ping{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp})
|
||||||
test.waitPacketOut(func(*v4wire.Pong, *net.UDPAddr, []byte) {})
|
test.waitPacketOut(func(*v4wire.Pong, netip.AddrPort, []byte) {})
|
||||||
|
|
||||||
test.waitPacketOut(func(p *v4wire.Ping, to netip.AddrPort, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Ping, to netip.AddrPort, hash []byte) {
|
||||||
wrongAddr := netip.MustParseAddrPort("33.44.1.2:30000")
|
wrongAddr := netip.MustParseAddrPort("33.44.1.2:30000")
|
||||||
|
|
@ -402,34 +401,26 @@ func TestUDPv4_successfulPing(t *testing.T) {
|
||||||
go test.packetIn(nil, &v4wire.Ping{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp})
|
go test.packetIn(nil, &v4wire.Ping{From: testRemote, To: testLocalAnnounced, Version: 4, Expiration: futureExp})
|
||||||
|
|
||||||
// The ping is replied to.
|
// The ping is replied to.
|
||||||
test.waitPacketOut(func(p *v4wire.Pong, to *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Pong, to netip.AddrPort, hash []byte) {
|
||||||
pinghash := test.sent[0][:32]
|
pinghash := test.sent[0][:32]
|
||||||
if !bytes.Equal(p.ReplyTok, pinghash) {
|
if !bytes.Equal(p.ReplyTok, pinghash) {
|
||||||
t.Errorf("got pong.ReplyTok %x, want %x", p.ReplyTok, pinghash)
|
t.Errorf("got pong.ReplyTok %x, want %x", p.ReplyTok, pinghash)
|
||||||
}
|
}
|
||||||
wantTo := v4wire.Endpoint{
|
// The mirrored UDP address is the UDP packet sender.
|
||||||
// The mirrored UDP address is the UDP packet sender
|
// The mirrored TCP port is the one from the ping packet.
|
||||||
IP: test.remoteaddr.Addr().AsSlice(),
|
wantTo := v4wire.NewEndpoint(test.remoteaddr, testRemote.TCP)
|
||||||
UDP: test.remoteaddr.Port(),
|
|
||||||
// The mirrored TCP port is the one from the ping packet
|
|
||||||
TCP: testRemote.TCP,
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(p.To, wantTo) {
|
if !reflect.DeepEqual(p.To, wantTo) {
|
||||||
t.Errorf("got pong.To %v, want %v", p.To, wantTo)
|
t.Errorf("got pong.To %v, want %v", p.To, wantTo)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Remote is unknown, the table pings back.
|
// Remote is unknown, the table pings back.
|
||||||
test.waitPacketOut(func(p *v4wire.Ping, to *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Ping, to netip.AddrPort, hash []byte) {
|
||||||
if !reflect.DeepEqual(p.From, test.udp.ourEndpoint()) {
|
if !reflect.DeepEqual(p.From, test.udp.ourEndpoint()) {
|
||||||
t.Errorf("got ping.From %#v, want %#v", p.From, test.udp.ourEndpoint())
|
t.Errorf("got ping.From %#v, want %#v", p.From, test.udp.ourEndpoint())
|
||||||
}
|
}
|
||||||
wantTo := v4wire.Endpoint{
|
// The mirrored UDP address is the UDP packet sender.
|
||||||
// The mirrored UDP address is the UDP packet sender.
|
wantTo := v4wire.NewEndpoint(test.remoteaddr, 0)
|
||||||
IP: test.remoteaddr.Addr().AsSlice(),
|
|
||||||
UDP: test.remoteaddr.Port(),
|
|
||||||
TCP: 0,
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(p.To, wantTo) {
|
if !reflect.DeepEqual(p.To, wantTo) {
|
||||||
t.Errorf("got ping.To %v, want %v", p.To, wantTo)
|
t.Errorf("got ping.To %v, want %v", p.To, wantTo)
|
||||||
}
|
}
|
||||||
|
|
@ -448,7 +439,7 @@ func TestUDPv4_successfulPing(t *testing.T) {
|
||||||
t.Errorf("node has wrong IP: got %v, want: %v", n.IP(), test.remoteaddr.Addr())
|
t.Errorf("node has wrong IP: got %v, want: %v", n.IP(), test.remoteaddr.Addr())
|
||||||
}
|
}
|
||||||
if n.UDP() != int(test.remoteaddr.Port()) {
|
if n.UDP() != int(test.remoteaddr.Port()) {
|
||||||
t.Errorf("node has wrong UDP port: got %v, want: %v", n.UDP(), test.remoteaddr.Port)
|
t.Errorf("node has wrong UDP port: got %v, want: %v", n.UDP(), test.remoteaddr.Port())
|
||||||
}
|
}
|
||||||
if n.TCP() != int(testRemote.TCP) {
|
if n.TCP() != int(testRemote.TCP) {
|
||||||
t.Errorf("node has wrong TCP port: got %v, want: %v", n.TCP(), testRemote.TCP)
|
t.Errorf("node has wrong TCP port: got %v, want: %v", n.TCP(), testRemote.TCP)
|
||||||
|
|
@ -471,12 +462,12 @@ func TestUDPv4_EIP868(t *testing.T) {
|
||||||
|
|
||||||
// Perform endpoint proof and check for sequence number in packet tail.
|
// Perform endpoint proof and check for sequence number in packet tail.
|
||||||
test.packetIn(nil, &v4wire.Ping{Expiration: futureExp})
|
test.packetIn(nil, &v4wire.Ping{Expiration: futureExp})
|
||||||
test.waitPacketOut(func(p *v4wire.Pong, addr *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Pong, addr netip.AddrPort, hash []byte) {
|
||||||
if p.ENRSeq != wantNode.Seq() {
|
if p.ENRSeq != wantNode.Seq() {
|
||||||
t.Errorf("wrong sequence number in pong: %d, want %d", p.ENRSeq, wantNode.Seq())
|
t.Errorf("wrong sequence number in pong: %d, want %d", p.ENRSeq, wantNode.Seq())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
test.waitPacketOut(func(p *v4wire.Ping, addr *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.Ping, addr netip.AddrPort, hash []byte) {
|
||||||
if p.ENRSeq != wantNode.Seq() {
|
if p.ENRSeq != wantNode.Seq() {
|
||||||
t.Errorf("wrong sequence number in ping: %d, want %d", p.ENRSeq, wantNode.Seq())
|
t.Errorf("wrong sequence number in ping: %d, want %d", p.ENRSeq, wantNode.Seq())
|
||||||
}
|
}
|
||||||
|
|
@ -485,7 +476,7 @@ func TestUDPv4_EIP868(t *testing.T) {
|
||||||
|
|
||||||
// Request should work now.
|
// Request should work now.
|
||||||
test.packetIn(nil, &v4wire.ENRRequest{Expiration: futureExp})
|
test.packetIn(nil, &v4wire.ENRRequest{Expiration: futureExp})
|
||||||
test.waitPacketOut(func(p *v4wire.ENRResponse, addr *net.UDPAddr, hash []byte) {
|
test.waitPacketOut(func(p *v4wire.ENRResponse, addr netip.AddrPort, hash []byte) {
|
||||||
n, err := enode.New(enode.ValidSchemes, &p.Record)
|
n, err := enode.New(enode.ValidSchemes, &p.Record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("invalid record: %v", err)
|
t.Fatalf("invalid record: %v", err)
|
||||||
|
|
@ -600,7 +591,7 @@ func newpipe() *dgramPipe {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteToUDP queues a datagram.
|
// WriteToUDP queues a datagram.
|
||||||
func (c *dgramPipe) WriteToUDP(b []byte, to *net.UDPAddr) (n int, err error) {
|
func (c *dgramPipe) WriteToUDPAddrPort(b []byte, to netip.AddrPort) (n int, err error) {
|
||||||
msg := make([]byte, len(b))
|
msg := make([]byte, len(b))
|
||||||
copy(msg, b)
|
copy(msg, b)
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
|
|
@ -608,20 +599,15 @@ func (c *dgramPipe) WriteToUDP(b []byte, to *net.UDPAddr) (n int, err error) {
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return 0, errors.New("closed")
|
return 0, errors.New("closed")
|
||||||
}
|
}
|
||||||
addr, ok := netip.AddrFromSlice(to.IP)
|
c.queue = append(c.queue, dgram{to, b})
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("invalid destination IP addr %v", to.IP))
|
|
||||||
}
|
|
||||||
addrPort := netip.AddrPortFrom(addr, uint16(to.Port))
|
|
||||||
c.queue = append(c.queue, dgram{addrPort, b})
|
|
||||||
c.cond.Signal()
|
c.cond.Signal()
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFromUDP just hangs until the pipe is closed.
|
// ReadFromUDP just hangs until the pipe is closed.
|
||||||
func (c *dgramPipe) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
|
func (c *dgramPipe) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error) {
|
||||||
<-c.closing
|
<-c.closing
|
||||||
return 0, nil, io.EOF
|
return 0, netip.AddrPort{}, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dgramPipe) Close() error {
|
func (c *dgramPipe) Close() error {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
|
@ -150,14 +151,15 @@ type Endpoint struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEndpoint creates an endpoint.
|
// NewEndpoint creates an endpoint.
|
||||||
func NewEndpoint(addr *net.UDPAddr, tcpPort uint16) Endpoint {
|
func NewEndpoint(addr netip.AddrPort, tcpPort uint16) Endpoint {
|
||||||
ip := net.IP{}
|
var ip net.IP
|
||||||
if ip4 := addr.IP.To4(); ip4 != nil {
|
if addr.Addr().Is4() || addr.Addr().Is4In6() {
|
||||||
ip = ip4
|
ip4 := addr.Addr().As4()
|
||||||
} else if ip6 := addr.IP.To16(); ip6 != nil {
|
ip = ip4[:]
|
||||||
ip = ip6
|
} else {
|
||||||
|
ip = addr.Addr().AsSlice()
|
||||||
}
|
}
|
||||||
return Endpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort}
|
return Endpoint{IP: ip, UDP: addr.Port(), TCP: tcpPort}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Packet interface {
|
type Packet interface {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package discover
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ func (t *talkSystem) register(protocol string, handler TalkRequestHandler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleRequest handles a talk request.
|
// handleRequest handles a talk request.
|
||||||
func (t *talkSystem) handleRequest(id enode.ID, addr *net.UDPAddr, req *v5wire.TalkRequest) {
|
func (t *talkSystem) handleRequest(id enode.ID, addr netip.AddrPort, req *v5wire.TalkRequest) {
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
handler, ok := t.handlers[req.Protocol]
|
handler, ok := t.handlers[req.Protocol]
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
|
@ -88,7 +89,8 @@ func (t *talkSystem) handleRequest(id enode.ID, addr *net.UDPAddr, req *v5wire.T
|
||||||
case <-t.slots:
|
case <-t.slots:
|
||||||
go func() {
|
go func() {
|
||||||
defer func() { t.slots <- struct{}{} }()
|
defer func() { t.slots <- struct{}{} }()
|
||||||
respMessage := handler(id, addr, req.Message)
|
udpAddr := &net.UDPAddr{IP: addr.Addr().AsSlice(), Port: int(addr.Port())}
|
||||||
|
respMessage := handler(id, udpAddr, req.Message)
|
||||||
resp := &v5wire.TalkResponse{ReqID: req.ReqID, Message: respMessage}
|
resp := &v5wire.TalkResponse{ReqID: req.ReqID, Message: respMessage}
|
||||||
t.transport.sendFromAnotherThread(id, addr, resp)
|
t.transport.sendFromAnotherThread(id, addr, resp)
|
||||||
}()
|
}()
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -101,14 +102,14 @@ type UDPv5 struct {
|
||||||
|
|
||||||
type sendRequest struct {
|
type sendRequest struct {
|
||||||
destID enode.ID
|
destID enode.ID
|
||||||
destAddr *net.UDPAddr
|
destAddr netip.AddrPort
|
||||||
msg v5wire.Packet
|
msg v5wire.Packet
|
||||||
}
|
}
|
||||||
|
|
||||||
// callV5 represents a remote procedure call against another node.
|
// callV5 represents a remote procedure call against another node.
|
||||||
type callV5 struct {
|
type callV5 struct {
|
||||||
id enode.ID
|
id enode.ID
|
||||||
addr *net.UDPAddr
|
addr netip.AddrPort
|
||||||
node *enode.Node // This is required to perform handshakes.
|
node *enode.Node // This is required to perform handshakes.
|
||||||
|
|
||||||
packet v5wire.Packet
|
packet v5wire.Packet
|
||||||
|
|
@ -266,7 +267,7 @@ func (t *UDPv5) TalkRequest(n *enode.Node, protocol string, request []byte) ([]b
|
||||||
}
|
}
|
||||||
|
|
||||||
// TalkRequestToID sends a talk request to a node and waits for a response.
|
// TalkRequestToID sends a talk request to a node and waits for a response.
|
||||||
func (t *UDPv5) TalkRequestToID(id enode.ID, addr *net.UDPAddr, protocol string, request []byte) ([]byte, error) {
|
func (t *UDPv5) TalkRequestToID(id enode.ID, addr netip.AddrPort, protocol string, request []byte) ([]byte, error) {
|
||||||
req := &v5wire.TalkRequest{Protocol: protocol, Message: request}
|
req := &v5wire.TalkRequest{Protocol: protocol, Message: request}
|
||||||
resp := t.callToID(id, addr, v5wire.TalkResponseMsg, req)
|
resp := t.callToID(id, addr, v5wire.TalkResponseMsg, req)
|
||||||
defer t.callDone(resp)
|
defer t.callDone(resp)
|
||||||
|
|
@ -427,7 +428,7 @@ func (t *UDPv5) verifyResponseNode(c *callV5, r *enr.Record, distances []uint, s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := netutil.CheckRelayIP(c.addr.IP, node.IP()); err != nil {
|
if err := netutil.CheckRelayIP(c.addr.Addr().AsSlice(), node.IP()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if t.netrestrict != nil && !t.netrestrict.Contains(node.IP()) {
|
if t.netrestrict != nil && !t.netrestrict.Contains(node.IP()) {
|
||||||
|
|
@ -452,14 +453,14 @@ func (t *UDPv5) verifyResponseNode(c *callV5, r *enr.Record, distances []uint, s
|
||||||
// callToNode sends the given call and sets up a handler for response packets (of message
|
// callToNode sends the given call and sets up a handler for response packets (of message
|
||||||
// type responseType). Responses are dispatched to the call's response channel.
|
// type responseType). Responses are dispatched to the call's response channel.
|
||||||
func (t *UDPv5) callToNode(n *enode.Node, responseType byte, req v5wire.Packet) *callV5 {
|
func (t *UDPv5) callToNode(n *enode.Node, responseType byte, req v5wire.Packet) *callV5 {
|
||||||
addr := &net.UDPAddr{IP: n.IP(), Port: n.UDP()}
|
addr, _ := n.UDPEndpoint()
|
||||||
c := &callV5{id: n.ID(), addr: addr, node: n}
|
c := &callV5{id: n.ID(), addr: addr, node: n}
|
||||||
t.initCall(c, responseType, req)
|
t.initCall(c, responseType, req)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// callToID is like callToNode, but for cases where the node record is not available.
|
// callToID is like callToNode, but for cases where the node record is not available.
|
||||||
func (t *UDPv5) callToID(id enode.ID, addr *net.UDPAddr, responseType byte, req v5wire.Packet) *callV5 {
|
func (t *UDPv5) callToID(id enode.ID, addr netip.AddrPort, responseType byte, req v5wire.Packet) *callV5 {
|
||||||
c := &callV5{id: id, addr: addr}
|
c := &callV5{id: id, addr: addr}
|
||||||
t.initCall(c, responseType, req)
|
t.initCall(c, responseType, req)
|
||||||
return c
|
return c
|
||||||
|
|
@ -619,12 +620,12 @@ func (t *UDPv5) sendCall(c *callV5) {
|
||||||
|
|
||||||
// sendResponse sends a response packet to the given node.
|
// sendResponse sends a response packet to the given node.
|
||||||
// This doesn't trigger a handshake even if no keys are available.
|
// This doesn't trigger a handshake even if no keys are available.
|
||||||
func (t *UDPv5) sendResponse(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet) error {
|
func (t *UDPv5) sendResponse(toID enode.ID, toAddr netip.AddrPort, packet v5wire.Packet) error {
|
||||||
_, err := t.send(toID, toAddr, packet, nil)
|
_, err := t.send(toID, toAddr, packet, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv5) sendFromAnotherThread(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet) {
|
func (t *UDPv5) sendFromAnotherThread(toID enode.ID, toAddr netip.AddrPort, packet v5wire.Packet) {
|
||||||
select {
|
select {
|
||||||
case t.sendCh <- sendRequest{toID, toAddr, packet}:
|
case t.sendCh <- sendRequest{toID, toAddr, packet}:
|
||||||
case <-t.closeCtx.Done():
|
case <-t.closeCtx.Done():
|
||||||
|
|
@ -632,7 +633,7 @@ func (t *UDPv5) sendFromAnotherThread(toID enode.ID, toAddr *net.UDPAddr, packet
|
||||||
}
|
}
|
||||||
|
|
||||||
// send sends a packet to the given node.
|
// send sends a packet to the given node.
|
||||||
func (t *UDPv5) send(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet, c *v5wire.Whoareyou) (v5wire.Nonce, error) {
|
func (t *UDPv5) send(toID enode.ID, toAddr netip.AddrPort, packet v5wire.Packet, c *v5wire.Whoareyou) (v5wire.Nonce, error) {
|
||||||
addr := toAddr.String()
|
addr := toAddr.String()
|
||||||
t.logcontext = append(t.logcontext[:0], "id", toID, "addr", addr)
|
t.logcontext = append(t.logcontext[:0], "id", toID, "addr", addr)
|
||||||
t.logcontext = packet.AppendLogInfo(t.logcontext)
|
t.logcontext = packet.AppendLogInfo(t.logcontext)
|
||||||
|
|
@ -644,7 +645,7 @@ func (t *UDPv5) send(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet, c
|
||||||
return nonce, err
|
return nonce, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = t.conn.WriteToUDP(enc, toAddr)
|
_, err = t.conn.WriteToUDPAddrPort(enc, toAddr)
|
||||||
t.log.Trace(">> "+packet.Name(), t.logcontext...)
|
t.log.Trace(">> "+packet.Name(), t.logcontext...)
|
||||||
return nonce, err
|
return nonce, err
|
||||||
}
|
}
|
||||||
|
|
@ -655,7 +656,7 @@ func (t *UDPv5) readLoop() {
|
||||||
|
|
||||||
buf := make([]byte, maxPacketSize)
|
buf := make([]byte, maxPacketSize)
|
||||||
for range t.readNextCh {
|
for range t.readNextCh {
|
||||||
nbytes, from, err := t.conn.ReadFromUDP(buf)
|
nbytes, from, err := t.conn.ReadFromUDPAddrPort(buf)
|
||||||
if netutil.IsTemporaryError(err) {
|
if netutil.IsTemporaryError(err) {
|
||||||
// Ignore temporary read errors.
|
// Ignore temporary read errors.
|
||||||
t.log.Debug("Temporary UDP read error", "err", err)
|
t.log.Debug("Temporary UDP read error", "err", err)
|
||||||
|
|
@ -672,7 +673,7 @@ func (t *UDPv5) readLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// dispatchReadPacket sends a packet into the dispatch loop.
|
// dispatchReadPacket sends a packet into the dispatch loop.
|
||||||
func (t *UDPv5) dispatchReadPacket(from *net.UDPAddr, content []byte) bool {
|
func (t *UDPv5) dispatchReadPacket(from netip.AddrPort, content []byte) bool {
|
||||||
select {
|
select {
|
||||||
case t.packetInCh <- ReadPacket{content, from}:
|
case t.packetInCh <- ReadPacket{content, from}:
|
||||||
return true
|
return true
|
||||||
|
|
@ -682,7 +683,7 @@ func (t *UDPv5) dispatchReadPacket(from *net.UDPAddr, content []byte) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePacket decodes and processes an incoming packet from the network.
|
// handlePacket decodes and processes an incoming packet from the network.
|
||||||
func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error {
|
func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr netip.AddrPort) error {
|
||||||
addr := fromAddr.String()
|
addr := fromAddr.String()
|
||||||
fromID, fromNode, packet, err := t.codec.Decode(rawpacket, addr)
|
fromID, fromNode, packet, err := t.codec.Decode(rawpacket, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -712,13 +713,13 @@ func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleCallResponse dispatches a response packet to the call waiting for it.
|
// handleCallResponse dispatches a response packet to the call waiting for it.
|
||||||
func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr *net.UDPAddr, p v5wire.Packet) bool {
|
func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr netip.AddrPort, p v5wire.Packet) bool {
|
||||||
ac := t.activeCallByNode[fromID]
|
ac := t.activeCallByNode[fromID]
|
||||||
if ac == nil || !bytes.Equal(p.RequestID(), ac.reqid) {
|
if ac == nil || !bytes.Equal(p.RequestID(), ac.reqid) {
|
||||||
t.log.Debug(fmt.Sprintf("Unsolicited/late %s response", p.Name()), "id", fromID, "addr", fromAddr)
|
t.log.Debug(fmt.Sprintf("Unsolicited/late %s response", p.Name()), "id", fromID, "addr", fromAddr)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !fromAddr.IP.Equal(ac.addr.IP) || fromAddr.Port != ac.addr.Port {
|
if fromAddr != ac.addr {
|
||||||
t.log.Debug(fmt.Sprintf("%s from wrong endpoint", p.Name()), "id", fromID, "addr", fromAddr)
|
t.log.Debug(fmt.Sprintf("%s from wrong endpoint", p.Name()), "id", fromID, "addr", fromAddr)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -743,7 +744,7 @@ func (t *UDPv5) getNode(id enode.ID) *enode.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 *net.UDPAddr) {
|
func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort) {
|
||||||
switch p := p.(type) {
|
switch p := p.(type) {
|
||||||
case *v5wire.Unknown:
|
case *v5wire.Unknown:
|
||||||
t.handleUnknown(p, fromID, fromAddr)
|
t.handleUnknown(p, fromID, fromAddr)
|
||||||
|
|
@ -753,7 +754,9 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr *net.UDPAddr)
|
||||||
t.handlePing(p, fromID, fromAddr)
|
t.handlePing(p, fromID, fromAddr)
|
||||||
case *v5wire.Pong:
|
case *v5wire.Pong:
|
||||||
if t.handleCallResponse(fromID, fromAddr, p) {
|
if t.handleCallResponse(fromID, fromAddr, p) {
|
||||||
t.localNode.UDPEndpointStatement(fromAddr, &net.UDPAddr{IP: p.ToIP, Port: int(p.ToPort)})
|
fromUDPAddr := &net.UDPAddr{IP: fromAddr.Addr().AsSlice(), Port: int(fromAddr.Port())}
|
||||||
|
toUDPAddr := &net.UDPAddr{IP: p.ToIP, Port: int(p.ToPort)}
|
||||||
|
t.localNode.UDPEndpointStatement(fromUDPAddr, toUDPAddr)
|
||||||
}
|
}
|
||||||
case *v5wire.Findnode:
|
case *v5wire.Findnode:
|
||||||
t.handleFindnode(p, fromID, fromAddr)
|
t.handleFindnode(p, fromID, fromAddr)
|
||||||
|
|
@ -767,7 +770,7 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr *net.UDPAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleUnknown initiates a handshake by responding with WHOAREYOU.
|
// handleUnknown initiates a handshake by responding with WHOAREYOU.
|
||||||
func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr *net.UDPAddr) {
|
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 {
|
||||||
|
|
@ -783,7 +786,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// handleWhoareyou resends the active call as a handshake packet.
|
// handleWhoareyou resends the active call as a handshake packet.
|
||||||
func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr *net.UDPAddr) {
|
func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr netip.AddrPort) {
|
||||||
c, err := t.matchWithCall(fromID, p.Nonce)
|
c, err := t.matchWithCall(fromID, p.Nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.log.Debug("Invalid "+p.Name(), "addr", fromAddr, "err", err)
|
t.log.Debug("Invalid "+p.Name(), "addr", fromAddr, "err", err)
|
||||||
|
|
@ -817,32 +820,35 @@ func (t *UDPv5) matchWithCall(fromID enode.ID, nonce v5wire.Nonce) (*callV5, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePing sends a PONG response.
|
// handlePing sends a PONG response.
|
||||||
func (t *UDPv5) handlePing(p *v5wire.Ping, fromID enode.ID, fromAddr *net.UDPAddr) {
|
func (t *UDPv5) handlePing(p *v5wire.Ping, fromID enode.ID, fromAddr netip.AddrPort) {
|
||||||
remoteIP := fromAddr.IP
|
var remoteIP net.IP
|
||||||
// Handle IPv4 mapped IPv6 addresses in the
|
// Handle IPv4 mapped IPv6 addresses in the event the local node is binded
|
||||||
// event the local node is binded to an
|
// to an ipv6 interface.
|
||||||
// ipv6 interface.
|
if fromAddr.Addr().Is4() || fromAddr.Addr().Is4In6() {
|
||||||
if remoteIP.To4() != nil {
|
ip4 := fromAddr.Addr().As4()
|
||||||
remoteIP = remoteIP.To4()
|
remoteIP = ip4[:]
|
||||||
|
} else {
|
||||||
|
remoteIP = fromAddr.Addr().AsSlice()
|
||||||
}
|
}
|
||||||
t.sendResponse(fromID, fromAddr, &v5wire.Pong{
|
t.sendResponse(fromID, fromAddr, &v5wire.Pong{
|
||||||
ReqID: p.ReqID,
|
ReqID: p.ReqID,
|
||||||
ToIP: remoteIP,
|
ToIP: remoteIP,
|
||||||
ToPort: uint16(fromAddr.Port),
|
ToPort: fromAddr.Port(),
|
||||||
ENRSeq: t.localNode.Node().Seq(),
|
ENRSeq: t.localNode.Node().Seq(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleFindnode returns nodes to the requester.
|
// handleFindnode returns nodes to the requester.
|
||||||
func (t *UDPv5) handleFindnode(p *v5wire.Findnode, fromID enode.ID, fromAddr *net.UDPAddr) {
|
func (t *UDPv5) handleFindnode(p *v5wire.Findnode, fromID enode.ID, fromAddr netip.AddrPort) {
|
||||||
nodes := t.collectTableNodes(fromAddr.IP, p.Distances, findnodeResultLimit)
|
nodes := t.collectTableNodes(fromAddr.Addr(), p.Distances, findnodeResultLimit)
|
||||||
for _, resp := range packNodes(p.ReqID, nodes) {
|
for _, resp := range packNodes(p.ReqID, nodes) {
|
||||||
t.sendResponse(fromID, fromAddr, resp)
|
t.sendResponse(fromID, fromAddr, resp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectTableNodes creates a FINDNODE result set for the given distances.
|
// collectTableNodes creates a FINDNODE result set for the given distances.
|
||||||
func (t *UDPv5) collectTableNodes(rip net.IP, distances []uint, limit int) []*enode.Node {
|
func (t *UDPv5) collectTableNodes(rip netip.Addr, distances []uint, limit int) []*enode.Node {
|
||||||
|
ripSlice := rip.AsSlice()
|
||||||
var bn []*enode.Node
|
var bn []*enode.Node
|
||||||
var nodes []*enode.Node
|
var nodes []*enode.Node
|
||||||
var processed = make(map[uint]struct{})
|
var processed = make(map[uint]struct{})
|
||||||
|
|
@ -857,7 +863,7 @@ func (t *UDPv5) collectTableNodes(rip net.IP, distances []uint, limit int) []*en
|
||||||
for _, n := range t.tab.appendLiveNodes(dist, bn[:0]) {
|
for _, n := range t.tab.appendLiveNodes(dist, bn[:0]) {
|
||||||
// Apply some pre-checks to avoid sending invalid nodes.
|
// Apply some pre-checks to avoid sending invalid nodes.
|
||||||
// Note liveness is checked by appendLiveNodes.
|
// Note liveness is checked by appendLiveNodes.
|
||||||
if netutil.CheckRelayIP(rip, n.IP()) != nil {
|
if netutil.CheckRelayIP(ripSlice, n.IP()) != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ func TestUDPv5_pingHandling(t *testing.T) {
|
||||||
defer test.close()
|
defer test.close()
|
||||||
|
|
||||||
test.packetIn(&v5wire.Ping{ReqID: []byte("foo")})
|
test.packetIn(&v5wire.Ping{ReqID: []byte("foo")})
|
||||||
test.waitPacketOut(func(p *v5wire.Pong, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Pong, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if !bytes.Equal(p.ReqID, []byte("foo")) {
|
if !bytes.Equal(p.ReqID, []byte("foo")) {
|
||||||
t.Error("wrong request ID in response:", p.ReqID)
|
t.Error("wrong request ID in response:", p.ReqID)
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ func TestUDPv5_unknownPacket(t *testing.T) {
|
||||||
|
|
||||||
// Unknown packet from unknown node.
|
// Unknown packet from unknown node.
|
||||||
test.packetIn(&v5wire.Unknown{Nonce: nonce})
|
test.packetIn(&v5wire.Unknown{Nonce: nonce})
|
||||||
test.waitPacketOut(func(p *v5wire.Whoareyou, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
check(p, 0)
|
check(p, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ func TestUDPv5_unknownPacket(t *testing.T) {
|
||||||
test.table.addFoundNode(n, false)
|
test.table.addFoundNode(n, false)
|
||||||
|
|
||||||
test.packetIn(&v5wire.Unknown{Nonce: nonce})
|
test.packetIn(&v5wire.Unknown{Nonce: nonce})
|
||||||
test.waitPacketOut(func(p *v5wire.Whoareyou, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Whoareyou, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
check(p, n.Seq())
|
check(p, n.Seq())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +200,7 @@ func (test *udpV5Test) expectNodes(wantReqID []byte, wantTotal uint8, wantNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
test.waitPacketOut(func(p *v5wire.Nodes, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Nodes, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if !bytes.Equal(p.ReqID, wantReqID) {
|
if !bytes.Equal(p.ReqID, wantReqID) {
|
||||||
test.t.Fatalf("wrong request ID %v in response, want %v", p.ReqID, wantReqID)
|
test.t.Fatalf("wrong request ID %v in response, want %v", p.ReqID, wantReqID)
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +239,7 @@ func TestUDPv5_pingCall(t *testing.T) {
|
||||||
_, err := test.udp.ping(remote)
|
_, err := test.udp.ping(remote)
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {})
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, _ v5wire.Nonce) {})
|
||||||
if err := <-done; err != errTimeout {
|
if err := <-done; err != errTimeout {
|
||||||
t.Fatalf("want errTimeout, got %q", err)
|
t.Fatalf("want errTimeout, got %q", err)
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +249,7 @@ func TestUDPv5_pingCall(t *testing.T) {
|
||||||
_, err := test.udp.ping(remote)
|
_, err := test.udp.ping(remote)
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
test.packetInFrom(test.remotekey, test.remoteaddr, &v5wire.Pong{ReqID: p.ReqID})
|
test.packetInFrom(test.remotekey, test.remoteaddr, &v5wire.Pong{ReqID: p.ReqID})
|
||||||
})
|
})
|
||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
|
|
@ -261,8 +261,8 @@ func TestUDPv5_pingCall(t *testing.T) {
|
||||||
_, err := test.udp.ping(remote)
|
_, err := test.udp.ping(remote)
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
wrongAddr := &net.UDPAddr{IP: net.IP{33, 44, 55, 22}, Port: 10101}
|
wrongAddr := netip.MustParseAddrPort("33.44.55.22:10101")
|
||||||
test.packetInFrom(test.remotekey, wrongAddr, &v5wire.Pong{ReqID: p.ReqID})
|
test.packetInFrom(test.remotekey, wrongAddr, &v5wire.Pong{ReqID: p.ReqID})
|
||||||
})
|
})
|
||||||
if err := <-done; err != errTimeout {
|
if err := <-done; err != errTimeout {
|
||||||
|
|
@ -292,7 +292,7 @@ func TestUDPv5_findnodeCall(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Serve the responses:
|
// Serve the responses:
|
||||||
test.waitPacketOut(func(p *v5wire.Findnode, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Findnode, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if !reflect.DeepEqual(p.Distances, distances) {
|
if !reflect.DeepEqual(p.Distances, distances) {
|
||||||
t.Fatalf("wrong distances in request: %v", p.Distances)
|
t.Fatalf("wrong distances in request: %v", p.Distances)
|
||||||
}
|
}
|
||||||
|
|
@ -338,15 +338,15 @@ func TestUDPv5_callResend(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Ping answered by WHOAREYOU.
|
// Ping answered by WHOAREYOU.
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, nonce v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, nonce v5wire.Nonce) {
|
||||||
test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
|
test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
|
||||||
})
|
})
|
||||||
// Ping should be re-sent.
|
// Ping should be re-sent.
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
test.packetIn(&v5wire.Pong{ReqID: p.ReqID})
|
test.packetIn(&v5wire.Pong{ReqID: p.ReqID})
|
||||||
})
|
})
|
||||||
// Answer the other ping.
|
// Answer the other ping.
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
test.packetIn(&v5wire.Pong{ReqID: p.ReqID})
|
test.packetIn(&v5wire.Pong{ReqID: p.ReqID})
|
||||||
})
|
})
|
||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
|
|
@ -371,11 +371,11 @@ func TestUDPv5_multipleHandshakeRounds(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Ping answered by WHOAREYOU.
|
// Ping answered by WHOAREYOU.
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, nonce v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, nonce v5wire.Nonce) {
|
||||||
test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
|
test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
|
||||||
})
|
})
|
||||||
// Ping answered by WHOAREYOU again.
|
// Ping answered by WHOAREYOU again.
|
||||||
test.waitPacketOut(func(p *v5wire.Ping, addr *net.UDPAddr, nonce v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Ping, addr netip.AddrPort, nonce v5wire.Nonce) {
|
||||||
test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
|
test.packetIn(&v5wire.Whoareyou{Nonce: nonce})
|
||||||
})
|
})
|
||||||
if err := <-done; err != errTimeout {
|
if err := <-done; err != errTimeout {
|
||||||
|
|
@ -402,7 +402,7 @@ func TestUDPv5_callTimeoutReset(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Serve two responses, slowly.
|
// Serve two responses, slowly.
|
||||||
test.waitPacketOut(func(p *v5wire.Findnode, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Findnode, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
time.Sleep(respTimeout - 50*time.Millisecond)
|
time.Sleep(respTimeout - 50*time.Millisecond)
|
||||||
test.packetIn(&v5wire.Nodes{
|
test.packetIn(&v5wire.Nodes{
|
||||||
ReqID: p.ReqID,
|
ReqID: p.ReqID,
|
||||||
|
|
@ -440,7 +440,7 @@ func TestUDPv5_talkHandling(t *testing.T) {
|
||||||
Protocol: "test",
|
Protocol: "test",
|
||||||
Message: []byte("test request"),
|
Message: []byte("test request"),
|
||||||
})
|
})
|
||||||
test.waitPacketOut(func(p *v5wire.TalkResponse, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.TalkResponse, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if !bytes.Equal(p.ReqID, []byte("foo")) {
|
if !bytes.Equal(p.ReqID, []byte("foo")) {
|
||||||
t.Error("wrong request ID in response:", p.ReqID)
|
t.Error("wrong request ID in response:", p.ReqID)
|
||||||
}
|
}
|
||||||
|
|
@ -459,7 +459,7 @@ func TestUDPv5_talkHandling(t *testing.T) {
|
||||||
Protocol: "wrong",
|
Protocol: "wrong",
|
||||||
Message: []byte("test request"),
|
Message: []byte("test request"),
|
||||||
})
|
})
|
||||||
test.waitPacketOut(func(p *v5wire.TalkResponse, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.TalkResponse, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if !bytes.Equal(p.ReqID, []byte("2")) {
|
if !bytes.Equal(p.ReqID, []byte("2")) {
|
||||||
t.Error("wrong request ID in response:", p.ReqID)
|
t.Error("wrong request ID in response:", p.ReqID)
|
||||||
}
|
}
|
||||||
|
|
@ -486,7 +486,7 @@ func TestUDPv5_talkRequest(t *testing.T) {
|
||||||
_, err := test.udp.TalkRequest(remote, "test", []byte("test request"))
|
_, err := test.udp.TalkRequest(remote, "test", []byte("test request"))
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.TalkRequest, addr *net.UDPAddr, _ v5wire.Nonce) {})
|
test.waitPacketOut(func(p *v5wire.TalkRequest, addr netip.AddrPort, _ v5wire.Nonce) {})
|
||||||
if err := <-done; err != errTimeout {
|
if err := <-done; err != errTimeout {
|
||||||
t.Fatalf("want errTimeout, got %q", err)
|
t.Fatalf("want errTimeout, got %q", err)
|
||||||
}
|
}
|
||||||
|
|
@ -496,7 +496,7 @@ func TestUDPv5_talkRequest(t *testing.T) {
|
||||||
_, err := test.udp.TalkRequest(remote, "test", []byte("test request"))
|
_, err := test.udp.TalkRequest(remote, "test", []byte("test request"))
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.TalkRequest, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.TalkRequest, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if p.Protocol != "test" {
|
if p.Protocol != "test" {
|
||||||
t.Errorf("wrong protocol ID in talk request: %q", p.Protocol)
|
t.Errorf("wrong protocol ID in talk request: %q", p.Protocol)
|
||||||
}
|
}
|
||||||
|
|
@ -517,7 +517,7 @@ func TestUDPv5_talkRequest(t *testing.T) {
|
||||||
_, err := test.udp.TalkRequestToID(remote.ID(), test.remoteaddr, "test", []byte("test request 2"))
|
_, err := test.udp.TalkRequestToID(remote.ID(), test.remoteaddr, "test", []byte("test request 2"))
|
||||||
done <- err
|
done <- err
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.TalkRequest, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.TalkRequest, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if p.Protocol != "test" {
|
if p.Protocol != "test" {
|
||||||
t.Errorf("wrong protocol ID in talk request: %q", p.Protocol)
|
t.Errorf("wrong protocol ID in talk request: %q", p.Protocol)
|
||||||
}
|
}
|
||||||
|
|
@ -584,7 +584,8 @@ func TestUDPv5_lookup(t *testing.T) {
|
||||||
for d, nn := range lookupTestnet.dists {
|
for d, nn := range lookupTestnet.dists {
|
||||||
for i, key := range nn {
|
for i, key := range nn {
|
||||||
n := lookupTestnet.node(d, i)
|
n := lookupTestnet.node(d, i)
|
||||||
test.getNode(key, &net.UDPAddr{IP: n.IP(), Port: n.UDP()})
|
addr, _ := n.UDPEndpoint()
|
||||||
|
test.getNode(key, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,11 +654,8 @@ func TestUDPv5_PingWithIPV4MappedAddress(t *testing.T) {
|
||||||
test := newUDPV5Test(t)
|
test := newUDPV5Test(t)
|
||||||
defer test.close()
|
defer test.close()
|
||||||
|
|
||||||
rawIP := net.IPv4(0xFF, 0x12, 0x33, 0xE5)
|
rawIP := netip.AddrFrom4([4]byte{0xFF, 0x12, 0x33, 0xE5})
|
||||||
test.remoteaddr = &net.UDPAddr{
|
test.remoteaddr = netip.AddrPortFrom(netip.AddrFrom16(rawIP.As16()), 0)
|
||||||
IP: rawIP.To16(),
|
|
||||||
Port: 0,
|
|
||||||
}
|
|
||||||
remote := test.getNode(test.remotekey, test.remoteaddr).Node()
|
remote := test.getNode(test.remotekey, test.remoteaddr).Node()
|
||||||
done := make(chan struct{}, 1)
|
done := make(chan struct{}, 1)
|
||||||
|
|
||||||
|
|
@ -666,14 +664,14 @@ func TestUDPv5_PingWithIPV4MappedAddress(t *testing.T) {
|
||||||
test.udp.handlePing(&v5wire.Ping{ENRSeq: 1}, remote.ID(), test.remoteaddr)
|
test.udp.handlePing(&v5wire.Ping{ENRSeq: 1}, remote.ID(), test.remoteaddr)
|
||||||
done <- struct{}{}
|
done <- struct{}{}
|
||||||
}()
|
}()
|
||||||
test.waitPacketOut(func(p *v5wire.Pong, addr *net.UDPAddr, _ v5wire.Nonce) {
|
test.waitPacketOut(func(p *v5wire.Pong, addr netip.AddrPort, _ v5wire.Nonce) {
|
||||||
if len(p.ToIP) == net.IPv6len {
|
if len(p.ToIP) == net.IPv6len {
|
||||||
t.Error("Received untruncated ip address")
|
t.Error("Received untruncated ip address")
|
||||||
}
|
}
|
||||||
if len(p.ToIP) != net.IPv4len {
|
if len(p.ToIP) != net.IPv4len {
|
||||||
t.Errorf("Received ip address with incorrect length: %d", len(p.ToIP))
|
t.Errorf("Received ip address with incorrect length: %d", len(p.ToIP))
|
||||||
}
|
}
|
||||||
if !p.ToIP.Equal(rawIP) {
|
if !p.ToIP.Equal(rawIP.AsSlice()) {
|
||||||
t.Errorf("Received incorrect ip address: wanted %s but received %s", rawIP.String(), p.ToIP.String())
|
t.Errorf("Received incorrect ip address: wanted %s but received %s", rawIP.String(), p.ToIP.String())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -751,9 +749,9 @@ func newUDPV5Test(t *testing.T) *udpV5Test {
|
||||||
pipe: newpipe(),
|
pipe: newpipe(),
|
||||||
localkey: newkey(),
|
localkey: newkey(),
|
||||||
remotekey: newkey(),
|
remotekey: newkey(),
|
||||||
remoteaddr: &net.UDPAddr{IP: net.IP{10, 0, 1, 99}, Port: 30303},
|
remoteaddr: netip.MustParseAddrPort("10.0.1.99:30303"),
|
||||||
nodesByID: make(map[enode.ID]*enode.LocalNode),
|
nodesByID: make(map[enode.ID]*enode.LocalNode),
|
||||||
nodesByIP: make(map[string]*enode.LocalNode),
|
nodesByIP: make(map[netip.Addr]*enode.LocalNode),
|
||||||
}
|
}
|
||||||
test.db, _ = enode.OpenDB("")
|
test.db, _ = enode.OpenDB("")
|
||||||
ln := enode.NewLocalNode(test.db, test.localkey)
|
ln := enode.NewLocalNode(test.db, test.localkey)
|
||||||
|
|
@ -804,12 +802,12 @@ func (test *udpV5Test) getNode(key *ecdsa.PrivateKey, addr netip.AddrPort) *enod
|
||||||
ln.Set(enr.UDP(addr.Port()))
|
ln.Set(enr.UDP(addr.Port()))
|
||||||
test.nodesByID[id] = ln
|
test.nodesByID[id] = ln
|
||||||
}
|
}
|
||||||
test.nodesByIP[string(addr.Addr().String())] = ln
|
test.nodesByIP[addr.Addr()] = ln
|
||||||
return ln
|
return ln
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitPacketOut waits for the next output packet and handles it using the given 'validate'
|
// waitPacketOut waits for the next output packet and handles it using the given 'validate'
|
||||||
// function. The function must be of type func (X, *net.UDPAddr, v5wire.Nonce) where X is
|
// function. The function must be of type func (X, netip.AddrPort, v5wire.Nonce) where X is
|
||||||
// assignable to packetV5.
|
// assignable to packetV5.
|
||||||
func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) {
|
func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) {
|
||||||
test.t.Helper()
|
test.t.Helper()
|
||||||
|
|
@ -825,7 +823,7 @@ func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) {
|
||||||
test.t.Fatalf("timed out waiting for %v", exptype)
|
test.t.Fatalf("timed out waiting for %v", exptype)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
ln := test.nodesByIP[string(dgram.to.IP)]
|
ln := test.nodesByIP[dgram.to.Addr()]
|
||||||
if ln == nil {
|
if ln == nil {
|
||||||
test.t.Fatalf("attempt to send to non-existing node %v", &dgram.to)
|
test.t.Fatalf("attempt to send to non-existing node %v", &dgram.to)
|
||||||
return false
|
return false
|
||||||
|
|
@ -840,7 +838,7 @@ func (test *udpV5Test) waitPacketOut(validate interface{}) (closed bool) {
|
||||||
test.t.Errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
|
test.t.Errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
fn.Call([]reflect.Value{reflect.ValueOf(p), reflect.ValueOf(&dgram.to), reflect.ValueOf(frame.AuthTag)})
|
fn.Call([]reflect.Value{reflect.ValueOf(p), reflect.ValueOf(dgram.to), reflect.ValueOf(frame.AuthTag)})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue