Skip to content

Commit dfcd39b

Browse files
committed
p2p/discover: send a packet and not wait for a response
Signed-off-by: thinkAfCod <[email protected]>
1 parent ee30681 commit dfcd39b

File tree

1 file changed

+72
-7
lines changed

1 file changed

+72
-7
lines changed

p2p/discover/v5_udp.go

+72-7
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,14 @@ type UDPv5 struct {
9393
callDoneCh chan *callV5
9494
respTimeoutCh chan *callTimeout
9595
sendCh chan sendRequest
96+
sendNoRespCh chan *sendNoRespRequest
9697
unhandled chan<- ReadPacket
9798

9899
// state of dispatch
99100
codec codecV5
100101
activeCallByNode map[enode.ID]*callV5
101102
activeCallByAuth map[v5wire.Nonce]*callV5
103+
noRespCallByAuth map[v5wire.Nonce]*callV5
102104
callQueue map[enode.ID][]*callV5
103105

104106
// shutdown stuff
@@ -112,6 +114,13 @@ type sendRequest struct {
112114
destID enode.ID
113115
destAddr netip.AddrPort
114116
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
115124
}
116125

117126
// callV5 represents a remote procedure call against another node.
@@ -173,12 +182,14 @@ func newUDPv5(conn UDPConn, ln *enode.LocalNode, cfg Config) (*UDPv5, error) {
173182
callCh: make(chan *callV5),
174183
callDoneCh: make(chan *callV5),
175184
sendCh: make(chan sendRequest),
185+
sendNoRespCh: make(chan *sendNoRespRequest),
176186
respTimeoutCh: make(chan *callTimeout),
177187
unhandled: cfg.Unhandled,
178188
// state of dispatch
179189
codec: v5wire.NewCodec(ln, cfg.PrivateKey, cfg.Clock, cfg.V5ProtocolID),
180190
activeCallByNode: make(map[enode.ID]*callV5),
181191
activeCallByAuth: make(map[v5wire.Nonce]*callV5),
192+
noRespCallByAuth: make(map[v5wire.Nonce]*callV5),
182193
callQueue: make(map[enode.ID][]*callV5),
183194
// shutdown
184195
closeCtx: closeCtx,
@@ -578,12 +589,18 @@ func (t *UDPv5) dispatch() {
578589
case c := <-t.callCh:
579590
t.callQueue[c.id] = append(t.callQueue[c.id], c)
580591
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)
581596

582597
case ct := <-t.respTimeoutCh:
583598
active := t.activeCallByNode[ct.c.id]
584599
if ct.c == active && ct.timer == active.timeout {
585600
ct.c.err <- errTimeout
586601
}
602+
delete(t.noRespCallByAuth, ct.c.nonce)
603+
ct.c.timeout.Stop()
587604

588605
case c := <-t.callDoneCh:
589606
active := t.activeCallByNode[c.id]
@@ -597,7 +614,6 @@ func (t *UDPv5) dispatch() {
597614

598615
case r := <-t.sendCh:
599616
t.send(r.destID, r.destAddr, r.msg, nil)
600-
601617
case p := <-t.packetInCh:
602618
t.handlePacket(p.Data, p.Addr)
603619
// Arm next read.
@@ -616,6 +632,9 @@ func (t *UDPv5) dispatch() {
616632
delete(t.activeCallByNode, id)
617633
delete(t.activeCallByAuth, c.nonce)
618634
}
635+
for nonce := range t.noRespCallByAuth {
636+
delete(t.activeCallByAuth, nonce)
637+
}
619638
return
620639
}
621640
}
@@ -641,6 +660,36 @@ func (t *UDPv5) startResponseTimeout(c *callV5) {
641660
close(done)
642661
}
643662

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+
644693
// sendNextCall sends the next call in the call queue if there is no active call.
645694
func (t *UDPv5) sendNextCall(id enode.ID) {
646695
queue := t.callQueue[id]
@@ -681,7 +730,15 @@ func (t *UDPv5) sendResponse(toID enode.ID, toAddr netip.AddrPort, packet v5wire
681730

682731
func (t *UDPv5) sendFromAnotherThread(toID enode.ID, toAddr netip.AddrPort, packet v5wire.Packet) {
683732
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}:
685742
case <-t.closeCtx.Done():
686743
}
687744
}
@@ -874,17 +931,25 @@ func (t *UDPv5) handleWhoareyou(p *v5wire.Whoareyou, fromID enode.ID, fromAddr n
874931
c.err <- errors.New("remote wants handshake, but call has no ENR")
875932
return
876933
}
877-
// Resend the call that was answered by WHOAREYOU.
934+
878935
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+
}
883945
}
884946

885947
// matchWithCall checks whether a handshake attempt matches the active call.
886948
func (t *UDPv5) matchWithCall(fromID enode.ID, nonce v5wire.Nonce) (*callV5, error) {
887949
c := t.activeCallByAuth[nonce]
950+
if c == nil {
951+
c = t.noRespCallByAuth[nonce]
952+
}
888953
if c == nil {
889954
return nil, errChallengeNoCall
890955
}

0 commit comments

Comments
 (0)