@@ -93,12 +93,14 @@ type UDPv5 struct {
93
93
callDoneCh chan * callV5
94
94
respTimeoutCh chan * callTimeout
95
95
sendCh chan sendRequest
96
+ sendNoRespCh chan * sendNoRespRequest
96
97
unhandled chan <- ReadPacket
97
98
98
99
// state of dispatch
99
100
codec codecV5
100
101
activeCallByNode map [enode.ID ]* callV5
101
102
activeCallByAuth map [v5wire.Nonce ]* callV5
103
+ noRespCallByAuth map [v5wire.Nonce ]* callV5
102
104
callQueue map [enode.ID ][]* callV5
103
105
104
106
// shutdown stuff
@@ -112,6 +114,13 @@ type sendRequest struct {
112
114
destID enode.ID
113
115
destAddr netip.AddrPort
114
116
msg v5wire.Packet
117
+ destNode * enode.Node
118
+ }
119
+
120
+ type sendNoRespRequest struct {
121
+ destNode * enode.Node
122
+ destAddr netip.AddrPort
123
+ msg v5wire.Packet
115
124
}
116
125
117
126
// callV5 represents a remote procedure call against another node.
@@ -173,12 +182,14 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) {
173
182
callCh : make (chan * callV5 ),
174
183
callDoneCh : make (chan * callV5 ),
175
184
sendCh : make (chan sendRequest ),
185
+ sendNoRespCh : make (chan * sendNoRespRequest ),
176
186
respTimeoutCh : make (chan * callTimeout ),
177
187
unhandled : cfg .Unhandled ,
178
188
// state of dispatch
179
189
codec : v5wire .NewCodec (ln , cfg .PrivateKey , cfg .Clock , cfg .V5ProtocolID ),
180
190
activeCallByNode : make (map [enode.ID ]* callV5 ),
181
191
activeCallByAuth : make (map [v5wire.Nonce ]* callV5 ),
192
+ noRespCallByAuth : make (map [v5wire.Nonce ]* callV5 ),
182
193
callQueue : make (map [enode.ID ][]* callV5 ),
183
194
// shutdown
184
195
closeCtx : closeCtx ,
@@ -578,12 +589,18 @@ func (t *UDPv5) dispatch() {
578
589
case c := <- t .callCh :
579
590
t .callQueue [c .id ] = append (t .callQueue [c .id ], c )
580
591
t .sendNextCall (c .id )
592
+ case cnr := <- t .sendNoRespCh :
593
+ // send a TalkReq call but not waiting for TalkResp
594
+ // may more used by portal network
595
+ t .sendCallNotWaitResp (cnr )
581
596
582
597
case ct := <- t .respTimeoutCh :
583
598
active := t .activeCallByNode [ct .c .id ]
584
599
if ct .c == active && ct .timer == active .timeout {
585
600
ct .c .err <- errTimeout
586
601
}
602
+ delete (t .noRespCallByAuth , ct .c .nonce )
603
+ ct .c .timeout .Stop ()
587
604
588
605
case c := <- t .callDoneCh :
589
606
active := t .activeCallByNode [c .id ]
@@ -597,7 +614,6 @@ func (t *UDPv5) dispatch() {
597
614
598
615
case r := <- t .sendCh :
599
616
t .send (r .destID , r .destAddr , r .msg , nil )
600
-
601
617
case p := <- t .packetInCh :
602
618
t .handlePacket (p .Data , p .Addr )
603
619
// Arm next read.
@@ -616,6 +632,9 @@ func (t *UDPv5) dispatch() {
616
632
delete (t .activeCallByNode , id )
617
633
delete (t .activeCallByAuth , c .nonce )
618
634
}
635
+ for nonce := range t .noRespCallByAuth {
636
+ delete (t .activeCallByAuth , nonce )
637
+ }
619
638
return
620
639
}
621
640
}
@@ -641,6 +660,36 @@ func (t *UDPv5) startResponseTimeout(c *callV5) {
641
660
close (done )
642
661
}
643
662
663
+ // sendCallNotWaitResp send a talk request contains utp packet by call, call will not insert into queue
664
+ func (t * UDPv5 ) sendCallNotWaitResp (r * sendNoRespRequest ) {
665
+ // send out a TalkRequest that is a UTP packet for portal network
666
+ // todo If the destination node has been handshaked, it may not be necessary to use call
667
+ // request should be cached to handle WHOAREYOU
668
+ c := & callV5 {id : r .destNode .ID (), addr : r .destAddr }
669
+ c .node = r .destNode
670
+ c .packet = r .msg
671
+ c .reqid = make ([]byte , 8 )
672
+ c .ch = make (chan v5wire.Packet , 1 )
673
+ c .err = make (chan error , 1 )
674
+ // Assign request ID.
675
+ crand .Read (c .reqid )
676
+ c .packet .SetRequestID (c .reqid )
677
+
678
+ nonce , _ := t .send (c .id , c .addr , c .packet , nil )
679
+ c .nonce = nonce
680
+ t .noRespCallByAuth [nonce ] = c
681
+ t .startResponseTimeout (c )
682
+ }
683
+
684
+ // sendNoRespData send a data from a call of no wait resp.
685
+ // The handshake just has been successful.
686
+ func (t * UDPv5 ) sendNoRespData (c * callV5 ) {
687
+ // Just resend the data and not use call again
688
+ delete (t .noRespCallByAuth , c .nonce )
689
+ c .timeout .Stop ()
690
+ t .send (c .node .ID (), c .addr , c .packet , nil )
691
+ }
692
+
644
693
// sendNextCall sends the next call in the call queue if there is no active call.
645
694
func (t * UDPv5 ) sendNextCall (id enode.ID ) {
646
695
queue := t .callQueue [id ]
@@ -681,7 +730,15 @@ func (t *UDPv5) sendResponse(toID enode.ID, toAddr netip.AddrPort, packet v5wire
681
730
682
731
func (t * UDPv5 ) sendFromAnotherThread (toID enode.ID , toAddr netip.AddrPort , packet v5wire.Packet ) {
683
732
select {
684
- case t .sendCh <- sendRequest {toID , toAddr , packet }:
733
+ case t .sendCh <- sendRequest {destID : toID , destAddr : toAddr , msg : packet }:
734
+ case <- t .closeCtx .Done ():
735
+ }
736
+ }
737
+
738
+ // SendNoResp Send a packet but will not wait for a response
739
+ func (t * UDPv5 ) SendNoResp (n * enode.Node , toAddr netip.AddrPort , packet v5wire.Packet ) {
740
+ select {
741
+ case t .sendNoRespCh <- & sendNoRespRequest {n , toAddr , packet }:
685
742
case <- t .closeCtx .Done ():
686
743
}
687
744
}
@@ -874,17 +931,25 @@ func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr n
874
931
c .err <- errors .New ("remote wants handshake, but call has no ENR" )
875
932
return
876
933
}
877
- // Resend the call that was answered by WHOAREYOU.
934
+
878
935
t .log .Trace ("<< " + p .Name (), "id" , c .node .ID (), "addr" , fromAddr )
879
- c .handshakeCount ++
880
- c .challenge = p
881
- p .Node = c .node
882
- t .sendCall (c )
936
+ if _ , ok := t .noRespCallByAuth [p .Nonce ]; ! ok {
937
+ // Resend the call that was answered by WHOAREYOU.
938
+ c .handshakeCount ++
939
+ c .challenge = p
940
+ p .Node = c .node
941
+ t .sendCall (c )
942
+ } else {
943
+ t .sendNoRespData (c )
944
+ }
883
945
}
884
946
885
947
// matchWithCall checks whether a handshake attempt matches the active call.
886
948
func (t * UDPv5 ) matchWithCall (fromID enode.ID , nonce v5wire.Nonce ) (* callV5 , error ) {
887
949
c := t .activeCallByAuth [nonce ]
950
+ if c == nil {
951
+ c = t .noRespCallByAuth [nonce ]
952
+ }
888
953
if c == nil {
889
954
return nil , errChallengeNoCall
890
955
}
0 commit comments