mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-27 08:41:36 +00:00
*: Format with rustfmt (#2188)
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
@ -28,16 +28,16 @@ pub(crate) mod pool;
|
||||
|
||||
pub use error::{ConnectionError, PendingConnectionError};
|
||||
pub use handler::{ConnectionHandler, ConnectionHandlerEvent, IntoConnectionHandler};
|
||||
pub use listeners::{ListenerId, ListenersStream, ListenersEvent};
|
||||
pub use listeners::{ListenerId, ListenersEvent, ListenersStream};
|
||||
pub use manager::ConnectionId;
|
||||
pub use substream::{Substream, SubstreamEndpoint, Close};
|
||||
pub use pool::{ConnectionCounters, ConnectionLimits};
|
||||
pub use pool::{EstablishedConnection, EstablishedConnectionIter, PendingConnection};
|
||||
pub use pool::{ConnectionLimits, ConnectionCounters};
|
||||
pub use substream::{Close, Substream, SubstreamEndpoint};
|
||||
|
||||
use crate::muxing::StreamMuxer;
|
||||
use crate::{Multiaddr, PeerId};
|
||||
use std::{error::Error, fmt, pin::Pin, task::Context, task::Poll};
|
||||
use std::hash::Hash;
|
||||
use std::{error::Error, fmt, pin::Pin, task::Context, task::Poll};
|
||||
use substream::{Muxing, SubstreamEvent};
|
||||
|
||||
/// The endpoint roles associated with a peer-to-peer communication channel.
|
||||
@ -55,7 +55,7 @@ impl std::ops::Not for Endpoint {
|
||||
fn not(self) -> Self::Output {
|
||||
match self {
|
||||
Endpoint::Dialer => Endpoint::Listener,
|
||||
Endpoint::Listener => Endpoint::Dialer
|
||||
Endpoint::Listener => Endpoint::Dialer,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +86,7 @@ pub enum ConnectedPoint {
|
||||
local_addr: Multiaddr,
|
||||
/// Stack of protocols used to send back data to the remote.
|
||||
send_back_addr: Multiaddr,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
impl From<&'_ ConnectedPoint> for Endpoint {
|
||||
@ -106,7 +106,7 @@ impl ConnectedPoint {
|
||||
pub fn to_endpoint(&self) -> Endpoint {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { .. } => Endpoint::Dialer,
|
||||
ConnectedPoint::Listener { .. } => Endpoint::Listener
|
||||
ConnectedPoint::Listener { .. } => Endpoint::Listener,
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ impl ConnectedPoint {
|
||||
pub fn is_dialer(&self) -> bool {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { .. } => true,
|
||||
ConnectedPoint::Listener { .. } => false
|
||||
ConnectedPoint::Listener { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ impl ConnectedPoint {
|
||||
pub fn is_listener(&self) -> bool {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { .. } => false,
|
||||
ConnectedPoint::Listener { .. } => true
|
||||
ConnectedPoint::Listener { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,9 +237,10 @@ where
|
||||
|
||||
/// Polls the connection for events produced by the associated handler
|
||||
/// as a result of I/O activity on the substream multiplexer.
|
||||
pub fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>)
|
||||
-> Poll<Result<Event<THandler::OutEvent>, ConnectionError<THandler::Error>>>
|
||||
{
|
||||
pub fn poll(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<Event<THandler::OutEvent>, ConnectionError<THandler::Error>>> {
|
||||
loop {
|
||||
let mut io_pending = false;
|
||||
|
||||
@ -247,10 +248,13 @@ where
|
||||
// of new substreams.
|
||||
match self.muxing.poll(cx) {
|
||||
Poll::Pending => io_pending = true,
|
||||
Poll::Ready(Ok(SubstreamEvent::InboundSubstream { substream })) => {
|
||||
self.handler.inject_substream(substream, SubstreamEndpoint::Listener)
|
||||
}
|
||||
Poll::Ready(Ok(SubstreamEvent::OutboundSubstream { user_data, substream })) => {
|
||||
Poll::Ready(Ok(SubstreamEvent::InboundSubstream { substream })) => self
|
||||
.handler
|
||||
.inject_substream(substream, SubstreamEndpoint::Listener),
|
||||
Poll::Ready(Ok(SubstreamEvent::OutboundSubstream {
|
||||
user_data,
|
||||
substream,
|
||||
})) => {
|
||||
let endpoint = SubstreamEndpoint::Dialer(user_data);
|
||||
self.handler.inject_substream(substream, endpoint)
|
||||
}
|
||||
@ -265,7 +269,7 @@ where
|
||||
match self.handler.poll(cx) {
|
||||
Poll::Pending => {
|
||||
if io_pending {
|
||||
return Poll::Pending // Nothing to do
|
||||
return Poll::Pending; // Nothing to do
|
||||
}
|
||||
}
|
||||
Poll::Ready(Ok(ConnectionHandlerEvent::OutboundSubstreamRequest(user_data))) => {
|
||||
@ -310,7 +314,7 @@ impl<'a> OutgoingInfo<'a> {
|
||||
/// Builds a `ConnectedPoint` corresponding to the outgoing connection.
|
||||
pub fn to_connected_point(&self) -> ConnectedPoint {
|
||||
ConnectedPoint::Dialer {
|
||||
address: self.address.clone()
|
||||
address: self.address.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
use crate::connection::ConnectionLimit;
|
||||
use crate::transport::TransportError;
|
||||
use std::{io, fmt};
|
||||
use std::{fmt, io};
|
||||
|
||||
/// Errors that can occur in the context of an established `Connection`.
|
||||
#[derive(Debug)]
|
||||
@ -33,23 +33,19 @@ pub enum ConnectionError<THandlerErr> {
|
||||
Handler(THandlerErr),
|
||||
}
|
||||
|
||||
impl<THandlerErr> fmt::Display
|
||||
for ConnectionError<THandlerErr>
|
||||
impl<THandlerErr> fmt::Display for ConnectionError<THandlerErr>
|
||||
where
|
||||
THandlerErr: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ConnectionError::IO(err) =>
|
||||
write!(f, "Connection error: I/O error: {}", err),
|
||||
ConnectionError::Handler(err) =>
|
||||
write!(f, "Connection error: Handler error: {}", err),
|
||||
ConnectionError::IO(err) => write!(f, "Connection error: I/O error: {}", err),
|
||||
ConnectionError::Handler(err) => write!(f, "Connection error: Handler error: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandlerErr> std::error::Error
|
||||
for ConnectionError<THandlerErr>
|
||||
impl<THandlerErr> std::error::Error for ConnectionError<THandlerErr>
|
||||
where
|
||||
THandlerErr: std::error::Error + 'static,
|
||||
{
|
||||
@ -80,29 +76,29 @@ pub enum PendingConnectionError<TTransErr> {
|
||||
IO(io::Error),
|
||||
}
|
||||
|
||||
impl<TTransErr> fmt::Display
|
||||
for PendingConnectionError<TTransErr>
|
||||
impl<TTransErr> fmt::Display for PendingConnectionError<TTransErr>
|
||||
where
|
||||
TTransErr: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
PendingConnectionError::IO(err) =>
|
||||
write!(f, "Pending connection: I/O error: {}", err),
|
||||
PendingConnectionError::Transport(err) =>
|
||||
write!(f, "Pending connection: Transport error: {}", err),
|
||||
PendingConnectionError::InvalidPeerId =>
|
||||
write!(f, "Pending connection: Invalid peer ID."),
|
||||
PendingConnectionError::ConnectionLimit(l) =>
|
||||
write!(f, "Connection error: Connection limit: {}.", l),
|
||||
PendingConnectionError::IO(err) => write!(f, "Pending connection: I/O error: {}", err),
|
||||
PendingConnectionError::Transport(err) => {
|
||||
write!(f, "Pending connection: Transport error: {}", err)
|
||||
}
|
||||
PendingConnectionError::InvalidPeerId => {
|
||||
write!(f, "Pending connection: Invalid peer ID.")
|
||||
}
|
||||
PendingConnectionError::ConnectionLimit(l) => {
|
||||
write!(f, "Connection error: Connection limit: {}.", l)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TTransErr> std::error::Error
|
||||
for PendingConnectionError<TTransErr>
|
||||
impl<TTransErr> std::error::Error for PendingConnectionError<TTransErr>
|
||||
where
|
||||
TTransErr: std::error::Error + 'static
|
||||
TTransErr: std::error::Error + 'static,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
|
@ -18,9 +18,9 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use super::{Connected, SubstreamEndpoint};
|
||||
use crate::Multiaddr;
|
||||
use std::{fmt::Debug, task::Context, task::Poll};
|
||||
use super::{Connected, SubstreamEndpoint};
|
||||
|
||||
/// The interface of a connection handler.
|
||||
///
|
||||
@ -53,7 +53,11 @@ pub trait ConnectionHandler {
|
||||
/// Implementations are allowed to panic in the case of dialing if the `user_data` in
|
||||
/// `endpoint` doesn't correspond to what was returned earlier when polling, or is used
|
||||
/// multiple times.
|
||||
fn inject_substream(&mut self, substream: Self::Substream, endpoint: SubstreamEndpoint<Self::OutboundOpenInfo>);
|
||||
fn inject_substream(
|
||||
&mut self,
|
||||
substream: Self::Substream,
|
||||
endpoint: SubstreamEndpoint<Self::OutboundOpenInfo>,
|
||||
);
|
||||
|
||||
/// Notifies the handler of an event.
|
||||
fn inject_event(&mut self, event: Self::InEvent);
|
||||
@ -64,8 +68,10 @@ pub trait ConnectionHandler {
|
||||
/// Polls the handler for events.
|
||||
///
|
||||
/// Returning an error will close the connection to the remote.
|
||||
fn poll(&mut self, cx: &mut Context<'_>)
|
||||
-> Poll<Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>>;
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>>;
|
||||
}
|
||||
|
||||
/// Prototype for a `ConnectionHandler`.
|
||||
@ -82,7 +88,7 @@ pub trait IntoConnectionHandler {
|
||||
|
||||
impl<T> IntoConnectionHandler for T
|
||||
where
|
||||
T: ConnectionHandler
|
||||
T: ConnectionHandler,
|
||||
{
|
||||
type Handler = Self;
|
||||
|
||||
@ -91,9 +97,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type THandlerInEvent<THandler> = <<THandler as IntoConnectionHandler>::Handler as ConnectionHandler>::InEvent;
|
||||
pub(crate) type THandlerOutEvent<THandler> = <<THandler as IntoConnectionHandler>::Handler as ConnectionHandler>::OutEvent;
|
||||
pub(crate) type THandlerError<THandler> = <<THandler as IntoConnectionHandler>::Handler as ConnectionHandler>::Error;
|
||||
pub(crate) type THandlerInEvent<THandler> =
|
||||
<<THandler as IntoConnectionHandler>::Handler as ConnectionHandler>::InEvent;
|
||||
pub(crate) type THandlerOutEvent<THandler> =
|
||||
<<THandler as IntoConnectionHandler>::Handler as ConnectionHandler>::OutEvent;
|
||||
pub(crate) type THandlerError<THandler> =
|
||||
<<THandler as IntoConnectionHandler>::Handler as ConnectionHandler>::Error;
|
||||
|
||||
/// Event produced by a handler.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
@ -109,24 +118,26 @@ pub enum ConnectionHandlerEvent<TOutboundOpenInfo, TCustom> {
|
||||
impl<TOutboundOpenInfo, TCustom> ConnectionHandlerEvent<TOutboundOpenInfo, TCustom> {
|
||||
/// If this is `OutboundSubstreamRequest`, maps the content to something else.
|
||||
pub fn map_outbound_open_info<F, I>(self, map: F) -> ConnectionHandlerEvent<I, TCustom>
|
||||
where F: FnOnce(TOutboundOpenInfo) -> I
|
||||
where
|
||||
F: FnOnce(TOutboundOpenInfo) -> I,
|
||||
{
|
||||
match self {
|
||||
ConnectionHandlerEvent::OutboundSubstreamRequest(val) => {
|
||||
ConnectionHandlerEvent::OutboundSubstreamRequest(map(val))
|
||||
},
|
||||
}
|
||||
ConnectionHandlerEvent::Custom(val) => ConnectionHandlerEvent::Custom(val),
|
||||
}
|
||||
}
|
||||
|
||||
/// If this is `Custom`, maps the content to something else.
|
||||
pub fn map_custom<F, I>(self, map: F) -> ConnectionHandlerEvent<TOutboundOpenInfo, I>
|
||||
where F: FnOnce(TCustom) -> I
|
||||
where
|
||||
F: FnOnce(TCustom) -> I,
|
||||
{
|
||||
match self {
|
||||
ConnectionHandlerEvent::OutboundSubstreamRequest(val) => {
|
||||
ConnectionHandlerEvent::OutboundSubstreamRequest(val)
|
||||
},
|
||||
}
|
||||
ConnectionHandlerEvent::Custom(val) => ConnectionHandlerEvent::Custom(map(val)),
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,10 @@
|
||||
|
||||
//! Manage listening on multiple multiaddresses at once.
|
||||
|
||||
use crate::{Multiaddr, Transport, transport::{TransportError, ListenerEvent}};
|
||||
use crate::{
|
||||
transport::{ListenerEvent, TransportError},
|
||||
Multiaddr, Transport,
|
||||
};
|
||||
use futures::{prelude::*, task::Context, task::Poll};
|
||||
use log::debug;
|
||||
use smallvec::SmallVec;
|
||||
@ -86,7 +89,7 @@ where
|
||||
/// can be resized, the only way is to use a `Pin<Box<>>`.
|
||||
listeners: VecDeque<Pin<Box<Listener<TTrans>>>>,
|
||||
/// The next listener ID to assign.
|
||||
next_id: ListenerId
|
||||
next_id: ListenerId,
|
||||
}
|
||||
|
||||
/// The ID of a single listener.
|
||||
@ -109,7 +112,7 @@ where
|
||||
#[pin]
|
||||
listener: TTrans::Listener,
|
||||
/// Addresses it is listening on.
|
||||
addresses: SmallVec<[Multiaddr; 4]>
|
||||
addresses: SmallVec<[Multiaddr; 4]>,
|
||||
}
|
||||
|
||||
/// Event that can happen on the `ListenersStream`.
|
||||
@ -122,14 +125,14 @@ where
|
||||
/// The listener that is listening on the new address.
|
||||
listener_id: ListenerId,
|
||||
/// The new address that is being listened on.
|
||||
listen_addr: Multiaddr
|
||||
listen_addr: Multiaddr,
|
||||
},
|
||||
/// An address is no longer being listened on.
|
||||
AddressExpired {
|
||||
/// The listener that is no longer listening on the address.
|
||||
listener_id: ListenerId,
|
||||
/// The new address that is being listened on.
|
||||
listen_addr: Multiaddr
|
||||
listen_addr: Multiaddr,
|
||||
},
|
||||
/// A connection is incoming on one of the listeners.
|
||||
Incoming {
|
||||
@ -161,7 +164,7 @@ where
|
||||
listener_id: ListenerId,
|
||||
/// The error value.
|
||||
error: TTrans::Error,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
impl<TTrans> ListenersStream<TTrans>
|
||||
@ -173,7 +176,7 @@ where
|
||||
ListenersStream {
|
||||
transport,
|
||||
listeners: VecDeque::new(),
|
||||
next_id: ListenerId(1)
|
||||
next_id: ListenerId(1),
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,14 +186,17 @@ where
|
||||
ListenersStream {
|
||||
transport,
|
||||
listeners: VecDeque::with_capacity(capacity),
|
||||
next_id: ListenerId(1)
|
||||
next_id: ListenerId(1),
|
||||
}
|
||||
}
|
||||
|
||||
/// Start listening on a multiaddress.
|
||||
///
|
||||
/// Returns an error if the transport doesn't support the given multiaddress.
|
||||
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<TTrans::Error>>
|
||||
pub fn listen_on(
|
||||
&mut self,
|
||||
addr: Multiaddr,
|
||||
) -> Result<ListenerId, TransportError<TTrans::Error>>
|
||||
where
|
||||
TTrans: Clone,
|
||||
{
|
||||
@ -198,7 +204,7 @@ where
|
||||
self.listeners.push_back(Box::pin(Listener {
|
||||
id: self.next_id,
|
||||
listener,
|
||||
addresses: SmallVec::new()
|
||||
addresses: SmallVec::new(),
|
||||
}));
|
||||
let id = self.next_id;
|
||||
self.next_id = ListenerId(self.next_id.0 + 1);
|
||||
@ -237,17 +243,23 @@ where
|
||||
Poll::Pending => {
|
||||
self.listeners.push_front(listener);
|
||||
remaining -= 1;
|
||||
if remaining == 0 { break }
|
||||
if remaining == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Poll::Ready(Some(Ok(ListenerEvent::Upgrade { upgrade, local_addr, remote_addr }))) => {
|
||||
Poll::Ready(Some(Ok(ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
}))) => {
|
||||
let id = *listener_project.id;
|
||||
self.listeners.push_front(listener);
|
||||
return Poll::Ready(ListenersEvent::Incoming {
|
||||
listener_id: id,
|
||||
upgrade,
|
||||
local_addr,
|
||||
send_back_addr: remote_addr
|
||||
})
|
||||
send_back_addr: remote_addr,
|
||||
});
|
||||
}
|
||||
Poll::Ready(Some(Ok(ListenerEvent::NewAddress(a)))) => {
|
||||
if listener_project.addresses.contains(&a) {
|
||||
@ -260,8 +272,8 @@ where
|
||||
self.listeners.push_front(listener);
|
||||
return Poll::Ready(ListenersEvent::NewAddress {
|
||||
listener_id: id,
|
||||
listen_addr: a
|
||||
})
|
||||
listen_addr: a,
|
||||
});
|
||||
}
|
||||
Poll::Ready(Some(Ok(ListenerEvent::AddressExpired(a)))) => {
|
||||
listener_project.addresses.retain(|x| x != &a);
|
||||
@ -269,8 +281,8 @@ where
|
||||
self.listeners.push_front(listener);
|
||||
return Poll::Ready(ListenersEvent::AddressExpired {
|
||||
listener_id: id,
|
||||
listen_addr: a
|
||||
})
|
||||
listen_addr: a,
|
||||
});
|
||||
}
|
||||
Poll::Ready(Some(Ok(ListenerEvent::Error(error)))) => {
|
||||
let id = *listener_project.id;
|
||||
@ -278,7 +290,7 @@ where
|
||||
return Poll::Ready(ListenersEvent::Error {
|
||||
listener_id: id,
|
||||
error,
|
||||
})
|
||||
});
|
||||
}
|
||||
Poll::Ready(None) => {
|
||||
return Poll::Ready(ListenersEvent::Closed {
|
||||
@ -313,11 +325,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TTrans> Unpin for ListenersStream<TTrans>
|
||||
where
|
||||
TTrans: Transport,
|
||||
{
|
||||
}
|
||||
impl<TTrans> Unpin for ListenersStream<TTrans> where TTrans: Transport {}
|
||||
|
||||
impl<TTrans> fmt::Debug for ListenersStream<TTrans>
|
||||
where
|
||||
@ -338,22 +346,36 @@ where
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
ListenersEvent::NewAddress { listener_id, listen_addr } => f
|
||||
ListenersEvent::NewAddress {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
} => f
|
||||
.debug_struct("ListenersEvent::NewAddress")
|
||||
.field("listener_id", listener_id)
|
||||
.field("listen_addr", listen_addr)
|
||||
.finish(),
|
||||
ListenersEvent::AddressExpired { listener_id, listen_addr } => f
|
||||
ListenersEvent::AddressExpired {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
} => f
|
||||
.debug_struct("ListenersEvent::AddressExpired")
|
||||
.field("listener_id", listener_id)
|
||||
.field("listen_addr", listen_addr)
|
||||
.finish(),
|
||||
ListenersEvent::Incoming { listener_id, local_addr, .. } => f
|
||||
ListenersEvent::Incoming {
|
||||
listener_id,
|
||||
local_addr,
|
||||
..
|
||||
} => f
|
||||
.debug_struct("ListenersEvent::Incoming")
|
||||
.field("listener_id", listener_id)
|
||||
.field("local_addr", local_addr)
|
||||
.finish(),
|
||||
ListenersEvent::Closed { listener_id, addresses, reason } => f
|
||||
ListenersEvent::Closed {
|
||||
listener_id,
|
||||
addresses,
|
||||
reason,
|
||||
} => f
|
||||
.debug_struct("ListenersEvent::Closed")
|
||||
.field("listener_id", listener_id)
|
||||
.field("addresses", addresses)
|
||||
@ -363,13 +385,15 @@ where
|
||||
.debug_struct("ListenersEvent::Error")
|
||||
.field("listener_id", listener_id)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use futures::{future::BoxFuture, stream::BoxStream};
|
||||
|
||||
use super::*;
|
||||
use crate::transport;
|
||||
|
||||
@ -396,11 +420,15 @@ mod tests {
|
||||
});
|
||||
|
||||
match listeners.next().await.unwrap() {
|
||||
ListenersEvent::Incoming { local_addr, send_back_addr, .. } => {
|
||||
ListenersEvent::Incoming {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(local_addr, address);
|
||||
assert!(send_back_addr != address);
|
||||
},
|
||||
_ => panic!()
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -415,21 +443,37 @@ mod tests {
|
||||
impl transport::Transport for DummyTrans {
|
||||
type Output = ();
|
||||
type Error = std::io::Error;
|
||||
type Listener = Pin<Box<dyn Stream<Item = Result<ListenerEvent<Self::ListenerUpgrade, std::io::Error>, std::io::Error>>>>;
|
||||
type ListenerUpgrade = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>>>>;
|
||||
type Dial = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>>>>;
|
||||
type Listener = BoxStream<
|
||||
'static,
|
||||
Result<ListenerEvent<Self::ListenerUpgrade, std::io::Error>, std::io::Error>,
|
||||
>;
|
||||
type ListenerUpgrade = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
|
||||
fn listen_on(self, _: Multiaddr) -> Result<Self::Listener, transport::TransportError<Self::Error>> {
|
||||
fn listen_on(
|
||||
self,
|
||||
_: Multiaddr,
|
||||
) -> Result<Self::Listener, transport::TransportError<Self::Error>> {
|
||||
Ok(Box::pin(stream::unfold((), |()| async move {
|
||||
Some((Ok(ListenerEvent::Error(std::io::Error::from(std::io::ErrorKind::Other))), ()))
|
||||
Some((
|
||||
Ok(ListenerEvent::Error(std::io::Error::from(
|
||||
std::io::ErrorKind::Other,
|
||||
))),
|
||||
(),
|
||||
))
|
||||
})))
|
||||
}
|
||||
|
||||
fn dial(self, _: Multiaddr) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
fn dial(
|
||||
self,
|
||||
_: Multiaddr,
|
||||
) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> { None }
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
async_std::task::block_on(async move {
|
||||
@ -439,8 +483,8 @@ mod tests {
|
||||
|
||||
for _ in 0..10 {
|
||||
match listeners.next().await.unwrap() {
|
||||
ListenersEvent::Error { .. } => {},
|
||||
_ => panic!()
|
||||
ListenersEvent::Error { .. } => {}
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -455,21 +499,32 @@ mod tests {
|
||||
impl transport::Transport for DummyTrans {
|
||||
type Output = ();
|
||||
type Error = std::io::Error;
|
||||
type Listener = Pin<Box<dyn Stream<Item = Result<ListenerEvent<Self::ListenerUpgrade, std::io::Error>, std::io::Error>>>>;
|
||||
type ListenerUpgrade = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>>>>;
|
||||
type Dial = Pin<Box<dyn Future<Output = Result<Self::Output, Self::Error>>>>;
|
||||
type Listener = BoxStream<
|
||||
'static,
|
||||
Result<ListenerEvent<Self::ListenerUpgrade, std::io::Error>, std::io::Error>,
|
||||
>;
|
||||
type ListenerUpgrade = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
type Dial = BoxFuture<'static, Result<Self::Output, Self::Error>>;
|
||||
|
||||
fn listen_on(self, _: Multiaddr) -> Result<Self::Listener, transport::TransportError<Self::Error>> {
|
||||
fn listen_on(
|
||||
self,
|
||||
_: Multiaddr,
|
||||
) -> Result<Self::Listener, transport::TransportError<Self::Error>> {
|
||||
Ok(Box::pin(stream::unfold((), |()| async move {
|
||||
Some((Err(std::io::Error::from(std::io::ErrorKind::Other)), ()))
|
||||
})))
|
||||
}
|
||||
|
||||
fn dial(self, _: Multiaddr) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
fn dial(
|
||||
self,
|
||||
_: Multiaddr,
|
||||
) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> { None }
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
async_std::task::block_on(async move {
|
||||
@ -478,8 +533,8 @@ mod tests {
|
||||
listeners.listen_on("/memory/0".parse().unwrap()).unwrap();
|
||||
|
||||
match listeners.next().await.unwrap() {
|
||||
ListenersEvent::Closed { .. } => {},
|
||||
_ => panic!()
|
||||
ListenersEvent::Closed { .. } => {}
|
||||
_ => panic!(),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -18,39 +18,20 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
Executor,
|
||||
muxing::StreamMuxer,
|
||||
use super::{
|
||||
handler::{THandlerError, THandlerInEvent, THandlerOutEvent},
|
||||
Connected, ConnectedPoint, Connection, ConnectionError, ConnectionHandler,
|
||||
IntoConnectionHandler, PendingConnectionError, Substream,
|
||||
};
|
||||
use crate::{muxing::StreamMuxer, Executor};
|
||||
use fnv::FnvHashMap;
|
||||
use futures::{
|
||||
prelude::*,
|
||||
channel::mpsc,
|
||||
stream::FuturesUnordered
|
||||
};
|
||||
use futures::{channel::mpsc, prelude::*, stream::FuturesUnordered};
|
||||
use std::{
|
||||
collections::hash_map,
|
||||
error,
|
||||
fmt,
|
||||
mem,
|
||||
error, fmt, mem,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use super::{
|
||||
Connected,
|
||||
ConnectedPoint,
|
||||
Connection,
|
||||
ConnectionError,
|
||||
ConnectionHandler,
|
||||
IntoConnectionHandler,
|
||||
PendingConnectionError,
|
||||
Substream,
|
||||
handler::{
|
||||
THandlerInEvent,
|
||||
THandlerOutEvent,
|
||||
THandlerError,
|
||||
},
|
||||
};
|
||||
use task::{Task, TaskId};
|
||||
|
||||
mod task;
|
||||
@ -123,11 +104,10 @@ pub struct Manager<H: IntoConnectionHandler, E> {
|
||||
events_tx: mpsc::Sender<task::Event<H, E>>,
|
||||
|
||||
/// Receiver for events reported from managed tasks.
|
||||
events_rx: mpsc::Receiver<task::Event<H, E>>
|
||||
events_rx: mpsc::Receiver<task::Event<H, E>>,
|
||||
}
|
||||
|
||||
impl<H: IntoConnectionHandler, E> fmt::Debug for Manager<H, E>
|
||||
{
|
||||
impl<H: IntoConnectionHandler, E> fmt::Debug for Manager<H, E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map()
|
||||
.entries(self.tasks.iter().map(|(id, task)| (id, &task.state)))
|
||||
@ -196,7 +176,7 @@ pub enum Event<'a, H: IntoConnectionHandler, TE> {
|
||||
/// What happened.
|
||||
error: PendingConnectionError<TE>,
|
||||
/// The handler that was supposed to handle the failed connection.
|
||||
handler: H
|
||||
handler: H,
|
||||
},
|
||||
|
||||
/// An established connection has been closed.
|
||||
@ -225,7 +205,7 @@ pub enum Event<'a, H: IntoConnectionHandler, TE> {
|
||||
/// The entry associated with the connection that produced the event.
|
||||
entry: EstablishedEntry<'a, THandlerInEvent<H>>,
|
||||
/// The produced event.
|
||||
event: THandlerOutEvent<H>
|
||||
event: THandlerOutEvent<H>,
|
||||
},
|
||||
|
||||
/// A connection to a node has changed its address.
|
||||
@ -250,7 +230,7 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
executor: config.executor,
|
||||
local_spawns: FuturesUnordered::new(),
|
||||
events_tx: tx,
|
||||
events_rx: rx
|
||||
events_rx: rx,
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,18 +245,28 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
M::OutboundSubstream: Send + 'static,
|
||||
F: Future<Output = ConnectResult<M, TE>> + Send + 'static,
|
||||
H: IntoConnectionHandler + Send + 'static,
|
||||
H::Handler: ConnectionHandler<
|
||||
Substream = Substream<M>,
|
||||
> + Send + 'static,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>> + Send + 'static,
|
||||
<H::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
{
|
||||
let task_id = self.next_task_id;
|
||||
self.next_task_id.0 += 1;
|
||||
|
||||
let (tx, rx) = mpsc::channel(self.task_command_buffer_size);
|
||||
self.tasks.insert(task_id, TaskInfo { sender: tx, state: TaskState::Pending });
|
||||
self.tasks.insert(
|
||||
task_id,
|
||||
TaskInfo {
|
||||
sender: tx,
|
||||
state: TaskState::Pending,
|
||||
},
|
||||
);
|
||||
|
||||
let task = Box::pin(Task::pending(task_id, self.events_tx.clone(), rx, future, handler));
|
||||
let task = Box::pin(Task::pending(
|
||||
task_id,
|
||||
self.events_tx.clone(),
|
||||
rx,
|
||||
future,
|
||||
handler,
|
||||
));
|
||||
if let Some(executor) = &mut self.executor {
|
||||
executor.exec(task);
|
||||
} else {
|
||||
@ -290,9 +280,7 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
pub fn add<M>(&mut self, conn: Connection<M, H::Handler>, info: Connected) -> ConnectionId
|
||||
where
|
||||
H: IntoConnectionHandler + Send + 'static,
|
||||
H::Handler: ConnectionHandler<
|
||||
Substream = Substream<M>,
|
||||
> + Send + 'static,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>> + Send + 'static,
|
||||
<H::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
TE: error::Error + Send + 'static,
|
||||
M: StreamMuxer + Send + Sync + 'static,
|
||||
@ -302,9 +290,13 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
self.next_task_id.0 += 1;
|
||||
|
||||
let (tx, rx) = mpsc::channel(self.task_command_buffer_size);
|
||||
self.tasks.insert(task_id, TaskInfo {
|
||||
sender: tx, state: TaskState::Established(info)
|
||||
});
|
||||
self.tasks.insert(
|
||||
task_id,
|
||||
TaskInfo {
|
||||
sender: tx,
|
||||
state: TaskState::Established(info),
|
||||
},
|
||||
);
|
||||
|
||||
let task: Pin<Box<Task<Pin<Box<future::Pending<_>>>, _, _, _>>> =
|
||||
Box::pin(Task::established(task_id, self.events_tx.clone(), rx, conn));
|
||||
@ -329,7 +321,13 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
|
||||
/// Checks whether an established connection with the given ID is currently managed.
|
||||
pub fn is_established(&self, id: &ConnectionId) -> bool {
|
||||
matches!(self.tasks.get(&id.0), Some(TaskInfo { state: TaskState::Established(..), .. }))
|
||||
matches!(
|
||||
self.tasks.get(&id.0),
|
||||
Some(TaskInfo {
|
||||
state: TaskState::Established(..),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/// Polls the manager for events relating to the managed connections.
|
||||
@ -341,8 +339,9 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
let event = loop {
|
||||
match self.events_rx.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(event)) => {
|
||||
if self.tasks.contains_key(event.id()) { // (1)
|
||||
break event
|
||||
if self.tasks.contains_key(event.id()) {
|
||||
// (1)
|
||||
break event;
|
||||
}
|
||||
}
|
||||
Poll::Pending => return Poll::Pending,
|
||||
@ -352,12 +351,12 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
|
||||
if let hash_map::Entry::Occupied(mut task) = self.tasks.entry(*event.id()) {
|
||||
Poll::Ready(match event {
|
||||
task::Event::Notify { id: _, event } =>
|
||||
Event::ConnectionEvent {
|
||||
entry: EstablishedEntry { task },
|
||||
event
|
||||
},
|
||||
task::Event::Established { id: _, info } => { // (2)
|
||||
task::Event::Notify { id: _, event } => Event::ConnectionEvent {
|
||||
entry: EstablishedEntry { task },
|
||||
event,
|
||||
},
|
||||
task::Event::Established { id: _, info } => {
|
||||
// (2)
|
||||
task.get_mut().state = TaskState::Established(info); // (3)
|
||||
Event::ConnectionEstablished {
|
||||
entry: EstablishedEntry { task },
|
||||
@ -389,11 +388,14 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
let id = ConnectionId(id);
|
||||
let task = task.remove();
|
||||
match task.state {
|
||||
TaskState::Established(connected) =>
|
||||
Event::ConnectionClosed { id, connected, error },
|
||||
TaskState::Established(connected) => Event::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
error,
|
||||
},
|
||||
TaskState::Pending => unreachable!(
|
||||
"`Event::Closed` implies (2) occurred on that task and thus (3)."
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -407,14 +409,14 @@ impl<H: IntoConnectionHandler, TE> Manager<H, TE> {
|
||||
#[derive(Debug)]
|
||||
pub enum Entry<'a, I> {
|
||||
Pending(PendingEntry<'a, I>),
|
||||
Established(EstablishedEntry<'a, I>)
|
||||
Established(EstablishedEntry<'a, I>),
|
||||
}
|
||||
|
||||
impl<'a, I> Entry<'a, I> {
|
||||
fn new(task: hash_map::OccupiedEntry<'a, TaskId, TaskInfo<I>>) -> Self {
|
||||
match &task.get().state {
|
||||
TaskState::Pending => Entry::Pending(PendingEntry { task }),
|
||||
TaskState::Established(_) => Entry::Established(EstablishedEntry { task })
|
||||
TaskState::Established(_) => Entry::Established(EstablishedEntry { task }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -442,10 +444,13 @@ impl<'a, I> EstablishedEntry<'a, I> {
|
||||
/// > the connection handler not being ready at this time.
|
||||
pub fn notify_handler(&mut self, event: I) -> Result<(), I> {
|
||||
let cmd = task::Command::NotifyHandler(event); // (*)
|
||||
self.task.get_mut().sender.try_send(cmd)
|
||||
self.task
|
||||
.get_mut()
|
||||
.sender
|
||||
.try_send(cmd)
|
||||
.map_err(|e| match e.into_inner() {
|
||||
task::Command::NotifyHandler(event) => event,
|
||||
_ => panic!("Unexpected command. Expected `NotifyHandler`") // see (*)
|
||||
_ => panic!("Unexpected command. Expected `NotifyHandler`"), // see (*)
|
||||
})
|
||||
}
|
||||
|
||||
@ -455,7 +460,7 @@ impl<'a, I> EstablishedEntry<'a, I> {
|
||||
///
|
||||
/// Returns `Err(())` if the background task associated with the connection
|
||||
/// is terminating and the connection is about to close.
|
||||
pub fn poll_ready_notify_handler(&mut self, cx: &mut Context<'_>) -> Poll<Result<(),()>> {
|
||||
pub fn poll_ready_notify_handler(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ()>> {
|
||||
self.task.get_mut().sender.poll_ready(cx).map_err(|_| ())
|
||||
}
|
||||
|
||||
@ -469,9 +474,15 @@ impl<'a, I> EstablishedEntry<'a, I> {
|
||||
pub fn start_close(mut self) {
|
||||
// Clone the sender so that we are guaranteed to have
|
||||
// capacity for the close command (every sender gets a slot).
|
||||
match self.task.get_mut().sender.clone().try_send(task::Command::Close) {
|
||||
Ok(()) => {},
|
||||
Err(e) => assert!(e.is_disconnected(), "No capacity for close command.")
|
||||
match self
|
||||
.task
|
||||
.get_mut()
|
||||
.sender
|
||||
.clone()
|
||||
.try_send(task::Command::Close)
|
||||
{
|
||||
Ok(()) => {}
|
||||
Err(e) => assert!(e.is_disconnected(), "No capacity for close command."),
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,7 +490,7 @@ impl<'a, I> EstablishedEntry<'a, I> {
|
||||
pub fn connected(&self) -> &Connected {
|
||||
match &self.task.get().state {
|
||||
TaskState::Established(c) => c,
|
||||
TaskState::Pending => unreachable!("By Entry::new()")
|
||||
TaskState::Pending => unreachable!("By Entry::new()"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,7 +501,7 @@ impl<'a, I> EstablishedEntry<'a, I> {
|
||||
pub fn remove(self) -> Connected {
|
||||
match self.task.remove().state {
|
||||
TaskState::Established(c) => c,
|
||||
TaskState::Pending => unreachable!("By Entry::new()")
|
||||
TaskState::Pending => unreachable!("By Entry::new()"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,7 +515,7 @@ impl<'a, I> EstablishedEntry<'a, I> {
|
||||
/// (i.e. pending).
|
||||
#[derive(Debug)]
|
||||
pub struct PendingEntry<'a, I> {
|
||||
task: hash_map::OccupiedEntry<'a, TaskId, TaskInfo<I>>
|
||||
task: hash_map::OccupiedEntry<'a, TaskId, TaskInfo<I>>,
|
||||
}
|
||||
|
||||
impl<'a, I> PendingEntry<'a, I> {
|
||||
@ -514,7 +525,7 @@ impl<'a, I> PendingEntry<'a, I> {
|
||||
}
|
||||
|
||||
/// Aborts the pending connection attempt.
|
||||
pub fn abort(self) {
|
||||
pub fn abort(self) {
|
||||
self.task.remove();
|
||||
}
|
||||
}
|
||||
|
@ -18,29 +18,19 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use super::ConnectResult;
|
||||
use crate::{
|
||||
Multiaddr,
|
||||
muxing::StreamMuxer,
|
||||
connection::{
|
||||
self,
|
||||
Close,
|
||||
Connected,
|
||||
Connection,
|
||||
ConnectionError,
|
||||
ConnectionHandler,
|
||||
IntoConnectionHandler,
|
||||
PendingConnectionError,
|
||||
Substream,
|
||||
handler::{
|
||||
THandlerInEvent,
|
||||
THandlerOutEvent,
|
||||
THandlerError,
|
||||
},
|
||||
handler::{THandlerError, THandlerInEvent, THandlerOutEvent},
|
||||
Close, Connected, Connection, ConnectionError, ConnectionHandler, IntoConnectionHandler,
|
||||
PendingConnectionError, Substream,
|
||||
},
|
||||
muxing::StreamMuxer,
|
||||
Multiaddr,
|
||||
};
|
||||
use futures::{prelude::*, channel::mpsc, stream};
|
||||
use futures::{channel::mpsc, prelude::*, stream};
|
||||
use std::{pin::Pin, task::Context, task::Poll};
|
||||
use super::ConnectResult;
|
||||
|
||||
/// Identifier of a [`Task`] in a [`Manager`](super::Manager).
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
@ -62,16 +52,26 @@ pub enum Event<H: IntoConnectionHandler, TE> {
|
||||
/// A connection to a node has succeeded.
|
||||
Established { id: TaskId, info: Connected },
|
||||
/// A pending connection failed.
|
||||
Failed { id: TaskId, error: PendingConnectionError<TE>, handler: H },
|
||||
Failed {
|
||||
id: TaskId,
|
||||
error: PendingConnectionError<TE>,
|
||||
handler: H,
|
||||
},
|
||||
/// A node we are connected to has changed its address.
|
||||
AddressChange { id: TaskId, new_address: Multiaddr },
|
||||
/// Notify the manager of an event from the connection.
|
||||
Notify { id: TaskId, event: THandlerOutEvent<H> },
|
||||
Notify {
|
||||
id: TaskId,
|
||||
event: THandlerOutEvent<H>,
|
||||
},
|
||||
/// A connection closed, possibly due to an error.
|
||||
///
|
||||
/// If `error` is `None`, the connection has completed
|
||||
/// an active orderly close.
|
||||
Closed { id: TaskId, error: Option<ConnectionError<THandlerError<H>>> }
|
||||
Closed {
|
||||
id: TaskId,
|
||||
error: Option<ConnectionError<THandlerError<H>>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<H: IntoConnectionHandler, TE> Event<H, TE> {
|
||||
@ -91,7 +91,7 @@ pub struct Task<F, M, H, E>
|
||||
where
|
||||
M: StreamMuxer,
|
||||
H: IntoConnectionHandler,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>,
|
||||
{
|
||||
/// The ID of this task.
|
||||
id: TaskId,
|
||||
@ -110,7 +110,7 @@ impl<F, M, H, E> Task<F, M, H, E>
|
||||
where
|
||||
M: StreamMuxer,
|
||||
H: IntoConnectionHandler,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>,
|
||||
{
|
||||
/// Create a new task to connect and handle some node.
|
||||
pub fn pending(
|
||||
@ -118,7 +118,7 @@ where
|
||||
events: mpsc::Sender<Event<H, E>>,
|
||||
commands: mpsc::Receiver<Command<THandlerInEvent<H>>>,
|
||||
future: F,
|
||||
handler: H
|
||||
handler: H,
|
||||
) -> Self {
|
||||
Task {
|
||||
id,
|
||||
@ -136,13 +136,16 @@ where
|
||||
id: TaskId,
|
||||
events: mpsc::Sender<Event<H, E>>,
|
||||
commands: mpsc::Receiver<Command<THandlerInEvent<H>>>,
|
||||
connection: Connection<M, H::Handler>
|
||||
connection: Connection<M, H::Handler>,
|
||||
) -> Self {
|
||||
Task {
|
||||
id,
|
||||
events,
|
||||
commands: commands.fuse(),
|
||||
state: State::Established { connection, event: None },
|
||||
state: State::Established {
|
||||
connection,
|
||||
event: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +155,7 @@ enum State<F, M, H, E>
|
||||
where
|
||||
M: StreamMuxer,
|
||||
H: IntoConnectionHandler,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>,
|
||||
{
|
||||
/// The connection is being negotiated.
|
||||
Pending {
|
||||
@ -180,14 +183,14 @@ where
|
||||
Terminating(Event<H, E>),
|
||||
|
||||
/// The task has finished.
|
||||
Done
|
||||
Done,
|
||||
}
|
||||
|
||||
impl<F, M, H, E> Unpin for Task<F, M, H, E>
|
||||
where
|
||||
M: StreamMuxer,
|
||||
H: IntoConnectionHandler,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>>,
|
||||
{
|
||||
}
|
||||
|
||||
@ -196,9 +199,7 @@ where
|
||||
M: StreamMuxer,
|
||||
F: Future<Output = ConnectResult<M, E>>,
|
||||
H: IntoConnectionHandler,
|
||||
H::Handler: ConnectionHandler<
|
||||
Substream = Substream<M>,
|
||||
> + Send + 'static,
|
||||
H::Handler: ConnectionHandler<Substream = Substream<M>> + Send + 'static,
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
@ -211,33 +212,33 @@ where
|
||||
|
||||
'poll: loop {
|
||||
match std::mem::replace(&mut this.state, State::Done) {
|
||||
State::Pending { mut future, handler } => {
|
||||
State::Pending {
|
||||
mut future,
|
||||
handler,
|
||||
} => {
|
||||
// Check whether the task is still registered with a `Manager`
|
||||
// by polling the commands channel.
|
||||
match this.commands.poll_next_unpin(cx) {
|
||||
Poll::Pending => {},
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(None) => {
|
||||
// The manager has dropped the task; abort.
|
||||
return Poll::Ready(())
|
||||
return Poll::Ready(());
|
||||
}
|
||||
Poll::Ready(Some(_)) => {
|
||||
panic!("Task received command while the connection is pending.")
|
||||
}
|
||||
Poll::Ready(Some(_)) => panic!(
|
||||
"Task received command while the connection is pending."
|
||||
)
|
||||
}
|
||||
// Check if the connection succeeded.
|
||||
match future.poll_unpin(cx) {
|
||||
Poll::Ready(Ok((info, muxer))) => {
|
||||
this.state = State::Established {
|
||||
connection: Connection::new(
|
||||
muxer,
|
||||
handler.into_handler(&info),
|
||||
),
|
||||
event: Some(Event::Established { id, info })
|
||||
connection: Connection::new(muxer, handler.into_handler(&info)),
|
||||
event: Some(Event::Established { id, info }),
|
||||
}
|
||||
}
|
||||
Poll::Pending => {
|
||||
this.state = State::Pending { future, handler };
|
||||
return Poll::Pending
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(Err(error)) => {
|
||||
// Don't accept any further commands and terminate the
|
||||
@ -249,23 +250,27 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
State::Established { mut connection, event } => {
|
||||
State::Established {
|
||||
mut connection,
|
||||
event,
|
||||
} => {
|
||||
// Check for commands from the `Manager`.
|
||||
loop {
|
||||
match this.commands.poll_next_unpin(cx) {
|
||||
Poll::Pending => break,
|
||||
Poll::Ready(Some(Command::NotifyHandler(event))) =>
|
||||
connection.inject_event(event),
|
||||
Poll::Ready(Some(Command::NotifyHandler(event))) => {
|
||||
connection.inject_event(event)
|
||||
}
|
||||
Poll::Ready(Some(Command::Close)) => {
|
||||
// Don't accept any further commands.
|
||||
this.commands.get_mut().close();
|
||||
// Discard the event, if any, and start a graceful close.
|
||||
this.state = State::Closing(connection.close());
|
||||
continue 'poll
|
||||
continue 'poll;
|
||||
}
|
||||
Poll::Ready(None) => {
|
||||
// The manager has dropped the task or disappeared; abort.
|
||||
return Poll::Ready(())
|
||||
return Poll::Ready(());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,44 +279,56 @@ where
|
||||
// Send the event to the manager.
|
||||
match this.events.poll_ready(cx) {
|
||||
Poll::Pending => {
|
||||
this.state = State::Established { connection, event: Some(event) };
|
||||
return Poll::Pending
|
||||
this.state = State::Established {
|
||||
connection,
|
||||
event: Some(event),
|
||||
};
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(result) => {
|
||||
if result.is_ok() {
|
||||
if let Ok(()) = this.events.start_send(event) {
|
||||
this.state = State::Established { connection, event: None };
|
||||
continue 'poll
|
||||
this.state = State::Established {
|
||||
connection,
|
||||
event: None,
|
||||
};
|
||||
continue 'poll;
|
||||
}
|
||||
}
|
||||
// The manager is no longer reachable; abort.
|
||||
return Poll::Ready(())
|
||||
return Poll::Ready(());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Poll the connection for new events.
|
||||
match Connection::poll(Pin::new(&mut connection), cx) {
|
||||
Poll::Pending => {
|
||||
this.state = State::Established { connection, event: None };
|
||||
return Poll::Pending
|
||||
this.state = State::Established {
|
||||
connection,
|
||||
event: None,
|
||||
};
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(Ok(connection::Event::Handler(event))) => {
|
||||
this.state = State::Established {
|
||||
connection,
|
||||
event: Some(Event::Notify { id, event })
|
||||
event: Some(Event::Notify { id, event }),
|
||||
};
|
||||
}
|
||||
Poll::Ready(Ok(connection::Event::AddressChange(new_address))) => {
|
||||
this.state = State::Established {
|
||||
connection,
|
||||
event: Some(Event::AddressChange { id, new_address })
|
||||
event: Some(Event::AddressChange { id, new_address }),
|
||||
};
|
||||
}
|
||||
Poll::Ready(Err(error)) => {
|
||||
// Don't accept any further commands.
|
||||
this.commands.get_mut().close();
|
||||
// Terminate the task with the error, dropping the connection.
|
||||
let event = Event::Closed { id, error: Some(error) };
|
||||
let event = Event::Closed {
|
||||
id,
|
||||
error: Some(error),
|
||||
};
|
||||
this.state = State::Terminating(event);
|
||||
}
|
||||
}
|
||||
@ -322,19 +339,22 @@ where
|
||||
// Try to gracefully close the connection.
|
||||
match closing.poll_unpin(cx) {
|
||||
Poll::Ready(Ok(())) => {
|
||||
let event = Event::Closed { id: this.id, error: None };
|
||||
let event = Event::Closed {
|
||||
id: this.id,
|
||||
error: None,
|
||||
};
|
||||
this.state = State::Terminating(event);
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
let event = Event::Closed {
|
||||
id: this.id,
|
||||
error: Some(ConnectionError::IO(e))
|
||||
error: Some(ConnectionError::IO(e)),
|
||||
};
|
||||
this.state = State::Terminating(event);
|
||||
}
|
||||
Poll::Pending => {
|
||||
this.state = State::Closing(closing);
|
||||
return Poll::Pending
|
||||
return Poll::Pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -344,18 +364,18 @@ where
|
||||
match this.events.poll_ready(cx) {
|
||||
Poll::Pending => {
|
||||
self.state = State::Terminating(event);
|
||||
return Poll::Pending
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(result) => {
|
||||
if result.is_ok() {
|
||||
let _ = this.events.start_send(event);
|
||||
}
|
||||
return Poll::Ready(())
|
||||
return Poll::Ready(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State::Done => panic!("`Task::poll()` called after completion.")
|
||||
State::Done => panic!("`Task::poll()` called after completion."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,29 +19,15 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
ConnectedPoint,
|
||||
PeerId,
|
||||
connection::{
|
||||
self,
|
||||
Connected,
|
||||
Connection,
|
||||
ConnectionId,
|
||||
ConnectionLimit,
|
||||
ConnectionError,
|
||||
ConnectionHandler,
|
||||
IncomingInfo,
|
||||
IntoConnectionHandler,
|
||||
OutgoingInfo,
|
||||
Substream,
|
||||
PendingConnectionError,
|
||||
handler::{
|
||||
THandlerInEvent,
|
||||
THandlerOutEvent,
|
||||
THandlerError,
|
||||
},
|
||||
handler::{THandlerError, THandlerInEvent, THandlerOutEvent},
|
||||
manager::{self, Manager, ManagerConfig},
|
||||
Connected, Connection, ConnectionError, ConnectionHandler, ConnectionId, ConnectionLimit,
|
||||
IncomingInfo, IntoConnectionHandler, OutgoingInfo, PendingConnectionError, Substream,
|
||||
},
|
||||
muxing::StreamMuxer,
|
||||
ConnectedPoint, PeerId,
|
||||
};
|
||||
use either::Either;
|
||||
use fnv::FnvHashMap;
|
||||
@ -76,9 +62,7 @@ pub struct Pool<THandler: IntoConnectionHandler, TTransErr> {
|
||||
disconnected: Vec<Disconnected>,
|
||||
}
|
||||
|
||||
impl<THandler: IntoConnectionHandler, TTransErr> fmt::Debug
|
||||
for Pool<THandler, TTransErr>
|
||||
{
|
||||
impl<THandler: IntoConnectionHandler, TTransErr> fmt::Debug for Pool<THandler, TTransErr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("Pool")
|
||||
.field("counters", &self.counters)
|
||||
@ -86,8 +70,7 @@ for Pool<THandler, TTransErr>
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandler: IntoConnectionHandler, TTransErr> Unpin
|
||||
for Pool<THandler, TTransErr> {}
|
||||
impl<THandler: IntoConnectionHandler, TTransErr> Unpin for Pool<THandler, TTransErr> {}
|
||||
|
||||
/// Event that can happen on the `Pool`.
|
||||
pub enum PoolEvent<'a, THandler: IntoConnectionHandler, TTransErr> {
|
||||
@ -157,56 +140,60 @@ pub enum PoolEvent<'a, THandler: IntoConnectionHandler, TTransErr> {
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a, THandler: IntoConnectionHandler, TTransErr> fmt::Debug for PoolEvent<'a, THandler, TTransErr>
|
||||
impl<'a, THandler: IntoConnectionHandler, TTransErr> fmt::Debug
|
||||
for PoolEvent<'a, THandler, TTransErr>
|
||||
where
|
||||
TTransErr: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
PoolEvent::ConnectionEstablished { ref connection, .. } => {
|
||||
f.debug_tuple("PoolEvent::ConnectionEstablished")
|
||||
.field(connection)
|
||||
.finish()
|
||||
},
|
||||
PoolEvent::ConnectionClosed { ref id, ref connected, ref error, .. } => {
|
||||
f.debug_struct("PoolEvent::ConnectionClosed")
|
||||
.field("id", id)
|
||||
.field("connected", connected)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
},
|
||||
PoolEvent::PendingConnectionError { ref id, ref error, .. } => {
|
||||
f.debug_struct("PoolEvent::PendingConnectionError")
|
||||
.field("id", id)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
},
|
||||
PoolEvent::ConnectionEvent { ref connection, ref event } => {
|
||||
f.debug_struct("PoolEvent::ConnectionEvent")
|
||||
.field("peer", &connection.peer_id())
|
||||
.field("event", event)
|
||||
.finish()
|
||||
},
|
||||
PoolEvent::AddressChange { ref connection, ref new_endpoint, ref old_endpoint } => {
|
||||
f.debug_struct("PoolEvent::AddressChange")
|
||||
.field("peer", &connection.peer_id())
|
||||
.field("new_endpoint", new_endpoint)
|
||||
.field("old_endpoint", old_endpoint)
|
||||
.finish()
|
||||
},
|
||||
PoolEvent::ConnectionEstablished { ref connection, .. } => f
|
||||
.debug_tuple("PoolEvent::ConnectionEstablished")
|
||||
.field(connection)
|
||||
.finish(),
|
||||
PoolEvent::ConnectionClosed {
|
||||
ref id,
|
||||
ref connected,
|
||||
ref error,
|
||||
..
|
||||
} => f
|
||||
.debug_struct("PoolEvent::ConnectionClosed")
|
||||
.field("id", id)
|
||||
.field("connected", connected)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
PoolEvent::PendingConnectionError {
|
||||
ref id, ref error, ..
|
||||
} => f
|
||||
.debug_struct("PoolEvent::PendingConnectionError")
|
||||
.field("id", id)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
PoolEvent::ConnectionEvent {
|
||||
ref connection,
|
||||
ref event,
|
||||
} => f
|
||||
.debug_struct("PoolEvent::ConnectionEvent")
|
||||
.field("peer", &connection.peer_id())
|
||||
.field("event", event)
|
||||
.finish(),
|
||||
PoolEvent::AddressChange {
|
||||
ref connection,
|
||||
ref new_endpoint,
|
||||
ref old_endpoint,
|
||||
} => f
|
||||
.debug_struct("PoolEvent::AddressChange")
|
||||
.field("peer", &connection.peer_id())
|
||||
.field("new_endpoint", new_endpoint)
|
||||
.field("old_endpoint", old_endpoint)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
Pool<THandler, TTransErr>
|
||||
{
|
||||
impl<THandler: IntoConnectionHandler, TTransErr> Pool<THandler, TTransErr> {
|
||||
/// Creates a new empty `Pool`.
|
||||
pub fn new(
|
||||
local_id: PeerId,
|
||||
manager_config: ManagerConfig,
|
||||
limits: ConnectionLimits
|
||||
) -> Self {
|
||||
pub fn new(local_id: PeerId, manager_config: ManagerConfig, limits: ConnectionLimits) -> Self {
|
||||
Pool {
|
||||
local_id,
|
||||
counters: ConnectionCounters::new(limits),
|
||||
@ -234,13 +221,11 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
info: IncomingInfo<'_>,
|
||||
) -> Result<ConnectionId, ConnectionLimit>
|
||||
where
|
||||
TFut: Future<
|
||||
Output = Result<(PeerId, TMuxer), PendingConnectionError<TTransErr>>
|
||||
> + Send + 'static,
|
||||
TFut: Future<Output = Result<(PeerId, TMuxer), PendingConnectionError<TTransErr>>>
|
||||
+ Send
|
||||
+ 'static,
|
||||
THandler: IntoConnectionHandler + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<
|
||||
Substream = Substream<TMuxer>,
|
||||
> + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<Substream = Substream<TMuxer>> + Send + 'static,
|
||||
<THandler::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
TTransErr: error::Error + Send + 'static,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
@ -263,13 +248,11 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
info: OutgoingInfo<'_>,
|
||||
) -> Result<ConnectionId, ConnectionLimit>
|
||||
where
|
||||
TFut: Future<
|
||||
Output = Result<(PeerId, TMuxer), PendingConnectionError<TTransErr>>
|
||||
> + Send + 'static,
|
||||
TFut: Future<Output = Result<(PeerId, TMuxer), PendingConnectionError<TTransErr>>>
|
||||
+ Send
|
||||
+ 'static,
|
||||
THandler: IntoConnectionHandler + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<
|
||||
Substream = Substream<TMuxer>,
|
||||
> + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<Substream = Substream<TMuxer>> + Send + 'static,
|
||||
<THandler::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
TTransErr: error::Error + Send + 'static,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
@ -290,13 +273,11 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
peer: Option<PeerId>,
|
||||
) -> ConnectionId
|
||||
where
|
||||
TFut: Future<
|
||||
Output = Result<(PeerId, TMuxer), PendingConnectionError<TTransErr>>
|
||||
> + Send + 'static,
|
||||
TFut: Future<Output = Result<(PeerId, TMuxer), PendingConnectionError<TTransErr>>>
|
||||
+ Send
|
||||
+ 'static,
|
||||
THandler: IntoConnectionHandler + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<
|
||||
Substream = Substream<TMuxer>,
|
||||
> + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<Substream = Substream<TMuxer>> + Send + 'static,
|
||||
<THandler::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
TTransErr: error::Error + Send + 'static,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
@ -313,12 +294,12 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
move |(peer_id, muxer)| {
|
||||
if let Some(peer) = expected_peer {
|
||||
if peer != peer_id {
|
||||
return future::err(PendingConnectionError::InvalidPeerId)
|
||||
return future::err(PendingConnectionError::InvalidPeerId);
|
||||
}
|
||||
}
|
||||
|
||||
if local_id == peer_id {
|
||||
return future::err(PendingConnectionError::InvalidPeerId)
|
||||
return future::err(PendingConnectionError::InvalidPeerId);
|
||||
}
|
||||
|
||||
let connected = Connected { peer_id, endpoint };
|
||||
@ -337,73 +318,80 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
/// Returns the assigned connection ID on success. An error is returned
|
||||
/// if the configured maximum number of established connections for the
|
||||
/// connected peer has been reached.
|
||||
pub fn add<TMuxer>(&mut self, c: Connection<TMuxer, THandler::Handler>, i: Connected)
|
||||
-> Result<ConnectionId, ConnectionLimit>
|
||||
pub fn add<TMuxer>(
|
||||
&mut self,
|
||||
c: Connection<TMuxer, THandler::Handler>,
|
||||
i: Connected,
|
||||
) -> Result<ConnectionId, ConnectionLimit>
|
||||
where
|
||||
THandler: IntoConnectionHandler + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<
|
||||
Substream = connection::Substream<TMuxer>,
|
||||
> + Send + 'static,
|
||||
THandler::Handler:
|
||||
ConnectionHandler<Substream = connection::Substream<TMuxer>> + Send + 'static,
|
||||
<THandler::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
TTransErr: error::Error + Send + 'static,
|
||||
TMuxer: StreamMuxer + Send + Sync + 'static,
|
||||
TMuxer::OutboundSubstream: Send + 'static,
|
||||
{
|
||||
self.counters.check_max_established(&i.endpoint)?;
|
||||
self.counters.check_max_established_per_peer(self.num_peer_established(&i.peer_id))?;
|
||||
self.counters
|
||||
.check_max_established_per_peer(self.num_peer_established(&i.peer_id))?;
|
||||
let id = self.manager.add(c, i.clone());
|
||||
self.counters.inc_established(&i.endpoint);
|
||||
self.established.entry(i.peer_id).or_default().insert(id, i.endpoint);
|
||||
self.established
|
||||
.entry(i.peer_id)
|
||||
.or_default()
|
||||
.insert(id, i.endpoint);
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Gets an entry representing a connection in the pool.
|
||||
///
|
||||
/// Returns `None` if the pool has no connection with the given ID.
|
||||
pub fn get(&mut self, id: ConnectionId)
|
||||
-> Option<PoolConnection<'_, THandlerInEvent<THandler>>>
|
||||
{
|
||||
pub fn get(
|
||||
&mut self,
|
||||
id: ConnectionId,
|
||||
) -> Option<PoolConnection<'_, THandlerInEvent<THandler>>> {
|
||||
match self.manager.entry(id) {
|
||||
Some(manager::Entry::Established(entry)) =>
|
||||
Some(PoolConnection::Established(EstablishedConnection {
|
||||
entry
|
||||
})),
|
||||
Some(manager::Entry::Pending(entry)) =>
|
||||
Some(manager::Entry::Established(entry)) => {
|
||||
Some(PoolConnection::Established(EstablishedConnection { entry }))
|
||||
}
|
||||
Some(manager::Entry::Pending(entry)) => {
|
||||
Some(PoolConnection::Pending(PendingConnection {
|
||||
entry,
|
||||
pending: &mut self.pending,
|
||||
counters: &mut self.counters,
|
||||
})),
|
||||
None => None
|
||||
}))
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an established connection from the pool by ID.
|
||||
pub fn get_established(&mut self, id: ConnectionId)
|
||||
-> Option<EstablishedConnection<'_, THandlerInEvent<THandler>>>
|
||||
{
|
||||
pub fn get_established(
|
||||
&mut self,
|
||||
id: ConnectionId,
|
||||
) -> Option<EstablishedConnection<'_, THandlerInEvent<THandler>>> {
|
||||
match self.get(id) {
|
||||
Some(PoolConnection::Established(c)) => Some(c),
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a pending outgoing connection by ID.
|
||||
pub fn get_outgoing(&mut self, id: ConnectionId)
|
||||
-> Option<PendingConnection<'_, THandlerInEvent<THandler>>>
|
||||
{
|
||||
pub fn get_outgoing(
|
||||
&mut self,
|
||||
id: ConnectionId,
|
||||
) -> Option<PendingConnection<'_, THandlerInEvent<THandler>>> {
|
||||
match self.pending.get(&id) {
|
||||
Some((ConnectedPoint::Dialer { .. }, _peer)) =>
|
||||
match self.manager.entry(id) {
|
||||
Some(manager::Entry::Pending(entry)) =>
|
||||
Some(PendingConnection {
|
||||
entry,
|
||||
pending: &mut self.pending,
|
||||
counters: &mut self.counters,
|
||||
}),
|
||||
_ => unreachable!("by consistency of `self.pending` with `self.manager`")
|
||||
}
|
||||
_ => None
|
||||
Some((ConnectedPoint::Dialer { .. }, _peer)) => match self.manager.entry(id) {
|
||||
Some(manager::Entry::Pending(entry)) => Some(PendingConnection {
|
||||
entry,
|
||||
pending: &mut self.pending,
|
||||
counters: &mut self.counters,
|
||||
}),
|
||||
_ => unreachable!("by consistency of `self.pending` with `self.manager`"),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,7 +425,9 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
if let Some(manager::Entry::Established(e)) = self.manager.entry(id) {
|
||||
let connected = e.remove();
|
||||
self.disconnected.push(Disconnected {
|
||||
id, connected, num_established
|
||||
id,
|
||||
connected,
|
||||
num_established,
|
||||
});
|
||||
num_established += 1;
|
||||
}
|
||||
@ -468,14 +458,13 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
}
|
||||
|
||||
/// Returns an iterator over all established connections of `peer`.
|
||||
pub fn iter_peer_established<'a>(&'a mut self, peer: &PeerId)
|
||||
-> EstablishedConnectionIter<'a,
|
||||
impl Iterator<Item = ConnectionId>,
|
||||
THandler,
|
||||
TTransErr,
|
||||
>
|
||||
pub fn iter_peer_established<'a>(
|
||||
&'a mut self,
|
||||
peer: &PeerId,
|
||||
) -> EstablishedConnectionIter<'a, impl Iterator<Item = ConnectionId>, THandler, TTransErr>
|
||||
{
|
||||
let ids = self.iter_peer_established_info(peer)
|
||||
let ids = self
|
||||
.iter_peer_established_info(peer)
|
||||
.map(|(id, _endpoint)| *id)
|
||||
.collect::<SmallVec<[ConnectionId; 10]>>()
|
||||
.into_iter();
|
||||
@ -486,45 +475,50 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
/// Returns an iterator for information on all pending incoming connections.
|
||||
pub fn iter_pending_incoming(&self) -> impl Iterator<Item = IncomingInfo<'_>> {
|
||||
self.iter_pending_info()
|
||||
.filter_map(|(_, ref endpoint, _)| {
|
||||
match endpoint {
|
||||
ConnectedPoint::Listener { local_addr, send_back_addr } => {
|
||||
Some(IncomingInfo { local_addr, send_back_addr })
|
||||
},
|
||||
ConnectedPoint::Dialer { .. } => None,
|
||||
}
|
||||
.filter_map(|(_, ref endpoint, _)| match endpoint {
|
||||
ConnectedPoint::Listener {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
} => Some(IncomingInfo {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
}),
|
||||
ConnectedPoint::Dialer { .. } => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns an iterator for information on all pending outgoing connections.
|
||||
pub fn iter_pending_outgoing(&self) -> impl Iterator<Item = OutgoingInfo<'_>> {
|
||||
self.iter_pending_info()
|
||||
.filter_map(|(_, ref endpoint, ref peer_id)| {
|
||||
match endpoint {
|
||||
ConnectedPoint::Listener { .. } => None,
|
||||
ConnectedPoint::Dialer { address } =>
|
||||
Some(OutgoingInfo { address, peer_id: peer_id.as_ref() }),
|
||||
}
|
||||
.filter_map(|(_, ref endpoint, ref peer_id)| match endpoint {
|
||||
ConnectedPoint::Listener { .. } => None,
|
||||
ConnectedPoint::Dialer { address } => Some(OutgoingInfo {
|
||||
address,
|
||||
peer_id: peer_id.as_ref(),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns an iterator over all connection IDs and associated endpoints
|
||||
/// of established connections to `peer` known to the pool.
|
||||
pub fn iter_peer_established_info(&self, peer: &PeerId)
|
||||
-> impl Iterator<Item = (&ConnectionId, &ConnectedPoint)> + fmt::Debug + '_
|
||||
{
|
||||
pub fn iter_peer_established_info(
|
||||
&self,
|
||||
peer: &PeerId,
|
||||
) -> impl Iterator<Item = (&ConnectionId, &ConnectedPoint)> + fmt::Debug + '_ {
|
||||
match self.established.get(peer) {
|
||||
Some(conns) => Either::Left(conns.iter()),
|
||||
None => Either::Right(std::iter::empty())
|
||||
None => Either::Right(std::iter::empty()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator over all pending connection IDs together
|
||||
/// with associated endpoints and expected peer IDs in the pool.
|
||||
pub fn iter_pending_info(&self)
|
||||
-> impl Iterator<Item = (&ConnectionId, &ConnectedPoint, &Option<PeerId>)> + '_
|
||||
{
|
||||
self.pending.iter().map(|(id, (endpoint, info))| (id, endpoint, info))
|
||||
pub fn iter_pending_info(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&ConnectionId, &ConnectedPoint, &Option<PeerId>)> + '_ {
|
||||
self.pending
|
||||
.iter()
|
||||
.map(|(id, (endpoint, info))| (id, endpoint, info))
|
||||
}
|
||||
|
||||
/// Returns an iterator over all connected peers, i.e. those that have
|
||||
@ -537,9 +531,10 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
///
|
||||
/// > **Note**: We use a regular `poll` method instead of implementing `Stream`,
|
||||
/// > because we want the `Pool` to stay borrowed if necessary.
|
||||
pub fn poll<'a>(&'a mut self, cx: &mut Context<'_>) -> Poll<
|
||||
PoolEvent<'a, THandler, TTransErr>
|
||||
> {
|
||||
pub fn poll<'a>(
|
||||
&'a mut self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<PoolEvent<'a, THandler, TTransErr>> {
|
||||
// Drain events resulting from forced disconnections.
|
||||
//
|
||||
// Note: The `Disconnected` entries in `self.disconnected`
|
||||
@ -548,15 +543,18 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
// events in an order that properly counts down `num_established`.
|
||||
// See also `Pool::disconnect`.
|
||||
if let Some(Disconnected {
|
||||
id, connected, num_established
|
||||
}) = self.disconnected.pop() {
|
||||
id,
|
||||
connected,
|
||||
num_established,
|
||||
}) = self.disconnected.pop()
|
||||
{
|
||||
return Poll::Ready(PoolEvent::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
num_established,
|
||||
error: None,
|
||||
pool: self,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Poll the connection `Manager`.
|
||||
@ -576,11 +574,15 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
error,
|
||||
handler: Some(handler),
|
||||
peer,
|
||||
pool: self
|
||||
})
|
||||
pool: self,
|
||||
});
|
||||
}
|
||||
},
|
||||
manager::Event::ConnectionClosed { id, connected, error } => {
|
||||
}
|
||||
manager::Event::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
error,
|
||||
} => {
|
||||
let num_established =
|
||||
if let Some(conns) = self.established.get_mut(&connected.peer_id) {
|
||||
if let Some(endpoint) = conns.remove(&id) {
|
||||
@ -594,8 +596,12 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
self.established.remove(&connected.peer_id);
|
||||
}
|
||||
return Poll::Ready(PoolEvent::ConnectionClosed {
|
||||
id, connected, error, num_established, pool: self
|
||||
})
|
||||
id,
|
||||
connected,
|
||||
error,
|
||||
num_established,
|
||||
pool: self,
|
||||
});
|
||||
}
|
||||
manager::Event::ConnectionEstablished { entry } => {
|
||||
let id = entry.id();
|
||||
@ -611,12 +617,13 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
error: PendingConnectionError::ConnectionLimit(e),
|
||||
handler: None,
|
||||
peer,
|
||||
pool: self
|
||||
})
|
||||
pool: self,
|
||||
});
|
||||
}
|
||||
|
||||
// Check per-peer established connection limit.
|
||||
let current = num_peer_established(&self.established, &entry.connected().peer_id);
|
||||
let current =
|
||||
num_peer_established(&self.established, &entry.connected().peer_id);
|
||||
if let Err(e) = self.counters.check_max_established_per_peer(current) {
|
||||
let connected = entry.remove();
|
||||
return Poll::Ready(PoolEvent::PendingConnectionError {
|
||||
@ -625,8 +632,8 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
error: PendingConnectionError::ConnectionLimit(e),
|
||||
handler: None,
|
||||
peer,
|
||||
pool: self
|
||||
})
|
||||
pool: self,
|
||||
});
|
||||
}
|
||||
|
||||
// Peer ID checks must already have happened. See `add_pending`.
|
||||
@ -644,54 +651,62 @@ impl<THandler: IntoConnectionHandler, TTransErr>
|
||||
// Add the connection to the pool.
|
||||
let peer = entry.connected().peer_id;
|
||||
let conns = self.established.entry(peer).or_default();
|
||||
let num_established = NonZeroU32::new(u32::try_from(conns.len() + 1).unwrap())
|
||||
.expect("n + 1 is always non-zero; qed");
|
||||
let num_established =
|
||||
NonZeroU32::new(u32::try_from(conns.len() + 1).unwrap())
|
||||
.expect("n + 1 is always non-zero; qed");
|
||||
self.counters.inc_established(&endpoint);
|
||||
conns.insert(id, endpoint);
|
||||
match self.get(id) {
|
||||
Some(PoolConnection::Established(connection)) =>
|
||||
Some(PoolConnection::Established(connection)) => {
|
||||
return Poll::Ready(PoolEvent::ConnectionEstablished {
|
||||
connection, num_established
|
||||
}),
|
||||
_ => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||
connection,
|
||||
num_established,
|
||||
})
|
||||
}
|
||||
_ => unreachable!("since `entry` is an `EstablishedEntry`."),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
manager::Event::ConnectionEvent { entry, event } => {
|
||||
let id = entry.id();
|
||||
match self.get(id) {
|
||||
Some(PoolConnection::Established(connection)) =>
|
||||
return Poll::Ready(PoolEvent::ConnectionEvent {
|
||||
connection,
|
||||
event,
|
||||
}),
|
||||
_ => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||
Some(PoolConnection::Established(connection)) => {
|
||||
return Poll::Ready(PoolEvent::ConnectionEvent { connection, event })
|
||||
}
|
||||
_ => unreachable!("since `entry` is an `EstablishedEntry`."),
|
||||
}
|
||||
},
|
||||
manager::Event::AddressChange { entry, new_endpoint, old_endpoint } => {
|
||||
}
|
||||
manager::Event::AddressChange {
|
||||
entry,
|
||||
new_endpoint,
|
||||
old_endpoint,
|
||||
} => {
|
||||
let id = entry.id();
|
||||
|
||||
match self.established.get_mut(&entry.connected().peer_id) {
|
||||
Some(list) => *list.get_mut(&id)
|
||||
.expect("state inconsistency: entry is `EstablishedEntry` but absent \
|
||||
from `established`") = new_endpoint.clone(),
|
||||
None => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||
Some(list) => {
|
||||
*list.get_mut(&id).expect(
|
||||
"state inconsistency: entry is `EstablishedEntry` but absent \
|
||||
from `established`",
|
||||
) = new_endpoint.clone()
|
||||
}
|
||||
None => unreachable!("since `entry` is an `EstablishedEntry`."),
|
||||
};
|
||||
|
||||
match self.get(id) {
|
||||
Some(PoolConnection::Established(connection)) =>
|
||||
Some(PoolConnection::Established(connection)) => {
|
||||
return Poll::Ready(PoolEvent::AddressChange {
|
||||
connection,
|
||||
new_endpoint,
|
||||
old_endpoint,
|
||||
}),
|
||||
_ => unreachable!("since `entry` is an `EstablishedEntry`.")
|
||||
})
|
||||
}
|
||||
_ => unreachable!("since `entry` is an `EstablishedEntry`."),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// A connection in a [`Pool`].
|
||||
@ -707,9 +722,7 @@ pub struct PendingConnection<'a, TInEvent> {
|
||||
counters: &'a mut ConnectionCounters,
|
||||
}
|
||||
|
||||
impl<TInEvent>
|
||||
PendingConnection<'_, TInEvent>
|
||||
{
|
||||
impl<TInEvent> PendingConnection<'_, TInEvent> {
|
||||
/// Returns the local connection ID.
|
||||
pub fn id(&self) -> ConnectionId {
|
||||
self.entry.id()
|
||||
@ -717,17 +730,29 @@ impl<TInEvent>
|
||||
|
||||
/// Returns the (expected) identity of the remote peer, if known.
|
||||
pub fn peer_id(&self) -> &Option<PeerId> {
|
||||
&self.pending.get(&self.entry.id()).expect("`entry` is a pending entry").1
|
||||
&self
|
||||
.pending
|
||||
.get(&self.entry.id())
|
||||
.expect("`entry` is a pending entry")
|
||||
.1
|
||||
}
|
||||
|
||||
/// Returns information about this endpoint of the connection.
|
||||
pub fn endpoint(&self) -> &ConnectedPoint {
|
||||
&self.pending.get(&self.entry.id()).expect("`entry` is a pending entry").0
|
||||
&self
|
||||
.pending
|
||||
.get(&self.entry.id())
|
||||
.expect("`entry` is a pending entry")
|
||||
.0
|
||||
}
|
||||
|
||||
/// Aborts the connection attempt, closing the connection.
|
||||
pub fn abort(self) {
|
||||
let endpoint = self.pending.remove(&self.entry.id()).expect("`entry` is a pending entry").0;
|
||||
let endpoint = self
|
||||
.pending
|
||||
.remove(&self.entry.id())
|
||||
.expect("`entry` is a pending entry")
|
||||
.0;
|
||||
self.counters.dec_pending(&endpoint);
|
||||
self.entry.abort();
|
||||
}
|
||||
@ -738,8 +763,7 @@ pub struct EstablishedConnection<'a, TInEvent> {
|
||||
entry: manager::EstablishedEntry<'a, TInEvent>,
|
||||
}
|
||||
|
||||
impl<TInEvent> fmt::Debug
|
||||
for EstablishedConnection<'_, TInEvent>
|
||||
impl<TInEvent> fmt::Debug for EstablishedConnection<'_, TInEvent>
|
||||
where
|
||||
TInEvent: fmt::Debug,
|
||||
{
|
||||
@ -790,7 +814,7 @@ impl<TInEvent> EstablishedConnection<'_, TInEvent> {
|
||||
///
|
||||
/// Returns `Err(())` if the background task associated with the connection
|
||||
/// is terminating and the connection is about to close.
|
||||
pub fn poll_ready_notify_handler(&mut self, cx: &mut Context<'_>) -> Poll<Result<(),()>> {
|
||||
pub fn poll_ready_notify_handler(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ()>> {
|
||||
self.entry.poll_ready_notify_handler(cx)
|
||||
}
|
||||
|
||||
@ -811,21 +835,22 @@ pub struct EstablishedConnectionIter<'a, I, THandler: IntoConnectionHandler, TTr
|
||||
// Note: Ideally this would be an implementation of `Iterator`, but that
|
||||
// requires GATs (cf. https://github.com/rust-lang/rust/issues/44265) and
|
||||
// a different definition of `Iterator`.
|
||||
impl<'a, I, THandler: IntoConnectionHandler, TTransErr> EstablishedConnectionIter<'a, I, THandler, TTransErr>
|
||||
impl<'a, I, THandler: IntoConnectionHandler, TTransErr>
|
||||
EstablishedConnectionIter<'a, I, THandler, TTransErr>
|
||||
where
|
||||
I: Iterator<Item = ConnectionId>
|
||||
I: Iterator<Item = ConnectionId>,
|
||||
{
|
||||
/// Obtains the next connection, if any.
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn next(&mut self) -> Option<EstablishedConnection<'_, THandlerInEvent<THandler>>>
|
||||
{
|
||||
pub fn next(&mut self) -> Option<EstablishedConnection<'_, THandlerInEvent<THandler>>> {
|
||||
while let Some(id) = self.ids.next() {
|
||||
if self.pool.manager.is_established(&id) { // (*)
|
||||
if self.pool.manager.is_established(&id) {
|
||||
// (*)
|
||||
match self.pool.manager.entry(id) {
|
||||
Some(manager::Entry::Established(entry)) => {
|
||||
return Some(EstablishedConnection { entry })
|
||||
}
|
||||
_ => panic!("Established entry not found in manager.") // see (*)
|
||||
_ => panic!("Established entry not found in manager."), // see (*)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -838,17 +863,18 @@ where
|
||||
}
|
||||
|
||||
/// Returns the first connection, if any, consuming the iterator.
|
||||
pub fn into_first<'b>(mut self)
|
||||
-> Option<EstablishedConnection<'b, THandlerInEvent<THandler>>>
|
||||
where 'a: 'b
|
||||
pub fn into_first<'b>(mut self) -> Option<EstablishedConnection<'b, THandlerInEvent<THandler>>>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
while let Some(id) = self.ids.next() {
|
||||
if self.pool.manager.is_established(&id) { // (*)
|
||||
if self.pool.manager.is_established(&id) {
|
||||
// (*)
|
||||
match self.pool.manager.entry(id) {
|
||||
Some(manager::Entry::Established(entry)) => {
|
||||
return Some(EstablishedConnection { entry })
|
||||
}
|
||||
_ => panic!("Established entry not found in manager.") // see (*)
|
||||
_ => panic!("Established entry not found in manager."), // see (*)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -924,29 +950,45 @@ impl ConnectionCounters {
|
||||
|
||||
fn inc_pending(&mut self, endpoint: &ConnectedPoint) {
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { .. } => { self.pending_outgoing += 1; }
|
||||
ConnectedPoint::Listener { .. } => { self.pending_incoming += 1; }
|
||||
ConnectedPoint::Dialer { .. } => {
|
||||
self.pending_outgoing += 1;
|
||||
}
|
||||
ConnectedPoint::Listener { .. } => {
|
||||
self.pending_incoming += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dec_pending(&mut self, endpoint: &ConnectedPoint) {
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { .. } => { self.pending_outgoing -= 1; }
|
||||
ConnectedPoint::Listener { .. } => { self.pending_incoming -= 1; }
|
||||
ConnectedPoint::Dialer { .. } => {
|
||||
self.pending_outgoing -= 1;
|
||||
}
|
||||
ConnectedPoint::Listener { .. } => {
|
||||
self.pending_incoming -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn inc_established(&mut self, endpoint: &ConnectedPoint) {
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { .. } => { self.established_outgoing += 1; }
|
||||
ConnectedPoint::Listener { .. } => { self.established_incoming += 1; }
|
||||
ConnectedPoint::Dialer { .. } => {
|
||||
self.established_outgoing += 1;
|
||||
}
|
||||
ConnectedPoint::Listener { .. } => {
|
||||
self.established_incoming += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dec_established(&mut self, endpoint: &ConnectedPoint) {
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { .. } => { self.established_outgoing -= 1; }
|
||||
ConnectedPoint::Listener { .. } => { self.established_incoming -= 1; }
|
||||
ConnectedPoint::Dialer { .. } => {
|
||||
self.established_outgoing -= 1;
|
||||
}
|
||||
ConnectedPoint::Listener { .. } => {
|
||||
self.established_incoming -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,18 +1000,19 @@ impl ConnectionCounters {
|
||||
Self::check(self.pending_incoming, self.limits.max_pending_incoming)
|
||||
}
|
||||
|
||||
fn check_max_established(&self, endpoint: &ConnectedPoint)
|
||||
-> Result<(), ConnectionLimit>
|
||||
{
|
||||
fn check_max_established(&self, endpoint: &ConnectedPoint) -> Result<(), ConnectionLimit> {
|
||||
// Check total connection limit.
|
||||
Self::check(self.num_established(), self.limits.max_established_total)?;
|
||||
// Check incoming/outgoing connection limits
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { .. } =>
|
||||
Self::check(self.established_outgoing, self.limits.max_established_outgoing),
|
||||
ConnectedPoint::Listener { .. } => {
|
||||
Self::check(self.established_incoming, self.limits.max_established_incoming)
|
||||
}
|
||||
ConnectedPoint::Dialer { .. } => Self::check(
|
||||
self.established_outgoing,
|
||||
self.limits.max_established_outgoing,
|
||||
),
|
||||
ConnectedPoint::Listener { .. } => Self::check(
|
||||
self.established_incoming,
|
||||
self.limits.max_established_incoming,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -980,22 +1023,21 @@ impl ConnectionCounters {
|
||||
fn check(current: u32, limit: Option<u32>) -> Result<(), ConnectionLimit> {
|
||||
if let Some(limit) = limit {
|
||||
if current >= limit {
|
||||
return Err(ConnectionLimit { limit, current })
|
||||
return Err(ConnectionLimit { limit, current });
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Counts the number of established connections to the given peer.
|
||||
fn num_peer_established(
|
||||
established: &FnvHashMap<PeerId, FnvHashMap<ConnectionId, ConnectedPoint>>,
|
||||
peer: &PeerId
|
||||
peer: &PeerId,
|
||||
) -> u32 {
|
||||
established.get(peer).map_or(0, |conns|
|
||||
u32::try_from(conns.len())
|
||||
.expect("Unexpectedly large number of connections for a peer."))
|
||||
established.get(peer).map_or(0, |conns| {
|
||||
u32::try_from(conns.len()).expect("Unexpectedly large number of connections for a peer.")
|
||||
})
|
||||
}
|
||||
|
||||
/// The configurable connection limits.
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::muxing::{StreamMuxer, StreamMuxerEvent, SubstreamRef, substream_from_ref};
|
||||
use crate::muxing::{substream_from_ref, StreamMuxer, StreamMuxerEvent, SubstreamRef};
|
||||
use futures::prelude::*;
|
||||
use multiaddr::Multiaddr;
|
||||
use smallvec::SmallVec;
|
||||
@ -135,7 +135,9 @@ where
|
||||
#[must_use]
|
||||
pub fn close(mut self) -> (Close<TMuxer>, Vec<TUserData>) {
|
||||
let substreams = self.cancel_outgoing();
|
||||
let close = Close { muxer: self.inner.clone() };
|
||||
let close = Close {
|
||||
muxer: self.inner.clone(),
|
||||
};
|
||||
(close, substreams)
|
||||
}
|
||||
|
||||
@ -150,17 +152,19 @@ where
|
||||
}
|
||||
|
||||
/// Provides an API similar to `Future`.
|
||||
pub fn poll(&mut self, cx: &mut Context<'_>) -> Poll<Result<SubstreamEvent<TMuxer, TUserData>, IoError>> {
|
||||
pub fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<SubstreamEvent<TMuxer, TUserData>, IoError>> {
|
||||
// Polling inbound substream.
|
||||
match self.inner.poll_event(cx) {
|
||||
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(substream))) => {
|
||||
let substream = substream_from_ref(self.inner.clone(), substream);
|
||||
return Poll::Ready(Ok(SubstreamEvent::InboundSubstream {
|
||||
substream,
|
||||
}));
|
||||
return Poll::Ready(Ok(SubstreamEvent::InboundSubstream { substream }));
|
||||
}
|
||||
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(addr))) => {
|
||||
return Poll::Ready(Ok(SubstreamEvent::AddressChange(addr)))
|
||||
}
|
||||
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(addr))) =>
|
||||
return Poll::Ready(Ok(SubstreamEvent::AddressChange(addr))),
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
Poll::Pending => {}
|
||||
}
|
||||
@ -238,8 +242,7 @@ where
|
||||
TMuxer: StreamMuxer,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("Close")
|
||||
.finish()
|
||||
f.debug_struct("Close").finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,22 +254,22 @@ where
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
SubstreamEvent::InboundSubstream { substream } => {
|
||||
f.debug_struct("SubstreamEvent::OutboundClosed")
|
||||
.field("substream", substream)
|
||||
.finish()
|
||||
},
|
||||
SubstreamEvent::OutboundSubstream { user_data, substream } => {
|
||||
f.debug_struct("SubstreamEvent::OutboundSubstream")
|
||||
.field("user_data", user_data)
|
||||
.field("substream", substream)
|
||||
.finish()
|
||||
},
|
||||
SubstreamEvent::AddressChange(address) => {
|
||||
f.debug_struct("SubstreamEvent::AddressChange")
|
||||
.field("address", address)
|
||||
.finish()
|
||||
},
|
||||
SubstreamEvent::InboundSubstream { substream } => f
|
||||
.debug_struct("SubstreamEvent::OutboundClosed")
|
||||
.field("substream", substream)
|
||||
.finish(),
|
||||
SubstreamEvent::OutboundSubstream {
|
||||
user_data,
|
||||
substream,
|
||||
} => f
|
||||
.debug_struct("SubstreamEvent::OutboundSubstream")
|
||||
.field("user_data", user_data)
|
||||
.field("substream", substream)
|
||||
.finish(),
|
||||
SubstreamEvent::AddressChange(address) => f
|
||||
.debug_struct("SubstreamEvent::AddressChange")
|
||||
.field("address", address)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,29 +20,31 @@
|
||||
|
||||
use crate::{
|
||||
muxing::{StreamMuxer, StreamMuxerEvent},
|
||||
ProtocolName,
|
||||
transport::{Transport, ListenerEvent, TransportError},
|
||||
Multiaddr
|
||||
transport::{ListenerEvent, Transport, TransportError},
|
||||
Multiaddr, ProtocolName,
|
||||
};
|
||||
use futures::{
|
||||
io::{IoSlice, IoSliceMut},
|
||||
prelude::*,
|
||||
};
|
||||
use futures::{prelude::*, io::{IoSlice, IoSliceMut}};
|
||||
use pin_project::pin_project;
|
||||
use std::{fmt, io::{Error as IoError}, pin::Pin, task::Context, task::Poll};
|
||||
use std::{fmt, io::Error as IoError, pin::Pin, task::Context, task::Poll};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum EitherError<A, B> {
|
||||
A(A),
|
||||
B(B)
|
||||
B(B),
|
||||
}
|
||||
|
||||
impl<A, B> fmt::Display for EitherError<A, B>
|
||||
where
|
||||
A: fmt::Display,
|
||||
B: fmt::Display
|
||||
B: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
EitherError::A(a) => a.fmt(f),
|
||||
EitherError::B(b) => b.fmt(f)
|
||||
EitherError::B(b) => b.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,12 +52,12 @@ where
|
||||
impl<A, B> std::error::Error for EitherError<A, B>
|
||||
where
|
||||
A: std::error::Error,
|
||||
B: std::error::Error
|
||||
B: std::error::Error,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
EitherError::A(a) => a.source(),
|
||||
EitherError::B(b) => b.source()
|
||||
EitherError::B(b) => b.source(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,16 +76,22 @@ where
|
||||
A: AsyncRead,
|
||||
B: AsyncRead,
|
||||
{
|
||||
fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize, IoError>> {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, IoError>> {
|
||||
match self.project() {
|
||||
EitherOutputProj::First(a) => AsyncRead::poll_read(a, cx, buf),
|
||||
EitherOutputProj::Second(b) => AsyncRead::poll_read(b, cx, buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_read_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>])
|
||||
-> Poll<Result<usize, IoError>>
|
||||
{
|
||||
fn poll_read_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<Result<usize, IoError>> {
|
||||
match self.project() {
|
||||
EitherOutputProj::First(a) => AsyncRead::poll_read_vectored(a, cx, bufs),
|
||||
EitherOutputProj::Second(b) => AsyncRead::poll_read_vectored(b, cx, bufs),
|
||||
@ -96,16 +104,22 @@ where
|
||||
A: AsyncWrite,
|
||||
B: AsyncWrite,
|
||||
{
|
||||
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize, IoError>> {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, IoError>> {
|
||||
match self.project() {
|
||||
EitherOutputProj::First(a) => AsyncWrite::poll_write(a, cx, buf),
|
||||
EitherOutputProj::Second(b) => AsyncWrite::poll_write(b, cx, buf),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>])
|
||||
-> Poll<Result<usize, IoError>>
|
||||
{
|
||||
fn poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<Result<usize, IoError>> {
|
||||
match self.project() {
|
||||
EitherOutputProj::First(a) => AsyncWrite::poll_write_vectored(a, cx, bufs),
|
||||
EitherOutputProj::Second(b) => AsyncWrite::poll_write_vectored(b, cx, bufs),
|
||||
@ -136,10 +150,12 @@ where
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
match self.project() {
|
||||
EitherOutputProj::First(a) => TryStream::try_poll_next(a, cx)
|
||||
.map(|v| v.map(|r| r.map_err(EitherError::A))),
|
||||
EitherOutputProj::Second(b) => TryStream::try_poll_next(b, cx)
|
||||
.map(|v| v.map(|r| r.map_err(EitherError::B))),
|
||||
EitherOutputProj::First(a) => {
|
||||
TryStream::try_poll_next(a, cx).map(|v| v.map(|r| r.map_err(EitherError::A)))
|
||||
}
|
||||
EitherOutputProj::Second(b) => {
|
||||
TryStream::try_poll_next(b, cx).map(|v| v.map(|r| r.map_err(EitherError::B)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,23 +205,24 @@ where
|
||||
type OutboundSubstream = EitherOutbound<A, B>;
|
||||
type Error = IoError;
|
||||
|
||||
fn poll_event(&self, cx: &mut Context<'_>) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||
fn poll_event(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||
match self {
|
||||
EitherOutput::First(inner) => inner.poll_event(cx).map(|result| {
|
||||
result.map_err(|e| e.into()).map(|event| {
|
||||
match event {
|
||||
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||
StreamMuxerEvent::InboundSubstream(substream) =>
|
||||
StreamMuxerEvent::InboundSubstream(EitherOutput::First(substream))
|
||||
result.map_err(|e| e.into()).map(|event| match event {
|
||||
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||
StreamMuxerEvent::InboundSubstream(substream) => {
|
||||
StreamMuxerEvent::InboundSubstream(EitherOutput::First(substream))
|
||||
}
|
||||
})
|
||||
}),
|
||||
EitherOutput::Second(inner) => inner.poll_event(cx).map(|result| {
|
||||
result.map_err(|e| e.into()).map(|event| {
|
||||
match event {
|
||||
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||
StreamMuxerEvent::InboundSubstream(substream) =>
|
||||
StreamMuxerEvent::InboundSubstream(EitherOutput::Second(substream))
|
||||
result.map_err(|e| e.into()).map(|event| match event {
|
||||
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||
StreamMuxerEvent::InboundSubstream(substream) => {
|
||||
StreamMuxerEvent::InboundSubstream(EitherOutput::Second(substream))
|
||||
}
|
||||
})
|
||||
}),
|
||||
@ -219,96 +236,112 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_outbound(&self, cx: &mut Context<'_>, substream: &mut Self::OutboundSubstream) -> Poll<Result<Self::Substream, Self::Error>> {
|
||||
fn poll_outbound(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
substream: &mut Self::OutboundSubstream,
|
||||
) -> Poll<Result<Self::Substream, Self::Error>> {
|
||||
match (self, substream) {
|
||||
(EitherOutput::First(ref inner), EitherOutbound::A(ref mut substream)) => {
|
||||
inner.poll_outbound(cx, substream).map(|p| p.map(EitherOutput::First)).map_err(|e| e.into())
|
||||
},
|
||||
(EitherOutput::Second(ref inner), EitherOutbound::B(ref mut substream)) => {
|
||||
inner.poll_outbound(cx, substream).map(|p| p.map(EitherOutput::Second)).map_err(|e| e.into())
|
||||
},
|
||||
_ => panic!("Wrong API usage")
|
||||
(EitherOutput::First(ref inner), EitherOutbound::A(ref mut substream)) => inner
|
||||
.poll_outbound(cx, substream)
|
||||
.map(|p| p.map(EitherOutput::First))
|
||||
.map_err(|e| e.into()),
|
||||
(EitherOutput::Second(ref inner), EitherOutbound::B(ref mut substream)) => inner
|
||||
.poll_outbound(cx, substream)
|
||||
.map(|p| p.map(EitherOutput::Second))
|
||||
.map_err(|e| e.into()),
|
||||
_ => panic!("Wrong API usage"),
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_outbound(&self, substream: Self::OutboundSubstream) {
|
||||
match self {
|
||||
EitherOutput::First(inner) => {
|
||||
match substream {
|
||||
EitherOutbound::A(substream) => inner.destroy_outbound(substream),
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
EitherOutput::First(inner) => match substream {
|
||||
EitherOutbound::A(substream) => inner.destroy_outbound(substream),
|
||||
_ => panic!("Wrong API usage"),
|
||||
},
|
||||
EitherOutput::Second(inner) => {
|
||||
match substream {
|
||||
EitherOutbound::B(substream) => inner.destroy_outbound(substream),
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
EitherOutput::Second(inner) => match substream {
|
||||
EitherOutbound::B(substream) => inner.destroy_outbound(substream),
|
||||
_ => panic!("Wrong API usage"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn read_substream(&self, cx: &mut Context<'_>, sub: &mut Self::Substream, buf: &mut [u8]) -> Poll<Result<usize, Self::Error>> {
|
||||
fn read_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
sub: &mut Self::Substream,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, Self::Error>> {
|
||||
match (self, sub) {
|
||||
(EitherOutput::First(ref inner), EitherOutput::First(ref mut sub)) => {
|
||||
inner.read_substream(cx, sub, buf).map_err(|e| e.into())
|
||||
},
|
||||
}
|
||||
(EitherOutput::Second(ref inner), EitherOutput::Second(ref mut sub)) => {
|
||||
inner.read_substream(cx, sub, buf).map_err(|e| e.into())
|
||||
},
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
_ => panic!("Wrong API usage"),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_substream(&self, cx: &mut Context<'_>, sub: &mut Self::Substream, buf: &[u8]) -> Poll<Result<usize, Self::Error>> {
|
||||
fn write_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
sub: &mut Self::Substream,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, Self::Error>> {
|
||||
match (self, sub) {
|
||||
(EitherOutput::First(ref inner), EitherOutput::First(ref mut sub)) => {
|
||||
inner.write_substream(cx, sub, buf).map_err(|e| e.into())
|
||||
},
|
||||
}
|
||||
(EitherOutput::Second(ref inner), EitherOutput::Second(ref mut sub)) => {
|
||||
inner.write_substream(cx, sub, buf).map_err(|e| e.into())
|
||||
},
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
_ => panic!("Wrong API usage"),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush_substream(&self, cx: &mut Context<'_>, sub: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
||||
fn flush_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
sub: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
match (self, sub) {
|
||||
(EitherOutput::First(ref inner), EitherOutput::First(ref mut sub)) => {
|
||||
inner.flush_substream(cx, sub).map_err(|e| e.into())
|
||||
},
|
||||
}
|
||||
(EitherOutput::Second(ref inner), EitherOutput::Second(ref mut sub)) => {
|
||||
inner.flush_substream(cx, sub).map_err(|e| e.into())
|
||||
},
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
_ => panic!("Wrong API usage"),
|
||||
}
|
||||
}
|
||||
|
||||
fn shutdown_substream(&self, cx: &mut Context<'_>, sub: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
||||
fn shutdown_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
sub: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
match (self, sub) {
|
||||
(EitherOutput::First(ref inner), EitherOutput::First(ref mut sub)) => {
|
||||
inner.shutdown_substream(cx, sub).map_err(|e| e.into())
|
||||
},
|
||||
}
|
||||
(EitherOutput::Second(ref inner), EitherOutput::Second(ref mut sub)) => {
|
||||
inner.shutdown_substream(cx, sub).map_err(|e| e.into())
|
||||
},
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
_ => panic!("Wrong API usage"),
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_substream(&self, substream: Self::Substream) {
|
||||
match self {
|
||||
EitherOutput::First(inner) => {
|
||||
match substream {
|
||||
EitherOutput::First(substream) => inner.destroy_substream(substream),
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
EitherOutput::First(inner) => match substream {
|
||||
EitherOutput::First(substream) => inner.destroy_substream(substream),
|
||||
_ => panic!("Wrong API usage"),
|
||||
},
|
||||
EitherOutput::Second(inner) => {
|
||||
match substream {
|
||||
EitherOutput::Second(substream) => inner.destroy_substream(substream),
|
||||
_ => panic!("Wrong API usage")
|
||||
}
|
||||
EitherOutput::Second(inner) => match substream {
|
||||
EitherOutput::Second(substream) => inner.destroy_substream(substream),
|
||||
_ => panic!("Wrong API usage"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -344,25 +377,33 @@ pub enum EitherListenStream<A, B> {
|
||||
Second(#[pin] B),
|
||||
}
|
||||
|
||||
impl<AStream, BStream, AInner, BInner, AError, BError> Stream for EitherListenStream<AStream, BStream>
|
||||
impl<AStream, BStream, AInner, BInner, AError, BError> Stream
|
||||
for EitherListenStream<AStream, BStream>
|
||||
where
|
||||
AStream: TryStream<Ok = ListenerEvent<AInner, AError>, Error = AError>,
|
||||
BStream: TryStream<Ok = ListenerEvent<BInner, BError>, Error = BError>,
|
||||
{
|
||||
type Item = Result<ListenerEvent<EitherFuture<AInner, BInner>, EitherError<AError, BError>>, EitherError<AError, BError>>;
|
||||
type Item = Result<
|
||||
ListenerEvent<EitherFuture<AInner, BInner>, EitherError<AError, BError>>,
|
||||
EitherError<AError, BError>,
|
||||
>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
match self.project() {
|
||||
EitherListenStreamProj::First(a) => match TryStream::try_poll_next(a, cx) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(None) => Poll::Ready(None),
|
||||
Poll::Ready(Some(Ok(le))) => Poll::Ready(Some(Ok(le.map(EitherFuture::First).map_err(EitherError::A)))),
|
||||
Poll::Ready(Some(Ok(le))) => Poll::Ready(Some(Ok(le
|
||||
.map(EitherFuture::First)
|
||||
.map_err(EitherError::A)))),
|
||||
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(EitherError::A(err)))),
|
||||
},
|
||||
EitherListenStreamProj::Second(a) => match TryStream::try_poll_next(a, cx) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(None) => Poll::Ready(None),
|
||||
Poll::Ready(Some(Ok(le))) => Poll::Ready(Some(Ok(le.map(EitherFuture::Second).map_err(EitherError::B)))),
|
||||
Poll::Ready(Some(Ok(le))) => Poll::Ready(Some(Ok(le
|
||||
.map(EitherFuture::Second)
|
||||
.map_err(EitherError::B)))),
|
||||
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(EitherError::B(err)))),
|
||||
},
|
||||
}
|
||||
@ -388,9 +429,11 @@ where
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.project() {
|
||||
EitherFutureProj::First(a) => TryFuture::try_poll(a, cx)
|
||||
.map_ok(EitherOutput::First).map_err(EitherError::A),
|
||||
.map_ok(EitherOutput::First)
|
||||
.map_err(EitherError::A),
|
||||
EitherFutureProj::Second(a) => TryFuture::try_poll(a, cx)
|
||||
.map_ok(EitherOutput::Second).map_err(EitherError::B),
|
||||
.map_ok(EitherOutput::Second)
|
||||
.map_err(EitherError::B),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -398,7 +441,10 @@ where
|
||||
#[pin_project(project = EitherFuture2Proj)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[must_use = "futures do nothing unless polled"]
|
||||
pub enum EitherFuture2<A, B> { A(#[pin] A), B(#[pin] B) }
|
||||
pub enum EitherFuture2<A, B> {
|
||||
A(#[pin] A),
|
||||
B(#[pin] B),
|
||||
}
|
||||
|
||||
impl<AFut, BFut, AItem, BItem, AError, BError> Future for EitherFuture2<AFut, BFut>
|
||||
where
|
||||
@ -410,21 +456,26 @@ where
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.project() {
|
||||
EitherFuture2Proj::A(a) => TryFuture::try_poll(a, cx)
|
||||
.map_ok(EitherOutput::First).map_err(EitherError::A),
|
||||
.map_ok(EitherOutput::First)
|
||||
.map_err(EitherError::A),
|
||||
EitherFuture2Proj::B(a) => TryFuture::try_poll(a, cx)
|
||||
.map_ok(EitherOutput::Second).map_err(EitherError::B),
|
||||
.map_ok(EitherOutput::Second)
|
||||
.map_err(EitherError::B),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EitherName<A, B> { A(A), B(B) }
|
||||
pub enum EitherName<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
|
||||
impl<A: ProtocolName, B: ProtocolName> ProtocolName for EitherName<A, B> {
|
||||
fn protocol_name(&self) -> &[u8] {
|
||||
match self {
|
||||
EitherName::A(a) => a.protocol_name(),
|
||||
EitherName::B(b) => b.protocol_name()
|
||||
EitherName::B(b) => b.protocol_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ pub mod secp256k1;
|
||||
pub mod error;
|
||||
|
||||
use self::error::*;
|
||||
use crate::{PeerId, keys_proto};
|
||||
use crate::{keys_proto, PeerId};
|
||||
|
||||
/// Identity keypair of a node.
|
||||
///
|
||||
@ -69,7 +69,7 @@ pub enum Keypair {
|
||||
Rsa(rsa::Keypair),
|
||||
/// A Secp256k1 keypair.
|
||||
#[cfg(feature = "secp256k1")]
|
||||
Secp256k1(secp256k1::Keypair)
|
||||
Secp256k1(secp256k1::Keypair),
|
||||
}
|
||||
|
||||
impl Keypair {
|
||||
@ -112,7 +112,7 @@ impl Keypair {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Rsa(ref pair) => pair.sign(msg),
|
||||
#[cfg(feature = "secp256k1")]
|
||||
Secp256k1(ref pair) => pair.secret().sign(msg)
|
||||
Secp256k1(ref pair) => pair.secret().sign(msg),
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +154,6 @@ impl Keypair {
|
||||
Ok(pk.encode_to_vec())
|
||||
}
|
||||
|
||||
|
||||
/// Decode a private key from a protobuf structure and parse it as a [`Keypair`].
|
||||
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Keypair, DecodingError> {
|
||||
use prost::Message;
|
||||
@ -163,19 +162,20 @@ impl Keypair {
|
||||
.map_err(|e| DecodingError::new("Protobuf").source(e))
|
||||
.map(zeroize::Zeroizing::new)?;
|
||||
|
||||
let key_type = keys_proto::KeyType::from_i32(private_key.r#type)
|
||||
.ok_or_else(|| DecodingError::new(format!("unknown key type: {}", private_key.r#type)))?;
|
||||
let key_type = keys_proto::KeyType::from_i32(private_key.r#type).ok_or_else(|| {
|
||||
DecodingError::new(format!("unknown key type: {}", private_key.r#type))
|
||||
})?;
|
||||
|
||||
match key_type {
|
||||
keys_proto::KeyType::Ed25519 => {
|
||||
ed25519::Keypair::decode(&mut private_key.data).map(Keypair::Ed25519)
|
||||
},
|
||||
keys_proto::KeyType::Rsa => {
|
||||
Err(DecodingError::new("Decoding RSA key from Protobuf is unsupported."))
|
||||
},
|
||||
keys_proto::KeyType::Secp256k1 => {
|
||||
Err(DecodingError::new("Decoding Secp256k1 key from Protobuf is unsupported."))
|
||||
},
|
||||
}
|
||||
keys_proto::KeyType::Rsa => Err(DecodingError::new(
|
||||
"Decoding RSA key from Protobuf is unsupported.",
|
||||
)),
|
||||
keys_proto::KeyType::Secp256k1 => Err(DecodingError::new(
|
||||
"Decoding Secp256k1 key from Protobuf is unsupported.",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,7 +197,7 @@ pub enum PublicKey {
|
||||
Rsa(rsa::PublicKey),
|
||||
#[cfg(feature = "secp256k1")]
|
||||
/// A public Secp256k1 key.
|
||||
Secp256k1(secp256k1::PublicKey)
|
||||
Secp256k1(secp256k1::PublicKey),
|
||||
}
|
||||
|
||||
impl PublicKey {
|
||||
@ -212,7 +212,7 @@ impl PublicKey {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Rsa(pk) => pk.verify(msg, sig),
|
||||
#[cfg(feature = "secp256k1")]
|
||||
Secp256k1(pk) => pk.verify(msg, sig)
|
||||
Secp256k1(pk) => pk.verify(msg, sig),
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,27 +222,26 @@ impl PublicKey {
|
||||
use prost::Message;
|
||||
|
||||
let public_key = match self {
|
||||
PublicKey::Ed25519(key) =>
|
||||
keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Ed25519 as i32,
|
||||
data: key.encode().to_vec()
|
||||
},
|
||||
PublicKey::Ed25519(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Ed25519 as i32,
|
||||
data: key.encode().to_vec(),
|
||||
},
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
PublicKey::Rsa(key) =>
|
||||
keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Rsa as i32,
|
||||
data: key.encode_x509()
|
||||
},
|
||||
PublicKey::Rsa(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Rsa as i32,
|
||||
data: key.encode_x509(),
|
||||
},
|
||||
#[cfg(feature = "secp256k1")]
|
||||
PublicKey::Secp256k1(key) =>
|
||||
keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Secp256k1 as i32,
|
||||
data: key.encode().to_vec()
|
||||
}
|
||||
PublicKey::Secp256k1(key) => keys_proto::PublicKey {
|
||||
r#type: keys_proto::KeyType::Secp256k1 as i32,
|
||||
data: key.encode().to_vec(),
|
||||
},
|
||||
};
|
||||
|
||||
let mut buf = Vec::with_capacity(public_key.encoded_len());
|
||||
public_key.encode(&mut buf).expect("Vec<u8> provides capacity as needed");
|
||||
public_key
|
||||
.encode(&mut buf)
|
||||
.expect("Vec<u8> provides capacity as needed");
|
||||
buf
|
||||
}
|
||||
|
||||
@ -261,7 +260,7 @@ impl PublicKey {
|
||||
match key_type {
|
||||
keys_proto::KeyType::Ed25519 => {
|
||||
ed25519::PublicKey::decode(&pubkey.data).map(PublicKey::Ed25519)
|
||||
},
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
keys_proto::KeyType::Rsa => {
|
||||
rsa::PublicKey::decode_x509(&pubkey.data).map(PublicKey::Rsa)
|
||||
@ -270,7 +269,7 @@ impl PublicKey {
|
||||
keys_proto::KeyType::Rsa => {
|
||||
log::debug!("support for RSA was disabled at compile-time");
|
||||
Err(DecodingError::new("Unsupported"))
|
||||
},
|
||||
}
|
||||
#[cfg(feature = "secp256k1")]
|
||||
keys_proto::KeyType::Secp256k1 => {
|
||||
secp256k1::PublicKey::decode(&pubkey.data).map(PublicKey::Secp256k1)
|
||||
@ -311,7 +310,8 @@ mod tests {
|
||||
fn keypair_from_protobuf_encoding() {
|
||||
// E.g. retrieved from an IPFS config file.
|
||||
let base_64_encoded = "CAESQL6vdKQuznQosTrW7FWI9At+XX7EBf0BnZLhb6w+N+XSQSdfInl6c7U4NuxXJlhKcRBlBw9d0tj2dfBIVf6mcPA=";
|
||||
let expected_peer_id = PeerId::from_str("12D3KooWEChVMMMzV8acJ53mJHrw1pQ27UAGkCxWXLJutbeUMvVu").unwrap();
|
||||
let expected_peer_id =
|
||||
PeerId::from_str("12D3KooWEChVMMMzV8acJ53mJHrw1pQ27UAGkCxWXLJutbeUMvVu").unwrap();
|
||||
|
||||
let encoded = base64::decode(base_64_encoded).unwrap();
|
||||
|
||||
|
@ -20,12 +20,12 @@
|
||||
|
||||
//! Ed25519 keys.
|
||||
|
||||
use super::error::DecodingError;
|
||||
use core::fmt;
|
||||
use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
|
||||
use rand::RngCore;
|
||||
use std::convert::TryFrom;
|
||||
use super::error::DecodingError;
|
||||
use zeroize::Zeroize;
|
||||
use core::fmt;
|
||||
|
||||
/// An Ed25519 keypair.
|
||||
pub struct Keypair(ed25519::Keypair);
|
||||
@ -49,7 +49,10 @@ impl Keypair {
|
||||
/// Note that this binary format is the same as `ed25519_dalek`'s and `ed25519_zebra`'s.
|
||||
pub fn decode(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
|
||||
ed25519::Keypair::from_bytes(kp)
|
||||
.map(|k| { kp.zeroize(); Keypair(k) })
|
||||
.map(|k| {
|
||||
kp.zeroize();
|
||||
Keypair(k)
|
||||
})
|
||||
.map_err(|e| DecodingError::new("Ed25519 keypair").source(e))
|
||||
}
|
||||
|
||||
@ -72,7 +75,9 @@ impl Keypair {
|
||||
|
||||
impl fmt::Debug for Keypair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Keypair").field("public", &self.0.public).finish()
|
||||
f.debug_struct("Keypair")
|
||||
.field("public", &self.0.public)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +85,8 @@ impl Clone for Keypair {
|
||||
fn clone(&self) -> Keypair {
|
||||
let mut sk_bytes = self.0.secret.to_bytes();
|
||||
let secret = SecretKey::from_bytes(&mut sk_bytes)
|
||||
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k").0;
|
||||
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
|
||||
.0;
|
||||
let public = ed25519::PublicKey::from_bytes(&self.0.public.to_bytes())
|
||||
.expect("ed25519::PublicKey::from_bytes(to_bytes(k)) != k");
|
||||
Keypair(ed25519::Keypair { secret, public })
|
||||
@ -99,7 +105,10 @@ impl From<SecretKey> for Keypair {
|
||||
fn from(sk: SecretKey) -> Keypair {
|
||||
let secret: ed25519::ExpandedSecretKey = (&sk.0).into();
|
||||
let public = ed25519::PublicKey::from(&secret);
|
||||
Keypair(ed25519::Keypair { secret: sk.0, public })
|
||||
Keypair(ed25519::Keypair {
|
||||
secret: sk.0,
|
||||
public,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +129,9 @@ impl fmt::Debug for PublicKey {
|
||||
impl PublicKey {
|
||||
/// Verify the Ed25519 signature on a message using the public key.
|
||||
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
|
||||
ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).is_ok()
|
||||
ed25519::Signature::try_from(sig)
|
||||
.and_then(|s| self.0.verify(msg, &s))
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
/// Encode the public key into a byte array in compressed form, i.e.
|
||||
@ -150,8 +161,7 @@ impl AsRef<[u8]> for SecretKey {
|
||||
impl Clone for SecretKey {
|
||||
fn clone(&self) -> SecretKey {
|
||||
let mut sk_bytes = self.0.to_bytes();
|
||||
Self::from_bytes(&mut sk_bytes)
|
||||
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
|
||||
Self::from_bytes(&mut sk_bytes).expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,8 +176,11 @@ impl SecretKey {
|
||||
pub fn generate() -> SecretKey {
|
||||
let mut bytes = [0u8; 32];
|
||||
rand::thread_rng().fill_bytes(&mut bytes);
|
||||
SecretKey(ed25519::SecretKey::from_bytes(&bytes)
|
||||
.expect("this returns `Err` only if the length is wrong; the length is correct; qed"))
|
||||
SecretKey(
|
||||
ed25519::SecretKey::from_bytes(&bytes).expect(
|
||||
"this returns `Err` only if the length is wrong; the length is correct; qed",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create an Ed25519 secret key from a byte slice, zeroing the input on success.
|
||||
@ -188,9 +201,7 @@ mod tests {
|
||||
use quickcheck::*;
|
||||
|
||||
fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
|
||||
kp1.public() == kp2.public()
|
||||
&&
|
||||
kp1.0.secret.as_bytes() == kp2.0.secret.as_bytes()
|
||||
kp1.public() == kp2.public() && kp1.0.secret.as_bytes() == kp2.0.secret.as_bytes()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -199,9 +210,7 @@ mod tests {
|
||||
let kp1 = Keypair::generate();
|
||||
let mut kp1_enc = kp1.encode();
|
||||
let kp2 = Keypair::decode(&mut kp1_enc).unwrap();
|
||||
eq_keypairs(&kp1, &kp2)
|
||||
&&
|
||||
kp1_enc.iter().all(|b| *b == 0)
|
||||
eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
|
||||
}
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
|
||||
}
|
||||
@ -212,9 +221,7 @@ mod tests {
|
||||
let kp1 = Keypair::generate();
|
||||
let mut sk = kp1.0.secret.to_bytes();
|
||||
let kp2 = Keypair::from(SecretKey::from_bytes(&mut sk).unwrap());
|
||||
eq_keypairs(&kp1, &kp2)
|
||||
&&
|
||||
sk == [0u8; 32]
|
||||
eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
|
||||
}
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
|
||||
}
|
||||
|
@ -27,16 +27,22 @@ use std::fmt;
|
||||
#[derive(Debug)]
|
||||
pub struct DecodingError {
|
||||
msg: String,
|
||||
source: Option<Box<dyn Error + Send + Sync>>
|
||||
source: Option<Box<dyn Error + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl DecodingError {
|
||||
pub(crate) fn new<S: ToString>(msg: S) -> Self {
|
||||
Self { msg: msg.to_string(), source: None }
|
||||
Self {
|
||||
msg: msg.to_string(),
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn source(self, source: impl Error + Send + Sync + 'static) -> Self {
|
||||
Self { source: Some(Box::new(source)), .. self }
|
||||
Self {
|
||||
source: Some(Box::new(source)),
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,17 +62,23 @@ impl Error for DecodingError {
|
||||
#[derive(Debug)]
|
||||
pub struct SigningError {
|
||||
msg: String,
|
||||
source: Option<Box<dyn Error + Send + Sync>>
|
||||
source: Option<Box<dyn Error + Send + Sync>>,
|
||||
}
|
||||
|
||||
/// An error during encoding of key material.
|
||||
impl SigningError {
|
||||
pub(crate) fn new<S: ToString>(msg: S) -> Self {
|
||||
Self { msg: msg.to_string(), source: None }
|
||||
Self {
|
||||
msg: msg.to_string(),
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn source(self, source: impl Error + Send + Sync + 'static) -> Self {
|
||||
Self { source: Some(Box::new(source)), .. self }
|
||||
Self {
|
||||
source: Some(Box::new(source)),
|
||||
..self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,4 +93,3 @@ impl Error for SigningError {
|
||||
self.source.as_ref().map(|s| &**s as &dyn Error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,12 @@
|
||||
|
||||
//! RSA keys.
|
||||
|
||||
use asn1_der::typed::{DerEncodable, DerDecodable, DerTypeView, Sequence};
|
||||
use asn1_der::{DerObject, Asn1DerError, Asn1DerErrorVariant, Sink, VecBacking};
|
||||
use super::error::*;
|
||||
use asn1_der::typed::{DerDecodable, DerEncodable, DerTypeView, Sequence};
|
||||
use asn1_der::{Asn1DerError, Asn1DerErrorVariant, DerObject, Sink, VecBacking};
|
||||
use ring::rand::SystemRandom;
|
||||
use ring::signature::{self, RsaKeyPair, RSA_PKCS1_SHA256, RSA_PKCS1_2048_8192_SHA256};
|
||||
use ring::signature::KeyPair;
|
||||
use ring::signature::{self, RsaKeyPair, RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_SHA256};
|
||||
use std::{fmt, sync::Arc};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
@ -56,7 +56,7 @@ impl Keypair {
|
||||
let rng = SystemRandom::new();
|
||||
match self.0.sign(&RSA_PKCS1_SHA256, &rng, &data, &mut signature) {
|
||||
Ok(()) => Ok(signature),
|
||||
Err(e) => Err(SigningError::new("RSA").source(e))
|
||||
Err(e) => Err(SigningError::new("RSA").source(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,12 +89,14 @@ impl PublicKey {
|
||||
let spki = Asn1SubjectPublicKeyInfo {
|
||||
algorithmIdentifier: Asn1RsaEncryption {
|
||||
algorithm: Asn1OidRsaEncryption,
|
||||
parameters: ()
|
||||
parameters: (),
|
||||
},
|
||||
subjectPublicKey: Asn1SubjectPublicKey(self.clone())
|
||||
subjectPublicKey: Asn1SubjectPublicKey(self.clone()),
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
let buf = spki.encode(&mut buf).map(|_| buf)
|
||||
let buf = spki
|
||||
.encode(&mut buf)
|
||||
.map(|_| buf)
|
||||
.expect("RSA X.509 public key encoding failed.");
|
||||
buf
|
||||
}
|
||||
@ -127,7 +129,7 @@ impl fmt::Debug for PublicKey {
|
||||
/// A raw ASN1 OID.
|
||||
#[derive(Copy, Clone)]
|
||||
struct Asn1RawOid<'a> {
|
||||
object: DerObject<'a>
|
||||
object: DerObject<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Asn1RawOid<'a> {
|
||||
@ -179,7 +181,7 @@ impl Asn1OidRsaEncryption {
|
||||
///
|
||||
/// [RFC-3279]: https://tools.ietf.org/html/rfc3279#section-2.3.1
|
||||
/// [RFC-5280]: https://tools.ietf.org/html/rfc5280#section-4.1
|
||||
const OID: [u8;9] = [ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 ];
|
||||
const OID: [u8; 9] = [0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01];
|
||||
}
|
||||
|
||||
impl DerEncodable for Asn1OidRsaEncryption {
|
||||
@ -194,7 +196,7 @@ impl DerDecodable<'_> for Asn1OidRsaEncryption {
|
||||
oid if oid == Self::OID => Ok(Self),
|
||||
_ => Err(Asn1DerError::new(Asn1DerErrorVariant::InvalidData(
|
||||
"DER object is not the 'rsaEncryption' identifier.",
|
||||
)))
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,7 +204,7 @@ impl DerDecodable<'_> for Asn1OidRsaEncryption {
|
||||
/// The ASN.1 AlgorithmIdentifier for "rsaEncryption".
|
||||
struct Asn1RsaEncryption {
|
||||
algorithm: Asn1OidRsaEncryption,
|
||||
parameters: ()
|
||||
parameters: (),
|
||||
}
|
||||
|
||||
impl DerEncodable for Asn1RsaEncryption {
|
||||
@ -211,7 +213,9 @@ impl DerEncodable for Asn1RsaEncryption {
|
||||
let algorithm = self.algorithm.der_object(VecBacking(&mut algorithm_buf))?;
|
||||
|
||||
let mut parameters_buf = Vec::new();
|
||||
let parameters = self.parameters.der_object(VecBacking(&mut parameters_buf))?;
|
||||
let parameters = self
|
||||
.parameters
|
||||
.der_object(VecBacking(&mut parameters_buf))?;
|
||||
|
||||
Sequence::write(&[algorithm, parameters], sink)
|
||||
}
|
||||
@ -221,7 +225,7 @@ impl DerDecodable<'_> for Asn1RsaEncryption {
|
||||
fn load(object: DerObject<'_>) -> Result<Self, Asn1DerError> {
|
||||
let seq: Sequence = Sequence::load(object)?;
|
||||
|
||||
Ok(Self{
|
||||
Ok(Self {
|
||||
algorithm: seq.get_as(0)?,
|
||||
parameters: seq.get_as(1)?,
|
||||
})
|
||||
@ -248,9 +252,9 @@ impl DerEncodable for Asn1SubjectPublicKey {
|
||||
impl DerDecodable<'_> for Asn1SubjectPublicKey {
|
||||
fn load(object: DerObject<'_>) -> Result<Self, Asn1DerError> {
|
||||
if object.tag() != 3 {
|
||||
return Err(Asn1DerError::new(
|
||||
Asn1DerErrorVariant::InvalidData("DER object tag is not the bit string tag."),
|
||||
));
|
||||
return Err(Asn1DerError::new(Asn1DerErrorVariant::InvalidData(
|
||||
"DER object tag is not the bit string tag.",
|
||||
)));
|
||||
}
|
||||
|
||||
let pk_der: Vec<u8> = object.value().into_iter().skip(1).cloned().collect();
|
||||
@ -264,13 +268,15 @@ impl DerDecodable<'_> for Asn1SubjectPublicKey {
|
||||
#[allow(non_snake_case)]
|
||||
struct Asn1SubjectPublicKeyInfo {
|
||||
algorithmIdentifier: Asn1RsaEncryption,
|
||||
subjectPublicKey: Asn1SubjectPublicKey
|
||||
subjectPublicKey: Asn1SubjectPublicKey,
|
||||
}
|
||||
|
||||
impl DerEncodable for Asn1SubjectPublicKeyInfo {
|
||||
fn encode<S: Sink>(&self, sink: &mut S) -> Result<(), Asn1DerError> {
|
||||
let mut identifier_buf = Vec::new();
|
||||
let identifier = self.algorithmIdentifier.der_object(VecBacking(&mut identifier_buf))?;
|
||||
let identifier = self
|
||||
.algorithmIdentifier
|
||||
.der_object(VecBacking(&mut identifier_buf))?;
|
||||
|
||||
let mut key_buf = Vec::new();
|
||||
let key = self.subjectPublicKey.der_object(VecBacking(&mut key_buf))?;
|
||||
@ -340,6 +346,8 @@ mod tests {
|
||||
fn prop(SomeKeypair(kp): SomeKeypair, msg: Vec<u8>) -> Result<bool, SigningError> {
|
||||
kp.sign(&msg).map(|s| kp.public().verify(&msg, &s))
|
||||
}
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_,_) -> _);
|
||||
QuickCheck::new()
|
||||
.tests(10)
|
||||
.quickcheck(prop as fn(_, _) -> _);
|
||||
}
|
||||
}
|
||||
|
@ -20,18 +20,18 @@
|
||||
|
||||
//! Secp256k1 keys.
|
||||
|
||||
use asn1_der::typed::{DerDecodable, Sequence};
|
||||
use sha2::{Digest as ShaDigestTrait, Sha256};
|
||||
use libsecp256k1::{Message, Signature};
|
||||
use super::error::{DecodingError, SigningError};
|
||||
use zeroize::Zeroize;
|
||||
use asn1_der::typed::{DerDecodable, Sequence};
|
||||
use core::fmt;
|
||||
use libsecp256k1::{Message, Signature};
|
||||
use sha2::{Digest as ShaDigestTrait, Sha256};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// A Secp256k1 keypair.
|
||||
#[derive(Clone)]
|
||||
pub struct Keypair {
|
||||
secret: SecretKey,
|
||||
public: PublicKey
|
||||
public: PublicKey,
|
||||
}
|
||||
|
||||
impl Keypair {
|
||||
@ -53,7 +53,9 @@ impl Keypair {
|
||||
|
||||
impl fmt::Debug for Keypair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Keypair").field("public", &self.public).finish()
|
||||
f.debug_struct("Keypair")
|
||||
.field("public", &self.public)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,10 +112,11 @@ impl SecretKey {
|
||||
let der_obj = der.as_mut();
|
||||
let obj: Sequence = DerDecodable::decode(der_obj)
|
||||
.map_err(|e| DecodingError::new("Secp256k1 DER ECPrivateKey").source(e))?;
|
||||
let sk_obj = obj.get(1)
|
||||
let sk_obj = obj
|
||||
.get(1)
|
||||
.map_err(|e| DecodingError::new("Not enough elements in DER").source(e))?;
|
||||
let mut sk_bytes: Vec<u8> = asn1_der::typed::DerDecodable::load(sk_obj)
|
||||
.map_err(DecodingError::new)?;
|
||||
let mut sk_bytes: Vec<u8> =
|
||||
asn1_der::typed::DerDecodable::load(sk_obj).map_err(DecodingError::new)?;
|
||||
let sk = SecretKey::from_bytes(&mut sk_bytes)?;
|
||||
sk_bytes.zeroize();
|
||||
der_obj.zeroize();
|
||||
@ -138,7 +141,11 @@ impl SecretKey {
|
||||
pub fn sign_hash(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
|
||||
let m = Message::parse_slice(msg)
|
||||
.map_err(|_| SigningError::new("failed to parse secp256k1 digest"))?;
|
||||
Ok(libsecp256k1::sign(&m, &self.0).0.serialize_der().as_ref().into())
|
||||
Ok(libsecp256k1::sign(&m, &self.0)
|
||||
.0
|
||||
.serialize_der()
|
||||
.as_ref()
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,16 +54,16 @@ pub mod network;
|
||||
pub mod transport;
|
||||
pub mod upgrade;
|
||||
|
||||
pub use connection::{Connected, ConnectedPoint, Endpoint};
|
||||
pub use identity::PublicKey;
|
||||
pub use multiaddr::Multiaddr;
|
||||
pub use multihash;
|
||||
pub use muxing::StreamMuxer;
|
||||
pub use peer_id::PeerId;
|
||||
pub use identity::PublicKey;
|
||||
pub use transport::Transport;
|
||||
pub use translation::address_translation;
|
||||
pub use upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, UpgradeError, ProtocolName};
|
||||
pub use connection::{Connected, Endpoint, ConnectedPoint};
|
||||
pub use network::Network;
|
||||
pub use peer_id::PeerId;
|
||||
pub use translation::address_translation;
|
||||
pub use transport::Transport;
|
||||
pub use upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError, UpgradeInfo};
|
||||
|
||||
use std::{future::Future, pin::Pin};
|
||||
|
||||
|
@ -55,7 +55,12 @@ use fnv::FnvHashMap;
|
||||
use futures::{future, prelude::*, task::Context, task::Poll};
|
||||
use multiaddr::Multiaddr;
|
||||
use parking_lot::Mutex;
|
||||
use std::{io, ops::Deref, fmt, pin::Pin, sync::atomic::{AtomicUsize, Ordering}};
|
||||
use std::{
|
||||
fmt, io,
|
||||
ops::Deref,
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
pub use self::singleton::SingletonMuxer;
|
||||
|
||||
@ -95,7 +100,10 @@ pub trait StreamMuxer {
|
||||
/// work, such as processing incoming packets and polling timers.
|
||||
///
|
||||
/// An error can be generated if the connection has been closed.
|
||||
fn poll_event(&self, cx: &mut Context<'_>) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>>;
|
||||
fn poll_event(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>>;
|
||||
|
||||
/// Opens a new outgoing substream, and produces the equivalent to a future that will be
|
||||
/// resolved when it becomes available.
|
||||
@ -113,8 +121,11 @@ pub trait StreamMuxer {
|
||||
///
|
||||
/// May panic or produce an undefined result if an earlier polling of the same substream
|
||||
/// returned `Ready` or `Err`.
|
||||
fn poll_outbound(&self, cx: &mut Context<'_>, s: &mut Self::OutboundSubstream)
|
||||
-> Poll<Result<Self::Substream, Self::Error>>;
|
||||
fn poll_outbound(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::OutboundSubstream,
|
||||
) -> Poll<Result<Self::Substream, Self::Error>>;
|
||||
|
||||
/// Destroys an outbound substream future. Use this after the outbound substream has finished,
|
||||
/// or if you want to interrupt it.
|
||||
@ -131,8 +142,12 @@ pub trait StreamMuxer {
|
||||
///
|
||||
/// An error can be generated if the connection has been closed, or if a protocol misbehaviour
|
||||
/// happened.
|
||||
fn read_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream, buf: &mut [u8])
|
||||
-> Poll<Result<usize, Self::Error>>;
|
||||
fn read_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, Self::Error>>;
|
||||
|
||||
/// Write data to a substream. The behaviour is the same as `futures::AsyncWrite::poll_write`.
|
||||
///
|
||||
@ -145,8 +160,12 @@ pub trait StreamMuxer {
|
||||
///
|
||||
/// It is incorrect to call this method on a substream if you called `shutdown_substream` on
|
||||
/// this substream earlier.
|
||||
fn write_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream, buf: &[u8])
|
||||
-> Poll<Result<usize, Self::Error>>;
|
||||
fn write_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, Self::Error>>;
|
||||
|
||||
/// Flushes a substream. The behaviour is the same as `futures::AsyncWrite::poll_flush`.
|
||||
///
|
||||
@ -158,8 +177,11 @@ pub trait StreamMuxer {
|
||||
/// call this method may be notified.
|
||||
///
|
||||
/// > **Note**: This method may be implemented as a call to `flush_all`.
|
||||
fn flush_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream)
|
||||
-> Poll<Result<(), Self::Error>>;
|
||||
fn flush_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>>;
|
||||
|
||||
/// Attempts to shut down the writing side of a substream. The behaviour is similar to
|
||||
/// `AsyncWrite::poll_close`.
|
||||
@ -172,8 +194,11 @@ pub trait StreamMuxer {
|
||||
///
|
||||
/// An error can be generated if the connection has been closed, or if a protocol misbehaviour
|
||||
/// happened.
|
||||
fn shutdown_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream)
|
||||
-> Poll<Result<(), Self::Error>>;
|
||||
fn shutdown_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>>;
|
||||
|
||||
/// Destroys a substream.
|
||||
fn destroy_substream(&self, s: Self::Substream);
|
||||
@ -246,14 +271,12 @@ where
|
||||
P::Target: StreamMuxer,
|
||||
{
|
||||
let muxer2 = muxer.clone();
|
||||
future::poll_fn(move |cx| muxer.poll_event(cx))
|
||||
.map_ok(|event| {
|
||||
match event {
|
||||
StreamMuxerEvent::InboundSubstream(substream) =>
|
||||
StreamMuxerEvent::InboundSubstream(substream_from_ref(muxer2, substream)),
|
||||
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||
}
|
||||
})
|
||||
future::poll_fn(move |cx| muxer.poll_event(cx)).map_ok(|event| match event {
|
||||
StreamMuxerEvent::InboundSubstream(substream) => {
|
||||
StreamMuxerEvent::InboundSubstream(substream_from_ref(muxer2, substream))
|
||||
}
|
||||
StreamMuxerEvent::AddressChange(addr) => StreamMuxerEvent::AddressChange(addr),
|
||||
})
|
||||
}
|
||||
|
||||
/// Same as `outbound_from_ref`, but wraps the output in an object that
|
||||
@ -336,7 +359,8 @@ where
|
||||
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
||||
// multiple different fields from the `Pin` at the same time.
|
||||
let this = &mut *self;
|
||||
this.muxer.poll_outbound(cx, this.outbound.as_mut().expect("outbound was empty"))
|
||||
this.muxer
|
||||
.poll_outbound(cx, this.outbound.as_mut().expect("outbound was empty"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +432,11 @@ where
|
||||
P: Deref,
|
||||
P::Target: StreamMuxer,
|
||||
{
|
||||
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize, io::Error>> {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
||||
// multiple different fields from the `Pin` at the same time.
|
||||
let this = &mut *self;
|
||||
@ -423,7 +451,11 @@ where
|
||||
P: Deref,
|
||||
P::Target: StreamMuxer,
|
||||
{
|
||||
fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize, io::Error>> {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
// We use a `this` because the compiler isn't smart enough to allow mutably borrowing
|
||||
// multiple different fields from the `Pin` at the same time.
|
||||
let this = &mut *self;
|
||||
@ -440,20 +472,16 @@ where
|
||||
let s = this.substream.as_mut().expect("substream was empty");
|
||||
loop {
|
||||
match this.shutdown_state {
|
||||
ShutdownState::Shutdown => {
|
||||
match this.muxer.shutdown_substream(cx, s) {
|
||||
Poll::Ready(Ok(())) => this.shutdown_state = ShutdownState::Flush,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
}
|
||||
ShutdownState::Flush => {
|
||||
match this.muxer.flush_substream(cx, s) {
|
||||
Poll::Ready(Ok(())) => this.shutdown_state = ShutdownState::Done,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
}
|
||||
ShutdownState::Shutdown => match this.muxer.shutdown_substream(cx, s) {
|
||||
Poll::Ready(Ok(())) => this.shutdown_state = ShutdownState::Flush,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
},
|
||||
ShutdownState::Flush => match this.muxer.flush_substream(cx, s) {
|
||||
Poll::Ready(Ok(())) => this.shutdown_state = ShutdownState::Done,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
},
|
||||
ShutdownState::Done => {
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
@ -477,13 +505,18 @@ where
|
||||
P::Target: StreamMuxer,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.muxer.destroy_substream(self.substream.take().expect("substream was empty"))
|
||||
self.muxer
|
||||
.destroy_substream(self.substream.take().expect("substream was empty"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Abstract `StreamMuxer`.
|
||||
pub struct StreamMuxerBox {
|
||||
inner: Box<dyn StreamMuxer<Substream = usize, OutboundSubstream = usize, Error = io::Error> + Send + Sync>,
|
||||
inner: Box<
|
||||
dyn StreamMuxer<Substream = usize, OutboundSubstream = usize, Error = io::Error>
|
||||
+ Send
|
||||
+ Sync,
|
||||
>,
|
||||
}
|
||||
|
||||
impl StreamMuxerBox {
|
||||
@ -514,7 +547,10 @@ impl StreamMuxer for StreamMuxerBox {
|
||||
type Error = io::Error;
|
||||
|
||||
#[inline]
|
||||
fn poll_event(&self, cx: &mut Context<'_>) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||
fn poll_event(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||
self.inner.poll_event(cx)
|
||||
}
|
||||
|
||||
@ -524,7 +560,11 @@ impl StreamMuxer for StreamMuxerBox {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_outbound(&self, cx: &mut Context<'_>, s: &mut Self::OutboundSubstream) -> Poll<Result<Self::Substream, Self::Error>> {
|
||||
fn poll_outbound(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::OutboundSubstream,
|
||||
) -> Poll<Result<Self::Substream, Self::Error>> {
|
||||
self.inner.poll_outbound(cx, s)
|
||||
}
|
||||
|
||||
@ -534,22 +574,40 @@ impl StreamMuxer for StreamMuxerBox {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<Result<usize, Self::Error>> {
|
||||
fn read_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, Self::Error>> {
|
||||
self.inner.read_substream(cx, s, buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream, buf: &[u8]) -> Poll<Result<usize, Self::Error>> {
|
||||
fn write_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, Self::Error>> {
|
||||
self.inner.write_substream(cx, s, buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
||||
fn flush_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
self.inner.flush_substream(cx, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
||||
fn shutdown_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
self.inner.shutdown_substream(cx, s)
|
||||
}
|
||||
|
||||
@ -569,7 +627,10 @@ impl StreamMuxer for StreamMuxerBox {
|
||||
}
|
||||
}
|
||||
|
||||
struct Wrap<T> where T: StreamMuxer {
|
||||
struct Wrap<T>
|
||||
where
|
||||
T: StreamMuxer,
|
||||
{
|
||||
inner: T,
|
||||
substreams: Mutex<FnvHashMap<usize, T::Substream>>,
|
||||
next_substream: AtomicUsize,
|
||||
@ -586,11 +647,15 @@ where
|
||||
type Error = io::Error;
|
||||
|
||||
#[inline]
|
||||
fn poll_event(&self, cx: &mut Context<'_>) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||
fn poll_event(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, Self::Error>> {
|
||||
let substream = match self.inner.poll_event(cx) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(a))) =>
|
||||
return Poll::Ready(Ok(StreamMuxerEvent::AddressChange(a))),
|
||||
Poll::Ready(Ok(StreamMuxerEvent::AddressChange(a))) => {
|
||||
return Poll::Ready(Ok(StreamMuxerEvent::AddressChange(a)))
|
||||
}
|
||||
Poll::Ready(Ok(StreamMuxerEvent::InboundSubstream(s))) => s,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
};
|
||||
@ -615,7 +680,10 @@ where
|
||||
substream: &mut Self::OutboundSubstream,
|
||||
) -> Poll<Result<Self::Substream, Self::Error>> {
|
||||
let mut list = self.outbound.lock();
|
||||
let substream = match self.inner.poll_outbound(cx, list.get_mut(substream).unwrap()) {
|
||||
let substream = match self
|
||||
.inner
|
||||
.poll_outbound(cx, list.get_mut(substream).unwrap())
|
||||
{
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Ok(s)) => s,
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())),
|
||||
@ -628,37 +696,65 @@ where
|
||||
#[inline]
|
||||
fn destroy_outbound(&self, substream: Self::OutboundSubstream) {
|
||||
let mut list = self.outbound.lock();
|
||||
self.inner.destroy_outbound(list.remove(&substream).unwrap())
|
||||
self.inner
|
||||
.destroy_outbound(list.remove(&substream).unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream, buf: &mut [u8]) -> Poll<Result<usize, Self::Error>> {
|
||||
fn read_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, Self::Error>> {
|
||||
let mut list = self.substreams.lock();
|
||||
self.inner.read_substream(cx, list.get_mut(s).unwrap(), buf).map_err(|e| e.into())
|
||||
self.inner
|
||||
.read_substream(cx, list.get_mut(s).unwrap(), buf)
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream, buf: &[u8]) -> Poll<Result<usize, Self::Error>> {
|
||||
fn write_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, Self::Error>> {
|
||||
let mut list = self.substreams.lock();
|
||||
self.inner.write_substream(cx, list.get_mut(s).unwrap(), buf).map_err(|e| e.into())
|
||||
self.inner
|
||||
.write_substream(cx, list.get_mut(s).unwrap(), buf)
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
||||
fn flush_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
let mut list = self.substreams.lock();
|
||||
self.inner.flush_substream(cx, list.get_mut(s).unwrap()).map_err(|e| e.into())
|
||||
self.inner
|
||||
.flush_substream(cx, list.get_mut(s).unwrap())
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn shutdown_substream(&self, cx: &mut Context<'_>, s: &mut Self::Substream) -> Poll<Result<(), Self::Error>> {
|
||||
fn shutdown_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
s: &mut Self::Substream,
|
||||
) -> Poll<Result<(), Self::Error>> {
|
||||
let mut list = self.substreams.lock();
|
||||
self.inner.shutdown_substream(cx, list.get_mut(s).unwrap()).map_err(|e| e.into())
|
||||
self.inner
|
||||
.shutdown_substream(cx, list.get_mut(s).unwrap())
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn destroy_substream(&self, substream: Self::Substream) {
|
||||
let mut list = self.substreams.lock();
|
||||
self.inner.destroy_substream(list.remove(&substream).unwrap())
|
||||
self.inner
|
||||
.destroy_substream(list.remove(&substream).unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -18,11 +18,20 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{connection::Endpoint, muxing::{StreamMuxer, StreamMuxerEvent}};
|
||||
use crate::{
|
||||
connection::Endpoint,
|
||||
muxing::{StreamMuxer, StreamMuxerEvent},
|
||||
};
|
||||
|
||||
use futures::prelude::*;
|
||||
use parking_lot::Mutex;
|
||||
use std::{io, pin::Pin, sync::atomic::{AtomicBool, Ordering}, task::Context, task::Poll};
|
||||
use std::{
|
||||
io,
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
task::Context,
|
||||
task::Poll,
|
||||
};
|
||||
|
||||
/// Implementation of `StreamMuxer` that allows only one substream on top of a connection,
|
||||
/// yielding the connection itself.
|
||||
@ -65,7 +74,10 @@ where
|
||||
type OutboundSubstream = OutboundSubstream;
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll_event(&self, _: &mut Context<'_>) -> Poll<Result<StreamMuxerEvent<Self::Substream>, io::Error>> {
|
||||
fn poll_event(
|
||||
&self,
|
||||
_: &mut Context<'_>,
|
||||
) -> Poll<Result<StreamMuxerEvent<Self::Substream>, io::Error>> {
|
||||
match self.endpoint {
|
||||
Endpoint::Dialer => return Poll::Pending,
|
||||
Endpoint::Listener => {}
|
||||
@ -82,7 +94,11 @@ where
|
||||
OutboundSubstream {}
|
||||
}
|
||||
|
||||
fn poll_outbound(&self, _: &mut Context<'_>, _: &mut Self::OutboundSubstream) -> Poll<Result<Self::Substream, io::Error>> {
|
||||
fn poll_outbound(
|
||||
&self,
|
||||
_: &mut Context<'_>,
|
||||
_: &mut Self::OutboundSubstream,
|
||||
) -> Poll<Result<Self::Substream, io::Error>> {
|
||||
match self.endpoint {
|
||||
Endpoint::Listener => return Poll::Pending,
|
||||
Endpoint::Dialer => {}
|
||||
@ -95,27 +111,43 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_outbound(&self, _: Self::OutboundSubstream) {
|
||||
}
|
||||
fn destroy_outbound(&self, _: Self::OutboundSubstream) {}
|
||||
|
||||
fn read_substream(&self, cx: &mut Context<'_>, _: &mut Self::Substream, buf: &mut [u8]) -> Poll<Result<usize, io::Error>> {
|
||||
fn read_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
_: &mut Self::Substream,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
AsyncRead::poll_read(Pin::new(&mut *self.inner.lock()), cx, buf)
|
||||
}
|
||||
|
||||
fn write_substream(&self, cx: &mut Context<'_>, _: &mut Self::Substream, buf: &[u8]) -> Poll<Result<usize, io::Error>> {
|
||||
fn write_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
_: &mut Self::Substream,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
AsyncWrite::poll_write(Pin::new(&mut *self.inner.lock()), cx, buf)
|
||||
}
|
||||
|
||||
fn flush_substream(&self, cx: &mut Context<'_>, _: &mut Self::Substream) -> Poll<Result<(), io::Error>> {
|
||||
fn flush_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
_: &mut Self::Substream,
|
||||
) -> Poll<Result<(), io::Error>> {
|
||||
AsyncWrite::poll_flush(Pin::new(&mut *self.inner.lock()), cx)
|
||||
}
|
||||
|
||||
fn shutdown_substream(&self, cx: &mut Context<'_>, _: &mut Self::Substream) -> Poll<Result<(), io::Error>> {
|
||||
fn shutdown_substream(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
_: &mut Self::Substream,
|
||||
) -> Poll<Result<(), io::Error>> {
|
||||
AsyncWrite::poll_close(Pin::new(&mut *self.inner.lock()), cx)
|
||||
}
|
||||
|
||||
fn destroy_substream(&self, _: Self::Substream) {
|
||||
}
|
||||
fn destroy_substream(&self, _: Self::Substream) {}
|
||||
|
||||
fn close(&self, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
// The `StreamMuxer` trait requires that `close()` implies `flush_all()`.
|
||||
|
@ -21,45 +21,30 @@
|
||||
mod event;
|
||||
pub mod peer;
|
||||
|
||||
pub use crate::connection::{ConnectionLimits, ConnectionCounters};
|
||||
pub use event::{NetworkEvent, IncomingConnection};
|
||||
pub use crate::connection::{ConnectionCounters, ConnectionLimits};
|
||||
pub use event::{IncomingConnection, NetworkEvent};
|
||||
pub use peer::Peer;
|
||||
|
||||
use crate::{
|
||||
ConnectedPoint,
|
||||
Executor,
|
||||
Multiaddr,
|
||||
PeerId,
|
||||
connection::{
|
||||
ConnectionId,
|
||||
ConnectionLimit,
|
||||
ConnectionHandler,
|
||||
IntoConnectionHandler,
|
||||
IncomingInfo,
|
||||
OutgoingInfo,
|
||||
ListenersEvent,
|
||||
ListenerId,
|
||||
ListenersStream,
|
||||
PendingConnectionError,
|
||||
Substream,
|
||||
handler::{
|
||||
THandlerInEvent,
|
||||
THandlerOutEvent,
|
||||
},
|
||||
handler::{THandlerInEvent, THandlerOutEvent},
|
||||
manager::ManagerConfig,
|
||||
pool::{Pool, PoolEvent},
|
||||
ConnectionHandler, ConnectionId, ConnectionLimit, IncomingInfo, IntoConnectionHandler,
|
||||
ListenerId, ListenersEvent, ListenersStream, OutgoingInfo, PendingConnectionError,
|
||||
Substream,
|
||||
},
|
||||
muxing::StreamMuxer,
|
||||
transport::{Transport, TransportError},
|
||||
ConnectedPoint, Executor, Multiaddr, PeerId,
|
||||
};
|
||||
use fnv::{FnvHashMap};
|
||||
use futures::{prelude::*, future};
|
||||
use fnv::FnvHashMap;
|
||||
use futures::{future, prelude::*};
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
collections::hash_map,
|
||||
convert::TryFrom as _,
|
||||
error,
|
||||
fmt,
|
||||
error, fmt,
|
||||
num::NonZeroUsize,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
@ -95,8 +80,7 @@ where
|
||||
dialing: FnvHashMap<PeerId, SmallVec<[peer::DialingState; 10]>>,
|
||||
}
|
||||
|
||||
impl<TTrans, THandler> fmt::Debug for
|
||||
Network<TTrans, THandler>
|
||||
impl<TTrans, THandler> fmt::Debug for Network<TTrans, THandler>
|
||||
where
|
||||
TTrans: fmt::Debug + Transport,
|
||||
THandler: fmt::Debug + ConnectionHandler,
|
||||
@ -111,16 +95,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TTrans, THandler> Unpin for
|
||||
Network<TTrans, THandler>
|
||||
impl<TTrans, THandler> Unpin for Network<TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
{
|
||||
}
|
||||
|
||||
impl<TTrans, THandler>
|
||||
Network<TTrans, THandler>
|
||||
impl<TTrans, THandler> Network<TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -131,8 +113,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TTrans, TMuxer, THandler>
|
||||
Network<TTrans, THandler>
|
||||
impl<TTrans, TMuxer, THandler> Network<TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport + Clone,
|
||||
TMuxer: StreamMuxer,
|
||||
@ -142,11 +123,7 @@ where
|
||||
THandler::Handler: ConnectionHandler<Substream = Substream<TMuxer>> + Send,
|
||||
{
|
||||
/// Creates a new node events stream.
|
||||
pub fn new(
|
||||
transport: TTrans,
|
||||
local_peer_id: PeerId,
|
||||
config: NetworkConfig,
|
||||
) -> Self {
|
||||
pub fn new(transport: TTrans, local_peer_id: PeerId, config: NetworkConfig) -> Self {
|
||||
Network {
|
||||
local_peer_id,
|
||||
listeners: ListenersStream::new(transport),
|
||||
@ -161,7 +138,10 @@ where
|
||||
}
|
||||
|
||||
/// Start listening on the given multiaddress.
|
||||
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<ListenerId, TransportError<TTrans::Error>> {
|
||||
pub fn listen_on(
|
||||
&mut self,
|
||||
addr: Multiaddr,
|
||||
) -> Result<ListenerId, TransportError<TTrans::Error>> {
|
||||
self.listeners.listen_on(addr)
|
||||
}
|
||||
|
||||
@ -189,14 +169,14 @@ where
|
||||
/// other than the peer who reported the `observed_addr`.
|
||||
///
|
||||
/// The translation is transport-specific. See [`Transport::address_translation`].
|
||||
pub fn address_translation<'a>(&'a self, observed_addr: &'a Multiaddr)
|
||||
-> Vec<Multiaddr>
|
||||
pub fn address_translation<'a>(&'a self, observed_addr: &'a Multiaddr) -> Vec<Multiaddr>
|
||||
where
|
||||
TMuxer: 'a,
|
||||
THandler: 'a,
|
||||
{
|
||||
let transport = self.listeners.transport();
|
||||
let mut addrs: Vec<_> = self.listen_addrs()
|
||||
let mut addrs: Vec<_> = self
|
||||
.listen_addrs()
|
||||
.filter_map(move |server| transport.address_translation(server, observed_addr))
|
||||
.collect();
|
||||
|
||||
@ -218,8 +198,11 @@ where
|
||||
/// The given `handler` will be used to create the
|
||||
/// [`Connection`](crate::connection::Connection) upon success and the
|
||||
/// connection ID is returned.
|
||||
pub fn dial(&mut self, address: &Multiaddr, handler: THandler)
|
||||
-> Result<ConnectionId, DialError>
|
||||
pub fn dial(
|
||||
&mut self,
|
||||
address: &Multiaddr,
|
||||
handler: THandler,
|
||||
) -> Result<ConnectionId, DialError>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)>,
|
||||
TTrans::Error: Send + 'static,
|
||||
@ -238,21 +221,29 @@ where
|
||||
address: address.clone(),
|
||||
handler,
|
||||
remaining: Vec::new(),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// The address does not specify an expected peer, so just try to dial it as-is,
|
||||
// accepting any peer ID that the remote identifies as.
|
||||
let info = OutgoingInfo { address, peer_id: None };
|
||||
let info = OutgoingInfo {
|
||||
address,
|
||||
peer_id: None,
|
||||
};
|
||||
match self.transport().clone().dial(address.clone()) {
|
||||
Ok(f) => {
|
||||
let f = f.map_err(|err| PendingConnectionError::Transport(TransportError::Other(err)));
|
||||
self.pool.add_outgoing(f, handler, info).map_err(DialError::ConnectionLimit)
|
||||
let f =
|
||||
f.map_err(|err| PendingConnectionError::Transport(TransportError::Other(err)));
|
||||
self.pool
|
||||
.add_outgoing(f, handler, info)
|
||||
.map_err(DialError::ConnectionLimit)
|
||||
}
|
||||
Err(err) => {
|
||||
let f = future::err(PendingConnectionError::Transport(err));
|
||||
self.pool.add_outgoing(f, handler, info).map_err(DialError::ConnectionLimit)
|
||||
self.pool
|
||||
.add_outgoing(f, handler, info)
|
||||
.map_err(DialError::ConnectionLimit)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,14 +265,13 @@ where
|
||||
|
||||
/// Returns the list of addresses we're currently dialing without knowing the `PeerId` of.
|
||||
pub fn unknown_dials(&self) -> impl Iterator<Item = &Multiaddr> {
|
||||
self.pool.iter_pending_outgoing()
|
||||
.filter_map(|info| {
|
||||
if info.peer_id.is_none() {
|
||||
Some(info.address)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
self.pool.iter_pending_outgoing().filter_map(|info| {
|
||||
if info.peer_id.is_none() {
|
||||
Some(info.address)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a list of all connected peers, i.e. peers to whom the `Network`
|
||||
@ -313,9 +303,7 @@ where
|
||||
}
|
||||
|
||||
/// Obtains a view of a [`Peer`] with the given ID in the network.
|
||||
pub fn peer(&mut self, peer_id: PeerId)
|
||||
-> Peer<'_, TTrans, THandler>
|
||||
{
|
||||
pub fn peer(&mut self, peer_id: PeerId) -> Peer<'_, TTrans, THandler> {
|
||||
Peer::new(self, peer_id)
|
||||
}
|
||||
|
||||
@ -336,8 +324,9 @@ where
|
||||
TTrans::Error: Send + 'static,
|
||||
TTrans::ListenerUpgrade: Send + 'static,
|
||||
{
|
||||
let upgrade = connection.upgrade.map_err(|err|
|
||||
PendingConnectionError::Transport(TransportError::Other(err)));
|
||||
let upgrade = connection
|
||||
.upgrade
|
||||
.map_err(|err| PendingConnectionError::Transport(TransportError::Other(err)));
|
||||
let info = IncomingInfo {
|
||||
local_addr: &connection.local_addr,
|
||||
send_back_addr: &connection.send_back_addr,
|
||||
@ -346,7 +335,12 @@ where
|
||||
}
|
||||
|
||||
/// Provides an API similar to `Stream`, except that it cannot error.
|
||||
pub fn poll<'a>(&'a mut self, cx: &mut Context<'_>) -> Poll<NetworkEvent<'a, TTrans, THandlerInEvent<THandler>, THandlerOutEvent<THandler>, THandler>>
|
||||
pub fn poll<'a>(
|
||||
&'a mut self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<
|
||||
NetworkEvent<'a, TTrans, THandlerInEvent<THandler>, THandlerOutEvent<THandler>, THandler>,
|
||||
>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)>,
|
||||
TTrans::Error: Send + 'static,
|
||||
@ -364,7 +358,7 @@ where
|
||||
listener_id,
|
||||
upgrade,
|
||||
local_addr,
|
||||
send_back_addr
|
||||
send_back_addr,
|
||||
}) => {
|
||||
return Poll::Ready(NetworkEvent::IncomingConnection {
|
||||
listener_id,
|
||||
@ -372,17 +366,37 @@ where
|
||||
upgrade,
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
Poll::Ready(ListenersEvent::NewAddress { listener_id, listen_addr }) => {
|
||||
return Poll::Ready(NetworkEvent::NewListenerAddress { listener_id, listen_addr })
|
||||
Poll::Ready(ListenersEvent::NewAddress {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
}) => {
|
||||
return Poll::Ready(NetworkEvent::NewListenerAddress {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
})
|
||||
}
|
||||
Poll::Ready(ListenersEvent::AddressExpired { listener_id, listen_addr }) => {
|
||||
return Poll::Ready(NetworkEvent::ExpiredListenerAddress { listener_id, listen_addr })
|
||||
Poll::Ready(ListenersEvent::AddressExpired {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
}) => {
|
||||
return Poll::Ready(NetworkEvent::ExpiredListenerAddress {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
})
|
||||
}
|
||||
Poll::Ready(ListenersEvent::Closed { listener_id, addresses, reason }) => {
|
||||
return Poll::Ready(NetworkEvent::ListenerClosed { listener_id, addresses, reason })
|
||||
Poll::Ready(ListenersEvent::Closed {
|
||||
listener_id,
|
||||
addresses,
|
||||
reason,
|
||||
}) => {
|
||||
return Poll::Ready(NetworkEvent::ListenerClosed {
|
||||
listener_id,
|
||||
addresses,
|
||||
reason,
|
||||
})
|
||||
}
|
||||
Poll::Ready(ListenersEvent::Error { listener_id, error }) => {
|
||||
return Poll::Ready(NetworkEvent::ListenerError { listener_id, error })
|
||||
@ -392,7 +406,10 @@ where
|
||||
// Poll the known peers.
|
||||
let event = match self.pool.poll(cx) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(PoolEvent::ConnectionEstablished { connection, num_established }) => {
|
||||
Poll::Ready(PoolEvent::ConnectionEstablished {
|
||||
connection,
|
||||
num_established,
|
||||
}) => {
|
||||
if let hash_map::Entry::Occupied(mut e) = self.dialing.entry(connection.peer_id()) {
|
||||
e.get_mut().retain(|s| s.current.0 != connection.id());
|
||||
if e.get().is_empty() {
|
||||
@ -405,7 +422,14 @@ where
|
||||
num_established,
|
||||
}
|
||||
}
|
||||
Poll::Ready(PoolEvent::PendingConnectionError { id, endpoint, error, handler, pool, .. }) => {
|
||||
Poll::Ready(PoolEvent::PendingConnectionError {
|
||||
id,
|
||||
endpoint,
|
||||
error,
|
||||
handler,
|
||||
pool,
|
||||
..
|
||||
}) => {
|
||||
let dialing = &mut self.dialing;
|
||||
let (next, event) = on_connection_failed(dialing, id, endpoint, error, handler);
|
||||
if let Some(dial) = next {
|
||||
@ -416,35 +440,37 @@ where
|
||||
}
|
||||
event
|
||||
}
|
||||
Poll::Ready(PoolEvent::ConnectionClosed { id, connected, error, num_established, .. }) => {
|
||||
NetworkEvent::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
num_established,
|
||||
error,
|
||||
}
|
||||
}
|
||||
Poll::Ready(PoolEvent::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
error,
|
||||
num_established,
|
||||
..
|
||||
}) => NetworkEvent::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
num_established,
|
||||
error,
|
||||
},
|
||||
Poll::Ready(PoolEvent::ConnectionEvent { connection, event }) => {
|
||||
NetworkEvent::ConnectionEvent {
|
||||
connection,
|
||||
event,
|
||||
}
|
||||
}
|
||||
Poll::Ready(PoolEvent::AddressChange { connection, new_endpoint, old_endpoint }) => {
|
||||
NetworkEvent::AddressChange {
|
||||
connection,
|
||||
new_endpoint,
|
||||
old_endpoint,
|
||||
}
|
||||
NetworkEvent::ConnectionEvent { connection, event }
|
||||
}
|
||||
Poll::Ready(PoolEvent::AddressChange {
|
||||
connection,
|
||||
new_endpoint,
|
||||
old_endpoint,
|
||||
}) => NetworkEvent::AddressChange {
|
||||
connection,
|
||||
new_endpoint,
|
||||
old_endpoint,
|
||||
},
|
||||
};
|
||||
|
||||
Poll::Ready(event)
|
||||
}
|
||||
|
||||
/// Initiates a connection attempt to a known peer.
|
||||
fn dial_peer(&mut self, opts: DialingOpts<PeerId, THandler>)
|
||||
-> Result<ConnectionId, DialError>
|
||||
fn dial_peer(&mut self, opts: DialingOpts<PeerId, THandler>) -> Result<ConnectionId, DialError>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)>,
|
||||
TTrans::Dial: Send + 'static,
|
||||
@ -452,7 +478,12 @@ where
|
||||
TMuxer: Send + Sync + 'static,
|
||||
TMuxer::OutboundSubstream: Send,
|
||||
{
|
||||
dial_peer_impl(self.transport().clone(), &mut self.pool, &mut self.dialing, opts)
|
||||
dial_peer_impl(
|
||||
self.transport().clone(),
|
||||
&mut self.pool,
|
||||
&mut self.dialing,
|
||||
opts,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,15 +501,13 @@ fn dial_peer_impl<TMuxer, THandler, TTrans>(
|
||||
transport: TTrans,
|
||||
pool: &mut Pool<THandler, TTrans::Error>,
|
||||
dialing: &mut FnvHashMap<PeerId, SmallVec<[peer::DialingState; 10]>>,
|
||||
opts: DialingOpts<PeerId, THandler>
|
||||
opts: DialingOpts<PeerId, THandler>,
|
||||
) -> Result<ConnectionId, DialError>
|
||||
where
|
||||
THandler: IntoConnectionHandler + Send + 'static,
|
||||
<THandler::Handler as ConnectionHandler>::Error: error::Error + Send + 'static,
|
||||
<THandler::Handler as ConnectionHandler>::OutboundOpenInfo: Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<
|
||||
Substream = Substream<TMuxer>,
|
||||
> + Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<Substream = Substream<TMuxer>> + Send + 'static,
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)>,
|
||||
TTrans::Dial: Send + 'static,
|
||||
TTrans::Error: error::Error + Send + 'static,
|
||||
@ -493,23 +522,32 @@ where
|
||||
let result = match transport.dial(addr.clone()) {
|
||||
Ok(fut) => {
|
||||
let fut = fut.map_err(|e| PendingConnectionError::Transport(TransportError::Other(e)));
|
||||
let info = OutgoingInfo { address: &addr, peer_id: Some(&opts.peer) };
|
||||
pool.add_outgoing(fut, opts.handler, info).map_err(DialError::ConnectionLimit)
|
||||
},
|
||||
let info = OutgoingInfo {
|
||||
address: &addr,
|
||||
peer_id: Some(&opts.peer),
|
||||
};
|
||||
pool.add_outgoing(fut, opts.handler, info)
|
||||
.map_err(DialError::ConnectionLimit)
|
||||
}
|
||||
Err(err) => {
|
||||
let fut = future::err(PendingConnectionError::Transport(err));
|
||||
let info = OutgoingInfo { address: &addr, peer_id: Some(&opts.peer) };
|
||||
pool.add_outgoing(fut, opts.handler, info).map_err(DialError::ConnectionLimit)
|
||||
},
|
||||
let info = OutgoingInfo {
|
||||
address: &addr,
|
||||
peer_id: Some(&opts.peer),
|
||||
};
|
||||
pool.add_outgoing(fut, opts.handler, info)
|
||||
.map_err(DialError::ConnectionLimit)
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(id) = &result {
|
||||
dialing.entry(opts.peer).or_default().push(
|
||||
peer::DialingState {
|
||||
dialing
|
||||
.entry(opts.peer)
|
||||
.or_default()
|
||||
.push(peer::DialingState {
|
||||
current: (*id, addr),
|
||||
remaining: opts.remaining,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
result
|
||||
@ -526,22 +564,24 @@ fn on_connection_failed<'a, TTrans, THandler>(
|
||||
endpoint: ConnectedPoint,
|
||||
error: PendingConnectionError<TTrans::Error>,
|
||||
handler: Option<THandler>,
|
||||
) -> (Option<DialingOpts<PeerId, THandler>>, NetworkEvent<'a, TTrans, THandlerInEvent<THandler>, THandlerOutEvent<THandler>, THandler>)
|
||||
) -> (
|
||||
Option<DialingOpts<PeerId, THandler>>,
|
||||
NetworkEvent<'a, TTrans, THandlerInEvent<THandler>, THandlerOutEvent<THandler>, THandler>,
|
||||
)
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
{
|
||||
// Check if the failed connection is associated with a dialing attempt.
|
||||
let dialing_failed = dialing.iter_mut()
|
||||
.find_map(|(peer, attempts)| {
|
||||
if let Some(pos) = attempts.iter().position(|s| s.current.0 == id) {
|
||||
let attempt = attempts.remove(pos);
|
||||
let last = attempts.is_empty();
|
||||
Some((*peer, attempt, last))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let dialing_failed = dialing.iter_mut().find_map(|(peer, attempts)| {
|
||||
if let Some(pos) = attempts.iter().position(|s| s.current.0 == id) {
|
||||
let attempt = attempts.remove(pos);
|
||||
let last = attempts.is_empty();
|
||||
Some((*peer, attempt, last))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some((peer_id, mut attempt, last)) = dialing_failed {
|
||||
if last {
|
||||
@ -551,47 +591,56 @@ where
|
||||
let num_remain = u32::try_from(attempt.remaining.len()).unwrap();
|
||||
let failed_addr = attempt.current.1.clone();
|
||||
|
||||
let (opts, attempts_remaining) =
|
||||
if num_remain > 0 {
|
||||
if let Some(handler) = handler {
|
||||
let next_attempt = attempt.remaining.remove(0);
|
||||
let opts = DialingOpts {
|
||||
peer: peer_id,
|
||||
handler,
|
||||
address: next_attempt,
|
||||
remaining: attempt.remaining
|
||||
};
|
||||
(Some(opts), num_remain)
|
||||
} else {
|
||||
// The error is "fatal" for the dialing attempt, since
|
||||
// the handler was already consumed. All potential
|
||||
// remaining connection attempts are thus void.
|
||||
(None, 0)
|
||||
}
|
||||
let (opts, attempts_remaining) = if num_remain > 0 {
|
||||
if let Some(handler) = handler {
|
||||
let next_attempt = attempt.remaining.remove(0);
|
||||
let opts = DialingOpts {
|
||||
peer: peer_id,
|
||||
handler,
|
||||
address: next_attempt,
|
||||
remaining: attempt.remaining,
|
||||
};
|
||||
(Some(opts), num_remain)
|
||||
} else {
|
||||
// The error is "fatal" for the dialing attempt, since
|
||||
// the handler was already consumed. All potential
|
||||
// remaining connection attempts are thus void.
|
||||
(None, 0)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
(None, 0)
|
||||
};
|
||||
|
||||
(opts, NetworkEvent::DialError {
|
||||
attempts_remaining,
|
||||
peer_id,
|
||||
multiaddr: failed_addr,
|
||||
error,
|
||||
})
|
||||
(
|
||||
opts,
|
||||
NetworkEvent::DialError {
|
||||
attempts_remaining,
|
||||
peer_id,
|
||||
multiaddr: failed_addr,
|
||||
error,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// A pending incoming connection or outgoing connection to an unknown peer failed.
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { address } =>
|
||||
(None, NetworkEvent::UnknownPeerDialError {
|
||||
ConnectedPoint::Dialer { address } => (
|
||||
None,
|
||||
NetworkEvent::UnknownPeerDialError {
|
||||
multiaddr: address,
|
||||
error,
|
||||
}),
|
||||
ConnectedPoint::Listener { local_addr, send_back_addr } =>
|
||||
(None, NetworkEvent::IncomingConnectionError {
|
||||
},
|
||||
),
|
||||
ConnectedPoint::Listener {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
} => (
|
||||
None,
|
||||
NetworkEvent::IncomingConnectionError {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
error
|
||||
})
|
||||
error,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -644,7 +693,7 @@ impl NetworkConfig {
|
||||
/// only if no executor has already been configured.
|
||||
pub fn or_else_with_executor<F>(mut self, f: F) -> Self
|
||||
where
|
||||
F: FnOnce() -> Option<Box<dyn Executor + Send>>
|
||||
F: FnOnce() -> Option<Box<dyn Executor + Send>>,
|
||||
{
|
||||
self.manager_config.executor = self.manager_config.executor.or_else(f);
|
||||
self
|
||||
@ -693,7 +742,7 @@ impl NetworkConfig {
|
||||
fn p2p_addr(peer: PeerId, addr: Multiaddr) -> Result<Multiaddr, Multiaddr> {
|
||||
if let Some(multiaddr::Protocol::P2p(hash)) = addr.iter().last() {
|
||||
if &hash != peer.as_ref() {
|
||||
return Err(addr)
|
||||
return Err(addr);
|
||||
}
|
||||
Ok(addr)
|
||||
} else {
|
||||
@ -718,7 +767,7 @@ mod tests {
|
||||
struct Dummy;
|
||||
|
||||
impl Executor for Dummy {
|
||||
fn exec(&self, _: Pin<Box<dyn Future<Output=()> + Send>>) { }
|
||||
fn exec(&self, _: Pin<Box<dyn Future<Output = ()> + Send>>) {}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -21,20 +21,12 @@
|
||||
//! Network events and associated information.
|
||||
|
||||
use crate::{
|
||||
Multiaddr,
|
||||
connection::{
|
||||
ConnectionId,
|
||||
ConnectedPoint,
|
||||
ConnectionError,
|
||||
ConnectionHandler,
|
||||
Connected,
|
||||
EstablishedConnection,
|
||||
IntoConnectionHandler,
|
||||
ListenerId,
|
||||
PendingConnectionError,
|
||||
Connected, ConnectedPoint, ConnectionError, ConnectionHandler, ConnectionId,
|
||||
EstablishedConnection, IntoConnectionHandler, ListenerId, PendingConnectionError,
|
||||
},
|
||||
transport::Transport,
|
||||
PeerId
|
||||
Multiaddr, PeerId,
|
||||
};
|
||||
use std::{fmt, num::NonZeroU32};
|
||||
|
||||
@ -60,7 +52,7 @@ where
|
||||
/// The listener that errored.
|
||||
listener_id: ListenerId,
|
||||
/// The listener error.
|
||||
error: TTrans::Error
|
||||
error: TTrans::Error,
|
||||
},
|
||||
|
||||
/// One of the listeners is now listening on an additional address.
|
||||
@ -68,7 +60,7 @@ where
|
||||
/// The listener that is listening on the new address.
|
||||
listener_id: ListenerId,
|
||||
/// The new address the listener is now also listening on.
|
||||
listen_addr: Multiaddr
|
||||
listen_addr: Multiaddr,
|
||||
},
|
||||
|
||||
/// One of the listeners is no longer listening on some address.
|
||||
@ -76,7 +68,7 @@ where
|
||||
/// The listener that is no longer listening on some address.
|
||||
listener_id: ListenerId,
|
||||
/// The expired address.
|
||||
listen_addr: Multiaddr
|
||||
listen_addr: Multiaddr,
|
||||
},
|
||||
|
||||
/// A new connection arrived on a listener.
|
||||
@ -177,8 +169,8 @@ where
|
||||
},
|
||||
}
|
||||
|
||||
impl<TTrans, TInEvent, TOutEvent, THandler> fmt::Debug for
|
||||
NetworkEvent<'_, TTrans, TInEvent, TOutEvent, THandler>
|
||||
impl<TTrans, TInEvent, TOutEvent, THandler> fmt::Debug
|
||||
for NetworkEvent<'_, TTrans, TInEvent, TOutEvent, THandler>
|
||||
where
|
||||
TInEvent: fmt::Debug,
|
||||
TOutEvent: fmt::Debug,
|
||||
@ -189,83 +181,101 @@ where
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
NetworkEvent::NewListenerAddress { listener_id, listen_addr } => {
|
||||
f.debug_struct("NewListenerAddress")
|
||||
.field("listener_id", listener_id)
|
||||
.field("listen_addr", listen_addr)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::ExpiredListenerAddress { listener_id, listen_addr } => {
|
||||
f.debug_struct("ExpiredListenerAddress")
|
||||
.field("listener_id", listener_id)
|
||||
.field("listen_addr", listen_addr)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::ListenerClosed { listener_id, addresses, reason } => {
|
||||
f.debug_struct("ListenerClosed")
|
||||
.field("listener_id", listener_id)
|
||||
.field("addresses", addresses)
|
||||
.field("reason", reason)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::ListenerError { listener_id, error } => {
|
||||
f.debug_struct("ListenerError")
|
||||
.field("listener_id", listener_id)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::IncomingConnection { connection, .. } => {
|
||||
f.debug_struct("IncomingConnection")
|
||||
.field("local_addr", &connection.local_addr)
|
||||
.field("send_back_addr", &connection.send_back_addr)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::IncomingConnectionError { local_addr, send_back_addr, error } => {
|
||||
f.debug_struct("IncomingConnectionError")
|
||||
.field("local_addr", local_addr)
|
||||
.field("send_back_addr", send_back_addr)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::ConnectionEstablished { connection, .. } => {
|
||||
f.debug_struct("ConnectionEstablished")
|
||||
.field("connection", connection)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::ConnectionClosed { id, connected, error, .. } => {
|
||||
f.debug_struct("ConnectionClosed")
|
||||
.field("id", id)
|
||||
.field("connected", connected)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::DialError { attempts_remaining, peer_id, multiaddr, error } => {
|
||||
f.debug_struct("DialError")
|
||||
.field("attempts_remaining", attempts_remaining)
|
||||
.field("peer_id", peer_id)
|
||||
.field("multiaddr", multiaddr)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::UnknownPeerDialError { multiaddr, error, .. } => {
|
||||
f.debug_struct("UnknownPeerDialError")
|
||||
.field("multiaddr", multiaddr)
|
||||
.field("error", error)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::ConnectionEvent { connection, event } => {
|
||||
f.debug_struct("ConnectionEvent")
|
||||
.field("connection", connection)
|
||||
.field("event", event)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::AddressChange { connection, new_endpoint, old_endpoint } => {
|
||||
f.debug_struct("AddressChange")
|
||||
.field("connection", connection)
|
||||
.field("new_endpoint", new_endpoint)
|
||||
.field("old_endpoint", old_endpoint)
|
||||
.finish()
|
||||
}
|
||||
NetworkEvent::NewListenerAddress {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
} => f
|
||||
.debug_struct("NewListenerAddress")
|
||||
.field("listener_id", listener_id)
|
||||
.field("listen_addr", listen_addr)
|
||||
.finish(),
|
||||
NetworkEvent::ExpiredListenerAddress {
|
||||
listener_id,
|
||||
listen_addr,
|
||||
} => f
|
||||
.debug_struct("ExpiredListenerAddress")
|
||||
.field("listener_id", listener_id)
|
||||
.field("listen_addr", listen_addr)
|
||||
.finish(),
|
||||
NetworkEvent::ListenerClosed {
|
||||
listener_id,
|
||||
addresses,
|
||||
reason,
|
||||
} => f
|
||||
.debug_struct("ListenerClosed")
|
||||
.field("listener_id", listener_id)
|
||||
.field("addresses", addresses)
|
||||
.field("reason", reason)
|
||||
.finish(),
|
||||
NetworkEvent::ListenerError { listener_id, error } => f
|
||||
.debug_struct("ListenerError")
|
||||
.field("listener_id", listener_id)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
NetworkEvent::IncomingConnection { connection, .. } => f
|
||||
.debug_struct("IncomingConnection")
|
||||
.field("local_addr", &connection.local_addr)
|
||||
.field("send_back_addr", &connection.send_back_addr)
|
||||
.finish(),
|
||||
NetworkEvent::IncomingConnectionError {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
error,
|
||||
} => f
|
||||
.debug_struct("IncomingConnectionError")
|
||||
.field("local_addr", local_addr)
|
||||
.field("send_back_addr", send_back_addr)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
NetworkEvent::ConnectionEstablished { connection, .. } => f
|
||||
.debug_struct("ConnectionEstablished")
|
||||
.field("connection", connection)
|
||||
.finish(),
|
||||
NetworkEvent::ConnectionClosed {
|
||||
id,
|
||||
connected,
|
||||
error,
|
||||
..
|
||||
} => f
|
||||
.debug_struct("ConnectionClosed")
|
||||
.field("id", id)
|
||||
.field("connected", connected)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
NetworkEvent::DialError {
|
||||
attempts_remaining,
|
||||
peer_id,
|
||||
multiaddr,
|
||||
error,
|
||||
} => f
|
||||
.debug_struct("DialError")
|
||||
.field("attempts_remaining", attempts_remaining)
|
||||
.field("peer_id", peer_id)
|
||||
.field("multiaddr", multiaddr)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
NetworkEvent::UnknownPeerDialError {
|
||||
multiaddr, error, ..
|
||||
} => f
|
||||
.debug_struct("UnknownPeerDialError")
|
||||
.field("multiaddr", multiaddr)
|
||||
.field("error", error)
|
||||
.finish(),
|
||||
NetworkEvent::ConnectionEvent { connection, event } => f
|
||||
.debug_struct("ConnectionEvent")
|
||||
.field("connection", connection)
|
||||
.field("event", event)
|
||||
.finish(),
|
||||
NetworkEvent::AddressChange {
|
||||
connection,
|
||||
new_endpoint,
|
||||
old_endpoint,
|
||||
} => f
|
||||
.debug_struct("AddressChange")
|
||||
.field("connection", connection)
|
||||
.field("new_endpoint", new_endpoint)
|
||||
.field("old_endpoint", old_endpoint)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,35 +18,18 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use super::{DialError, DialingOpts, Network};
|
||||
use crate::{
|
||||
Multiaddr,
|
||||
Transport,
|
||||
StreamMuxer,
|
||||
connection::{
|
||||
Connected,
|
||||
ConnectedPoint,
|
||||
ConnectionHandler,
|
||||
Connection,
|
||||
ConnectionId,
|
||||
ConnectionLimit,
|
||||
EstablishedConnection,
|
||||
EstablishedConnectionIter,
|
||||
IntoConnectionHandler,
|
||||
PendingConnection,
|
||||
Substream,
|
||||
handler::THandlerInEvent,
|
||||
pool::Pool,
|
||||
handler::THandlerInEvent, pool::Pool, Connected, ConnectedPoint, Connection,
|
||||
ConnectionHandler, ConnectionId, ConnectionLimit, EstablishedConnection,
|
||||
EstablishedConnectionIter, IntoConnectionHandler, PendingConnection, Substream,
|
||||
},
|
||||
PeerId
|
||||
Multiaddr, PeerId, StreamMuxer, Transport,
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
collections::hash_map,
|
||||
error,
|
||||
fmt,
|
||||
};
|
||||
use super::{Network, DialingOpts, DialError};
|
||||
use std::{collections::hash_map, error, fmt};
|
||||
|
||||
/// The possible representations of a peer in a [`Network`], as
|
||||
/// seen by the local node.
|
||||
@ -57,7 +40,7 @@ use super::{Network, DialingOpts, DialError};
|
||||
pub enum Peer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler
|
||||
THandler: IntoConnectionHandler,
|
||||
{
|
||||
/// At least one established connection exists to the peer.
|
||||
Connected(ConnectedPeer<'a, TTrans, THandler>),
|
||||
@ -76,53 +59,33 @@ where
|
||||
Local,
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler> fmt::Debug for
|
||||
Peer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> fmt::Debug for Peer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
Peer::Connected(p) => {
|
||||
f.debug_struct("Connected")
|
||||
.field("peer", &p)
|
||||
.finish()
|
||||
}
|
||||
Peer::Dialing(p) => {
|
||||
f.debug_struct("Dialing")
|
||||
.field("peer", &p)
|
||||
.finish()
|
||||
}
|
||||
Peer::Disconnected(p) => {
|
||||
f.debug_struct("Disconnected")
|
||||
.field("peer", &p)
|
||||
.finish()
|
||||
}
|
||||
Peer::Local => {
|
||||
f.debug_struct("Local")
|
||||
.finish()
|
||||
}
|
||||
Peer::Connected(p) => f.debug_struct("Connected").field("peer", &p).finish(),
|
||||
Peer::Dialing(p) => f.debug_struct("Dialing").field("peer", &p).finish(),
|
||||
Peer::Disconnected(p) => f.debug_struct("Disconnected").field("peer", &p).finish(),
|
||||
Peer::Local => f.debug_struct("Local").finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler>
|
||||
Peer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> Peer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
{
|
||||
pub(super) fn new(
|
||||
network: &'a mut Network<TTrans, THandler>,
|
||||
peer_id: PeerId
|
||||
) -> Self {
|
||||
pub(super) fn new(network: &'a mut Network<TTrans, THandler>, peer_id: PeerId) -> Self {
|
||||
if peer_id == network.local_peer_id {
|
||||
return Peer::Local;
|
||||
}
|
||||
|
||||
if network.pool.is_connected(&peer_id) {
|
||||
return Self::connected(network, peer_id)
|
||||
return Self::connected(network, peer_id);
|
||||
}
|
||||
|
||||
if network.dialing.get_mut(&peer_id).is_some() {
|
||||
@ -132,31 +95,20 @@ where
|
||||
Self::disconnected(network, peer_id)
|
||||
}
|
||||
|
||||
|
||||
fn disconnected(
|
||||
network: &'a mut Network<TTrans, THandler>,
|
||||
peer_id: PeerId
|
||||
) -> Self {
|
||||
fn disconnected(network: &'a mut Network<TTrans, THandler>, peer_id: PeerId) -> Self {
|
||||
Peer::Disconnected(DisconnectedPeer { network, peer_id })
|
||||
}
|
||||
|
||||
fn connected(
|
||||
network: &'a mut Network<TTrans, THandler>,
|
||||
peer_id: PeerId
|
||||
) -> Self {
|
||||
fn connected(network: &'a mut Network<TTrans, THandler>, peer_id: PeerId) -> Self {
|
||||
Peer::Connected(ConnectedPeer { network, peer_id })
|
||||
}
|
||||
|
||||
fn dialing(
|
||||
network: &'a mut Network<TTrans, THandler>,
|
||||
peer_id: PeerId
|
||||
) -> Self {
|
||||
fn dialing(network: &'a mut Network<TTrans, THandler>, peer_id: PeerId) -> Self {
|
||||
Peer::Dialing(DialingPeer { network, peer_id })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TTrans, TMuxer, THandler>
|
||||
Peer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, TMuxer, THandler> Peer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport<Output = (PeerId, TMuxer)> + Clone,
|
||||
TTrans::Error: Send + 'static,
|
||||
@ -176,7 +128,7 @@ where
|
||||
Peer::Connected(..) => true,
|
||||
Peer::Dialing(peer) => peer.is_connected(),
|
||||
Peer::Disconnected(..) => false,
|
||||
Peer::Local => false
|
||||
Peer::Local => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,7 +140,7 @@ where
|
||||
Peer::Dialing(_) => true,
|
||||
Peer::Connected(peer) => peer.is_dialing(),
|
||||
Peer::Disconnected(..) => false,
|
||||
Peer::Local => false
|
||||
Peer::Local => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,11 +158,12 @@ where
|
||||
/// `remaining` addresses are tried in order in subsequent connection
|
||||
/// attempts in the context of the same dialing attempt, if the connection
|
||||
/// attempt to the first address fails.
|
||||
pub fn dial<I>(self, address: Multiaddr, remaining: I, handler: THandler)
|
||||
-> Result<
|
||||
(ConnectionId, DialingPeer<'a, TTrans, THandler>),
|
||||
DialError
|
||||
>
|
||||
pub fn dial<I>(
|
||||
self,
|
||||
address: Multiaddr,
|
||||
remaining: I,
|
||||
handler: THandler,
|
||||
) -> Result<(ConnectionId, DialingPeer<'a, TTrans, THandler>), DialError>
|
||||
where
|
||||
I: IntoIterator<Item = Multiaddr>,
|
||||
{
|
||||
@ -218,9 +171,12 @@ where
|
||||
Peer::Connected(p) => (p.peer_id, p.network),
|
||||
Peer::Dialing(p) => (p.peer_id, p.network),
|
||||
Peer::Disconnected(p) => (p.peer_id, p.network),
|
||||
Peer::Local => return Err(DialError::ConnectionLimit(ConnectionLimit {
|
||||
current: 0, limit: 0
|
||||
}))
|
||||
Peer::Local => {
|
||||
return Err(DialError::ConnectionLimit(ConnectionLimit {
|
||||
current: 0,
|
||||
limit: 0,
|
||||
}))
|
||||
}
|
||||
};
|
||||
|
||||
let id = network.dial_peer(DialingOpts {
|
||||
@ -236,9 +192,7 @@ where
|
||||
/// Converts the peer into a `ConnectedPeer`, if an established connection exists.
|
||||
///
|
||||
/// Succeeds if the there is at least one established connection to the peer.
|
||||
pub fn into_connected(self) -> Option<
|
||||
ConnectedPeer<'a, TTrans, THandler>
|
||||
> {
|
||||
pub fn into_connected(self) -> Option<ConnectedPeer<'a, TTrans, THandler>> {
|
||||
match self {
|
||||
Peer::Connected(peer) => Some(peer),
|
||||
Peer::Dialing(peer) => peer.into_connected(),
|
||||
@ -250,22 +204,18 @@ where
|
||||
/// Converts the peer into a `DialingPeer`, if a dialing attempt exists.
|
||||
///
|
||||
/// Succeeds if the there is at least one pending outgoing connection to the peer.
|
||||
pub fn into_dialing(self) -> Option<
|
||||
DialingPeer<'a, TTrans, THandler>
|
||||
> {
|
||||
pub fn into_dialing(self) -> Option<DialingPeer<'a, TTrans, THandler>> {
|
||||
match self {
|
||||
Peer::Dialing(peer) => Some(peer),
|
||||
Peer::Connected(peer) => peer.into_dialing(),
|
||||
Peer::Disconnected(..) => None,
|
||||
Peer::Local => None
|
||||
Peer::Local => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the peer into a `DisconnectedPeer`, if neither an established connection
|
||||
/// nor a dialing attempt exists.
|
||||
pub fn into_disconnected(self) -> Option<
|
||||
DisconnectedPeer<'a, TTrans, THandler>
|
||||
> {
|
||||
pub fn into_disconnected(self) -> Option<DisconnectedPeer<'a, TTrans, THandler>> {
|
||||
match self {
|
||||
Peer::Disconnected(peer) => Some(peer),
|
||||
_ => None,
|
||||
@ -285,8 +235,7 @@ where
|
||||
peer_id: PeerId,
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler>
|
||||
ConnectedPeer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> ConnectedPeer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -301,9 +250,10 @@ where
|
||||
}
|
||||
|
||||
/// Obtains an established connection to the peer by ID.
|
||||
pub fn connection(&mut self, id: ConnectionId)
|
||||
-> Option<EstablishedConnection<THandlerInEvent<THandler>>>
|
||||
{
|
||||
pub fn connection(
|
||||
&mut self,
|
||||
id: ConnectionId,
|
||||
) -> Option<EstablishedConnection<THandlerInEvent<THandler>>> {
|
||||
self.network.pool.get_established(id)
|
||||
}
|
||||
|
||||
@ -321,47 +271,43 @@ where
|
||||
|
||||
/// Converts this peer into a [`DialingPeer`], if there is an ongoing
|
||||
/// dialing attempt, `None` otherwise.
|
||||
pub fn into_dialing(self) -> Option<
|
||||
DialingPeer<'a, TTrans, THandler>
|
||||
> {
|
||||
pub fn into_dialing(self) -> Option<DialingPeer<'a, TTrans, THandler>> {
|
||||
if self.network.dialing.contains_key(&self.peer_id) {
|
||||
Some(DialingPeer { network: self.network, peer_id: self.peer_id })
|
||||
Some(DialingPeer {
|
||||
network: self.network,
|
||||
peer_id: self.peer_id,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an iterator over all established connections to the peer.
|
||||
pub fn connections(&mut self) ->
|
||||
EstablishedConnectionIter<
|
||||
impl Iterator<Item = ConnectionId>,
|
||||
THandler,
|
||||
TTrans::Error,
|
||||
>
|
||||
pub fn connections(
|
||||
&mut self,
|
||||
) -> EstablishedConnectionIter<impl Iterator<Item = ConnectionId>, THandler, TTrans::Error>
|
||||
{
|
||||
self.network.pool.iter_peer_established(&self.peer_id)
|
||||
}
|
||||
|
||||
/// Obtains some established connection to the peer.
|
||||
pub fn some_connection(&mut self)
|
||||
-> EstablishedConnection<THandlerInEvent<THandler>>
|
||||
{
|
||||
pub fn some_connection(&mut self) -> EstablishedConnection<THandlerInEvent<THandler>> {
|
||||
self.connections()
|
||||
.into_first()
|
||||
.expect("By `Peer::new` and the definition of `ConnectedPeer`.")
|
||||
}
|
||||
|
||||
/// Disconnects from the peer, closing all connections.
|
||||
pub fn disconnect(self)
|
||||
-> DisconnectedPeer<'a, TTrans, THandler>
|
||||
{
|
||||
pub fn disconnect(self) -> DisconnectedPeer<'a, TTrans, THandler> {
|
||||
self.network.disconnect(&self.peer_id);
|
||||
DisconnectedPeer { network: self.network, peer_id: self.peer_id }
|
||||
DisconnectedPeer {
|
||||
network: self.network,
|
||||
peer_id: self.peer_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler> fmt::Debug for
|
||||
ConnectedPeer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> fmt::Debug for ConnectedPeer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -369,7 +315,10 @@ where
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("ConnectedPeer")
|
||||
.field("peer_id", &self.peer_id)
|
||||
.field("established", &self.network.pool.iter_peer_established_info(&self.peer_id))
|
||||
.field(
|
||||
"established",
|
||||
&self.network.pool.iter_peer_established_info(&self.peer_id),
|
||||
)
|
||||
.field("attempts", &self.network.dialing.get(&self.peer_id))
|
||||
.finish()
|
||||
}
|
||||
@ -387,8 +336,7 @@ where
|
||||
peer_id: PeerId,
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler>
|
||||
DialingPeer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> DialingPeer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -404,11 +352,12 @@ where
|
||||
|
||||
/// Disconnects from this peer, closing all established connections and
|
||||
/// aborting all dialing attempts.
|
||||
pub fn disconnect(self)
|
||||
-> DisconnectedPeer<'a, TTrans, THandler>
|
||||
{
|
||||
pub fn disconnect(self) -> DisconnectedPeer<'a, TTrans, THandler> {
|
||||
self.network.disconnect(&self.peer_id);
|
||||
DisconnectedPeer { network: self.network, peer_id: self.peer_id }
|
||||
DisconnectedPeer {
|
||||
network: self.network,
|
||||
peer_id: self.peer_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether there is an established connection to the peer.
|
||||
@ -419,11 +368,12 @@ where
|
||||
}
|
||||
|
||||
/// Converts the peer into a `ConnectedPeer`, if an established connection exists.
|
||||
pub fn into_connected(self)
|
||||
-> Option<ConnectedPeer<'a, TTrans, THandler>>
|
||||
{
|
||||
pub fn into_connected(self) -> Option<ConnectedPeer<'a, TTrans, THandler>> {
|
||||
if self.is_connected() {
|
||||
Some(ConnectedPeer { peer_id: self.peer_id, network: self.network })
|
||||
Some(ConnectedPeer {
|
||||
peer_id: self.peer_id,
|
||||
network: self.network,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -431,13 +381,18 @@ where
|
||||
|
||||
/// Obtains a dialing attempt to the peer by connection ID of
|
||||
/// the current connection attempt.
|
||||
pub fn attempt(&mut self, id: ConnectionId)
|
||||
-> Option<DialingAttempt<'_, THandlerInEvent<THandler>>>
|
||||
{
|
||||
pub fn attempt(
|
||||
&mut self,
|
||||
id: ConnectionId,
|
||||
) -> Option<DialingAttempt<'_, THandlerInEvent<THandler>>> {
|
||||
if let hash_map::Entry::Occupied(attempts) = self.network.dialing.entry(self.peer_id) {
|
||||
if let Some(pos) = attempts.get().iter().position(|s| s.current.0 == id) {
|
||||
if let Some(inner) = self.network.pool.get_outgoing(id) {
|
||||
return Some(DialingAttempt { pos, inner, attempts })
|
||||
return Some(DialingAttempt {
|
||||
pos,
|
||||
inner,
|
||||
attempts,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -445,25 +400,25 @@ where
|
||||
}
|
||||
|
||||
/// Gets an iterator over all dialing (i.e. pending outgoing) connections to the peer.
|
||||
pub fn attempts(&mut self) -> DialingAttemptIter<'_, THandler, TTrans::Error>
|
||||
{
|
||||
DialingAttemptIter::new(&self.peer_id, &mut self.network.pool, &mut self.network.dialing)
|
||||
pub fn attempts(&mut self) -> DialingAttemptIter<'_, THandler, TTrans::Error> {
|
||||
DialingAttemptIter::new(
|
||||
&self.peer_id,
|
||||
&mut self.network.pool,
|
||||
&mut self.network.dialing,
|
||||
)
|
||||
}
|
||||
|
||||
/// Obtains some dialing connection to the peer.
|
||||
///
|
||||
/// At least one dialing connection is guaranteed to exist on a `DialingPeer`.
|
||||
pub fn some_attempt(&mut self)
|
||||
-> DialingAttempt<'_, THandlerInEvent<THandler>>
|
||||
{
|
||||
pub fn some_attempt(&mut self) -> DialingAttempt<'_, THandlerInEvent<THandler>> {
|
||||
self.attempts()
|
||||
.into_first()
|
||||
.expect("By `Peer::new` and the definition of `DialingPeer`.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler> fmt::Debug for
|
||||
DialingPeer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> fmt::Debug for DialingPeer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -471,7 +426,10 @@ where
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("DialingPeer")
|
||||
.field("peer_id", &self.peer_id)
|
||||
.field("established", &self.network.pool.iter_peer_established_info(&self.peer_id))
|
||||
.field(
|
||||
"established",
|
||||
&self.network.pool.iter_peer_established_info(&self.peer_id),
|
||||
)
|
||||
.field("attempts", &self.network.dialing.get(&self.peer_id))
|
||||
.finish()
|
||||
}
|
||||
@ -489,8 +447,7 @@ where
|
||||
network: &'a mut Network<TTrans, THandler>,
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler> fmt::Debug for
|
||||
DisconnectedPeer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> fmt::Debug for DisconnectedPeer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -502,8 +459,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TTrans, THandler>
|
||||
DisconnectedPeer<'a, TTrans, THandler>
|
||||
impl<'a, TTrans, THandler> DisconnectedPeer<'a, TTrans, THandler>
|
||||
where
|
||||
TTrans: Transport,
|
||||
THandler: IntoConnectionHandler,
|
||||
@ -529,10 +485,8 @@ where
|
||||
self,
|
||||
connected: Connected,
|
||||
connection: Connection<TMuxer, THandler::Handler>,
|
||||
) -> Result<
|
||||
ConnectedPeer<'a, TTrans, THandler>,
|
||||
ConnectionLimit
|
||||
> where
|
||||
) -> Result<ConnectedPeer<'a, TTrans, THandler>, ConnectionLimit>
|
||||
where
|
||||
THandler: Send + 'static,
|
||||
TTrans::Error: Send + 'static,
|
||||
THandler::Handler: ConnectionHandler<Substream = Substream<TMuxer>> + Send,
|
||||
@ -542,10 +496,15 @@ where
|
||||
TMuxer::OutboundSubstream: Send,
|
||||
{
|
||||
if connected.peer_id != self.peer_id {
|
||||
panic!("Invalid peer ID given: {:?}. Expected: {:?}", connected.peer_id, self.peer_id)
|
||||
panic!(
|
||||
"Invalid peer ID given: {:?}. Expected: {:?}",
|
||||
connected.peer_id, self.peer_id
|
||||
)
|
||||
}
|
||||
|
||||
self.network.pool.add(connection, connected)
|
||||
self.network
|
||||
.pool
|
||||
.add(connection, connected)
|
||||
.map(move |_id| ConnectedPeer {
|
||||
network: self.network,
|
||||
peer_id: self.peer_id,
|
||||
@ -575,9 +534,7 @@ pub struct DialingAttempt<'a, TInEvent> {
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a, TInEvent>
|
||||
DialingAttempt<'a, TInEvent>
|
||||
{
|
||||
impl<'a, TInEvent> DialingAttempt<'a, TInEvent> {
|
||||
/// Returns the ID of the current connection attempt.
|
||||
pub fn id(&self) -> ConnectionId {
|
||||
self.inner.id()
|
||||
@ -592,7 +549,7 @@ impl<'a, TInEvent>
|
||||
pub fn address(&self) -> &Multiaddr {
|
||||
match self.inner.endpoint() {
|
||||
ConnectedPoint::Dialer { address } => address,
|
||||
ConnectedPoint::Listener { .. } => unreachable!("by definition of a `DialingAttempt`.")
|
||||
ConnectedPoint::Listener { .. } => unreachable!("by definition of a `DialingAttempt`."),
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,16 +597,20 @@ pub struct DialingAttemptIter<'a, THandler: IntoConnectionHandler, TTransErr> {
|
||||
// Note: Ideally this would be an implementation of `Iterator`, but that
|
||||
// requires GATs (cf. https://github.com/rust-lang/rust/issues/44265) and
|
||||
// a different definition of `Iterator`.
|
||||
impl<'a, THandler: IntoConnectionHandler, TTransErr>
|
||||
DialingAttemptIter<'a, THandler, TTransErr>
|
||||
{
|
||||
impl<'a, THandler: IntoConnectionHandler, TTransErr> DialingAttemptIter<'a, THandler, TTransErr> {
|
||||
fn new(
|
||||
peer_id: &'a PeerId,
|
||||
pool: &'a mut Pool<THandler, TTransErr>,
|
||||
dialing: &'a mut FnvHashMap<PeerId, SmallVec<[DialingState; 10]>>,
|
||||
) -> Self {
|
||||
let end = dialing.get(peer_id).map_or(0, |conns| conns.len());
|
||||
Self { pos: 0, end, pool, dialing, peer_id }
|
||||
Self {
|
||||
pos: 0,
|
||||
end,
|
||||
pool,
|
||||
dialing,
|
||||
peer_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtains the next dialing connection, if any.
|
||||
@ -658,22 +619,29 @@ impl<'a, THandler: IntoConnectionHandler, TTransErr>
|
||||
// If the number of elements reduced, the current `DialingAttempt` has been
|
||||
// aborted and iteration needs to continue from the previous position to
|
||||
// account for the removed element.
|
||||
let end = self.dialing.get(self.peer_id).map_or(0, |conns| conns.len());
|
||||
let end = self
|
||||
.dialing
|
||||
.get(self.peer_id)
|
||||
.map_or(0, |conns| conns.len());
|
||||
if self.end > end {
|
||||
self.end = end;
|
||||
self.pos -= 1;
|
||||
}
|
||||
|
||||
if self.pos == self.end {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
|
||||
if let hash_map::Entry::Occupied(attempts) = self.dialing.entry(*self.peer_id) {
|
||||
let id = attempts.get()[self.pos].current.0;
|
||||
if let Some(inner) = self.pool.get_outgoing(id) {
|
||||
let conn = DialingAttempt { pos: self.pos, inner, attempts };
|
||||
let conn = DialingAttempt {
|
||||
pos: self.pos,
|
||||
inner,
|
||||
attempts,
|
||||
};
|
||||
self.pos += 1;
|
||||
return Some(conn)
|
||||
return Some(conn);
|
||||
}
|
||||
}
|
||||
|
||||
@ -681,18 +649,22 @@ impl<'a, THandler: IntoConnectionHandler, TTransErr>
|
||||
}
|
||||
|
||||
/// Returns the first connection, if any, consuming the iterator.
|
||||
pub fn into_first<'b>(self)
|
||||
-> Option<DialingAttempt<'b, THandlerInEvent<THandler>>>
|
||||
where 'a: 'b
|
||||
pub fn into_first<'b>(self) -> Option<DialingAttempt<'b, THandlerInEvent<THandler>>>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
if self.pos == self.end {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
|
||||
if let hash_map::Entry::Occupied(attempts) = self.dialing.entry(*self.peer_id) {
|
||||
let id = attempts.get()[self.pos].current.0;
|
||||
if let Some(inner) = self.pool.get_outgoing(id) {
|
||||
return Some(DialingAttempt { pos: self.pos, inner, attempts })
|
||||
return Some(DialingAttempt {
|
||||
pos: self.pos,
|
||||
inner,
|
||||
attempts,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,7 @@ pub struct PeerId {
|
||||
|
||||
impl fmt::Debug for PeerId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("PeerId")
|
||||
.field(&self.to_base58())
|
||||
.finish()
|
||||
f.debug_tuple("PeerId").field(&self.to_base58()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,9 +78,10 @@ impl PeerId {
|
||||
pub fn from_multihash(multihash: Multihash) -> Result<PeerId, Multihash> {
|
||||
match Code::try_from(multihash.code()) {
|
||||
Ok(Code::Sha2_256) => Ok(PeerId { multihash }),
|
||||
Ok(Code::Identity) if multihash.digest().len() <= MAX_INLINE_KEY_LENGTH
|
||||
=> Ok(PeerId { multihash }),
|
||||
_ => Err(multihash)
|
||||
Ok(Code::Identity) if multihash.digest().len() <= MAX_INLINE_KEY_LENGTH => {
|
||||
Ok(PeerId { multihash })
|
||||
}
|
||||
_ => Err(multihash),
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +92,7 @@ impl PeerId {
|
||||
let peer_id = rand::thread_rng().gen::<[u8; 32]>();
|
||||
PeerId {
|
||||
multihash: Multihash::wrap(Code::Identity.into(), &peer_id)
|
||||
.expect("The digest size is never too large")
|
||||
.expect("The digest size is never too large"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,7 +184,7 @@ impl FromStr for PeerId {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{PeerId, identity};
|
||||
use crate::{identity, PeerId};
|
||||
|
||||
#[test]
|
||||
fn peer_id_is_public_key() {
|
||||
@ -210,7 +209,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn random_peer_id_is_valid() {
|
||||
for _ in 0 .. 5000 {
|
||||
for _ in 0..5000 {
|
||||
let peer_id = PeerId::random();
|
||||
assert_eq!(peer_id, PeerId::from_bytes(&peer_id.to_bytes()).unwrap());
|
||||
}
|
||||
|
@ -94,7 +94,9 @@ pub trait Transport {
|
||||
///
|
||||
/// If this stream produces an error, it is considered fatal and the listener is killed. It
|
||||
/// is possible to report non-fatal errors by producing a [`ListenerEvent::Error`].
|
||||
type Listener: Stream<Item = Result<ListenerEvent<Self::ListenerUpgrade, Self::Error>, Self::Error>>;
|
||||
type Listener: Stream<
|
||||
Item = Result<ListenerEvent<Self::ListenerUpgrade, Self::Error>, Self::Error>,
|
||||
>;
|
||||
|
||||
/// A pending [`Output`](Transport::Output) for an inbound connection,
|
||||
/// obtained from the [`Listener`](Transport::Listener) stream.
|
||||
@ -149,7 +151,7 @@ pub trait Transport {
|
||||
fn map<F, O>(self, f: F) -> map::Map<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Output, ConnectedPoint) -> O + Clone
|
||||
F: FnOnce(Self::Output, ConnectedPoint) -> O + Clone,
|
||||
{
|
||||
map::Map::new(self, f)
|
||||
}
|
||||
@ -158,7 +160,7 @@ pub trait Transport {
|
||||
fn map_err<F, E>(self, f: F) -> map_err::MapErr<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Error) -> E + Clone
|
||||
F: FnOnce(Self::Error) -> E + Clone,
|
||||
{
|
||||
map_err::MapErr::new(self, f)
|
||||
}
|
||||
@ -172,7 +174,7 @@ pub trait Transport {
|
||||
where
|
||||
Self: Sized,
|
||||
U: Transport,
|
||||
<U as Transport>::Error: 'static
|
||||
<U as Transport>::Error: 'static,
|
||||
{
|
||||
OrTransport::new(self, other)
|
||||
}
|
||||
@ -189,7 +191,7 @@ pub trait Transport {
|
||||
Self: Sized,
|
||||
C: FnOnce(Self::Output, ConnectedPoint) -> F + Clone,
|
||||
F: TryFuture<Ok = O>,
|
||||
<F as TryFuture>::Error: Error + 'static
|
||||
<F as TryFuture>::Error: Error + 'static,
|
||||
{
|
||||
and_then::AndThen::new(self, f)
|
||||
}
|
||||
@ -199,7 +201,7 @@ pub trait Transport {
|
||||
fn upgrade(self, version: upgrade::Version) -> upgrade::Builder<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Error: 'static
|
||||
Self::Error: 'static,
|
||||
{
|
||||
upgrade::Builder::new(self, version)
|
||||
}
|
||||
@ -222,7 +224,7 @@ pub enum ListenerEvent<TUpgr, TErr> {
|
||||
/// The local address which produced this upgrade.
|
||||
local_addr: Multiaddr,
|
||||
/// The remote address which produced this upgrade.
|
||||
remote_addr: Multiaddr
|
||||
remote_addr: Multiaddr,
|
||||
},
|
||||
/// A [`Multiaddr`] is no longer used for listening.
|
||||
AddressExpired(Multiaddr),
|
||||
@ -239,9 +241,15 @@ impl<TUpgr, TErr> ListenerEvent<TUpgr, TErr> {
|
||||
/// based the the function's result.
|
||||
pub fn map<U>(self, f: impl FnOnce(TUpgr) -> U) -> ListenerEvent<U, TErr> {
|
||||
match self {
|
||||
ListenerEvent::Upgrade { upgrade, local_addr, remote_addr } => {
|
||||
ListenerEvent::Upgrade { upgrade: f(upgrade), local_addr, remote_addr }
|
||||
}
|
||||
ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
} => ListenerEvent::Upgrade {
|
||||
upgrade: f(upgrade),
|
||||
local_addr,
|
||||
remote_addr,
|
||||
},
|
||||
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||
ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a),
|
||||
ListenerEvent::Error(e) => ListenerEvent::Error(e),
|
||||
@ -253,8 +261,15 @@ impl<TUpgr, TErr> ListenerEvent<TUpgr, TErr> {
|
||||
/// function's result.
|
||||
pub fn map_err<U>(self, f: impl FnOnce(TErr) -> U) -> ListenerEvent<TUpgr, U> {
|
||||
match self {
|
||||
ListenerEvent::Upgrade { upgrade, local_addr, remote_addr } =>
|
||||
ListenerEvent::Upgrade { upgrade, local_addr, remote_addr },
|
||||
ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
} => ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
},
|
||||
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||
ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a),
|
||||
ListenerEvent::Error(e) => ListenerEvent::Error(f(e)),
|
||||
@ -263,7 +278,7 @@ impl<TUpgr, TErr> ListenerEvent<TUpgr, TErr> {
|
||||
|
||||
/// Returns `true` if this is an `Upgrade` listener event.
|
||||
pub fn is_upgrade(&self) -> bool {
|
||||
matches!(self, ListenerEvent::Upgrade {..})
|
||||
matches!(self, ListenerEvent::Upgrade { .. })
|
||||
}
|
||||
|
||||
/// Try to turn this listener event into upgrade parts.
|
||||
@ -271,7 +286,12 @@ impl<TUpgr, TErr> ListenerEvent<TUpgr, TErr> {
|
||||
/// Returns `None` if the event is not actually an upgrade,
|
||||
/// otherwise the upgrade and the remote address.
|
||||
pub fn into_upgrade(self) -> Option<(TUpgr, Multiaddr)> {
|
||||
if let ListenerEvent::Upgrade { upgrade, remote_addr, .. } = self {
|
||||
if let ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
remote_addr,
|
||||
..
|
||||
} = self
|
||||
{
|
||||
Some((upgrade, remote_addr))
|
||||
} else {
|
||||
None
|
||||
@ -347,25 +367,31 @@ impl<TErr> TransportError<TErr> {
|
||||
/// Applies a function to the the error in [`TransportError::Other`].
|
||||
pub fn map<TNewErr>(self, map: impl FnOnce(TErr) -> TNewErr) -> TransportError<TNewErr> {
|
||||
match self {
|
||||
TransportError::MultiaddrNotSupported(addr) => TransportError::MultiaddrNotSupported(addr),
|
||||
TransportError::MultiaddrNotSupported(addr) => {
|
||||
TransportError::MultiaddrNotSupported(addr)
|
||||
}
|
||||
TransportError::Other(err) => TransportError::Other(map(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TErr> fmt::Display for TransportError<TErr>
|
||||
where TErr: fmt::Display,
|
||||
where
|
||||
TErr: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
TransportError::MultiaddrNotSupported(addr) => write!(f, "Multiaddr is not supported: {}", addr),
|
||||
TransportError::MultiaddrNotSupported(addr) => {
|
||||
write!(f, "Multiaddr is not supported: {}", addr)
|
||||
}
|
||||
TransportError::Other(err) => write!(f, "{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TErr> Error for TransportError<TErr>
|
||||
where TErr: Error + 'static,
|
||||
where
|
||||
TErr: Error + 'static,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
|
@ -19,9 +19,9 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
ConnectedPoint,
|
||||
either::EitherError,
|
||||
transport::{Transport, TransportError, ListenerEvent}
|
||||
transport::{ListenerEvent, Transport, TransportError},
|
||||
ConnectedPoint,
|
||||
};
|
||||
use futures::{future::Either, prelude::*};
|
||||
use multiaddr::Multiaddr;
|
||||
@ -29,7 +29,10 @@ use std::{error, marker::PhantomPinned, pin::Pin, task::Context, task::Poll};
|
||||
|
||||
/// See the `Transport::and_then` method.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AndThen<T, C> { transport: T, fun: C }
|
||||
pub struct AndThen<T, C> {
|
||||
transport: T,
|
||||
fun: C,
|
||||
}
|
||||
|
||||
impl<T, C> AndThen<T, C> {
|
||||
pub(crate) fn new(transport: T, fun: C) -> Self {
|
||||
@ -51,17 +54,26 @@ where
|
||||
type Dial = AndThenFuture<T::Dial, C, F>;
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
let listener = self.transport.listen_on(addr).map_err(|err| err.map(EitherError::A))?;
|
||||
let listener = self
|
||||
.transport
|
||||
.listen_on(addr)
|
||||
.map_err(|err| err.map(EitherError::A))?;
|
||||
// Try to negotiate the protocol.
|
||||
// Note that failing to negotiate a protocol will never produce a future with an error.
|
||||
// Instead the `stream` will produce `Ok(Err(...))`.
|
||||
// `stream` can only produce an `Err` if `listening_stream` produces an `Err`.
|
||||
let stream = AndThenStream { stream: listener, fun: self.fun };
|
||||
let stream = AndThenStream {
|
||||
stream: listener,
|
||||
fun: self.fun,
|
||||
};
|
||||
Ok(stream)
|
||||
}
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let dialed_fut = self.transport.dial(addr.clone()).map_err(|err| err.map(EitherError::A))?;
|
||||
let dialed_fut = self
|
||||
.transport
|
||||
.dial(addr.clone())
|
||||
.map_err(|err| err.map(EitherError::A))?;
|
||||
let future = AndThenFuture {
|
||||
inner: Either::Left(Box::pin(dialed_fut)),
|
||||
args: Some((self.fun, ConnectedPoint::Dialer { address: addr })),
|
||||
@ -83,19 +95,23 @@ where
|
||||
pub struct AndThenStream<TListener, TMap> {
|
||||
#[pin]
|
||||
stream: TListener,
|
||||
fun: TMap
|
||||
fun: TMap,
|
||||
}
|
||||
|
||||
impl<TListener, TMap, TTransOut, TMapOut, TListUpgr, TTransErr> Stream for AndThenStream<TListener, TMap>
|
||||
impl<TListener, TMap, TTransOut, TMapOut, TListUpgr, TTransErr> Stream
|
||||
for AndThenStream<TListener, TMap>
|
||||
where
|
||||
TListener: TryStream<Ok = ListenerEvent<TListUpgr, TTransErr>, Error = TTransErr>,
|
||||
TListUpgr: TryFuture<Ok = TTransOut, Error = TTransErr>,
|
||||
TMap: FnOnce(TTransOut, ConnectedPoint) -> TMapOut + Clone,
|
||||
TMapOut: TryFuture
|
||||
TMapOut: TryFuture,
|
||||
{
|
||||
type Item = Result<
|
||||
ListenerEvent<AndThenFuture<TListUpgr, TMap, TMapOut>, EitherError<TTransErr, TMapOut::Error>>,
|
||||
EitherError<TTransErr, TMapOut::Error>
|
||||
ListenerEvent<
|
||||
AndThenFuture<TListUpgr, TMap, TMapOut>,
|
||||
EitherError<TTransErr, TMapOut::Error>,
|
||||
>,
|
||||
EitherError<TTransErr, TMapOut::Error>,
|
||||
>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
@ -103,10 +119,14 @@ where
|
||||
match TryStream::try_poll_next(this.stream, cx) {
|
||||
Poll::Ready(Some(Ok(event))) => {
|
||||
let event = match event {
|
||||
ListenerEvent::Upgrade { upgrade, local_addr, remote_addr } => {
|
||||
ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
} => {
|
||||
let point = ConnectedPoint::Listener {
|
||||
local_addr: local_addr.clone(),
|
||||
send_back_addr: remote_addr.clone()
|
||||
send_back_addr: remote_addr.clone(),
|
||||
};
|
||||
ListenerEvent::Upgrade {
|
||||
upgrade: AndThenFuture {
|
||||
@ -115,7 +135,7 @@ where
|
||||
marker: PhantomPinned,
|
||||
},
|
||||
local_addr,
|
||||
remote_addr
|
||||
remote_addr,
|
||||
}
|
||||
}
|
||||
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||
@ -127,7 +147,7 @@ where
|
||||
}
|
||||
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(EitherError::A(err)))),
|
||||
Poll::Ready(None) => Poll::Ready(None),
|
||||
Poll::Pending => Poll::Pending
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,7 +179,10 @@ where
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(EitherError::A(err))),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
};
|
||||
let (f, a) = self.args.take().expect("AndThenFuture has already finished.");
|
||||
let (f, a) = self
|
||||
.args
|
||||
.take()
|
||||
.expect("AndThenFuture has already finished.");
|
||||
f(item, a)
|
||||
}
|
||||
Either::Right(future) => {
|
||||
@ -176,5 +199,4 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<TFut, TMap, TMapOut> Unpin for AndThenFuture<TFut, TMap, TMapOut> {
|
||||
}
|
||||
impl<TFut, TMap, TMapOut> Unpin for AndThenFuture<TFut, TMap, TMapOut> {}
|
||||
|
@ -45,7 +45,8 @@ pub struct Boxed<O> {
|
||||
}
|
||||
|
||||
type Dial<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>;
|
||||
type Listener<O> = Pin<Box<dyn Stream<Item = io::Result<ListenerEvent<ListenerUpgrade<O>, io::Error>>> + Send>>;
|
||||
type Listener<O> =
|
||||
Pin<Box<dyn Stream<Item = io::Result<ListenerEvent<ListenerUpgrade<O>, io::Error>>> + Send>>;
|
||||
type ListenerUpgrade<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>;
|
||||
|
||||
trait Abstract<O> {
|
||||
@ -64,12 +65,16 @@ where
|
||||
{
|
||||
fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O>, TransportError<io::Error>> {
|
||||
let listener = Transport::listen_on(self.clone(), addr).map_err(|e| e.map(box_err))?;
|
||||
let fut = listener.map_ok(|event|
|
||||
event.map(|upgrade| {
|
||||
let up = upgrade.map_err(box_err);
|
||||
Box::pin(up) as ListenerUpgrade<O>
|
||||
}).map_err(box_err)
|
||||
).map_err(box_err);
|
||||
let fut = listener
|
||||
.map_ok(|event| {
|
||||
event
|
||||
.map(|upgrade| {
|
||||
let up = upgrade.map_err(box_err);
|
||||
Box::pin(up) as ListenerUpgrade<O>
|
||||
})
|
||||
.map_err(box_err)
|
||||
})
|
||||
.map_err(box_err);
|
||||
Ok(Box::pin(fut))
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::either::{EitherListenStream, EitherOutput, EitherError, EitherFuture};
|
||||
use crate::either::{EitherError, EitherFuture, EitherListenStream, EitherOutput};
|
||||
use crate::transport::{Transport, TransportError};
|
||||
use multiaddr::Multiaddr;
|
||||
|
||||
@ -47,13 +47,17 @@ where
|
||||
let addr = match self.0.listen_on(addr) {
|
||||
Ok(listener) => return Ok(EitherListenStream::First(listener)),
|
||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
||||
Err(TransportError::Other(err)) => return Err(TransportError::Other(EitherError::A(err))),
|
||||
Err(TransportError::Other(err)) => {
|
||||
return Err(TransportError::Other(EitherError::A(err)))
|
||||
}
|
||||
};
|
||||
|
||||
let addr = match self.1.listen_on(addr) {
|
||||
Ok(listener) => return Ok(EitherListenStream::Second(listener)),
|
||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
||||
Err(TransportError::Other(err)) => return Err(TransportError::Other(EitherError::B(err))),
|
||||
Err(TransportError::Other(err)) => {
|
||||
return Err(TransportError::Other(EitherError::B(err)))
|
||||
}
|
||||
};
|
||||
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
@ -63,13 +67,17 @@ where
|
||||
let addr = match self.0.dial(addr) {
|
||||
Ok(connec) => return Ok(EitherFuture::First(connec)),
|
||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
||||
Err(TransportError::Other(err)) => return Err(TransportError::Other(EitherError::A(err))),
|
||||
Err(TransportError::Other(err)) => {
|
||||
return Err(TransportError::Other(EitherError::A(err)))
|
||||
}
|
||||
};
|
||||
|
||||
let addr = match self.1.dial(addr) {
|
||||
Ok(connec) => return Ok(EitherFuture::Second(connec)),
|
||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
||||
Err(TransportError::Other(err)) => return Err(TransportError::Other(EitherError::B(err))),
|
||||
Err(TransportError::Other(err)) => {
|
||||
return Err(TransportError::Other(EitherError::B(err)))
|
||||
}
|
||||
};
|
||||
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::transport::{Transport, TransportError, ListenerEvent};
|
||||
use crate::transport::{ListenerEvent, Transport, TransportError};
|
||||
use crate::Multiaddr;
|
||||
use futures::{prelude::*, task::Context, task::Poll};
|
||||
use std::{fmt, io, marker::PhantomData, pin::Pin};
|
||||
@ -56,7 +56,9 @@ impl<TOut> Clone for DummyTransport<TOut> {
|
||||
impl<TOut> Transport for DummyTransport<TOut> {
|
||||
type Output = TOut;
|
||||
type Error = io::Error;
|
||||
type Listener = futures::stream::Pending<Result<ListenerEvent<Self::ListenerUpgrade, Self::Error>, Self::Error>>;
|
||||
type Listener = futures::stream::Pending<
|
||||
Result<ListenerEvent<Self::ListenerUpgrade, Self::Error>, Self::Error>,
|
||||
>;
|
||||
type ListenerUpgrade = futures::future::Pending<Result<Self::Output, io::Error>>;
|
||||
type Dial = futures::future::Pending<Result<Self::Output, io::Error>>;
|
||||
|
||||
@ -83,29 +85,29 @@ impl fmt::Debug for DummyStream {
|
||||
}
|
||||
|
||||
impl AsyncRead for DummyStream {
|
||||
fn poll_read(self: Pin<&mut Self>, _: &mut Context<'_>, _: &mut [u8])
|
||||
-> Poll<Result<usize, io::Error>>
|
||||
{
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
_: &mut [u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
Poll::Ready(Err(io::ErrorKind::Other.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for DummyStream {
|
||||
fn poll_write(self: Pin<&mut Self>, _: &mut Context<'_>, _: &[u8])
|
||||
-> Poll<Result<usize, io::Error>>
|
||||
{
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
_: &[u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
Poll::Ready(Err(io::ErrorKind::Other.into()))
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>)
|
||||
-> Poll<Result<(), io::Error>>
|
||||
{
|
||||
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
Poll::Ready(Err(io::ErrorKind::Other.into()))
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>)
|
||||
-> Poll<Result<(), io::Error>>
|
||||
{
|
||||
fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
Poll::Ready(Err(io::ErrorKind::Other.into()))
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
transport::{ListenerEvent, Transport, TransportError},
|
||||
ConnectedPoint,
|
||||
transport::{Transport, TransportError, ListenerEvent}
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use multiaddr::Multiaddr;
|
||||
@ -28,7 +28,10 @@ use std::{pin::Pin, task::Context, task::Poll};
|
||||
|
||||
/// See `Transport::map`.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Map<T, F> { transport: T, fun: F }
|
||||
pub struct Map<T, F> {
|
||||
transport: T,
|
||||
fun: F,
|
||||
}
|
||||
|
||||
impl<T, F> Map<T, F> {
|
||||
pub(crate) fn new(transport: T, fun: F) -> Self {
|
||||
@ -39,7 +42,7 @@ impl<T, F> Map<T, F> {
|
||||
impl<T, F, D> Transport for Map<T, F>
|
||||
where
|
||||
T: Transport,
|
||||
F: FnOnce(T::Output, ConnectedPoint) -> D + Clone
|
||||
F: FnOnce(T::Output, ConnectedPoint) -> D + Clone,
|
||||
{
|
||||
type Output = D;
|
||||
type Error = T::Error;
|
||||
@ -49,13 +52,19 @@ where
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
let stream = self.transport.listen_on(addr)?;
|
||||
Ok(MapStream { stream, fun: self.fun })
|
||||
Ok(MapStream {
|
||||
stream,
|
||||
fun: self.fun,
|
||||
})
|
||||
}
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let future = self.transport.dial(addr.clone())?;
|
||||
let p = ConnectedPoint::Dialer { address: addr };
|
||||
Ok(MapFuture { inner: future, args: Some((self.fun, p)) })
|
||||
Ok(MapFuture {
|
||||
inner: future,
|
||||
args: Some((self.fun, p)),
|
||||
})
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
@ -68,13 +77,17 @@ where
|
||||
/// Maps a function over every stream item.
|
||||
#[pin_project::pin_project]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapStream<T, F> { #[pin] stream: T, fun: F }
|
||||
pub struct MapStream<T, F> {
|
||||
#[pin]
|
||||
stream: T,
|
||||
fun: F,
|
||||
}
|
||||
|
||||
impl<T, F, A, B, X, E> Stream for MapStream<T, F>
|
||||
where
|
||||
T: TryStream<Ok = ListenerEvent<X, E>, Error = E>,
|
||||
X: TryFuture<Ok = A>,
|
||||
F: FnOnce(A, ConnectedPoint) -> B + Clone
|
||||
F: FnOnce(A, ConnectedPoint) -> B + Clone,
|
||||
{
|
||||
type Item = Result<ListenerEvent<MapFuture<X, F>, E>, E>;
|
||||
|
||||
@ -83,18 +96,22 @@ where
|
||||
match TryStream::try_poll_next(this.stream, cx) {
|
||||
Poll::Ready(Some(Ok(event))) => {
|
||||
let event = match event {
|
||||
ListenerEvent::Upgrade { upgrade, local_addr, remote_addr } => {
|
||||
ListenerEvent::Upgrade {
|
||||
upgrade,
|
||||
local_addr,
|
||||
remote_addr,
|
||||
} => {
|
||||
let point = ConnectedPoint::Listener {
|
||||
local_addr: local_addr.clone(),
|
||||
send_back_addr: remote_addr.clone()
|
||||
send_back_addr: remote_addr.clone(),
|
||||
};
|
||||
ListenerEvent::Upgrade {
|
||||
upgrade: MapFuture {
|
||||
inner: upgrade,
|
||||
args: Some((this.fun.clone(), point))
|
||||
args: Some((this.fun.clone(), point)),
|
||||
},
|
||||
local_addr,
|
||||
remote_addr
|
||||
remote_addr,
|
||||
}
|
||||
}
|
||||
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||
@ -105,7 +122,7 @@ where
|
||||
}
|
||||
Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(err))),
|
||||
Poll::Ready(None) => Poll::Ready(None),
|
||||
Poll::Pending => Poll::Pending
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,13 +135,13 @@ where
|
||||
pub struct MapFuture<T, F> {
|
||||
#[pin]
|
||||
inner: T,
|
||||
args: Option<(F, ConnectedPoint)>
|
||||
args: Option<(F, ConnectedPoint)>,
|
||||
}
|
||||
|
||||
impl<T, A, F, B> Future for MapFuture<T, F>
|
||||
where
|
||||
T: TryFuture<Ok = A>,
|
||||
F: FnOnce(A, ConnectedPoint) -> B
|
||||
F: FnOnce(A, ConnectedPoint) -> B,
|
||||
{
|
||||
type Output = Result<B, T::Error>;
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::transport::{Transport, TransportError, ListenerEvent};
|
||||
use crate::transport::{ListenerEvent, Transport, TransportError};
|
||||
use futures::prelude::*;
|
||||
use multiaddr::Multiaddr;
|
||||
use std::{error, pin::Pin, task::Context, task::Poll};
|
||||
@ -53,14 +53,17 @@ where
|
||||
let map = self.map;
|
||||
match self.transport.listen_on(addr) {
|
||||
Ok(stream) => Ok(MapErrListener { inner: stream, map }),
|
||||
Err(err) => Err(err.map(map))
|
||||
Err(err) => Err(err.map(map)),
|
||||
}
|
||||
}
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let map = self.map;
|
||||
match self.transport.dial(addr) {
|
||||
Ok(future) => Ok(MapErrDial { inner: future, map: Some(map) }),
|
||||
Ok(future) => Ok(MapErrDial {
|
||||
inner: future,
|
||||
map: Some(map),
|
||||
}),
|
||||
Err(err) => Err(err.map(map)),
|
||||
}
|
||||
}
|
||||
@ -92,11 +95,9 @@ where
|
||||
Poll::Ready(Some(Ok(event))) => {
|
||||
let map = &*this.map;
|
||||
let event = event
|
||||
.map(move |value| {
|
||||
MapErrListenerUpgrade {
|
||||
inner: value,
|
||||
map: Some(map.clone())
|
||||
}
|
||||
.map(move |value| MapErrListenerUpgrade {
|
||||
inner: value,
|
||||
map: Some(map.clone()),
|
||||
})
|
||||
.map_err(|err| (map.clone())(err));
|
||||
Poll::Ready(Some(Ok(event)))
|
||||
@ -117,7 +118,8 @@ pub struct MapErrListenerUpgrade<T: Transport, F> {
|
||||
}
|
||||
|
||||
impl<T, F, TErr> Future for MapErrListenerUpgrade<T, F>
|
||||
where T: Transport,
|
||||
where
|
||||
T: Transport,
|
||||
F: FnOnce(T::Error) -> TErr,
|
||||
{
|
||||
type Output = Result<T::Output, TErr>;
|
||||
|
@ -18,11 +18,20 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{Transport, transport::{TransportError, ListenerEvent}};
|
||||
use crate::{
|
||||
transport::{ListenerEvent, TransportError},
|
||||
Transport,
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use futures::{future::{self, Ready}, prelude::*, channel::mpsc, task::Context, task::Poll};
|
||||
use futures::{
|
||||
channel::mpsc,
|
||||
future::{self, Ready},
|
||||
prelude::*,
|
||||
task::Context,
|
||||
task::Poll,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use multiaddr::{Multiaddr, Protocol};
|
||||
use parking_lot::Mutex;
|
||||
use rw_stream_sink::RwStreamSink;
|
||||
use std::{collections::hash_map::Entry, error, fmt, io, num::NonZeroU64, pin::Pin};
|
||||
@ -66,7 +75,7 @@ impl Hub {
|
||||
let (tx, rx) = mpsc::channel(2);
|
||||
match hub.entry(port) {
|
||||
Entry::Occupied(_) => return None,
|
||||
Entry::Vacant(e) => e.insert(tx)
|
||||
Entry::Vacant(e) => e.insert(tx),
|
||||
};
|
||||
|
||||
Some((rx, port))
|
||||
@ -103,7 +112,8 @@ impl DialFuture {
|
||||
fn new(port: NonZeroU64) -> Option<Self> {
|
||||
let sender = HUB.get(&port)?;
|
||||
|
||||
let (_dial_port_channel, dial_port) = HUB.register_port(0)
|
||||
let (_dial_port_channel, dial_port) = HUB
|
||||
.register_port(0)
|
||||
.expect("there to be some random unoccupied port.");
|
||||
|
||||
let (a_tx, a_rx) = mpsc::channel(4096);
|
||||
@ -129,14 +139,15 @@ impl Future for DialFuture {
|
||||
type Output = Result<Channel<Vec<u8>>, MemoryTransportError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
|
||||
match self.sender.poll_ready(cx) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Ok(())) => {},
|
||||
Poll::Ready(Ok(())) => {}
|
||||
Poll::Ready(Err(_)) => return Poll::Ready(Err(MemoryTransportError::Unreachable)),
|
||||
}
|
||||
|
||||
let channel_to_send = self.channel_to_send.take()
|
||||
let channel_to_send = self
|
||||
.channel_to_send
|
||||
.take()
|
||||
.expect("Future should not be polled again once complete");
|
||||
let dial_port = self.dial_port;
|
||||
match self.sender.start_send((channel_to_send, dial_port)) {
|
||||
@ -144,8 +155,10 @@ impl Future for DialFuture {
|
||||
Ok(()) => {}
|
||||
}
|
||||
|
||||
Poll::Ready(Ok(self.channel_to_return.take()
|
||||
.expect("Future should not be polled again once complete")))
|
||||
Poll::Ready(Ok(self
|
||||
.channel_to_return
|
||||
.take()
|
||||
.expect("Future should not be polled again once complete")))
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +185,7 @@ impl Transport for MemoryTransport {
|
||||
port,
|
||||
addr: Protocol::Memory(port.get()).into(),
|
||||
receiver: rx,
|
||||
tell_listen_addr: true
|
||||
tell_listen_addr: true,
|
||||
};
|
||||
|
||||
Ok(listener)
|
||||
@ -226,16 +239,19 @@ pub struct Listener {
|
||||
/// Receives incoming connections.
|
||||
receiver: ChannelReceiver,
|
||||
/// Generate `ListenerEvent::NewAddress` to inform about our listen address.
|
||||
tell_listen_addr: bool
|
||||
tell_listen_addr: bool,
|
||||
}
|
||||
|
||||
impl Stream for Listener {
|
||||
type Item = Result<ListenerEvent<Ready<Result<Channel<Vec<u8>>, MemoryTransportError>>, MemoryTransportError>, MemoryTransportError>;
|
||||
type Item = Result<
|
||||
ListenerEvent<Ready<Result<Channel<Vec<u8>>, MemoryTransportError>>, MemoryTransportError>,
|
||||
MemoryTransportError,
|
||||
>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
if self.tell_listen_addr {
|
||||
self.tell_listen_addr = false;
|
||||
return Poll::Ready(Some(Ok(ListenerEvent::NewAddress(self.addr.clone()))))
|
||||
return Poll::Ready(Some(Ok(ListenerEvent::NewAddress(self.addr.clone()))));
|
||||
}
|
||||
|
||||
let (channel, dial_port) = match Stream::poll_next(Pin::new(&mut self.receiver), cx) {
|
||||
@ -247,7 +263,7 @@ impl Stream for Listener {
|
||||
let event = ListenerEvent::Upgrade {
|
||||
upgrade: future::ready(Ok(channel)),
|
||||
local_addr: self.addr.clone(),
|
||||
remote_addr: Protocol::Memory(dial_port.get()).into()
|
||||
remote_addr: Protocol::Memory(dial_port.get()).into(),
|
||||
};
|
||||
|
||||
Poll::Ready(Some(Ok(event)))
|
||||
@ -267,9 +283,9 @@ fn parse_memory_addr(a: &Multiaddr) -> Result<u64, ()> {
|
||||
match protocols.next() {
|
||||
Some(Protocol::Memory(port)) => match protocols.next() {
|
||||
None | Some(Protocol::P2p(_)) => Ok(port),
|
||||
_ => Err(())
|
||||
}
|
||||
_ => Err(())
|
||||
_ => Err(()),
|
||||
},
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,8 +310,7 @@ pub struct Chan<T = Vec<u8>> {
|
||||
dial_port: Option<NonZeroU64>,
|
||||
}
|
||||
|
||||
impl<T> Unpin for Chan<T> {
|
||||
}
|
||||
impl<T> Unpin for Chan<T> {}
|
||||
|
||||
impl<T> Stream for Chan<T> {
|
||||
type Item = Result<T, io::Error>;
|
||||
@ -313,12 +328,15 @@ impl<T> Sink<T> for Chan<T> {
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.outgoing.poll_ready(cx)
|
||||
self.outgoing
|
||||
.poll_ready(cx)
|
||||
.map(|v| v.map_err(|_| io::ErrorKind::BrokenPipe.into()))
|
||||
}
|
||||
|
||||
fn start_send(mut self: Pin<&mut Self>, item: T) -> Result<(), Self::Error> {
|
||||
self.outgoing.start_send(item).map_err(|_| io::ErrorKind::BrokenPipe.into())
|
||||
self.outgoing
|
||||
.start_send(item)
|
||||
.map_err(|_| io::ErrorKind::BrokenPipe.into())
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
@ -354,30 +372,59 @@ mod tests {
|
||||
assert_eq!(parse_memory_addr(&"/memory/5".parse().unwrap()), Ok(5));
|
||||
assert_eq!(parse_memory_addr(&"/tcp/150".parse().unwrap()), Err(()));
|
||||
assert_eq!(parse_memory_addr(&"/memory/0".parse().unwrap()), Ok(0));
|
||||
assert_eq!(parse_memory_addr(&"/memory/5/tcp/150".parse().unwrap()), Err(()));
|
||||
assert_eq!(parse_memory_addr(&"/tcp/150/memory/5".parse().unwrap()), Err(()));
|
||||
assert_eq!(parse_memory_addr(&"/memory/1234567890".parse().unwrap()), Ok(1_234_567_890));
|
||||
assert_eq!(
|
||||
parse_memory_addr(&"/memory/5/tcp/150".parse().unwrap()),
|
||||
Err(())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_memory_addr(&"/tcp/150/memory/5".parse().unwrap()),
|
||||
Err(())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_memory_addr(&"/memory/1234567890".parse().unwrap()),
|
||||
Ok(1_234_567_890)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn listening_twice() {
|
||||
let transport = MemoryTransport::default();
|
||||
assert!(transport.listen_on("/memory/1639174018481".parse().unwrap()).is_ok());
|
||||
assert!(transport.listen_on("/memory/1639174018481".parse().unwrap()).is_ok());
|
||||
let _listener = transport.listen_on("/memory/1639174018481".parse().unwrap()).unwrap();
|
||||
assert!(transport.listen_on("/memory/1639174018481".parse().unwrap()).is_err());
|
||||
assert!(transport.listen_on("/memory/1639174018481".parse().unwrap()).is_err());
|
||||
assert!(transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.is_ok());
|
||||
assert!(transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.is_ok());
|
||||
let _listener = transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.unwrap();
|
||||
assert!(transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.is_err());
|
||||
assert!(transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.is_err());
|
||||
drop(_listener);
|
||||
assert!(transport.listen_on("/memory/1639174018481".parse().unwrap()).is_ok());
|
||||
assert!(transport.listen_on("/memory/1639174018481".parse().unwrap()).is_ok());
|
||||
assert!(transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.is_ok());
|
||||
assert!(transport
|
||||
.listen_on("/memory/1639174018481".parse().unwrap())
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn port_not_in_use() {
|
||||
let transport = MemoryTransport::default();
|
||||
assert!(transport.dial("/memory/810172461024613".parse().unwrap()).is_err());
|
||||
let _listener = transport.listen_on("/memory/810172461024613".parse().unwrap()).unwrap();
|
||||
assert!(transport.dial("/memory/810172461024613".parse().unwrap()).is_ok());
|
||||
assert!(transport
|
||||
.dial("/memory/810172461024613".parse().unwrap())
|
||||
.is_err());
|
||||
let _listener = transport
|
||||
.listen_on("/memory/810172461024613".parse().unwrap())
|
||||
.unwrap();
|
||||
assert!(transport
|
||||
.dial("/memory/810172461024613".parse().unwrap())
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -395,9 +442,11 @@ mod tests {
|
||||
let listener = async move {
|
||||
let listener = t1.listen_on(t1_addr.clone()).unwrap();
|
||||
|
||||
let upgrade = listener.filter_map(|ev| futures::future::ready(
|
||||
ListenerEvent::into_upgrade(ev.unwrap())
|
||||
)).next().await.unwrap();
|
||||
let upgrade = listener
|
||||
.filter_map(|ev| futures::future::ready(ListenerEvent::into_upgrade(ev.unwrap())))
|
||||
.next()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut socket = upgrade.0.await.unwrap();
|
||||
|
||||
@ -422,16 +471,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn dialer_address_unequal_to_listener_address() {
|
||||
let listener_addr: Multiaddr = Protocol::Memory(
|
||||
rand::random::<u64>().saturating_add(1),
|
||||
).into();
|
||||
let listener_addr: Multiaddr =
|
||||
Protocol::Memory(rand::random::<u64>().saturating_add(1)).into();
|
||||
let listener_addr_cloned = listener_addr.clone();
|
||||
|
||||
let listener_transport = MemoryTransport::default();
|
||||
|
||||
let listener = async move {
|
||||
let mut listener = listener_transport.listen_on(listener_addr.clone())
|
||||
.unwrap();
|
||||
let mut listener = listener_transport.listen_on(listener_addr.clone()).unwrap();
|
||||
while let Some(ev) = listener.next().await {
|
||||
if let ListenerEvent::Upgrade { remote_addr, .. } = ev.unwrap() {
|
||||
assert!(
|
||||
@ -444,7 +491,8 @@ mod tests {
|
||||
};
|
||||
|
||||
let dialer = async move {
|
||||
MemoryTransport::default().dial(listener_addr_cloned)
|
||||
MemoryTransport::default()
|
||||
.dial(listener_addr_cloned)
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
@ -458,21 +506,18 @@ mod tests {
|
||||
let (terminate, should_terminate) = futures::channel::oneshot::channel();
|
||||
let (terminated, is_terminated) = futures::channel::oneshot::channel();
|
||||
|
||||
let listener_addr: Multiaddr = Protocol::Memory(
|
||||
rand::random::<u64>().saturating_add(1),
|
||||
).into();
|
||||
let listener_addr: Multiaddr =
|
||||
Protocol::Memory(rand::random::<u64>().saturating_add(1)).into();
|
||||
let listener_addr_cloned = listener_addr.clone();
|
||||
|
||||
let listener_transport = MemoryTransport::default();
|
||||
|
||||
let listener = async move {
|
||||
let mut listener = listener_transport.listen_on(listener_addr.clone())
|
||||
.unwrap();
|
||||
let mut listener = listener_transport.listen_on(listener_addr.clone()).unwrap();
|
||||
while let Some(ev) = listener.next().await {
|
||||
if let ListenerEvent::Upgrade { remote_addr, .. } = ev.unwrap() {
|
||||
let dialer_port = NonZeroU64::new(
|
||||
parse_memory_addr(&remote_addr).unwrap(),
|
||||
).unwrap();
|
||||
let dialer_port =
|
||||
NonZeroU64::new(parse_memory_addr(&remote_addr).unwrap()).unwrap();
|
||||
|
||||
assert!(
|
||||
HUB.get(&dialer_port).is_some(),
|
||||
@ -493,7 +538,8 @@ mod tests {
|
||||
};
|
||||
|
||||
let dialer = async move {
|
||||
let _chan = MemoryTransport::default().dial(listener_addr_cloned)
|
||||
let _chan = MemoryTransport::default()
|
||||
.dial(listener_addr_cloned)
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap();
|
||||
|
@ -24,7 +24,10 @@
|
||||
//! underlying `Transport`.
|
||||
// TODO: add example
|
||||
|
||||
use crate::{Multiaddr, Transport, transport::{TransportError, ListenerEvent}};
|
||||
use crate::{
|
||||
transport::{ListenerEvent, TransportError},
|
||||
Multiaddr, Transport,
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use futures_timer::Delay;
|
||||
use std::{error, fmt, io, pin::Pin, task::Context, task::Poll, time::Duration};
|
||||
@ -82,7 +85,9 @@ where
|
||||
type Dial = Timeout<InnerTrans::Dial>;
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
let listener = self.inner.listen_on(addr)
|
||||
let listener = self
|
||||
.inner
|
||||
.listen_on(addr)
|
||||
.map_err(|err| err.map(TransportTimeoutError::Other))?;
|
||||
|
||||
let listener = TimeoutListener {
|
||||
@ -94,7 +99,9 @@ where
|
||||
}
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let dial = self.inner.dial(addr)
|
||||
let dial = self
|
||||
.inner
|
||||
.dial(addr)
|
||||
.map_err(|err| err.map(TransportTimeoutError::Other))?;
|
||||
Ok(Timeout {
|
||||
inner: dial,
|
||||
@ -120,13 +127,16 @@ impl<InnerStream, O, E> Stream for TimeoutListener<InnerStream>
|
||||
where
|
||||
InnerStream: TryStream<Ok = ListenerEvent<O, E>, Error = E>,
|
||||
{
|
||||
type Item = Result<ListenerEvent<Timeout<O>, TransportTimeoutError<E>>, TransportTimeoutError<E>>;
|
||||
type Item =
|
||||
Result<ListenerEvent<Timeout<O>, TransportTimeoutError<E>>, TransportTimeoutError<E>>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let this = self.project();
|
||||
|
||||
let poll_out = match TryStream::try_poll_next(this.inner, cx) {
|
||||
Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(TransportTimeoutError::Other(err)))),
|
||||
Poll::Ready(Some(Err(err))) => {
|
||||
return Poll::Ready(Some(Err(TransportTimeoutError::Other(err))))
|
||||
}
|
||||
Poll::Ready(Some(Ok(v))) => v,
|
||||
Poll::Ready(None) => return Poll::Ready(None),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
@ -134,11 +144,9 @@ where
|
||||
|
||||
let timeout = *this.timeout;
|
||||
let event = poll_out
|
||||
.map(move |inner_fut| {
|
||||
Timeout {
|
||||
inner: inner_fut,
|
||||
timer: Delay::new(timeout),
|
||||
}
|
||||
.map(move |inner_fut| Timeout {
|
||||
inner: inner_fut,
|
||||
timer: Delay::new(timeout),
|
||||
})
|
||||
.map_err(TransportTimeoutError::Other);
|
||||
|
||||
@ -173,14 +181,14 @@ where
|
||||
let mut this = self.project();
|
||||
|
||||
match TryFuture::try_poll(this.inner, cx) {
|
||||
Poll::Pending => {},
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(Ok(v)) => return Poll::Ready(Ok(v)),
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Err(TransportTimeoutError::Other(err))),
|
||||
}
|
||||
|
||||
match Pin::new(&mut this.timer).poll(cx) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(()) => Poll::Ready(Err(TransportTimeoutError::Timeout))
|
||||
Poll::Ready(()) => Poll::Ready(Err(TransportTimeoutError::Timeout)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,7 +205,8 @@ pub enum TransportTimeoutError<TErr> {
|
||||
}
|
||||
|
||||
impl<TErr> fmt::Display for TransportTimeoutError<TErr>
|
||||
where TErr: fmt::Display,
|
||||
where
|
||||
TErr: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
@ -209,7 +218,8 @@ where TErr: fmt::Display,
|
||||
}
|
||||
|
||||
impl<TErr> error::Error for TransportTimeoutError<TErr>
|
||||
where TErr: error::Error + 'static,
|
||||
where
|
||||
TErr: error::Error + 'static,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
|
@ -23,28 +23,16 @@
|
||||
pub use crate::upgrade::Version;
|
||||
|
||||
use crate::{
|
||||
ConnectedPoint,
|
||||
Negotiated,
|
||||
transport::{
|
||||
Transport,
|
||||
TransportError,
|
||||
ListenerEvent,
|
||||
and_then::AndThen,
|
||||
boxed::boxed,
|
||||
timeout::TransportTimeout,
|
||||
},
|
||||
muxing::{StreamMuxer, StreamMuxerBox},
|
||||
upgrade::{
|
||||
self,
|
||||
OutboundUpgrade,
|
||||
InboundUpgrade,
|
||||
apply_inbound,
|
||||
apply_outbound,
|
||||
UpgradeError,
|
||||
OutboundUpgradeApply,
|
||||
InboundUpgradeApply
|
||||
transport::{
|
||||
and_then::AndThen, boxed::boxed, timeout::TransportTimeout, ListenerEvent, Transport,
|
||||
TransportError,
|
||||
},
|
||||
PeerId
|
||||
upgrade::{
|
||||
self, apply_inbound, apply_outbound, InboundUpgrade, InboundUpgradeApply, OutboundUpgrade,
|
||||
OutboundUpgradeApply, UpgradeError,
|
||||
},
|
||||
ConnectedPoint, Negotiated, PeerId,
|
||||
};
|
||||
use futures::{prelude::*, ready};
|
||||
use multiaddr::Multiaddr;
|
||||
@ -53,7 +41,7 @@ use std::{
|
||||
fmt,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
time::Duration
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
/// A `Builder` facilitates upgrading of a [`Transport`] for use with
|
||||
@ -105,9 +93,11 @@ where
|
||||
///
|
||||
/// * I/O upgrade: `C -> (PeerId, D)`.
|
||||
/// * Transport output: `C -> (PeerId, D)`
|
||||
pub fn authenticate<C, D, U, E>(self, upgrade: U) -> Authenticated<
|
||||
AndThen<T, impl FnOnce(C, ConnectedPoint) -> Authenticate<C, U> + Clone>
|
||||
> where
|
||||
pub fn authenticate<C, D, U, E>(
|
||||
self,
|
||||
upgrade: U,
|
||||
) -> Authenticated<AndThen<T, impl FnOnce(C, ConnectedPoint) -> Authenticate<C, U> + Clone>>
|
||||
where
|
||||
T: Transport<Output = C>,
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
D: AsyncRead + AsyncWrite + Unpin,
|
||||
@ -116,11 +106,12 @@ where
|
||||
E: Error + 'static,
|
||||
{
|
||||
let version = self.version;
|
||||
Authenticated(Builder::new(self.inner.and_then(move |conn, endpoint| {
|
||||
Authenticate {
|
||||
inner: upgrade::apply(conn, upgrade, endpoint, version)
|
||||
}
|
||||
}), version))
|
||||
Authenticated(Builder::new(
|
||||
self.inner.and_then(move |conn, endpoint| Authenticate {
|
||||
inner: upgrade::apply(conn, upgrade, endpoint, version),
|
||||
}),
|
||||
version,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,19 +123,21 @@ where
|
||||
pub struct Authenticate<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>> + OutboundUpgrade<Negotiated<C>>
|
||||
U: InboundUpgrade<Negotiated<C>> + OutboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
#[pin]
|
||||
inner: EitherUpgrade<C, U>
|
||||
inner: EitherUpgrade<C, U>,
|
||||
}
|
||||
|
||||
impl<C, U> Future for Authenticate<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>> + OutboundUpgrade<Negotiated<C>,
|
||||
Output = <U as InboundUpgrade<Negotiated<C>>>::Output,
|
||||
Error = <U as InboundUpgrade<Negotiated<C>>>::Error
|
||||
>
|
||||
U: InboundUpgrade<Negotiated<C>>
|
||||
+ OutboundUpgrade<
|
||||
Negotiated<C>,
|
||||
Output = <U as InboundUpgrade<Negotiated<C>>>::Output,
|
||||
Error = <U as InboundUpgrade<Negotiated<C>>>::Error,
|
||||
>,
|
||||
{
|
||||
type Output = <EitherUpgrade<C, U> as Future>::Output;
|
||||
|
||||
@ -173,7 +166,7 @@ impl<C, U, M, E> Future for Multiplex<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>, Output = M, Error = E>,
|
||||
U: OutboundUpgrade<Negotiated<C>, Output = M, Error = E>
|
||||
U: OutboundUpgrade<Negotiated<C>, Output = M, Error = E>,
|
||||
{
|
||||
type Output = Result<(PeerId, M), UpgradeError<E>>;
|
||||
|
||||
@ -183,7 +176,10 @@ where
|
||||
Ok(m) => m,
|
||||
Err(err) => return Poll::Ready(Err(err)),
|
||||
};
|
||||
let i = this.peer_id.take().expect("Multiplex future polled after completion.");
|
||||
let i = this
|
||||
.peer_id
|
||||
.take()
|
||||
.expect("Multiplex future polled after completion.");
|
||||
Poll::Ready(Ok((i, m)))
|
||||
}
|
||||
}
|
||||
@ -195,7 +191,7 @@ pub struct Authenticated<T>(Builder<T>);
|
||||
impl<T> Authenticated<T>
|
||||
where
|
||||
T: Transport,
|
||||
T::Error: 'static
|
||||
T::Error: 'static,
|
||||
{
|
||||
/// Applies an arbitrary upgrade.
|
||||
///
|
||||
@ -216,7 +212,10 @@ where
|
||||
U: OutboundUpgrade<Negotiated<C>, Output = D, Error = E> + Clone,
|
||||
E: Error + 'static,
|
||||
{
|
||||
Authenticated(Builder::new(Upgrade::new(self.0.inner, upgrade), self.0.version))
|
||||
Authenticated(Builder::new(
|
||||
Upgrade::new(self.0.inner, upgrade),
|
||||
self.0.version,
|
||||
))
|
||||
}
|
||||
|
||||
/// Upgrades the transport with a (sub)stream multiplexer.
|
||||
@ -229,9 +228,11 @@ where
|
||||
///
|
||||
/// * I/O upgrade: `C -> M`.
|
||||
/// * Transport output: `(PeerId, C) -> (PeerId, M)`.
|
||||
pub fn multiplex<C, M, U, E>(self, upgrade: U) -> Multiplexed<
|
||||
AndThen<T, impl FnOnce((PeerId, C), ConnectedPoint) -> Multiplex<C, U> + Clone>
|
||||
> where
|
||||
pub fn multiplex<C, M, U, E>(
|
||||
self,
|
||||
upgrade: U,
|
||||
) -> Multiplexed<AndThen<T, impl FnOnce((PeerId, C), ConnectedPoint) -> Multiplex<C, U> + Clone>>
|
||||
where
|
||||
T: Transport<Output = (PeerId, C)>,
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
M: StreamMuxer,
|
||||
@ -242,7 +243,10 @@ where
|
||||
let version = self.0.version;
|
||||
Multiplexed(self.0.inner.and_then(move |(i, c), endpoint| {
|
||||
let upgrade = upgrade::apply(c, upgrade, endpoint, version);
|
||||
Multiplex { peer_id: Some(i), upgrade }
|
||||
Multiplex {
|
||||
peer_id: Some(i),
|
||||
upgrade,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
@ -257,21 +261,26 @@ where
|
||||
///
|
||||
/// * I/O upgrade: `C -> M`.
|
||||
/// * Transport output: `(PeerId, C) -> (PeerId, M)`.
|
||||
pub fn multiplex_ext<C, M, U, E, F>(self, up: F) -> Multiplexed<
|
||||
AndThen<T, impl FnOnce((PeerId, C), ConnectedPoint) -> Multiplex<C, U> + Clone>
|
||||
> where
|
||||
pub fn multiplex_ext<C, M, U, E, F>(
|
||||
self,
|
||||
up: F,
|
||||
) -> Multiplexed<AndThen<T, impl FnOnce((PeerId, C), ConnectedPoint) -> Multiplex<C, U> + Clone>>
|
||||
where
|
||||
T: Transport<Output = (PeerId, C)>,
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
M: StreamMuxer,
|
||||
U: InboundUpgrade<Negotiated<C>, Output = M, Error = E>,
|
||||
U: OutboundUpgrade<Negotiated<C>, Output = M, Error = E> + Clone,
|
||||
E: Error + 'static,
|
||||
F: for<'a> FnOnce(&'a PeerId, &'a ConnectedPoint) -> U + Clone
|
||||
F: for<'a> FnOnce(&'a PeerId, &'a ConnectedPoint) -> U + Clone,
|
||||
{
|
||||
let version = self.0.version;
|
||||
Multiplexed(self.0.inner.and_then(move |(peer_id, c), endpoint| {
|
||||
let upgrade = upgrade::apply(c, up(&peer_id, &endpoint), endpoint, version);
|
||||
Multiplex { peer_id: Some(peer_id), upgrade }
|
||||
Multiplex {
|
||||
peer_id: Some(peer_id),
|
||||
upgrade,
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -293,7 +302,7 @@ impl<T> Multiplexed<T> {
|
||||
T::Error: Send + Sync,
|
||||
M: StreamMuxer + Send + Sync + 'static,
|
||||
M::Substream: Send + 'static,
|
||||
M::OutboundSubstream: Send + 'static
|
||||
M::OutboundSubstream: Send + 'static,
|
||||
{
|
||||
boxed(self.map(|(i, m), _| (i, StreamMuxerBox::new(m))))
|
||||
}
|
||||
@ -347,7 +356,10 @@ type EitherUpgrade<C, U> = future::Either<InboundUpgradeApply<C, U>, OutboundUpg
|
||||
///
|
||||
/// See [`Transport::upgrade`]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Upgrade<T, U> { inner: T, upgrade: U }
|
||||
pub struct Upgrade<T, U> {
|
||||
inner: T,
|
||||
upgrade: U,
|
||||
}
|
||||
|
||||
impl<T, U> Upgrade<T, U> {
|
||||
pub fn new(inner: T, upgrade: U) -> Self {
|
||||
@ -362,7 +374,7 @@ where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>, Output = D, Error = E>,
|
||||
U: OutboundUpgrade<Negotiated<C>, Output = D, Error = E> + Clone,
|
||||
E: Error + 'static
|
||||
E: Error + 'static,
|
||||
{
|
||||
type Output = (PeerId, D);
|
||||
type Error = TransportUpgradeError<T::Error, E>;
|
||||
@ -371,20 +383,24 @@ where
|
||||
type Dial = DialUpgradeFuture<T::Dial, U, C>;
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let future = self.inner.dial(addr)
|
||||
let future = self
|
||||
.inner
|
||||
.dial(addr)
|
||||
.map_err(|err| err.map(TransportUpgradeError::Transport))?;
|
||||
Ok(DialUpgradeFuture {
|
||||
future: Box::pin(future),
|
||||
upgrade: future::Either::Left(Some(self.upgrade))
|
||||
upgrade: future::Either::Left(Some(self.upgrade)),
|
||||
})
|
||||
}
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
let stream = self.inner.listen_on(addr)
|
||||
let stream = self
|
||||
.inner
|
||||
.listen_on(addr)
|
||||
.map_err(|err| err.map(TransportUpgradeError::Transport))?;
|
||||
Ok(ListenerStream {
|
||||
stream: Box::pin(stream),
|
||||
upgrade: self.upgrade
|
||||
upgrade: self.upgrade,
|
||||
})
|
||||
}
|
||||
|
||||
@ -435,7 +451,7 @@ where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
future: Pin<Box<F>>,
|
||||
upgrade: future::Either<Option<U>, (Option<PeerId>, OutboundUpgradeApply<C, U>)>
|
||||
upgrade: future::Either<Option<U>, (Option<PeerId>, OutboundUpgradeApply<C, U>)>,
|
||||
}
|
||||
|
||||
impl<F, U, C, D> Future for DialUpgradeFuture<F, U, C>
|
||||
@ -443,7 +459,7 @@ where
|
||||
F: TryFuture<Ok = (PeerId, C)>,
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: OutboundUpgrade<Negotiated<C>, Output = D>,
|
||||
U::Error: Error
|
||||
U::Error: Error,
|
||||
{
|
||||
type Output = Result<(PeerId, D), TransportUpgradeError<F::Error, U::Error>>;
|
||||
|
||||
@ -455,20 +471,28 @@ where
|
||||
loop {
|
||||
this.upgrade = match this.upgrade {
|
||||
future::Either::Left(ref mut up) => {
|
||||
let (i, c) = match ready!(TryFuture::try_poll(this.future.as_mut(), cx).map_err(TransportUpgradeError::Transport)) {
|
||||
let (i, c) = match ready!(TryFuture::try_poll(this.future.as_mut(), cx)
|
||||
.map_err(TransportUpgradeError::Transport))
|
||||
{
|
||||
Ok(v) => v,
|
||||
Err(err) => return Poll::Ready(Err(err)),
|
||||
};
|
||||
let u = up.take().expect("DialUpgradeFuture is constructed with Either::Left(Some).");
|
||||
let u = up
|
||||
.take()
|
||||
.expect("DialUpgradeFuture is constructed with Either::Left(Some).");
|
||||
future::Either::Right((Some(i), apply_outbound(c, u, upgrade::Version::V1)))
|
||||
}
|
||||
future::Either::Right((ref mut i, ref mut up)) => {
|
||||
let d = match ready!(Future::poll(Pin::new(up), cx).map_err(TransportUpgradeError::Upgrade)) {
|
||||
let d = match ready!(
|
||||
Future::poll(Pin::new(up), cx).map_err(TransportUpgradeError::Upgrade)
|
||||
) {
|
||||
Ok(d) => d,
|
||||
Err(err) => return Poll::Ready(Err(err)),
|
||||
};
|
||||
let i = i.take().expect("DialUpgradeFuture polled after completion.");
|
||||
return Poll::Ready(Ok((i, d)))
|
||||
let i = i
|
||||
.take()
|
||||
.expect("DialUpgradeFuture polled after completion.");
|
||||
return Poll::Ready(Ok((i, d)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -485,7 +509,7 @@ where
|
||||
/// The [`Transport::Listener`] stream of an [`Upgrade`]d transport.
|
||||
pub struct ListenerStream<S, U> {
|
||||
stream: Pin<Box<S>>,
|
||||
upgrade: U
|
||||
upgrade: U,
|
||||
}
|
||||
|
||||
impl<S, U, F, C, D, E> Stream for ListenerStream<S, U>
|
||||
@ -493,42 +517,40 @@ where
|
||||
S: TryStream<Ok = ListenerEvent<F, E>, Error = E>,
|
||||
F: TryFuture<Ok = (PeerId, C)>,
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>, Output = D> + Clone
|
||||
U: InboundUpgrade<Negotiated<C>, Output = D> + Clone,
|
||||
{
|
||||
type Item = Result<ListenerEvent<ListenerUpgradeFuture<F, U, C>, TransportUpgradeError<E, U::Error>>, TransportUpgradeError<E, U::Error>>;
|
||||
type Item = Result<
|
||||
ListenerEvent<ListenerUpgradeFuture<F, U, C>, TransportUpgradeError<E, U::Error>>,
|
||||
TransportUpgradeError<E, U::Error>,
|
||||
>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
match ready!(TryStream::try_poll_next(self.stream.as_mut(), cx)) {
|
||||
Some(Ok(event)) => {
|
||||
let event = event
|
||||
.map(move |future| {
|
||||
ListenerUpgradeFuture {
|
||||
future: Box::pin(future),
|
||||
upgrade: future::Either::Left(Some(self.upgrade.clone()))
|
||||
}
|
||||
.map(move |future| ListenerUpgradeFuture {
|
||||
future: Box::pin(future),
|
||||
upgrade: future::Either::Left(Some(self.upgrade.clone())),
|
||||
})
|
||||
.map_err(TransportUpgradeError::Transport);
|
||||
Poll::Ready(Some(Ok(event)))
|
||||
}
|
||||
Some(Err(err)) => {
|
||||
Poll::Ready(Some(Err(TransportUpgradeError::Transport(err))))
|
||||
}
|
||||
None => Poll::Ready(None)
|
||||
Some(Err(err)) => Poll::Ready(Some(Err(TransportUpgradeError::Transport(err)))),
|
||||
None => Poll::Ready(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, U> Unpin for ListenerStream<S, U> {
|
||||
}
|
||||
impl<S, U> Unpin for ListenerStream<S, U> {}
|
||||
|
||||
/// The [`Transport::ListenerUpgrade`] future of an [`Upgrade`]d transport.
|
||||
pub struct ListenerUpgradeFuture<F, U, C>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>>
|
||||
U: InboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
future: Pin<Box<F>>,
|
||||
upgrade: future::Either<Option<U>, (Option<PeerId>, InboundUpgradeApply<C, U>)>
|
||||
upgrade: future::Either<Option<U>, (Option<PeerId>, InboundUpgradeApply<C, U>)>,
|
||||
}
|
||||
|
||||
impl<F, U, C, D> Future for ListenerUpgradeFuture<F, U, C>
|
||||
@ -536,7 +558,7 @@ where
|
||||
F: TryFuture<Ok = (PeerId, C)>,
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>, Output = D>,
|
||||
U::Error: Error
|
||||
U::Error: Error,
|
||||
{
|
||||
type Output = Result<(PeerId, D), TransportUpgradeError<F::Error, U::Error>>;
|
||||
|
||||
@ -548,20 +570,28 @@ where
|
||||
loop {
|
||||
this.upgrade = match this.upgrade {
|
||||
future::Either::Left(ref mut up) => {
|
||||
let (i, c) = match ready!(TryFuture::try_poll(this.future.as_mut(), cx).map_err(TransportUpgradeError::Transport)) {
|
||||
let (i, c) = match ready!(TryFuture::try_poll(this.future.as_mut(), cx)
|
||||
.map_err(TransportUpgradeError::Transport))
|
||||
{
|
||||
Ok(v) => v,
|
||||
Err(err) => return Poll::Ready(Err(err))
|
||||
Err(err) => return Poll::Ready(Err(err)),
|
||||
};
|
||||
let u = up.take().expect("ListenerUpgradeFuture is constructed with Either::Left(Some).");
|
||||
let u = up
|
||||
.take()
|
||||
.expect("ListenerUpgradeFuture is constructed with Either::Left(Some).");
|
||||
future::Either::Right((Some(i), apply_inbound(c, u)))
|
||||
}
|
||||
future::Either::Right((ref mut i, ref mut up)) => {
|
||||
let d = match ready!(TryFuture::try_poll(Pin::new(up), cx).map_err(TransportUpgradeError::Upgrade)) {
|
||||
let d = match ready!(TryFuture::try_poll(Pin::new(up), cx)
|
||||
.map_err(TransportUpgradeError::Upgrade))
|
||||
{
|
||||
Ok(v) => v,
|
||||
Err(err) => return Poll::Ready(Err(err))
|
||||
Err(err) => return Poll::Ready(Err(err)),
|
||||
};
|
||||
let i = i.take().expect("ListenerUpgradeFuture polled after completion.");
|
||||
return Poll::Ready(Ok((i, d)))
|
||||
let i = i
|
||||
.take()
|
||||
.expect("ListenerUpgradeFuture polled after completion.");
|
||||
return Poll::Ready(Ok((i, d)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -571,6 +601,6 @@ where
|
||||
impl<F, U, C> Unpin for ListenerUpgradeFuture<F, U, C>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>>
|
||||
U: InboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
}
|
||||
|
@ -69,21 +69,21 @@ mod transfer;
|
||||
|
||||
use futures::future::Future;
|
||||
|
||||
pub use crate::Negotiated;
|
||||
pub use multistream_select::{Version, NegotiatedComplete, NegotiationError, ProtocolError};
|
||||
#[allow(deprecated)]
|
||||
pub use self::transfer::ReadOneError;
|
||||
pub use self::{
|
||||
apply::{apply, apply_inbound, apply_outbound, InboundUpgradeApply, OutboundUpgradeApply},
|
||||
denied::DeniedUpgrade,
|
||||
either::EitherUpgrade,
|
||||
error::UpgradeError,
|
||||
from_fn::{from_fn, FromFnUpgrade},
|
||||
map::{MapInboundUpgrade, MapOutboundUpgrade, MapInboundUpgradeErr, MapOutboundUpgradeErr},
|
||||
map::{MapInboundUpgrade, MapInboundUpgradeErr, MapOutboundUpgrade, MapOutboundUpgradeErr},
|
||||
optional::OptionalUpgrade,
|
||||
select::SelectUpgrade,
|
||||
transfer::{write_length_prefixed, write_varint, read_length_prefixed, read_varint},
|
||||
transfer::{read_length_prefixed, read_varint, write_length_prefixed, write_varint},
|
||||
};
|
||||
#[allow(deprecated)]
|
||||
pub use self::transfer::ReadOneError;
|
||||
pub use crate::Negotiated;
|
||||
pub use multistream_select::{NegotiatedComplete, NegotiationError, ProtocolError, Version};
|
||||
|
||||
/// Types serving as protocol names.
|
||||
///
|
||||
@ -167,7 +167,7 @@ pub trait InboundUpgradeExt<C>: InboundUpgrade<C> {
|
||||
fn map_inbound<F, T>(self, f: F) -> MapInboundUpgrade<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Output) -> T
|
||||
F: FnOnce(Self::Output) -> T,
|
||||
{
|
||||
MapInboundUpgrade::new(self, f)
|
||||
}
|
||||
@ -176,7 +176,7 @@ pub trait InboundUpgradeExt<C>: InboundUpgrade<C> {
|
||||
fn map_inbound_err<F, T>(self, f: F) -> MapInboundUpgradeErr<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Error) -> T
|
||||
F: FnOnce(Self::Error) -> T,
|
||||
{
|
||||
MapInboundUpgradeErr::new(self, f)
|
||||
}
|
||||
@ -207,7 +207,7 @@ pub trait OutboundUpgradeExt<C>: OutboundUpgrade<C> {
|
||||
fn map_outbound<F, T>(self, f: F) -> MapOutboundUpgrade<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Output) -> T
|
||||
F: FnOnce(Self::Output) -> T,
|
||||
{
|
||||
MapOutboundUpgrade::new(self, f)
|
||||
}
|
||||
@ -216,11 +216,10 @@ pub trait OutboundUpgradeExt<C>: OutboundUpgrade<C> {
|
||||
fn map_outbound_err<F, T>(self, f: F) -> MapOutboundUpgradeErr<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Error) -> T
|
||||
F: FnOnce(Self::Error) -> T,
|
||||
{
|
||||
MapOutboundUpgradeErr::new(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, U: OutboundUpgrade<C>> OutboundUpgradeExt<C> for U {}
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
||||
// 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::{ConnectedPoint, Negotiated};
|
||||
use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeError, ProtocolName};
|
||||
use futures::{future::Either, prelude::*};
|
||||
use log::debug;
|
||||
use multistream_select::{self, DialerSelectFuture, ListenerSelectFuture};
|
||||
@ -28,8 +28,12 @@ use std::{iter, mem, pin::Pin, task::Context, task::Poll};
|
||||
pub use multistream_select::Version;
|
||||
|
||||
/// Applies an upgrade to the inbound and outbound direction of a connection or substream.
|
||||
pub fn apply<C, U>(conn: C, up: U, cp: ConnectedPoint, v: Version)
|
||||
-> Either<InboundUpgradeApply<C, U>, OutboundUpgradeApply<C, U>>
|
||||
pub fn apply<C, U>(
|
||||
conn: C,
|
||||
up: U,
|
||||
cp: ConnectedPoint,
|
||||
v: Version,
|
||||
) -> Either<InboundUpgradeApply<C, U>, OutboundUpgradeApply<C, U>>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>> + OutboundUpgrade<Negotiated<C>>,
|
||||
@ -47,10 +51,16 @@ where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
let iter = up.protocol_info().into_iter().map(NameWrap as fn(_) -> NameWrap<_>);
|
||||
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, upgrade: up }
|
||||
inner: InboundUpgradeApplyState::Init {
|
||||
future,
|
||||
upgrade: up,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,12 +68,18 @@ where
|
||||
pub fn apply_outbound<C, U>(conn: C, up: U, v: Version) -> OutboundUpgradeApply<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: OutboundUpgrade<Negotiated<C>>
|
||||
U: OutboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
let iter = up.protocol_info().into_iter().map(NameWrap as fn(_) -> NameWrap<_>);
|
||||
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, upgrade: up }
|
||||
inner: OutboundUpgradeApplyState::Init {
|
||||
future,
|
||||
upgrade: up,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,9 +87,9 @@ where
|
||||
pub struct InboundUpgradeApply<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>>
|
||||
U: InboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
inner: InboundUpgradeApplyState<C, U>
|
||||
inner: InboundUpgradeApplyState<C, U>,
|
||||
}
|
||||
|
||||
enum InboundUpgradeApplyState<C, U>
|
||||
@ -86,9 +102,9 @@ where
|
||||
upgrade: U,
|
||||
},
|
||||
Upgrade {
|
||||
future: Pin<Box<U::Future>>
|
||||
future: Pin<Box<U::Future>>,
|
||||
},
|
||||
Undefined
|
||||
Undefined,
|
||||
}
|
||||
|
||||
impl<C, U> Unpin for InboundUpgradeApply<C, U>
|
||||
@ -108,36 +124,40 @@ where
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
loop {
|
||||
match mem::replace(&mut self.inner, InboundUpgradeApplyState::Undefined) {
|
||||
InboundUpgradeApplyState::Init { mut future, upgrade } => {
|
||||
InboundUpgradeApplyState::Init {
|
||||
mut future,
|
||||
upgrade,
|
||||
} => {
|
||||
let (info, io) = match Future::poll(Pin::new(&mut future), cx)? {
|
||||
Poll::Ready(x) => x,
|
||||
Poll::Pending => {
|
||||
self.inner = InboundUpgradeApplyState::Init { future, upgrade };
|
||||
return Poll::Pending
|
||||
return Poll::Pending;
|
||||
}
|
||||
};
|
||||
self.inner = InboundUpgradeApplyState::Upgrade {
|
||||
future: Box::pin(upgrade.upgrade_inbound(io, info.0))
|
||||
future: Box::pin(upgrade.upgrade_inbound(io, info.0)),
|
||||
};
|
||||
}
|
||||
InboundUpgradeApplyState::Upgrade { mut future } => {
|
||||
match Future::poll(Pin::new(&mut future), cx) {
|
||||
Poll::Pending => {
|
||||
self.inner = InboundUpgradeApplyState::Upgrade { future };
|
||||
return Poll::Pending
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(Ok(x)) => {
|
||||
debug!("Successfully applied negotiated protocol");
|
||||
return Poll::Ready(Ok(x))
|
||||
return Poll::Ready(Ok(x));
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
debug!("Failed to apply negotiated protocol");
|
||||
return Poll::Ready(Err(UpgradeError::Apply(e)))
|
||||
return Poll::Ready(Err(UpgradeError::Apply(e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
InboundUpgradeApplyState::Undefined =>
|
||||
InboundUpgradeApplyState::Undefined => {
|
||||
panic!("InboundUpgradeApplyState::poll called after completion")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,24 +167,24 @@ where
|
||||
pub struct OutboundUpgradeApply<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: OutboundUpgrade<Negotiated<C>>
|
||||
U: OutboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
inner: OutboundUpgradeApplyState<C, U>
|
||||
inner: OutboundUpgradeApplyState<C, U>,
|
||||
}
|
||||
|
||||
enum OutboundUpgradeApplyState<C, U>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: OutboundUpgrade<Negotiated<C>>
|
||||
U: OutboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
Init {
|
||||
future: DialerSelectFuture<C, NameWrapIter<<U::InfoIter as IntoIterator>::IntoIter>>,
|
||||
upgrade: U
|
||||
upgrade: U,
|
||||
},
|
||||
Upgrade {
|
||||
future: Pin<Box<U::Future>>
|
||||
future: Pin<Box<U::Future>>,
|
||||
},
|
||||
Undefined
|
||||
Undefined,
|
||||
}
|
||||
|
||||
impl<C, U> Unpin for OutboundUpgradeApply<C, U>
|
||||
@ -184,27 +204,30 @@ where
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
loop {
|
||||
match mem::replace(&mut self.inner, OutboundUpgradeApplyState::Undefined) {
|
||||
OutboundUpgradeApplyState::Init { mut future, upgrade } => {
|
||||
OutboundUpgradeApplyState::Init {
|
||||
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
|
||||
return Poll::Pending;
|
||||
}
|
||||
};
|
||||
self.inner = OutboundUpgradeApplyState::Upgrade {
|
||||
future: Box::pin(upgrade.upgrade_outbound(connection, info.0))
|
||||
future: Box::pin(upgrade.upgrade_outbound(connection, info.0)),
|
||||
};
|
||||
}
|
||||
OutboundUpgradeApplyState::Upgrade { mut future } => {
|
||||
match Future::poll(Pin::new(&mut future), cx) {
|
||||
Poll::Pending => {
|
||||
self.inner = OutboundUpgradeApplyState::Upgrade { future };
|
||||
return Poll::Pending
|
||||
return Poll::Pending;
|
||||
}
|
||||
Poll::Ready(Ok(x)) => {
|
||||
debug!("Successfully applied negotiated protocol");
|
||||
return Poll::Ready(Ok(x))
|
||||
return Poll::Ready(Ok(x));
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
debug!("Failed to apply negotiated protocol");
|
||||
@ -212,8 +235,9 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
OutboundUpgradeApplyState::Undefined =>
|
||||
OutboundUpgradeApplyState::Undefined => {
|
||||
panic!("OutboundUpgradeApplyState::poll called after completion")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,4 +254,3 @@ impl<N: ProtocolName> AsRef<[u8]> for NameWrap<N> {
|
||||
self.0.protocol_name()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,29 +19,32 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
either::{EitherOutput, EitherError, EitherFuture2, EitherName},
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}
|
||||
either::{EitherError, EitherFuture2, EitherName, EitherOutput},
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo},
|
||||
};
|
||||
|
||||
/// A type to represent two possible upgrade types (inbound or outbound).
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum EitherUpgrade<A, B> { A(A), B(B) }
|
||||
pub enum EitherUpgrade<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
|
||||
impl<A, B> UpgradeInfo for EitherUpgrade<A, B>
|
||||
where
|
||||
A: UpgradeInfo,
|
||||
B: UpgradeInfo
|
||||
B: UpgradeInfo,
|
||||
{
|
||||
type Info = EitherName<A::Info, B::Info>;
|
||||
type InfoIter = EitherIter<
|
||||
<A::InfoIter as IntoIterator>::IntoIter,
|
||||
<B::InfoIter as IntoIterator>::IntoIter
|
||||
<B::InfoIter as IntoIterator>::IntoIter,
|
||||
>;
|
||||
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
match self {
|
||||
EitherUpgrade::A(a) => EitherIter::A(a.protocol_info().into_iter()),
|
||||
EitherUpgrade::B(b) => EitherIter::B(b.protocol_info().into_iter())
|
||||
EitherUpgrade::B(b) => EitherIter::B(b.protocol_info().into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -57,9 +60,13 @@ where
|
||||
|
||||
fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
match (self, info) {
|
||||
(EitherUpgrade::A(a), EitherName::A(info)) => EitherFuture2::A(a.upgrade_inbound(sock, info)),
|
||||
(EitherUpgrade::B(b), EitherName::B(info)) => EitherFuture2::B(b.upgrade_inbound(sock, info)),
|
||||
_ => panic!("Invalid invocation of EitherUpgrade::upgrade_inbound")
|
||||
(EitherUpgrade::A(a), EitherName::A(info)) => {
|
||||
EitherFuture2::A(a.upgrade_inbound(sock, info))
|
||||
}
|
||||
(EitherUpgrade::B(b), EitherName::B(info)) => {
|
||||
EitherFuture2::B(b.upgrade_inbound(sock, info))
|
||||
}
|
||||
_ => panic!("Invalid invocation of EitherUpgrade::upgrade_inbound"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,36 +82,42 @@ where
|
||||
|
||||
fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
match (self, info) {
|
||||
(EitherUpgrade::A(a), EitherName::A(info)) => EitherFuture2::A(a.upgrade_outbound(sock, info)),
|
||||
(EitherUpgrade::B(b), EitherName::B(info)) => EitherFuture2::B(b.upgrade_outbound(sock, info)),
|
||||
_ => panic!("Invalid invocation of EitherUpgrade::upgrade_outbound")
|
||||
(EitherUpgrade::A(a), EitherName::A(info)) => {
|
||||
EitherFuture2::A(a.upgrade_outbound(sock, info))
|
||||
}
|
||||
(EitherUpgrade::B(b), EitherName::B(info)) => {
|
||||
EitherFuture2::B(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, B> { A(A), B(B) }
|
||||
pub enum EitherIter<A, B> {
|
||||
A(A),
|
||||
B(B),
|
||||
}
|
||||
|
||||
impl<A, B> Iterator for EitherIter<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator
|
||||
B: Iterator,
|
||||
{
|
||||
type Item = EitherName<A::Item, B::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self {
|
||||
EitherIter::A(a) => a.next().map(EitherName::A),
|
||||
EitherIter::B(b) => b.next().map(EitherName::B)
|
||||
EitherIter::B(b) => b.next().map(EitherName::B),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self {
|
||||
EitherIter::A(a) => a.size_hint(),
|
||||
EitherIter::B(b) => b.size_hint()
|
||||
EitherIter::B(b) => b.size_hint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ pub enum UpgradeError<E> {
|
||||
impl<E> UpgradeError<E> {
|
||||
pub fn map_err<F, T>(self, f: F) -> UpgradeError<T>
|
||||
where
|
||||
F: FnOnce(E) -> T
|
||||
F: FnOnce(E) -> T,
|
||||
{
|
||||
match self {
|
||||
UpgradeError::Select(e) => UpgradeError::Select(e),
|
||||
@ -43,7 +43,7 @@ impl<E> UpgradeError<E> {
|
||||
|
||||
pub fn into_err<T>(self) -> UpgradeError<T>
|
||||
where
|
||||
T: From<E>
|
||||
T: From<E>,
|
||||
{
|
||||
self.map_err(Into::into)
|
||||
}
|
||||
@ -51,7 +51,7 @@ impl<E> UpgradeError<E> {
|
||||
|
||||
impl<E> fmt::Display for UpgradeError<E>
|
||||
where
|
||||
E: fmt::Display
|
||||
E: fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
@ -63,7 +63,7 @@ where
|
||||
|
||||
impl<E> std::error::Error for UpgradeError<E>
|
||||
where
|
||||
E: std::error::Error + 'static
|
||||
E: std::error::Error + 'static,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
@ -78,4 +78,3 @@ impl<E> From<NegotiationError> for UpgradeError<E> {
|
||||
UpgradeError::Select(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,10 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{Endpoint, upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo}};
|
||||
use crate::{
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeInfo},
|
||||
Endpoint,
|
||||
};
|
||||
|
||||
use futures::prelude::*;
|
||||
use std::iter;
|
||||
|
@ -24,7 +24,10 @@ use std::{pin::Pin, task::Context, task::Poll};
|
||||
|
||||
/// Wraps around an upgrade and applies a closure to the output.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MapInboundUpgrade<U, F> { upgrade: U, fun: F }
|
||||
pub struct MapInboundUpgrade<U, F> {
|
||||
upgrade: U,
|
||||
fun: F,
|
||||
}
|
||||
|
||||
impl<U, F> MapInboundUpgrade<U, F> {
|
||||
pub fn new(upgrade: U, fun: F) -> Self {
|
||||
@ -34,7 +37,7 @@ impl<U, F> MapInboundUpgrade<U, F> {
|
||||
|
||||
impl<U, F> UpgradeInfo for MapInboundUpgrade<U, F>
|
||||
where
|
||||
U: UpgradeInfo
|
||||
U: UpgradeInfo,
|
||||
{
|
||||
type Info = U::Info;
|
||||
type InfoIter = U::InfoIter;
|
||||
@ -47,7 +50,7 @@ where
|
||||
impl<C, U, F, T> InboundUpgrade<C> for MapInboundUpgrade<U, F>
|
||||
where
|
||||
U: InboundUpgrade<C>,
|
||||
F: FnOnce(U::Output) -> T
|
||||
F: FnOnce(U::Output) -> T,
|
||||
{
|
||||
type Output = T;
|
||||
type Error = U::Error;
|
||||
@ -56,7 +59,7 @@ where
|
||||
fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
MapFuture {
|
||||
inner: self.upgrade.upgrade_inbound(sock, info),
|
||||
map: Some(self.fun)
|
||||
map: Some(self.fun),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -76,7 +79,10 @@ where
|
||||
|
||||
/// Wraps around an upgrade and applies a closure to the output.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MapOutboundUpgrade<U, F> { upgrade: U, fun: F }
|
||||
pub struct MapOutboundUpgrade<U, F> {
|
||||
upgrade: U,
|
||||
fun: F,
|
||||
}
|
||||
|
||||
impl<U, F> MapOutboundUpgrade<U, F> {
|
||||
pub fn new(upgrade: U, fun: F) -> Self {
|
||||
@ -86,7 +92,7 @@ impl<U, F> MapOutboundUpgrade<U, F> {
|
||||
|
||||
impl<U, F> UpgradeInfo for MapOutboundUpgrade<U, F>
|
||||
where
|
||||
U: UpgradeInfo
|
||||
U: UpgradeInfo,
|
||||
{
|
||||
type Info = U::Info;
|
||||
type InfoIter = U::InfoIter;
|
||||
@ -112,7 +118,7 @@ where
|
||||
impl<C, U, F, T> OutboundUpgrade<C> for MapOutboundUpgrade<U, F>
|
||||
where
|
||||
U: OutboundUpgrade<C>,
|
||||
F: FnOnce(U::Output) -> T
|
||||
F: FnOnce(U::Output) -> T,
|
||||
{
|
||||
type Output = T;
|
||||
type Error = U::Error;
|
||||
@ -121,14 +127,17 @@ where
|
||||
fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
MapFuture {
|
||||
inner: self.upgrade.upgrade_outbound(sock, info),
|
||||
map: Some(self.fun)
|
||||
map: Some(self.fun),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps around an upgrade and applies a closure to the error.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MapInboundUpgradeErr<U, F> { upgrade: U, fun: F }
|
||||
pub struct MapInboundUpgradeErr<U, F> {
|
||||
upgrade: U,
|
||||
fun: F,
|
||||
}
|
||||
|
||||
impl<U, F> MapInboundUpgradeErr<U, F> {
|
||||
pub fn new(upgrade: U, fun: F) -> Self {
|
||||
@ -138,7 +147,7 @@ impl<U, F> MapInboundUpgradeErr<U, F> {
|
||||
|
||||
impl<U, F> UpgradeInfo for MapInboundUpgradeErr<U, F>
|
||||
where
|
||||
U: UpgradeInfo
|
||||
U: UpgradeInfo,
|
||||
{
|
||||
type Info = U::Info;
|
||||
type InfoIter = U::InfoIter;
|
||||
@ -151,7 +160,7 @@ where
|
||||
impl<C, U, F, T> InboundUpgrade<C> for MapInboundUpgradeErr<U, F>
|
||||
where
|
||||
U: InboundUpgrade<C>,
|
||||
F: FnOnce(U::Error) -> T
|
||||
F: FnOnce(U::Error) -> T,
|
||||
{
|
||||
type Output = U::Output;
|
||||
type Error = T;
|
||||
@ -160,7 +169,7 @@ where
|
||||
fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
MapErrFuture {
|
||||
fut: self.upgrade.upgrade_inbound(sock, info),
|
||||
fun: Some(self.fun)
|
||||
fun: Some(self.fun),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -180,7 +189,10 @@ where
|
||||
|
||||
/// Wraps around an upgrade and applies a closure to the error.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MapOutboundUpgradeErr<U, F> { upgrade: U, fun: F }
|
||||
pub struct MapOutboundUpgradeErr<U, F> {
|
||||
upgrade: U,
|
||||
fun: F,
|
||||
}
|
||||
|
||||
impl<U, F> MapOutboundUpgradeErr<U, F> {
|
||||
pub fn new(upgrade: U, fun: F) -> Self {
|
||||
@ -190,7 +202,7 @@ impl<U, F> MapOutboundUpgradeErr<U, F> {
|
||||
|
||||
impl<U, F> UpgradeInfo for MapOutboundUpgradeErr<U, F>
|
||||
where
|
||||
U: UpgradeInfo
|
||||
U: UpgradeInfo,
|
||||
{
|
||||
type Info = U::Info;
|
||||
type InfoIter = U::InfoIter;
|
||||
@ -203,7 +215,7 @@ where
|
||||
impl<C, U, F, T> OutboundUpgrade<C> for MapOutboundUpgradeErr<U, F>
|
||||
where
|
||||
U: OutboundUpgrade<C>,
|
||||
F: FnOnce(U::Error) -> T
|
||||
F: FnOnce(U::Error) -> T,
|
||||
{
|
||||
type Output = U::Output;
|
||||
type Error = T;
|
||||
@ -212,14 +224,14 @@ where
|
||||
fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
MapErrFuture {
|
||||
fut: self.upgrade.upgrade_outbound(sock, info),
|
||||
fun: Some(self.fun)
|
||||
fun: Some(self.fun),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, U, F> InboundUpgrade<C> for MapOutboundUpgradeErr<U, F>
|
||||
where
|
||||
U: InboundUpgrade<C>
|
||||
U: InboundUpgrade<C>,
|
||||
{
|
||||
type Output = U::Output;
|
||||
type Error = U::Error;
|
||||
@ -283,4 +295,3 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,8 +112,4 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ExactSizeIterator for Iter<T>
|
||||
where
|
||||
T: ExactSizeIterator
|
||||
{
|
||||
}
|
||||
impl<T> ExactSizeIterator for Iter<T> where T: ExactSizeIterator {}
|
||||
|
@ -19,8 +19,8 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
either::{EitherOutput, EitherError, EitherFuture2, EitherName},
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}
|
||||
either::{EitherError, EitherFuture2, EitherName, EitherOutput},
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo},
|
||||
};
|
||||
|
||||
/// Upgrade that combines two upgrades into one. Supports all the protocols supported by either
|
||||
@ -42,16 +42,19 @@ impl<A, B> SelectUpgrade<A, B> {
|
||||
impl<A, B> UpgradeInfo for SelectUpgrade<A, B>
|
||||
where
|
||||
A: UpgradeInfo,
|
||||
B: UpgradeInfo
|
||||
B: UpgradeInfo,
|
||||
{
|
||||
type Info = EitherName<A::Info, B::Info>;
|
||||
type InfoIter = InfoIterChain<
|
||||
<A::InfoIter as IntoIterator>::IntoIter,
|
||||
<B::InfoIter as IntoIterator>::IntoIter
|
||||
<B::InfoIter as IntoIterator>::IntoIter,
|
||||
>;
|
||||
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
InfoIterChain(self.0.protocol_info().into_iter(), self.1.protocol_info().into_iter())
|
||||
InfoIterChain(
|
||||
self.0.protocol_info().into_iter(),
|
||||
self.1.protocol_info().into_iter(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +70,7 @@ where
|
||||
fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
match info {
|
||||
EitherName::A(info) => EitherFuture2::A(self.0.upgrade_inbound(sock, info)),
|
||||
EitherName::B(info) => EitherFuture2::B(self.1.upgrade_inbound(sock, info))
|
||||
EitherName::B(info) => EitherFuture2::B(self.1.upgrade_inbound(sock, info)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +87,7 @@ where
|
||||
fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
match info {
|
||||
EitherName::A(info) => EitherFuture2::A(self.0.upgrade_outbound(sock, info)),
|
||||
EitherName::B(info) => EitherFuture2::B(self.1.upgrade_outbound(sock, info))
|
||||
EitherName::B(info) => EitherFuture2::B(self.1.upgrade_outbound(sock, info)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,16 +99,16 @@ pub struct InfoIterChain<A, B>(A, B);
|
||||
impl<A, B> Iterator for InfoIterChain<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator
|
||||
B: Iterator,
|
||||
{
|
||||
type Item = EitherName<A::Item, B::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(info) = self.0.next() {
|
||||
return Some(EitherName::A(info))
|
||||
return Some(EitherName::A(info));
|
||||
}
|
||||
if let Some(info) = self.1.next() {
|
||||
return Some(EitherName::B(info))
|
||||
return Some(EitherName::B(info));
|
||||
}
|
||||
None
|
||||
}
|
||||
@ -117,4 +120,3 @@ where
|
||||
(min1.saturating_add(min2), max)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,10 @@ use std::{error, fmt, io};
|
||||
///
|
||||
/// > **Note**: Prepends a variable-length prefix indicate the length of the message. This is
|
||||
/// > compatible with what [`read_length_prefixed`] expects.
|
||||
pub async fn write_length_prefixed(socket: &mut (impl AsyncWrite + Unpin), data: impl AsRef<[u8]>)
|
||||
-> Result<(), io::Error>
|
||||
{
|
||||
pub async fn write_length_prefixed(
|
||||
socket: &mut (impl AsyncWrite + Unpin),
|
||||
data: impl AsRef<[u8]>,
|
||||
) -> Result<(), io::Error> {
|
||||
write_varint(socket, data.as_ref().len()).await?;
|
||||
socket.write_all(data.as_ref()).await?;
|
||||
socket.flush().await?;
|
||||
@ -44,11 +45,15 @@ pub async fn write_length_prefixed(socket: &mut (impl AsyncWrite + Unpin), data:
|
||||
/// > **Note**: Prepends a variable-length prefix indicate the length of the message. This is
|
||||
/// > compatible with what `read_one` expects.
|
||||
///
|
||||
#[deprecated(since = "0.29.0", note = "Use `write_length_prefixed` instead. You will need to manually close the stream using `socket.close().await`.")]
|
||||
#[deprecated(
|
||||
since = "0.29.0",
|
||||
note = "Use `write_length_prefixed` instead. You will need to manually close the stream using `socket.close().await`."
|
||||
)]
|
||||
#[allow(dead_code)]
|
||||
pub async fn write_one(socket: &mut (impl AsyncWrite + Unpin), data: impl AsRef<[u8]>)
|
||||
-> Result<(), io::Error>
|
||||
{
|
||||
pub async fn write_one(
|
||||
socket: &mut (impl AsyncWrite + Unpin),
|
||||
data: impl AsRef<[u8]>,
|
||||
) -> Result<(), io::Error> {
|
||||
write_varint(socket, data.as_ref().len()).await?;
|
||||
socket.write_all(data.as_ref()).await?;
|
||||
socket.close().await?;
|
||||
@ -61,9 +66,10 @@ pub async fn write_one(socket: &mut (impl AsyncWrite + Unpin), data: impl AsRef<
|
||||
/// > compatible with what `read_one` expects.
|
||||
#[deprecated(since = "0.29.0", note = "Use `write_length_prefixed` instead.")]
|
||||
#[allow(dead_code)]
|
||||
pub async fn write_with_len_prefix(socket: &mut (impl AsyncWrite + Unpin), data: impl AsRef<[u8]>)
|
||||
-> Result<(), io::Error>
|
||||
{
|
||||
pub async fn write_with_len_prefix(
|
||||
socket: &mut (impl AsyncWrite + Unpin),
|
||||
data: impl AsRef<[u8]>,
|
||||
) -> Result<(), io::Error> {
|
||||
write_varint(socket, data.as_ref().len()).await?;
|
||||
socket.write_all(data.as_ref()).await?;
|
||||
socket.flush().await?;
|
||||
@ -73,9 +79,10 @@ pub async fn write_with_len_prefix(socket: &mut (impl AsyncWrite + Unpin), data:
|
||||
/// Writes a variable-length integer to the `socket`.
|
||||
///
|
||||
/// > **Note**: Does **NOT** flush the socket.
|
||||
pub async fn write_varint(socket: &mut (impl AsyncWrite + Unpin), len: usize)
|
||||
-> Result<(), io::Error>
|
||||
{
|
||||
pub async fn write_varint(
|
||||
socket: &mut (impl AsyncWrite + Unpin),
|
||||
len: usize,
|
||||
) -> Result<(), io::Error> {
|
||||
let mut len_data = unsigned_varint::encode::usize_buffer();
|
||||
let encoded_len = unsigned_varint::encode::usize(len, &mut len_data).len();
|
||||
socket.write_all(&len_data[..encoded_len]).await?;
|
||||
@ -95,7 +102,7 @@ pub async fn read_varint(socket: &mut (impl AsyncRead + Unpin)) -> Result<usize,
|
||||
let mut buffer_len = 0;
|
||||
|
||||
loop {
|
||||
match socket.read(&mut buffer[buffer_len..buffer_len+1]).await? {
|
||||
match socket.read(&mut buffer[buffer_len..buffer_len + 1]).await? {
|
||||
0 => {
|
||||
// Reaching EOF before finishing to read the length is an error, unless the EOF is
|
||||
// at the very beginning of the substream, in which case we assume that the data is
|
||||
@ -116,7 +123,7 @@ pub async fn read_varint(socket: &mut (impl AsyncRead + Unpin)) -> Result<usize,
|
||||
Err(unsigned_varint::decode::Error::Overflow) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"overflow in variable-length integer"
|
||||
"overflow in variable-length integer",
|
||||
));
|
||||
}
|
||||
// TODO: why do we have a `__Nonexhaustive` variant in the error? I don't know how to process it
|
||||
@ -134,11 +141,19 @@ pub async fn read_varint(socket: &mut (impl AsyncRead + Unpin)) -> Result<usize,
|
||||
///
|
||||
/// > **Note**: Assumes that a variable-length prefix indicates the length of the message. This is
|
||||
/// > compatible with what [`write_length_prefixed`] does.
|
||||
pub async fn read_length_prefixed(socket: &mut (impl AsyncRead + Unpin), max_size: usize) -> io::Result<Vec<u8>>
|
||||
{
|
||||
pub async fn read_length_prefixed(
|
||||
socket: &mut (impl AsyncRead + Unpin),
|
||||
max_size: usize,
|
||||
) -> io::Result<Vec<u8>> {
|
||||
let len = read_varint(socket).await?;
|
||||
if len > max_size {
|
||||
return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Received data size ({} bytes) exceeds maximum ({} bytes)", len, max_size)))
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"Received data size ({} bytes) exceeds maximum ({} bytes)",
|
||||
len, max_size
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
let mut buf = vec![0; len];
|
||||
@ -157,9 +172,10 @@ pub async fn read_length_prefixed(socket: &mut (impl AsyncRead + Unpin), max_siz
|
||||
/// > compatible with what `write_one` does.
|
||||
#[deprecated(since = "0.29.0", note = "Use `read_length_prefixed` instead.")]
|
||||
#[allow(dead_code, deprecated)]
|
||||
pub async fn read_one(socket: &mut (impl AsyncRead + Unpin), max_size: usize)
|
||||
-> Result<Vec<u8>, ReadOneError>
|
||||
{
|
||||
pub async fn read_one(
|
||||
socket: &mut (impl AsyncRead + Unpin),
|
||||
max_size: usize,
|
||||
) -> Result<Vec<u8>, ReadOneError> {
|
||||
let len = read_varint(socket).await?;
|
||||
if len > max_size {
|
||||
return Err(ReadOneError::TooLarge {
|
||||
@ -175,7 +191,10 @@ pub async fn read_one(socket: &mut (impl AsyncRead + Unpin), max_size: usize)
|
||||
|
||||
/// Error while reading one message.
|
||||
#[derive(Debug)]
|
||||
#[deprecated(since = "0.29.0", note = "Use `read_length_prefixed` instead of `read_one` to avoid depending on this type.")]
|
||||
#[deprecated(
|
||||
since = "0.29.0",
|
||||
note = "Use `read_length_prefixed` instead of `read_one` to avoid depending on this type."
|
||||
)]
|
||||
pub enum ReadOneError {
|
||||
/// Error on the socket.
|
||||
Io(std::io::Error),
|
||||
@ -239,7 +258,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// TODO: rewrite these tests
|
||||
/*
|
||||
/*
|
||||
#[test]
|
||||
fn read_one_works() {
|
||||
let original_data = (0..rand::random::<usize>() % 10_000)
|
||||
|
Reference in New Issue
Block a user