mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-12 09:31:20 +00:00
core/muxing: Flatten StreamMuxer
interface to poll_{inbound,outbound,address_change,close}
(#2724)
Instead of having a mix of `poll_event`, `poll_outbound` and `poll_close`, we flatten the entire interface of `StreamMuxer` into 4 individual functions: - `poll_inbound` - `poll_outbound` - `poll_address_change` - `poll_close` This design is closer to the design of other async traits like `AsyncRead` and `AsyncWrite`. It also allows us to delete the `StreamMuxerEvent`.
This commit is contained in:
@ -20,7 +20,6 @@
|
||||
|
||||
mod error;
|
||||
mod handler_wrapper;
|
||||
mod substream;
|
||||
|
||||
pub(crate) mod pool;
|
||||
|
||||
@ -30,18 +29,19 @@ pub use error::{
|
||||
};
|
||||
pub use pool::{ConnectionCounters, ConnectionLimits};
|
||||
pub use pool::{EstablishedConnection, PendingConnection};
|
||||
pub use substream::{Close, SubstreamEndpoint};
|
||||
|
||||
use crate::handler::ConnectionHandler;
|
||||
use crate::IntoConnectionHandler;
|
||||
use futures::future::poll_fn;
|
||||
use handler_wrapper::HandlerWrapper;
|
||||
use libp2p_core::connection::ConnectedPoint;
|
||||
use libp2p_core::multiaddr::Multiaddr;
|
||||
use libp2p_core::muxing::StreamMuxerBox;
|
||||
use libp2p_core::upgrade;
|
||||
use libp2p_core::PeerId;
|
||||
use std::{error::Error, fmt, pin::Pin, task::Context, task::Poll};
|
||||
use substream::{Muxing, SubstreamEvent};
|
||||
use libp2p_core::{upgrade, StreamMuxer};
|
||||
use std::collections::VecDeque;
|
||||
use std::future::Future;
|
||||
use std::{error::Error, fmt, io, pin::Pin, task::Context, task::Poll};
|
||||
|
||||
/// Information about a successfully established connection.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -52,6 +52,13 @@ pub struct Connected {
|
||||
pub peer_id: PeerId,
|
||||
}
|
||||
|
||||
/// Endpoint for a received substream.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum SubstreamEndpoint<TDialInfo> {
|
||||
Dialer(TDialInfo),
|
||||
Listener,
|
||||
}
|
||||
|
||||
/// Event generated by a [`Connection`].
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event<T> {
|
||||
@ -67,19 +74,22 @@ where
|
||||
THandler: ConnectionHandler,
|
||||
{
|
||||
/// Node that handles the muxing.
|
||||
muxing: substream::Muxing<StreamMuxerBox, handler_wrapper::OutboundOpenInfo<THandler>>,
|
||||
muxing: StreamMuxerBox,
|
||||
/// Handler that processes substreams.
|
||||
handler: HandlerWrapper<THandler>,
|
||||
/// List of "open_info" that is waiting for new outbound substreams.
|
||||
open_info: VecDeque<handler_wrapper::OutboundOpenInfo<THandler>>,
|
||||
}
|
||||
|
||||
impl<THandler> fmt::Debug for Connection<THandler>
|
||||
where
|
||||
THandler: ConnectionHandler + fmt::Debug,
|
||||
THandler::OutboundOpenInfo: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Connection")
|
||||
.field("muxing", &self.muxing)
|
||||
.field("handler", &self.handler)
|
||||
.field("open_info", &self.open_info)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@ -108,8 +118,9 @@ where
|
||||
max_negotiating_inbound_streams,
|
||||
);
|
||||
Connection {
|
||||
muxing: Muxing::new(muxer),
|
||||
muxing: muxer,
|
||||
handler: wrapped_handler,
|
||||
open_info: VecDeque::with_capacity(8),
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,10 +131,10 @@ where
|
||||
|
||||
/// Begins an orderly shutdown of the connection, returning the connection
|
||||
/// handler and a `Future` that resolves when connection shutdown is complete.
|
||||
pub fn close(self) -> (THandler, Close<StreamMuxerBox>) {
|
||||
pub fn close(self) -> (THandler, impl Future<Output = io::Result<()>>) {
|
||||
(
|
||||
self.handler.into_connection_handler(),
|
||||
self.muxing.close().0,
|
||||
poll_fn(move |cx| self.muxing.poll_close(cx)),
|
||||
)
|
||||
}
|
||||
|
||||
@ -138,38 +149,38 @@ where
|
||||
match self.handler.poll(cx)? {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(handler_wrapper::Event::OutboundSubstreamRequest(user_data)) => {
|
||||
self.muxing.open_substream(user_data);
|
||||
continue;
|
||||
self.open_info.push_back(user_data);
|
||||
continue; // Poll handler until exhausted.
|
||||
}
|
||||
Poll::Ready(handler_wrapper::Event::Custom(event)) => {
|
||||
return Poll::Ready(Ok(Event::Handler(event)));
|
||||
}
|
||||
}
|
||||
|
||||
// Perform I/O on the connection through the muxer, informing the handler
|
||||
// of new substreams.
|
||||
match self.muxing.poll(cx)? {
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(SubstreamEvent::InboundSubstream { substream }) => {
|
||||
self.handler
|
||||
.inject_substream(substream, SubstreamEndpoint::Listener);
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(SubstreamEvent::OutboundSubstream {
|
||||
user_data,
|
||||
substream,
|
||||
}) => {
|
||||
if !self.open_info.is_empty() {
|
||||
if let Poll::Ready(substream) = self.muxing.poll_outbound(cx)? {
|
||||
let user_data = self
|
||||
.open_info
|
||||
.pop_front()
|
||||
.expect("`open_info` is not empty");
|
||||
let endpoint = SubstreamEndpoint::Dialer(user_data);
|
||||
self.handler.inject_substream(substream, endpoint);
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(SubstreamEvent::AddressChange(address)) => {
|
||||
self.handler.inject_address_change(&address);
|
||||
return Poll::Ready(Ok(Event::AddressChange(address)));
|
||||
continue; // Go back to the top, handler can potentially make progress again.
|
||||
}
|
||||
}
|
||||
|
||||
return Poll::Pending;
|
||||
if let Poll::Ready(substream) = self.muxing.poll_inbound(cx)? {
|
||||
self.handler
|
||||
.inject_substream(substream, SubstreamEndpoint::Listener);
|
||||
continue; // Go back to the top, handler can potentially make progress again.
|
||||
}
|
||||
|
||||
if let Poll::Ready(address) = self.muxing.poll_address_change(cx)? {
|
||||
self.handler.inject_address_change(&address);
|
||||
return Poll::Ready(Ok(Event::AddressChange(address)));
|
||||
}
|
||||
|
||||
return Poll::Pending; // Nothing can make progress, return `Pending`.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user