@@ -29,12 +29,13 @@ use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailu
29
29
use libp2p_swarm:: dial_opts:: { self , DialOpts } ;
30
30
use libp2p_swarm:: {
31
31
ConnectionHandlerUpgrErr , ExternalAddresses , NetworkBehaviour , NetworkBehaviourAction ,
32
- NotifyHandler , PollParameters ,
32
+ NotifyHandler , PollParameters , THandlerInEvent ,
33
33
} ;
34
34
use libp2p_swarm:: { ConnectionId , THandlerOutEvent } ;
35
35
use std:: collections:: { HashMap , HashSet , VecDeque } ;
36
36
use std:: task:: { Context , Poll } ;
37
37
use thiserror:: Error ;
38
+ use void:: Void ;
38
39
39
40
const MAX_NUMBER_OF_UPGRADE_ATTEMPTS : u8 = 3 ;
40
41
@@ -68,14 +69,20 @@ pub enum Error {
68
69
69
70
pub struct Behaviour {
70
71
/// Queue of actions to return when polled.
71
- queued_events : VecDeque < NetworkBehaviourAction < Event , handler:: Prototype > > ,
72
+ queued_events : VecDeque < NetworkBehaviourAction < Event , Either < handler:: relayed :: Command , Void > > > ,
72
73
73
74
/// All direct (non-relayed) connections.
74
75
direct_connections : HashMap < PeerId , HashSet < ConnectionId > > ,
75
76
76
77
external_addresses : ExternalAddresses ,
77
78
78
79
local_peer_id : PeerId ,
80
+
81
+ direct_to_relayed_connections : HashMap < ConnectionId , ConnectionId > ,
82
+
83
+ /// Indexed by the [`ConnectionId`] of the relayed connection and
84
+ /// the [`PeerId`] we are trying to establish a direct connection to.
85
+ outgoing_direct_connection_attempts : HashMap < ( ConnectionId , PeerId ) , u8 > ,
79
86
}
80
87
81
88
impl Behaviour {
@@ -85,6 +92,8 @@ impl Behaviour {
85
92
direct_connections : Default :: default ( ) ,
86
93
external_addresses : Default :: default ( ) ,
87
94
local_peer_id,
95
+ direct_to_relayed_connections : Default :: default ( ) ,
96
+ outgoing_direct_connection_attempts : Default :: default ( ) ,
88
97
}
89
98
}
90
99
@@ -148,40 +157,57 @@ impl Behaviour {
148
157
fn on_dial_failure (
149
158
& mut self ,
150
159
DialFailure {
151
- peer_id, handler, ..
152
- } : DialFailure < <Self as NetworkBehaviour >:: ConnectionHandler > ,
160
+ peer_id,
161
+ connection_id : failed_direct_connection,
162
+ ..
163
+ } : DialFailure ,
153
164
) {
154
- if let handler:: Prototype :: DirectConnection {
155
- relayed_connection_id,
156
- role : handler:: Role :: Initiator { attempt } ,
157
- } = handler
165
+ let peer_id = if let Some ( peer_id) = peer_id {
166
+ peer_id
167
+ } else {
168
+ return ;
169
+ } ;
170
+
171
+ let relayed_connection_id = if let Some ( relayed_connection_id) = self
172
+ . direct_to_relayed_connections
173
+ . get ( & failed_direct_connection)
158
174
{
159
- let peer_id = peer_id. expect ( "Peer of `Prototype::DirectConnection` is always known." ) ;
160
- if attempt < MAX_NUMBER_OF_UPGRADE_ATTEMPTS {
161
- self . queued_events
162
- . push_back ( NetworkBehaviourAction :: NotifyHandler {
163
- handler : NotifyHandler :: One ( relayed_connection_id) ,
164
- peer_id,
165
- event : Either :: Left ( handler:: relayed:: Command :: Connect {
166
- attempt : attempt + 1 ,
167
- obs_addrs : self . observed_addreses ( ) ,
168
- } ) ,
169
- } )
170
- } else {
171
- self . queued_events . extend ( [
172
- NetworkBehaviourAction :: NotifyHandler {
173
- peer_id,
174
- handler : NotifyHandler :: One ( relayed_connection_id) ,
175
- event : Either :: Left (
176
- handler:: relayed:: Command :: UpgradeFinishedDontKeepAlive ,
177
- ) ,
178
- } ,
179
- NetworkBehaviourAction :: GenerateEvent ( Event :: DirectConnectionUpgradeFailed {
180
- remote_peer_id : peer_id,
181
- error : Error :: Dial ,
175
+ * relayed_connection_id
176
+ } else {
177
+ return ;
178
+ } ;
179
+
180
+ let attempt = if let Some ( attempt) = self
181
+ . outgoing_direct_connection_attempts
182
+ . get ( & ( relayed_connection_id, peer_id) )
183
+ {
184
+ * attempt
185
+ } else {
186
+ return ;
187
+ } ;
188
+
189
+ if attempt < MAX_NUMBER_OF_UPGRADE_ATTEMPTS {
190
+ self . queued_events
191
+ . push_back ( NetworkBehaviourAction :: NotifyHandler {
192
+ handler : NotifyHandler :: One ( relayed_connection_id) ,
193
+ peer_id,
194
+ event : Either :: Left ( handler:: relayed:: Command :: Connect {
195
+ attempt : attempt + 1 ,
196
+ obs_addrs : self . observed_addreses ( ) ,
182
197
} ) ,
183
- ] ) ;
184
- }
198
+ } )
199
+ } else {
200
+ self . queued_events . extend ( [
201
+ NetworkBehaviourAction :: NotifyHandler {
202
+ peer_id,
203
+ handler : NotifyHandler :: One ( relayed_connection_id) ,
204
+ event : Either :: Left ( handler:: relayed:: Command :: UpgradeFinishedDontKeepAlive ) ,
205
+ } ,
206
+ NetworkBehaviourAction :: GenerateEvent ( Event :: DirectConnectionUpgradeFailed {
207
+ remote_peer_id : peer_id,
208
+ error : Error :: Dial ,
209
+ } ) ,
210
+ ] ) ;
185
211
}
186
212
}
187
213
@@ -215,23 +241,34 @@ impl NetworkBehaviour for Behaviour {
215
241
type OutEvent = Event ;
216
242
217
243
fn new_handler ( & mut self ) -> Self :: ConnectionHandler {
218
- handler:: Prototype :: UnknownConnection
244
+ handler:: Prototype
219
245
}
220
246
221
247
fn on_connection_handler_event (
222
248
& mut self ,
223
249
event_source : PeerId ,
224
- connection : ConnectionId ,
250
+ connection_id : ConnectionId ,
225
251
handler_event : THandlerOutEvent < Self > ,
226
252
) {
253
+ let relayed_connection_id = match handler_event. as_ref ( ) {
254
+ Either :: Left ( _) => connection_id,
255
+ Either :: Right ( _) => match self . direct_to_relayed_connections . get ( & connection_id) {
256
+ None => {
257
+ // If the connection ID is unknown to us, it means we didn't create it so ignore any event coming from it.
258
+ return ;
259
+ }
260
+ Some ( relayed_connection_id) => * relayed_connection_id,
261
+ } ,
262
+ } ;
263
+
227
264
match handler_event {
228
265
Either :: Left ( handler:: relayed:: Event :: InboundConnectRequest {
229
266
inbound_connect,
230
267
remote_addr,
231
268
} ) => {
232
269
self . queued_events . extend ( [
233
270
NetworkBehaviourAction :: NotifyHandler {
234
- handler : NotifyHandler :: One ( connection ) ,
271
+ handler : NotifyHandler :: One ( relayed_connection_id ) ,
235
272
peer_id : event_source,
236
273
event : Either :: Left ( handler:: relayed:: Command :: AcceptInboundConnect {
237
274
inbound_connect,
@@ -256,16 +293,17 @@ impl NetworkBehaviour for Behaviour {
256
293
) ) ;
257
294
}
258
295
Either :: Left ( handler:: relayed:: Event :: InboundConnectNegotiated ( remote_addrs) ) => {
259
- self . queued_events . push_back ( NetworkBehaviourAction :: Dial {
260
- opts : DialOpts :: peer_id ( event_source)
261
- . addresses ( remote_addrs)
262
- . condition ( dial_opts:: PeerCondition :: Always )
263
- . build ( ) ,
264
- handler : handler:: Prototype :: DirectConnection {
265
- relayed_connection_id : connection,
266
- role : handler:: Role :: Listener ,
267
- } ,
268
- } ) ;
296
+ let opts = DialOpts :: peer_id ( event_source)
297
+ . addresses ( remote_addrs)
298
+ . condition ( dial_opts:: PeerCondition :: Always )
299
+ . build ( ) ;
300
+
301
+ let maybe_direct_connection_id = opts. connection_id ( ) ;
302
+
303
+ self . direct_to_relayed_connections
304
+ . insert ( maybe_direct_connection_id, relayed_connection_id) ;
305
+ self . queued_events
306
+ . push_back ( NetworkBehaviourAction :: Dial { opts } ) ;
269
307
}
270
308
Either :: Left ( handler:: relayed:: Event :: OutboundNegotiationFailed { error } ) => {
271
309
self . queued_events
@@ -276,27 +314,25 @@ impl NetworkBehaviour for Behaviour {
276
314
} ,
277
315
) ) ;
278
316
}
279
- Either :: Left ( handler:: relayed:: Event :: OutboundConnectNegotiated {
280
- remote_addrs,
281
- attempt,
282
- } ) => {
283
- self . queued_events . push_back ( NetworkBehaviourAction :: Dial {
284
- opts : DialOpts :: peer_id ( event_source)
285
- . condition ( dial_opts:: PeerCondition :: Always )
286
- . addresses ( remote_addrs)
287
- . override_role ( )
288
- . build ( ) ,
289
- handler : handler:: Prototype :: DirectConnection {
290
- relayed_connection_id : connection,
291
- role : handler:: Role :: Initiator { attempt } ,
292
- } ,
293
- } ) ;
317
+ Either :: Left ( handler:: relayed:: Event :: OutboundConnectNegotiated { remote_addrs } ) => {
318
+ let opts = DialOpts :: peer_id ( event_source)
319
+ . condition ( dial_opts:: PeerCondition :: Always )
320
+ . addresses ( remote_addrs)
321
+ . override_role ( )
322
+ . build ( ) ;
323
+
324
+ let maybe_direct_connection_id = opts. connection_id ( ) ;
325
+
326
+ self . direct_to_relayed_connections
327
+ . insert ( maybe_direct_connection_id, relayed_connection_id) ;
328
+ * self
329
+ . outgoing_direct_connection_attempts
330
+ . entry ( ( relayed_connection_id, event_source) )
331
+ . or_default ( ) += 1 ;
332
+ self . queued_events
333
+ . push_back ( NetworkBehaviourAction :: Dial { opts } ) ;
294
334
}
295
- Either :: Right ( Either :: Left (
296
- handler:: direct:: Event :: DirectConnectionUpgradeSucceeded {
297
- relayed_connection_id,
298
- } ,
299
- ) ) => {
335
+ Either :: Right ( handler:: direct:: Event :: DirectConnectionEstablished ) => {
300
336
self . queued_events . extend ( [
301
337
NetworkBehaviourAction :: NotifyHandler {
302
338
peer_id : event_source,
@@ -312,15 +348,14 @@ impl NetworkBehaviour for Behaviour {
312
348
) ,
313
349
] ) ;
314
350
}
315
- Either :: Right ( Either :: Right ( event) ) => void:: unreachable ( event) ,
316
351
} ;
317
352
}
318
353
319
354
fn poll (
320
355
& mut self ,
321
356
_cx : & mut Context < ' _ > ,
322
357
_: & mut impl PollParameters ,
323
- ) -> Poll < NetworkBehaviourAction < Self :: OutEvent , Self :: ConnectionHandler > > {
358
+ ) -> Poll < NetworkBehaviourAction < Self :: OutEvent , THandlerInEvent < Self > > > {
324
359
if let Some ( event) = self . queued_events . pop_front ( ) {
325
360
return Poll :: Ready ( event) ;
326
361
}
0 commit comments