2018-08-31 10:31:34 +02:00
|
|
|
// Copyright 2018 Parity Technologies (UK) Ltd.
|
2017-11-28 12:20:28 +01:00
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2018-11-16 12:24:12 +01:00
|
|
|
//! Muxing is the process of splitting a connection into multiple substreams.
|
|
|
|
//!
|
|
|
|
//! The main item of this module is the `StreamMuxer` trait. An implementation of `StreamMuxer`
|
|
|
|
//! has ownership of a connection, lets you open and close substreams, and read/write data
|
|
|
|
//! on open substreams.
|
|
|
|
//!
|
|
|
|
//! > **Note**: You normally don't need to use the methods of the `StreamMuxer` directly, as this
|
|
|
|
//! > is managed by the library's internals.
|
|
|
|
//!
|
|
|
|
//! Each substream of a connection is an isolated stream of data. All the substreams are muxed
|
|
|
|
//! together so that the data read from or written to each substream doesn't influence the other
|
|
|
|
//! substreams.
|
|
|
|
//!
|
|
|
|
//! In the context of libp2p, each substream can use a different protocol. Contrary to opening a
|
|
|
|
//! connection, opening a substream is almost free in terms of resources. This means that you
|
|
|
|
//! shouldn't hesitate to rapidly open and close substreams, and to design protocols that don't
|
|
|
|
//! require maintaining long-lived channels of communication.
|
|
|
|
//!
|
|
|
|
//! > **Example**: The Kademlia protocol opens a new substream for each request it wants to
|
|
|
|
//! > perform. Multiple requests can be performed simultaneously by opening multiple
|
|
|
|
//! > substreams, without having to worry about associating responses with the
|
|
|
|
//! > right request.
|
|
|
|
//!
|
|
|
|
//! # Implementing a muxing protocol
|
|
|
|
//!
|
|
|
|
//! In order to implement a muxing protocol, create an object that implements the `UpgradeInfo`,
|
|
|
|
//! `InboundUpgrade` and `OutboundUpgrade` traits. See the `upgrade` module for more information.
|
|
|
|
//! The `Output` associated type of the `InboundUpgrade` and `OutboundUpgrade` traits should be
|
|
|
|
//! identical, and should be an object that implements the `StreamMuxer` trait.
|
|
|
|
//!
|
|
|
|
//! The upgrade process will take ownership of the connection, which makes it possible for the
|
|
|
|
//! implementation of `StreamMuxer` to control everything that happens on the wire.
|
|
|
|
|
2018-09-14 13:18:10 +02:00
|
|
|
use fnv::FnvHashMap;
|
2019-11-01 16:53:11 +01:00
|
|
|
use futures::{future, prelude::*, task::Context, task::Poll};
|
2018-09-14 13:18:10 +02:00
|
|
|
use parking_lot::Mutex;
|
2019-09-16 11:08:44 +02:00
|
|
|
use std::{io, ops::Deref, fmt, pin::Pin, sync::atomic::{AtomicUsize, Ordering}};
|
2017-11-28 12:20:28 +01:00
|
|
|
|
2019-04-23 15:08:59 +02:00
|
|
|
pub use self::singleton::SingletonMuxer;
|
|
|
|
|
|
|
|
mod singleton;
|
|
|
|
|
2018-08-31 10:31:34 +02:00
|
|
|
/// Implemented on objects that can open and manage substreams.
|
2019-03-11 17:19:50 +01:00
|
|
|
///
|
|
|
|
/// The state of a muxer, as exposed by this API, is the following:
|
|
|
|
///
|
2020-06-19 11:59:24 +02:00
|
|
|
/// - A connection to the remote. The `flush_all` and `close` methods operate on this.
|
2019-03-11 17:19:50 +01:00
|
|
|
/// - A list of substreams that are open. The `poll_inbound`, `poll_outbound`, `read_substream`,
|
|
|
|
/// `write_substream`, `flush_substream`, `shutdown_substream` and `destroy_substream` methods
|
|
|
|
/// allow controlling these entries.
|
|
|
|
/// - A list of outbound substreams being opened. The `open_outbound`, `poll_outbound` and
|
|
|
|
/// `destroy_outbound` methods allow controlling these entries.
|
|
|
|
///
|
2017-11-28 12:20:28 +01:00
|
|
|
pub trait StreamMuxer {
|
2018-03-07 16:20:55 +01:00
|
|
|
/// Type of the object that represents the raw substream where data can be read and written.
|
2018-08-31 10:31:34 +02:00
|
|
|
type Substream;
|
2018-05-14 14:49:29 +02:00
|
|
|
|
2018-03-07 16:20:55 +01:00
|
|
|
/// Future that will be resolved when the outgoing substream is open.
|
2018-08-31 10:31:34 +02:00
|
|
|
type OutboundSubstream;
|
2017-11-28 12:20:28 +01:00
|
|
|
|
2019-04-28 14:42:18 +03:00
|
|
|
/// Error type of the muxer
|
|
|
|
type Error: Into<io::Error>;
|
|
|
|
|
2018-08-31 10:31:34 +02:00
|
|
|
/// Polls for an inbound substream.
|
|
|
|
///
|
|
|
|
/// This function behaves the same as a `Stream`.
|
2018-09-11 11:17:44 +02:00
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// If `Pending` is returned, then the current task will be notified once the muxer
|
2018-09-11 11:17:44 +02:00
|
|
|
/// is ready to be polled, similar to the API of `Stream::poll()`.
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Only the latest task that was used to call this method may be notified.
|
|
|
|
///
|
|
|
|
/// An error can be generated if the connection has been closed.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>>;
|
2017-11-28 12:20:28 +01:00
|
|
|
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Opens a new outgoing substream, and produces the equivalent to a future that will be
|
|
|
|
/// resolved when it becomes available.
|
|
|
|
///
|
|
|
|
/// The API of `OutboundSubstream` is totally opaque, and the object can only be interfaced
|
|
|
|
/// through the methods on the `StreamMuxer` trait.
|
2018-08-31 10:31:34 +02:00
|
|
|
fn open_outbound(&self) -> Self::OutboundSubstream;
|
|
|
|
|
|
|
|
/// Polls the outbound substream.
|
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// If `Pending` is returned, then the current task will be notified once the substream
|
2018-09-11 11:17:44 +02:00
|
|
|
/// is ready to be polled, similar to the API of `Future::poll()`.
|
|
|
|
/// However, for each individual outbound substream, only the latest task that was used to
|
|
|
|
/// call this method may be notified.
|
2018-09-14 13:18:10 +02:00
|
|
|
///
|
|
|
|
/// May panic or produce an undefined result if an earlier polling of the same substream
|
|
|
|
/// returned `Ready` or `Err`.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_outbound(&self, cx: &mut Context, s: &mut Self::OutboundSubstream)
|
|
|
|
-> Poll<Result<Self::Substream, Self::Error>>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Destroys an outbound substream future. Use this after the outbound substream has finished,
|
|
|
|
/// or if you want to interrupt it.
|
2018-10-11 10:35:14 +02:00
|
|
|
fn destroy_outbound(&self, s: Self::OutboundSubstream);
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
/// Reads data from a substream. The behaviour is the same as `futures::AsyncRead::poll_read`.
|
2018-09-11 11:17:44 +02:00
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// If `Pending` is returned, then the current task will be notified once the substream
|
2018-10-11 10:35:14 +02:00
|
|
|
/// is ready to be read. However, for each individual substream, only the latest task that
|
|
|
|
/// was used to call this method may be notified.
|
2019-03-11 17:19:50 +01:00
|
|
|
///
|
|
|
|
/// If `Async::Ready(0)` is returned, the substream has been closed by the remote and should
|
|
|
|
/// no longer be read afterwards.
|
|
|
|
///
|
|
|
|
/// An error can be generated if the connection has been closed, or if a protocol misbehaviour
|
|
|
|
/// happened.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn read_substream(&self, cx: &mut Context, s: &mut Self::Substream, buf: &mut [u8])
|
|
|
|
-> Poll<Result<usize, Self::Error>>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
/// Write data to a substream. The behaviour is the same as `futures::AsyncWrite::poll_write`.
|
2018-09-11 11:17:44 +02:00
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// If `Pending` is returned, then the current task will be notified once the substream
|
2019-03-11 17:19:50 +01:00
|
|
|
/// is ready to be read. For each individual substream, only the latest task that was used to
|
|
|
|
/// call this method may be notified.
|
|
|
|
///
|
|
|
|
/// Calling `write_substream` does not guarantee that data will arrive to the remote. To
|
|
|
|
/// ensure that, you should call `flush_substream`.
|
|
|
|
///
|
|
|
|
/// It is incorrect to call this method on a substream if you called `shutdown_substream` on
|
|
|
|
/// this substream earlier.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn write_substream(&self, cx: &mut Context, s: &mut Self::Substream, buf: &[u8])
|
|
|
|
-> Poll<Result<usize, Self::Error>>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
/// Flushes a substream. The behaviour is the same as `futures::AsyncWrite::poll_flush`.
|
2018-09-11 11:17:44 +02:00
|
|
|
///
|
2019-03-11 17:19:50 +01:00
|
|
|
/// After this method has been called, data written earlier on the substream is guaranteed to
|
|
|
|
/// be received by the remote.
|
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// If `Pending` is returned, then the current task will be notified once the substream
|
2019-03-11 17:19:50 +01:00
|
|
|
/// is ready to be read. For each individual substream, only the latest task that was used to
|
|
|
|
/// call this method may be notified.
|
|
|
|
///
|
|
|
|
/// > **Note**: This method may be implemented as a call to `flush_all`.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn flush_substream(&self, cx: &mut Context, s: &mut Self::Substream)
|
|
|
|
-> Poll<Result<(), Self::Error>>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Attempts to shut down the writing side of a substream. The behaviour is similar to
|
2019-09-16 11:08:44 +02:00
|
|
|
/// `AsyncWrite::poll_close`.
|
2018-09-11 11:17:44 +02:00
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// Contrary to `AsyncWrite::poll_close`, shutting down a substream does not imply
|
2019-03-11 17:19:50 +01:00
|
|
|
/// `flush_substream`. If you want to make sure that the remote is immediately informed about
|
|
|
|
/// the shutdown, use `flush_substream` or `flush_all`.
|
|
|
|
///
|
|
|
|
/// After this method has been called, you should no longer attempt to write to this substream.
|
|
|
|
///
|
|
|
|
/// An error can be generated if the connection has been closed, or if a protocol misbehaviour
|
|
|
|
/// happened.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn shutdown_substream(&self, cx: &mut Context, s: &mut Self::Substream)
|
|
|
|
-> Poll<Result<(), Self::Error>>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
|
|
|
/// Destroys a substream.
|
2018-10-11 10:35:14 +02:00
|
|
|
fn destroy_substream(&self, s: Self::Substream);
|
2018-09-14 13:18:10 +02:00
|
|
|
|
2019-02-20 16:25:34 +01:00
|
|
|
/// Returns `true` if the remote has shown any sign of activity after the muxer has been open.
|
|
|
|
///
|
|
|
|
/// For optimisation purposes, the connection handshake of libp2p can be very optimistic and is
|
|
|
|
/// allowed to assume that the handshake has succeeded when it didn't in fact succeed. This
|
|
|
|
/// method can be called in order to determine whether the remote has accepted our handshake or
|
|
|
|
/// has potentially not received it yet.
|
2020-06-19 11:59:24 +02:00
|
|
|
#[deprecated(note = "This method is unused and will be removed in the future")]
|
|
|
|
fn is_remote_acknowledged(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
2019-02-20 16:25:34 +01:00
|
|
|
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Closes this `StreamMuxer`.
|
|
|
|
///
|
2019-09-16 11:08:44 +02:00
|
|
|
/// After this has returned `Poll::Ready(Ok(()))`, the muxer has become useless. All
|
2019-03-11 17:19:50 +01:00
|
|
|
/// subsequent reads must return either `EOF` or an error. All subsequent writes, shutdowns,
|
|
|
|
/// or polls must generate an error or be ignored.
|
2018-10-11 10:35:14 +02:00
|
|
|
///
|
2019-03-11 17:19:50 +01:00
|
|
|
/// Calling this method implies `flush_all`.
|
2018-10-11 10:35:14 +02:00
|
|
|
///
|
2019-03-11 17:19:50 +01:00
|
|
|
/// > **Note**: You are encouraged to call this method and wait for it to return `Ready`, so
|
|
|
|
/// > that the remote is properly informed of the shutdown. However, apart from
|
|
|
|
/// > properly informing the remote, there is no difference between this and
|
|
|
|
/// > immediately dropping the muxer.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn close(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
|
2018-10-11 10:35:14 +02:00
|
|
|
|
|
|
|
/// Flush this `StreamMuxer`.
|
|
|
|
///
|
2019-03-11 17:19:50 +01:00
|
|
|
/// This drains any write buffers of substreams and delivers any pending shutdown notifications
|
|
|
|
/// due to `shutdown_substream` or `close`. One may thus shutdown groups of substreams
|
|
|
|
/// followed by a final `flush_all` instead of having to do `flush_substream` for each.
|
2019-09-16 11:08:44 +02:00
|
|
|
fn flush_all(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Polls for an inbound from the muxer but wraps the output in an object that
|
|
|
|
/// implements `Read`/`Write`/`AsyncRead`/`AsyncWrite`.
|
|
|
|
pub fn inbound_from_ref_and_wrap<P>(
|
|
|
|
muxer: P,
|
2019-09-16 11:08:44 +02:00
|
|
|
) -> impl Future<Output = Result<SubstreamRef<P>, <P::Target as StreamMuxer>::Error>>
|
2018-08-31 10:31:34 +02:00
|
|
|
where
|
|
|
|
P: Deref + Clone,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
let muxer2 = muxer.clone();
|
2019-09-16 11:08:44 +02:00
|
|
|
future::poll_fn(move |cx| muxer.poll_inbound(cx))
|
|
|
|
.map_ok(|substream| substream_from_ref(muxer2, substream))
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Same as `outbound_from_ref`, but wraps the output in an object that
|
|
|
|
/// implements `Read`/`Write`/`AsyncRead`/`AsyncWrite`.
|
|
|
|
pub fn outbound_from_ref_and_wrap<P>(muxer: P) -> OutboundSubstreamRefWrapFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref + Clone,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
let inner = outbound_from_ref(muxer);
|
|
|
|
OutboundSubstreamRefWrapFuture { inner }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Future returned by `outbound_from_ref_and_wrap`.
|
|
|
|
pub struct OutboundSubstreamRefWrapFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref + Clone,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
inner: OutboundSubstreamRefFuture<P>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P> Future for OutboundSubstreamRefWrapFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref + Clone,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
2019-09-16 11:08:44 +02:00
|
|
|
type Output = Result<SubstreamRef<P>, <P::Target as StreamMuxer>::Error>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
match Future::poll(Pin::new(&mut self.inner), cx) {
|
|
|
|
Poll::Ready(Ok(substream)) => {
|
2018-08-31 10:31:34 +02:00
|
|
|
let out = substream_from_ref(self.inner.muxer.clone(), substream);
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(Ok(out))
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Pending => Poll::Pending,
|
|
|
|
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Builds a new future for an outbound substream, where the muxer is a reference.
|
|
|
|
pub fn outbound_from_ref<P>(muxer: P) -> OutboundSubstreamRefFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
let outbound = muxer.open_outbound();
|
|
|
|
OutboundSubstreamRefFuture {
|
|
|
|
muxer,
|
|
|
|
outbound: Some(outbound),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Future returned by `outbound_from_ref`.
|
|
|
|
pub struct OutboundSubstreamRefFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
muxer: P,
|
|
|
|
outbound: Option<<P::Target as StreamMuxer>::OutboundSubstream>,
|
|
|
|
}
|
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
impl<P> Unpin for OutboundSubstreamRefFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-08-31 10:31:34 +02:00
|
|
|
impl<P> Future for OutboundSubstreamRefFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
2019-09-16 11:08:44 +02:00
|
|
|
type Output = Result<<P::Target as StreamMuxer>::Substream, <P::Target as StreamMuxer>::Error>;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
|
|
|
// multiple different fields from the `Pin` at the same time.
|
|
|
|
let this = &mut *self;
|
|
|
|
this.muxer.poll_outbound(cx, this.outbound.as_mut().expect("outbound was empty"))
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P> Drop for OutboundSubstreamRefFuture<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
fn drop(&mut self) {
|
|
|
|
self.muxer
|
|
|
|
.destroy_outbound(self.outbound.take().expect("outbound was empty"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Builds an implementation of `Read`/`Write`/`AsyncRead`/`AsyncWrite` from an `Arc` to the
|
|
|
|
/// muxer and a substream.
|
|
|
|
pub fn substream_from_ref<P>(
|
|
|
|
muxer: P,
|
|
|
|
substream: <P::Target as StreamMuxer>::Substream,
|
|
|
|
) -> SubstreamRef<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
SubstreamRef {
|
|
|
|
muxer,
|
|
|
|
substream: Some(substream),
|
2019-06-24 17:42:33 +09:00
|
|
|
shutdown_state: ShutdownState::Shutdown,
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Stream returned by `substream_from_ref`.
|
|
|
|
pub struct SubstreamRef<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
muxer: P,
|
|
|
|
substream: Option<<P::Target as StreamMuxer>::Substream>,
|
2019-06-24 17:42:33 +09:00
|
|
|
shutdown_state: ShutdownState,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum ShutdownState {
|
|
|
|
Shutdown,
|
|
|
|
Flush,
|
|
|
|
Done,
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
|
2018-10-05 11:55:32 +02:00
|
|
|
impl<P> fmt::Debug for SubstreamRef<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
2018-11-03 09:54:31 +01:00
|
|
|
<P::Target as StreamMuxer>::Substream: fmt::Debug,
|
2018-10-05 11:55:32 +02:00
|
|
|
{
|
2019-02-11 14:58:15 +01:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
2018-11-03 09:54:31 +01:00
|
|
|
write!(f, "Substream({:?})", self.substream)
|
2018-10-05 11:55:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
impl<P> Unpin for SubstreamRef<P>
|
2018-08-31 10:31:34 +02:00
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P> AsyncRead for SubstreamRef<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context, buf: &mut [u8]) -> Poll<Result<usize, io::Error>> {
|
|
|
|
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
|
|
|
// multiple different fields from the `Pin` at the same time.
|
|
|
|
let this = &mut *self;
|
2018-08-31 10:31:34 +02:00
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
let s = this.substream.as_mut().expect("substream was empty");
|
|
|
|
this.muxer.read_substream(cx, s, buf).map_err(|e| e.into())
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P> AsyncWrite for SubstreamRef<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize, io::Error>> {
|
|
|
|
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
|
|
|
// multiple different fields from the `Pin` at the same time.
|
|
|
|
let this = &mut *self;
|
|
|
|
|
|
|
|
let s = this.substream.as_mut().expect("substream was empty");
|
|
|
|
this.muxer.write_substream(cx, s, buf).map_err(|e| e.into())
|
2018-10-11 10:35:14 +02:00
|
|
|
}
|
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
|
|
|
|
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
|
|
|
// multiple different fields from the `Pin` at the same time.
|
|
|
|
let this = &mut *self;
|
|
|
|
|
|
|
|
let s = this.substream.as_mut().expect("substream was empty");
|
2019-06-24 17:42:33 +09:00
|
|
|
loop {
|
2019-09-16 11:08:44 +02:00
|
|
|
match this.shutdown_state {
|
2019-06-24 17:42:33 +09:00
|
|
|
ShutdownState::Shutdown => {
|
2019-09-16 11:08:44 +02:00
|
|
|
match this.muxer.shutdown_substream(cx, s) {
|
|
|
|
Poll::Ready(Ok(())) => this.shutdown_state = ShutdownState::Flush,
|
|
|
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
|
|
|
Poll::Pending => return Poll::Pending,
|
|
|
|
}
|
2019-06-24 17:42:33 +09:00
|
|
|
}
|
|
|
|
ShutdownState::Flush => {
|
2019-09-16 11:08:44 +02:00
|
|
|
match this.muxer.flush_substream(cx, s) {
|
|
|
|
Poll::Ready(Ok(())) => this.shutdown_state = ShutdownState::Done,
|
|
|
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
|
|
|
Poll::Pending => return Poll::Pending,
|
|
|
|
}
|
2019-06-24 17:42:33 +09:00
|
|
|
}
|
|
|
|
ShutdownState::Done => {
|
2019-09-16 11:08:44 +02:00
|
|
|
return Poll::Ready(Ok(()));
|
2019-06-24 17:42:33 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-10-11 10:35:14 +02:00
|
|
|
}
|
|
|
|
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
|
|
|
|
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
|
|
|
// multiple different fields from the `Pin` at the same time.
|
|
|
|
let this = &mut *self;
|
|
|
|
|
|
|
|
let s = this.substream.as_mut().expect("substream was empty");
|
|
|
|
this.muxer.flush_substream(cx, s).map_err(|e| e.into())
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P> Drop for SubstreamRef<P>
|
|
|
|
where
|
|
|
|
P: Deref,
|
|
|
|
P::Target: StreamMuxer,
|
|
|
|
{
|
|
|
|
fn drop(&mut self) {
|
2018-10-11 10:35:14 +02:00
|
|
|
self.muxer.destroy_substream(self.substream.take().expect("substream was empty"))
|
2018-08-31 10:31:34 +02:00
|
|
|
}
|
2017-11-28 12:20:28 +01:00
|
|
|
}
|
2018-09-14 13:18:10 +02:00
|
|
|
|
|
|
|
/// Abstract `StreamMuxer`.
|
|
|
|
pub struct StreamMuxerBox {
|
2019-04-28 14:42:18 +03:00
|
|
|
inner: Box<dyn StreamMuxer<Substream = usize, OutboundSubstream = usize, Error = io::Error> + Send + Sync>,
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl StreamMuxerBox {
|
|
|
|
/// Turns a stream muxer into a `StreamMuxerBox`.
|
|
|
|
pub fn new<T>(muxer: T) -> StreamMuxerBox
|
|
|
|
where
|
|
|
|
T: StreamMuxer + Send + Sync + 'static,
|
|
|
|
T::OutboundSubstream: Send,
|
|
|
|
T::Substream: Send,
|
|
|
|
{
|
|
|
|
let wrap = Wrap {
|
|
|
|
inner: muxer,
|
|
|
|
substreams: Mutex::new(Default::default()),
|
|
|
|
next_substream: AtomicUsize::new(0),
|
|
|
|
outbound: Mutex::new(Default::default()),
|
|
|
|
next_outbound: AtomicUsize::new(0),
|
|
|
|
};
|
|
|
|
|
|
|
|
StreamMuxerBox {
|
|
|
|
inner: Box::new(wrap),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StreamMuxer for StreamMuxerBox {
|
|
|
|
type Substream = usize; // TODO: use a newtype
|
|
|
|
type OutboundSubstream = usize; // TODO: use a newtype
|
2019-04-28 14:42:18 +03:00
|
|
|
type Error = io::Error;
|
2018-09-14 13:18:10 +02:00
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>> {
|
|
|
|
self.inner.poll_inbound(cx)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn open_outbound(&self) -> Self::OutboundSubstream {
|
|
|
|
self.inner.open_outbound()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_outbound(&self, cx: &mut Context, s: &mut Self::OutboundSubstream) -> Poll<Result<Self::Substream, Self::Error>> {
|
|
|
|
self.inner.poll_outbound(cx, s)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn destroy_outbound(&self, substream: Self::OutboundSubstream) {
|
|
|
|
self.inner.destroy_outbound(substream)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn read_substream(&self, cx: &mut Context, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<Result<usize, Self::Error>> {
|
|
|
|
self.inner.read_substream(cx, s, buf)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn write_substream(&self, cx: &mut Context, s: &mut Self::Substream, buf: &[u8]) -> Poll<Result<usize, Self::Error>> {
|
|
|
|
self.inner.write_substream(cx, s, buf)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn flush_substream(&self, cx: &mut Context, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.inner.flush_substream(cx, s)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn shutdown_substream(&self, cx: &mut Context, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.inner.shutdown_substream(cx, s)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2018-10-11 10:35:14 +02:00
|
|
|
fn destroy_substream(&self, s: Self::Substream) {
|
|
|
|
self.inner.destroy_substream(s)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn close(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.inner.close(cx)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn flush_all(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.inner.flush_all(cx)
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Wrap<T> where T: StreamMuxer {
|
|
|
|
inner: T,
|
|
|
|
substreams: Mutex<FnvHashMap<usize, T::Substream>>,
|
|
|
|
next_substream: AtomicUsize,
|
|
|
|
outbound: Mutex<FnvHashMap<usize, T::OutboundSubstream>>,
|
|
|
|
next_outbound: AtomicUsize,
|
|
|
|
}
|
|
|
|
|
2019-04-28 14:42:18 +03:00
|
|
|
impl<T> StreamMuxer for Wrap<T>
|
|
|
|
where
|
|
|
|
T: StreamMuxer,
|
|
|
|
{
|
2018-09-14 13:18:10 +02:00
|
|
|
type Substream = usize; // TODO: use a newtype
|
|
|
|
type OutboundSubstream = usize; // TODO: use a newtype
|
2019-04-28 14:42:18 +03:00
|
|
|
type Error = io::Error;
|
2018-09-14 13:18:10 +02:00
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn poll_inbound(&self, cx: &mut Context) -> Poll<Result<Self::Substream, Self::Error>> {
|
|
|
|
let substream = match self.inner.poll_inbound(cx) {
|
|
|
|
Poll::Pending => return Poll::Pending,
|
|
|
|
Poll::Ready(Ok(s)) => s,
|
|
|
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
|
|
|
};
|
|
|
|
|
2019-03-11 17:19:50 +01:00
|
|
|
let id = self.next_substream.fetch_add(1, Ordering::Relaxed);
|
|
|
|
self.substreams.lock().insert(id, substream);
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(Ok(id))
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn open_outbound(&self) -> Self::OutboundSubstream {
|
|
|
|
let outbound = self.inner.open_outbound();
|
|
|
|
let id = self.next_outbound.fetch_add(1, Ordering::Relaxed);
|
|
|
|
self.outbound.lock().insert(id, outbound);
|
|
|
|
id
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn poll_outbound(
|
|
|
|
&self,
|
2019-09-16 11:08:44 +02:00
|
|
|
cx: &mut Context,
|
2018-09-14 13:18:10 +02:00
|
|
|
substream: &mut Self::OutboundSubstream,
|
2019-09-16 11:08:44 +02:00
|
|
|
) -> Poll<Result<Self::Substream, Self::Error>> {
|
2018-09-14 13:18:10 +02:00
|
|
|
let mut list = self.outbound.lock();
|
2019-09-16 11:08:44 +02:00
|
|
|
let substream = match self.inner.poll_outbound(cx, list.get_mut(substream).unwrap()) {
|
|
|
|
Poll::Pending => return Poll::Pending,
|
|
|
|
Poll::Ready(Ok(s)) => s,
|
|
|
|
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
|
|
|
};
|
2019-03-11 17:19:50 +01:00
|
|
|
let id = self.next_substream.fetch_add(1, Ordering::Relaxed);
|
|
|
|
self.substreams.lock().insert(id, substream);
|
2019-09-16 11:08:44 +02:00
|
|
|
Poll::Ready(Ok(id))
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn destroy_outbound(&self, substream: Self::OutboundSubstream) {
|
|
|
|
let mut list = self.outbound.lock();
|
|
|
|
self.inner.destroy_outbound(list.remove(&substream).unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn read_substream(&self, cx: &mut Context, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<Result<usize, Self::Error>> {
|
2018-09-14 13:18:10 +02:00
|
|
|
let mut list = self.substreams.lock();
|
2019-09-16 11:08:44 +02:00
|
|
|
self.inner.read_substream(cx, list.get_mut(s).unwrap(), buf).map_err(|e| e.into())
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn write_substream(&self, cx: &mut Context, s: &mut Self::Substream, buf: &[u8]) -> Poll<Result<usize, Self::Error>> {
|
2018-09-14 13:18:10 +02:00
|
|
|
let mut list = self.substreams.lock();
|
2019-09-16 11:08:44 +02:00
|
|
|
self.inner.write_substream(cx, list.get_mut(s).unwrap(), buf).map_err(|e| e.into())
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn flush_substream(&self, cx: &mut Context, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
2018-09-14 13:18:10 +02:00
|
|
|
let mut list = self.substreams.lock();
|
2019-09-16 11:08:44 +02:00
|
|
|
self.inner.flush_substream(cx, list.get_mut(s).unwrap()).map_err(|e| e.into())
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn shutdown_substream(&self, cx: &mut Context, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
2018-09-14 13:18:10 +02:00
|
|
|
let mut list = self.substreams.lock();
|
2019-09-16 11:08:44 +02:00
|
|
|
self.inner.shutdown_substream(cx, list.get_mut(s).unwrap()).map_err(|e| e.into())
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn destroy_substream(&self, substream: Self::Substream) {
|
|
|
|
let mut list = self.substreams.lock();
|
|
|
|
self.inner.destroy_substream(list.remove(&substream).unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn close(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.inner.close(cx).map_err(|e| e.into())
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-09-16 11:08:44 +02:00
|
|
|
fn flush_all(&self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
self.inner.flush_all(cx).map_err(|e| e.into())
|
2018-09-14 13:18:10 +02:00
|
|
|
}
|
|
|
|
}
|