18
18
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
19
// DEALINGS IN THE SOFTWARE.
20
20
21
+ use crate :: client:: Connection ;
21
22
use crate :: priv_client:: transport;
23
+ use crate :: priv_client:: transport:: ToListenerMsg ;
22
24
use crate :: protocol:: { self , inbound_stop, outbound_hop} ;
23
25
use crate :: { priv_client, proto, HOP_PROTOCOL_NAME , STOP_PROTOCOL_NAME } ;
26
+ use futures:: channel:: mpsc:: Sender ;
24
27
use futures:: channel:: { mpsc, oneshot} ;
25
28
use futures:: future:: FutureExt ;
26
29
use futures_timer:: Delay ;
27
30
use libp2p_core:: multiaddr:: Protocol ;
28
31
use libp2p_core:: upgrade:: ReadyUpgrade ;
29
32
use libp2p_core:: Multiaddr ;
30
33
use libp2p_identity:: PeerId ;
31
- use libp2p_swarm:: handler:: {
32
- ConnectionEvent , DialUpgradeError , FullyNegotiatedInbound , FullyNegotiatedOutbound ,
33
- } ;
34
+ use libp2p_swarm:: handler:: { ConnectionEvent , FullyNegotiatedInbound } ;
34
35
use libp2p_swarm:: {
35
- ConnectionHandler , ConnectionHandlerEvent , StreamProtocol , StreamUpgradeError ,
36
+ ConnectionHandler , ConnectionHandlerEvent , Stream , StreamProtocol , StreamUpgradeError ,
36
37
SubstreamProtocol ,
37
38
} ;
38
39
use std:: collections:: VecDeque ;
39
40
use std:: task:: { Context , Poll } ;
40
41
use std:: time:: Duration ;
41
42
use std:: { fmt, io} ;
43
+ use void:: Void ;
42
44
43
45
/// The maximum number of circuits being denied concurrently.
44
46
///
@@ -104,8 +106,7 @@ pub struct Handler {
104
106
> ,
105
107
> ,
106
108
107
- /// We issue a stream upgrade for each pending request.
108
- pending_requests : VecDeque < PendingRequest > ,
109
+ pending_streams : VecDeque < oneshot:: Sender < Result < Stream , StreamUpgradeError < Void > > > > ,
109
110
110
111
inflight_reserve_requests : futures_bounded:: FuturesTupleSet <
111
112
Result < outbound_hop:: Reservation , outbound_hop:: ReserveError > ,
@@ -133,7 +134,7 @@ impl Handler {
133
134
remote_peer_id,
134
135
remote_addr,
135
136
queued_events : Default :: default ( ) ,
136
- pending_requests : Default :: default ( ) ,
137
+ pending_streams : Default :: default ( ) ,
137
138
inflight_reserve_requests : futures_bounded:: FuturesTupleSet :: new (
138
139
STREAM_TIMEOUT ,
139
140
MAX_CONCURRENT_STREAMS_PER_CONNECTION ,
@@ -154,57 +155,6 @@ impl Handler {
154
155
}
155
156
}
156
157
157
- fn on_dial_upgrade_error (
158
- & mut self ,
159
- DialUpgradeError { error, .. } : DialUpgradeError <
160
- <Self as ConnectionHandler >:: OutboundOpenInfo ,
161
- <Self as ConnectionHandler >:: OutboundProtocol ,
162
- > ,
163
- ) {
164
- let pending_request = self
165
- . pending_requests
166
- . pop_front ( )
167
- . expect ( "got a stream error without a pending request" ) ;
168
-
169
- match pending_request {
170
- PendingRequest :: Reserve { mut to_listener } => {
171
- let error = match error {
172
- StreamUpgradeError :: Timeout => {
173
- outbound_hop:: ReserveError :: Io ( io:: ErrorKind :: TimedOut . into ( ) )
174
- }
175
- StreamUpgradeError :: Apply ( never) => void:: unreachable ( never) ,
176
- StreamUpgradeError :: NegotiationFailed => {
177
- outbound_hop:: ReserveError :: Unsupported
178
- }
179
- StreamUpgradeError :: Io ( e) => outbound_hop:: ReserveError :: Io ( e) ,
180
- } ;
181
-
182
- if let Err ( e) =
183
- to_listener. try_send ( transport:: ToListenerMsg :: Reservation ( Err ( error) ) )
184
- {
185
- tracing:: debug!( "Unable to send error to listener: {}" , e. into_send_error( ) )
186
- }
187
- self . reservation . failed ( ) ;
188
- }
189
- PendingRequest :: Connect {
190
- to_dial : send_back, ..
191
- } => {
192
- let error = match error {
193
- StreamUpgradeError :: Timeout => {
194
- outbound_hop:: ConnectError :: Io ( io:: ErrorKind :: TimedOut . into ( ) )
195
- }
196
- StreamUpgradeError :: NegotiationFailed => {
197
- outbound_hop:: ConnectError :: Unsupported
198
- }
199
- StreamUpgradeError :: Io ( e) => outbound_hop:: ConnectError :: Io ( e) ,
200
- StreamUpgradeError :: Apply ( v) => void:: unreachable ( v) ,
201
- } ;
202
-
203
- let _ = send_back. send ( Err ( error) ) ;
204
- }
205
- }
206
- }
207
-
208
158
fn insert_to_deny_futs ( & mut self , circuit : inbound_stop:: Circuit ) {
209
159
let src_peer_id = circuit. src_peer_id ( ) ;
210
160
@@ -219,6 +169,62 @@ impl Handler {
219
169
)
220
170
}
221
171
}
172
+
173
+ fn make_new_reservation ( & mut self , to_listener : Sender < ToListenerMsg > ) {
174
+ let ( sender, receiver) = oneshot:: channel ( ) ;
175
+
176
+ self . pending_streams . push_back ( sender) ;
177
+ self . queued_events
178
+ . push_back ( ConnectionHandlerEvent :: OutboundSubstreamRequest {
179
+ protocol : SubstreamProtocol :: new ( ReadyUpgrade :: new ( HOP_PROTOCOL_NAME ) , ( ) ) ,
180
+ } ) ;
181
+ let result = self . inflight_reserve_requests . try_push (
182
+ async move {
183
+ let stream = receiver
184
+ . await
185
+ . map_err ( |_| io:: Error :: from ( io:: ErrorKind :: BrokenPipe ) ) ?
186
+ . map_err ( into_reserve_error) ?;
187
+
188
+ let reservation = outbound_hop:: make_reservation ( stream) . await ?;
189
+
190
+ Ok ( reservation)
191
+ } ,
192
+ to_listener,
193
+ ) ;
194
+
195
+ if result. is_err ( ) {
196
+ tracing:: warn!( "Dropping in-flight reservation request because we are at capacity" ) ;
197
+ }
198
+ }
199
+
200
+ fn establish_new_circuit (
201
+ & mut self ,
202
+ to_dial : oneshot:: Sender < Result < Connection , outbound_hop:: ConnectError > > ,
203
+ dst_peer_id : PeerId ,
204
+ ) {
205
+ let ( sender, receiver) = oneshot:: channel ( ) ;
206
+
207
+ self . pending_streams . push_back ( sender) ;
208
+ self . queued_events
209
+ . push_back ( ConnectionHandlerEvent :: OutboundSubstreamRequest {
210
+ protocol : SubstreamProtocol :: new ( ReadyUpgrade :: new ( HOP_PROTOCOL_NAME ) , ( ) ) ,
211
+ } ) ;
212
+ let result = self . inflight_outbound_connect_requests . try_push (
213
+ async move {
214
+ let stream = receiver
215
+ . await
216
+ . map_err ( |_| io:: Error :: from ( io:: ErrorKind :: BrokenPipe ) ) ?
217
+ . map_err ( into_connect_error) ?;
218
+
219
+ outbound_hop:: open_circuit ( stream, dst_peer_id) . await
220
+ } ,
221
+ to_dial,
222
+ ) ;
223
+
224
+ if result. is_err ( ) {
225
+ tracing:: warn!( "Dropping in-flight connect request because we are at capacity" )
226
+ }
227
+ }
222
228
}
223
229
224
230
impl ConnectionHandler for Handler {
@@ -236,25 +242,13 @@ impl ConnectionHandler for Handler {
236
242
fn on_behaviour_event ( & mut self , event : Self :: FromBehaviour ) {
237
243
match event {
238
244
In :: Reserve { to_listener } => {
239
- self . pending_requests
240
- . push_back ( PendingRequest :: Reserve { to_listener } ) ;
241
- self . queued_events
242
- . push_back ( ConnectionHandlerEvent :: OutboundSubstreamRequest {
243
- protocol : SubstreamProtocol :: new ( ReadyUpgrade :: new ( HOP_PROTOCOL_NAME ) , ( ) ) ,
244
- } ) ;
245
+ self . make_new_reservation ( to_listener) ;
245
246
}
246
247
In :: EstablishCircuit {
247
- to_dial : send_back ,
248
+ to_dial,
248
249
dst_peer_id,
249
250
} => {
250
- self . pending_requests . push_back ( PendingRequest :: Connect {
251
- dst_peer_id,
252
- to_dial : send_back,
253
- } ) ;
254
- self . queued_events
255
- . push_back ( ConnectionHandlerEvent :: OutboundSubstreamRequest {
256
- protocol : SubstreamProtocol :: new ( ReadyUpgrade :: new ( HOP_PROTOCOL_NAME ) , ( ) ) ,
257
- } ) ;
251
+ self . establish_new_circuit ( to_dial, dst_peer_id) ;
258
252
}
259
253
}
260
254
}
@@ -402,12 +396,8 @@ impl ConnectionHandler for Handler {
402
396
}
403
397
404
398
if let Poll :: Ready ( Some ( to_listener) ) = self . reservation . poll ( cx) {
405
- self . pending_requests
406
- . push_back ( PendingRequest :: Reserve { to_listener } ) ;
407
-
408
- return Poll :: Ready ( ConnectionHandlerEvent :: OutboundSubstreamRequest {
409
- protocol : SubstreamProtocol :: new ( ReadyUpgrade :: new ( HOP_PROTOCOL_NAME ) , ( ) ) ,
410
- } ) ;
399
+ self . make_new_reservation ( to_listener) ;
400
+ continue ;
411
401
}
412
402
413
403
// Deny incoming circuit requests.
@@ -450,42 +440,16 @@ impl ConnectionHandler for Handler {
450
440
tracing:: warn!( "Dropping inbound stream because we are at capacity" )
451
441
}
452
442
}
453
- ConnectionEvent :: FullyNegotiatedOutbound ( FullyNegotiatedOutbound {
454
- protocol : stream,
455
- ..
456
- } ) => {
457
- let pending_request = self . pending_requests . pop_front ( ) . expect (
458
- "opened a stream without a pending connection command or a reserve listener" ,
459
- ) ;
460
- match pending_request {
461
- PendingRequest :: Reserve { to_listener } => {
462
- if self
463
- . inflight_reserve_requests
464
- . try_push ( outbound_hop:: make_reservation ( stream) , to_listener)
465
- . is_err ( )
466
- {
467
- tracing:: warn!( "Dropping outbound stream because we are at capacity" ) ;
468
- }
469
- }
470
- PendingRequest :: Connect {
471
- dst_peer_id,
472
- to_dial : send_back,
473
- } => {
474
- if self
475
- . inflight_outbound_connect_requests
476
- . try_push ( outbound_hop:: open_circuit ( stream, dst_peer_id) , send_back)
477
- . is_err ( )
478
- {
479
- tracing:: warn!( "Dropping outbound stream because we are at capacity" ) ;
480
- }
481
- }
443
+ ConnectionEvent :: FullyNegotiatedOutbound ( ev) => {
444
+ if let Some ( next) = self . pending_streams . pop_front ( ) {
445
+ let _ = next. send ( Ok ( ev. protocol ) ) ;
482
446
}
483
447
}
484
- ConnectionEvent :: ListenUpgradeError ( listen_upgrade_error ) => {
485
- void :: unreachable ( listen_upgrade_error . error )
486
- }
487
- ConnectionEvent :: DialUpgradeError ( dial_upgrade_error ) => {
488
- self . on_dial_upgrade_error ( dial_upgrade_error )
448
+ ConnectionEvent :: ListenUpgradeError ( ev ) => void :: unreachable ( ev . error ) ,
449
+ ConnectionEvent :: DialUpgradeError ( ev ) => {
450
+ if let Some ( next ) = self . pending_streams . pop_front ( ) {
451
+ let _ = next . send ( Err ( ev . error ) ) ;
452
+ }
489
453
}
490
454
_ => { }
491
455
}
@@ -614,14 +578,24 @@ impl Reservation {
614
578
}
615
579
}
616
580
617
- pub ( crate ) enum PendingRequest {
618
- Reserve {
619
- /// A channel into the [`Transport`](priv_client::Transport).
620
- to_listener : mpsc:: Sender < transport:: ToListenerMsg > ,
621
- } ,
622
- Connect {
623
- dst_peer_id : PeerId ,
624
- /// A channel into the future returned by [`Transport::dial`](libp2p_core::Transport::dial).
625
- to_dial : oneshot:: Sender < Result < priv_client:: Connection , outbound_hop:: ConnectError > > ,
626
- } ,
581
+ fn into_reserve_error ( e : StreamUpgradeError < Void > ) -> outbound_hop:: ReserveError {
582
+ match e {
583
+ StreamUpgradeError :: Timeout => {
584
+ outbound_hop:: ReserveError :: Io ( io:: ErrorKind :: TimedOut . into ( ) )
585
+ }
586
+ StreamUpgradeError :: Apply ( never) => void:: unreachable ( never) ,
587
+ StreamUpgradeError :: NegotiationFailed => outbound_hop:: ReserveError :: Unsupported ,
588
+ StreamUpgradeError :: Io ( e) => outbound_hop:: ReserveError :: Io ( e) ,
589
+ }
590
+ }
591
+
592
+ fn into_connect_error ( e : StreamUpgradeError < Void > ) -> outbound_hop:: ConnectError {
593
+ match e {
594
+ StreamUpgradeError :: Timeout => {
595
+ outbound_hop:: ConnectError :: Io ( io:: ErrorKind :: TimedOut . into ( ) )
596
+ }
597
+ StreamUpgradeError :: Apply ( never) => void:: unreachable ( never) ,
598
+ StreamUpgradeError :: NegotiationFailed => outbound_hop:: ConnectError :: Unsupported ,
599
+ StreamUpgradeError :: Io ( e) => outbound_hop:: ConnectError :: Io ( e) ,
600
+ }
627
601
}
0 commit comments