@@ -56,6 +56,8 @@ type codecV5 interface {
5656 // Decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
5757 // The *enode.Node return value is non-nil when the input contains a handshake response.
5858 Decode ([]byte , string ) (enode.ID , * enode.Node , v5wire.Packet , error )
59+
60+ CurrentChallenge (enode.ID , string ) * v5wire.Whoareyou
5961}
6062
6163// UDPv5 is the implementation of protocol version 5.
@@ -863,6 +865,19 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort
863865
864866// handleUnknown initiates a handshake by responding with WHOAREYOU.
865867func (t * UDPv5 ) handleUnknown (p * v5wire.Unknown , fromID enode.ID , fromAddr netip.AddrPort ) {
868+ currentChallenge := t .codec .CurrentChallenge (fromID , fromAddr .String ())
869+ if currentChallenge != nil {
870+ // This case happens when the sender issues multiple concurrent requests.
871+ // Since we only support one in-progress handshake at a time, we need to tell
872+ // them which handshake attempt they need to complete. We tell them to use the
873+ // existing handshake attempt since the response to that one might still be in
874+ // transit.
875+ t .log .Warn ("Repeating discv5 handshake challenge" , "id" , fromID , "addr" , fromAddr )
876+ t .sendResponse (fromID , fromAddr , currentChallenge )
877+ return
878+ }
879+
880+ // Send a fresh challenge.
866881 challenge := & v5wire.Whoareyou {Nonce : p .Nonce }
867882 crand .Read (challenge .IDNonce [:])
868883 if n := t .GetNode (fromID ); n != nil {
0 commit comments