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