*: Dial with handler and return handler on error and closed (#2191)

Require `NetworkBehaviourAction::{DialPeer,DialAddress}` to contain a
`ProtocolsHandler`. This allows a behaviour to attach custom state to its
handler. The behaviour would no longer need to track this state separately
during connection establishment, thus reducing state required in a behaviour.
E.g. in the case of `libp2p-kad` the behaviour can include a `GetRecord` request
in its handler, or e.g. in the case of `libp2p-request-response` the behaviour
can include the first request in the handler.

Return `ProtocolsHandler` on connection error and close. This allows a behaviour
to extract its custom state previously included in the handler on connection
failure and connection closing. E.g. in the case of `libp2p-kad` the behaviour
could extract the attached `GetRecord` from the handler of the failed connection
and then start another connection attempt with a new handler with the same
`GetRecord` or bubble up an error to the user.

Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
Max Inden
2021-08-31 17:00:51 +02:00
committed by GitHub
parent b55ee69645
commit c161acfb50
38 changed files with 1111 additions and 477 deletions

View File

@ -68,7 +68,8 @@ use futures::channel::oneshot;
use handler::{RequestProtocol, RequestResponseHandler, RequestResponseHandlerEvent};
use libp2p_core::{connection::ConnectionId, ConnectedPoint, Multiaddr, PeerId};
use libp2p_swarm::{
DialPeerCondition, NetworkBehaviour, NetworkBehaviourAction, NotifyHandler, PollParameters,
DialError, DialPeerCondition, IntoProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction,
NotifyHandler, PollParameters,
};
use smallvec::SmallVec;
use std::{
@ -303,7 +304,7 @@ impl RequestResponseConfig {
/// A request/response protocol for some message codec.
pub struct RequestResponse<TCodec>
where
TCodec: RequestResponseCodec,
TCodec: RequestResponseCodec + Clone + Send + 'static,
{
/// The supported inbound protocols.
inbound_protocols: SmallVec<[TCodec::Protocol; 2]>,
@ -320,8 +321,8 @@ where
/// Pending events to return from `poll`.
pending_events: VecDeque<
NetworkBehaviourAction<
RequestProtocol<TCodec>,
RequestResponseEvent<TCodec::Request, TCodec::Response>,
RequestResponseHandler<TCodec>,
>,
>,
/// The currently connected peers, their pending outbound and inbound responses and their known,
@ -336,7 +337,7 @@ where
impl<TCodec> RequestResponse<TCodec>
where
TCodec: RequestResponseCodec + Clone,
TCodec: RequestResponseCodec + Clone + Send + 'static,
{
/// Creates a new `RequestResponse` behaviour for the given
/// protocols, codec and configuration.
@ -403,10 +404,12 @@ where
};
if let Some(request) = self.try_send_request(peer, request) {
let handler = self.new_handler();
self.pending_events
.push_back(NetworkBehaviourAction::DialPeer {
peer_id: *peer,
condition: DialPeerCondition::Disconnected,
handler,
});
self.pending_outbound_requests
.entry(*peer)
@ -639,6 +642,7 @@ where
peer_id: &PeerId,
conn: &ConnectionId,
_: &ConnectedPoint,
_: <Self::ProtocolsHandler as IntoProtocolsHandler>::Handler,
) {
let connections = self
.connected
@ -682,7 +686,7 @@ where
self.connected.remove(peer);
}
fn inject_dial_failure(&mut self, peer: &PeerId) {
fn inject_dial_failure(&mut self, peer: &PeerId, _: Self::ProtocolsHandler, _: DialError) {
// If there are pending outgoing requests when a dial failure occurs,
// it is implied that we are not connected to the peer, since pending
// outgoing requests are drained when a connection is established and
@ -863,12 +867,7 @@ where
&mut self,
_: &mut Context<'_>,
_: &mut impl PollParameters,
) -> Poll<
NetworkBehaviourAction<
RequestProtocol<TCodec>,
RequestResponseEvent<TCodec::Request, TCodec::Response>,
>,
> {
) -> Poll<NetworkBehaviourAction<Self::OutEvent, Self::ProtocolsHandler>> {
if let Some(ev) = self.pending_events.pop_front() {
return Poll::Ready(ev);
} else if self.pending_events.capacity() > EMPTY_QUEUE_SHRINK_THRESHOLD {