Move code from sc-network-common back to sc-network (#13592)

* Move service tests to `client/network/tests`

These tests depend on `sc-network` and `sc-network-sync` so they should
live outside the crate.

* Move some configs from `sc-network-common` to `sc-network`

* Move `NetworkService` traits to `sc-network`

* Move request-responses to `sc-network`

* Remove more stuff

* Remove rest of configs from `sc-network-common` to `sc-network`

* Remove more stuff

* Fix warnings

* Update client/network/src/request_responses.rs

Co-authored-by: Dmitry Markin <dmitry@markin.tech>

* Fix cargo doc

---------

Co-authored-by: Dmitry Markin <dmitry@markin.tech>
This commit is contained in:
Aaro Altonen
2023-03-14 14:06:40 +02:00
committed by GitHub
parent 5d718e45c1
commit 9ced14e2de
85 changed files with 1411 additions and 1434 deletions
+147 -13
View File
@@ -34,7 +34,8 @@
//! - If provided, a ["requests processing"](ProtocolConfig::inbound_queue) channel
//! is used to handle incoming requests.
use crate::ReputationChange;
use crate::{types::ProtocolName, ReputationChange};
use futures::{
channel::{mpsc, oneshot},
prelude::*,
@@ -43,7 +44,7 @@ use libp2p::{
core::{connection::ConnectionId, Multiaddr, PeerId},
request_response::{
handler::RequestResponseHandler, ProtocolSupport, RequestResponse, RequestResponseCodec,
RequestResponseConfig, RequestResponseEvent, RequestResponseMessage, ResponseChannel,
RequestResponseEvent, RequestResponseMessage, ResponseChannel,
},
swarm::{
behaviour::{ConnectionClosed, DialFailure, FromSwarm, ListenFailure},
@@ -52,12 +53,9 @@ use libp2p::{
PollParameters,
},
};
use sc_network_common::{
protocol::ProtocolName,
request_responses::{
IfDisconnected, IncomingRequest, OutgoingResponse, ProtocolConfig, RequestFailure,
},
};
use sc_peerset::{PeersetHandle, BANNED_THRESHOLD};
use std::{
collections::{hash_map::Entry, HashMap},
io, iter,
@@ -66,8 +64,138 @@ use std::{
time::{Duration, Instant},
};
pub use libp2p::request_response::{InboundFailure, OutboundFailure, RequestId};
use sc_peerset::{PeersetHandle, BANNED_THRESHOLD};
pub use libp2p::request_response::{
InboundFailure, OutboundFailure, RequestId, RequestResponseConfig,
};
/// Error in a request.
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum RequestFailure {
#[error("We are not currently connected to the requested peer.")]
NotConnected,
#[error("Given protocol hasn't been registered.")]
UnknownProtocol,
#[error("Remote has closed the substream before answering, thereby signaling that it considers the request as valid, but refused to answer it.")]
Refused,
#[error("The remote replied, but the local node is no longer interested in the response.")]
Obsolete,
#[error("Problem on the network: {0}")]
Network(OutboundFailure),
}
/// Configuration for a single request-response protocol.
#[derive(Debug, Clone)]
pub struct ProtocolConfig {
/// Name of the protocol on the wire. Should be something like `/foo/bar`.
pub name: ProtocolName,
/// Fallback on the wire protocol names to support.
pub fallback_names: Vec<ProtocolName>,
/// Maximum allowed size, in bytes, of a request.
///
/// Any request larger than this value will be declined as a way to avoid allocating too
/// much memory for it.
pub max_request_size: u64,
/// Maximum allowed size, in bytes, of a response.
///
/// Any response larger than this value will be declined as a way to avoid allocating too
/// much memory for it.
pub max_response_size: u64,
/// Duration after which emitted requests are considered timed out.
///
/// If you expect the response to come back quickly, you should set this to a smaller duration.
pub request_timeout: Duration,
/// Channel on which the networking service will send incoming requests.
///
/// Every time a peer sends a request to the local node using this protocol, the networking
/// service will push an element on this channel. The receiving side of this channel then has
/// to pull this element, process the request, and send back the response to send back to the
/// peer.
///
/// The size of the channel has to be carefully chosen. If the channel is full, the networking
/// service will discard the incoming request send back an error to the peer. Consequently,
/// the channel being full is an indicator that the node is overloaded.
///
/// You can typically set the size of the channel to `T / d`, where `T` is the
/// `request_timeout` and `d` is the expected average duration of CPU and I/O it takes to
/// build a response.
///
/// Can be `None` if the local node does not support answering incoming requests.
/// If this is `None`, then the local node will not advertise support for this protocol towards
/// other peers. If this is `Some` but the channel is closed, then the local node will
/// advertise support for this protocol, but any incoming request will lead to an error being
/// sent back.
pub inbound_queue: Option<mpsc::Sender<IncomingRequest>>,
}
/// A single request received by a peer on a request-response protocol.
#[derive(Debug)]
pub struct IncomingRequest {
/// Who sent the request.
pub peer: PeerId,
/// Request sent by the remote. Will always be smaller than
/// [`ProtocolConfig::max_request_size`].
pub payload: Vec<u8>,
/// Channel to send back the response.
///
/// There are two ways to indicate that handling the request failed:
///
/// 1. Drop `pending_response` and thus not changing the reputation of the peer.
///
/// 2. Sending an `Err(())` via `pending_response`, optionally including reputation changes for
/// the given peer.
pub pending_response: oneshot::Sender<OutgoingResponse>,
}
/// Response for an incoming request to be send by a request protocol handler.
#[derive(Debug)]
pub struct OutgoingResponse {
/// The payload of the response.
///
/// `Err(())` if none is available e.g. due an error while handling the request.
pub result: Result<Vec<u8>, ()>,
/// Reputation changes accrued while handling the request. To be applied to the reputation of
/// the peer sending the request.
pub reputation_changes: Vec<ReputationChange>,
/// If provided, the `oneshot::Sender` will be notified when the request has been sent to the
/// peer.
///
/// > **Note**: Operating systems typically maintain a buffer of a few dozen kilobytes of
/// > outgoing data for each TCP socket, and it is not possible for a user
/// > application to inspect this buffer. This channel here is not actually notified
/// > when the response has been fully sent out, but rather when it has fully been
/// > written to the buffer managed by the operating system.
pub sent_feedback: Option<oneshot::Sender<()>>,
}
/// When sending a request, what to do on a disconnected recipient.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum IfDisconnected {
/// Try to connect to the peer.
TryConnect,
/// Just fail if the destination is not yet connected.
ImmediateError,
}
/// Convenience functions for `IfDisconnected`.
impl IfDisconnected {
/// Shall we connect to a disconnected peer?
pub fn should_connect(self) -> bool {
match self {
Self::TryConnect => true,
Self::ImmediateError => false,
}
}
}
/// Event generated by the [`RequestResponsesBehaviour`].
#[derive(Debug)]
@@ -103,7 +231,12 @@ pub enum Event {
},
/// A request protocol handler issued reputation changes for the given peer.
ReputationChanges { peer: PeerId, changes: Vec<ReputationChange> },
ReputationChanges {
/// Peer whose reputation needs to be adjust.
peer: PeerId,
/// Reputation changes.
changes: Vec<ReputationChange>,
},
}
/// Combination of a protocol name and a request id.
@@ -344,7 +477,7 @@ impl NetworkBehaviour for RequestResponsesBehaviour {
)
}
},
FromSwarm::DialFailure(DialFailure { peer_id, error, handler }) =>
FromSwarm::DialFailure(DialFailure { peer_id, error, handler }) => {
for (p_name, p_handler) in handler.into_iter() {
if let Some((proto, _)) = self.protocols.get_mut(p_name.as_str()) {
proto.on_swarm_event(FromSwarm::DialFailure(DialFailure {
@@ -359,7 +492,8 @@ impl NetworkBehaviour for RequestResponsesBehaviour {
p_name,
)
}
},
}
},
FromSwarm::ListenerClosed(e) =>
for (p, _) in self.protocols.values_mut() {
NetworkBehaviour::on_swarm_event(p, FromSwarm::ListenerClosed(e));