mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-28 01:01:34 +00:00
Simplify trait bounds on NetworkBehaviour (#1405)
* Simplify trait bounds requirements * More work * Moar * Finish * Fix final tests * More simplification * Use separate traits for Inbound/Outbound * Update gossipsub and remove warnings * Add documentation to swarm * Remove BoxSubstream * Fix tests not compiling * Fix stack overflow * Address concerns * For some reason my IDE ignored libp2p-kad
This commit is contained in:
@ -25,6 +25,7 @@ use crate::protocol::{
|
||||
use crate::record::{self, Record};
|
||||
use futures::prelude::*;
|
||||
use libp2p_swarm::{
|
||||
NegotiatedSubstream,
|
||||
KeepAlive,
|
||||
SubstreamProtocol,
|
||||
ProtocolsHandler,
|
||||
@ -33,7 +34,7 @@ use libp2p_swarm::{
|
||||
};
|
||||
use libp2p_core::{
|
||||
either::EitherOutput,
|
||||
upgrade::{self, InboundUpgrade, OutboundUpgrade, Negotiated}
|
||||
upgrade::{self, InboundUpgrade, OutboundUpgrade}
|
||||
};
|
||||
use log::trace;
|
||||
use std::{borrow::Cow, error, fmt, io, pin::Pin, task::Context, task::Poll, time::Duration};
|
||||
@ -45,10 +46,7 @@ use wasm_timer::Instant;
|
||||
/// make.
|
||||
///
|
||||
/// It also handles requests made by the remote.
|
||||
pub struct KademliaHandler<TSubstream, TUserData>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
pub struct KademliaHandler<TUserData> {
|
||||
/// Configuration for the Kademlia protocol.
|
||||
config: KademliaProtocolConfig,
|
||||
|
||||
@ -59,51 +57,45 @@ where
|
||||
next_connec_unique_id: UniqueConnecId,
|
||||
|
||||
/// List of active substreams with the state they are in.
|
||||
substreams: Vec<SubstreamState<TSubstream, TUserData>>,
|
||||
substreams: Vec<SubstreamState<TUserData>>,
|
||||
|
||||
/// Until when to keep the connection alive.
|
||||
keep_alive: KeepAlive,
|
||||
}
|
||||
|
||||
/// State of an active substream, opened either by us or by the remote.
|
||||
enum SubstreamState<TSubstream, TUserData>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
enum SubstreamState<TUserData> {
|
||||
/// We haven't started opening the outgoing substream yet.
|
||||
/// Contains the request we want to send, and the user data if we expect an answer.
|
||||
OutPendingOpen(KadRequestMsg, Option<TUserData>),
|
||||
/// Waiting to send a message to the remote.
|
||||
OutPendingSend(
|
||||
KadOutStreamSink<Negotiated<TSubstream>>,
|
||||
KadOutStreamSink<NegotiatedSubstream>,
|
||||
KadRequestMsg,
|
||||
Option<TUserData>,
|
||||
),
|
||||
/// Waiting to flush the substream so that the data arrives to the remote.
|
||||
OutPendingFlush(KadOutStreamSink<Negotiated<TSubstream>>, Option<TUserData>),
|
||||
OutPendingFlush(KadOutStreamSink<NegotiatedSubstream>, Option<TUserData>),
|
||||
/// Waiting for an answer back from the remote.
|
||||
// TODO: add timeout
|
||||
OutWaitingAnswer(KadOutStreamSink<Negotiated<TSubstream>>, TUserData),
|
||||
OutWaitingAnswer(KadOutStreamSink<NegotiatedSubstream>, TUserData),
|
||||
/// An error happened on the substream and we should report the error to the user.
|
||||
OutReportError(KademliaHandlerQueryErr, TUserData),
|
||||
/// The substream is being closed.
|
||||
OutClosing(KadOutStreamSink<Negotiated<TSubstream>>),
|
||||
OutClosing(KadOutStreamSink<NegotiatedSubstream>),
|
||||
/// Waiting for a request from the remote.
|
||||
InWaitingMessage(UniqueConnecId, KadInStreamSink<Negotiated<TSubstream>>),
|
||||
InWaitingMessage(UniqueConnecId, KadInStreamSink<NegotiatedSubstream>),
|
||||
/// Waiting for the user to send a `KademliaHandlerIn` event containing the response.
|
||||
InWaitingUser(UniqueConnecId, KadInStreamSink<Negotiated<TSubstream>>),
|
||||
InWaitingUser(UniqueConnecId, KadInStreamSink<NegotiatedSubstream>),
|
||||
/// Waiting to send an answer back to the remote.
|
||||
InPendingSend(UniqueConnecId, KadInStreamSink<Negotiated<TSubstream>>, KadResponseMsg),
|
||||
InPendingSend(UniqueConnecId, KadInStreamSink<NegotiatedSubstream>, KadResponseMsg),
|
||||
/// Waiting to flush an answer back to the remote.
|
||||
InPendingFlush(UniqueConnecId, KadInStreamSink<Negotiated<TSubstream>>),
|
||||
InPendingFlush(UniqueConnecId, KadInStreamSink<NegotiatedSubstream>),
|
||||
/// The substream is being closed.
|
||||
InClosing(KadInStreamSink<Negotiated<TSubstream>>),
|
||||
InClosing(KadInStreamSink<NegotiatedSubstream>),
|
||||
}
|
||||
|
||||
impl<TSubstream, TUserData> SubstreamState<TSubstream, TUserData>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
impl<TUserData> SubstreamState<TUserData> {
|
||||
/// Tries to close the substream.
|
||||
///
|
||||
/// If the substream is not ready to be closed, returns it back.
|
||||
@ -379,10 +371,7 @@ pub struct KademliaRequestId {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
struct UniqueConnecId(u64);
|
||||
|
||||
impl<TSubstream, TUserData> KademliaHandler<TSubstream, TUserData>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
impl<TUserData> KademliaHandler<TUserData> {
|
||||
/// Create a `KademliaHandler` that only allows sending messages to the remote but denying
|
||||
/// incoming connections.
|
||||
pub fn dial_only() -> Self {
|
||||
@ -415,25 +404,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSubstream, TUserData> Default for KademliaHandler<TSubstream, TUserData>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
impl<TUserData> Default for KademliaHandler<TUserData> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
KademliaHandler::dial_and_listen()
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSubstream, TUserData> ProtocolsHandler for KademliaHandler<TSubstream, TUserData>
|
||||
impl<TUserData> ProtocolsHandler for KademliaHandler<TUserData>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
TUserData: Clone,
|
||||
TUserData: Clone + Send + 'static,
|
||||
{
|
||||
type InEvent = KademliaHandlerIn<TUserData>;
|
||||
type OutEvent = KademliaHandlerEvent<TUserData>;
|
||||
type Error = io::Error; // TODO: better error type?
|
||||
type Substream = TSubstream;
|
||||
type InboundProtocol = upgrade::EitherUpgrade<KademliaProtocolConfig, upgrade::DeniedUpgrade>;
|
||||
type OutboundProtocol = KademliaProtocolConfig;
|
||||
// Message of the request to send to the remote, and user data if we expect an answer.
|
||||
@ -450,7 +434,7 @@ where
|
||||
|
||||
fn inject_fully_negotiated_outbound(
|
||||
&mut self,
|
||||
protocol: <Self::OutboundProtocol as OutboundUpgrade<Negotiated<TSubstream>>>::Output,
|
||||
protocol: <Self::OutboundProtocol as OutboundUpgrade<NegotiatedSubstream>>::Output,
|
||||
(msg, user_data): Self::OutboundOpenInfo,
|
||||
) {
|
||||
self.substreams
|
||||
@ -459,7 +443,7 @@ where
|
||||
|
||||
fn inject_fully_negotiated_inbound(
|
||||
&mut self,
|
||||
protocol: <Self::InboundProtocol as InboundUpgrade<Negotiated<TSubstream>>>::Output,
|
||||
protocol: <Self::InboundProtocol as InboundUpgrade<NegotiatedSubstream>>::Output,
|
||||
) {
|
||||
// If `self.allow_listening` is false, then we produced a `DeniedUpgrade` and `protocol`
|
||||
// is a `Void`.
|
||||
@ -695,12 +679,12 @@ where
|
||||
///
|
||||
/// Returns the new state for that substream, an event to generate, and whether the substream
|
||||
/// should be polled again.
|
||||
fn advance_substream<TSubstream, TUserData>(
|
||||
state: SubstreamState<TSubstream, TUserData>,
|
||||
fn advance_substream<TUserData>(
|
||||
state: SubstreamState<TUserData>,
|
||||
upgrade: KademliaProtocolConfig,
|
||||
cx: &mut Context,
|
||||
) -> (
|
||||
Option<SubstreamState<TSubstream, TUserData>>,
|
||||
Option<SubstreamState<TUserData>>,
|
||||
Option<
|
||||
ProtocolsHandlerEvent<
|
||||
KademliaProtocolConfig,
|
||||
@ -711,8 +695,6 @@ fn advance_substream<TSubstream, TUserData>(
|
||||
>,
|
||||
bool,
|
||||
)
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
match state {
|
||||
SubstreamState::OutPendingOpen(msg, user_data) => {
|
||||
|
Reference in New Issue
Block a user