Skip to content

Commit 0fd0c83

Browse files
committed
p2p/discover: repeat WHOAREYOU challenge when handshake in progress
1 parent 4cdd7c8 commit 0fd0c83

3 files changed

Lines changed: 25 additions & 0 deletions

File tree

p2p/discover/v5_udp.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ type codecV5 interface {
5555
// Decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
5656
// The *enode.Node return value is non-nil when the input contains a handshake response.
5757
Decode([]byte, string) (enode.ID, *enode.Node, v5wire.Packet, error)
58+
59+
CurrentChallenge(enode.ID, string) *v5wire.Whoareyou
5860
}
5961

6062
// UDPv5 is the implementation of protocol version 5.
@@ -774,6 +776,19 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort
774776

775777
// handleUnknown initiates a handshake by responding with WHOAREYOU.
776778
func (t *UDPv5) handleUnknown(p *v5wire.Unknown, fromID enode.ID, fromAddr netip.AddrPort) {
779+
currentChallenge := t.codec.CurrentChallenge(fromID, fromAddr.String())
780+
if currentChallenge != nil {
781+
// This case happens when the sender issues multiple concurrent requests.
782+
// Since we only support one in-progress handshake at a time, we need to tell
783+
// them which handshake attempt they need to complete. We tell them to use the
784+
// existing handshake attempt since the response to that one might still be in
785+
// transit.
786+
t.log.Warn("Repeating discv5 handshake challenge", "id", fromID, "addr", fromAddr)
787+
t.sendResponse(fromID, fromAddr, currentChallenge)
788+
return
789+
}
790+
791+
// Send a fresh challenge.
777792
challenge := &v5wire.Whoareyou{Nonce: p.Nonce}
778793
crand.Read(challenge.IDNonce[:])
779794
if n := t.getNode(fromID); n != nil {

p2p/discover/v5_udp_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,10 @@ func (c *testCodec) Encode(toID enode.ID, addr string, p v5wire.Packet, _ *v5wir
717717
return frame, authTag, err
718718
}
719719

720+
func (c *testCodec) CurrentChallenge(enode.ID, string) *v5wire.Whoareyou {
721+
return nil
722+
}
723+
720724
func (c *testCodec) Decode(input []byte, addr string) (enode.ID, *enode.Node, v5wire.Packet, error) {
721725
frame, p, err := c.decodeFrame(input)
722726
if err != nil {

p2p/discover/v5wire/encoding.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ func (c *Codec) EncodeRaw(id enode.ID, head Header, msgdata []byte) ([]byte, err
245245
return c.buf.Bytes(), nil
246246
}
247247

248+
// CurrentChallenge returns the latest challenge sent to the given node.
249+
// This will return non-nil while a handshake is in progress.
250+
func (c *Codec) CurrentChallenge(id enode.ID, addr string) *Whoareyou {
251+
return c.sc.getHandshake(id, addr)
252+
}
253+
248254
func (c *Codec) writeHeaders(head *Header) {
249255
c.buf.Reset()
250256
c.buf.Write(head.IV[:])

0 commit comments

Comments
 (0)