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