diff --git a/core/src/either.rs b/core/src/either.rs index 8049717a878..a04029cc035 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -22,7 +22,7 @@ use crate::muxing::StreamMuxerEvent; use crate::{ muxing::StreamMuxer, transport::{ListenerId, Transport, TransportError, TransportEvent}, - Multiaddr, ProtocolName, + Multiaddr, }; use either::Either; use futures::prelude::*; @@ -121,15 +121,6 @@ pub enum EitherName { B(B), } -impl ProtocolName for EitherName { - fn protocol_name(&self) -> &[u8] { - match self { - EitherName::A(a) => a.protocol_name(), - EitherName::B(b) => b.protocol_name(), - } - } -} - impl Transport for Either where B: Transport, diff --git a/core/src/lib.rs b/core/src/lib.rs index ba531c919f2..0c96e556a3d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -127,7 +127,12 @@ pub use peer_record::PeerRecord; pub use signed_envelope::SignedEnvelope; pub use translation::address_translation; pub use transport::Transport; -pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo}; +#[allow(deprecated)] +pub use upgrade::ProtocolName; +pub use upgrade::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter, UpgradeError}; + +#[allow(deprecated)] +pub use upgrade::UpgradeInfo; #[derive(Debug, thiserror::Error)] pub struct DecodeError(String); diff --git a/core/src/upgrade.rs b/core/src/upgrade.rs index 4c46418e7a7..d8665934857 100644 --- a/core/src/upgrade.rs +++ b/core/src/upgrade.rs @@ -61,18 +61,15 @@ mod apply; mod denied; mod either; mod error; -mod from_fn; -mod map; -mod optional; mod pending; mod ready; mod select; mod transfer; use futures::future::Future; +use std::fmt; +use std::iter::FilterMap; -#[allow(deprecated)] -pub use self::from_fn::{from_fn, FromFnUpgrade}; pub use self::{ apply::{apply, apply_inbound, apply_outbound, InboundUpgradeApply, OutboundUpgradeApply}, denied::DeniedUpgrade, @@ -83,11 +80,7 @@ pub use self::{ transfer::{read_length_prefixed, read_varint, write_length_prefixed, write_varint}, }; pub use crate::Negotiated; -#[allow(deprecated)] -pub use map::{MapInboundUpgrade, MapInboundUpgradeErr, MapOutboundUpgrade, MapOutboundUpgradeErr}; pub use multistream_select::{NegotiatedComplete, NegotiationError, ProtocolError, Version}; -#[allow(deprecated)] -pub use optional::OptionalUpgrade; /// Types serving as protocol names. /// @@ -122,6 +115,7 @@ pub use optional::OptionalUpgrade; /// } /// ``` /// +#[deprecated(note = "Use the `Protocol` new-type instead.")] pub trait ProtocolName { /// The protocol name as bytes. Transmitted on the network. /// @@ -130,6 +124,7 @@ pub trait ProtocolName { fn protocol_name(&self) -> &[u8]; } +#[allow(deprecated)] impl> ProtocolName for T { fn protocol_name(&self) -> &[u8] { self.as_ref() @@ -138,6 +133,8 @@ impl> ProtocolName for T { /// Common trait for upgrades that can be applied on inbound substreams, outbound substreams, /// or both. +#[deprecated(note = "Implement `ToProtocolsIter` instead.")] +#[allow(deprecated)] pub trait UpgradeInfo { /// Opaque type representing a negotiable protocol. type Info: ProtocolName + Clone; @@ -148,8 +145,120 @@ pub trait UpgradeInfo { fn protocol_info(&self) -> Self::InfoIter; } +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct Protocol { + inner: multistream_select::Protocol, +} + +impl Protocol { + /// Construct a new protocol from a static string slice. + /// + /// # Panics + /// + /// This function panics if the protocol does not start with a forward slash: `/`. + pub const fn from_static(s: &'static str) -> Self { + Protocol { + inner: multistream_select::Protocol::from_static(s), + } + } + + /// Attempt to construct a protocol from an owned string. + /// + /// This function will fail if the protocol does not start with a forward slash: `/`. + /// Where possible, you should use [`Protocol::from_static`] instead to avoid allocations. + pub fn try_from_owned(protocol: String) -> Result { + Ok(Protocol { + inner: multistream_select::Protocol::try_from_owned(protocol) + .map_err(InvalidProtocol)?, + }) + } + + /// View the protocol as a string slice. + pub fn as_str(&self) -> &str { + self.inner.as_str() + } + + pub(crate) fn from_inner(inner: multistream_select::Protocol) -> Self { + Protocol { inner } + } + + pub(crate) fn into_inner(self) -> multistream_select::Protocol { + self.inner + } +} + +impl fmt::Display for Protocol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl PartialEq for Protocol { + fn eq(&self, other: &str) -> bool { + self.inner.as_str() == other + } +} + +#[derive(Debug)] +pub struct InvalidProtocol(multistream_select::ProtocolError); + +impl fmt::Display for InvalidProtocol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "invalid protocol") + } +} + +impl std::error::Error for InvalidProtocol { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&self.0) + } +} + +/// Each protocol upgrade must implement the [`ToProtocolsIter`] trait. +/// +/// The returned iterator should yield the protocols that the upgrade supports. +pub trait ToProtocolsIter { + type Iter: Iterator + Send; + + fn to_protocols_iter(&self) -> Self::Iter; +} + +#[allow(deprecated)] +impl ToProtocolsIter for U +where + U: UpgradeInfo + Send + 'static, + U::Info: Send + 'static, + U::InfoIter: Send + 'static, + ::IntoIter: Send + 'static, +{ + type Iter = FilterMap<::IntoIter, fn(U::Info) -> Option>; + + fn to_protocols_iter(&self) -> Self::Iter { + self.protocol_info() + .into_iter() + .filter_map(filter_non_utf8_protocols) + } +} + +#[allow(deprecated)] +fn filter_non_utf8_protocols(p: impl ProtocolName) -> Option { + let name = p.protocol_name(); + + match multistream_select::Protocol::try_from(name) { + Ok(p) => Some(Protocol::from_inner(p)), + Err(e) => { + log::warn!( + "ignoring protocol {} during upgrade because it is malformed: {e}", + String::from_utf8_lossy(name) + ); + + None + } + } +} + /// Possible upgrade on an inbound connection or substream. -pub trait InboundUpgrade: UpgradeInfo { +pub trait InboundUpgrade: ToProtocolsIter { /// Output after the upgrade has been successfully negotiated and the handshake performed. type Output; /// Possible error during the handshake. @@ -161,40 +270,11 @@ pub trait InboundUpgrade: UpgradeInfo { /// method is called to start the handshake. /// /// The `info` is the identifier of the protocol, as produced by `protocol_info`. - fn upgrade_inbound(self, socket: C, info: Self::Info) -> Self::Future; + fn upgrade_inbound(self, socket: C, selected_protocol: Protocol) -> Self::Future; } -/// Extension trait for `InboundUpgrade`. Automatically implemented on all types that implement -/// `InboundUpgrade`. -#[deprecated( - note = "Will be removed without replacement because it is not used within rust-libp2p." -)] -#[allow(deprecated)] -pub trait InboundUpgradeExt: InboundUpgrade { - /// Returns a new object that wraps around `Self` and applies a closure to the `Output`. - fn map_inbound(self, f: F) -> MapInboundUpgrade - where - Self: Sized, - F: FnOnce(Self::Output) -> T, - { - MapInboundUpgrade::new(self, f) - } - - /// Returns a new object that wraps around `Self` and applies a closure to the `Error`. - fn map_inbound_err(self, f: F) -> MapInboundUpgradeErr - where - Self: Sized, - F: FnOnce(Self::Error) -> T, - { - MapInboundUpgradeErr::new(self, f) - } -} - -#[allow(deprecated)] -impl> InboundUpgradeExt for U {} - /// Possible upgrade on an outbound connection or substream. -pub trait OutboundUpgrade: UpgradeInfo { +pub trait OutboundUpgrade: ToProtocolsIter { /// Output after the upgrade has been successfully negotiated and the handshake performed. type Output; /// Possible error during the handshake. @@ -206,34 +286,5 @@ pub trait OutboundUpgrade: UpgradeInfo { /// method is called to start the handshake. /// /// The `info` is the identifier of the protocol, as produced by `protocol_info`. - fn upgrade_outbound(self, socket: C, info: Self::Info) -> Self::Future; + fn upgrade_outbound(self, socket: C, selected_protocol: Protocol) -> Self::Future; } - -/// Extention trait for `OutboundUpgrade`. Automatically implemented on all types that implement -/// `OutboundUpgrade`. -#[deprecated( - note = "Will be removed without replacement because it is not used within rust-libp2p." -)] -#[allow(deprecated)] -pub trait OutboundUpgradeExt: OutboundUpgrade { - /// Returns a new object that wraps around `Self` and applies a closure to the `Output`. - fn map_outbound(self, f: F) -> MapOutboundUpgrade - where - Self: Sized, - F: FnOnce(Self::Output) -> T, - { - MapOutboundUpgrade::new(self, f) - } - - /// Returns a new object that wraps around `Self` and applies a closure to the `Error`. - fn map_outbound_err(self, f: F) -> MapOutboundUpgradeErr - where - Self: Sized, - F: FnOnce(Self::Error) -> T, - { - MapOutboundUpgradeErr::new(self, f) - } -} - -#[allow(deprecated)] -impl> OutboundUpgradeExt for U {} diff --git a/core/src/upgrade/apply.rs b/core/src/upgrade/apply.rs index 0b4b4d6b992..5e2f310939f 100644 --- a/core/src/upgrade/apply.rs +++ b/core/src/upgrade/apply.rs @@ -18,16 +18,14 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError}; +use crate::upgrade::{InboundUpgrade, OutboundUpgrade, Protocol, UpgradeError}; use crate::{connection::ConnectedPoint, Negotiated}; use futures::{future::Either, prelude::*}; use log::debug; use multistream_select::{self, DialerSelectFuture, ListenerSelectFuture}; -use std::{iter, mem, pin::Pin, task::Context, task::Poll}; +use std::{mem, pin::Pin, task::Context, task::Poll}; pub(crate) use multistream_select::Version; -use smallvec::SmallVec; -use std::fmt; // TODO: Still needed? /// Applies an upgrade to the inbound and outbound direction of a connection or substream. @@ -55,14 +53,12 @@ where C: AsyncRead + AsyncWrite + Unpin, U: InboundUpgrade>, { - let iter = up - .protocol_info() - .into_iter() - .map(NameWrap as fn(_) -> NameWrap<_>); - let future = multistream_select::listener_select_proto(conn, iter); InboundUpgradeApply { inner: InboundUpgradeApplyState::Init { - future, + future: multistream_select::listener_select_proto( + conn, + up.to_protocols_iter().map(Protocol::into_inner), + ), upgrade: up, }, } @@ -74,14 +70,13 @@ where C: AsyncRead + AsyncWrite + Unpin, U: OutboundUpgrade>, { - let iter = up - .protocol_info() - .into_iter() - .map(NameWrap as fn(_) -> NameWrap<_>); - let future = multistream_select::dialer_select_proto(conn, iter, v); OutboundUpgradeApply { inner: OutboundUpgradeApplyState::Init { - future, + future: multistream_select::dialer_select_proto( + conn, + up.to_protocols_iter().map(Protocol::into_inner), + v, + ), upgrade: up, }, } @@ -96,18 +91,19 @@ where inner: InboundUpgradeApplyState, } +#[allow(clippy::large_enum_variant)] enum InboundUpgradeApplyState where C: AsyncRead + AsyncWrite + Unpin, U: InboundUpgrade>, { Init { - future: ListenerSelectFuture>, + future: ListenerSelectFuture, upgrade: U, }, Upgrade { future: Pin>, - name: SmallVec<[u8; 32]>, + name: multistream_select::Protocol, }, Undefined, } @@ -133,18 +129,21 @@ where mut future, upgrade, } => { - let (info, io) = match Future::poll(Pin::new(&mut future), cx)? { + let (selected_protocol, io) = match Future::poll(Pin::new(&mut future), cx)? { Poll::Ready(x) => x, Poll::Pending => { self.inner = InboundUpgradeApplyState::Init { future, upgrade }; return Poll::Pending; } }; - let name = SmallVec::from_slice(info.protocol_name()); - self.inner = InboundUpgradeApplyState::Upgrade { - future: Box::pin(upgrade.upgrade_inbound(io, info.0)), - name, - }; + self.inner = + InboundUpgradeApplyState::Upgrade { + future: Box::pin(upgrade.upgrade_inbound( + io, + Protocol::from_inner(selected_protocol.clone()), + )), + name: selected_protocol, + }; } InboundUpgradeApplyState::Upgrade { mut future, name } => { match Future::poll(Pin::new(&mut future), cx) { @@ -153,14 +152,11 @@ where return Poll::Pending; } Poll::Ready(Ok(x)) => { - log::trace!("Upgraded inbound stream to {}", DisplayProtocolName(name)); + log::trace!("Upgraded inbound stream to {name}"); return Poll::Ready(Ok(x)); } Poll::Ready(Err(e)) => { - debug!( - "Failed to upgrade inbound stream to {}", - DisplayProtocolName(name) - ); + debug!("Failed to upgrade inbound stream to {name}"); return Poll::Ready(Err(UpgradeError::Apply(e))); } } @@ -188,12 +184,15 @@ where U: OutboundUpgrade>, { Init { - future: DialerSelectFuture::IntoIter>>, + future: DialerSelectFuture< + C, + std::iter::Map multistream_select::Protocol>, + >, upgrade: U, }, Upgrade { future: Pin>, - name: SmallVec<[u8; 32]>, + name: multistream_select::Protocol, }, Undefined, } @@ -219,17 +218,20 @@ where mut future, upgrade, } => { - let (info, connection) = match Future::poll(Pin::new(&mut future), cx)? { - Poll::Ready(x) => x, - Poll::Pending => { - self.inner = OutboundUpgradeApplyState::Init { future, upgrade }; - return Poll::Pending; - } - }; - let name = SmallVec::from_slice(info.protocol_name()); + let (selected_protocol, connection) = + match Future::poll(Pin::new(&mut future), cx)? { + Poll::Ready(x) => x, + Poll::Pending => { + self.inner = OutboundUpgradeApplyState::Init { future, upgrade }; + return Poll::Pending; + } + }; self.inner = OutboundUpgradeApplyState::Upgrade { - future: Box::pin(upgrade.upgrade_outbound(connection, info.0)), - name, + future: Box::pin(upgrade.upgrade_outbound( + connection, + Protocol::from_inner(selected_protocol.clone()), + )), + name: selected_protocol, }; } OutboundUpgradeApplyState::Upgrade { mut future, name } => { @@ -239,17 +241,11 @@ where return Poll::Pending; } Poll::Ready(Ok(x)) => { - log::trace!( - "Upgraded outbound stream to {}", - DisplayProtocolName(name) - ); + log::trace!("Upgraded outbound stream to {name}"); return Poll::Ready(Ok(x)); } Poll::Ready(Err(e)) => { - debug!( - "Failed to upgrade outbound stream to {}", - DisplayProtocolName(name) - ); + debug!("Failed to upgrade outbound stream to {name}"); return Poll::Ready(Err(UpgradeError::Apply(e))); } } @@ -261,51 +257,3 @@ where } } } - -type NameWrapIter = iter::Map::Item) -> NameWrap<::Item>>; - -/// Wrapper type to expose an `AsRef<[u8]>` impl for all types implementing `ProtocolName`. -#[derive(Clone)] -struct NameWrap(N); - -impl AsRef<[u8]> for NameWrap { - fn as_ref(&self) -> &[u8] { - self.0.protocol_name() - } -} - -/// Wrapper for printing a [`ProtocolName`] that is expected to be mostly ASCII -pub(crate) struct DisplayProtocolName(pub(crate) N); - -impl fmt::Display for DisplayProtocolName { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use fmt::Write; - for byte in self.0.protocol_name() { - if (b' '..=b'~').contains(byte) { - f.write_char(char::from(*byte))?; - } else { - write!(f, "<{byte:02X}>")?; - } - } - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn display_protocol_name() { - assert_eq!(DisplayProtocolName(b"/hello/1.0").to_string(), "/hello/1.0"); - assert_eq!(DisplayProtocolName("/hellö/").to_string(), "/hell/"); - assert_eq!( - DisplayProtocolName((0u8..=255).collect::>()).to_string(), - (0..32) - .map(|c| format!("<{c:02X}>")) - .chain((32..127).map(|c| format!("{}", char::from_u32(c).unwrap()))) - .chain((127..256).map(|c| format!("<{c:02X}>"))) - .collect::() - ); - } -} diff --git a/core/src/upgrade/denied.rs b/core/src/upgrade/denied.rs index 93438e0bea8..ca3a0db8f24 100644 --- a/core/src/upgrade/denied.rs +++ b/core/src/upgrade/denied.rs @@ -18,7 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use crate::upgrade::{InboundUpgrade, OutboundUpgrade, Protocol, ToProtocolsIter}; use futures::future; use std::iter; use void::Void; @@ -28,11 +28,10 @@ use void::Void; #[derive(Debug, Copy, Clone)] pub struct DeniedUpgrade; -impl UpgradeInfo for DeniedUpgrade { - type Info = &'static [u8]; - type InfoIter = iter::Empty; +impl ToProtocolsIter for DeniedUpgrade { + type Iter = iter::Empty; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::empty() } } @@ -42,7 +41,7 @@ impl InboundUpgrade for DeniedUpgrade { type Error = Void; type Future = future::Pending>; - fn upgrade_inbound(self, _: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, _: C, _: Protocol) -> Self::Future { future::pending() } } @@ -52,7 +51,7 @@ impl OutboundUpgrade for DeniedUpgrade { type Error = Void; type Future = future::Pending>; - fn upgrade_outbound(self, _: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, _: C, _: Protocol) -> Self::Future { future::pending() } } diff --git a/core/src/upgrade/either.rs b/core/src/upgrade/either.rs index 563e7651c07..31b8d1d10aa 100644 --- a/core/src/upgrade/either.rs +++ b/core/src/upgrade/either.rs @@ -18,28 +18,26 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +use crate::upgrade::Protocol; +use crate::upgrade::ToProtocolsIter; use crate::{ - either::{EitherFuture, EitherName}, - upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}, + either::EitherFuture, + upgrade::{InboundUpgrade, OutboundUpgrade}, }; use either::Either; use futures::future; -impl UpgradeInfo for Either +impl ToProtocolsIter for Either where - A: UpgradeInfo, - B: UpgradeInfo, + A: ToProtocolsIter, + B: ToProtocolsIter, { - type Info = EitherName; - type InfoIter = EitherIter< - ::IntoIter, - ::IntoIter, - >; + type Iter = Either; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { match self { - Either::Left(a) => EitherIter::A(a.protocol_info().into_iter()), - Either::Right(b) => EitherIter::B(b.protocol_info().into_iter()), + Either::Left(a) => Either::Left(a.to_protocols_iter()), + Either::Right(b) => Either::Right(b.to_protocols_iter()), } } } @@ -53,15 +51,10 @@ where type Error = Either; type Future = EitherFuture; - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - match (self, info) { - (Either::Left(a), EitherName::A(info)) => { - EitherFuture::First(a.upgrade_inbound(sock, info)) - } - (Either::Right(b), EitherName::B(info)) => { - EitherFuture::Second(b.upgrade_inbound(sock, info)) - } - _ => panic!("Invalid invocation of EitherUpgrade::upgrade_inbound"), + fn upgrade_inbound(self, sock: C, selected_protocol: Protocol) -> Self::Future { + match self { + Either::Left(a) => EitherFuture::First(a.upgrade_inbound(sock, selected_protocol)), + Either::Right(b) => EitherFuture::Second(b.upgrade_inbound(sock, selected_protocol)), } } } @@ -75,44 +68,10 @@ where type Error = Either; type Future = EitherFuture; - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - match (self, info) { - (Either::Left(a), EitherName::A(info)) => { - EitherFuture::First(a.upgrade_outbound(sock, info)) - } - (Either::Right(b), EitherName::B(info)) => { - EitherFuture::Second(b.upgrade_outbound(sock, info)) - } - _ => panic!("Invalid invocation of EitherUpgrade::upgrade_outbound"), - } - } -} - -/// A type to represent two possible `Iterator` types. -#[derive(Debug, Clone)] -pub enum EitherIter { - A(A), - B(B), -} - -impl Iterator for EitherIter -where - A: Iterator, - B: Iterator, -{ - type Item = EitherName; - - fn next(&mut self) -> Option { - match self { - EitherIter::A(a) => a.next().map(EitherName::A), - EitherIter::B(b) => b.next().map(EitherName::B), - } - } - - fn size_hint(&self) -> (usize, Option) { + fn upgrade_outbound(self, sock: C, selected_protocol: Protocol) -> Self::Future { match self { - EitherIter::A(a) => a.size_hint(), - EitherIter::B(b) => b.size_hint(), + Either::Left(a) => EitherFuture::First(a.upgrade_outbound(sock, selected_protocol)), + Either::Right(b) => EitherFuture::Second(b.upgrade_outbound(sock, selected_protocol)), } } } diff --git a/core/src/upgrade/from_fn.rs b/core/src/upgrade/from_fn.rs deleted file mode 100644 index d6da7b6ed5a..00000000000 --- a/core/src/upgrade/from_fn.rs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2020 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 crate::{ - upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo}, - Endpoint, -}; - -use futures::prelude::*; -use std::iter; - -/// Initializes a new [`FromFnUpgrade`]. -/// -/// # Example -/// -/// ``` -/// # use libp2p_core::transport::{Transport, MemoryTransport, memory::Channel}; -/// # use libp2p_core::{upgrade, Negotiated}; -/// # use std::io; -/// # use futures::AsyncWriteExt; -/// # #[allow(deprecated)] -/// let _transport = MemoryTransport::default() -/// .and_then(move |out, cp| { -/// upgrade::apply(out, upgrade::from_fn("/foo/1", move |mut sock: Negotiated>>, endpoint| async move { -/// if endpoint.is_dialer() { -/// upgrade::write_length_prefixed(&mut sock, "some handshake data").await?; -/// sock.close().await?; -/// } else { -/// let handshake_data = upgrade::read_length_prefixed(&mut sock, 1024).await?; -/// if handshake_data != b"some handshake data" { -/// return Err(io::Error::new(io::ErrorKind::Other, "bad handshake")); -/// } -/// } -/// Ok(sock) -/// }), cp, upgrade::Version::V1) -/// }); -/// ``` -/// -#[deprecated( - note = "`from_fn` upgrade will be removed without replacement as it is not used within `rust-libp2p`." -)] -#[allow(deprecated)] -pub fn from_fn(protocol_name: P, fun: F) -> FromFnUpgrade -where - // Note: these bounds are there in order to help the compiler infer types - P: ProtocolName + Clone, - F: FnOnce(C, Endpoint) -> Fut, - Fut: Future>, -{ - FromFnUpgrade { protocol_name, fun } -} - -/// Implements the `UpgradeInfo`, `InboundUpgrade` and `OutboundUpgrade` traits. -/// -/// The upgrade consists in calling the function passed when creating this struct. -#[derive(Debug, Clone)] -#[deprecated( - note = "`from_fn` upgrade will be removed without replacement as it is not used within `rust-libp2p`." -)] -pub struct FromFnUpgrade { - protocol_name: P, - fun: F, -} - -#[allow(deprecated)] -impl UpgradeInfo for FromFnUpgrade -where - P: ProtocolName + Clone, -{ - type Info = P; - type InfoIter = iter::Once

; - - fn protocol_info(&self) -> Self::InfoIter { - iter::once(self.protocol_name.clone()) - } -} - -#[allow(deprecated)] -impl InboundUpgrade for FromFnUpgrade -where - P: ProtocolName + Clone, - F: FnOnce(C, Endpoint) -> Fut, - Fut: Future>, -{ - type Output = Out; - type Error = Err; - type Future = Fut; - - fn upgrade_inbound(self, sock: C, _: Self::Info) -> Self::Future { - (self.fun)(sock, Endpoint::Listener) - } -} - -#[allow(deprecated)] -impl OutboundUpgrade for FromFnUpgrade -where - P: ProtocolName + Clone, - F: FnOnce(C, Endpoint) -> Fut, - Fut: Future>, -{ - type Output = Out; - type Error = Err; - type Future = Fut; - - fn upgrade_outbound(self, sock: C, _: Self::Info) -> Self::Future { - (self.fun)(sock, Endpoint::Dialer) - } -} diff --git a/core/src/upgrade/map.rs b/core/src/upgrade/map.rs deleted file mode 100644 index 4287665c88f..00000000000 --- a/core/src/upgrade/map.rs +++ /dev/null @@ -1,303 +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. - -#![allow(deprecated)] - -use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; -use futures::prelude::*; -use std::{pin::Pin, task::Context, task::Poll}; - -/// Wraps around an upgrade and applies a closure to the output. -#[derive(Debug, Clone)] -#[deprecated(note = "Deprecated without replacement because it is not used within rust-libp2p.")] -pub struct MapInboundUpgrade { - upgrade: U, - fun: F, -} - -impl MapInboundUpgrade { - pub fn new(upgrade: U, fun: F) -> Self { - MapInboundUpgrade { upgrade, fun } - } -} - -impl UpgradeInfo for MapInboundUpgrade -where - U: UpgradeInfo, -{ - type Info = U::Info; - type InfoIter = U::InfoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.upgrade.protocol_info() - } -} - -impl InboundUpgrade for MapInboundUpgrade -where - U: InboundUpgrade, - F: FnOnce(U::Output) -> T, -{ - type Output = T; - type Error = U::Error; - type Future = MapFuture; - - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - MapFuture { - inner: self.upgrade.upgrade_inbound(sock, info), - map: Some(self.fun), - } - } -} - -impl OutboundUpgrade for MapInboundUpgrade -where - U: OutboundUpgrade, -{ - type Output = U::Output; - type Error = U::Error; - type Future = U::Future; - - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - self.upgrade.upgrade_outbound(sock, info) - } -} - -/// Wraps around an upgrade and applies a closure to the output. -#[derive(Debug, Clone)] -#[deprecated(note = "Deprecated without replacement because it is not used within rust-libp2p.")] -pub struct MapOutboundUpgrade { - upgrade: U, - fun: F, -} - -impl MapOutboundUpgrade { - pub fn new(upgrade: U, fun: F) -> Self { - MapOutboundUpgrade { upgrade, fun } - } -} - -impl UpgradeInfo for MapOutboundUpgrade -where - U: UpgradeInfo, -{ - type Info = U::Info; - type InfoIter = U::InfoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.upgrade.protocol_info() - } -} - -impl InboundUpgrade for MapOutboundUpgrade -where - U: InboundUpgrade, -{ - type Output = U::Output; - type Error = U::Error; - type Future = U::Future; - - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - self.upgrade.upgrade_inbound(sock, info) - } -} - -impl OutboundUpgrade for MapOutboundUpgrade -where - U: OutboundUpgrade, - F: FnOnce(U::Output) -> T, -{ - type Output = T; - type Error = U::Error; - type Future = MapFuture; - - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - MapFuture { - inner: self.upgrade.upgrade_outbound(sock, info), - map: Some(self.fun), - } - } -} - -/// Wraps around an upgrade and applies a closure to the error. -#[derive(Debug, Clone)] -#[deprecated(note = "Deprecated without replacement because it is not used within rust-libp2p.")] -pub struct MapInboundUpgradeErr { - upgrade: U, - fun: F, -} - -impl MapInboundUpgradeErr { - pub fn new(upgrade: U, fun: F) -> Self { - MapInboundUpgradeErr { upgrade, fun } - } -} - -impl UpgradeInfo for MapInboundUpgradeErr -where - U: UpgradeInfo, -{ - type Info = U::Info; - type InfoIter = U::InfoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.upgrade.protocol_info() - } -} - -impl InboundUpgrade for MapInboundUpgradeErr -where - U: InboundUpgrade, - F: FnOnce(U::Error) -> T, -{ - type Output = U::Output; - type Error = T; - type Future = MapErrFuture; - - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - MapErrFuture { - fut: self.upgrade.upgrade_inbound(sock, info), - fun: Some(self.fun), - } - } -} - -impl OutboundUpgrade for MapInboundUpgradeErr -where - U: OutboundUpgrade, -{ - type Output = U::Output; - type Error = U::Error; - type Future = U::Future; - - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - self.upgrade.upgrade_outbound(sock, info) - } -} - -/// Wraps around an upgrade and applies a closure to the error. -#[derive(Debug, Clone)] -#[deprecated(note = "Deprecated without replacement because it is not used within rust-libp2p.")] -pub struct MapOutboundUpgradeErr { - upgrade: U, - fun: F, -} - -impl MapOutboundUpgradeErr { - pub fn new(upgrade: U, fun: F) -> Self { - MapOutboundUpgradeErr { upgrade, fun } - } -} - -impl UpgradeInfo for MapOutboundUpgradeErr -where - U: UpgradeInfo, -{ - type Info = U::Info; - type InfoIter = U::InfoIter; - - fn protocol_info(&self) -> Self::InfoIter { - self.upgrade.protocol_info() - } -} - -impl OutboundUpgrade for MapOutboundUpgradeErr -where - U: OutboundUpgrade, - F: FnOnce(U::Error) -> T, -{ - type Output = U::Output; - type Error = T; - type Future = MapErrFuture; - - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - MapErrFuture { - fut: self.upgrade.upgrade_outbound(sock, info), - fun: Some(self.fun), - } - } -} - -impl InboundUpgrade for MapOutboundUpgradeErr -where - U: InboundUpgrade, -{ - type Output = U::Output; - type Error = U::Error; - type Future = U::Future; - - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - self.upgrade.upgrade_inbound(sock, info) - } -} - -#[pin_project::pin_project] -pub struct MapFuture { - #[pin] - inner: TInnerFut, - map: Option, -} - -impl Future for MapFuture -where - TInnerFut: TryFuture, - TMap: FnOnce(TIn) -> TOut, -{ - type Output = Result; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.project(); - let item = match TryFuture::try_poll(this.inner, cx) { - Poll::Ready(Ok(v)) => v, - Poll::Ready(Err(err)) => return Poll::Ready(Err(err)), - Poll::Pending => return Poll::Pending, - }; - - let map = this.map.take().expect("Future has already finished"); - Poll::Ready(Ok(map(item))) - } -} - -#[pin_project::pin_project] -pub struct MapErrFuture { - #[pin] - fut: T, - fun: Option, -} - -impl Future for MapErrFuture -where - T: TryFuture, - F: FnOnce(E) -> A, -{ - type Output = Result; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.project(); - match TryFuture::try_poll(this.fut, cx) { - Poll::Pending => Poll::Pending, - Poll::Ready(Ok(x)) => Poll::Ready(Ok(x)), - Poll::Ready(Err(e)) => { - let f = this.fun.take().expect("Future has not resolved yet"); - Poll::Ready(Err(f(e))) - } - } - } -} diff --git a/core/src/upgrade/optional.rs b/core/src/upgrade/optional.rs deleted file mode 100644 index 40303db2bdf..00000000000 --- a/core/src/upgrade/optional.rs +++ /dev/null @@ -1,120 +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. - -#![allow(deprecated)] - -use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; - -/// Upgrade that can be disabled at runtime. -/// -/// Wraps around an `Option` and makes it available or not depending on whether it contains or -/// not an upgrade. -#[derive(Debug, Clone)] -#[deprecated( - note = "Will be removed without replacement because it is not used within rust-libp2p." -)] -pub struct OptionalUpgrade(Option); - -impl OptionalUpgrade { - /// Creates an enabled `OptionalUpgrade`. - pub fn some(inner: T) -> Self { - OptionalUpgrade(Some(inner)) - } - - /// Creates a disabled `OptionalUpgrade`. - pub fn none() -> Self { - OptionalUpgrade(None) - } -} - -impl UpgradeInfo for OptionalUpgrade -where - T: UpgradeInfo, -{ - type Info = T::Info; - type InfoIter = Iter<::IntoIter>; - - fn protocol_info(&self) -> Self::InfoIter { - Iter(self.0.as_ref().map(|p| p.protocol_info().into_iter())) - } -} - -impl InboundUpgrade for OptionalUpgrade -where - T: InboundUpgrade, -{ - type Output = T::Output; - type Error = T::Error; - type Future = T::Future; - - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - if let Some(inner) = self.0 { - inner.upgrade_inbound(sock, info) - } else { - panic!("Bad API usage; a protocol has been negotiated while this struct contains None") - } - } -} - -impl OutboundUpgrade for OptionalUpgrade -where - T: OutboundUpgrade, -{ - type Output = T::Output; - type Error = T::Error; - type Future = T::Future; - - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - if let Some(inner) = self.0 { - inner.upgrade_outbound(sock, info) - } else { - panic!("Bad API usage; a protocol has been negotiated while this struct contains None") - } - } -} - -/// Iterator that flattens an `Option` where `T` is an iterator. -#[derive(Debug, Clone)] -pub struct Iter(Option); - -impl Iterator for Iter -where - T: Iterator, -{ - type Item = T::Item; - - fn next(&mut self) -> Option { - if let Some(iter) = self.0.as_mut() { - iter.next() - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option) { - if let Some(iter) = self.0.as_ref() { - iter.size_hint() - } else { - (0, Some(0)) - } - } -} - -impl ExactSizeIterator for Iter where T: ExactSizeIterator {} diff --git a/core/src/upgrade/pending.rs b/core/src/upgrade/pending.rs index 15d3c31df48..bc7e1774cf8 100644 --- a/core/src/upgrade/pending.rs +++ b/core/src/upgrade/pending.rs @@ -19,58 +19,50 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo}; +use crate::upgrade::Protocol; +use crate::upgrade::{InboundUpgrade, OutboundUpgrade}; +use crate::ToProtocolsIter; use futures::future; use std::iter; use void::Void; /// Implementation of [`UpgradeInfo`], [`InboundUpgrade`] and [`OutboundUpgrade`] that always /// returns a pending upgrade. -#[derive(Debug, Copy, Clone)] -pub struct PendingUpgrade

{ - protocol_name: P, +#[derive(Debug, Clone)] +pub struct PendingUpgrade { + protocol_name: Protocol, } -impl

PendingUpgrade

{ - pub fn new(protocol_name: P) -> Self { +impl PendingUpgrade { + pub fn new(protocol_name: Protocol) -> Self { Self { protocol_name } } } -impl

UpgradeInfo for PendingUpgrade

-where - P: ProtocolName + Clone, -{ - type Info = P; - type InfoIter = iter::Once

; +impl ToProtocolsIter for PendingUpgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(self.protocol_name.clone()) } } -impl InboundUpgrade for PendingUpgrade

-where - P: ProtocolName + Clone, -{ +impl InboundUpgrade for PendingUpgrade { type Output = Void; type Error = Void; type Future = future::Pending>; - fn upgrade_inbound(self, _: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, _: C, _: Protocol) -> Self::Future { future::pending() } } -impl OutboundUpgrade for PendingUpgrade

-where - P: ProtocolName + Clone, -{ +impl OutboundUpgrade for PendingUpgrade { type Output = Void; type Error = Void; type Future = future::Pending>; - fn upgrade_outbound(self, _: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, _: C, _: Protocol) -> Self::Future { future::pending() } } diff --git a/core/src/upgrade/ready.rs b/core/src/upgrade/ready.rs index 16a9b2867f4..64794c12294 100644 --- a/core/src/upgrade/ready.rs +++ b/core/src/upgrade/ready.rs @@ -19,57 +19,49 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo}; +use crate::upgrade::Protocol; +use crate::upgrade::{InboundUpgrade, OutboundUpgrade}; +use crate::ToProtocolsIter; use futures::future; use std::iter; use void::Void; /// Implementation of [`UpgradeInfo`], [`InboundUpgrade`] and [`OutboundUpgrade`] that directly yields the substream. -#[derive(Debug, Copy, Clone)] -pub struct ReadyUpgrade

{ - protocol_name: P, +#[derive(Debug, Clone)] +pub struct ReadyUpgrade { + protocol_name: Protocol, } -impl

ReadyUpgrade

{ - pub fn new(protocol_name: P) -> Self { +impl ReadyUpgrade { + pub fn new(protocol_name: Protocol) -> Self { Self { protocol_name } } } -impl

UpgradeInfo for ReadyUpgrade

-where - P: ProtocolName + Clone, -{ - type Info = P; - type InfoIter = iter::Once

; +impl ToProtocolsIter for ReadyUpgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(self.protocol_name.clone()) } } -impl InboundUpgrade for ReadyUpgrade

-where - P: ProtocolName + Clone, -{ +impl InboundUpgrade for ReadyUpgrade { type Output = C; type Error = Void; type Future = future::Ready>; - fn upgrade_inbound(self, stream: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, stream: C, _: Protocol) -> Self::Future { future::ready(Ok(stream)) } } -impl OutboundUpgrade for ReadyUpgrade

-where - P: ProtocolName + Clone, -{ +impl OutboundUpgrade for ReadyUpgrade { type Output = C; type Error = Void; type Future = future::Ready>; - fn upgrade_outbound(self, stream: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, stream: C, _: Protocol) -> Self::Future { future::ready(Ok(stream)) } } diff --git a/core/src/upgrade/select.rs b/core/src/upgrade/select.rs index 1d5ab9abe53..e1d218233c7 100644 --- a/core/src/upgrade/select.rs +++ b/core/src/upgrade/select.rs @@ -19,10 +19,8 @@ // DEALINGS IN THE SOFTWARE. use crate::either::EitherFuture; -use crate::{ - either::EitherName, - upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}, -}; +use crate::upgrade::{InboundUpgrade, OutboundUpgrade}; +use crate::upgrade::{Protocol, ToProtocolsIter}; use either::Either; use futures::future; @@ -42,22 +40,15 @@ impl SelectUpgrade { } } -impl UpgradeInfo for SelectUpgrade +impl ToProtocolsIter for SelectUpgrade where - A: UpgradeInfo, - B: UpgradeInfo, + A: ToProtocolsIter, + B: ToProtocolsIter, { - type Info = EitherName; - type InfoIter = InfoIterChain< - ::IntoIter, - ::IntoIter, - >; + type Iter = std::iter::Chain; - fn protocol_info(&self) -> Self::InfoIter { - InfoIterChain( - self.0.protocol_info().into_iter(), - self.1.protocol_info().into_iter(), - ) + fn to_protocols_iter(&self) -> Self::Iter { + self.0.to_protocols_iter().chain(self.1.to_protocols_iter()) } } @@ -70,11 +61,16 @@ where type Error = Either; type Future = EitherFuture; - fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future { - match info { - EitherName::A(info) => EitherFuture::First(self.0.upgrade_inbound(sock, info)), - EitherName::B(info) => EitherFuture::Second(self.1.upgrade_inbound(sock, info)), + fn upgrade_inbound(self, sock: C, selected_protocol: Protocol) -> Self::Future { + if self.0.to_protocols_iter().any(|p| p == selected_protocol) { + return EitherFuture::First(self.0.upgrade_inbound(sock, selected_protocol)); } + + if self.1.to_protocols_iter().any(|p| p == selected_protocol) { + return EitherFuture::Second(self.1.upgrade_inbound(sock, selected_protocol)); + } + + panic!("selected protocol is not supported by either upgrade") } } @@ -87,39 +83,15 @@ where type Error = Either; type Future = EitherFuture; - fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future { - match info { - EitherName::A(info) => EitherFuture::First(self.0.upgrade_outbound(sock, info)), - EitherName::B(info) => EitherFuture::Second(self.1.upgrade_outbound(sock, info)), + fn upgrade_outbound(self, sock: C, selected_protocol: Protocol) -> Self::Future { + if self.0.to_protocols_iter().any(|p| p == selected_protocol) { + return EitherFuture::First(self.0.upgrade_outbound(sock, selected_protocol)); } - } -} - -/// Iterator that combines the protocol names of twp upgrades. -#[derive(Debug, Clone)] -pub struct InfoIterChain(A, B); - -impl Iterator for InfoIterChain -where - A: Iterator, - B: Iterator, -{ - type Item = EitherName; - fn next(&mut self) -> Option { - if let Some(info) = self.0.next() { - return Some(EitherName::A(info)); - } - if let Some(info) = self.1.next() { - return Some(EitherName::B(info)); + if self.1.to_protocols_iter().any(|p| p == selected_protocol) { + return EitherFuture::Second(self.1.upgrade_outbound(sock, selected_protocol)); } - None - } - fn size_hint(&self) -> (usize, Option) { - let (min1, max1) = self.0.size_hint(); - let (min2, max2) = self.1.size_hint(); - let max = max1.and_then(move |m1| max2.and_then(move |m2| m1.checked_add(m2))); - (min1.saturating_add(min2), max) + panic!("selected protocol is not supported by either upgrade") } } diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs index e2c44f9f0d4..e7274f500a1 100644 --- a/core/tests/transport_upgrade.rs +++ b/core/tests/transport_upgrade.rs @@ -20,23 +20,23 @@ use futures::prelude::*; use libp2p_core::transport::{MemoryTransport, Transport}; -use libp2p_core::upgrade::{self, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::{self, InboundUpgrade, OutboundUpgrade}; +use libp2p_core::ToProtocolsIter; use libp2p_identity as identity; use libp2p_mplex::MplexConfig; use libp2p_noise as noise; use multiaddr::{Multiaddr, Protocol}; use rand::random; -use std::{io, pin::Pin}; +use std::{io, iter, pin::Pin}; #[derive(Clone)] struct HelloUpgrade {} -impl UpgradeInfo for HelloUpgrade { - type Info = &'static str; - type InfoIter = std::iter::Once; +impl ToProtocolsIter for HelloUpgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - std::iter::once("/hello/1") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(upgrade::Protocol::from_static("/hello/1")) } } @@ -48,7 +48,7 @@ where type Error = io::Error; type Future = Pin> + Send>>; - fn upgrade_inbound(self, mut socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, mut socket: C, _: upgrade::Protocol) -> Self::Future { Box::pin(async move { let mut buf = [0u8; 5]; socket.read_exact(&mut buf).await.unwrap(); @@ -66,7 +66,7 @@ where type Error = io::Error; type Future = Pin> + Send>>; - fn upgrade_outbound(self, mut socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, mut socket: C, _: upgrade::Protocol) -> Self::Future { Box::pin(async move { socket.write_all(b"hello").await.unwrap(); socket.flush().await.unwrap(); diff --git a/examples/file-sharing/src/network.rs b/examples/file-sharing/src/network.rs index 62496172e4a..1f20ad19890 100644 --- a/examples/file-sharing/src/network.rs +++ b/examples/file-sharing/src/network.rs @@ -6,7 +6,7 @@ use futures::prelude::*; use libp2p::{ core::{ - upgrade::{read_length_prefixed, write_length_prefixed, ProtocolName}, + upgrade::{read_length_prefixed, write_length_prefixed}, Multiaddr, }, identity, @@ -20,7 +20,7 @@ use libp2p::{ tcp, yamux, PeerId, Transport, }; -use libp2p::core::upgrade::Version; +use libp2p::core::upgrade; use std::collections::{hash_map, HashMap, HashSet}; use std::error::Error; use std::iter; @@ -48,7 +48,7 @@ pub(crate) async fn new( let peer_id = id_keys.public().to_peer_id(); let transport = tcp::async_io::Transport::default() - .upgrade(Version::V1Lazy) + .upgrade(upgrade::Version::V1Lazy) .authenticate(noise::NoiseAuthenticated::xx(&id_keys)?) .multiplex(yamux::YamuxConfig::default()) .boxed(); @@ -61,7 +61,7 @@ pub(crate) async fn new( kademlia: Kademlia::new(peer_id, MemoryStore::new(peer_id)), request_response: request_response::Behaviour::new( FileExchangeCodec(), - iter::once((FileExchangeProtocol(), ProtocolSupport::Full)), + iter::once((FILE_EXCHANGE_PROTOCOL, ProtocolSupport::Full)), Default::default(), ), }, @@ -468,29 +468,23 @@ pub(crate) enum Event { // Simple file exchange protocol -#[derive(Debug, Clone)] -struct FileExchangeProtocol(); +const FILE_EXCHANGE_PROTOCOL: upgrade::Protocol = + upgrade::Protocol::from_static("/file-exchange/1"); + #[derive(Clone)] struct FileExchangeCodec(); #[derive(Debug, Clone, PartialEq, Eq)] struct FileRequest(String); #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct FileResponse(Vec); -impl ProtocolName for FileExchangeProtocol { - fn protocol_name(&self) -> &[u8] { - "/file-exchange/1".as_bytes() - } -} - #[async_trait] impl request_response::Codec for FileExchangeCodec { - type Protocol = FileExchangeProtocol; type Request = FileRequest; type Response = FileResponse; async fn read_request( &mut self, - _: &FileExchangeProtocol, + _: &upgrade::Protocol, io: &mut T, ) -> io::Result where @@ -507,7 +501,7 @@ impl request_response::Codec for FileExchangeCodec { async fn read_response( &mut self, - _: &FileExchangeProtocol, + _: &upgrade::Protocol, io: &mut T, ) -> io::Result where @@ -524,7 +518,7 @@ impl request_response::Codec for FileExchangeCodec { async fn write_request( &mut self, - _: &FileExchangeProtocol, + _: &upgrade::Protocol, io: &mut T, FileRequest(data): FileRequest, ) -> io::Result<()> @@ -539,7 +533,7 @@ impl request_response::Codec for FileExchangeCodec { async fn write_response( &mut self, - _: &FileExchangeProtocol, + _: &upgrade::Protocol, io: &mut T, FileResponse(data): FileResponse, ) -> io::Result<()> diff --git a/libp2p/src/lib.rs b/libp2p/src/lib.rs index 79acd4249b8..edb988b71c9 100644 --- a/libp2p/src/lib.rs +++ b/libp2p/src/lib.rs @@ -167,8 +167,6 @@ pub mod bandwidth; #[cfg(doc)] pub mod tutorials; -#[allow(deprecated)] -pub use self::core::upgrade::{InboundUpgradeExt, OutboundUpgradeExt}; pub use self::core::{ transport::TransportError, upgrade::{InboundUpgrade, OutboundUpgrade}, diff --git a/misc/metrics/src/identify.rs b/misc/metrics/src/identify.rs index 91f7d78722d..42de62abbfa 100644 --- a/misc/metrics/src/identify.rs +++ b/misc/metrics/src/identify.rs @@ -134,12 +134,11 @@ impl super::Recorder for Metrics { } libp2p_identify::Event::Received { peer_id, info, .. } => { { - let mut protocols: Vec = info + let mut protocols = info .protocols .iter() .filter(|p| { - let allowed_protocols: &[&[u8]] = &[ - #[cfg(feature = "dcutr")] + let allowed_protocols = [ libp2p_dcutr::PROTOCOL_NAME, // #[cfg(feature = "gossipsub")] // #[cfg(not(target_os = "unknown"))] @@ -156,10 +155,10 @@ impl super::Recorder for Metrics { libp2p_relay::HOP_PROTOCOL_NAME, ]; - allowed_protocols.contains(&p.as_bytes()) + allowed_protocols.contains(p) }) - .cloned() - .collect(); + .map(|p| p.to_string()) + .collect::>(); // Signal via an additional label value that one or more // protocols of the remote peer have not been recognized. diff --git a/misc/multistream-select/src/dialer_select.rs b/misc/multistream-select/src/dialer_select.rs index 893c86f8867..9961a68e5f0 100644 --- a/misc/multistream-select/src/dialer_select.rs +++ b/misc/multistream-select/src/dialer_select.rs @@ -25,7 +25,6 @@ use crate::{Negotiated, NegotiationError, Version}; use futures::prelude::*; use std::{ - convert::TryFrom as _, iter, mem, pin::Pin, task::{Context, Poll}, @@ -48,13 +47,12 @@ pub fn dialer_select_proto( inner: R, protocols: I, version: Version, -) -> DialerSelectFuture +) -> DialerSelectFuture where R: AsyncRead + AsyncWrite, - I: IntoIterator, - I::Item: AsRef<[u8]>, + I: Iterator, { - let protocols = protocols.into_iter().peekable(); + let protocols = protocols.peekable(); DialerSelectFuture { version, protocols, @@ -68,17 +66,27 @@ where /// a protocol iteratively by considering one protocol after the other. #[pin_project::pin_project] pub struct DialerSelectFuture { - // TODO: It would be nice if eventually N = I::Item = Protocol. protocols: iter::Peekable, - state: State, + state: State, version: Version, } -enum State { - SendHeader { io: MessageIO }, - SendProtocol { io: MessageIO, protocol: N }, - FlushProtocol { io: MessageIO, protocol: N }, - AwaitProtocol { io: MessageIO, protocol: N }, +enum State { + SendHeader { + io: MessageIO, + }, + SendProtocol { + io: MessageIO, + protocol: Protocol, + }, + FlushProtocol { + io: MessageIO, + protocol: Protocol, + }, + AwaitProtocol { + io: MessageIO, + protocol: Protocol, + }, Done, } @@ -87,10 +95,9 @@ where // The Unpin bound here is required because we produce a `Negotiated` as the output. // It also makes the implementation considerably easier to write. R: AsyncRead + AsyncWrite + Unpin, - I: Iterator, - I::Item: AsRef<[u8]>, + I: Iterator, { - type Output = Result<(I::Item, Negotiated), NegotiationError>; + type Output = Result<(Protocol, Negotiated), NegotiationError>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); @@ -127,11 +134,12 @@ where } } - let p = Protocol::try_from(protocol.as_ref())?; - if let Err(err) = Pin::new(&mut io).start_send(Message::Protocol(p.clone())) { + if let Err(err) = + Pin::new(&mut io).start_send(Message::Protocol(protocol.clone())) + { return Poll::Ready(Err(From::from(err))); } - log::debug!("Dialer: Proposed protocol: {}", p); + log::debug!("Dialer: Proposed protocol: {}", protocol); if this.protocols.peek().is_some() { *this.state = State::FlushProtocol { io, protocol } @@ -143,9 +151,13 @@ where // the dialer supports for this negotiation. Notably, // the dialer expects a regular `V1` response. Version::V1Lazy => { - log::debug!("Dialer: Expecting proposed protocol: {}", p); + log::debug!("Dialer: Expecting proposed protocol: {protocol}"); let hl = HeaderLine::from(Version::V1Lazy); - let io = Negotiated::expecting(io.into_reader(), p, Some(hl)); + let io = Negotiated::expecting( + io.into_reader(), + protocol.clone(), + Some(hl), + ); return Poll::Ready(Ok((protocol, io))); } } @@ -179,16 +191,13 @@ where Message::Header(v) if v == HeaderLine::from(*this.version) => { *this.state = State::AwaitProtocol { io, protocol }; } - Message::Protocol(ref p) if p.as_ref() == protocol.as_ref() => { - log::debug!("Dialer: Received confirmation for protocol: {}", p); + Message::Protocol(ref p) if p == &protocol => { + log::debug!("Dialer: Received confirmation for protocol: {p}"); let io = Negotiated::completed(io.into_inner()); return Poll::Ready(Ok((protocol, io))); } Message::NotAvailable => { - log::debug!( - "Dialer: Received rejection of protocol: {}", - String::from_utf8_lossy(protocol.as_ref()) - ); + log::debug!("Dialer: Received rejection of protocol: {protocol}",); let protocol = this.protocols.next().ok_or(NegotiationError::Failed)?; *this.state = State::SendProtocol { io, protocol } } diff --git a/misc/multistream-select/src/lib.rs b/misc/multistream-select/src/lib.rs index 0dbcf3cbe0b..a6d003b3449 100644 --- a/misc/multistream-select/src/lib.rs +++ b/misc/multistream-select/src/lib.rs @@ -72,13 +72,13 @@ //! //! ```no_run //! use async_std::net::TcpStream; -//! use multistream_select::{dialer_select_proto, Version}; +//! use multistream_select::{dialer_select_proto, Protocol, Version}; //! use futures::prelude::*; //! //! async_std::task::block_on(async move { //! let socket = TcpStream::connect("127.0.0.1:10333").await.unwrap(); //! -//! let protos = vec![b"/echo/1.0.0", b"/echo/2.5.0"]; +//! let protos = vec![Protocol::from_static("/echo/1.0.0"), Protocol::from_static("/echo/2.5.0")]; //! let (protocol, _io) = dialer_select_proto(socket, protos, Version::V1).await.unwrap(); //! //! println!("Negotiated protocol: {:?}", protocol); @@ -98,7 +98,7 @@ mod protocol; pub use self::dialer_select::{dialer_select_proto, DialerSelectFuture}; pub use self::listener_select::{listener_select_proto, ListenerSelectFuture}; pub use self::negotiated::{Negotiated, NegotiatedComplete, NegotiationError}; -pub use self::protocol::ProtocolError; +pub use self::protocol::{Protocol, ProtocolError}; /// Supported multistream-select versions. #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/misc/multistream-select/src/listener_select.rs b/misc/multistream-select/src/listener_select.rs index aa433e40c4d..ddb26235737 100644 --- a/misc/multistream-select/src/listener_select.rs +++ b/misc/multistream-select/src/listener_select.rs @@ -27,8 +27,6 @@ use crate::{Negotiated, NegotiationError}; use futures::prelude::*; use smallvec::SmallVec; use std::{ - convert::TryFrom as _, - iter::FromIterator, mem, pin::Pin, task::{Context, Poll}, @@ -41,25 +39,11 @@ use std::{ /// computation that performs the protocol negotiation with the remote. The /// returned `Future` resolves with the name of the negotiated protocol and /// a [`Negotiated`] I/O stream. -pub fn listener_select_proto(inner: R, protocols: I) -> ListenerSelectFuture +pub fn listener_select_proto(inner: R, protocols: I) -> ListenerSelectFuture where R: AsyncRead + AsyncWrite, - I: IntoIterator, - I::Item: AsRef<[u8]>, + I: Iterator, { - let protocols = protocols - .into_iter() - .filter_map(|n| match Protocol::try_from(n.as_ref()) { - Ok(p) => Some((n, p)), - Err(e) => { - log::warn!( - "Listener: Ignoring invalid protocol: {} due to {}", - String::from_utf8_lossy(n.as_ref()), - e - ); - None - } - }); ListenerSelectFuture { protocols: SmallVec::from_iter(protocols), state: State::RecvHeader { @@ -72,11 +56,9 @@ where /// The `Future` returned by [`listener_select_proto`] that performs a /// multistream-select protocol negotiation on an underlying I/O stream. #[pin_project::pin_project] -pub struct ListenerSelectFuture { - // TODO: It would be nice if eventually N = Protocol, which has a - // few more implications on the API. - protocols: SmallVec<[(N, Protocol); 8]>, - state: State, +pub struct ListenerSelectFuture { + protocols: SmallVec<[Protocol; 8]>, + state: State, /// Whether the last message sent was a protocol rejection (i.e. `na\n`). /// /// If the listener reads garbage or EOF after such a rejection, @@ -86,7 +68,7 @@ pub struct ListenerSelectFuture { last_sent_na: bool, } -enum State { +enum State { RecvHeader { io: MessageIO, }, @@ -99,23 +81,22 @@ enum State { SendMessage { io: MessageIO, message: Message, - protocol: Option, + protocol: Option, }, Flush { io: MessageIO, - protocol: Option, + protocol: Option, }, Done, } -impl Future for ListenerSelectFuture +impl Future for ListenerSelectFuture where // The Unpin bound here is required because we produce a `Negotiated` as the output. // It also makes the implementation considerably easier to write. R: AsyncRead + AsyncWrite + Unpin, - N: AsRef<[u8]> + Clone, { - type Output = Result<(N, Negotiated), NegotiationError>; + type Output = Result<(Protocol, Negotiated), NegotiationError>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); @@ -209,8 +190,7 @@ where match msg { Message::ListProtocols => { - let supported = - this.protocols.iter().map(|(_, p)| p).cloned().collect(); + let supported = this.protocols.clone().into_iter().collect(); let message = Message::Protocols(supported); *this.state = State::SendMessage { io, @@ -219,29 +199,20 @@ where } } Message::Protocol(p) => { - let protocol = this.protocols.iter().find_map(|(name, proto)| { - if &p == proto { - Some(name.clone()) - } else { - None - } - }); + let protocol = this.protocols.iter().find(|proto| &&p == proto); let message = if protocol.is_some() { log::debug!("Listener: confirming protocol: {}", p); Message::Protocol(p.clone()) } else { - log::debug!( - "Listener: rejecting protocol: {}", - String::from_utf8_lossy(p.as_ref()) - ); + log::debug!("Listener: rejecting protocol: {p}"); Message::NotAvailable }; *this.state = State::SendMessage { io, message, - protocol, + protocol: protocol.cloned(), }; } _ => return Poll::Ready(Err(ProtocolError::InvalidMessage.into())), @@ -290,10 +261,7 @@ where // Otherwise expect to receive another message. match protocol { Some(protocol) => { - log::debug!( - "Listener: sent confirmed protocol: {}", - String::from_utf8_lossy(protocol.as_ref()) - ); + log::debug!("Listener: sent confirmed protocol: {protocol}"); let io = Negotiated::completed(io.into_inner()); return Poll::Ready(Ok((protocol, io))); } diff --git a/misc/multistream-select/src/negotiated.rs b/misc/multistream-select/src/negotiated.rs index dabcec4f605..35010748b8e 100644 --- a/misc/multistream-select/src/negotiated.rs +++ b/misc/multistream-select/src/negotiated.rs @@ -170,8 +170,8 @@ impl Negotiated { } if let Message::Protocol(p) = &msg { - if p.as_ref() == protocol.as_ref() { - log::debug!("Negotiated: Received confirmation for protocol: {}", p); + if p == &protocol { + log::debug!("Negotiated: Received confirmation for protocol: {p}"); *this.state = State::Completed { io: io.into_inner(), }; diff --git a/misc/multistream-select/src/protocol.rs b/misc/multistream-select/src/protocol.rs index a560d116e53..e8145947cec 100644 --- a/misc/multistream-select/src/protocol.rs +++ b/misc/multistream-select/src/protocol.rs @@ -30,6 +30,7 @@ use crate::Version; use bytes::{BufMut, Bytes, BytesMut}; use futures::{io::IoSlice, prelude::*, ready}; +use std::borrow::Cow; use std::{ convert::TryFrom, error::Error, @@ -67,10 +68,40 @@ impl From for HeaderLine { } /// A protocol (name) exchanged during protocol negotiation. -#[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) struct Protocol(Bytes); -impl AsRef<[u8]> for Protocol { - fn as_ref(&self) -> &[u8] { +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Protocol(Cow<'static, str>); // TODO: Instead of `Cow`, we should probably be storing `Arc` + +impl Protocol { + /// Construct a new protocol from a static string slice. + /// + /// # Panics + /// + /// This function panics if the protocol does not start with a forward slash: `/`. + pub const fn from_static(protocol: &'static str) -> Self { + match protocol.as_bytes() { + [b'/', ..] => {} + _ => panic!("Protocols should start with a /"), + } + + Self(Cow::Borrowed(protocol)) + } + + /// Attempt to construct a protocol from an owned string. + /// + /// This function will fail if the protocol does not start with a forward slash: `/`. + /// Where possible, you should use [`Protocol::from_static`] instead to avoid allocations. + pub fn try_from_owned(protocol: String) -> Result { + // let arc = Arc::from(protocol.as_str()); + + if !protocol.starts_with('/') { + return Err(ProtocolError::InvalidProtocol); + } + + Ok(Self(Cow::Owned(protocol))) + } + + /// View the protocol as a string slice. + pub fn as_str(&self) -> &str { self.0.as_ref() } } @@ -79,10 +110,14 @@ impl TryFrom for Protocol { type Error = ProtocolError; fn try_from(value: Bytes) -> Result { - if !value.as_ref().starts_with(b"/") { + let protocol_string = + String::from_utf8(value.to_vec()).map_err(|_| ProtocolError::InvalidProtocol)?; + + if !protocol_string.starts_with('/') { return Err(ProtocolError::InvalidProtocol); } - Ok(Protocol(value)) + + Ok(Protocol(Cow::Owned(protocol_string))) } } @@ -96,7 +131,7 @@ impl TryFrom<&[u8]> for Protocol { impl fmt::Display for Protocol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", String::from_utf8_lossy(&self.0)) + write!(f, "{}", self.0) } } @@ -132,7 +167,7 @@ impl Message { Message::Protocol(p) => { let len = p.0.as_ref().len() + 1; // + 1 for \n dest.reserve(len); - dest.put(p.0.as_ref()); + dest.put(p.0.as_bytes()); dest.put_u8(b'\n'); Ok(()) } @@ -146,7 +181,7 @@ impl Message { let mut encoded = Vec::with_capacity(ps.len()); for p in ps { encoded.extend(uvi::encode::usize(p.0.as_ref().len() + 1, &mut buf)); // +1 for '\n' - encoded.extend_from_slice(p.0.as_ref()); + encoded.extend_from_slice(p.0.as_bytes()); encoded.push(b'\n') } encoded.push(b'\n'); @@ -464,7 +499,8 @@ mod tests { .filter(|&c| c.is_ascii_alphanumeric()) .take(n) .collect(); - Protocol(Bytes::from(format!("/{p}"))) + + Protocol::try_from_owned(format!("/{p}")).expect("it starts with /") } } diff --git a/misc/multistream-select/tests/dialer_select.rs b/misc/multistream-select/tests/dialer_select.rs index 378c8c15909..29f7d067609 100644 --- a/misc/multistream-select/tests/dialer_select.rs +++ b/misc/multistream-select/tests/dialer_select.rs @@ -22,7 +22,9 @@ use async_std::net::{TcpListener, TcpStream}; use futures::prelude::*; -use multistream_select::{dialer_select_proto, listener_select_proto, NegotiationError, Version}; +use multistream_select::{ + dialer_select_proto, listener_select_proto, NegotiationError, Protocol, Version, +}; #[test] fn select_proto_basic() { @@ -32,9 +34,13 @@ fn select_proto_basic() { let server = async_std::task::spawn(async move { let connec = listener.accept().await.unwrap().0; - let protos = vec![b"/proto1", b"/proto2"]; + let protos = vec![ + Protocol::from_static("/proto1"), + Protocol::from_static("/proto2"), + ] + .into_iter(); let (proto, mut io) = listener_select_proto(connec, protos).await.unwrap(); - assert_eq!(proto, b"/proto2"); + assert_eq!(proto, Protocol::from_static("/proto2")); let mut out = vec![0; 32]; let n = io.read(&mut out).await.unwrap(); @@ -47,11 +53,13 @@ fn select_proto_basic() { let client = async_std::task::spawn(async move { let connec = TcpStream::connect(&listener_addr).await.unwrap(); - let protos = vec![b"/proto3", b"/proto2"]; - let (proto, mut io) = dialer_select_proto(connec, protos.into_iter(), version) - .await - .unwrap(); - assert_eq!(proto, b"/proto2"); + let protos = vec![ + Protocol::from_static("/proto3"), + Protocol::from_static("/proto2"), + ] + .into_iter(); + let (proto, mut io) = dialer_select_proto(connec, protos, version).await.unwrap(); + assert_eq!(proto, Protocol::from_static("/proto2")); io.write_all(b"ping").await.unwrap(); io.flush().await.unwrap(); @@ -88,7 +96,7 @@ fn negotiation_failed() { let server = async_std::task::spawn(async move { let connec = listener.accept().await.unwrap().0; - let io = match listener_select_proto(connec, listen_protos).await { + let io = match listener_select_proto(connec, listen_protos.into_iter()).await { Ok((_, io)) => io, Err(NegotiationError::Failed) => return, Err(NegotiationError::ProtocolError(e)) => { @@ -126,8 +134,8 @@ fn negotiation_failed() { #[derive(Clone)] struct Test { version: Version, - listen_protos: Vec<&'static str>, - dial_protos: Vec<&'static str>, + listen_protos: Vec, + dial_protos: Vec, dial_payload: Vec, } @@ -136,8 +144,20 @@ fn negotiation_failed() { // The choices here cover the main distinction between a single // and multiple protocols. let protos = vec![ - (vec!["/proto1"], vec!["/proto2"]), - (vec!["/proto1", "/proto2"], vec!["/proto3", "/proto4"]), + ( + vec![Protocol::from_static("/proto1")], + vec![Protocol::from_static("/proto2")], + ), + ( + vec![ + Protocol::from_static("/proto1"), + Protocol::from_static("/proto2"), + ], + vec![ + Protocol::from_static("/proto3"), + Protocol::from_static("/proto4"), + ], + ), ]; // The payloads that the dialer sends after "successful" negotiation, diff --git a/muxers/mplex/src/config.rs b/muxers/mplex/src/config.rs index 587a4230480..67ee8314de7 100644 --- a/muxers/mplex/src/config.rs +++ b/muxers/mplex/src/config.rs @@ -19,9 +19,10 @@ // DEALINGS IN THE SOFTWARE. use crate::codec::MAX_FRAME_SIZE; +use libp2p_core::upgrade::Protocol; use std::cmp; -pub(crate) const DEFAULT_MPLEX_PROTOCOL_NAME: &[u8] = b"/mplex/6.7.0"; +pub(crate) const DEFAULT_MPLEX_PROTOCOL_NAME: Protocol = Protocol::from_static("/mplex/6.7.0"); /// Configuration for the multiplexer. #[derive(Debug, Clone)] @@ -36,7 +37,7 @@ pub struct MplexConfig { /// (max 1MByte, as per the Mplex spec). pub(crate) split_send_size: usize, /// Protocol name, defaults to b"/mplex/6.7.0" - pub(crate) protocol_name: &'static [u8], + pub(crate) protocol_name: Protocol, } impl MplexConfig { @@ -92,11 +93,12 @@ impl MplexConfig { /// Set the protocol name. /// /// ```rust + /// use libp2p_core::upgrade::Protocol; /// use libp2p_mplex::MplexConfig; /// let mut muxer_config = MplexConfig::new(); - /// muxer_config.set_protocol_name(b"/mplex/6.7.0"); + /// muxer_config.set_protocol_name(Protocol::from_static("/mplex/6.7.0")); /// ``` - pub fn set_protocol_name(&mut self, protocol_name: &'static [u8]) -> &mut Self { + pub fn set_protocol_name(&mut self, protocol_name: Protocol) -> &mut Self { self.protocol_name = protocol_name; self } diff --git a/muxers/mplex/src/lib.rs b/muxers/mplex/src/lib.rs index e1b1eb08cd9..e0773424a19 100644 --- a/muxers/mplex/src/lib.rs +++ b/muxers/mplex/src/lib.rs @@ -32,16 +32,16 @@ use bytes::Bytes; use codec::LocalStreamId; use futures::{future, prelude::*, ready}; use libp2p_core::muxing::{StreamMuxer, StreamMuxerEvent}; -use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, Protocol}; +use libp2p_core::ToProtocolsIter; use parking_lot::Mutex; use std::{cmp, iter, pin::Pin, sync::Arc, task::Context, task::Poll}; -impl UpgradeInfo for MplexConfig { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for MplexConfig { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - iter::once(self.protocol_name) + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(self.protocol_name.clone()) } } @@ -53,7 +53,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: C, _: Protocol) -> Self::Future { future::ready(Ok(Multiplex { io: Arc::new(Mutex::new(io::Multiplexed::new(socket, self))), })) @@ -68,7 +68,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: C, _: Protocol) -> Self::Future { future::ready(Ok(Multiplex { io: Arc::new(Mutex::new(io::Multiplexed::new(socket, self))), })) diff --git a/muxers/test-harness/src/lib.rs b/muxers/test-harness/src/lib.rs index 8eeafb363f5..80dba7600ce 100644 --- a/muxers/test-harness/src/lib.rs +++ b/muxers/test-harness/src/lib.rs @@ -7,7 +7,7 @@ use libp2p_core::muxing::StreamMuxerExt; use libp2p_core::transport::memory::Channel; use libp2p_core::transport::MemoryTransport; use libp2p_core::{ - upgrade, InboundUpgrade, Negotiated, OutboundUpgrade, StreamMuxer, Transport, UpgradeInfo, + upgrade, InboundUpgrade, Negotiated, OutboundUpgrade, StreamMuxer, ToProtocolsIter, Transport, }; use std::future::Future; use std::pin::Pin; @@ -17,13 +17,12 @@ use std::{fmt, mem}; pub async fn connected_muxers_on_memory_transport() -> (M, M) where - MC: InboundUpgrade>>, Error = E, Output = M> + MC: ToProtocolsIter + + InboundUpgrade>>, Error = E, Output = M> + OutboundUpgrade>>, Error = E, Output = M> + Send + 'static + Default, - ::Info: Send, - <::InfoIter as IntoIterator>::IntoIter: Send, >>>>::Future: Send, >>>>::Future: Send, E: std::error::Error + Send + Sync + 'static, diff --git a/muxers/yamux/src/lib.rs b/muxers/yamux/src/lib.rs index 42fb1621e56..931b982d909 100644 --- a/muxers/yamux/src/lib.rs +++ b/muxers/yamux/src/lib.rs @@ -29,7 +29,8 @@ use futures::{ stream::{BoxStream, LocalBoxStream}, }; use libp2p_core::muxing::{StreamMuxer, StreamMuxerEvent}; -use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, Protocol}; +use libp2p_core::ToProtocolsIter; use std::collections::VecDeque; use std::task::Waker; use std::{ @@ -311,21 +312,19 @@ impl Default for YamuxConfig { } } -impl UpgradeInfo for YamuxConfig { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for YamuxConfig { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - iter::once(b"/yamux/1.0.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(Protocol::from_static("/yamux/1.0.0")) } } -impl UpgradeInfo for YamuxLocalConfig { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for YamuxLocalConfig { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - iter::once(b"/yamux/1.0.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(Protocol::from_static("/yamux/1.0.0")) } } @@ -337,7 +336,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_inbound(self, io: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, io: C, _: Protocol) -> Self::Future { let mode = self.mode.unwrap_or(yamux::Mode::Server); future::ready(Ok(Yamux::new(io, self.inner, mode))) } @@ -351,7 +350,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_inbound(self, io: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, io: C, _: Protocol) -> Self::Future { let cfg = self.0; let mode = cfg.mode.unwrap_or(yamux::Mode::Server); future::ready(Ok(Yamux::local(io, cfg.inner, mode))) @@ -366,7 +365,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_outbound(self, io: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, io: C, _: Protocol) -> Self::Future { let mode = self.mode.unwrap_or(yamux::Mode::Client); future::ready(Ok(Yamux::new(io, self.inner, mode))) } @@ -380,7 +379,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_outbound(self, io: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, io: C, _: Protocol) -> Self::Future { let cfg = self.0; let mode = cfg.mode.unwrap_or(yamux::Mode::Client); future::ready(Ok(Yamux::local(io, cfg.inner, mode))) diff --git a/protocols/autonat/src/behaviour.rs b/protocols/autonat/src/behaviour.rs index b0d07f7a37b..c46d8044989 100644 --- a/protocols/autonat/src/behaviour.rs +++ b/protocols/autonat/src/behaviour.rs @@ -21,7 +21,8 @@ mod as_client; mod as_server; -use crate::protocol::{AutoNatCodec, AutoNatProtocol, DialRequest, DialResponse, ResponseError}; +use crate::protocol::{AutoNatCodec, DialRequest, DialResponse, ResponseError}; +use crate::DEFAULT_PROTOCOL_NAME; use as_client::AsClient; pub use as_client::{OutboundProbeError, OutboundProbeEvent}; use as_server::AsServer; @@ -218,7 +219,7 @@ pub struct Behaviour { impl Behaviour { pub fn new(local_peer_id: PeerId, config: Config) -> Self { - let protocols = iter::once((AutoNatProtocol, ProtocolSupport::Full)); + let protocols = iter::once((DEFAULT_PROTOCOL_NAME, ProtocolSupport::Full)); let mut cfg = request_response::Config::default(); cfg.set_request_timeout(config.timeout); let inner = request_response::Behaviour::new(AutoNatCodec, protocols, cfg); diff --git a/protocols/autonat/src/protocol.rs b/protocols/autonat/src/protocol.rs index 82e448cda24..7bb206174a1 100644 --- a/protocols/autonat/src/protocol.rs +++ b/protocols/autonat/src/protocol.rs @@ -21,38 +21,25 @@ use crate::proto; use async_trait::async_trait; use futures::io::{AsyncRead, AsyncWrite, AsyncWriteExt}; +use libp2p_core::upgrade::Protocol; use libp2p_core::{upgrade, Multiaddr}; use libp2p_identity::PeerId; -use libp2p_request_response::{self as request_response, ProtocolName}; +use libp2p_request_response::{self as request_response}; use quick_protobuf::{BytesReader, Writer}; use std::{convert::TryFrom, io}; -#[derive(Clone, Debug)] -pub struct AutoNatProtocol; - /// The protocol name used for negotiating with multistream-select. -pub const DEFAULT_PROTOCOL_NAME: &[u8] = b"/libp2p/autonat/1.0.0"; - -impl ProtocolName for AutoNatProtocol { - fn protocol_name(&self) -> &[u8] { - DEFAULT_PROTOCOL_NAME - } -} +pub const DEFAULT_PROTOCOL_NAME: Protocol = Protocol::from_static("/libp2p/autonat/1.0.0"); #[derive(Clone)] pub struct AutoNatCodec; #[async_trait] impl request_response::Codec for AutoNatCodec { - type Protocol = AutoNatProtocol; type Request = DialRequest; type Response = DialResponse; - async fn read_request( - &mut self, - _: &AutoNatProtocol, - io: &mut T, - ) -> io::Result + async fn read_request(&mut self, _: &Protocol, io: &mut T) -> io::Result where T: AsyncRead + Send + Unpin, { @@ -61,11 +48,7 @@ impl request_response::Codec for AutoNatCodec { Ok(request) } - async fn read_response( - &mut self, - _: &AutoNatProtocol, - io: &mut T, - ) -> io::Result + async fn read_response(&mut self, _: &Protocol, io: &mut T) -> io::Result where T: AsyncRead + Send + Unpin, { @@ -76,7 +59,7 @@ impl request_response::Codec for AutoNatCodec { async fn write_request( &mut self, - _: &AutoNatProtocol, + _: &Protocol, io: &mut T, data: Self::Request, ) -> io::Result<()> @@ -89,7 +72,7 @@ impl request_response::Codec for AutoNatCodec { async fn write_response( &mut self, - _: &AutoNatProtocol, + _: &Protocol, io: &mut T, data: Self::Response, ) -> io::Result<()> diff --git a/protocols/dcutr/src/protocol.rs b/protocols/dcutr/src/protocol.rs index 4da255fc1d9..6474c695730 100644 --- a/protocols/dcutr/src/protocol.rs +++ b/protocols/dcutr/src/protocol.rs @@ -18,8 +18,10 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +use libp2p_core::upgrade::Protocol; + pub(crate) mod inbound; pub(crate) mod outbound; -pub const PROTOCOL_NAME: &[u8; 13] = b"/libp2p/dcutr"; +pub const PROTOCOL_NAME: Protocol = Protocol::from_static("/libp2p/dcutr"); const MAX_MESSAGE_SIZE_BYTES: usize = 4096; diff --git a/protocols/dcutr/src/protocol/inbound.rs b/protocols/dcutr/src/protocol/inbound.rs index fde42c6c924..05682b4f335 100644 --- a/protocols/dcutr/src/protocol/inbound.rs +++ b/protocols/dcutr/src/protocol/inbound.rs @@ -21,7 +21,7 @@ use crate::proto; use asynchronous_codec::Framed; use futures::{future::BoxFuture, prelude::*}; -use libp2p_core::{multiaddr::Protocol, upgrade, Multiaddr}; +use libp2p_core::{multiaddr::Protocol, upgrade, Multiaddr, ToProtocolsIter}; use libp2p_swarm::NegotiatedSubstream; use std::convert::TryFrom; use std::iter; @@ -29,11 +29,10 @@ use thiserror::Error; pub struct Upgrade {} -impl upgrade::UpgradeInfo for Upgrade { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Upgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(super::PROTOCOL_NAME) } } @@ -43,7 +42,7 @@ impl upgrade::InboundUpgrade for Upgrade { type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, substream: NegotiatedSubstream, _: upgrade::Protocol) -> Self::Future { let mut substream = Framed::new( substream, quick_protobuf_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES), diff --git a/protocols/dcutr/src/protocol/outbound.rs b/protocols/dcutr/src/protocol/outbound.rs index 9bbb1eb89a8..37a6ff02b70 100644 --- a/protocols/dcutr/src/protocol/outbound.rs +++ b/protocols/dcutr/src/protocol/outbound.rs @@ -23,7 +23,7 @@ use asynchronous_codec::Framed; use futures::{future::BoxFuture, prelude::*}; use futures_timer::Delay; use instant::Instant; -use libp2p_core::{multiaddr::Protocol, upgrade, Multiaddr}; +use libp2p_core::{multiaddr::Protocol, upgrade, Multiaddr, ToProtocolsIter}; use libp2p_swarm::NegotiatedSubstream; use std::convert::TryFrom; use std::iter; @@ -33,11 +33,10 @@ pub struct Upgrade { obs_addrs: Vec, } -impl upgrade::UpgradeInfo for Upgrade { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Upgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(super::PROTOCOL_NAME) } } @@ -53,7 +52,11 @@ impl upgrade::OutboundUpgrade for Upgrade { type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future { + fn upgrade_outbound( + self, + substream: NegotiatedSubstream, + _: upgrade::Protocol, + ) -> Self::Future { let mut substream = Framed::new( substream, quick_protobuf_codec::Codec::new(super::MAX_MESSAGE_SIZE_BYTES), diff --git a/protocols/floodsub/src/protocol.rs b/protocols/floodsub/src/protocol.rs index 7ac584bd2de..7dc0181c899 100644 --- a/protocols/floodsub/src/protocol.rs +++ b/protocols/floodsub/src/protocol.rs @@ -26,13 +26,14 @@ use futures::{ Future, }; use futures::{SinkExt, StreamExt}; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_identity::PeerId; use std::{io, iter, pin::Pin}; const MAX_MESSAGE_LEN_BYTES: usize = 2048; -const PROTOCOL_NAME: &[u8] = b"/floodsub/1.0.0"; +const PROTOCOL_NAME: Protocol = Protocol::from_static("/floodsub/1.0.0"); /// Implementation of `ConnectionUpgrade` for the floodsub protocol. #[derive(Debug, Clone, Default)] @@ -45,11 +46,10 @@ impl FloodsubProtocol { } } -impl UpgradeInfo for FloodsubProtocol { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for FloodsubProtocol { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(PROTOCOL_NAME) } } @@ -62,7 +62,7 @@ where type Error = FloodsubError; type Future = Pin> + Send>>; - fn upgrade_inbound(self, socket: TSocket, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: TSocket, _: Protocol) -> Self::Future { Box::pin(async move { let mut framed = Framed::new( socket, @@ -132,11 +132,10 @@ pub struct FloodsubRpc { pub subscriptions: Vec, } -impl UpgradeInfo for FloodsubRpc { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for FloodsubRpc { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(PROTOCOL_NAME) } } @@ -149,7 +148,7 @@ where type Error = CodecError; type Future = Pin> + Send>>; - fn upgrade_outbound(self, socket: TSocket, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: TSocket, _: Protocol) -> Self::Future { Box::pin(async move { let mut framed = Framed::new( socket, diff --git a/protocols/gossipsub/src/behaviour.rs b/protocols/gossipsub/src/behaviour.rs index 13ce3fcee35..02182d07bec 100644 --- a/protocols/gossipsub/src/behaviour.rs +++ b/protocols/gossipsub/src/behaviour.rs @@ -3249,7 +3249,7 @@ where .get(&peer_id) .expect("Connected peer must be registered") .kind; - metrics.peer_protocol_disconnected(peer_kind.clone()); + metrics.peer_protocol_disconnected(*peer_kind); } self.connected_peers.remove(&peer_id); @@ -3346,7 +3346,7 @@ where // We have identified the protocol this peer is using if let Some(metrics) = self.metrics.as_mut() { - metrics.peer_protocol_connected(kind.clone()); + metrics.peer_protocol_connected(kind); } if let PeerKind::NotSupported = kind { diff --git a/protocols/gossipsub/src/config.rs b/protocols/gossipsub/src/config.rs index 098a3eb7e0b..49784d8d110 100644 --- a/protocols/gossipsub/src/config.rs +++ b/protocols/gossipsub/src/config.rs @@ -886,9 +886,9 @@ mod test { use super::*; use crate::protocol_priv::ProtocolConfig; use crate::topic::IdentityHash; - use crate::types::PeerKind; use crate::Topic; - use libp2p_core::UpgradeInfo; + use libp2p_core::upgrade::Protocol; + use libp2p_core::ToProtocolsIter; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -991,15 +991,17 @@ mod test { assert_eq!(builder.custom_id_version(), &None); let protocol_config = ProtocolConfig::new(&builder); - let protocol_ids = protocol_config.protocol_info(); + let protocol_ids = protocol_config + .to_protocols_iter() + .collect::>(); assert_eq!(protocol_ids.len(), 2); - assert_eq!(protocol_ids[0].protocol_id, b"/purple/1.1.0".to_vec()); - assert_eq!(protocol_ids[0].kind, PeerKind::Gossipsubv1_1); + assert_eq!(protocol_ids[0], Protocol::from_static("/purple/1.1.0")); + // assert_eq!(protocol_ids[0].kind, PeerKind::Gossipsubv1_1); // TODO - assert_eq!(protocol_ids[1].protocol_id, b"/purple/1.0.0".to_vec()); - assert_eq!(protocol_ids[1].kind, PeerKind::Gossipsub); + assert_eq!(protocol_ids[1], Protocol::from_static("/purple/1.0.0")); + // assert_eq!(protocol_ids[1].kind, PeerKind::Gossipsub); // TODO } #[test] @@ -1015,11 +1017,11 @@ mod test { assert_eq!(builder.custom_id_version(), &Some(Version::V1_0)); let protocol_config = ProtocolConfig::new(&builder); - let protocol_ids = protocol_config.protocol_info(); + let protocol_ids = protocol_config.to_protocols_iter().collect::>(); assert_eq!(protocol_ids.len(), 1); - assert_eq!(protocol_ids[0].protocol_id, b"purple".to_vec()); - assert_eq!(protocol_ids[0].kind, PeerKind::Gossipsub); + assert_eq!(protocol_ids[0], Protocol::from_static("purple")); + // assert_eq!(protocol_ids[0].kind, PeerKind::Gossipsub); } } diff --git a/protocols/gossipsub/src/handler.rs b/protocols/gossipsub/src/handler.rs index 269bdcd404f..0c651001c15 100644 --- a/protocols/gossipsub/src/handler.rs +++ b/protocols/gossipsub/src/handler.rs @@ -79,6 +79,7 @@ pub enum HandlerIn { /// creation loops. const MAX_SUBSTREAM_ATTEMPTS: usize = 5; +#[allow(clippy::large_enum_variant)] pub enum Handler { Enabled(EnabledHandler), Disabled(DisabledHandler), @@ -229,10 +230,10 @@ impl EnabledHandler { >, > { if !self.peer_kind_sent { - if let Some(peer_kind) = self.peer_kind.as_ref() { + if let Some(peer_kind) = self.peer_kind { self.peer_kind_sent = true; return Poll::Ready(ConnectionHandlerEvent::Custom(HandlerEvent::PeerKind( - peer_kind.clone(), + peer_kind, ))); } } diff --git a/protocols/gossipsub/src/protocol_priv.rs b/protocols/gossipsub/src/protocol_priv.rs index 34d931bbaf9..58cb5972d46 100644 --- a/protocols/gossipsub/src/protocol_priv.rs +++ b/protocols/gossipsub/src/protocol_priv.rs @@ -31,7 +31,8 @@ use byteorder::{BigEndian, ByteOrder}; use bytes::BytesMut; use futures::future; use futures::prelude::*; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_identity::{PeerId, PublicKey}; use log::{debug, warn}; use quick_protobuf::Writer; @@ -101,7 +102,7 @@ impl ProtocolConfig { #[derive(Clone, Debug)] pub struct ProtocolId { /// The RPC message type/name. - pub protocol_id: Vec, + pub protocol_id: Protocol, /// The type of protocol we support pub kind: PeerKind, } @@ -109,37 +110,38 @@ pub struct ProtocolId { /// An RPC protocol ID. impl ProtocolId { pub fn new(id: &str, kind: PeerKind, prefix: bool) -> Self { - let protocol_id = match kind { - PeerKind::Gossipsubv1_1 => match prefix { - true => format!("/{}/{}", id, "1.1.0"), - false => id.to_string(), - }, - PeerKind::Gossipsub => match prefix { - true => format!("/{}/{}", id, "1.0.0"), - false => id.to_string(), - }, - PeerKind::Floodsub => format!("/{}/{}", "floodsub", "1.0.0"), + if !prefix { + return ProtocolId { + protocol_id: Protocol::try_from_owned(id.to_string()).expect("bad protocol id"), + kind, + }; + } + + let protocol = match kind { + PeerKind::Gossipsubv1_1 => { + Protocol::try_from_owned(format!("/{}/1.1.0", id)).expect("starts with a slash") + } + PeerKind::Gossipsub => { + Protocol::try_from_owned(format!("/{}/1.0.0", id)).expect("starts with a slash") + } + PeerKind::Floodsub => Protocol::from_static("/floodsub/1.0.0"), // NOTE: This is used for informing the behaviour of unsupported peers. We do not // advertise this variant. PeerKind::NotSupported => unreachable!("Should never advertise NotSupported"), - } - .into_bytes(); - ProtocolId { protocol_id, kind } - } -} + }; -impl ProtocolName for ProtocolId { - fn protocol_name(&self) -> &[u8] { - &self.protocol_id + ProtocolId { + protocol_id: protocol, + kind, + } } } -impl UpgradeInfo for ProtocolConfig { - type Info = ProtocolId; - type InfoIter = Vec; +impl ToProtocolsIter for ProtocolConfig { + type Iter = std::iter::Map, fn(ProtocolId) -> Protocol>; - fn protocol_info(&self) -> Self::InfoIter { - self.protocol_ids.clone() + fn to_protocols_iter(&self) -> Self::Iter { + self.protocol_ids.clone().into_iter().map(|p| p.protocol_id) } } @@ -151,15 +153,22 @@ where type Error = Void; type Future = Pin> + Send>>; - fn upgrade_inbound(self, socket: TSocket, protocol_id: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: TSocket, protocol_id: Protocol) -> Self::Future { let mut length_codec = codec::UviBytes::default(); length_codec.set_max_len(self.max_transmit_size); + + let peer_kind = self + .protocol_ids + .iter() + .find_map(|p| (p.protocol_id == protocol_id).then_some(p.kind)) + .expect("to receive a protocol id we support"); + Box::pin(future::ok(( Framed::new( socket, GossipsubCodec::new(length_codec, self.validation_mode), ), - protocol_id.kind, + peer_kind, ))) } } @@ -172,15 +181,22 @@ where type Error = Void; type Future = Pin> + Send>>; - fn upgrade_outbound(self, socket: TSocket, protocol_id: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: TSocket, protocol_id: Protocol) -> Self::Future { let mut length_codec = codec::UviBytes::default(); length_codec.set_max_len(self.max_transmit_size); + + let peer_kind = self + .protocol_ids + .iter() + .find_map(|p| (p.protocol_id == protocol_id).then_some(p.kind)) + .expect("to receive a protocol id we support"); + Box::pin(future::ok(( Framed::new( socket, GossipsubCodec::new(length_codec, self.validation_mode), ), - protocol_id.kind, + peer_kind, ))) } } diff --git a/protocols/gossipsub/src/types.rs b/protocols/gossipsub/src/types.rs index 9c9cd3f97f1..6d1bd394f8e 100644 --- a/protocols/gossipsub/src/types.rs +++ b/protocols/gossipsub/src/types.rs @@ -96,7 +96,7 @@ pub(crate) struct PeerConnections { } /// Describes the types of peers that can exist in the gossipsub context. -#[derive(Debug, Clone, PartialEq, Hash, EncodeLabelValue, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Hash, EncodeLabelValue, Eq)] pub enum PeerKind { /// A gossipsub 1.1 peer. Gossipsubv1_1, diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 8ba50e2db4b..f544e027511 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -20,7 +20,7 @@ use crate::handler::{self, Handler, InEvent}; use crate::protocol::{Info, Protocol, UpgradeError}; -use libp2p_core::{multiaddr, ConnectedPoint, Endpoint, Multiaddr}; +use libp2p_core::{multiaddr, upgrade, ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_identity::PublicKey; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; @@ -488,12 +488,14 @@ pub enum Event { }, } -fn supported_protocols(params: &impl PollParameters) -> Vec { +fn supported_protocols(params: &impl PollParameters) -> Vec { // The protocol names can be bytes, but the identify protocol except UTF-8 strings. // There's not much we can do to solve this conflict except strip non-UTF-8 characters. params .supported_protocols() - .map(|p| String::from_utf8_lossy(&p).to_string()) + .filter_map(|p| { + upgrade::Protocol::try_from_owned(String::from_utf8_lossy(&p).to_string()).ok() + }) .collect() } diff --git a/protocols/identify/src/handler.rs b/protocols/identify/src/handler.rs index c0bd9d928eb..a5c21ff00fa 100644 --- a/protocols/identify/src/handler.rs +++ b/protocols/identify/src/handler.rs @@ -27,7 +27,7 @@ use futures::prelude::*; use futures::stream::FuturesUnordered; use futures_timer::Delay; use libp2p_core::upgrade::SelectUpgrade; -use libp2p_core::Multiaddr; +use libp2p_core::{upgrade, Multiaddr}; use libp2p_identity::PeerId; use libp2p_identity::PublicKey; use libp2p_swarm::handler::{ @@ -92,7 +92,7 @@ pub struct InEvent { pub listen_addrs: Vec, /// The list of protocols supported by the peer, e.g. `/ipfs/ping/1.0.0`. - pub supported_protocols: Vec, + pub supported_protocols: Vec, /// The protocol w.r.t. the information requested. pub protocol: Protocol, diff --git a/protocols/identify/src/protocol.rs b/protocols/identify/src/protocol.rs index 1a10b591278..4163752c475 100644 --- a/protocols/identify/src/protocol.rs +++ b/protocols/identify/src/protocol.rs @@ -22,9 +22,9 @@ use crate::proto; use asynchronous_codec::{FramedRead, FramedWrite}; use futures::{future::BoxFuture, prelude::*}; use libp2p_core::{ - multiaddr, - upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}, - Multiaddr, + multiaddr, upgrade, + upgrade::{InboundUpgrade, OutboundUpgrade}, + Multiaddr, ToProtocolsIter, }; use libp2p_identity as identity; use libp2p_identity::PublicKey; @@ -37,9 +37,9 @@ use void::Void; const MAX_MESSAGE_SIZE_BYTES: usize = 4096; -pub const PROTOCOL_NAME: &[u8; 14] = b"/ipfs/id/1.0.0"; - -pub const PUSH_PROTOCOL_NAME: &[u8; 19] = b"/ipfs/id/push/1.0.0"; +pub const PROTOCOL_NAME: upgrade::Protocol = upgrade::Protocol::from_static("/ipfs/id/1.0.0"); +pub const PUSH_PROTOCOL_NAME: upgrade::Protocol = + upgrade::Protocol::from_static("/ipfs/id/push/1.0.0"); /// The type of the Substream protocol. #[derive(Debug, PartialEq, Eq)] @@ -84,16 +84,15 @@ pub struct Info { /// The addresses that the peer is listening on. pub listen_addrs: Vec, /// The list of protocols supported by the peer, e.g. `/ipfs/ping/1.0.0`. - pub protocols: Vec, + pub protocols: Vec, /// Address observed by or for the remote. pub observed_addr: Multiaddr, } -impl UpgradeInfo for Identify { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Identify { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(PROTOCOL_NAME) } } @@ -103,7 +102,7 @@ impl InboundUpgrade for Identify { type Error = UpgradeError; type Future = future::Ready>; - fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: C, _: libp2p_core::upgrade::Protocol) -> Self::Future { future::ok(socket) } } @@ -116,16 +115,15 @@ where type Error = UpgradeError; type Future = Pin> + Send>>; - fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: C, _: upgrade::Protocol) -> Self::Future { recv(socket).boxed() } } -impl UpgradeInfo for Push { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Push { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(PUSH_PROTOCOL_NAME) } } @@ -138,7 +136,7 @@ where type Error = Void; type Future = future::Ready>; - fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: C, _: libp2p_core::upgrade::Protocol) -> Self::Future { // Lazily upgrade stream, thus allowing upgrade to happen within identify's handler. future::ok(recv(socket).boxed()) } @@ -152,7 +150,7 @@ where type Error = UpgradeError; type Future = Pin> + Send>>; - fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: C, _: libp2p_core::upgrade::Protocol) -> Self::Future { send(socket, self.0 .0).boxed() } } @@ -177,7 +175,7 @@ where publicKey: Some(pubkey_bytes), listenAddrs: listen_addrs, observedAddr: Some(info.observed_addr.to_vec()), - protocols: info.protocols, + protocols: info.protocols.into_iter().map(|p| p.to_string()).collect(), }; let mut framed_io = FramedWrite::new( @@ -249,7 +247,17 @@ impl TryFrom for Info { protocol_version: msg.protocolVersion.unwrap_or_default(), agent_version: msg.agentVersion.unwrap_or_default(), listen_addrs, - protocols: msg.protocols, + protocols: msg + .protocols + .into_iter() + .filter_map(|p| match upgrade::Protocol::try_from_owned(p) { + Ok(p) => Some(p), + Err(e) => { + log::debug!("Unable to parse protocol: {e}"); + None + } + }) + .collect(), observed_addr, }; @@ -328,7 +336,10 @@ mod tests { "/ip4/80.81.82.83/tcp/500".parse().unwrap(), "/ip6/::1/udp/1000".parse().unwrap(), ], - protocols: vec!["proto1".to_string(), "proto2".to_string()], + protocols: vec![ + upgrade::Protocol::from_static("/proto1"), + upgrade::Protocol::from_static("/proto2"), + ], observed_addr: "/ip4/100.101.102.103/tcp/5000".parse().unwrap(), }, ) @@ -359,7 +370,10 @@ mod tests { ); assert_eq!( info.protocols, - &["proto1".to_string(), "proto2".to_string()] + &[ + upgrade::Protocol::from_static("/proto1"), + upgrade::Protocol::from_static("/proto2") + ] ); bg_task.await; diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index b34c5e428f7..56bc5738a2a 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -39,6 +39,7 @@ use crate::record_priv::{ use crate::K_VALUE; use fnv::{FnvHashMap, FnvHashSet}; use instant::Instant; +use libp2p_core::upgrade::Protocol; use libp2p_core::{ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_swarm::behaviour::{ @@ -56,8 +57,8 @@ use std::collections::{BTreeMap, HashSet, VecDeque}; use std::fmt; use std::num::NonZeroUsize; use std::task::{Context, Poll}; +use std::time::Duration; use std::vec; -use std::{borrow::Cow, time::Duration}; use thiserror::Error; pub use crate::query::QueryStats; @@ -228,7 +229,7 @@ impl KademliaConfig { /// More than one protocol name can be supplied. In this case the node will /// be able to talk to other nodes supporting any of the provided names. /// Multiple names must be used with caution to avoid network partitioning. - pub fn set_protocol_names(&mut self, names: Vec>) -> &mut Self { + pub fn set_protocol_names(&mut self, names: Vec) -> &mut Self { self.protocol_config.set_protocol_names(names); self } @@ -411,7 +412,7 @@ where } /// Get the protocol name of this kademlia instance. - pub fn protocol_names(&self) -> &[Cow<'static, [u8]>] { + pub fn protocol_names(&self) -> &[Protocol] { self.protocol_config.protocol_names() } diff --git a/protocols/kad/src/protocol_priv.rs b/protocols/kad/src/protocol_priv.rs index 3f7f9d99443..7f00045d9e7 100644 --- a/protocols/kad/src/protocol_priv.rs +++ b/protocols/kad/src/protocol_priv.rs @@ -33,16 +33,16 @@ use bytes::BytesMut; use codec::UviBytes; use futures::prelude::*; use instant::Instant; -use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; -use libp2p_core::Multiaddr; +use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, Protocol}; +use libp2p_core::{Multiaddr, ToProtocolsIter}; use libp2p_identity::PeerId; use quick_protobuf::{BytesReader, Writer}; -use std::{borrow::Cow, convert::TryFrom, time::Duration}; +use std::{convert::TryFrom, time::Duration}; use std::{io, iter}; use unsigned_varint::codec; /// The protocol name used for negotiating with multistream-select. -pub const DEFAULT_PROTO_NAME: &[u8] = b"/ipfs/kad/1.0.0"; +pub const DEFAULT_PROTO_NAME: Protocol = Protocol::from_static("/ipfs/kad/1.0.0"); /// The default maximum size for a varint length-delimited packet. pub const DEFAULT_MAX_PACKET_SIZE: usize = 16 * 1024; @@ -139,20 +139,20 @@ impl From for proto::Peer { // `OutboundUpgrade` to be just a single message #[derive(Debug, Clone)] pub struct KademliaProtocolConfig { - protocol_names: Vec>, + protocol_names: Vec, /// Maximum allowed size of a packet. max_packet_size: usize, } impl KademliaProtocolConfig { /// Returns the configured protocol name. - pub fn protocol_names(&self) -> &[Cow<'static, [u8]>] { + pub fn protocol_names(&self) -> &[Protocol] { &self.protocol_names } /// Modifies the protocol names used on the wire. Can be used to create incompatibilities /// between networks on purpose. - pub fn set_protocol_names(&mut self, names: Vec>) { + pub fn set_protocol_names(&mut self, names: Vec) { self.protocol_names = names; } @@ -165,17 +165,16 @@ impl KademliaProtocolConfig { impl Default for KademliaProtocolConfig { fn default() -> Self { KademliaProtocolConfig { - protocol_names: iter::once(Cow::Borrowed(DEFAULT_PROTO_NAME)).collect(), + protocol_names: iter::once(DEFAULT_PROTO_NAME).collect(), max_packet_size: DEFAULT_MAX_PACKET_SIZE, } } } -impl UpgradeInfo for KademliaProtocolConfig { - type Info = Cow<'static, [u8]>; - type InfoIter = std::vec::IntoIter; +impl ToProtocolsIter for KademliaProtocolConfig { + type Iter = std::vec::IntoIter; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { self.protocol_names.clone().into_iter() } } @@ -188,7 +187,7 @@ where type Future = future::Ready>; type Error = io::Error; - fn upgrade_inbound(self, incoming: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, incoming: C, _: Protocol) -> Self::Future { use quick_protobuf::{MessageRead, MessageWrite}; let mut codec = UviBytes::default(); @@ -226,7 +225,7 @@ where type Future = future::Ready>; type Error = io::Error; - fn upgrade_outbound(self, incoming: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, incoming: C, _: Protocol) -> Self::Future { use quick_protobuf::{MessageRead, MessageWrite}; let mut codec = UviBytes::default(); diff --git a/protocols/perf/src/client/handler.rs b/protocols/perf/src/client/handler.rs index f75a43f0a4e..6a6bf2c3882 100644 --- a/protocols/perf/src/client/handler.rs +++ b/protocols/perf/src/client/handler.rs @@ -87,7 +87,7 @@ impl ConnectionHandler for Handler { type OutEvent = Event; type Error = Void; type InboundProtocol = DeniedUpgrade; - type OutboundProtocol = ReadyUpgrade<&'static [u8]>; + type OutboundProtocol = ReadyUpgrade; type OutboundOpenInfo = Command; type InboundOpenInfo = (); diff --git a/protocols/perf/src/lib.rs b/protocols/perf/src/lib.rs index 19bb956a1d2..4cd7ec3f5b1 100644 --- a/protocols/perf/src/lib.rs +++ b/protocols/perf/src/lib.rs @@ -24,8 +24,10 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +use libp2p_core::upgrade::Protocol; + pub mod client; mod protocol; pub mod server; -pub const PROTOCOL_NAME: &[u8; 11] = b"/perf/1.0.0"; +pub const PROTOCOL_NAME: Protocol = Protocol::from_static("/perf/1.0.0"); diff --git a/protocols/perf/src/server/handler.rs b/protocols/perf/src/server/handler.rs index 2946b6d4a4c..20b09f3a4f3 100644 --- a/protocols/perf/src/server/handler.rs +++ b/protocols/perf/src/server/handler.rs @@ -67,7 +67,7 @@ impl ConnectionHandler for Handler { type InEvent = Void; type OutEvent = Event; type Error = Void; - type InboundProtocol = ReadyUpgrade<&'static [u8]>; + type InboundProtocol = ReadyUpgrade; type OutboundProtocol = DeniedUpgrade; type OutboundOpenInfo = Void; type InboundOpenInfo = (); diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index 2703b274c77..49e5292bbce 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -257,12 +257,12 @@ impl ConnectionHandler for Handler { type InEvent = Void; type OutEvent = crate::Result; type Error = Failure; - type InboundProtocol = ReadyUpgrade<&'static [u8]>; - type OutboundProtocol = ReadyUpgrade<&'static [u8]>; + type InboundProtocol = ReadyUpgrade; + type OutboundProtocol = ReadyUpgrade; type OutboundOpenInfo = (); type InboundOpenInfo = (); - fn listen_protocol(&self) -> SubstreamProtocol, ()> { + fn listen_protocol(&self) -> SubstreamProtocol { SubstreamProtocol::new(ReadyUpgrade::new(PROTOCOL_NAME), ()) } @@ -279,8 +279,7 @@ impl ConnectionHandler for Handler { fn poll( &mut self, cx: &mut Context<'_>, - ) -> Poll, (), crate::Result, Self::Error>> - { + ) -> Poll> { match self.state { State::Inactive { reported: true } => { return Poll::Pending; // nothing to do on this connection diff --git a/protocols/ping/src/protocol.rs b/protocols/ping/src/protocol.rs index 032b4aa0a0a..86d7137a77d 100644 --- a/protocols/ping/src/protocol.rs +++ b/protocols/ping/src/protocol.rs @@ -20,10 +20,11 @@ use futures::prelude::*; use instant::Instant; +use libp2p_core::upgrade::Protocol; use rand::{distributions, prelude::*}; use std::{io, time::Duration}; -pub const PROTOCOL_NAME: &[u8] = b"/ipfs/ping/1.0.0"; +pub const PROTOCOL_NAME: Protocol = Protocol::from_static("/ipfs/ping/1.0.0"); /// The `Ping` protocol upgrade. /// diff --git a/protocols/relay/src/protocol.rs b/protocols/relay/src/protocol.rs index 2c471d36dd9..9e23944d6da 100644 --- a/protocols/relay/src/protocol.rs +++ b/protocols/relay/src/protocol.rs @@ -19,14 +19,15 @@ // DEALINGS IN THE SOFTWARE. use crate::proto; +use libp2p_core::upgrade::Protocol; use std::time::Duration; pub(crate) mod inbound_hop; pub(crate) mod inbound_stop; pub(crate) mod outbound_hop; pub(crate) mod outbound_stop; -pub const HOP_PROTOCOL_NAME: &[u8; 31] = b"/libp2p/circuit/relay/0.2.0/hop"; -pub const STOP_PROTOCOL_NAME: &[u8; 32] = b"/libp2p/circuit/relay/0.2.0/stop"; +pub const HOP_PROTOCOL_NAME: Protocol = Protocol::from_static("/libp2p/circuit/relay/0.2.0/hop"); +pub const STOP_PROTOCOL_NAME: Protocol = Protocol::from_static("/libp2p/circuit/relay/0.2.0/stop"); const MAX_MESSAGE_SIZE: usize = 4096; diff --git a/protocols/relay/src/protocol/inbound_hop.rs b/protocols/relay/src/protocol/inbound_hop.rs index 485c3ef76bd..3a0692f88b9 100644 --- a/protocols/relay/src/protocol/inbound_hop.rs +++ b/protocols/relay/src/protocol/inbound_hop.rs @@ -24,7 +24,8 @@ use asynchronous_codec::{Framed, FramedParts}; use bytes::Bytes; use futures::{future::BoxFuture, prelude::*}; use instant::{Duration, SystemTime}; -use libp2p_core::{upgrade, Multiaddr}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{upgrade, Multiaddr, ToProtocolsIter}; use libp2p_identity::PeerId; use libp2p_swarm::NegotiatedSubstream; use std::convert::TryInto; @@ -37,11 +38,10 @@ pub struct Upgrade { pub max_circuit_bytes: u64, } -impl upgrade::UpgradeInfo for Upgrade { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Upgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(HOP_PROTOCOL_NAME) } } @@ -51,7 +51,7 @@ impl upgrade::InboundUpgrade for Upgrade { type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Protocol) -> Self::Future { let mut substream = Framed::new( substream, quick_protobuf_codec::Codec::new(MAX_MESSAGE_SIZE), diff --git a/protocols/relay/src/protocol/inbound_stop.rs b/protocols/relay/src/protocol/inbound_stop.rs index 67e4cdd5323..9f1e99a910d 100644 --- a/protocols/relay/src/protocol/inbound_stop.rs +++ b/protocols/relay/src/protocol/inbound_stop.rs @@ -23,7 +23,8 @@ use crate::protocol::{self, MAX_MESSAGE_SIZE, STOP_PROTOCOL_NAME}; use asynchronous_codec::{Framed, FramedParts}; use bytes::Bytes; use futures::{future::BoxFuture, prelude::*}; -use libp2p_core::upgrade; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{upgrade, ToProtocolsIter}; use libp2p_identity::PeerId; use libp2p_swarm::NegotiatedSubstream; use std::iter; @@ -31,11 +32,10 @@ use thiserror::Error; pub struct Upgrade {} -impl upgrade::UpgradeInfo for Upgrade { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Upgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(STOP_PROTOCOL_NAME) } } @@ -45,7 +45,7 @@ impl upgrade::InboundUpgrade for Upgrade { type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, substream: NegotiatedSubstream, _: Protocol) -> Self::Future { let mut substream = Framed::new( substream, quick_protobuf_codec::Codec::new(MAX_MESSAGE_SIZE), diff --git a/protocols/relay/src/protocol/outbound_hop.rs b/protocols/relay/src/protocol/outbound_hop.rs index 323d0be3b9a..5ac2bd94b47 100644 --- a/protocols/relay/src/protocol/outbound_hop.rs +++ b/protocols/relay/src/protocol/outbound_hop.rs @@ -25,7 +25,8 @@ use bytes::Bytes; use futures::{future::BoxFuture, prelude::*}; use futures_timer::Delay; use instant::{Duration, SystemTime}; -use libp2p_core::{upgrade, Multiaddr}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{upgrade, Multiaddr, ToProtocolsIter}; use libp2p_identity::PeerId; use libp2p_swarm::NegotiatedSubstream; use std::convert::TryFrom; @@ -37,11 +38,10 @@ pub enum Upgrade { Connect { dst_peer_id: PeerId }, } -impl upgrade::UpgradeInfo for Upgrade { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Upgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(HOP_PROTOCOL_NAME) } } @@ -51,7 +51,7 @@ impl upgrade::OutboundUpgrade for Upgrade { type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Protocol) -> Self::Future { let msg = match self { Upgrade::Reserve => proto::HopMessage { type_pb: proto::HopMessageType::RESERVE, diff --git a/protocols/relay/src/protocol/outbound_stop.rs b/protocols/relay/src/protocol/outbound_stop.rs index 9b028bc5b66..e3f168d165f 100644 --- a/protocols/relay/src/protocol/outbound_stop.rs +++ b/protocols/relay/src/protocol/outbound_stop.rs @@ -23,7 +23,8 @@ use crate::protocol::{MAX_MESSAGE_SIZE, STOP_PROTOCOL_NAME}; use asynchronous_codec::{Framed, FramedParts}; use bytes::Bytes; use futures::{future::BoxFuture, prelude::*}; -use libp2p_core::upgrade; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{upgrade, ToProtocolsIter}; use libp2p_identity::PeerId; use libp2p_swarm::NegotiatedSubstream; use std::convert::TryInto; @@ -37,11 +38,10 @@ pub struct Upgrade { pub max_circuit_bytes: u64, } -impl upgrade::UpgradeInfo for Upgrade { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for Upgrade { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { iter::once(STOP_PROTOCOL_NAME) } } @@ -51,7 +51,7 @@ impl upgrade::OutboundUpgrade for Upgrade { type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, substream: NegotiatedSubstream, _: Protocol) -> Self::Future { let msg = proto::StopMessage { type_pb: proto::StopMessageType::CONNECT, peer: Some(proto::Peer { diff --git a/protocols/relay/src/v2.rs b/protocols/relay/src/v2.rs index baaf148f2b5..819c1ef6930 100644 --- a/protocols/relay/src/v2.rs +++ b/protocols/relay/src/v2.rs @@ -155,17 +155,18 @@ pub mod protocol { )] pub type OutboundStopFatalUpgradeError = crate::outbound::stop::FatalUpgradeError; - #[deprecated( - since = "0.15.0", - note = "Use libp2p_relay::HOP_PROTOCOL_NAME instead." - )] - pub const HOP_PROTOCOL_NAME: &[u8; 31] = crate::HOP_PROTOCOL_NAME; - - #[deprecated( - since = "0.15.0", - note = "Use libp2p_relay::STOP_PROTOCOL_NAME instead." - )] - pub const STOP_PROTOCOL_NAME: &[u8; 32] = crate::STOP_PROTOCOL_NAME; + // TODO: Need to delete these before we can merge this PR. + // #[deprecated( + // since = "0.15.0", + // note = "Use libp2p_relay::HOP_PROTOCOL_NAME instead." + // )] + // pub const HOP_PROTOCOL_NAME: &[u8; 31] = crate::HOP_PROTOCOL_NAME; + + // #[deprecated( + // since = "0.15.0", + // note = "Use libp2p_relay::STOP_PROTOCOL_NAME instead." + // )] + // pub const STOP_PROTOCOL_NAME: &[u8; 32] = crate::STOP_PROTOCOL_NAME; } #[deprecated( diff --git a/protocols/rendezvous/src/handler.rs b/protocols/rendezvous/src/handler.rs index f69748a400b..724be72faa2 100644 --- a/protocols/rendezvous/src/handler.rs +++ b/protocols/rendezvous/src/handler.rs @@ -20,9 +20,10 @@ use crate::codec; use crate::codec::Message; +use libp2p_core::upgrade::Protocol; use void::Void; -const PROTOCOL_IDENT: &[u8] = b"/rendezvous/1.0.0"; +const PROTOCOL_IDENT: Protocol = Protocol::from_static("/rendezvous/1.0.0"); pub(crate) mod inbound; pub(crate) mod outbound; diff --git a/protocols/rendezvous/src/substream_handler.rs b/protocols/rendezvous/src/substream_handler.rs index f5f79451b09..caea835ce9f 100644 --- a/protocols/rendezvous/src/substream_handler.rs +++ b/protocols/rendezvous/src/substream_handler.rs @@ -28,7 +28,8 @@ use futures::future::{self, BoxFuture, Fuse, FusedFuture}; use futures::FutureExt; use instant::Instant; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_swarm::handler::{ConnectionEvent, FullyNegotiatedInbound, FullyNegotiatedOutbound}; use libp2p_swarm::{ ConnectionHandler, ConnectionHandlerEvent, KeepAlive, NegotiatedSubstream, SubstreamProtocol, @@ -127,21 +128,20 @@ impl fmt::Display for OutboundSubstreamId { } pub struct PassthroughProtocol { - ident: Option<&'static [u8]>, + ident: Option, } impl PassthroughProtocol { - pub fn new(ident: &'static [u8]) -> Self { + pub fn new(ident: Protocol) -> Self { Self { ident: Some(ident) } } } -impl UpgradeInfo for PassthroughProtocol { - type Info = &'static [u8]; - type InfoIter = std::option::IntoIter; +impl ToProtocolsIter for PassthroughProtocol { + type Iter = std::option::IntoIter; - fn protocol_info(&self) -> Self::InfoIter { - self.ident.into_iter() + fn to_protocols_iter(&self) -> Self::Iter { + self.ident.clone().into_iter() } } @@ -150,7 +150,7 @@ impl InboundUpgrade for PassthroughProtocol { type Error = Void; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: C, _: Protocol) -> Self::Future { match self.ident { Some(_) => future::ready(Ok(socket)).boxed(), None => future::pending().boxed(), @@ -163,7 +163,7 @@ impl OutboundUpgrade for PassthroughProtocol { type Error = Void; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: C, _: Protocol) -> Self::Future { match self.ident { Some(_) => future::ready(Ok(socket)).boxed(), None => future::pending().boxed(), diff --git a/protocols/request-response/src/codec.rs b/protocols/request-response/src/codec.rs index c5af967d0b9..2fd598da211 100644 --- a/protocols/request-response/src/codec.rs +++ b/protocols/request-response/src/codec.rs @@ -18,78 +18,16 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -pub use libp2p_core::ProtocolName; - use async_trait::async_trait; use futures::prelude::*; +use libp2p_core::upgrade::Protocol; use std::io; -/// A `RequestResponseCodec` defines the request and response types -/// for a request-response `Behaviour` protocol or -/// protocol family and how they are encoded / decoded on an I/O stream. -#[deprecated( - since = "0.24.0", - note = "Use re-exports that omit `RequestResponse` prefix, i.e. `libp2p::request_response::Codec`" -)] -#[async_trait] -pub trait RequestResponseCodec { - /// The type of protocol(s) or protocol versions being negotiated. - type Protocol: ProtocolName + Send + Clone; - /// The type of inbound and outbound requests. - type Request: Send; - /// The type of inbound and outbound responses. - type Response: Send; - - /// Reads a request from the given I/O stream according to the - /// negotiated protocol. - async fn read_request( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - ) -> io::Result - where - T: AsyncRead + Unpin + Send; - - /// Reads a response from the given I/O stream according to the - /// negotiated protocol. - async fn read_response( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - ) -> io::Result - where - T: AsyncRead + Unpin + Send; - - /// Writes a request to the given I/O stream according to the - /// negotiated protocol. - async fn write_request( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - req: Self::Request, - ) -> io::Result<()> - where - T: AsyncWrite + Unpin + Send; - - /// Writes a response to the given I/O stream according to the - /// negotiated protocol. - async fn write_response( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - res: Self::Response, - ) -> io::Result<()> - where - T: AsyncWrite + Unpin + Send; -} - /// A `Codec` defines the request and response types /// for a request-response [`Behaviour`](crate::Behaviour) protocol or /// protocol family and how they are encoded / decoded on an I/O stream. #[async_trait] -pub trait Codec { - /// The type of protocol(s) or protocol versions being negotiated. - type Protocol: ProtocolName + Send + Clone; +pub trait Codec: Send { /// The type of inbound and outbound requests. type Request: Send; /// The type of inbound and outbound responses. @@ -99,7 +37,7 @@ pub trait Codec { /// negotiated protocol. async fn read_request( &mut self, - protocol: &Self::Protocol, + protocol: &Protocol, io: &mut T, ) -> io::Result where @@ -109,7 +47,7 @@ pub trait Codec { /// negotiated protocol. async fn read_response( &mut self, - protocol: &Self::Protocol, + protocol: &Protocol, io: &mut T, ) -> io::Result where @@ -119,7 +57,7 @@ pub trait Codec { /// negotiated protocol. async fn write_request( &mut self, - protocol: &Self::Protocol, + protocol: &Protocol, io: &mut T, req: Self::Request, ) -> io::Result<()> @@ -130,70 +68,10 @@ pub trait Codec { /// negotiated protocol. async fn write_response( &mut self, - protocol: &Self::Protocol, + protocol: &Protocol, io: &mut T, res: Self::Response, ) -> io::Result<()> where T: AsyncWrite + Unpin + Send; } - -#[allow(deprecated)] -#[async_trait] -impl Codec for U -where - U: RequestResponseCodec + Send, - U::Protocol: Sync, -{ - type Protocol = U::Protocol; - - type Request = U::Request; - - type Response = U::Response; - - async fn read_request( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - ) -> io::Result - where - T: AsyncRead + Unpin + Send, - { - self.read_request(protocol, io).await - } - - async fn read_response( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - ) -> io::Result - where - T: AsyncRead + Unpin + Send, - { - self.read_response(protocol, io).await - } - - async fn write_request( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - req: Self::Request, - ) -> io::Result<()> - where - T: AsyncWrite + Unpin + Send, - { - self.write_request(protocol, io, req).await - } - - async fn write_response( - &mut self, - protocol: &Self::Protocol, - io: &mut T, - res: Self::Response, - ) -> io::Result<()> - where - T: AsyncWrite + Unpin + Send, - { - self.write_response(protocol, io, res).await - } -} diff --git a/protocols/request-response/src/handler.rs b/protocols/request-response/src/handler.rs index 50cd6adb055..978251504b9 100644 --- a/protocols/request-response/src/handler.rs +++ b/protocols/request-response/src/handler.rs @@ -31,7 +31,7 @@ pub use protocol::{ProtocolSupport, RequestProtocol, ResponseProtocol}; use futures::{channel::oneshot, future::BoxFuture, prelude::*, stream::FuturesUnordered}; use instant::Instant; -use libp2p_core::upgrade::{NegotiationError, UpgradeError}; +use libp2p_core::upgrade::{NegotiationError, Protocol, UpgradeError}; use libp2p_swarm::{ handler::{ConnectionHandler, ConnectionHandlerEvent, ConnectionHandlerUpgrErr, KeepAlive}, SubstreamProtocol, @@ -60,7 +60,7 @@ where TCodec: Codec, { /// The supported inbound protocols. - inbound_protocols: SmallVec<[TCodec::Protocol; 2]>, + inbound_protocols: SmallVec<[Protocol; 2]>, /// The request/response message codec. codec: TCodec, /// The keep-alive timeout of idle connections. A connection is considered @@ -98,7 +98,7 @@ where TCodec: Codec + Send + Clone + 'static, { pub(super) fn new( - inbound_protocols: SmallVec<[TCodec::Protocol; 2]>, + inbound_protocols: SmallVec<[Protocol; 2]>, codec: TCodec, keep_alive_timeout: Duration, substream_timeout: Duration, diff --git a/protocols/request-response/src/handler/protocol.rs b/protocols/request-response/src/handler/protocol.rs index 84ef365734f..900460fed90 100644 --- a/protocols/request-response/src/handler/protocol.rs +++ b/protocols/request-response/src/handler/protocol.rs @@ -27,7 +27,8 @@ use crate::codec::Codec; use crate::RequestId; use futures::{channel::oneshot, future::BoxFuture, prelude::*}; -use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, Protocol}; +use libp2p_core::ToProtocolsIter; use libp2p_swarm::NegotiatedSubstream; use smallvec::SmallVec; use std::{fmt, io}; @@ -70,20 +71,19 @@ where TCodec: Codec, { pub(crate) codec: TCodec, - pub(crate) protocols: SmallVec<[TCodec::Protocol; 2]>, + pub(crate) protocols: SmallVec<[Protocol; 2]>, pub(crate) request_sender: oneshot::Sender<(RequestId, TCodec::Request)>, pub(crate) response_receiver: oneshot::Receiver, pub(crate) request_id: RequestId, } -impl UpgradeInfo for ResponseProtocol +impl ToProtocolsIter for ResponseProtocol where TCodec: Codec, { - type Info = TCodec::Protocol; - type InfoIter = smallvec::IntoIter<[Self::Info; 2]>; + type Iter = smallvec::IntoIter<[Protocol; 2]>; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { self.protocols.clone().into_iter() } } @@ -96,11 +96,7 @@ where type Error = io::Error; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound( - mut self, - mut io: NegotiatedSubstream, - protocol: Self::Info, - ) -> Self::Future { + fn upgrade_inbound(mut self, mut io: NegotiatedSubstream, protocol: Protocol) -> Self::Future { async move { let read = self.codec.read_request(&protocol, &mut io); let request = read.await?; @@ -135,7 +131,7 @@ where TCodec: Codec, { pub(crate) codec: TCodec, - pub(crate) protocols: SmallVec<[TCodec::Protocol; 2]>, + pub(crate) protocols: SmallVec<[Protocol; 2]>, pub(crate) request_id: RequestId, pub(crate) request: TCodec::Request, } @@ -151,14 +147,13 @@ where } } -impl UpgradeInfo for RequestProtocol +impl ToProtocolsIter for RequestProtocol where TCodec: Codec, { - type Info = TCodec::Protocol; - type InfoIter = smallvec::IntoIter<[Self::Info; 2]>; + type Iter = smallvec::IntoIter<[Protocol; 2]>; - fn protocol_info(&self) -> Self::InfoIter { + fn to_protocols_iter(&self) -> Self::Iter { self.protocols.clone().into_iter() } } @@ -171,11 +166,7 @@ where type Error = io::Error; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound( - mut self, - mut io: NegotiatedSubstream, - protocol: Self::Info, - ) -> Self::Future { + fn upgrade_outbound(mut self, mut io: NegotiatedSubstream, protocol: Protocol) -> Self::Future { async move { let write = self.codec.write_request(&protocol, &mut io, self.request); write.await?; diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index d9f2220d839..378ee314d1d 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -43,8 +43,8 @@ //! //! A single [`Behaviour`] instance can be used with an entire //! protocol family that share the same request and response types. -//! For that purpose, [`Codec::Protocol`] is typically -//! instantiated with a sum type. +//! For that purpose, pass a list of protocols into the constructor +//! instead of a single one. //! //! ## Limited Protocol Support //! @@ -61,15 +61,13 @@ pub mod codec; pub mod handler; -pub use codec::{Codec, ProtocolName}; - -#[allow(deprecated)] -pub use codec::RequestResponseCodec; +pub use codec::Codec; pub use handler::ProtocolSupport; use futures::channel::oneshot; use handler::{Handler, RequestProtocol}; +use libp2p_core::upgrade::Protocol; use libp2p_core::{ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_swarm::{ @@ -338,9 +336,9 @@ where TCodec: Codec + Clone + Send + 'static, { /// The supported inbound protocols. - inbound_protocols: SmallVec<[TCodec::Protocol; 2]>, + inbound_protocols: SmallVec<[Protocol; 2]>, /// The supported outbound protocols. - outbound_protocols: SmallVec<[TCodec::Protocol; 2]>, + outbound_protocols: SmallVec<[Protocol; 2]>, /// The next (local) request ID. next_request_id: RequestId, /// The next (inbound) request ID. @@ -370,7 +368,7 @@ where /// protocols, codec and configuration. pub fn new(codec: TCodec, protocols: I, cfg: Config) -> Self where - I: IntoIterator, + I: IntoIterator, { let mut inbound_protocols = SmallVec::new(); let mut outbound_protocols = SmallVec::new(); diff --git a/protocols/request-response/tests/ping.rs b/protocols/request-response/tests/ping.rs index c69f771dbe0..cc21dfdd1d6 100644 --- a/protocols/request-response/tests/ping.rs +++ b/protocols/request-response/tests/ping.rs @@ -22,10 +22,8 @@ use async_trait::async_trait; use futures::{prelude::*, AsyncWriteExt}; -use libp2p_core::{ - upgrade::{read_length_prefixed, write_length_prefixed}, - ProtocolName, -}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::upgrade::{read_length_prefixed, write_length_prefixed}; use libp2p_identity::PeerId; use libp2p_request_response as request_response; use libp2p_request_response::ProtocolSupport; @@ -40,7 +38,7 @@ async fn is_response_outbound() { let ping = Ping("ping".to_string().into_bytes()); let offline_peer = PeerId::random(); - let protocols = iter::once((PingProtocol(), request_response::ProtocolSupport::Full)); + let protocols = iter::once((PING_PROTOCOL, request_response::ProtocolSupport::Full)); let cfg = request_response::Config::default(); let mut swarm1 = @@ -83,7 +81,7 @@ async fn ping_protocol() { let ping = Ping("ping".to_string().into_bytes()); let pong = Pong("pong".to_string().into_bytes()); - let protocols = iter::once((PingProtocol(), ProtocolSupport::Full)); + let protocols = iter::once((PING_PROTOCOL, ProtocolSupport::Full)); let cfg = request_response::Config::default(); let mut swarm1 = Swarm::new_ephemeral(|_| { @@ -174,7 +172,7 @@ async fn ping_protocol() { async fn emits_inbound_connection_closed_failure() { let ping = Ping("ping".to_string().into_bytes()); - let protocols = iter::once((PingProtocol(), ProtocolSupport::Full)); + let protocols = iter::once((PING_PROTOCOL, ProtocolSupport::Full)); let cfg = request_response::Config::default(); let mut swarm1 = Swarm::new_ephemeral(|_| { @@ -237,7 +235,7 @@ async fn emits_inbound_connection_closed_failure() { async fn emits_inbound_connection_closed_if_channel_is_dropped() { let ping = Ping("ping".to_string().into_bytes()); - let protocols = iter::once((PingProtocol(), ProtocolSupport::Full)); + let protocols = iter::once((PING_PROTOCOL, ProtocolSupport::Full)); let cfg = request_response::Config::default(); let mut swarm1 = Swarm::new_ephemeral(|_| { @@ -286,8 +284,6 @@ async fn emits_inbound_connection_closed_if_channel_is_dropped() { // Simple Ping-Pong Protocol -#[derive(Debug, Clone)] -struct PingProtocol(); #[derive(Clone)] struct PingCodec(); #[derive(Debug, Clone, PartialEq, Eq)] @@ -295,19 +291,14 @@ struct Ping(Vec); #[derive(Debug, Clone, PartialEq, Eq)] struct Pong(Vec); -impl ProtocolName for PingProtocol { - fn protocol_name(&self) -> &[u8] { - "/ping/1".as_bytes() - } -} +const PING_PROTOCOL: Protocol = Protocol::from_static("/ping/1"); #[async_trait] impl libp2p_request_response::Codec for PingCodec { - type Protocol = PingProtocol; type Request = Ping; type Response = Pong; - async fn read_request(&mut self, _: &PingProtocol, io: &mut T) -> io::Result + async fn read_request(&mut self, _: &Protocol, io: &mut T) -> io::Result where T: AsyncRead + Unpin + Send, { @@ -320,7 +311,7 @@ impl libp2p_request_response::Codec for PingCodec { Ok(Ping(vec)) } - async fn read_response(&mut self, _: &PingProtocol, io: &mut T) -> io::Result + async fn read_response(&mut self, _: &Protocol, io: &mut T) -> io::Result where T: AsyncRead + Unpin + Send, { @@ -335,7 +326,7 @@ impl libp2p_request_response::Codec for PingCodec { async fn write_request( &mut self, - _: &PingProtocol, + _: &Protocol, io: &mut T, Ping(data): Ping, ) -> io::Result<()> @@ -350,7 +341,7 @@ impl libp2p_request_response::Codec for PingCodec { async fn write_response( &mut self, - _: &PingProtocol, + _: &Protocol, io: &mut T, Pong(data): Pong, ) -> io::Result<()> diff --git a/swarm/src/handler.rs b/swarm/src/handler.rs index 1917117c44e..ea7e00216d6 100644 --- a/swarm/src/handler.rs +++ b/swarm/src/handler.rs @@ -46,7 +46,7 @@ mod one_shot; mod pending; mod select; -pub use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper, UpgradeInfoSend}; +pub use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, SendWrapper}; use instant::Instant; use libp2p_core::{upgrade::UpgradeError, ConnectedPoint, Multiaddr}; diff --git a/swarm/src/handler/multi.rs b/swarm/src/handler/multi.rs index 146a2a96895..13a28aa3b00 100644 --- a/swarm/src/handler/multi.rs +++ b/swarm/src/handler/multi.rs @@ -28,10 +28,12 @@ use crate::handler::{ ConnectionHandlerUpgrErr, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, ListenUpgradeError, SubstreamProtocol, }; -use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend, UpgradeInfoSend}; +use crate::upgrade::{InboundUpgradeSend, OutboundUpgradeSend}; use crate::NegotiatedSubstream; use futures::{future::BoxFuture, prelude::*}; -use libp2p_core::upgrade::{NegotiationError, ProtocolError, ProtocolName, UpgradeError}; +use libp2p_core::upgrade::{ + NegotiationError, Protocol, ProtocolError, ToProtocolsIter, UpgradeError, +}; use libp2p_core::ConnectedPoint; use libp2p_identity::PeerId; use rand::Rng; @@ -41,7 +43,7 @@ use std::{ error, fmt::{self, Debug}, hash::Hash, - iter::{self, FromIterator}, + iter::FromIterator, task::{Context, Poll}, time::Duration, }; @@ -68,6 +70,8 @@ impl MultiHandler where K: Clone + Debug + Hash + Eq + Send + 'static, H: ConnectionHandler, + H::InboundProtocol: Clone, + H::OutboundProtocol: Clone, { /// Create and populate a `MultiHandler` from the given handler iterator. /// @@ -82,7 +86,7 @@ where uniq_proto_names( m.handlers .values() - .map(|h| h.listen_protocol().into_upgrade().0), + .flat_map(|h| h.listen_protocol().upgrade.to_protocols_iter()), )?; Ok(m) } @@ -220,8 +224,8 @@ impl ConnectionHandler for MultiHandler where K: Clone + Debug + Hash + Eq + Send + 'static, H: ConnectionHandler, - H::InboundProtocol: InboundUpgradeSend, - H::OutboundProtocol: OutboundUpgradeSend, + H::InboundProtocol: InboundUpgradeSend + Clone, + H::OutboundProtocol: OutboundUpgradeSend + Clone, { type InEvent = (K, ::InEvent); type OutEvent = (K, ::OutEvent); @@ -425,7 +429,11 @@ where let m = IntoMultiHandler { handlers: HashMap::from_iter(iter), }; - uniq_proto_names(m.handlers.values().map(|h| h.inbound_protocol()))?; + uniq_proto_names( + m.handlers + .values() + .flat_map(|h| h.inbound_protocol().to_protocols_iter()), + )?; Ok(m) } } @@ -435,6 +443,8 @@ impl IntoConnectionHandler for IntoMultiHandler where K: Debug + Clone + Eq + Hash + Send + 'static, H: IntoConnectionHandler, + <::Handler as ConnectionHandler>::InboundProtocol: Clone, + <::Handler as ConnectionHandler>::OutboundProtocol: Clone, { type Handler = MultiHandler; @@ -459,16 +469,6 @@ where } } -/// Index and protocol name pair used as `UpgradeInfo::Info`. -#[derive(Debug, Clone)] -pub struct IndexedProtoName(usize, H); - -impl ProtocolName for IndexedProtoName { - fn protocol_name(&self) -> &[u8] { - self.1.protocol_name() - } -} - /// The aggregated `InboundOpenInfo`s of supported inbound substream protocols. #[derive(Clone)] pub struct Info { @@ -514,39 +514,46 @@ where } } -impl UpgradeInfoSend for Upgrade +impl ToProtocolsIter for Upgrade where - H: UpgradeInfoSend, - K: Send + 'static, + H: Clone + ToProtocolsIter + Send + 'static, + K: Clone + Send + 'static, { - type Info = IndexedProtoName; - type InfoIter = std::vec::IntoIter; + type Iter = Box + Send + 'static>; - fn protocol_info(&self) -> Self::InfoIter { - self.upgrades - .iter() - .enumerate() - .flat_map(|(i, (_, h))| iter::repeat(i).zip(h.protocol_info())) - .map(|(i, h)| IndexedProtoName(i, h)) - .collect::>() - .into_iter() + fn to_protocols_iter(&self) -> Self::Iter { + Box::new( + self.upgrades + .clone() + .into_iter() + .flat_map(|(_, u)| u.to_protocols_iter()), + ) } } impl InboundUpgradeSend for Upgrade where - H: InboundUpgradeSend, - K: Send + 'static, + H: Clone + InboundUpgradeSend + 'static, + K: Clone + Send + 'static, { type Output = (K, ::Output); type Error = (K, ::Error); type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(mut self, resource: NegotiatedSubstream, info: Self::Info) -> Self::Future { - let IndexedProtoName(index, info) = info; + fn upgrade_inbound( + mut self, + resource: NegotiatedSubstream, + selected_protocol: Protocol, + ) -> Self::Future { + let index = self + .upgrades + .iter() + .position(|(_, h)| h.to_protocols_iter().any(|p| p == selected_protocol)) + .expect("at least one upgrade must contain the selected protocol"); let (key, upgrade) = self.upgrades.remove(index); + upgrade - .upgrade_inbound(resource, info) + .upgrade_inbound(resource, selected_protocol) .map(move |out| match out { Ok(o) => Ok((key, o)), Err(e) => Err((key, e)), @@ -557,18 +564,27 @@ where impl OutboundUpgradeSend for Upgrade where - H: OutboundUpgradeSend, - K: Send + 'static, + H: Clone + OutboundUpgradeSend + 'static, + K: Clone + Send + 'static, { type Output = (K, ::Output); type Error = (K, ::Error); type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(mut self, resource: NegotiatedSubstream, info: Self::Info) -> Self::Future { - let IndexedProtoName(index, info) = info; + fn upgrade_outbound( + mut self, + resource: NegotiatedSubstream, + selected_protocol: Protocol, + ) -> Self::Future { + let index = self + .upgrades + .iter() + .position(|(_, h)| h.to_protocols_iter().any(|p| p == selected_protocol)) + .expect("at least one upgrade must contain the selected protocol"); let (key, upgrade) = self.upgrades.remove(index); + upgrade - .upgrade_outbound(resource, info) + .upgrade_outbound(resource, selected_protocol) .map(move |out| match out { Ok(o) => Ok((key, o)), Err(e) => Err((key, e)), @@ -578,20 +594,16 @@ where } /// Check that no two protocol names are equal. -fn uniq_proto_names(iter: I) -> Result<(), DuplicateProtonameError> +fn uniq_proto_names(iter: I) -> Result<(), DuplicateProtonameError> where - I: Iterator, - T: UpgradeInfoSend, + I: Iterator, { let mut set = HashSet::new(); - for infos in iter { - for i in infos.protocol_info() { - let v = Vec::from(i.protocol_name()); - if set.contains(&v) { - return Err(DuplicateProtonameError(v)); - } else { - set.insert(v); - } + for p in iter { + if set.contains(&p) { + return Err(DuplicateProtonameError(p)); + } else { + set.insert(p); } } Ok(()) @@ -599,22 +611,18 @@ where /// It is an error if two handlers share the same protocol name. #[derive(Debug, Clone)] -pub struct DuplicateProtonameError(Vec); +pub struct DuplicateProtonameError(Protocol); impl DuplicateProtonameError { /// The protocol name bytes that occured in more than one handler. pub fn protocol_name(&self) -> &[u8] { - &self.0 + self.0.as_str().as_bytes() } } impl fmt::Display for DuplicateProtonameError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Ok(s) = std::str::from_utf8(&self.0) { - write!(f, "duplicate protocol name: {s}") - } else { - write!(f, "duplicate protocol name: {:?}", self.0) - } + write!(f, "duplicate protocol name: {}", self.0) } } diff --git a/swarm/src/handler/one_shot.rs b/swarm/src/handler/one_shot.rs index 29ba45ab678..8705d5f0dc6 100644 --- a/swarm/src/handler/one_shot.rs +++ b/swarm/src/handler/one_shot.rs @@ -114,7 +114,7 @@ where impl ConnectionHandler for OneShotHandler where TInbound: InboundUpgradeSend + Send + 'static, - TOutbound: Debug + OutboundUpgradeSend, + TOutbound: Debug + OutboundUpgradeSend + 'static, TInbound::Output: Into, TOutbound::Output: Into, TOutbound::Error: error::Error + Send + 'static, diff --git a/swarm/src/handler/pending.rs b/swarm/src/handler/pending.rs index a39e498c3f2..db2c184a30d 100644 --- a/swarm/src/handler/pending.rs +++ b/swarm/src/handler/pending.rs @@ -23,18 +23,18 @@ use crate::handler::{ ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound, FullyNegotiatedOutbound, KeepAlive, SubstreamProtocol, }; -use libp2p_core::upgrade::PendingUpgrade; +use libp2p_core::upgrade::{PendingUpgrade, Protocol}; use std::task::{Context, Poll}; use void::Void; /// Implementation of [`ConnectionHandler`] that returns a pending upgrade. #[derive(Clone, Debug)] pub struct PendingConnectionHandler { - protocol_name: String, + protocol_name: Protocol, } impl PendingConnectionHandler { - pub fn new(protocol_name: String) -> Self { + pub fn new(protocol_name: Protocol) -> Self { PendingConnectionHandler { protocol_name } } } @@ -43,8 +43,8 @@ impl ConnectionHandler for PendingConnectionHandler { type InEvent = Void; type OutEvent = Void; type Error = Void; - type InboundProtocol = PendingUpgrade; - type OutboundProtocol = PendingUpgrade; + type InboundProtocol = PendingUpgrade; + type OutboundProtocol = PendingUpgrade; type OutboundOpenInfo = Void; type InboundOpenInfo = (); diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 3fba83cd44d..62a9938df49 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -127,11 +127,11 @@ pub use handler::{ IntoConnectionHandlerSelect, KeepAlive, OneShotHandler, OneShotHandlerConfig, SubstreamProtocol, }; +pub use libp2p_core::upgrade::Protocol; #[cfg(feature = "macros")] pub use libp2p_swarm_derive::NetworkBehaviour; pub use registry::{AddAddressResult, AddressRecord, AddressScore}; -use crate::handler::UpgradeInfoSend; use connection::pool::{EstablishedConnection, Pool, PoolConfig, PoolEvent}; use connection::IncomingInfo; use connection::{ @@ -140,13 +140,14 @@ use connection::{ use dial_opts::{DialOpts, PeerCondition}; use futures::{executor::ThreadPoolBuilder, prelude::*, stream::FusedStream}; use libp2p_core::muxing::SubstreamBox; +use libp2p_core::upgrade::ToProtocolsIter; use libp2p_core::{ connection::ConnectedPoint, - multiaddr::Protocol, + multiaddr, multihash::Multihash, muxing::StreamMuxerBox, transport::{self, ListenerId, TransportError, TransportEvent}, - Endpoint, Multiaddr, Negotiated, ProtocolName, Transport, + Endpoint, Multiaddr, Negotiated, Transport, }; use libp2p_identity::PeerId; use registry::{AddressIntoIter, Addresses}; @@ -882,12 +883,7 @@ where } }; - let supported_protocols = handler - .listen_protocol() - .upgrade() - .protocol_info() - .map(|p| p.protocol_name().to_owned()) - .collect(); + let supported_protocols = handler.listen_protocol().upgrade().to_protocols_iter(); let other_established_connection_ids = self .pool .iter_established_connections_of_peer(&peer_id) @@ -925,7 +921,9 @@ where other_established: other_established_connection_ids.len(), }, )); - self.supported_protocols = supported_protocols; + self.supported_protocols = supported_protocols + .map(|p| p.as_str().as_bytes().to_vec()) // TODO: Don't do this. + .collect(); return Some(SwarmEvent::ConnectionEstablished { peer_id, num_established, @@ -2015,13 +2013,13 @@ fn p2p_addr(peer: Option, addr: Multiaddr) -> Result return Ok(addr), }; - if let Some(Protocol::P2p(hash)) = addr.iter().last() { + if let Some(multiaddr::Protocol::P2p(hash)) = addr.iter().last() { if &hash != peer.as_ref() { return Err(addr); } Ok(addr) } else { - Ok(addr.with(Protocol::P2p(peer.into()))) + Ok(addr.with(multiaddr::Protocol::P2p(peer.into()))) } } @@ -2728,7 +2726,7 @@ mod tests { })); let other_id = PeerId::random(); - let other_addr = address.with(Protocol::P2p(other_id.into())); + let other_addr = address.with(multiaddr::Protocol::P2p(other_id.into())); swarm2.dial(other_addr.clone()).unwrap(); @@ -2876,7 +2874,7 @@ mod tests { let failed_addresses = errors.into_iter().map(|(addr, _)| addr).collect::>(); let expected_addresses = addresses .into_iter() - .map(|addr| addr.with(Protocol::P2p(target.into()))) + .map(|addr| addr.with(multiaddr::Protocol::P2p(target.into()))) .collect::>(); assert_eq!(expected_addresses, failed_addresses); diff --git a/swarm/src/upgrade.rs b/swarm/src/upgrade.rs index e544ac3f27f..bcb06be217d 100644 --- a/swarm/src/upgrade.rs +++ b/swarm/src/upgrade.rs @@ -18,46 +18,18 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::NegotiatedSubstream; +use crate::{NegotiatedSubstream, Protocol}; use futures::prelude::*; use libp2p_core::upgrade; - -/// Implemented automatically on all types that implement [`UpgradeInfo`](upgrade::UpgradeInfo) -/// and `Send + 'static`. -/// -/// Do not implement this trait yourself. Instead, please implement -/// [`UpgradeInfo`](upgrade::UpgradeInfo). -pub trait UpgradeInfoSend: Send + 'static { - /// Equivalent to [`UpgradeInfo::Info`](upgrade::UpgradeInfo::Info). - type Info: upgrade::ProtocolName + Clone + Send + 'static; - /// Equivalent to [`UpgradeInfo::InfoIter`](upgrade::UpgradeInfo::InfoIter). - type InfoIter: Iterator + Send + 'static; - - /// Equivalent to [`UpgradeInfo::protocol_info`](upgrade::UpgradeInfo::protocol_info). - fn protocol_info(&self) -> Self::InfoIter; -} - -impl UpgradeInfoSend for T -where - T: upgrade::UpgradeInfo + Send + 'static, - T::Info: Send + 'static, - ::IntoIter: Send + 'static, -{ - type Info = T::Info; - type InfoIter = ::IntoIter; - - fn protocol_info(&self) -> Self::InfoIter { - upgrade::UpgradeInfo::protocol_info(self).into_iter() - } -} +use libp2p_core::upgrade::ToProtocolsIter; /// Implemented automatically on all types that implement /// [`OutboundUpgrade`](upgrade::OutboundUpgrade) and `Send + 'static`. /// /// Do not implement this trait yourself. Instead, please implement /// [`OutboundUpgrade`](upgrade::OutboundUpgrade). -pub trait OutboundUpgradeSend: UpgradeInfoSend { +pub trait OutboundUpgradeSend: ToProtocolsIter + Send { /// Equivalent to [`OutboundUpgrade::Output`](upgrade::OutboundUpgrade::Output). type Output: Send + 'static; /// Equivalent to [`OutboundUpgrade::Error`](upgrade::OutboundUpgrade::Error). @@ -66,13 +38,16 @@ pub trait OutboundUpgradeSend: UpgradeInfoSend { type Future: Future> + Send + 'static; /// Equivalent to [`OutboundUpgrade::upgrade_outbound`](upgrade::OutboundUpgrade::upgrade_outbound). - fn upgrade_outbound(self, socket: NegotiatedSubstream, info: Self::Info) -> Self::Future; + fn upgrade_outbound( + self, + socket: NegotiatedSubstream, + selected_protocol: Protocol, + ) -> Self::Future; } -impl OutboundUpgradeSend for T +impl OutboundUpgradeSend for T where - T: upgrade::OutboundUpgrade + UpgradeInfoSend, - TInfo: upgrade::ProtocolName + Clone + Send + 'static, + T: upgrade::OutboundUpgrade + Send, T::Output: Send + 'static, T::Error: Send + 'static, T::Future: Send + 'static, @@ -81,8 +56,12 @@ where type Error = T::Error; type Future = T::Future; - fn upgrade_outbound(self, socket: NegotiatedSubstream, info: TInfo) -> Self::Future { - upgrade::OutboundUpgrade::upgrade_outbound(self, socket, info) + fn upgrade_outbound( + self, + socket: NegotiatedSubstream, + selected_protocol: Protocol, + ) -> Self::Future { + upgrade::OutboundUpgrade::upgrade_outbound(self, socket, selected_protocol) } } @@ -91,7 +70,7 @@ where /// /// Do not implement this trait yourself. Instead, please implement /// [`InboundUpgrade`](upgrade::InboundUpgrade). -pub trait InboundUpgradeSend: UpgradeInfoSend { +pub trait InboundUpgradeSend: ToProtocolsIter + Send { /// Equivalent to [`InboundUpgrade::Output`](upgrade::InboundUpgrade::Output). type Output: Send + 'static; /// Equivalent to [`InboundUpgrade::Error`](upgrade::InboundUpgrade::Error). @@ -100,13 +79,16 @@ pub trait InboundUpgradeSend: UpgradeInfoSend { type Future: Future> + Send + 'static; /// Equivalent to [`InboundUpgrade::upgrade_inbound`](upgrade::InboundUpgrade::upgrade_inbound). - fn upgrade_inbound(self, socket: NegotiatedSubstream, info: Self::Info) -> Self::Future; + fn upgrade_inbound( + self, + socket: NegotiatedSubstream, + selected_protocol: Protocol, + ) -> Self::Future; } -impl InboundUpgradeSend for T +impl InboundUpgradeSend for T where - T: upgrade::InboundUpgrade + UpgradeInfoSend, - TInfo: upgrade::ProtocolName + Clone + Send + 'static, + T: upgrade::InboundUpgrade + Send, T::Output: Send + 'static, T::Error: Send + 'static, T::Future: Send + 'static, @@ -115,8 +97,12 @@ where type Error = T::Error; type Future = T::Future; - fn upgrade_inbound(self, socket: NegotiatedSubstream, info: TInfo) -> Self::Future { - upgrade::InboundUpgrade::upgrade_inbound(self, socket, info) + fn upgrade_inbound( + self, + socket: NegotiatedSubstream, + selected_protocol: Protocol, + ) -> Self::Future { + upgrade::InboundUpgrade::upgrade_inbound(self, socket, selected_protocol) } } @@ -128,12 +114,11 @@ where /// > doesn't need to be used directly. pub struct SendWrapper(pub T); -impl upgrade::UpgradeInfo for SendWrapper { - type Info = T::Info; - type InfoIter = T::InfoIter; +impl upgrade::ToProtocolsIter for SendWrapper { + type Iter = T::Iter; - fn protocol_info(&self) -> Self::InfoIter { - UpgradeInfoSend::protocol_info(&self.0) + fn to_protocols_iter(&self) -> Self::Iter { + self.0.to_protocols_iter() } } @@ -142,7 +127,7 @@ impl upgrade::OutboundUpgrade for S type Error = T::Error; type Future = T::Future; - fn upgrade_outbound(self, socket: NegotiatedSubstream, info: T::Info) -> Self::Future { + fn upgrade_outbound(self, socket: NegotiatedSubstream, info: Protocol) -> Self::Future { OutboundUpgradeSend::upgrade_outbound(self.0, socket, info) } } @@ -152,7 +137,7 @@ impl upgrade::InboundUpgrade for Sen type Error = T::Error; type Future = T::Future; - fn upgrade_inbound(self, socket: NegotiatedSubstream, info: T::Info) -> Self::Future { + fn upgrade_inbound(self, socket: NegotiatedSubstream, info: Protocol) -> Self::Future { InboundUpgradeSend::upgrade_inbound(self.0, socket, info) } } diff --git a/transports/deflate/src/lib.rs b/transports/deflate/src/lib.rs index 29be83462b9..adea9aa1618 100644 --- a/transports/deflate/src/lib.rs +++ b/transports/deflate/src/lib.rs @@ -21,7 +21,8 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] use futures::{prelude::*, ready}; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use std::{io, iter, pin::Pin, task::Context, task::Poll}; #[derive(Debug, Copy, Clone)] @@ -37,12 +38,11 @@ impl Default for DeflateConfig { } } -impl UpgradeInfo for DeflateConfig { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for DeflateConfig { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - iter::once(b"/deflate/1.0.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(Protocol::from_static("/deflate/1.0.0")) } } @@ -54,7 +54,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_inbound(self, r: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, r: C, _: Protocol) -> Self::Future { future::ok(DeflateOutput::new(r, self.compression)) } } @@ -67,7 +67,7 @@ where type Error = io::Error; type Future = future::Ready>; - fn upgrade_outbound(self, w: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, w: C, _: Protocol) -> Self::Future { future::ok(DeflateOutput::new(w, self.compression)) } } diff --git a/transports/noise/src/lib.rs b/transports/noise/src/lib.rs index c1c120f38a6..f0fcd533e37 100644 --- a/transports/noise/src/lib.rs +++ b/transports/noise/src/lib.rs @@ -72,7 +72,7 @@ use crate::handshake::State; use crate::io::handshake; use futures::future::BoxFuture; use futures::prelude::*; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_identity as identity; use libp2p_identity::PeerId; use std::pin::Pin; @@ -320,7 +320,7 @@ impl From for NoiseError { /// ``` impl InboundUpgrade for NoiseConfig where - NoiseConfig: UpgradeInfo, + NoiseConfig: ToProtocolsIter, T: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: Protocol + AsRef<[u8]> + Zeroize + Clone + Send + 'static, { @@ -328,7 +328,7 @@ where type Error = NoiseError; type Future = BoxFuture<'static, Result<(RemoteIdentity, NoiseOutput), NoiseError>>; - fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: T, _: libp2p_core::upgrade::Protocol) -> Self::Future { async move { let mut state = self.into_responder(socket)?; @@ -351,7 +351,7 @@ where /// ``` impl OutboundUpgrade for NoiseConfig where - NoiseConfig: UpgradeInfo, + NoiseConfig: ToProtocolsIter, T: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: Protocol + AsRef<[u8]> + Zeroize + Clone + Send + 'static, { @@ -359,7 +359,7 @@ where type Error = NoiseError; type Future = BoxFuture<'static, Result<(RemoteIdentity, NoiseOutput), NoiseError>>; - fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: T, _: libp2p_core::upgrade::Protocol) -> Self::Future { async move { let mut state = self.into_initiator(socket)?; @@ -386,7 +386,7 @@ where /// ``` impl InboundUpgrade for NoiseConfig where - NoiseConfig: UpgradeInfo, + NoiseConfig: ToProtocolsIter, T: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: Protocol + AsRef<[u8]> + Zeroize + Clone + Send + 'static, { @@ -394,7 +394,7 @@ where type Error = NoiseError; type Future = BoxFuture<'static, Result<(RemoteIdentity, NoiseOutput), NoiseError>>; - fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: T, _: libp2p_core::upgrade::Protocol) -> Self::Future { async move { let mut state = self.into_responder(socket)?; @@ -422,7 +422,7 @@ where /// ``` impl OutboundUpgrade for NoiseConfig where - NoiseConfig: UpgradeInfo, + NoiseConfig: ToProtocolsIter, T: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: Protocol + AsRef<[u8]> + Zeroize + Clone + Send + 'static, { @@ -430,7 +430,7 @@ where type Error = NoiseError; type Future = BoxFuture<'static, Result<(RemoteIdentity, NoiseOutput), NoiseError>>; - fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: T, _: libp2p_core::upgrade::Protocol) -> Self::Future { async move { let mut state = self.into_initiator(socket)?; @@ -457,7 +457,7 @@ where /// ``` impl InboundUpgrade for NoiseConfig where - NoiseConfig: UpgradeInfo, + NoiseConfig: ToProtocolsIter, T: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: Protocol + AsRef<[u8]> + Zeroize + Clone + Send + 'static, { @@ -465,7 +465,7 @@ where type Error = NoiseError; type Future = BoxFuture<'static, Result<(RemoteIdentity, NoiseOutput), NoiseError>>; - fn upgrade_inbound(self, socket: T, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: T, _: libp2p_core::upgrade::Protocol) -> Self::Future { async move { let mut state = self.into_responder(socket)?; @@ -491,7 +491,7 @@ where /// ``` impl OutboundUpgrade for NoiseConfig, identity::PublicKey)> where - NoiseConfig, identity::PublicKey)>: UpgradeInfo, + NoiseConfig, identity::PublicKey)>: ToProtocolsIter, T: AsyncRead + AsyncWrite + Unpin + Send + 'static, C: Protocol + AsRef<[u8]> + Zeroize + Clone + Send + 'static, { @@ -499,7 +499,7 @@ where type Error = NoiseError; type Future = BoxFuture<'static, Result<(RemoteIdentity, NoiseOutput), NoiseError>>; - fn upgrade_outbound(self, socket: T, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: T, _: libp2p_core::upgrade::Protocol) -> Self::Future { async move { let mut state = self.into_initiator(socket)?; @@ -542,21 +542,21 @@ impl NoiseAuthenticated { } } -impl UpgradeInfo for NoiseAuthenticated +impl ToProtocolsIter for NoiseAuthenticated where - NoiseConfig: UpgradeInfo, + NoiseConfig: ToProtocolsIter, + C: Zeroize, { - type Info = as UpgradeInfo>::Info; - type InfoIter = as UpgradeInfo>::InfoIter; + type Iter = as ToProtocolsIter>::Iter; - fn protocol_info(&self) -> Self::InfoIter { - self.config.protocol_info() + fn to_protocols_iter(&self) -> Self::Iter { + self.config.to_protocols_iter() } } impl InboundUpgrade for NoiseAuthenticated where - NoiseConfig: UpgradeInfo + NoiseConfig: ToProtocolsIter + InboundUpgrade, NoiseOutput), Error = NoiseError> + 'static, as InboundUpgrade>::Future: Send, @@ -567,7 +567,7 @@ where type Error = NoiseError; type Future = Pin> + Send>>; - fn upgrade_inbound(self, socket: T, info: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: T, info: libp2p_core::upgrade::Protocol) -> Self::Future { Box::pin( self.config .upgrade_inbound(socket, info) @@ -581,7 +581,7 @@ where impl OutboundUpgrade for NoiseAuthenticated where - NoiseConfig: UpgradeInfo + NoiseConfig: ToProtocolsIter + OutboundUpgrade, NoiseOutput), Error = NoiseError> + 'static, as OutboundUpgrade>::Future: Send, @@ -592,7 +592,7 @@ where type Error = NoiseError; type Future = Pin> + Send>>; - fn upgrade_outbound(self, socket: T, info: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: T, info: libp2p_core::upgrade::Protocol) -> Self::Future { Box::pin( self.config .upgrade_outbound(socket, info) diff --git a/transports/noise/src/protocol/x25519_spec.rs b/transports/noise/src/protocol/x25519_spec.rs index 0924bdd51e4..21edb5e5ab9 100644 --- a/transports/noise/src/protocol/x25519_spec.rs +++ b/transports/noise/src/protocol/x25519_spec.rs @@ -23,9 +23,10 @@ //! [libp2p-noise-spec]: https://github.com/libp2p/specs/tree/master/noise use crate::{NoiseConfig, NoiseError, Protocol, ProtocolParams}; -use libp2p_core::UpgradeInfo; +use libp2p_core::{upgrade, ToProtocolsIter}; use libp2p_identity as identity; use rand::Rng; +use std::iter; use x25519_dalek::{x25519, X25519_BASEPOINT_BYTES}; use zeroize::Zeroize; @@ -84,34 +85,35 @@ impl From> for Keypair { } } -impl UpgradeInfo for NoiseConfig { - type Info = &'static [u8]; - type InfoIter = std::iter::Once; +impl ToProtocolsIter for NoiseConfig { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - std::iter::once(b"/noise") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(upgrade::Protocol::from_static("/noise")) } } /// **Note**: This is not currentlyy a standardised upgrade. -impl UpgradeInfo for NoiseConfig { - type Info = &'static [u8]; - type InfoIter = std::iter::Once; +impl ToProtocolsIter for NoiseConfig { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - std::iter::once(b"/noise/ix/25519/chachapoly/sha256/0.1.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(upgrade::Protocol::from_static( + "/noise/ix/25519/chachapoly/sha256/0.1.0", + )) } } -/// **Note**: This is not currently a standardised upgrade. -impl UpgradeInfo for NoiseConfig { - type Info = &'static [u8]; - type InfoIter = std::iter::Once; - - fn protocol_info(&self) -> Self::InfoIter { - std::iter::once(b"/noise/ik/25519/chachapoly/sha256/0.1.0") - } -} +// /// **Note**: This is not currentlyy a standardised upgrade. +// impl ToProtocolsIter for NoiseConfig { +// type Iter = iter::Once; +// +// fn to_protocols_iter(&self) -> Self::Iter { +// iter::once(upgrade::Protocol::from_static( +// "/noise/ik/25519/chachapoly/sha256/0.1.0", +// )) +// } +// } /// Noise protocols for X25519 with libp2p-spec compliant signatures. /// diff --git a/transports/noise/tests/smoke.rs b/transports/noise/tests/smoke.rs index 2b71b115b99..a58b76ac685 100644 --- a/transports/noise/tests/smoke.rs +++ b/transports/noise/tests/smoke.rs @@ -20,11 +20,11 @@ use async_io::Async; use futures::{ - future::{self, Either}, + future::{self}, prelude::*, }; use libp2p_core::transport::Transport; -use libp2p_core::upgrade::{apply_inbound, apply_outbound, Negotiated}; +use libp2p_core::upgrade::Negotiated; use libp2p_core::{transport, upgrade}; use libp2p_identity as identity; use libp2p_noise::{ @@ -144,62 +144,62 @@ fn ix() { .quickcheck(prop as fn(Vec) -> bool) } -#[test] -fn ik_xx() { - let _ = env_logger::try_init(); - fn prop(mut messages: Vec) -> bool { - messages.truncate(5); - let server_id = identity::Keypair::generate_ed25519(); - let server_id_public = server_id.public(); - - let client_id = identity::Keypair::generate_ed25519(); - let client_id_public = client_id.public(); - - let server_dh = Keypair::::new() - .into_authentic(&server_id) - .unwrap(); - let server_dh_public = server_dh.public_dh_key().clone(); - let server_transport = tcp::async_io::Transport::default() - .and_then(move |output, endpoint| { - if endpoint.is_listener() { - Either::Left(apply_inbound(output, NoiseConfig::ik_listener(server_dh))) - } else { - Either::Right(apply_outbound( - output, - NoiseConfig::xx(server_dh), - upgrade::Version::V1, - )) - } - }) - .and_then(move |out, _| expect_identity(out, &client_id_public)) - .boxed(); - - let client_dh = Keypair::::new() - .into_authentic(&client_id) - .unwrap(); - let server_id_public2 = server_id_public.clone(); - let client_transport = tcp::async_io::Transport::default() - .and_then(move |output, endpoint| { - if endpoint.is_dialer() { - Either::Left(apply_outbound( - output, - NoiseConfig::ik_dialer(client_dh, server_id_public, server_dh_public), - upgrade::Version::V1, - )) - } else { - Either::Right(apply_inbound(output, NoiseConfig::xx(client_dh))) - } - }) - .and_then(move |out, _| expect_identity(out, &server_id_public2)) - .boxed(); - - run(server_transport, client_transport, messages); - true - } - QuickCheck::new() - .max_tests(30) - .quickcheck(prop as fn(Vec) -> bool) -} +// #[test] +// fn ik_xx() { +// let _ = env_logger::try_init(); +// fn prop(mut messages: Vec) -> bool { +// messages.truncate(5); +// let server_id = identity::Keypair::generate_ed25519(); +// let server_id_public = server_id.public(); +// +// let client_id = identity::Keypair::generate_ed25519(); +// let client_id_public = client_id.public(); +// +// let server_dh = Keypair::::new() +// .into_authentic(&server_id) +// .unwrap(); +// let server_dh_public = server_dh.public_dh_key().clone(); +// let server_transport = tcp::async_io::Transport::default() +// .and_then(move |output, endpoint| { +// if endpoint.is_listener() { +// Either::Left(apply_inbound(output, NoiseConfig::ik_listener(server_dh))) +// } else { +// Either::Right(apply_outbound( +// output, +// NoiseConfig::xx(server_dh), +// upgrade::Version::V1, +// )) +// } +// }) +// .and_then(move |out, _| expect_identity(out, &client_id_public)) +// .boxed(); +// +// let client_dh = Keypair::::new() +// .into_authentic(&client_id) +// .unwrap(); +// let server_id_public2 = server_id_public.clone(); +// let client_transport = tcp::async_io::Transport::default() +// .and_then(move |output, endpoint| { +// if endpoint.is_dialer() { +// Either::Left(apply_outbound( +// output, +// NoiseConfig::ik_dialer(client_dh, server_id_public, server_dh_public), +// upgrade::Version::V1, +// )) +// } else { +// Either::Right(apply_inbound(output, NoiseConfig::xx(client_dh))) +// } +// }) +// .and_then(move |out, _| expect_identity(out, &server_id_public2)) +// .boxed(); +// +// run(server_transport, client_transport, messages); +// true +// } +// QuickCheck::new() +// .max_tests(30) +// .quickcheck(prop as fn(Vec) -> bool) +// } type Output = (RemoteIdentity, NoiseOutput>>); diff --git a/transports/plaintext/src/lib.rs b/transports/plaintext/src/lib.rs index fe4aba91a88..7346d3ab23e 100644 --- a/transports/plaintext/src/lib.rs +++ b/transports/plaintext/src/lib.rs @@ -28,7 +28,8 @@ use bytes::Bytes; use futures::future::BoxFuture; use futures::future::{self, Ready}; use futures::prelude::*; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_identity as identity; use libp2p_identity::PeerId; use libp2p_identity::PublicKey; @@ -77,12 +78,11 @@ mod proto { #[derive(Debug, Copy, Clone)] pub struct PlainText1Config; -impl UpgradeInfo for PlainText1Config { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for PlainText1Config { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - iter::once(b"/plaintext/1.0.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(Protocol::from_static("/plaintext/1.0.0")) } } @@ -91,7 +91,7 @@ impl InboundUpgrade for PlainText1Config { type Error = Void; type Future = Ready>; - fn upgrade_inbound(self, i: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, i: C, _: Protocol) -> Self::Future { future::ready(Ok(i)) } } @@ -101,7 +101,7 @@ impl OutboundUpgrade for PlainText1Config { type Error = Void; type Future = Ready>; - fn upgrade_outbound(self, i: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, i: C, _: Protocol) -> Self::Future { future::ready(Ok(i)) } } @@ -113,15 +113,13 @@ pub struct PlainText2Config { pub local_public_key: identity::PublicKey, } -impl UpgradeInfo for PlainText2Config { - type Info = &'static [u8]; - type InfoIter = iter::Once; +impl ToProtocolsIter for PlainText2Config { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - iter::once(b"/plaintext/2.0.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(Protocol::from_static("/plaintext/2.0.0")) } } - impl InboundUpgrade for PlainText2Config where C: AsyncRead + AsyncWrite + Send + Unpin + 'static, @@ -130,7 +128,7 @@ where type Error = PlainTextError; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: C, _: Protocol) -> Self::Future { Box::pin(self.handshake(socket)) } } @@ -143,7 +141,7 @@ where type Error = PlainTextError; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: C, _: Protocol) -> Self::Future { Box::pin(self.handshake(socket)) } } diff --git a/transports/tls/src/upgrade.rs b/transports/tls/src/upgrade.rs index d1c9a6cefb4..0bfa8dfd310 100644 --- a/transports/tls/src/upgrade.rs +++ b/transports/tls/src/upgrade.rs @@ -24,10 +24,12 @@ use futures::future::BoxFuture; use futures::AsyncWrite; use futures::{AsyncRead, FutureExt}; use futures_rustls::TlsStream; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::upgrade::Protocol; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_identity as identity; use libp2p_identity::PeerId; use rustls::{CommonState, ServerName}; +use std::iter; use std::net::{IpAddr, Ipv4Addr}; use std::sync::Arc; @@ -58,12 +60,11 @@ impl Config { } } -impl UpgradeInfo for Config { - type Info = &'static [u8]; - type InfoIter = std::iter::Once; +impl ToProtocolsIter for Config { + type Iter = iter::Once; - fn protocol_info(&self) -> Self::InfoIter { - std::iter::once(b"/tls/1.0.0") + fn to_protocols_iter(&self) -> Self::Iter { + iter::once(Protocol::from_static("/tls/1.0.0")) } } @@ -75,7 +76,7 @@ where type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_inbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_inbound(self, socket: C, _: Protocol) -> Self::Future { async move { let stream = futures_rustls::TlsAcceptor::from(Arc::new(self.server)) .accept(socket) @@ -98,7 +99,7 @@ where type Error = UpgradeError; type Future = BoxFuture<'static, Result>; - fn upgrade_outbound(self, socket: C, _: Self::Info) -> Self::Future { + fn upgrade_outbound(self, socket: C, _: Protocol) -> Self::Future { async move { // Spec: In order to keep this flexibility for future versions, clients that only support the version of the handshake defined in this document MUST NOT send any value in the Server Name Indication. // Setting `ServerName` to unspecified will disable the use of the SNI extension. diff --git a/transports/webrtc/src/tokio/upgrade/noise.rs b/transports/webrtc/src/tokio/upgrade/noise.rs index fb95a0f4b46..25c5db7f861 100644 --- a/transports/webrtc/src/tokio/upgrade/noise.rs +++ b/transports/webrtc/src/tokio/upgrade/noise.rs @@ -19,7 +19,7 @@ // DEALINGS IN THE SOFTWARE. use futures::{AsyncRead, AsyncWrite, AsyncWriteExt}; -use libp2p_core::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; +use libp2p_core::{InboundUpgrade, OutboundUpgrade, ToProtocolsIter}; use libp2p_identity as identity; use libp2p_identity::PeerId; use libp2p_noise::{Keypair, NoiseConfig, X25519Spec}; @@ -41,7 +41,7 @@ where .unwrap(); let noise = NoiseConfig::xx(dh_keys) .with_prologue(noise_prologue(client_fingerprint, server_fingerprint)); - let info = noise.protocol_info().next().unwrap(); + let info = noise.to_protocols_iter().next().unwrap(); // Note the roles are reversed because it allows the server (webrtc connection responder) to // send application data 0.5 RTT earlier. let (peer_id, mut channel) = noise @@ -68,7 +68,7 @@ where .unwrap(); let noise = NoiseConfig::xx(dh_keys) .with_prologue(noise_prologue(client_fingerprint, server_fingerprint)); - let info = noise.protocol_info().next().unwrap(); + let info = noise.to_protocols_iter().next().unwrap(); // Note the roles are reversed because it allows the server (webrtc connection responder) to // send application data 0.5 RTT earlier. let (peer_id, mut channel) = noise