Improve substream management (#3261)
## Issue Addressed Which issue # does this PR address? ## Proposed Changes Please list or describe the changes introduced by this PR. ## Additional Info Please provide any additional information. For example, future considerations or information useful for reviewers.
This commit is contained in:
parent
11d80a6a38
commit
3dd50bda11
@ -1006,9 +1006,6 @@ where
|
|||||||
proto,
|
proto,
|
||||||
error,
|
error,
|
||||||
} => {
|
} => {
|
||||||
if matches!(error, RPCError::HandlerRejected) {
|
|
||||||
// this peer's request got canceled
|
|
||||||
}
|
|
||||||
// Inform the peer manager of the error.
|
// Inform the peer manager of the error.
|
||||||
// An inbound error here means we sent an error to the peer, or the stream
|
// An inbound error here means we sent an error to the peer, or the stream
|
||||||
// timed out.
|
// timed out.
|
||||||
|
@ -457,10 +457,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
debug!(self.log, "Internal RPC Error"; "error" => %e, "peer_id" => %peer_id);
|
debug!(self.log, "Internal RPC Error"; "error" => %e, "peer_id" => %peer_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RPCError::HandlerRejected => {
|
RPCError::HandlerRejected => PeerAction::Fatal,
|
||||||
// Our fault. Do nothing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RPCError::InvalidData(_) => {
|
RPCError::InvalidData(_) => {
|
||||||
// Peer is not complying with the protocol. This is considered a malicious action
|
// Peer is not complying with the protocol. This is considered a malicious action
|
||||||
PeerAction::Fatal
|
PeerAction::Fatal
|
||||||
|
@ -40,6 +40,9 @@ const IO_ERROR_RETRIES: u8 = 3;
|
|||||||
/// Maximum time given to the handler to perform shutdown operations.
|
/// Maximum time given to the handler to perform shutdown operations.
|
||||||
const SHUTDOWN_TIMEOUT_SECS: u8 = 15;
|
const SHUTDOWN_TIMEOUT_SECS: u8 = 15;
|
||||||
|
|
||||||
|
/// Maximum number of simultaneous inbound substreams we keep for this peer.
|
||||||
|
const MAX_INBOUND_SUBSTREAMS: usize = 32;
|
||||||
|
|
||||||
/// Identifier of inbound and outbound substreams from the handler's perspective.
|
/// Identifier of inbound and outbound substreams from the handler's perspective.
|
||||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||||
pub struct SubstreamId(usize);
|
pub struct SubstreamId(usize);
|
||||||
@ -241,7 +244,7 @@ where
|
|||||||
// We now drive to completion communications already dialed/established
|
// We now drive to completion communications already dialed/established
|
||||||
while let Some((id, req)) = self.dial_queue.pop() {
|
while let Some((id, req)) = self.dial_queue.pop() {
|
||||||
self.events_out.push(Err(HandlerErr::Outbound {
|
self.events_out.push(Err(HandlerErr::Outbound {
|
||||||
error: RPCError::HandlerRejected,
|
error: RPCError::Disconnected,
|
||||||
proto: req.protocol(),
|
proto: req.protocol(),
|
||||||
id,
|
id,
|
||||||
}));
|
}));
|
||||||
@ -265,7 +268,7 @@ where
|
|||||||
self.dial_queue.push((id, req));
|
self.dial_queue.push((id, req));
|
||||||
}
|
}
|
||||||
_ => self.events_out.push(Err(HandlerErr::Outbound {
|
_ => self.events_out.push(Err(HandlerErr::Outbound {
|
||||||
error: RPCError::HandlerRejected,
|
error: RPCError::Disconnected,
|
||||||
proto: req.protocol(),
|
proto: req.protocol(),
|
||||||
id,
|
id,
|
||||||
})),
|
})),
|
||||||
@ -339,23 +342,32 @@ where
|
|||||||
|
|
||||||
// store requests that expect responses
|
// store requests that expect responses
|
||||||
if expected_responses > 0 {
|
if expected_responses > 0 {
|
||||||
// Store the stream and tag the output.
|
if self.inbound_substreams.len() < MAX_INBOUND_SUBSTREAMS {
|
||||||
let delay_key = self.inbound_substreams_delay.insert(
|
// Store the stream and tag the output.
|
||||||
self.current_inbound_substream_id,
|
let delay_key = self.inbound_substreams_delay.insert(
|
||||||
Duration::from_secs(RESPONSE_TIMEOUT),
|
self.current_inbound_substream_id,
|
||||||
);
|
Duration::from_secs(RESPONSE_TIMEOUT),
|
||||||
let awaiting_stream = InboundState::Idle(substream);
|
);
|
||||||
self.inbound_substreams.insert(
|
let awaiting_stream = InboundState::Idle(substream);
|
||||||
self.current_inbound_substream_id,
|
self.inbound_substreams.insert(
|
||||||
InboundInfo {
|
self.current_inbound_substream_id,
|
||||||
state: awaiting_stream,
|
InboundInfo {
|
||||||
pending_items: VecDeque::with_capacity(expected_responses as usize),
|
state: awaiting_stream,
|
||||||
delay_key: Some(delay_key),
|
pending_items: VecDeque::with_capacity(expected_responses as usize),
|
||||||
protocol: req.protocol(),
|
delay_key: Some(delay_key),
|
||||||
request_start_time: Instant::now(),
|
protocol: req.protocol(),
|
||||||
remaining_chunks: expected_responses,
|
request_start_time: Instant::now(),
|
||||||
},
|
remaining_chunks: expected_responses,
|
||||||
);
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.events_out.push(Err(HandlerErr::Inbound {
|
||||||
|
id: self.current_inbound_substream_id,
|
||||||
|
proto: req.protocol(),
|
||||||
|
error: RPCError::HandlerRejected,
|
||||||
|
}));
|
||||||
|
return self.shutdown(None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we received a goodbye, shutdown the connection.
|
// If we received a goodbye, shutdown the connection.
|
||||||
@ -382,7 +394,7 @@ where
|
|||||||
// accept outbound connections only if the handler is not deactivated
|
// accept outbound connections only if the handler is not deactivated
|
||||||
if matches!(self.state, HandlerState::Deactivated) {
|
if matches!(self.state, HandlerState::Deactivated) {
|
||||||
self.events_out.push(Err(HandlerErr::Outbound {
|
self.events_out.push(Err(HandlerErr::Outbound {
|
||||||
error: RPCError::HandlerRejected,
|
error: RPCError::Disconnected,
|
||||||
proto,
|
proto,
|
||||||
id,
|
id,
|
||||||
}));
|
}));
|
||||||
@ -671,7 +683,7 @@ where
|
|||||||
{
|
{
|
||||||
// if the request was still active, report back to cancel it
|
// if the request was still active, report back to cancel it
|
||||||
self.events_out.push(Err(HandlerErr::Inbound {
|
self.events_out.push(Err(HandlerErr::Inbound {
|
||||||
error: RPCError::HandlerRejected,
|
error: RPCError::Disconnected,
|
||||||
proto: info.protocol,
|
proto: info.protocol,
|
||||||
id: *id,
|
id: *id,
|
||||||
}));
|
}));
|
||||||
@ -803,7 +815,7 @@ where
|
|||||||
// the handler is deactivated. Close the stream
|
// the handler is deactivated. Close the stream
|
||||||
entry.get_mut().state = OutboundSubstreamState::Closing(substream);
|
entry.get_mut().state = OutboundSubstreamState::Closing(substream);
|
||||||
self.events_out.push(Err(HandlerErr::Outbound {
|
self.events_out.push(Err(HandlerErr::Outbound {
|
||||||
error: RPCError::HandlerRejected,
|
error: RPCError::Disconnected,
|
||||||
proto: entry.get().proto,
|
proto: entry.get().proto,
|
||||||
id: entry.get().req_id,
|
id: entry.get().req_id,
|
||||||
}))
|
}))
|
||||||
|
Loading…
Reference in New Issue
Block a user