23
23
use std:: {
24
24
borrow:: Borrow ,
25
25
collections:: HashMap ,
26
- error:: Error ,
27
26
hash:: { Hash , Hasher } ,
28
27
net:: { Ipv4Addr , SocketAddrV4 } ,
29
28
pin:: Pin ,
@@ -36,7 +35,13 @@ use crate::{
36
35
gateway:: { Gateway , Protocol } ,
37
36
Config ,
38
37
} ;
39
- use futures:: { future:: BoxFuture , stream:: FuturesUnordered , Future , FutureExt , StreamExt } ;
38
+ use futures:: {
39
+ channel:: mpsc:: { self , Receiver , UnboundedSender } ,
40
+ future:: BoxFuture ,
41
+ select,
42
+ stream:: FuturesUnordered ,
43
+ Future , FutureExt , SinkExt , StreamExt ,
44
+ } ;
40
45
use futures_timer:: Delay ;
41
46
use libp2p_core:: { multiaddr, transport:: ListenerId , Endpoint , Multiaddr } ;
42
47
use libp2p_swarm:: {
@@ -85,11 +90,11 @@ enum Event {
85
90
/// Port was successfully mapped.
86
91
Mapped ( Mapping ) ,
87
92
/// There was a failure mapping port.
88
- MapFailure ( Mapping , Box < dyn Error > ) ,
93
+ MapFailure ( Mapping , String ) ,
89
94
/// Port was successfully removed.
90
95
Removed ( Mapping ) ,
91
96
/// There was a failure removing the mapping port.
92
- RemovalFailure ( Mapping , Box < dyn Error > ) ,
97
+ RemovalFailure ( Mapping , String ) ,
93
98
}
94
99
95
100
/// Mapping of a Protocol and Port on the gateway.
@@ -155,7 +160,10 @@ where
155
160
mappings : HashMap < Mapping , MappingState > ,
156
161
157
162
/// Pending gateway events.
158
- pending_events : FuturesUnordered < BoxFuture < ' static , Event > > ,
163
+ events_queue : Receiver < Event > ,
164
+
165
+ /// Events sender.
166
+ events_sender : UnboundedSender < BoxFuture < ' static , Event > > ,
159
167
}
160
168
161
169
impl < P > Default for Behaviour < P >
@@ -173,11 +181,29 @@ where
173
181
{
174
182
/// Builds a new `UPnP` behaviour.
175
183
pub fn new ( config : Config ) -> Self {
184
+ let ( events_sender, mut task_receiver) = mpsc:: unbounded ( ) ;
185
+ let ( mut task_sender, events_queue) = mpsc:: channel ( 0 ) ;
186
+ P :: spawn ( async move {
187
+ let mut futs = FuturesUnordered :: new ( ) ;
188
+ loop {
189
+ select ! {
190
+ fut = task_receiver. select_next_some( ) => {
191
+ futs. push( fut) ;
192
+ } ,
193
+ event = futs. select_next_some( ) => {
194
+ task_sender. send( event) . await . expect( "receiver should be available" ) ;
195
+ }
196
+ complete => break ,
197
+ }
198
+ }
199
+ } ) ;
200
+
176
201
Self {
177
202
config,
178
203
state : GatewayState :: Searching ( P :: search ( config) . boxed ( ) ) ,
179
204
mappings : Default :: default ( ) ,
180
- pending_events : Default :: default ( ) ,
205
+ events_queue,
206
+ events_sender,
181
207
}
182
208
}
183
209
}
@@ -255,10 +281,16 @@ where
255
281
multiaddr : multiaddr. clone ( ) ,
256
282
} ;
257
283
258
- self . pending_events . push (
259
- map_port :: < P > ( gateway. clone ( ) , mapping. clone ( ) , self . config . permanent )
284
+ self . events_sender
285
+ . unbounded_send (
286
+ map_port :: < P > (
287
+ gateway. clone ( ) ,
288
+ mapping. clone ( ) ,
289
+ self . config . permanent ,
290
+ )
260
291
. boxed ( ) ,
261
- ) ;
292
+ )
293
+ . expect ( "receiver should be available" ) ;
262
294
263
295
self . mappings . insert ( mapping, MappingState :: Pending ) ;
264
296
}
@@ -275,9 +307,11 @@ where
275
307
} ) => {
276
308
if let GatewayState :: Available ( ( gateway, _external_addr) ) = & self . state {
277
309
if let Some ( ( mapping, _state) ) = self . mappings . remove_entry ( & listener_id) {
278
- self . pending_events . push (
279
- remove_port_mapping :: < P > ( gateway. clone ( ) , mapping. clone ( ) ) . boxed ( ) ,
280
- ) ;
310
+ self . events_sender
311
+ . unbounded_send (
312
+ remove_port_mapping :: < P > ( gateway. clone ( ) , mapping. clone ( ) ) . boxed ( ) ,
313
+ )
314
+ . expect ( "receiver should be available" ) ;
281
315
self . mappings . insert ( mapping, MappingState :: Pending ) ;
282
316
}
283
317
}
@@ -328,7 +362,7 @@ where
328
362
} ,
329
363
GatewayState :: Available ( ( ref gateway, external_addr) ) => {
330
364
// Check pending mappings.
331
- if let Poll :: Ready ( Some ( result) ) = self . pending_events . poll_next_unpin ( cx) {
365
+ if let Poll :: Ready ( Some ( result) ) = self . events_queue . poll_next_unpin ( cx) {
332
366
match result {
333
367
Event :: Mapped ( mapping) => {
334
368
let state = self
@@ -430,9 +464,12 @@ where
430
464
mapping. internal_addr,
431
465
mapping. protocol
432
466
) ;
433
- self . pending_events . push (
434
- remove_port_mapping :: < P > ( gateway. clone ( ) , mapping) . boxed ( ) ,
435
- ) ;
467
+ self . events_sender
468
+ . unbounded_send (
469
+ remove_port_mapping :: < P > ( gateway. clone ( ) , mapping. clone ( ) )
470
+ . boxed ( ) ,
471
+ )
472
+ . expect ( "receiver should be available" ) ;
436
473
}
437
474
}
438
475
}
@@ -441,22 +478,30 @@ where
441
478
for ( mapping, state) in self . mappings . iter_mut ( ) {
442
479
match state {
443
480
MappingState :: Inactive => {
444
- self . pending_events . push (
445
- map_port :: < P > (
446
- gateway. clone ( ) ,
447
- mapping. clone ( ) ,
448
- self . config . permanent ,
481
+ self . events_sender
482
+ . unbounded_send (
483
+ map_port :: < P > (
484
+ gateway. clone ( ) ,
485
+ mapping. clone ( ) ,
486
+ self . config . permanent ,
487
+ )
488
+ . boxed ( ) ,
449
489
)
450
- . boxed ( ) ,
451
- ) ;
490
+ . expect ( "receiver should be available" ) ;
452
491
* state = MappingState :: Pending ;
453
492
}
454
493
MappingState :: Active ( timeout) => {
455
494
if Pin :: new ( timeout) . poll ( cx) . is_ready ( ) {
456
- self . pending_events . push (
457
- map_port :: < P > ( gateway. clone ( ) , mapping. clone ( ) , false )
495
+ self . events_sender
496
+ . unbounded_send (
497
+ map_port :: < P > (
498
+ gateway. clone ( ) ,
499
+ mapping. clone ( ) ,
500
+ self . config . permanent ,
501
+ )
458
502
. boxed ( ) ,
459
- ) ;
503
+ )
504
+ . expect ( "receiver should be available" ) ;
460
505
}
461
506
}
462
507
MappingState :: Pending | MappingState :: Permanent => { }
0 commit comments