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:
Thomas Eizinger
2022-07-18 04:20:11 +01:00
committed by GitHub
parent d4f8ec2d48
commit 1a553db596
61 changed files with 281 additions and 696 deletions

View File

@ -78,25 +78,25 @@ instant = "0.1.11" # Explicit dependency to be used in `wasm-bindgen` feature
lazy_static = "1.2" lazy_static = "1.2"
libp2p-autonat = { version = "0.6.0", path = "protocols/autonat", optional = true } libp2p-autonat = { version = "0.6.0", path = "protocols/autonat", optional = true }
libp2p-core = { version = "0.34.0", path = "core", default-features = false } libp2p-core = { version = "0.35.0", path = "core", default-features = false }
libp2p-dcutr = { version = "0.5.0", path = "protocols/dcutr", optional = true } libp2p-dcutr = { version = "0.5.0", path = "protocols/dcutr", optional = true }
libp2p-floodsub = { version = "0.38.0", path = "protocols/floodsub", optional = true } libp2p-floodsub = { version = "0.38.0", path = "protocols/floodsub", optional = true }
libp2p-identify = { version = "0.38.0", path = "protocols/identify", optional = true } libp2p-identify = { version = "0.38.0", path = "protocols/identify", optional = true }
libp2p-kad = { version = "0.39.0", path = "protocols/kad", optional = true } libp2p-kad = { version = "0.39.0", path = "protocols/kad", optional = true }
libp2p-metrics = { version = "0.8.0", path = "misc/metrics", optional = true } libp2p-metrics = { version = "0.8.0", path = "misc/metrics", optional = true }
libp2p-mplex = { version = "0.34.0", path = "muxers/mplex", optional = true } libp2p-mplex = { version = "0.35.0", path = "muxers/mplex", optional = true }
libp2p-noise = { version = "0.37.0", path = "transports/noise", optional = true } libp2p-noise = { version = "0.38.0", path = "transports/noise", optional = true }
libp2p-ping = { version = "0.38.0", path = "protocols/ping", optional = true } libp2p-ping = { version = "0.38.0", path = "protocols/ping", optional = true }
libp2p-plaintext = { version = "0.34.0", path = "transports/plaintext", optional = true } libp2p-plaintext = { version = "0.35.0", path = "transports/plaintext", optional = true }
libp2p-pnet = { version = "0.22.0", path = "transports/pnet", optional = true } libp2p-pnet = { version = "0.22.0", path = "transports/pnet", optional = true }
libp2p-relay = { version = "0.11.0", path = "protocols/relay", optional = true } libp2p-relay = { version = "0.11.0", path = "protocols/relay", optional = true }
libp2p-rendezvous = { version = "0.8.0", path = "protocols/rendezvous", optional = true } libp2p-rendezvous = { version = "0.8.0", path = "protocols/rendezvous", optional = true }
libp2p-request-response = { version = "0.20.0", path = "protocols/request-response", optional = true } libp2p-request-response = { version = "0.20.0", path = "protocols/request-response", optional = true }
libp2p-swarm = { version = "0.38.0", path = "swarm" } libp2p-swarm = { version = "0.38.0", path = "swarm" }
libp2p-swarm-derive = { version = "0.28.0", path = "swarm-derive" } libp2p-swarm-derive = { version = "0.28.0", path = "swarm-derive" }
libp2p-uds = { version = "0.33.0", path = "transports/uds", optional = true } libp2p-uds = { version = "0.34.0", path = "transports/uds", optional = true }
libp2p-wasm-ext = { version = "0.34.0", path = "transports/wasm-ext", default-features = false, optional = true } libp2p-wasm-ext = { version = "0.35.0", path = "transports/wasm-ext", default-features = false, optional = true }
libp2p-yamux = { version = "0.38.0", path = "muxers/yamux", optional = true } libp2p-yamux = { version = "0.39.0", path = "muxers/yamux", optional = true }
multiaddr = { version = "0.14.0" } multiaddr = { version = "0.14.0" }
parking_lot = "0.12.0" parking_lot = "0.12.0"
pin-project = "1.0.0" pin-project = "1.0.0"
@ -104,11 +104,11 @@ rand = "0.7.3" # Explicit dependency to be used in `wasm-bindgen` feature
smallvec = "1.6.1" smallvec = "1.6.1"
[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies] [target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies]
libp2p-deflate = { version = "0.34.0", path = "transports/deflate", optional = true } libp2p-deflate = { version = "0.35.0", path = "transports/deflate", optional = true }
libp2p-dns = { version = "0.34.0", path = "transports/dns", optional = true, default-features = false } libp2p-dns = { version = "0.35.0", path = "transports/dns", optional = true, default-features = false }
libp2p-mdns = { version = "0.39.0", path = "protocols/mdns", optional = true } libp2p-mdns = { version = "0.39.0", path = "protocols/mdns", optional = true }
libp2p-tcp = { version = "0.34.0", path = "transports/tcp", default-features = false, optional = true } libp2p-tcp = { version = "0.34.0", path = "transports/tcp", default-features = false, optional = true }
libp2p-websocket = { version = "0.36.0", path = "transports/websocket", optional = true } libp2p-websocket = { version = "0.37.0", path = "transports/websocket", optional = true }
[target.'cfg(not(target_os = "unknown"))'.dependencies] [target.'cfg(not(target_os = "unknown"))'.dependencies]
libp2p-gossipsub = { version = "0.40.0", path = "protocols/gossipsub", optional = true } libp2p-gossipsub = { version = "0.40.0", path = "protocols/gossipsub", optional = true }

View File

@ -1,6 +1,12 @@
# 0.35.0 [unreleased]
- Remove `StreamMuxer::poll_event` in favor of individual functions: `poll_inbound`, `poll_outbound`
and `poll_address_change`. Consequently, `StreamMuxerEvent` is also removed. See [PR 2724].
[PR 2724]: https://github.com/libp2p/rust-libp2p/pull/2724
# 0.34.0 # 0.34.0
- Introduce `StreamMuxerEvent::map_inbound_stream`. See [PR 2691].
- Remove `{read,write,flush,shutdown,destroy}_substream` functions from `StreamMuxer` trait - Remove `{read,write,flush,shutdown,destroy}_substream` functions from `StreamMuxer` trait
in favor of forcing `StreamMuxer::Substream` to implement `AsyncRead + AsyncWrite`. See [PR 2707]. in favor of forcing `StreamMuxer::Substream` to implement `AsyncRead + AsyncWrite`. See [PR 2707].
- Replace `Into<std::io::Error>` bound on `StreamMuxer::Error` with `std::error::Error`. See [PR 2710]. - Replace `Into<std::io::Error>` bound on `StreamMuxer::Error` with `std::error::Error`. See [PR 2710].

View File

@ -3,7 +3,7 @@ name = "libp2p-core"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Core traits and structs of libp2p" description = "Core traits and structs of libp2p"
version = "0.34.0" version = "0.35.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"

View File

@ -19,7 +19,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use crate::{ use crate::{
muxing::{StreamMuxer, StreamMuxerEvent}, muxing::StreamMuxer,
transport::{ListenerId, Transport, TransportError, TransportEvent}, transport::{ListenerId, Transport, TransportError, TransportEvent},
Multiaddr, ProtocolName, Multiaddr, ProtocolName,
}; };
@ -202,60 +202,38 @@ where
B: StreamMuxer, B: StreamMuxer,
{ {
type Substream = EitherOutput<A::Substream, B::Substream>; type Substream = EitherOutput<A::Substream, B::Substream>;
type OutboundSubstream = EitherOutbound<A, B>;
type Error = EitherError<A::Error, B::Error>; type Error = EitherError<A::Error, B::Error>;
fn poll_event( fn poll_inbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
&self,
cx: &mut Context<'_>,
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
match self { match self {
EitherOutput::First(inner) => inner EitherOutput::First(inner) => inner
.poll_event(cx) .poll_inbound(cx)
.map_err(EitherError::A) .map_ok(EitherOutput::First)
.map_ok(|event| event.map_inbound_stream(EitherOutput::First)),
EitherOutput::Second(inner) => inner
.poll_event(cx)
.map_err(EitherError::B)
.map_ok(|event| event.map_inbound_stream(EitherOutput::Second)),
}
}
fn open_outbound(&self) -> Self::OutboundSubstream {
match self {
EitherOutput::First(inner) => EitherOutbound::A(inner.open_outbound()),
EitherOutput::Second(inner) => EitherOutbound::B(inner.open_outbound()),
}
}
fn poll_outbound(
&self,
cx: &mut Context<'_>,
substream: &mut Self::OutboundSubstream,
) -> Poll<Result<Self::Substream, Self::Error>> {
match (self, substream) {
(EitherOutput::First(ref inner), EitherOutbound::A(ref mut substream)) => inner
.poll_outbound(cx, substream)
.map(|p| p.map(EitherOutput::First))
.map_err(EitherError::A), .map_err(EitherError::A),
(EitherOutput::Second(ref inner), EitherOutbound::B(ref mut substream)) => inner EitherOutput::Second(inner) => inner
.poll_outbound(cx, substream) .poll_inbound(cx)
.map(|p| p.map(EitherOutput::Second)) .map_ok(EitherOutput::Second)
.map_err(EitherError::B), .map_err(EitherError::B),
_ => panic!("Wrong API usage"),
} }
} }
fn destroy_outbound(&self, substream: Self::OutboundSubstream) { fn poll_outbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
match self { match self {
EitherOutput::First(inner) => match substream { EitherOutput::First(inner) => inner
EitherOutbound::A(substream) => inner.destroy_outbound(substream), .poll_outbound(cx)
_ => panic!("Wrong API usage"), .map_ok(EitherOutput::First)
}, .map_err(EitherError::A),
EitherOutput::Second(inner) => match substream { EitherOutput::Second(inner) => inner
EitherOutbound::B(substream) => inner.destroy_outbound(substream), .poll_outbound(cx)
_ => panic!("Wrong API usage"), .map_ok(EitherOutput::Second)
}, .map_err(EitherError::B),
}
}
fn poll_address_change(&self, cx: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>> {
match self {
EitherOutput::First(inner) => inner.poll_address_change(cx).map_err(EitherError::A),
EitherOutput::Second(inner) => inner.poll_address_change(cx).map_err(EitherError::B),
} }
} }
@ -267,13 +245,6 @@ where
} }
} }
#[derive(Debug, Copy, Clone)]
#[must_use = "futures do nothing unless polled"]
pub enum EitherOutbound<A: StreamMuxer, B: StreamMuxer> {
A(A::OutboundSubstream),
B(B::OutboundSubstream),
}
/// Implements `Future` and dispatches all method calls to either `First` or `Second`. /// Implements `Future` and dispatches all method calls to either `First` or `Second`.
#[pin_project(project = EitherFutureProj)] #[pin_project(project = EitherFutureProj)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]

View File

@ -63,62 +63,25 @@ mod singleton;
/// Provides multiplexing for a connection by allowing users to open substreams. /// Provides multiplexing for a connection by allowing users to open substreams.
/// ///
/// A substream created by a [`StreamMuxer`] is a type that implements [`AsyncRead`] and [`AsyncWrite`]. /// A substream created by a [`StreamMuxer`] is a type that implements [`AsyncRead`] and [`AsyncWrite`].
/// /// The [`StreamMuxer`] itself is modelled closely after [`AsyncWrite`]. It features `poll`-style
/// Inbound substreams are reported via [`StreamMuxer::poll_event`]. /// functions that allow the implementation to make progress on various tasks.
/// Outbound substreams can be opened via [`StreamMuxer::open_outbound`] and subsequent polling via
/// [`StreamMuxer::poll_outbound`].
pub trait StreamMuxer { pub trait StreamMuxer {
/// Type of the object that represents the raw substream where data can be read and written. /// Type of the object that represents the raw substream where data can be read and written.
type Substream: AsyncRead + AsyncWrite; type Substream: AsyncRead + AsyncWrite;
/// Future that will be resolved when the outgoing substream is open.
type OutboundSubstream;
/// Error type of the muxer /// Error type of the muxer
type Error: std::error::Error; type Error: std::error::Error;
/// Polls for a connection-wide event. /// Poll for new inbound substreams.
/// fn poll_inbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>>;
/// This function behaves the same as a `Stream`.
///
/// If `Pending` is returned, then the current task will be notified once the muxer
/// is ready to be polled, similar to the API of `Stream::poll()`.
/// Only the latest task that was used to call this method may be notified.
///
/// It is permissible and common to use this method to perform background
/// work, such as processing incoming packets and polling timers.
///
/// An error can be generated if the connection has been closed.
fn poll_event(
&self,
cx: &mut Context<'_>,
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>>;
/// Opens a new outgoing substream, and produces the equivalent to a future that will be /// Poll for a new, outbound substream.
/// resolved when it becomes available. fn poll_outbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>>;
///
/// The API of `OutboundSubstream` is totally opaque, and the object can only be interfaced
/// through the methods on the `StreamMuxer` trait.
fn open_outbound(&self) -> Self::OutboundSubstream;
/// Polls the outbound substream. /// Poll for an address change of the underlying connection.
/// ///
/// If `Pending` is returned, then the current task will be notified once the substream /// Not all implementations may support this feature.
/// is ready to be polled, similar to the API of `Future::poll()`. fn poll_address_change(&self, cx: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>>;
/// However, for each individual outbound substream, only the latest task that was used to
/// call this method may be notified.
///
/// May panic or produce an undefined result if an earlier polling of the same substream
/// returned `Ready` or `Err`.
fn poll_outbound(
&self,
cx: &mut Context<'_>,
s: &mut Self::OutboundSubstream,
) -> Poll<Result<Self::Substream, Self::Error>>;
/// Destroys an outbound substream future. Use this after the outbound substream has finished,
/// or if you want to interrupt it.
fn destroy_outbound(&self, s: Self::OutboundSubstream);
/// Closes this `StreamMuxer`. /// Closes this `StreamMuxer`.
/// ///
@ -132,38 +95,3 @@ pub trait StreamMuxer {
/// > immediately dropping the muxer. /// > immediately dropping the muxer.
fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>; fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
} }
/// Event about a connection, reported by an implementation of [`StreamMuxer`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StreamMuxerEvent<T> {
/// Remote has opened a new substream. Contains the substream in question.
InboundSubstream(T),
/// Address to the remote has changed. The previous one is now obsolete.
///
/// > **Note**: This can for example happen when using the QUIC protocol, where the two nodes
/// > can change their IP address while retaining the same QUIC connection.
AddressChange(Multiaddr),
}
impl<T> StreamMuxerEvent<T> {
/// If `self` is a [`StreamMuxerEvent::InboundSubstream`], returns the content. Otherwise
/// returns `None`.
pub fn into_inbound_substream(self) -> Option<T> {
if let StreamMuxerEvent::InboundSubstream(s) = self {
Some(s)
} else {
None
}
}
/// Map the stream within [`StreamMuxerEvent::InboundSubstream`] to a new type.
pub fn map_inbound_stream<O>(self, map: impl FnOnce(T) -> O) -> StreamMuxerEvent<O> {
match self {
StreamMuxerEvent::InboundSubstream(stream) => {
StreamMuxerEvent::InboundSubstream(map(stream))
}
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
}
}
}

View File

@ -1,23 +1,16 @@
use crate::muxing::StreamMuxerEvent;
use crate::StreamMuxer; use crate::StreamMuxer;
use fnv::FnvHashMap; use futures::{AsyncRead, AsyncWrite};
use futures::{ready, AsyncRead, AsyncWrite}; use multiaddr::Multiaddr;
use parking_lot::Mutex;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::io::{IoSlice, IoSliceMut}; use std::io::{IoSlice, IoSliceMut};
use std::pin::Pin; use std::pin::Pin;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::task::{Context, Poll}; use std::task::{Context, Poll};
/// Abstract `StreamMuxer`. /// Abstract `StreamMuxer`.
pub struct StreamMuxerBox { pub struct StreamMuxerBox {
inner: Box< inner: Box<dyn StreamMuxer<Substream = SubstreamBox, Error = io::Error> + Send + Sync>,
dyn StreamMuxer<Substream = SubstreamBox, OutboundSubstream = usize, Error = io::Error>
+ Send
+ Sync,
>,
} }
/// Abstract type for asynchronous reading and writing. /// Abstract type for asynchronous reading and writing.
@ -31,8 +24,6 @@ where
T: StreamMuxer, T: StreamMuxer,
{ {
inner: T, inner: T,
outbound: Mutex<FnvHashMap<usize, T::OutboundSubstream>>,
next_outbound: AtomicUsize,
} }
impl<T> StreamMuxer for Wrap<T> impl<T> StreamMuxer for Wrap<T>
@ -42,54 +33,30 @@ where
T::Error: Send + Sync + 'static, T::Error: Send + Sync + 'static,
{ {
type Substream = SubstreamBox; type Substream = SubstreamBox;
type OutboundSubstream = usize; // TODO: use a newtype
type Error = io::Error; type Error = io::Error;
#[inline]
fn poll_event(
&self,
cx: &mut Context<'_>,
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
let event = ready!(self.inner.poll_event(cx).map_err(into_io_error)?)
.map_inbound_stream(SubstreamBox::new);
Poll::Ready(Ok(event))
}
#[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,
cx: &mut Context<'_>,
substream: &mut Self::OutboundSubstream,
) -> Poll<Result<Self::Substream, Self::Error>> {
let mut list = self.outbound.lock();
let stream = ready!(self
.inner
.poll_outbound(cx, list.get_mut(substream).unwrap())
.map_err(into_io_error)?);
Poll::Ready(Ok(SubstreamBox::new(stream)))
}
#[inline]
fn destroy_outbound(&self, substream: Self::OutboundSubstream) {
let mut list = self.outbound.lock();
self.inner
.destroy_outbound(list.remove(&substream).unwrap())
}
#[inline] #[inline]
fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_close(cx).map_err(into_io_error) self.inner.poll_close(cx).map_err(into_io_error)
} }
fn poll_inbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
self.inner
.poll_inbound(cx)
.map_ok(SubstreamBox::new)
.map_err(into_io_error)
}
fn poll_outbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
self.inner
.poll_outbound(cx)
.map_ok(SubstreamBox::new)
.map_err(into_io_error)
}
fn poll_address_change(&self, cx: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>> {
self.inner.poll_address_change(cx).map_err(into_io_error)
}
} }
fn into_io_error<E>(err: E) -> io::Error fn into_io_error<E>(err: E) -> io::Error
@ -104,15 +71,10 @@ impl StreamMuxerBox {
pub fn new<T>(muxer: T) -> StreamMuxerBox pub fn new<T>(muxer: T) -> StreamMuxerBox
where where
T: StreamMuxer + Send + Sync + 'static, T: StreamMuxer + Send + Sync + 'static,
T::OutboundSubstream: Send,
T::Substream: Send + Unpin + 'static, T::Substream: Send + Unpin + 'static,
T::Error: Send + Sync + 'static, T::Error: Send + Sync + 'static,
{ {
let wrap = Wrap { let wrap = Wrap { inner: muxer };
inner: muxer,
outbound: Mutex::new(Default::default()),
next_outbound: AtomicUsize::new(0),
};
StreamMuxerBox { StreamMuxerBox {
inner: Box::new(wrap), inner: Box::new(wrap),
@ -122,40 +84,24 @@ impl StreamMuxerBox {
impl StreamMuxer for StreamMuxerBox { impl StreamMuxer for StreamMuxerBox {
type Substream = SubstreamBox; type Substream = SubstreamBox;
type OutboundSubstream = usize; // TODO: use a newtype
type Error = io::Error; type Error = io::Error;
#[inline]
fn poll_event(
&self,
cx: &mut Context<'_>,
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
self.inner.poll_event(cx)
}
#[inline]
fn open_outbound(&self) -> Self::OutboundSubstream {
self.inner.open_outbound()
}
#[inline]
fn poll_outbound(
&self,
cx: &mut Context<'_>,
s: &mut Self::OutboundSubstream,
) -> Poll<Result<Self::Substream, Self::Error>> {
self.inner.poll_outbound(cx, s)
}
#[inline]
fn destroy_outbound(&self, substream: Self::OutboundSubstream) {
self.inner.destroy_outbound(substream)
}
#[inline] #[inline]
fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_close(cx) self.inner.poll_close(cx)
} }
fn poll_inbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
self.inner.poll_inbound(cx)
}
fn poll_outbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
self.inner.poll_outbound(cx)
}
fn poll_address_change(&self, cx: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>> {
self.inner.poll_address_change(cx)
}
} }
impl SubstreamBox { impl SubstreamBox {

View File

@ -18,12 +18,10 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
use crate::{ use crate::{connection::Endpoint, muxing::StreamMuxer};
connection::Endpoint,
muxing::{StreamMuxer, StreamMuxerEvent},
};
use futures::prelude::*; use futures::prelude::*;
use multiaddr::Multiaddr;
use std::cell::Cell; use std::cell::Cell;
use std::{io, task::Context, task::Poll}; use std::{io, task::Context, task::Poll};
@ -52,55 +50,36 @@ impl<TSocket> SingletonMuxer<TSocket> {
} }
} }
/// Outbound substream attempt of the `SingletonMuxer`.
pub struct OutboundSubstream {}
impl<TSocket> StreamMuxer for SingletonMuxer<TSocket> impl<TSocket> StreamMuxer for SingletonMuxer<TSocket>
where where
TSocket: AsyncRead + AsyncWrite + Unpin, TSocket: AsyncRead + AsyncWrite + Unpin,
{ {
type Substream = TSocket; type Substream = TSocket;
type OutboundSubstream = OutboundSubstream;
type Error = io::Error; type Error = io::Error;
fn poll_event( fn poll_inbound(&self, _: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
&self,
_: &mut Context<'_>,
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, io::Error>> {
match self.endpoint { match self.endpoint {
Endpoint::Dialer => return Poll::Pending, Endpoint::Dialer => Poll::Pending,
Endpoint::Listener => {} Endpoint::Listener => match self.inner.replace(None) {
} None => Poll::Pending,
Some(stream) => Poll::Ready(Ok(stream)),
if let Some(stream) = self.inner.replace(None) { },
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(stream)))
} else {
Poll::Pending
} }
} }
fn open_outbound(&self) -> Self::OutboundSubstream { fn poll_outbound(&self, _: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
OutboundSubstream {}
}
fn poll_outbound(
&self,
_: &mut Context<'_>,
_: &mut Self::OutboundSubstream,
) -> Poll<Result<Self::Substream, io::Error>> {
match self.endpoint { match self.endpoint {
Endpoint::Listener => return Poll::Pending, Endpoint::Listener => Poll::Pending,
Endpoint::Dialer => {} Endpoint::Dialer => match self.inner.replace(None) {
} None => Poll::Pending,
Some(stream) => Poll::Ready(Ok(stream)),
if let Some(stream) = self.inner.replace(None) { },
Poll::Ready(Ok(stream))
} else {
Poll::Pending
} }
} }
fn destroy_outbound(&self, _: Self::OutboundSubstream) {} fn poll_address_change(&self, _: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>> {
Poll::Pending
}
fn poll_close(&self, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { fn poll_close(&self, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))

View File

@ -301,7 +301,6 @@ impl<T> Multiplexed<T> {
T::Error: Send + Sync, T::Error: Send + Sync,
M: StreamMuxer + Send + Sync + 'static, M: StreamMuxer + Send + Sync + 'static,
M::Substream: Send + Unpin + 'static, M::Substream: Send + Unpin + 'static,
M::OutboundSubstream: Send + 'static,
M::Error: Send + Sync + 'static, M::Error: Send + Sync + 'static,
{ {
boxed(self.map(|(i, m), _| (i, StreamMuxerBox::new(m)))) boxed(self.map(|(i, m), _| (i, StreamMuxerBox::new(m))))

View File

@ -13,5 +13,5 @@ clap = {version = "3.1.6", features = ["derive"]}
zeroize = "1" zeroize = "1"
serde = { version = "1.0.136", features = ["derive"] } serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79" serde_json = "1.0.79"
libp2p-core = { path = "../../core", default-features = false, version = "0.34.0"} libp2p-core = { path = "../../core", default-features = false, version = "0.35.0"}
base64 = "0.13.0" base64 = "0.13.0"

View File

@ -14,6 +14,8 @@
- Track number of connected nodes supporting a specific protocol via the identify protocol. See [PR 2734]. - Track number of connected nodes supporting a specific protocol via the identify protocol. See [PR 2734].
- Update to `libp2p-core` `v0.35.0`.
[PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/ [PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/
# 0.7.0 # 0.7.0

View File

@ -19,7 +19,7 @@ relay = ["libp2p-relay"]
dcutr = ["libp2p-dcutr"] dcutr = ["libp2p-dcutr"]
[dependencies] [dependencies]
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-dcutr = { version = "0.5.0", path = "../../protocols/dcutr", optional = true } libp2p-dcutr = { version = "0.5.0", path = "../../protocols/dcutr", optional = true }
libp2p-identify = { version = "0.38.0", path = "../../protocols/identify", optional = true } libp2p-identify = { version = "0.38.0", path = "../../protocols/identify", optional = true }
libp2p-kad = { version = "0.39.0", path = "../../protocols/kad", optional = true } libp2p-kad = { version = "0.39.0", path = "../../protocols/kad", optional = true }

View File

@ -1,3 +1,7 @@
# 0.35.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`
# 0.34.0 # 0.34.0
- `Substream` now implements `AsyncRead` and `AsyncWrite`. See [PR 2706]. - `Substream` now implements `AsyncRead` and `AsyncWrite`. See [PR 2706].

View File

@ -3,7 +3,7 @@ name = "libp2p-mplex"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Mplex multiplexing protocol for libp2p" description = "Mplex multiplexing protocol for libp2p"
version = "0.34.0" version = "0.35.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
bytes = "1" bytes = "1"
futures = "0.3.1" futures = "0.3.1"
asynchronous-codec = "0.6" asynchronous-codec = "0.6"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4" log = "0.4"
nohash-hasher = "0.2" nohash-hasher = "0.2"
parking_lot = "0.12" parking_lot = "0.12"

View File

@ -114,11 +114,9 @@ fn run(
} }
transport::TransportEvent::Incoming { upgrade, .. } => { transport::TransportEvent::Incoming { upgrade, .. } => {
let (_peer, conn) = upgrade.await.unwrap(); let (_peer, conn) = upgrade.await.unwrap();
let mut s = poll_fn(|cx| conn.poll_event(cx)) let mut s = poll_fn(|cx| conn.poll_inbound(cx))
.await .await
.expect("unexpected error") .expect("unexpected error");
.into_inbound_substream()
.expect("Unexpected muxer event");
let mut buf = vec![0u8; payload_len]; let mut buf = vec![0u8; payload_len];
let mut off = 0; let mut off = 0;
@ -143,10 +141,7 @@ fn run(
let sender = async move { let sender = async move {
let addr = addr_receiver.await.unwrap(); let addr = addr_receiver.await.unwrap();
let (_peer, conn) = sender_trans.dial(addr).unwrap().await.unwrap(); let (_peer, conn) = sender_trans.dial(addr).unwrap().await.unwrap();
let mut handle = conn.open_outbound(); let mut stream = poll_fn(|cx| conn.poll_outbound(cx)).await.unwrap();
let mut stream = poll_fn(|cx| conn.poll_outbound(cx, &mut handle))
.await
.unwrap();
let mut off = 0; let mut off = 0;
loop { loop {
let n = poll_fn(|cx| Pin::new(&mut stream).poll_write(cx, &payload[off..])) let n = poll_fn(|cx| Pin::new(&mut stream).poll_write(cx, &payload[off..]))

View File

@ -28,9 +28,8 @@ use bytes::Bytes;
use codec::LocalStreamId; use codec::LocalStreamId;
use futures::{future, prelude::*, ready}; use futures::{future, prelude::*, ready};
use libp2p_core::{ use libp2p_core::{
muxing::StreamMuxerEvent,
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}, upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo},
StreamMuxer, Multiaddr, StreamMuxer,
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{cmp, iter, pin::Pin, sync::Arc, task::Context, task::Poll}; use std::{cmp, iter, pin::Pin, sync::Arc, task::Context, task::Poll};
@ -75,9 +74,6 @@ where
} }
/// Multiplexer. Implements the `StreamMuxer` trait. /// Multiplexer. Implements the `StreamMuxer` trait.
///
/// This implementation isn't capable of detecting when the underlying socket changes its address,
/// and no [`StreamMuxerEvent::AddressChange`] event is ever emitted.
pub struct Multiplex<C> { pub struct Multiplex<C> {
io: Arc<Mutex<io::Multiplexed<C>>>, io: Arc<Mutex<io::Multiplexed<C>>>,
} }
@ -87,33 +83,24 @@ where
C: AsyncRead + AsyncWrite + Unpin, C: AsyncRead + AsyncWrite + Unpin,
{ {
type Substream = Substream<C>; type Substream = Substream<C>;
type OutboundSubstream = OutboundSubstream;
type Error = io::Error; type Error = io::Error;
fn poll_event( fn poll_inbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
&self, self.io
cx: &mut Context<'_>, .lock()
) -> Poll<io::Result<StreamMuxerEvent<Self::Substream>>> { .poll_next_stream(cx)
let stream_id = ready!(self.io.lock().poll_next_stream(cx))?; .map_ok(|stream_id| Substream::new(stream_id, self.io.clone()))
let stream = Substream::new(stream_id, self.io.clone());
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(stream)))
} }
fn open_outbound(&self) -> Self::OutboundSubstream { fn poll_outbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
OutboundSubstream {} self.io
.lock()
.poll_open_stream(cx)
.map_ok(|stream_id| Substream::new(stream_id, self.io.clone()))
} }
fn poll_outbound( fn poll_address_change(&self, _: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>> {
&self, Poll::Pending
cx: &mut Context<'_>,
_: &mut Self::OutboundSubstream,
) -> Poll<Result<Self::Substream, io::Error>> {
let stream_id = ready!(self.io.lock().poll_open_stream(cx))?;
Poll::Ready(Ok(Substream::new(stream_id, self.io.clone())))
}
fn destroy_outbound(&self, _substream: Self::OutboundSubstream) {
// Nothing to do, since `open_outbound` creates no new local state.
} }
fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { fn poll_close(&self, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
@ -121,9 +108,6 @@ where
} }
} }
/// Active attempt to open an outbound substream.
pub struct OutboundSubstream {}
impl<C> AsyncRead for Substream<C> impl<C> AsyncRead for Substream<C>
where where
C: AsyncRead + AsyncWrite + Unpin, C: AsyncRead + AsyncWrite + Unpin,

View File

@ -60,10 +60,7 @@ fn async_write() {
.await .await
.unwrap(); .unwrap();
let mut outbound_token = client.open_outbound(); let mut outbound = poll_fn(|cx| client.poll_outbound(cx)).await.unwrap();
let mut outbound = poll_fn(|cx| client.poll_outbound(cx, &mut outbound_token))
.await
.unwrap();
let mut buf = Vec::new(); let mut buf = Vec::new();
outbound.read_to_end(&mut buf).await.unwrap(); outbound.read_to_end(&mut buf).await.unwrap();
@ -76,15 +73,7 @@ fn async_write() {
.and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1));
let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap()); let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap());
let mut inbound = loop { let mut inbound = poll_fn(|cx| client.poll_inbound(cx)).await.unwrap();
if let Some(s) = poll_fn(|cx| client.poll_event(cx))
.await
.unwrap()
.into_inbound_substream()
{
break s;
}
};
inbound.write_all(b"hello world").await.unwrap(); inbound.write_all(b"hello world").await.unwrap();
// The test consists in making sure that this flushes the substream. // The test consists in making sure that this flushes the substream.

View File

@ -60,10 +60,7 @@ fn client_to_server_outbound() {
.await .await
.unwrap(); .unwrap();
let mut outbound_token = client.open_outbound(); let mut outbound = poll_fn(|cx| client.poll_outbound(cx)).await.unwrap();
let mut outbound = poll_fn(|cx| client.poll_outbound(cx, &mut outbound_token))
.await
.unwrap();
let mut buf = Vec::new(); let mut buf = Vec::new();
outbound.read_to_end(&mut buf).await.unwrap(); outbound.read_to_end(&mut buf).await.unwrap();
@ -77,15 +74,7 @@ fn client_to_server_outbound() {
.boxed(); .boxed();
let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap()); let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap());
let mut inbound = loop { let mut inbound = poll_fn(|cx| client.poll_inbound(cx)).await.unwrap();
if let Some(s) = poll_fn(|cx| client.poll_event(cx))
.await
.unwrap()
.into_inbound_substream()
{
break s;
}
};
inbound.write_all(b"hello world").await.unwrap(); inbound.write_all(b"hello world").await.unwrap();
inbound.close().await.unwrap(); inbound.close().await.unwrap();
@ -131,15 +120,7 @@ fn client_to_server_inbound() {
.unwrap(), .unwrap(),
); );
let mut inbound = loop { let mut inbound = poll_fn(|cx| client.poll_inbound(cx)).await.unwrap();
if let Some(s) = poll_fn(|cx| client.poll_event(cx))
.await
.unwrap()
.into_inbound_substream()
{
break s;
}
};
let mut buf = Vec::new(); let mut buf = Vec::new();
inbound.read_to_end(&mut buf).await.unwrap(); inbound.read_to_end(&mut buf).await.unwrap();
@ -154,10 +135,7 @@ fn client_to_server_inbound() {
let client = transport.dial(rx.await.unwrap()).unwrap().await.unwrap(); let client = transport.dial(rx.await.unwrap()).unwrap().await.unwrap();
let mut outbound_token = client.open_outbound(); let mut outbound = poll_fn(|cx| client.poll_outbound(cx)).await.unwrap();
let mut outbound = poll_fn(|cx| client.poll_outbound(cx, &mut outbound_token))
.await
.unwrap();
outbound.write_all(b"hello world").await.unwrap(); outbound.write_all(b"hello world").await.unwrap();
outbound.close().await.unwrap(); outbound.close().await.unwrap();
@ -199,10 +177,7 @@ fn protocol_not_match() {
.await .await
.unwrap(); .unwrap();
let mut outbound_token = client.open_outbound(); let mut outbound = poll_fn(|cx| client.poll_outbound(cx)).await.unwrap();
let mut outbound = poll_fn(|cx| client.poll_outbound(cx, &mut outbound_token))
.await
.unwrap();
let mut buf = Vec::new(); let mut buf = Vec::new();
outbound.read_to_end(&mut buf).await.unwrap(); outbound.read_to_end(&mut buf).await.unwrap();

View File

@ -1,3 +1,7 @@
# 0.39.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`
# 0.38.0 # 0.38.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-yamux"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Yamux multiplexing protocol for libp2p" description = "Yamux multiplexing protocol for libp2p"
version = "0.38.0" version = "0.39.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.1"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
parking_lot = "0.12" parking_lot = "0.12"
thiserror = "1.0" thiserror = "1.0"
yamux = "0.10.0" yamux = "0.10.0"

View File

@ -24,11 +24,11 @@
use futures::{ use futures::{
future, future,
prelude::*, prelude::*,
ready,
stream::{BoxStream, LocalBoxStream}, stream::{BoxStream, LocalBoxStream},
}; };
use libp2p_core::muxing::{StreamMuxer, StreamMuxerEvent}; use libp2p_core::muxing::StreamMuxer;
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use libp2p_core::Multiaddr;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
fmt, io, iter, mem, fmt, io, iter, mem,
@ -36,6 +36,7 @@ use std::{
task::{Context, Poll}, task::{Context, Poll},
}; };
use thiserror::Error; use thiserror::Error;
use yamux::ConnectionError;
/// A Yamux connection. /// A Yamux connection.
pub struct Yamux<S>(Mutex<Inner<S>>); pub struct Yamux<S>(Mutex<Inner<S>>);
@ -97,44 +98,35 @@ where
pub type YamuxResult<T> = Result<T, YamuxError>; pub type YamuxResult<T> = Result<T, YamuxError>;
/// > **Note**: This implementation never emits [`StreamMuxerEvent::AddressChange`] events.
impl<S> StreamMuxer for Yamux<S> impl<S> StreamMuxer for Yamux<S>
where where
S: Stream<Item = Result<yamux::Stream, YamuxError>> + Unpin, S: Stream<Item = Result<yamux::Stream, YamuxError>> + Unpin,
{ {
type Substream = yamux::Stream; type Substream = yamux::Stream;
type OutboundSubstream = OpenSubstreamToken;
type Error = YamuxError; type Error = YamuxError;
fn poll_event( fn poll_inbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
&self, self.0
c: &mut Context<'_>, .lock()
) -> Poll<YamuxResult<StreamMuxerEvent<Self::Substream>>> { .incoming
let mut inner = self.0.lock(); .poll_next_unpin(cx)
match ready!(inner.incoming.poll_next_unpin(c)) { .map(|maybe_stream| {
Some(Ok(s)) => Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(s))), let stream = maybe_stream
Some(Err(e)) => Poll::Ready(Err(e)), .transpose()?
None => Poll::Ready(Err(yamux::ConnectionError::Closed.into())), .ok_or(YamuxError(ConnectionError::Closed))?;
}
Ok(stream)
})
} }
fn open_outbound(&self) -> Self::OutboundSubstream { fn poll_outbound(&self, cx: &mut Context<'_>) -> Poll<Result<Self::Substream, Self::Error>> {
OpenSubstreamToken(()) Pin::new(&mut self.0.lock().control)
} .poll_open_stream(cx)
fn poll_outbound(
&self,
c: &mut Context<'_>,
_: &mut OpenSubstreamToken,
) -> Poll<YamuxResult<Self::Substream>> {
let mut inner = self.0.lock();
Pin::new(&mut inner.control)
.poll_open_stream(c)
.map_err(YamuxError) .map_err(YamuxError)
} }
fn destroy_outbound(&self, _: Self::OutboundSubstream) { fn poll_address_change(&self, _: &mut Context<'_>) -> Poll<Result<Multiaddr, Self::Error>> {
self.0.lock().control.abort_open_stream() Poll::Pending
} }
fn poll_close(&self, c: &mut Context<'_>) -> Poll<YamuxResult<()>> { fn poll_close(&self, c: &mut Context<'_>) -> Poll<YamuxResult<()>> {

View File

@ -4,6 +4,8 @@
- Update to `libp2p-request-response` `v0.20.0`. - Update to `libp2p-request-response` `v0.20.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.5.0 # 0.5.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -18,7 +18,7 @@ async-trait = "0.1"
futures = "0.3" futures = "0.3"
futures-timer = "3.0" futures-timer = "3.0"
instant = "0.1" instant = "0.1"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
libp2p-request-response = { version = "0.20.0", path = "../request-response" } libp2p-request-response = { version = "0.20.0", path = "../request-response" }
log = "0.4" log = "0.4"

View File

@ -4,6 +4,8 @@
- Expose `PROTOCOL_NAME`. See [PR 2734]. - Expose `PROTOCOL_NAME`. See [PR 2734].
- Update to `libp2p-core` `v0.35.0`.
[PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/ [PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/
# 0.4.0 # 0.4.0

View File

@ -17,7 +17,7 @@ either = "1.6.0"
futures = "0.3.1" futures = "0.3.1"
futures-timer = "3.0" futures-timer = "3.0"
instant = "0.1.11" instant = "0.1.11"
libp2p-core = { version = "0.34.0", path = "../../core" } libp2p-core = { version = "0.35.0", path = "../../core" }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4" log = "0.4"
prost-codec = { version = "0.1", path = "../../misc/prost-codec" } prost-codec = { version = "0.1", path = "../../misc/prost-codec" }

View File

@ -2,6 +2,8 @@
- Update to `libp2p-swarm` `v0.38.0`. - Update to `libp2p-swarm` `v0.38.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.37.0 # 0.37.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
cuckoofilter = "0.5.0" cuckoofilter = "0.5.0"
fnv = "1.0" fnv = "1.0"
futures = "0.3.1" futures = "0.3.1"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4" log = "0.4"
prost = "0.10" prost = "0.10"

View File

@ -2,6 +2,8 @@
- Update to `libp2p-swarm` `v0.38.0`. - Update to `libp2p-swarm` `v0.38.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.39.0 # 0.39.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies] [dependencies]
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
bytes = "1.0" bytes = "1.0"
byteorder = "1.3.4" byteorder = "1.3.4"
fnv = "1.0.7" fnv = "1.0.7"

View File

@ -4,6 +4,8 @@
- Expose `PROTOCOL_NAME` and `PUSH_PROTOCOL_NAME`. See [PR 2734]. - Expose `PROTOCOL_NAME` and `PUSH_PROTOCOL_NAME`. See [PR 2734].
- Update to `libp2p-core` `v0.35.0`.
[PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/ [PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/
# 0.37.0 # 0.37.0

View File

@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
asynchronous-codec = "0.6" asynchronous-codec = "0.6"
futures = "0.3.1" futures = "0.3.1"
futures-timer = "3.0.2" futures-timer = "3.0.2"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4.1" log = "0.4.1"
lru = "0.7.2" lru = "0.7.2"

View File

@ -2,6 +2,8 @@
- Update to `libp2p-swarm` `v0.38.0`. - Update to `libp2p-swarm` `v0.38.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.38.0 # 0.38.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -18,7 +18,7 @@ fnv = "1.0"
asynchronous-codec = "0.6" asynchronous-codec = "0.6"
futures = "0.3.1" futures = "0.3.1"
log = "0.4" log = "0.4"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
prost = "0.10" prost = "0.10"
rand = "0.7.2" rand = "0.7.2"

View File

@ -2,6 +2,8 @@
- Update to `libp2p-swarm` `v0.38.0`. - Update to `libp2p-swarm` `v0.38.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.38.0 # 0.38.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -17,7 +17,7 @@ dns-parser = "0.8.0"
futures = "0.3.13" futures = "0.3.13"
if-watch = "1.0.0" if-watch = "1.0.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4.14" log = "0.4.14"
rand = "0.8.3" rand = "0.8.3"

View File

@ -4,6 +4,8 @@
- Expose `PROTOCOL_NAME`. See [PR 2734]. - Expose `PROTOCOL_NAME`. See [PR 2734].
- Update to `libp2p-core` `v0.35.0`.
[PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/ [PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/
# 0.37.0 # 0.37.0

View File

@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
futures = "0.3.1" futures = "0.3.1"
futures-timer = "3.0.2" futures-timer = "3.0.2"
instant = "0.1.11" instant = "0.1.11"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4.1" log = "0.4.1"
rand = "0.7.2" rand = "0.7.2"

View File

@ -4,6 +4,8 @@
- Expose `HOP_PROTOCOL_NAME` and `STOP_PROTOCOL_NAME`. See [PR 2734]. - Expose `HOP_PROTOCOL_NAME` and `STOP_PROTOCOL_NAME`. See [PR 2734].
- Update to `libp2p-core` `v0.35.0`.
[PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/ [PR 2734]: https://github.com/libp2p/rust-libp2p/pull/2734/
# 0.10.0 # 0.10.0

View File

@ -17,7 +17,7 @@ either = "1.6.0"
futures = "0.3.1" futures = "0.3.1"
futures-timer = "3" futures-timer = "3"
instant = "0.1.11" instant = "0.1.11"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4" log = "0.4"
pin-project = "1" pin-project = "1"

View File

@ -2,6 +2,8 @@
- Update to `libp2p-swarm` `v0.38.0`. - Update to `libp2p-swarm` `v0.38.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.7.0 # 0.7.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies] [dependencies]
asynchronous-codec = "0.6" asynchronous-codec = "0.6"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
prost = "0.10" prost = "0.10"
void = "1" void = "1"

View File

@ -2,6 +2,8 @@
- Update to `libp2p-swarm` `v0.38.0`. - Update to `libp2p-swarm` `v0.38.0`.
- Update to `libp2p-core` `v0.35.0`.
# 0.19.0 # 0.19.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -15,7 +15,7 @@ async-trait = "0.1"
bytes = "1" bytes = "1"
futures = "0.3.1" futures = "0.3.1"
instant = "0.1.11" instant = "0.1.11"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
libp2p-swarm = { version = "0.38.0", path = "../../swarm" } libp2p-swarm = { version = "0.38.0", path = "../../swarm" }
log = "0.4.11" log = "0.4.11"
rand = "0.7" rand = "0.7"

View File

@ -2,6 +2,8 @@
- Update dial address concurrency factor to `8`, thus dialing up to 8 addresses concurrently for a single connection attempt. See `Swarm::dial_concurrency_factor` and [PR 2741]. - Update dial address concurrency factor to `8`, thus dialing up to 8 addresses concurrently for a single connection attempt. See `Swarm::dial_concurrency_factor` and [PR 2741].
- Update to `libp2p-core` `v0.35.0`.
[PR 2741]: https://github.com/libp2p/rust-libp2p/pull/2741/ [PR 2741]: https://github.com/libp2p/rust-libp2p/pull/2741/
# 0.37.0 # 0.37.0

View File

@ -16,7 +16,7 @@ fnv = "1.0"
futures = "0.3.1" futures = "0.3.1"
futures-timer = "3.0.2" futures-timer = "3.0.2"
instant = "0.1.11" instant = "0.1.11"
libp2p-core = { version = "0.34.0", path = "../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../core", default-features = false }
log = "0.4" log = "0.4"
pin-project = "1.0.0" pin-project = "1.0.0"
rand = "0.7" rand = "0.7"

View File

@ -20,7 +20,6 @@
mod error; mod error;
mod handler_wrapper; mod handler_wrapper;
mod substream;
pub(crate) mod pool; pub(crate) mod pool;
@ -30,18 +29,19 @@ pub use error::{
}; };
pub use pool::{ConnectionCounters, ConnectionLimits}; pub use pool::{ConnectionCounters, ConnectionLimits};
pub use pool::{EstablishedConnection, PendingConnection}; pub use pool::{EstablishedConnection, PendingConnection};
pub use substream::{Close, SubstreamEndpoint};
use crate::handler::ConnectionHandler; use crate::handler::ConnectionHandler;
use crate::IntoConnectionHandler; use crate::IntoConnectionHandler;
use futures::future::poll_fn;
use handler_wrapper::HandlerWrapper; use handler_wrapper::HandlerWrapper;
use libp2p_core::connection::ConnectedPoint; use libp2p_core::connection::ConnectedPoint;
use libp2p_core::multiaddr::Multiaddr; use libp2p_core::multiaddr::Multiaddr;
use libp2p_core::muxing::StreamMuxerBox; use libp2p_core::muxing::StreamMuxerBox;
use libp2p_core::upgrade;
use libp2p_core::PeerId; use libp2p_core::PeerId;
use std::{error::Error, fmt, pin::Pin, task::Context, task::Poll}; use libp2p_core::{upgrade, StreamMuxer};
use substream::{Muxing, SubstreamEvent}; 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. /// Information about a successfully established connection.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -52,6 +52,13 @@ pub struct Connected {
pub peer_id: PeerId, 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`]. /// Event generated by a [`Connection`].
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Event<T> { pub enum Event<T> {
@ -67,19 +74,22 @@ where
THandler: ConnectionHandler, THandler: ConnectionHandler,
{ {
/// Node that handles the muxing. /// Node that handles the muxing.
muxing: substream::Muxing<StreamMuxerBox, handler_wrapper::OutboundOpenInfo<THandler>>, muxing: StreamMuxerBox,
/// Handler that processes substreams. /// Handler that processes substreams.
handler: HandlerWrapper<THandler>, 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> impl<THandler> fmt::Debug for Connection<THandler>
where where
THandler: ConnectionHandler + fmt::Debug, THandler: ConnectionHandler + fmt::Debug,
THandler::OutboundOpenInfo: fmt::Debug,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Connection") f.debug_struct("Connection")
.field("muxing", &self.muxing)
.field("handler", &self.handler) .field("handler", &self.handler)
.field("open_info", &self.open_info)
.finish() .finish()
} }
} }
@ -108,8 +118,9 @@ where
max_negotiating_inbound_streams, max_negotiating_inbound_streams,
); );
Connection { Connection {
muxing: Muxing::new(muxer), muxing: muxer,
handler: wrapped_handler, handler: wrapped_handler,
open_info: VecDeque::with_capacity(8),
} }
} }
@ -120,10 +131,10 @@ where
/// Begins an orderly shutdown of the connection, returning the connection /// Begins an orderly shutdown of the connection, returning the connection
/// handler and a `Future` that resolves when connection shutdown is complete. /// 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.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)? { match self.handler.poll(cx)? {
Poll::Pending => {} Poll::Pending => {}
Poll::Ready(handler_wrapper::Event::OutboundSubstreamRequest(user_data)) => { Poll::Ready(handler_wrapper::Event::OutboundSubstreamRequest(user_data)) => {
self.muxing.open_substream(user_data); self.open_info.push_back(user_data);
continue; continue; // Poll handler until exhausted.
} }
Poll::Ready(handler_wrapper::Event::Custom(event)) => { Poll::Ready(handler_wrapper::Event::Custom(event)) => {
return Poll::Ready(Ok(Event::Handler(event))); return Poll::Ready(Ok(Event::Handler(event)));
} }
} }
// Perform I/O on the connection through the muxer, informing the handler if !self.open_info.is_empty() {
// of new substreams. if let Poll::Ready(substream) = self.muxing.poll_outbound(cx)? {
match self.muxing.poll(cx)? { let user_data = self
Poll::Pending => {} .open_info
Poll::Ready(SubstreamEvent::InboundSubstream { substream }) => { .pop_front()
self.handler .expect("`open_info` is not empty");
.inject_substream(substream, SubstreamEndpoint::Listener);
continue;
}
Poll::Ready(SubstreamEvent::OutboundSubstream {
user_data,
substream,
}) => {
let endpoint = SubstreamEndpoint::Dialer(user_data); let endpoint = SubstreamEndpoint::Dialer(user_data);
self.handler.inject_substream(substream, endpoint); self.handler.inject_substream(substream, endpoint);
continue; continue; // Go back to the top, handler can potentially make progress again.
}
Poll::Ready(SubstreamEvent::AddressChange(address)) => {
self.handler.inject_address_change(&address);
return Poll::Ready(Ok(Event::AddressChange(address)));
} }
} }
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`.
} }
} }
} }

View File

@ -1,252 +0,0 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
//
// 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.
use futures::prelude::*;
use libp2p_core::multiaddr::Multiaddr;
use libp2p_core::muxing::{StreamMuxer, StreamMuxerEvent};
use smallvec::SmallVec;
use std::sync::Arc;
use std::{fmt, pin::Pin, task::Context, task::Poll};
/// Endpoint for a received substream.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SubstreamEndpoint<TDialInfo> {
Dialer(TDialInfo),
Listener,
}
/// Implementation of `Stream` that handles substream multiplexing.
///
/// The stream will receive substreams and can be used to open new outgoing substreams. Destroying
/// the `Muxing` will **not** close the existing substreams.
///
/// The stream will close once both the inbound and outbound channels are closed, and no more
/// outbound substream attempt is pending.
pub struct Muxing<TMuxer, TUserData>
where
TMuxer: StreamMuxer,
{
/// The muxer used to manage substreams.
inner: Arc<TMuxer>,
/// List of substreams we are currently opening.
outbound_substreams: SmallVec<[(TUserData, TMuxer::OutboundSubstream); 8]>,
}
/// Future that signals the remote that we have closed the connection.
pub struct Close<TMuxer> {
/// Muxer to close.
muxer: Arc<TMuxer>,
}
/// Event that can happen on the `Muxing`.
pub enum SubstreamEvent<TMuxer, TUserData>
where
TMuxer: StreamMuxer,
{
/// A new inbound substream arrived.
InboundSubstream {
/// The newly-opened substream. Will return EOF of an error if the `Muxing` is
/// destroyed or `close_graceful` is called.
substream: TMuxer::Substream,
},
/// An outbound substream has successfully been opened.
OutboundSubstream {
/// User data that has been passed to the `open_substream` method.
user_data: TUserData,
/// The newly-opened substream. Will return EOF of an error if the `Muxing` is
/// destroyed or `close_graceful` is called.
substream: TMuxer::Substream,
},
/// Address to the remote has changed. The previous one is now obsolete.
///
/// > **Note**: This can for example happen when using the QUIC protocol, where the two nodes
/// > can change their IP address while retaining the same QUIC connection.
AddressChange(Multiaddr),
}
/// Identifier for a substream being opened.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct OutboundSubstreamId(usize);
impl<TMuxer, TUserData> Muxing<TMuxer, TUserData>
where
TMuxer: StreamMuxer,
{
/// Creates a new node events stream.
pub fn new(muxer: TMuxer) -> Self {
Muxing {
inner: Arc::new(muxer),
outbound_substreams: SmallVec::new(),
}
}
/// Starts the process of opening a new outbound substream.
///
/// After calling this method, polling the stream should eventually produce either an
/// `OutboundSubstream` event or an `OutboundClosed` event containing the user data that has
/// been passed to this method.
pub fn open_substream(&mut self, user_data: TUserData) {
let raw = self.inner.open_outbound();
self.outbound_substreams.push((user_data, raw));
}
/// Destroys the node stream and returns all the pending outbound substreams, plus an object
/// that signals the remote that we shut down the connection.
#[must_use]
pub fn close(mut self) -> (Close<TMuxer>, Vec<TUserData>) {
let substreams = self.cancel_outgoing();
let close = Close {
muxer: self.inner.clone(),
};
(close, substreams)
}
/// Destroys all outbound streams and returns the corresponding user data.
pub fn cancel_outgoing(&mut self) -> Vec<TUserData> {
let mut out = Vec::with_capacity(self.outbound_substreams.len());
for (user_data, outbound) in self.outbound_substreams.drain(..) {
out.push(user_data);
self.inner.destroy_outbound(outbound);
}
out
}
/// Provides an API similar to `Future`.
pub fn poll(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<SubstreamEvent<TMuxer, TUserData>, TMuxer::Error>> {
// Polling inbound substream.
match self.inner.poll_event(cx) {
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(substream))) => {
return Poll::Ready(Ok(SubstreamEvent::InboundSubstream { substream }));
}
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(addr))) => {
return Poll::Ready(Ok(SubstreamEvent::AddressChange(addr)))
}
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
Poll::Pending => {}
}
// Polling outbound substreams.
// We remove each element from `outbound_substreams` one by one and add them back.
for n in (0..self.outbound_substreams.len()).rev() {
let (user_data, mut outbound) = self.outbound_substreams.swap_remove(n);
match self.inner.poll_outbound(cx, &mut outbound) {
Poll::Ready(Ok(substream)) => {
self.inner.destroy_outbound(outbound);
return Poll::Ready(Ok(SubstreamEvent::OutboundSubstream {
user_data,
substream,
}));
}
Poll::Pending => {
self.outbound_substreams.push((user_data, outbound));
}
Poll::Ready(Err(err)) => {
self.inner.destroy_outbound(outbound);
return Poll::Ready(Err(err));
}
}
}
// Nothing happened. Register our task to be notified and return.
Poll::Pending
}
}
impl<TMuxer, TUserData> fmt::Debug for Muxing<TMuxer, TUserData>
where
TMuxer: StreamMuxer,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Muxing")
.field("outbound_substreams", &self.outbound_substreams.len())
.finish()
}
}
impl<TMuxer, TUserData> Drop for Muxing<TMuxer, TUserData>
where
TMuxer: StreamMuxer,
{
fn drop(&mut self) {
// The substreams that were produced will continue to work, as the muxer is held in an Arc.
// However we will no longer process any further inbound or outbound substream, and we
// therefore close everything.
for (_, outbound) in self.outbound_substreams.drain(..) {
self.inner.destroy_outbound(outbound);
}
}
}
impl<TMuxer> Future for Close<TMuxer>
where
TMuxer: StreamMuxer,
{
type Output = Result<(), TMuxer::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.muxer.poll_close(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(Ok(())) => Poll::Ready(Ok(())),
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
}
}
}
impl<TMuxer> fmt::Debug for Close<TMuxer>
where
TMuxer: StreamMuxer,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Close").finish()
}
}
impl<TMuxer, TUserData> fmt::Debug for SubstreamEvent<TMuxer, TUserData>
where
TMuxer: StreamMuxer,
TMuxer::Substream: fmt::Debug,
TUserData: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SubstreamEvent::InboundSubstream { substream } => f
.debug_struct("SubstreamEvent::OutboundClosed")
.field("substream", substream)
.finish(),
SubstreamEvent::OutboundSubstream {
user_data,
substream,
} => f
.debug_struct("SubstreamEvent::OutboundSubstream")
.field("user_data", user_data)
.field("substream", substream)
.finish(),
SubstreamEvent::AddressChange(address) => f
.debug_struct("SubstreamEvent::AddressChange")
.field("address", address)
.finish(),
}
}
}

View File

@ -1,3 +1,7 @@
# 0.35.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.34.0 # 0.34.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-deflate"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Deflate encryption protocol for libp2p" description = "Deflate encryption protocol for libp2p"
version = "0.34.0" version = "0.35.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.1"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
flate2 = "1.0" flate2 = "1.0"
[dev-dependencies] [dev-dependencies]

View File

@ -1,3 +1,7 @@
# 0.35.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.34.0 # 0.34.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-dns"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "DNS transport implementation for libp2p" description = "DNS transport implementation for libp2p"
version = "0.34.0" version = "0.35.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -11,7 +11,7 @@ keywords = ["peer-to-peer", "libp2p", "networking"]
categories = ["network-programming", "asynchronous"] categories = ["network-programming", "asynchronous"]
[dependencies] [dependencies]
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4.1" log = "0.4.1"
futures = "0.3.1" futures = "0.3.1"
async-std-resolver = { version = "0.21", optional = true } async-std-resolver = { version = "0.21", optional = true }

View File

@ -1,3 +1,7 @@
# 0.38.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.37.0 # 0.37.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-noise"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Cryptographic handshake protocol using the noise framework." description = "Cryptographic handshake protocol using the noise framework."
version = "0.37.0" version = "0.38.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -13,7 +13,7 @@ bytes = "1"
curve25519-dalek = "3.0.0" curve25519-dalek = "3.0.0"
futures = "0.3.1" futures = "0.3.1"
lazy_static = "1.2" lazy_static = "1.2"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4" log = "0.4"
prost = "0.10" prost = "0.10"
rand = "0.8.3" rand = "0.8.3"

View File

@ -1,3 +1,7 @@
# 0.35.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.34.0 # 0.34.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-plaintext"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Plaintext encryption dummy protocol for libp2p" description = "Plaintext encryption dummy protocol for libp2p"
version = "0.34.0" version = "0.35.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
bytes = "1" bytes = "1"
futures = "0.3.1" futures = "0.3.1"
asynchronous-codec = "0.6" asynchronous-codec = "0.6"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4.8" log = "0.4.8"
prost = "0.10" prost = "0.10"
unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] } unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }

View File

@ -18,7 +18,7 @@ if-watch = { version = "1.0.0", optional = true }
if-addrs = { version = "0.7.0", optional = true } if-addrs = { version = "0.7.0", optional = true }
ipnet = "2.0.0" ipnet = "2.0.0"
libc = "0.2.80" libc = "0.2.80"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4.11" log = "0.4.11"
socket2 = { version = "0.4.0", features = ["all"] } socket2 = { version = "0.4.0", features = ["all"] }
tokio-crate = { package = "tokio", version = "1.19.0", default-features = false, features = ["net"], optional = true } tokio-crate = { package = "tokio", version = "1.19.0", default-features = false, features = ["net"], optional = true }

View File

@ -1,3 +1,7 @@
# 0.34.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.33.0 # 0.33.0
- Update dependencies. - Update dependencies.

View File

@ -3,7 +3,7 @@ name = "libp2p-uds"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Unix domain sockets transport for libp2p" description = "Unix domain sockets transport for libp2p"
version = "0.33.0" version = "0.34.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"]
[target.'cfg(all(unix, not(target_os = "emscripten")))'.dependencies] [target.'cfg(all(unix, not(target_os = "emscripten")))'.dependencies]
async-std = { version = "1.6.2", optional = true } async-std = { version = "1.6.2", optional = true }
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4.1" log = "0.4.1"
futures = "0.3.1" futures = "0.3.1"
tokio = { version = "1.15", default-features = false, features = ["net"], optional = true } tokio = { version = "1.15", default-features = false, features = ["net"], optional = true }

View File

@ -1,3 +1,7 @@
# 0.35.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.34.0 # 0.34.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-wasm-ext"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "Allows passing in an external transport in a WASM environment" description = "Allows passing in an external transport in a WASM environment"
version = "0.34.0" version = "0.35.0"
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"] authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -13,7 +13,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies] [dependencies]
futures = "0.3.1" futures = "0.3.1"
js-sys = "0.3.50" js-sys = "0.3.50"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
parity-send-wrapper = "0.1.0" parity-send-wrapper = "0.1.0"
wasm-bindgen = "0.2.42" wasm-bindgen = "0.2.42"
wasm-bindgen-futures = "0.4.4" wasm-bindgen-futures = "0.4.4"

View File

@ -1,3 +1,7 @@
# 0.37.0 [unreleased]
- Update to `libp2p-core` `v0.35.0`.
# 0.36.0 # 0.36.0
- Update to `libp2p-core` `v0.34.0`. - Update to `libp2p-core` `v0.34.0`.

View File

@ -3,7 +3,7 @@ name = "libp2p-websocket"
edition = "2021" edition = "2021"
rust-version = "1.56.1" rust-version = "1.56.1"
description = "WebSocket transport for libp2p" description = "WebSocket transport for libp2p"
version = "0.36.0" version = "0.37.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT" license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p" repository = "https://github.com/libp2p/rust-libp2p"
@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"]
futures-rustls = "0.22" futures-rustls = "0.22"
either = "1.5.3" either = "1.5.3"
futures = "0.3.1" futures = "0.3.1"
libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } libp2p-core = { version = "0.35.0", path = "../../core", default-features = false }
log = "0.4.8" log = "0.4.8"
parking_lot = "0.12.0" parking_lot = "0.12.0"
quicksink = "0.1" quicksink = "0.1"