github.com/theQRL/go-zond@v0.1.1/p2p/discover/v5_udp.go (about)

     1  // Copyright 2020 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package discover
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"crypto/ecdsa"
    23  	crand "crypto/rand"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"net"
    28  	"sync"
    29  	"time"
    30  
    31  	"github.com/theQRL/go-zond/common/mclock"
    32  	"github.com/theQRL/go-zond/log"
    33  	"github.com/theQRL/go-zond/p2p/discover/v5wire"
    34  	"github.com/theQRL/go-zond/p2p/enode"
    35  	"github.com/theQRL/go-zond/p2p/enr"
    36  	"github.com/theQRL/go-zond/p2p/netutil"
    37  )
    38  
    39  const (
    40  	lookupRequestLimit      = 3  // max requests against a single node during lookup
    41  	findnodeResultLimit     = 16 // applies in FINDNODE handler
    42  	totalNodesResponseLimit = 5  // applies in waitForNodes
    43  
    44  	respTimeoutV5 = 700 * time.Millisecond
    45  )
    46  
    47  // codecV5 is implemented by v5wire.Codec (and testCodec).
    48  //
    49  // The UDPv5 transport is split into two objects: the codec object deals with
    50  // encoding/decoding and with the handshake; the UDPv5 object handles higher-level concerns.
    51  type codecV5 interface {
    52  	// Encode encodes a packet.
    53  	Encode(enode.ID, string, v5wire.Packet, *v5wire.Whoareyou) ([]byte, v5wire.Nonce, error)
    54  
    55  	// Decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
    56  	// The *enode.Node return value is non-nil when the input contains a handshake response.
    57  	Decode([]byte, string) (enode.ID, *enode.Node, v5wire.Packet, error)
    58  }
    59  
    60  // UDPv5 is the implementation of protocol version 5.
    61  type UDPv5 struct {
    62  	// static fields
    63  	conn         UDPConn
    64  	tab          *Table
    65  	netrestrict  *netutil.Netlist
    66  	priv         *ecdsa.PrivateKey
    67  	localNode    *enode.LocalNode
    68  	db           *enode.DB
    69  	log          log.Logger
    70  	clock        mclock.Clock
    71  	validSchemes enr.IdentityScheme
    72  
    73  	// misc buffers used during message handling
    74  	logcontext []interface{}
    75  
    76  	// talkreq handler registry
    77  	talk *talkSystem
    78  
    79  	// channels into dispatch
    80  	packetInCh    chan ReadPacket
    81  	readNextCh    chan struct{}
    82  	callCh        chan *callV5
    83  	callDoneCh    chan *callV5
    84  	respTimeoutCh chan *callTimeout
    85  	sendCh        chan sendRequest
    86  	unhandled     chan<- ReadPacket
    87  
    88  	// state of dispatch
    89  	codec            codecV5
    90  	activeCallByNode map[enode.ID]*callV5
    91  	activeCallByAuth map[v5wire.Nonce]*callV5
    92  	callQueue        map[enode.ID][]*callV5
    93  
    94  	// shutdown stuff
    95  	closeOnce      sync.Once
    96  	closeCtx       context.Context
    97  	cancelCloseCtx context.CancelFunc
    98  	wg             sync.WaitGroup
    99  }
   100  
   101  type sendRequest struct {
   102  	destID   enode.ID
   103  	destAddr *net.UDPAddr
   104  	msg      v5wire.Packet
   105  }
   106  
   107  // callV5 represents a remote procedure call against another node.
   108  type callV5 struct {
   109  	id   enode.ID
   110  	addr *net.UDPAddr
   111  	node *enode.Node // This is required to perform handshakes.
   112  
   113  	packet       v5wire.Packet
   114  	responseType byte // expected packet type of response
   115  	reqid        []byte
   116  	ch           chan v5wire.Packet // responses sent here
   117  	err          chan error         // errors sent here
   118  
   119  	// Valid for active calls only:
   120  	nonce          v5wire.Nonce      // nonce of request packet
   121  	handshakeCount int               // # times we attempted handshake for this call
   122  	challenge      *v5wire.Whoareyou // last sent handshake challenge
   123  	timeout        mclock.Timer
   124  }
   125  
   126  // callTimeout is the response timeout event of a call.
   127  type callTimeout struct {
   128  	c     *callV5
   129  	timer mclock.Timer
   130  }
   131  
   132  // ListenV5 listens on the given connection.
   133  func ListenV5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) {
   134  	t, err := newUDPv5(conn, ln, cfg)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	go t.tab.loop()
   139  	t.wg.Add(2)
   140  	go t.readLoop()
   141  	go t.dispatch()
   142  	return t, nil
   143  }
   144  
   145  // newUDPv5 creates a UDPv5 transport, but doesn't start any goroutines.
   146  func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) {
   147  	closeCtx, cancelCloseCtx := context.WithCancel(context.Background())
   148  	cfg = cfg.withDefaults()
   149  	t := &UDPv5{
   150  		// static fields
   151  		conn:         newMeteredConn(conn),
   152  		localNode:    ln,
   153  		db:           ln.Database(),
   154  		netrestrict:  cfg.NetRestrict,
   155  		priv:         cfg.PrivateKey,
   156  		log:          cfg.Log,
   157  		validSchemes: cfg.ValidSchemes,
   158  		clock:        cfg.Clock,
   159  		// channels into dispatch
   160  		packetInCh:    make(chan ReadPacket, 1),
   161  		readNextCh:    make(chan struct{}, 1),
   162  		callCh:        make(chan *callV5),
   163  		callDoneCh:    make(chan *callV5),
   164  		sendCh:        make(chan sendRequest),
   165  		respTimeoutCh: make(chan *callTimeout),
   166  		unhandled:     cfg.Unhandled,
   167  		// state of dispatch
   168  		codec:            v5wire.NewCodec(ln, cfg.PrivateKey, cfg.Clock, cfg.V5ProtocolID),
   169  		activeCallByNode: make(map[enode.ID]*callV5),
   170  		activeCallByAuth: make(map[v5wire.Nonce]*callV5),
   171  		callQueue:        make(map[enode.ID][]*callV5),
   172  		// shutdown
   173  		closeCtx:       closeCtx,
   174  		cancelCloseCtx: cancelCloseCtx,
   175  	}
   176  	t.talk = newTalkSystem(t)
   177  	tab, err := newMeteredTable(t, t.db, cfg)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	t.tab = tab
   182  	return t, nil
   183  }
   184  
   185  // Self returns the local node record.
   186  func (t *UDPv5) Self() *enode.Node {
   187  	return t.localNode.Node()
   188  }
   189  
   190  // Close shuts down packet processing.
   191  func (t *UDPv5) Close() {
   192  	t.closeOnce.Do(func() {
   193  		t.cancelCloseCtx()
   194  		t.conn.Close()
   195  		t.talk.wait()
   196  		t.wg.Wait()
   197  		t.tab.close()
   198  	})
   199  }
   200  
   201  // Ping sends a ping message to the given node.
   202  func (t *UDPv5) Ping(n *enode.Node) error {
   203  	_, err := t.ping(n)
   204  	return err
   205  }
   206  
   207  // Resolve searches for a specific node with the given ID and tries to get the most recent
   208  // version of the node record for it. It returns n if the node could not be resolved.
   209  func (t *UDPv5) Resolve(n *enode.Node) *enode.Node {
   210  	if intable := t.tab.getNode(n.ID()); intable != nil && intable.Seq() > n.Seq() {
   211  		n = intable
   212  	}
   213  	// Try asking directly. This works if the node is still responding on the endpoint we have.
   214  	if resp, err := t.RequestENR(n); err == nil {
   215  		return resp
   216  	}
   217  	// Otherwise do a network lookup.
   218  	result := t.Lookup(n.ID())
   219  	for _, rn := range result {
   220  		if rn.ID() == n.ID() && rn.Seq() > n.Seq() {
   221  			return rn
   222  		}
   223  	}
   224  	return n
   225  }
   226  
   227  // AllNodes returns all the nodes stored in the local table.
   228  func (t *UDPv5) AllNodes() []*enode.Node {
   229  	t.tab.mutex.Lock()
   230  	defer t.tab.mutex.Unlock()
   231  	nodes := make([]*enode.Node, 0)
   232  
   233  	for _, b := range &t.tab.buckets {
   234  		for _, n := range b.entries {
   235  			nodes = append(nodes, unwrapNode(n))
   236  		}
   237  	}
   238  	return nodes
   239  }
   240  
   241  // LocalNode returns the current local node running the
   242  // protocol.
   243  func (t *UDPv5) LocalNode() *enode.LocalNode {
   244  	return t.localNode
   245  }
   246  
   247  // RegisterTalkHandler adds a handler for 'talk requests'. The handler function is called
   248  // whenever a request for the given protocol is received and should return the response
   249  // data or nil.
   250  func (t *UDPv5) RegisterTalkHandler(protocol string, handler TalkRequestHandler) {
   251  	t.talk.register(protocol, handler)
   252  }
   253  
   254  // TalkRequest sends a talk request to a node and waits for a response.
   255  func (t *UDPv5) TalkRequest(n *enode.Node, protocol string, request []byte) ([]byte, error) {
   256  	req := &v5wire.TalkRequest{Protocol: protocol, Message: request}
   257  	resp := t.callToNode(n, v5wire.TalkResponseMsg, req)
   258  	defer t.callDone(resp)
   259  	select {
   260  	case respMsg := <-resp.ch:
   261  		return respMsg.(*v5wire.TalkResponse).Message, nil
   262  	case err := <-resp.err:
   263  		return nil, err
   264  	}
   265  }
   266  
   267  // TalkRequestToID sends a talk request to a node and waits for a response.
   268  func (t *UDPv5) TalkRequestToID(id enode.ID, addr *net.UDPAddr, protocol string, request []byte) ([]byte, error) {
   269  	req := &v5wire.TalkRequest{Protocol: protocol, Message: request}
   270  	resp := t.callToID(id, addr, v5wire.TalkResponseMsg, req)
   271  	defer t.callDone(resp)
   272  	select {
   273  	case respMsg := <-resp.ch:
   274  		return respMsg.(*v5wire.TalkResponse).Message, nil
   275  	case err := <-resp.err:
   276  		return nil, err
   277  	}
   278  }
   279  
   280  // RandomNodes returns an iterator that finds random nodes in the DHT.
   281  func (t *UDPv5) RandomNodes() enode.Iterator {
   282  	if t.tab.len() == 0 {
   283  		// All nodes were dropped, refresh. The very first query will hit this
   284  		// case and run the bootstrapping logic.
   285  		<-t.tab.refresh()
   286  	}
   287  
   288  	return newLookupIterator(t.closeCtx, t.newRandomLookup)
   289  }
   290  
   291  // Lookup performs a recursive lookup for the given target.
   292  // It returns the closest nodes to target.
   293  func (t *UDPv5) Lookup(target enode.ID) []*enode.Node {
   294  	return t.newLookup(t.closeCtx, target).run()
   295  }
   296  
   297  // lookupRandom looks up a random target.
   298  // This is needed to satisfy the transport interface.
   299  func (t *UDPv5) lookupRandom() []*enode.Node {
   300  	return t.newRandomLookup(t.closeCtx).run()
   301  }
   302  
   303  // lookupSelf looks up our own node ID.
   304  // This is needed to satisfy the transport interface.
   305  func (t *UDPv5) lookupSelf() []*enode.Node {
   306  	return t.newLookup(t.closeCtx, t.Self().ID()).run()
   307  }
   308  
   309  func (t *UDPv5) newRandomLookup(ctx context.Context) *lookup {
   310  	var target enode.ID
   311  	crand.Read(target[:])
   312  	return t.newLookup(ctx, target)
   313  }
   314  
   315  func (t *UDPv5) newLookup(ctx context.Context, target enode.ID) *lookup {
   316  	return newLookup(ctx, t.tab, target, func(n *node) ([]*node, error) {
   317  		return t.lookupWorker(n, target)
   318  	})
   319  }
   320  
   321  // lookupWorker performs FINDNODE calls against a single node during lookup.
   322  func (t *UDPv5) lookupWorker(destNode *node, target enode.ID) ([]*node, error) {
   323  	var (
   324  		dists = lookupDistances(target, destNode.ID())
   325  		nodes = nodesByDistance{target: target}
   326  		err   error
   327  	)
   328  	var r []*enode.Node
   329  	r, err = t.findnode(unwrapNode(destNode), dists)
   330  	if errors.Is(err, errClosed) {
   331  		return nil, err
   332  	}
   333  	for _, n := range r {
   334  		if n.ID() != t.Self().ID() {
   335  			nodes.push(wrapNode(n), findnodeResultLimit)
   336  		}
   337  	}
   338  	return nodes.entries, err
   339  }
   340  
   341  // lookupDistances computes the distance parameter for FINDNODE calls to dest.
   342  // It chooses distances adjacent to logdist(target, dest), e.g. for a target
   343  // with logdist(target, dest) = 255 the result is [255, 256, 254].
   344  func lookupDistances(target, dest enode.ID) (dists []uint) {
   345  	td := enode.LogDist(target, dest)
   346  	dists = append(dists, uint(td))
   347  	for i := 1; len(dists) < lookupRequestLimit; i++ {
   348  		if td+i <= 256 {
   349  			dists = append(dists, uint(td+i))
   350  		}
   351  		if td-i > 0 {
   352  			dists = append(dists, uint(td-i))
   353  		}
   354  	}
   355  	return dists
   356  }
   357  
   358  // ping calls PING on a node and waits for a PONG response.
   359  func (t *UDPv5) ping(n *enode.Node) (uint64, error) {
   360  	req := &v5wire.Ping{ENRSeq: t.localNode.Node().Seq()}
   361  	resp := t.callToNode(n, v5wire.PongMsg, req)
   362  	defer t.callDone(resp)
   363  
   364  	select {
   365  	case pong := <-resp.ch:
   366  		return pong.(*v5wire.Pong).ENRSeq, nil
   367  	case err := <-resp.err:
   368  		return 0, err
   369  	}
   370  }
   371  
   372  // RequestENR requests n's record.
   373  func (t *UDPv5) RequestENR(n *enode.Node) (*enode.Node, error) {
   374  	nodes, err := t.findnode(n, []uint{0})
   375  	if err != nil {
   376  		return nil, err
   377  	}
   378  	if len(nodes) != 1 {
   379  		return nil, fmt.Errorf("%d nodes in response for distance zero", len(nodes))
   380  	}
   381  	return nodes[0], nil
   382  }
   383  
   384  // findnode calls FINDNODE on a node and waits for responses.
   385  func (t *UDPv5) findnode(n *enode.Node, distances []uint) ([]*enode.Node, error) {
   386  	resp := t.callToNode(n, v5wire.NodesMsg, &v5wire.Findnode{Distances: distances})
   387  	return t.waitForNodes(resp, distances)
   388  }
   389  
   390  // waitForNodes waits for NODES responses to the given call.
   391  func (t *UDPv5) waitForNodes(c *callV5, distances []uint) ([]*enode.Node, error) {
   392  	defer t.callDone(c)
   393  
   394  	var (
   395  		nodes           []*enode.Node
   396  		seen            = make(map[enode.ID]struct{})
   397  		received, total = 0, -1
   398  	)
   399  	for {
   400  		select {
   401  		case responseP := <-c.ch:
   402  			response := responseP.(*v5wire.Nodes)
   403  			for _, record := range response.Nodes {
   404  				node, err := t.verifyResponseNode(c, record, distances, seen)
   405  				if err != nil {
   406  					t.log.Debug("Invalid record in "+response.Name(), "id", c.node.ID(), "err", err)
   407  					continue
   408  				}
   409  				nodes = append(nodes, node)
   410  			}
   411  			if total == -1 {
   412  				total = min(int(response.RespCount), totalNodesResponseLimit)
   413  			}
   414  			if received++; received == total {
   415  				return nodes, nil
   416  			}
   417  		case err := <-c.err:
   418  			return nodes, err
   419  		}
   420  	}
   421  }
   422  
   423  // verifyResponseNode checks validity of a record in a NODES response.
   424  func (t *UDPv5) verifyResponseNode(c *callV5, r *enr.Record, distances []uint, seen map[enode.ID]struct{}) (*enode.Node, error) {
   425  	node, err := enode.New(t.validSchemes, r)
   426  	if err != nil {
   427  		return nil, err
   428  	}
   429  	if err := netutil.CheckRelayIP(c.addr.IP, node.IP()); err != nil {
   430  		return nil, err
   431  	}
   432  	if t.netrestrict != nil && !t.netrestrict.Contains(node.IP()) {
   433  		return nil, errors.New("not contained in netrestrict list")
   434  	}
   435  	if node.UDP() <= 1024 {
   436  		return nil, errLowPort
   437  	}
   438  	if distances != nil {
   439  		nd := enode.LogDist(c.id, node.ID())
   440  		if !containsUint(uint(nd), distances) {
   441  			return nil, errors.New("does not match any requested distance")
   442  		}
   443  	}
   444  	if _, ok := seen[node.ID()]; ok {
   445  		return nil, fmt.Errorf("duplicate record")
   446  	}
   447  	seen[node.ID()] = struct{}{}
   448  	return node, nil
   449  }
   450  
   451  func containsUint(x uint, xs []uint) bool {
   452  	for _, v := range xs {
   453  		if x == v {
   454  			return true
   455  		}
   456  	}
   457  	return false
   458  }
   459  
   460  // callToNode sends the given call and sets up a handler for response packets (of message
   461  // type responseType). Responses are dispatched to the call's response channel.
   462  func (t *UDPv5) callToNode(n *enode.Node, responseType byte, req v5wire.Packet) *callV5 {
   463  	addr := &net.UDPAddr{IP: n.IP(), Port: n.UDP()}
   464  	c := &callV5{id: n.ID(), addr: addr, node: n}
   465  	t.initCall(c, responseType, req)
   466  	return c
   467  }
   468  
   469  // callToID is like callToNode, but for cases where the node record is not available.
   470  func (t *UDPv5) callToID(id enode.ID, addr *net.UDPAddr, responseType byte, req v5wire.Packet) *callV5 {
   471  	c := &callV5{id: id, addr: addr}
   472  	t.initCall(c, responseType, req)
   473  	return c
   474  }
   475  
   476  func (t *UDPv5) initCall(c *callV5, responseType byte, packet v5wire.Packet) {
   477  	c.packet = packet
   478  	c.responseType = responseType
   479  	c.reqid = make([]byte, 8)
   480  	c.ch = make(chan v5wire.Packet, 1)
   481  	c.err = make(chan error, 1)
   482  	// Assign request ID.
   483  	crand.Read(c.reqid)
   484  	packet.SetRequestID(c.reqid)
   485  	// Send call to dispatch.
   486  	select {
   487  	case t.callCh <- c:
   488  	case <-t.closeCtx.Done():
   489  		c.err <- errClosed
   490  	}
   491  }
   492  
   493  // callDone tells dispatch that the active call is done.
   494  func (t *UDPv5) callDone(c *callV5) {
   495  	// This needs a loop because further responses may be incoming until the
   496  	// send to callDoneCh has completed. Such responses need to be discarded
   497  	// in order to avoid blocking the dispatch loop.
   498  	for {
   499  		select {
   500  		case <-c.ch:
   501  			// late response, discard.
   502  		case <-c.err:
   503  			// late error, discard.
   504  		case t.callDoneCh <- c:
   505  			return
   506  		case <-t.closeCtx.Done():
   507  			return
   508  		}
   509  	}
   510  }
   511  
   512  // dispatch runs in its own goroutine, handles incoming packets and deals with calls.
   513  //
   514  // For any destination node there is at most one 'active call', stored in the t.activeCall*
   515  // maps. A call is made active when it is sent. The active call can be answered by a
   516  // matching response, in which case c.ch receives the response; or by timing out, in which case
   517  // c.err receives the error. When the function that created the call signals the active
   518  // call is done through callDone, the next call from the call queue is started.
   519  //
   520  // Calls may also be answered by a WHOAREYOU packet referencing the call packet's authTag.
   521  // When that happens the call is simply re-sent to complete the handshake. We allow one
   522  // handshake attempt per call.
   523  func (t *UDPv5) dispatch() {
   524  	defer t.wg.Done()
   525  
   526  	// Arm first read.
   527  	t.readNextCh <- struct{}{}
   528  
   529  	for {
   530  		select {
   531  		case c := <-t.callCh:
   532  			t.callQueue[c.id] = append(t.callQueue[c.id], c)
   533  			t.sendNextCall(c.id)
   534  
   535  		case ct := <-t.respTimeoutCh:
   536  			active := t.activeCallByNode[ct.c.id]
   537  			if ct.c == active && ct.timer == active.timeout {
   538  				ct.c.err <- errTimeout
   539  			}
   540  
   541  		case c := <-t.callDoneCh:
   542  			active := t.activeCallByNode[c.id]
   543  			if active != c {
   544  				panic("BUG: callDone for inactive call")
   545  			}
   546  			c.timeout.Stop()
   547  			delete(t.activeCallByAuth, c.nonce)
   548  			delete(t.activeCallByNode, c.id)
   549  			t.sendNextCall(c.id)
   550  
   551  		case r := <-t.sendCh:
   552  			t.send(r.destID, r.destAddr, r.msg, nil)
   553  
   554  		case p := <-t.packetInCh:
   555  			t.handlePacket(p.Data, p.Addr)
   556  			// Arm next read.
   557  			t.readNextCh <- struct{}{}
   558  
   559  		case <-t.closeCtx.Done():
   560  			close(t.readNextCh)
   561  			for id, queue := range t.callQueue {
   562  				for _, c := range queue {
   563  					c.err <- errClosed
   564  				}
   565  				delete(t.callQueue, id)
   566  			}
   567  			for id, c := range t.activeCallByNode {
   568  				c.err <- errClosed
   569  				delete(t.activeCallByNode, id)
   570  				delete(t.activeCallByAuth, c.nonce)
   571  			}
   572  			return
   573  		}
   574  	}
   575  }
   576  
   577  // startResponseTimeout sets the response timer for a call.
   578  func (t *UDPv5) startResponseTimeout(c *callV5) {
   579  	if c.timeout != nil {
   580  		c.timeout.Stop()
   581  	}
   582  	var (
   583  		timer mclock.Timer
   584  		done  = make(chan struct{})
   585  	)
   586  	timer = t.clock.AfterFunc(respTimeoutV5, func() {
   587  		<-done
   588  		select {
   589  		case t.respTimeoutCh <- &callTimeout{c, timer}:
   590  		case <-t.closeCtx.Done():
   591  		}
   592  	})
   593  	c.timeout = timer
   594  	close(done)
   595  }
   596  
   597  // sendNextCall sends the next call in the call queue if there is no active call.
   598  func (t *UDPv5) sendNextCall(id enode.ID) {
   599  	queue := t.callQueue[id]
   600  	if len(queue) == 0 || t.activeCallByNode[id] != nil {
   601  		return
   602  	}
   603  	t.activeCallByNode[id] = queue[0]
   604  	t.sendCall(t.activeCallByNode[id])
   605  	if len(queue) == 1 {
   606  		delete(t.callQueue, id)
   607  	} else {
   608  		copy(queue, queue[1:])
   609  		t.callQueue[id] = queue[:len(queue)-1]
   610  	}
   611  }
   612  
   613  // sendCall encodes and sends a request packet to the call's recipient node.
   614  // This performs a handshake if needed.
   615  func (t *UDPv5) sendCall(c *callV5) {
   616  	// The call might have a nonce from a previous handshake attempt. Remove the entry for
   617  	// the old nonce because we're about to generate a new nonce for this call.
   618  	if c.nonce != (v5wire.Nonce{}) {
   619  		delete(t.activeCallByAuth, c.nonce)
   620  	}
   621  
   622  	newNonce, _ := t.send(c.id, c.addr, c.packet, c.challenge)
   623  	c.nonce = newNonce
   624  	t.activeCallByAuth[newNonce] = c
   625  	t.startResponseTimeout(c)
   626  }
   627  
   628  // sendResponse sends a response packet to the given node.
   629  // This doesn't trigger a handshake even if no keys are available.
   630  func (t *UDPv5) sendResponse(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet) error {
   631  	_, err := t.send(toID, toAddr, packet, nil)
   632  	return err
   633  }
   634  
   635  func (t *UDPv5) sendFromAnotherThread(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet) {
   636  	select {
   637  	case t.sendCh <- sendRequest{toID, toAddr, packet}:
   638  	case <-t.closeCtx.Done():
   639  	}
   640  }
   641  
   642  // send sends a packet to the given node.
   643  func (t *UDPv5) send(toID enode.ID, toAddr *net.UDPAddr, packet v5wire.Packet, c *v5wire.Whoareyou) (v5wire.Nonce, error) {
   644  	addr := toAddr.String()
   645  	t.logcontext = append(t.logcontext[:0], "id", toID, "addr", addr)
   646  	t.logcontext = packet.AppendLogInfo(t.logcontext)
   647  
   648  	enc, nonce, err := t.codec.Encode(toID, addr, packet, c)
   649  	if err != nil {
   650  		t.logcontext = append(t.logcontext, "err", err)
   651  		t.log.Warn(">> "+packet.Name(), t.logcontext...)
   652  		return nonce, err
   653  	}
   654  
   655  	_, err = t.conn.WriteToUDP(enc, toAddr)
   656  	t.log.Trace(">> "+packet.Name(), t.logcontext...)
   657  	return nonce, err
   658  }
   659  
   660  // readLoop runs in its own goroutine and reads packets from the network.
   661  func (t *UDPv5) readLoop() {
   662  	defer t.wg.Done()
   663  
   664  	buf := make([]byte, maxPacketSize)
   665  	for range t.readNextCh {
   666  		nbytes, from, err := t.conn.ReadFromUDP(buf)
   667  		if netutil.IsTemporaryError(err) {
   668  			// Ignore temporary read errors.
   669  			t.log.Debug("Temporary UDP read error", "err", err)
   670  			continue
   671  		} else if err != nil {
   672  			// Shut down the loop for permanent errors.
   673  			if !errors.Is(err, io.EOF) {
   674  				t.log.Debug("UDP read error", "err", err)
   675  			}
   676  			return
   677  		}
   678  		t.dispatchReadPacket(from, buf[:nbytes])
   679  	}
   680  }
   681  
   682  // dispatchReadPacket sends a packet into the dispatch loop.
   683  func (t *UDPv5) dispatchReadPacket(from *net.UDPAddr, content []byte) bool {
   684  	select {
   685  	case t.packetInCh <- ReadPacket{content, from}:
   686  		return true
   687  	case <-t.closeCtx.Done():
   688  		return false
   689  	}
   690  }
   691  
   692  // handlePacket decodes and processes an incoming packet from the network.
   693  func (t *UDPv5) handlePacket(rawpacket []byte, fromAddr *net.UDPAddr) error {
   694  	addr := fromAddr.String()
   695  	fromID, fromNode, packet, err := t.codec.Decode(rawpacket, addr)
   696  	if err != nil {
   697  		if t.unhandled != nil && v5wire.IsInvalidHeader(err) {
   698  			// The packet seems unrelated to discv5, send it to the next protocol.
   699  			// t.log.Trace("Unhandled discv5 packet", "id", fromID, "addr", addr, "err", err)
   700  			up := ReadPacket{Data: make([]byte, len(rawpacket)), Addr: fromAddr}
   701  			copy(up.Data, rawpacket)
   702  			t.unhandled <- up
   703  			return nil
   704  		}
   705  		t.log.Debug("Bad discv5 packet", "id", fromID, "addr", addr, "err", err)
   706  		return err
   707  	}
   708  	if fromNode != nil {
   709  		// Handshake succeeded, add to table.
   710  		t.tab.addSeenNode(wrapNode(fromNode))
   711  	}
   712  	if packet.Kind() != v5wire.WhoareyouPacket {
   713  		// WHOAREYOU logged separately to report errors.
   714  		t.logcontext = append(t.logcontext[:0], "id", fromID, "addr", addr)
   715  		t.logcontext = packet.AppendLogInfo(t.logcontext)
   716  		t.log.Trace("<< "+packet.Name(), t.logcontext...)
   717  	}
   718  	t.handle(packet, fromID, fromAddr)
   719  	return nil
   720  }
   721  
   722  // handleCallResponse dispatches a response packet to the call waiting for it.
   723  func (t *UDPv5) handleCallResponse(fromID enode.ID, fromAddr *net.UDPAddr, p v5wire.Packet) bool {
   724  	ac := t.activeCallByNode[fromID]
   725  	if ac == nil || !bytes.Equal(p.RequestID(), ac.reqid) {
   726  		t.log.Debug(fmt.Sprintf("Unsolicited/late %s response", p.Name()), "id", fromID, "addr", fromAddr)
   727  		return false
   728  	}
   729  	if !fromAddr.IP.Equal(ac.addr.IP) || fromAddr.Port != ac.addr.Port {
   730  		t.log.Debug(fmt.Sprintf("%s from wrong endpoint", p.Name()), "id", fromID, "addr", fromAddr)
   731  		return false
   732  	}
   733  	if p.Kind() != ac.responseType {
   734  		t.log.Debug(fmt.Sprintf("Wrong discv5 response type %s", p.Name()), "id", fromID, "addr", fromAddr)
   735  		return false
   736  	}
   737  	t.startResponseTimeout(ac)
   738  	ac.ch <- p
   739  	return true
   740  }
   741  
   742  // getNode looks for a node record in table and database.
   743  func (t *UDPv5) getNode(id enode.ID) *enode.Node {
   744  	if n := t.tab.getNode(id); n != nil {
   745  		return n
   746  	}
   747  	if n := t.localNode.Database().Node(id); n != nil {
   748  		return n
   749  	}
   750  	return nil
   751  }
   752  
   753  // handle processes incoming packets according to their message type.
   754  func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr *net.UDPAddr) {
   755  	switch p := p.(type) {
   756  	case *v5wire.Unknown:
   757  		t.handleUnknown(p, fromID, fromAddr)
   758  	case *v5wire.Whoareyou:
   759  		t.handleWhoareyou(p, fromID, fromAddr)
   760  	case *v5wire.Ping:
   761  		t.handlePing(p, fromID, fromAddr)
   762  	case *v5wire.Pong:
   763  		if t.handleCallResponse(fromID, fromAddr, p) {
   764  			t.localNode.UDPEndpointStatement(fromAddr, &net.UDPAddr{IP: p.ToIP, Port: int(p.ToPort)})
   765  		}
   766  	case *v5wire.Findnode:
   767  		t.handleFindnode(p, fromID, fromAddr)
   768  	case *v5wire.Nodes:
   769  		t.handleCallResponse(fromID, fromAddr, p)
   770  	case *v5wire.TalkRequest:
   771  		t.talk.handleRequest(fromID, fromAddr, p)
   772  	case *v5wire.TalkResponse:
   773  		t.handleCallResponse(fromID, fromAddr, p)
   774  	}
   775  }
   776  
   777  // handleUnknown initiates a handshake by responding with WHOAREYOU.
   778  func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr *net.UDPAddr) {
   779  	challenge := &v5wire.Whoareyou{Nonce: p.Nonce}
   780  	crand.Read(challenge.IDNonce[:])
   781  	if n := t.getNode(fromID); n != nil {
   782  		challenge.Node = n
   783  		challenge.RecordSeq = n.Seq()
   784  	}
   785  	t.sendResponse(fromID, fromAddr, challenge)
   786  }
   787  
   788  var (
   789  	errChallengeNoCall = errors.New("no matching call")
   790  	errChallengeTwice  = errors.New("second handshake")
   791  )
   792  
   793  // handleWhoareyou resends the active call as a handshake packet.
   794  func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr *net.UDPAddr) {
   795  	c, err := t.matchWithCall(fromID, p.Nonce)
   796  	if err != nil {
   797  		t.log.Debug("Invalid "+p.Name(), "addr", fromAddr, "err", err)
   798  		return
   799  	}
   800  
   801  	if c.node == nil {
   802  		// Can't perform handshake because we don't have the ENR.
   803  		t.log.Debug("Can't handle "+p.Name(), "addr", fromAddr, "err", "call has no ENR")
   804  		c.err <- errors.New("remote wants handshake, but call has no ENR")
   805  		return
   806  	}
   807  	// Resend the call that was answered by WHOAREYOU.
   808  	t.log.Trace("<< "+p.Name(), "id", c.node.ID(), "addr", fromAddr)
   809  	c.handshakeCount++
   810  	c.challenge = p
   811  	p.Node = c.node
   812  	t.sendCall(c)
   813  }
   814  
   815  // matchWithCall checks whether a handshake attempt matches the active call.
   816  func (t *UDPv5) matchWithCall(fromID enode.ID, nonce v5wire.Nonce) (*callV5, error) {
   817  	c := t.activeCallByAuth[nonce]
   818  	if c == nil {
   819  		return nil, errChallengeNoCall
   820  	}
   821  	if c.handshakeCount > 0 {
   822  		return nil, errChallengeTwice
   823  	}
   824  	return c, nil
   825  }
   826  
   827  // handlePing sends a PONG response.
   828  func (t *UDPv5) handlePing(p *v5wire.Ping, fromID enode.ID, fromAddr *net.UDPAddr) {
   829  	remoteIP := fromAddr.IP
   830  	// Handle IPv4 mapped IPv6 addresses in the
   831  	// event the local node is binded to an
   832  	// ipv6 interface.
   833  	if remoteIP.To4() != nil {
   834  		remoteIP = remoteIP.To4()
   835  	}
   836  	t.sendResponse(fromID, fromAddr, &v5wire.Pong{
   837  		ReqID:  p.ReqID,
   838  		ToIP:   remoteIP,
   839  		ToPort: uint16(fromAddr.Port),
   840  		ENRSeq: t.localNode.Node().Seq(),
   841  	})
   842  }
   843  
   844  // handleFindnode returns nodes to the requester.
   845  func (t *UDPv5) handleFindnode(p *v5wire.Findnode, fromID enode.ID, fromAddr *net.UDPAddr) {
   846  	nodes := t.collectTableNodes(fromAddr.IP, p.Distances, findnodeResultLimit)
   847  	for _, resp := range packNodes(p.ReqID, nodes) {
   848  		t.sendResponse(fromID, fromAddr, resp)
   849  	}
   850  }
   851  
   852  // collectTableNodes creates a FINDNODE result set for the given distances.
   853  func (t *UDPv5) collectTableNodes(rip net.IP, distances []uint, limit int) []*enode.Node {
   854  	var nodes []*enode.Node
   855  	var processed = make(map[uint]struct{})
   856  	for _, dist := range distances {
   857  		// Reject duplicate / invalid distances.
   858  		_, seen := processed[dist]
   859  		if seen || dist > 256 {
   860  			continue
   861  		}
   862  
   863  		// Get the nodes.
   864  		var bn []*enode.Node
   865  		if dist == 0 {
   866  			bn = []*enode.Node{t.Self()}
   867  		} else if dist <= 256 {
   868  			t.tab.mutex.Lock()
   869  			bn = unwrapNodes(t.tab.bucketAtDistance(int(dist)).entries)
   870  			t.tab.mutex.Unlock()
   871  		}
   872  		processed[dist] = struct{}{}
   873  
   874  		// Apply some pre-checks to avoid sending invalid nodes.
   875  		for _, n := range bn {
   876  			// TODO livenessChecks > 1
   877  			if netutil.CheckRelayIP(rip, n.IP()) != nil {
   878  				continue
   879  			}
   880  			nodes = append(nodes, n)
   881  			if len(nodes) >= limit {
   882  				return nodes
   883  			}
   884  		}
   885  	}
   886  	return nodes
   887  }
   888  
   889  // packNodes creates NODES response packets for the given node list.
   890  func packNodes(reqid []byte, nodes []*enode.Node) []*v5wire.Nodes {
   891  	if len(nodes) == 0 {
   892  		return []*v5wire.Nodes{{ReqID: reqid, RespCount: 1}}
   893  	}
   894  
   895  	// This limit represents the available space for nodes in output packets. Maximum
   896  	// packet size is 1280, and out of this ~80 bytes will be taken up by the packet
   897  	// frame. So limiting to 1000 bytes here leaves 200 bytes for other fields of the
   898  	// NODES message, which is a lot.
   899  	const sizeLimit = 1000
   900  
   901  	var resp []*v5wire.Nodes
   902  	for len(nodes) > 0 {
   903  		p := &v5wire.Nodes{ReqID: reqid}
   904  		size := uint64(0)
   905  		for len(nodes) > 0 {
   906  			r := nodes[0].Record()
   907  			if size += r.Size(); size > sizeLimit {
   908  				break
   909  			}
   910  			p.Nodes = append(p.Nodes, r)
   911  			nodes = nodes[1:]
   912  		}
   913  		resp = append(resp, p)
   914  	}
   915  	for _, msg := range resp {
   916  		msg.RespCount = uint8(len(resp))
   917  	}
   918  	return resp
   919  }