@@ -17,7 +17,7 @@ use std::marker::PhantomData;
17
17
use std:: sync:: Arc ;
18
18
use std:: task:: { Context , Poll } ;
19
19
use std:: time:: Duration ;
20
- use tracing:: { debug, error , instrument, trace} ;
20
+ use tracing:: { debug, instrument, trace} ;
21
21
use types:: { EthSpec , ForkContext } ;
22
22
23
23
pub ( crate ) use handler:: { HandlerErr , HandlerEvent } ;
@@ -98,6 +98,13 @@ pub struct InboundRequestId {
98
98
substream_id : SubstreamId ,
99
99
}
100
100
101
+ // An Active inbound request received via Rpc.
102
+ struct ActiveInboundRequest < E : EthSpec > {
103
+ pub peer_id : PeerId ,
104
+ pub request_type : RequestType < E > ,
105
+ pub peer_disconnected : bool ,
106
+ }
107
+
101
108
impl InboundRequestId {
102
109
/// Creates an _unchecked_ [`InboundRequestId`].
103
110
///
@@ -150,7 +157,7 @@ pub struct RPC<Id: ReqId, E: EthSpec> {
150
157
/// Rate limiter for our own requests.
151
158
outbound_request_limiter : SelfRateLimiter < Id , E > ,
152
159
/// Active inbound requests that are awaiting a response.
153
- active_inbound_requests : HashMap < InboundRequestId , ( PeerId , RequestType < E > ) > ,
160
+ active_inbound_requests : HashMap < InboundRequestId , ActiveInboundRequest < E > > ,
154
161
/// Queue of events to be processed.
155
162
events : Vec < BehaviourAction < Id , E > > ,
156
163
fork_context : Arc < ForkContext > ,
@@ -199,8 +206,7 @@ impl<Id: ReqId, E: EthSpec> RPC<Id, E> {
199
206
}
200
207
201
208
/// Sends an RPC response.
202
- ///
203
- /// The peer must be connected for this to succeed.
209
+ /// Returns an `Err` if the request does exist in the active inbound requests list.
204
210
#[ instrument( parent = None ,
205
211
level = "trace" ,
206
212
fields( service = "libp2p_rpc" ) ,
@@ -209,26 +215,41 @@ impl<Id: ReqId, E: EthSpec> RPC<Id, E> {
209
215
) ]
210
216
pub fn send_response (
211
217
& mut self ,
212
- peer_id : PeerId ,
213
218
request_id : InboundRequestId ,
214
219
response : RpcResponse < E > ,
215
- ) {
216
- let Some ( ( _peer_id, request_type) ) = self . active_inbound_requests . remove ( & request_id)
220
+ ) -> Result < ( ) , RpcResponse < E > > {
221
+ let Some ( ActiveInboundRequest {
222
+ peer_id,
223
+ request_type,
224
+ peer_disconnected,
225
+ } ) = self . active_inbound_requests . remove ( & request_id)
217
226
else {
218
- error ! ( %peer_id, ?request_id, %response, "Request not found in active_inbound_requests. Response not sent" ) ;
219
- return ;
227
+ return Err ( response) ;
220
228
} ;
221
229
222
230
// Add the request back to active requests if the response is `Success` and requires stream
223
231
// termination.
224
232
if request_type. protocol ( ) . terminator ( ) . is_some ( )
225
233
&& matches ! ( response, RpcResponse :: Success ( _) )
226
234
{
227
- self . active_inbound_requests
228
- . insert ( request_id, ( peer_id, request_type. clone ( ) ) ) ;
235
+ self . active_inbound_requests . insert (
236
+ request_id,
237
+ ActiveInboundRequest {
238
+ peer_id,
239
+ request_type : request_type. clone ( ) ,
240
+ peer_disconnected,
241
+ } ,
242
+ ) ;
243
+ }
244
+
245
+ if peer_disconnected {
246
+ trace ! ( %peer_id, ?request_id, %response,
247
+ "Discarding response, peer is no longer connected" ) ;
248
+ return Ok ( ( ) ) ;
229
249
}
230
250
231
251
self . send_response_inner ( peer_id, request_type. protocol ( ) , request_id, response) ;
252
+ Ok ( ( ) )
232
253
}
233
254
234
255
fn send_response_inner (
@@ -425,9 +446,10 @@ where
425
446
self . events . push ( error_msg) ;
426
447
}
427
448
428
- self . active_inbound_requests . retain (
429
- |_inbound_request_id, ( request_peer_id, _request_type) | * request_peer_id != peer_id,
430
- ) ;
449
+ self . active_inbound_requests
450
+ . values_mut ( )
451
+ . filter ( |request| request. peer_id == peer_id)
452
+ . for_each ( |request| request. peer_disconnected = true ) ;
431
453
432
454
if let Some ( limiter) = self . response_limiter . as_mut ( ) {
433
455
limiter. peer_disconnected ( peer_id) ;
@@ -468,9 +490,17 @@ where
468
490
. active_inbound_requests
469
491
. iter ( )
470
492
. filter (
471
- |( _inbound_request_id, ( request_peer_id, active_request_type) ) | {
493
+ |(
494
+ _inbound_request_id,
495
+ ActiveInboundRequest {
496
+ peer_id : request_peer_id,
497
+ request_type : active_request_type,
498
+ peer_disconnected,
499
+ } ,
500
+ ) | {
472
501
* request_peer_id == peer_id
473
502
&& active_request_type. protocol ( ) == request_type. protocol ( )
503
+ && !peer_disconnected
474
504
} ,
475
505
)
476
506
. count ( )
@@ -494,19 +524,25 @@ where
494
524
}
495
525
496
526
// Requests that are below the limit on the number of simultaneous requests are added to the active inbound requests.
497
- self . active_inbound_requests
498
- . insert ( request_id, ( peer_id, request_type. clone ( ) ) ) ;
527
+ self . active_inbound_requests . insert (
528
+ request_id,
529
+ ActiveInboundRequest {
530
+ peer_id,
531
+ request_type : request_type. clone ( ) ,
532
+ peer_disconnected : false ,
533
+ } ,
534
+ ) ;
499
535
500
536
// If we received a Ping, we queue a Pong response.
501
537
if let RequestType :: Ping ( _) = request_type {
502
538
trace ! ( connection_id = %connection_id, %peer_id, "Received Ping, queueing Pong" ) ;
503
539
self . send_response (
504
- peer_id,
505
540
request_id,
506
541
RpcResponse :: Success ( RpcSuccessResponse :: Pong ( Ping {
507
542
data : self . seq_number ,
508
543
} ) ) ,
509
- ) ;
544
+ )
545
+ . expect ( "Request to exist" ) ;
510
546
}
511
547
512
548
self . events . push ( ToSwarm :: GenerateEvent ( RPCMessage {
0 commit comments