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