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 }