@@ -136,7 +136,7 @@ pub enum Event<TRequest, TResponse, TChannelResponse = TResponse> {
136136 /// An outbound request failed.
137137 OutboundFailure {
138138 /// The peer to whom the request was sent.
139- peer : PeerId ,
139+ peer : Option < PeerId > ,
140140 /// The (local) ID of the failed request.
141141 request_id : OutboundRequestId ,
142142 /// The error that occurred.
@@ -333,6 +333,24 @@ impl Config {
333333 }
334334}
335335
336+ #[ derive( Debug , Eq , PartialEq , Hash ) ]
337+ enum PendingOutgoingRequest {
338+ PeerId ( PeerId ) ,
339+ ConnectionId ( ConnectionId ) ,
340+ }
341+
342+ impl From < PeerId > for PendingOutgoingRequest {
343+ fn from ( peer_id : PeerId ) -> Self {
344+ Self :: PeerId ( peer_id)
345+ }
346+ }
347+
348+ impl From < ConnectionId > for PendingOutgoingRequest {
349+ fn from ( connection_id : ConnectionId ) -> Self {
350+ Self :: ConnectionId ( connection_id)
351+ }
352+ }
353+
336354/// A request/response protocol for some message codec.
337355pub struct Behaviour < TCodec >
338356where
@@ -360,7 +378,8 @@ where
360378 addresses : PeerAddresses ,
361379 /// Requests that have not yet been sent and are waiting for a connection
362380 /// to be established.
363- pending_outbound_requests : HashMap < PeerId , SmallVec < [ OutboundMessage < TCodec > ; 10 ] > > ,
381+ pending_outbound_requests :
382+ HashMap < PendingOutgoingRequest , SmallVec < [ OutboundMessage < TCodec > ; 10 ] > > ,
364383}
365384
366385impl < TCodec > Behaviour < TCodec >
@@ -417,28 +436,45 @@ where
417436 /// connection is established.
418437 ///
419438 /// > **Note**: In order for such a dialing attempt to succeed,
420- /// > the `RequestResonse` protocol must either be embedded
421- /// > in another `NetworkBehaviour` that provides peer and
422- /// > address discovery, or known addresses of peers must be
423- /// > managed via [`Behaviour::add_address`] and
439+ /// > the `peer` must be [`DialOpts`] with multiaddresses or
440+ /// > in case of simple [`PeerId`] `RequestResponse` protocol
441+ /// > must either be embedded in another `NetworkBehaviour`
442+ /// > that provides peer and address discovery, or known addresses of
443+ /// > peers must be managed via [`Behaviour::add_address`] and
424444 /// > [`Behaviour::remove_address`].
425- pub fn send_request ( & mut self , peer : & PeerId , request : TCodec :: Request ) -> OutboundRequestId {
445+ pub fn send_request < Peer > ( & mut self , peer : Peer , request : TCodec :: Request ) -> OutboundRequestId
446+ where
447+ DialOpts : From < Peer > ,
448+ {
426449 let request_id = self . next_outbound_request_id ( ) ;
427450 let request = OutboundMessage {
428451 request_id,
429452 request,
430453 protocols : self . outbound_protocols . clone ( ) ,
431454 } ;
432455
433- if let Some ( request) = self . try_send_request ( peer, request) {
434- self . pending_events . push_back ( ToSwarm :: Dial {
435- opts : DialOpts :: peer_id ( * peer) . build ( ) ,
436- } ) ;
437- self . pending_outbound_requests
438- . entry ( * peer)
439- . or_default ( )
440- . push ( request) ;
441- }
456+ let opts = DialOpts :: from ( peer) ;
457+ let maybe_peer_id = opts. get_peer_id ( ) ;
458+ let request = if let Some ( peer_id) = & maybe_peer_id {
459+ if let Some ( request) = self . try_send_request ( peer_id, request) {
460+ request
461+ } else {
462+ // Sent successfully
463+ return request_id;
464+ }
465+ } else {
466+ request
467+ } ;
468+
469+ self . pending_outbound_requests
470+ . entry ( if let Some ( peer_id) = maybe_peer_id {
471+ peer_id. into ( )
472+ } else {
473+ opts. connection_id ( ) . into ( )
474+ } )
475+ . or_default ( )
476+ . push ( request) ;
477+ self . pending_events . push_back ( ToSwarm :: Dial { opts } ) ;
442478
443479 request_id
444480 }
@@ -506,7 +542,7 @@ where
506542 // Check if request is still pending to be sent.
507543 let pen_conn = self
508544 . pending_outbound_requests
509- . get ( peer)
545+ . get ( & PendingOutgoingRequest :: from ( * peer) )
510546 . map ( |rps| rps. iter ( ) . any ( |rp| rp. request_id == * request_id) )
511547 . unwrap_or ( false ) ;
512548
@@ -665,30 +701,41 @@ where
665701 for request_id in connection. pending_outbound_responses {
666702 self . pending_events
667703 . push_back ( ToSwarm :: GenerateEvent ( Event :: OutboundFailure {
668- peer : peer_id,
704+ peer : Some ( peer_id) ,
669705 request_id,
670706 error : OutboundFailure :: ConnectionClosed ,
671707 } ) ) ;
672708 }
673709 }
674710
675- fn on_dial_failure ( & mut self , DialFailure { peer_id, .. } : DialFailure ) {
676- if let Some ( peer) = peer_id {
677- // If there are pending outgoing requests when a dial failure occurs,
678- // it is implied that we are not connected to the peer, since pending
679- // outgoing requests are drained when a connection is established and
680- // only created when a peer is not connected when a request is made.
681- // Thus these requests must be considered failed, even if there is
682- // another, concurrent dialing attempt ongoing.
683- if let Some ( pending) = self . pending_outbound_requests . remove ( & peer) {
684- for request in pending {
685- self . pending_events
686- . push_back ( ToSwarm :: GenerateEvent ( Event :: OutboundFailure {
687- peer,
688- request_id : request. request_id ,
689- error : OutboundFailure :: DialFailure ,
690- } ) ) ;
691- }
711+ fn on_dial_failure (
712+ & mut self ,
713+ DialFailure {
714+ peer_id,
715+ connection_id,
716+ ..
717+ } : DialFailure ,
718+ ) {
719+ let key = if let Some ( peer_id) = peer_id {
720+ peer_id. into ( )
721+ } else {
722+ connection_id. into ( )
723+ } ;
724+
725+ // If there are pending outgoing requests when a dial failure occurs,
726+ // it is implied that we are not connected to the peer, since pending
727+ // outgoing requests are drained when a connection is established and
728+ // only created when a peer is not connected when a request is made.
729+ // Thus, these requests must be considered failed, even if there is
730+ // another, concurrent dialing attempt ongoing.
731+ if let Some ( pending) = self . pending_outbound_requests . remove ( & key) {
732+ for request in pending {
733+ self . pending_events
734+ . push_back ( ToSwarm :: GenerateEvent ( Event :: OutboundFailure {
735+ peer : peer_id,
736+ request_id : request. request_id ,
737+ error : OutboundFailure :: DialFailure ,
738+ } ) ) ;
692739 }
693740 }
694741 }
@@ -703,7 +750,7 @@ where
703750 ) {
704751 let mut connection = Connection :: new ( connection_id, remote_address) ;
705752
706- if let Some ( pending_requests) = self . pending_outbound_requests . remove ( & peer) {
753+ if let Some ( pending_requests) = self . pending_outbound_requests . remove ( & peer. into ( ) ) {
707754 for request in pending_requests {
708755 connection
709756 . pending_outbound_responses
@@ -887,7 +934,7 @@ where
887934
888935 self . pending_events
889936 . push_back ( ToSwarm :: GenerateEvent ( Event :: OutboundFailure {
890- peer,
937+ peer : Some ( peer ) ,
891938 request_id,
892939 error : OutboundFailure :: Timeout ,
893940 } ) ) ;
@@ -901,7 +948,7 @@ where
901948
902949 self . pending_events
903950 . push_back ( ToSwarm :: GenerateEvent ( Event :: OutboundFailure {
904- peer,
951+ peer : Some ( peer ) ,
905952 request_id,
906953 error : OutboundFailure :: UnsupportedProtocols ,
907954 } ) ) ;
@@ -912,7 +959,7 @@ where
912959
913960 self . pending_events
914961 . push_back ( ToSwarm :: GenerateEvent ( Event :: OutboundFailure {
915- peer,
962+ peer : Some ( peer ) ,
916963 request_id,
917964 error : OutboundFailure :: Io ( error) ,
918965 } ) )
0 commit comments