mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Implement request-responses protocols (#6634)
* Implement request-responses protocols * Add tests * Fix sc-cli * Apply suggestions from code review Co-authored-by: Max Inden <mail@max-inden.de> * Fix naming * Fix other issues * Other naming fix * Fix error logging * Max sizes to u64 * Don't kill connections on refusal to process * Adjust comment Co-authored-by: Max Inden <mail@max-inden.de>
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
config::{ProtocolId, Role}, block_requests, light_client_handler, finality_requests,
|
||||
peer_info, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut},
|
||||
peer_info, request_responses, discovery::{DiscoveryBehaviour, DiscoveryConfig, DiscoveryOut},
|
||||
protocol::{message::{self, Roles}, CustomMessageOutcome, NotificationsSink, Protocol},
|
||||
ObservedRole, DhtEvent, ExHashT,
|
||||
};
|
||||
@@ -39,6 +39,10 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub use crate::request_responses::{
|
||||
ResponseFailure, InboundFailure, RequestFailure, OutboundFailure, RequestId, SendRequestError
|
||||
};
|
||||
|
||||
/// General behaviour of the network. Combines all protocols together.
|
||||
#[derive(NetworkBehaviour)]
|
||||
#[behaviour(out_event = "BehaviourOut<B>", poll_method = "poll")]
|
||||
@@ -50,6 +54,8 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
|
||||
peer_info: peer_info::PeerInfoBehaviour,
|
||||
/// Discovers nodes of the network.
|
||||
discovery: DiscoveryBehaviour,
|
||||
/// Generic request-reponse protocols.
|
||||
request_responses: request_responses::RequestResponsesBehaviour,
|
||||
/// Block request handling.
|
||||
block_requests: block_requests::BlockRequests<B>,
|
||||
/// Finality proof request handling.
|
||||
@@ -76,22 +82,40 @@ pub enum BehaviourOut<B: BlockT> {
|
||||
RandomKademliaStarted(ProtocolId),
|
||||
|
||||
/// We have received a request from a peer and answered it.
|
||||
AnsweredRequest {
|
||||
///
|
||||
/// This event is generated for statistics purposes.
|
||||
InboundRequest {
|
||||
/// Peer which sent us a request.
|
||||
peer: PeerId,
|
||||
/// Protocol name of the request.
|
||||
protocol: String,
|
||||
/// Time it took to build the response.
|
||||
build_time: Duration,
|
||||
protocol: Cow<'static, str>,
|
||||
/// If `Ok`, contains the time elapsed between when we received the request and when we
|
||||
/// sent back the response. If `Err`, the error that happened.
|
||||
result: Result<Duration, ResponseFailure>,
|
||||
},
|
||||
|
||||
/// A request initiated using [`Behaviour::send_request`] has succeeded or failed.
|
||||
RequestFinished {
|
||||
/// Request that has succeeded.
|
||||
request_id: RequestId,
|
||||
/// Response sent by the remote or reason for failure.
|
||||
result: Result<Vec<u8>, RequestFailure>,
|
||||
},
|
||||
|
||||
/// Started a new request with the given node.
|
||||
RequestStarted {
|
||||
///
|
||||
/// This event is for statistics purposes only. The request and response handling are entirely
|
||||
/// internal to the behaviour.
|
||||
OpaqueRequestStarted {
|
||||
peer: PeerId,
|
||||
/// Protocol name of the request.
|
||||
protocol: String,
|
||||
},
|
||||
/// Finished, successfully or not, a previously-started request.
|
||||
RequestFinished {
|
||||
///
|
||||
/// This event is for statistics purposes only. The request and response handling are entirely
|
||||
/// internal to the behaviour.
|
||||
OpaqueRequestFinished {
|
||||
/// Who we were requesting.
|
||||
peer: PeerId,
|
||||
/// Protocol name of the request.
|
||||
@@ -161,17 +185,20 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
||||
finality_proof_requests: finality_requests::FinalityProofRequests<B>,
|
||||
light_client_handler: light_client_handler::LightClientHandler<B>,
|
||||
disco_config: DiscoveryConfig,
|
||||
) -> Self {
|
||||
Behaviour {
|
||||
request_response_protocols: Vec<request_responses::ProtocolConfig>,
|
||||
) -> Result<Self, request_responses::RegisterError> {
|
||||
Ok(Behaviour {
|
||||
substrate,
|
||||
peer_info: peer_info::PeerInfoBehaviour::new(user_agent, local_public_key),
|
||||
discovery: disco_config.finish(),
|
||||
request_responses:
|
||||
request_responses::RequestResponsesBehaviour::new(request_response_protocols.into_iter())?,
|
||||
block_requests,
|
||||
finality_proof_requests,
|
||||
light_client_handler,
|
||||
events: VecDeque::new(),
|
||||
role,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the list of nodes that we know exist in the network.
|
||||
@@ -208,6 +235,16 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
|
||||
self.peer_info.node(peer_id)
|
||||
}
|
||||
|
||||
/// Initiates sending a request.
|
||||
///
|
||||
/// An error is returned if we are not connected to the target peer of if the protocol doesn't
|
||||
/// match one that has been registered.
|
||||
pub fn send_request(&mut self, target: &PeerId, protocol: &str, request: Vec<u8>)
|
||||
-> Result<RequestId, SendRequestError>
|
||||
{
|
||||
self.request_responses.send_request(target, protocol, request)
|
||||
}
|
||||
|
||||
/// Registers a new notifications protocol.
|
||||
///
|
||||
/// Please call `event_stream` before registering a protocol, otherwise you may miss events
|
||||
@@ -298,18 +335,18 @@ Behaviour<B, H> {
|
||||
CustomMessageOutcome::BlockRequest { target, request } => {
|
||||
match self.block_requests.send_request(&target, request) {
|
||||
block_requests::SendRequestOutcome::Ok => {
|
||||
self.events.push_back(BehaviourOut::RequestStarted {
|
||||
self.events.push_back(BehaviourOut::OpaqueRequestStarted {
|
||||
peer: target,
|
||||
protocol: self.block_requests.protocol_name().to_owned(),
|
||||
});
|
||||
},
|
||||
block_requests::SendRequestOutcome::Replaced { request_duration, .. } => {
|
||||
self.events.push_back(BehaviourOut::RequestFinished {
|
||||
self.events.push_back(BehaviourOut::OpaqueRequestFinished {
|
||||
peer: target.clone(),
|
||||
protocol: self.block_requests.protocol_name().to_owned(),
|
||||
request_duration,
|
||||
});
|
||||
self.events.push_back(BehaviourOut::RequestStarted {
|
||||
self.events.push_back(BehaviourOut::OpaqueRequestStarted {
|
||||
peer: target,
|
||||
protocol: self.block_requests.protocol_name().to_owned(),
|
||||
});
|
||||
@@ -358,18 +395,39 @@ Behaviour<B, H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<request_responses::Event> for Behaviour<B, H> {
|
||||
fn inject_event(&mut self, event: request_responses::Event) {
|
||||
match event {
|
||||
request_responses::Event::InboundRequest { peer, protocol, result } => {
|
||||
self.events.push_back(BehaviourOut::InboundRequest {
|
||||
peer,
|
||||
protocol,
|
||||
result,
|
||||
});
|
||||
}
|
||||
|
||||
request_responses::Event::RequestFinished { request_id, result } => {
|
||||
self.events.push_back(BehaviourOut::RequestFinished {
|
||||
request_id,
|
||||
result,
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<block_requests::Event<B>> for Behaviour<B, H> {
|
||||
fn inject_event(&mut self, event: block_requests::Event<B>) {
|
||||
match event {
|
||||
block_requests::Event::AnsweredRequest { peer, total_handling_time } => {
|
||||
self.events.push_back(BehaviourOut::AnsweredRequest {
|
||||
self.events.push_back(BehaviourOut::InboundRequest {
|
||||
peer,
|
||||
protocol: self.block_requests.protocol_name().to_owned(),
|
||||
build_time: total_handling_time,
|
||||
protocol: self.block_requests.protocol_name().to_owned().into(),
|
||||
result: Ok(total_handling_time),
|
||||
});
|
||||
},
|
||||
block_requests::Event::Response { peer, original_request: _, response, request_duration } => {
|
||||
self.events.push_back(BehaviourOut::RequestFinished {
|
||||
self.events.push_back(BehaviourOut::OpaqueRequestFinished {
|
||||
peer: peer.clone(),
|
||||
protocol: self.block_requests.protocol_name().to_owned(),
|
||||
request_duration,
|
||||
@@ -381,7 +439,7 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<block_requests::Event<B
|
||||
block_requests::Event::RequestTimeout { peer, request_duration, .. } => {
|
||||
// There doesn't exist any mechanism to report cancellations or timeouts yet, so
|
||||
// we process them by disconnecting the node.
|
||||
self.events.push_back(BehaviourOut::RequestFinished {
|
||||
self.events.push_back(BehaviourOut::OpaqueRequestFinished {
|
||||
peer: peer.clone(),
|
||||
protocol: self.block_requests.protocol_name().to_owned(),
|
||||
request_duration,
|
||||
|
||||
Reference in New Issue
Block a user