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