@@ -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.
776778func (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 {
0 commit comments