mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-19 21:11:22 +00:00
Have Transport::Listener
s produce ListenerEvent
s. (#1032)
Replace the listener and address pair returned from `Transport::listen_on` with just a listener that produces `ListenerEvent` values which include upgrades as well as address changes.
This commit is contained in:
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{muxing::StreamMuxer, Multiaddr, ProtocolName};
|
use crate::{muxing::StreamMuxer, ProtocolName, transport::ListenerEvent};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use std::{fmt, io::{Error as IoError, Read, Write}};
|
use std::{fmt, io::{Error as IoError, Read, Write}};
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
@ -282,20 +282,20 @@ pub enum EitherListenStream<A, B> {
|
|||||||
|
|
||||||
impl<AStream, BStream, AInner, BInner> Stream for EitherListenStream<AStream, BStream>
|
impl<AStream, BStream, AInner, BInner> Stream for EitherListenStream<AStream, BStream>
|
||||||
where
|
where
|
||||||
AStream: Stream<Item = (AInner, Multiaddr)>,
|
AStream: Stream<Item = ListenerEvent<AInner>>,
|
||||||
BStream: Stream<Item = (BInner, Multiaddr)>,
|
BStream: Stream<Item = ListenerEvent<BInner>>,
|
||||||
{
|
{
|
||||||
type Item = (EitherFuture<AInner, BInner>, Multiaddr);
|
type Item = ListenerEvent<EitherFuture<AInner, BInner>>;
|
||||||
type Error = EitherError<AStream::Error, BStream::Error>;
|
type Error = EitherError<AStream::Error, BStream::Error>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
match self {
|
match self {
|
||||||
EitherListenStream::First(a) => a.poll()
|
EitherListenStream::First(a) => a.poll()
|
||||||
.map(|i| (i.map(|v| (v.map(|(o, addr)| (EitherFuture::First(o), addr))))))
|
.map(|i| (i.map(|v| (v.map(|e| e.map(EitherFuture::First))))))
|
||||||
.map_err(EitherError::A),
|
.map_err(EitherError::A),
|
||||||
EitherListenStream::Second(a) => a.poll()
|
EitherListenStream::Second(a) => a.poll()
|
||||||
.map(|i| (i.map(|v| (v.map(|(o, addr)| (EitherFuture::Second(o), addr))))))
|
.map(|i| (i.map(|v| (v.map(|e| e.map(EitherFuture::Second))))))
|
||||||
.map_err(EitherError::B),
|
.map_err(EitherError::B),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,3 +106,23 @@ impl std::ops::Not for Endpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Endpoint {
|
||||||
|
/// Is this endpoint a dialer?
|
||||||
|
pub fn is_dialer(self) -> bool {
|
||||||
|
if let Endpoint::Dialer = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is this endpoint a listener?
|
||||||
|
pub fn is_listener(self) -> bool {
|
||||||
|
if let Endpoint::Listener = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
|
|
||||||
//! Manage listening on multiple multiaddresses at once.
|
//! Manage listening on multiple multiaddresses at once.
|
||||||
|
|
||||||
use crate::{Multiaddr, Transport, transport::TransportError};
|
use crate::{Multiaddr, Transport, transport::{TransportError, ListenerEvent}};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::{collections::VecDeque, fmt};
|
use std::{collections::VecDeque, fmt};
|
||||||
use void::Void;
|
use void::Void;
|
||||||
|
|
||||||
@ -49,14 +50,17 @@ use void::Void;
|
|||||||
/// // Ask the `listeners` to start listening on the given multiaddress.
|
/// // Ask the `listeners` to start listening on the given multiaddress.
|
||||||
/// listeners.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap()).unwrap();
|
/// listeners.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap()).unwrap();
|
||||||
///
|
///
|
||||||
/// // You can retrieve the list of active listeners with `listeners()`.
|
|
||||||
/// println!("Listening on: {:?}", listeners.listeners().collect::<Vec<_>>());
|
|
||||||
///
|
|
||||||
/// // The `listeners` will now generate events when polled.
|
/// // The `listeners` will now generate events when polled.
|
||||||
/// let future = listeners.for_each(move |event| {
|
/// let future = listeners.for_each(move |event| {
|
||||||
/// match event {
|
/// match event {
|
||||||
/// ListenersEvent::Closed { listen_addr, listener, result } => {
|
/// ListenersEvent::NewAddress { listen_addr } => {
|
||||||
/// println!("Listener {} has been closed: {:?}", listen_addr, result);
|
/// println!("Listener is listening at address {}", listen_addr);
|
||||||
|
/// },
|
||||||
|
/// ListenersEvent::AddressExpired { listen_addr } => {
|
||||||
|
/// println!("Listener is no longer listening at address {}", listen_addr);
|
||||||
|
/// },
|
||||||
|
/// ListenersEvent::Closed { result, .. } => {
|
||||||
|
/// println!("Listener has been closed: {:?}", result);
|
||||||
/// },
|
/// },
|
||||||
/// ListenersEvent::Incoming { upgrade, listen_addr, .. } => {
|
/// ListenersEvent::Incoming { upgrade, listen_addr, .. } => {
|
||||||
/// println!("A connection has arrived on {}", listen_addr);
|
/// println!("A connection has arrived on {}", listen_addr);
|
||||||
@ -79,7 +83,7 @@ where
|
|||||||
/// Transport used to spawn listeners.
|
/// Transport used to spawn listeners.
|
||||||
transport: TTrans,
|
transport: TTrans,
|
||||||
/// All the active listeners.
|
/// All the active listeners.
|
||||||
listeners: VecDeque<Listener<TTrans>>,
|
listeners: VecDeque<Listener<TTrans>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single active listener.
|
/// A single active listener.
|
||||||
@ -90,8 +94,8 @@ where
|
|||||||
{
|
{
|
||||||
/// The object that actually listens.
|
/// The object that actually listens.
|
||||||
listener: TTrans::Listener,
|
listener: TTrans::Listener,
|
||||||
/// Address it is listening on.
|
/// Addresses it is listening on.
|
||||||
address: Multiaddr,
|
addresses: SmallVec<[Multiaddr; 4]>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Event that can happen on the `ListenersStream`.
|
/// Event that can happen on the `ListenersStream`.
|
||||||
@ -99,6 +103,16 @@ pub enum ListenersEvent<TTrans>
|
|||||||
where
|
where
|
||||||
TTrans: Transport,
|
TTrans: Transport,
|
||||||
{
|
{
|
||||||
|
/// A new address is being listened on.
|
||||||
|
NewAddress {
|
||||||
|
/// The new address that is being listened on.
|
||||||
|
listen_addr: Multiaddr
|
||||||
|
},
|
||||||
|
/// An address is no longer being listened on.
|
||||||
|
AddressExpired {
|
||||||
|
/// The new address that is being listened on.
|
||||||
|
listen_addr: Multiaddr
|
||||||
|
},
|
||||||
/// A connection is incoming on one of the listeners.
|
/// A connection is incoming on one of the listeners.
|
||||||
Incoming {
|
Incoming {
|
||||||
/// The produced upgrade.
|
/// The produced upgrade.
|
||||||
@ -108,11 +122,8 @@ where
|
|||||||
/// Address used to send back data to the incoming client.
|
/// Address used to send back data to the incoming client.
|
||||||
send_back_addr: Multiaddr,
|
send_back_addr: Multiaddr,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A listener has closed, either gracefully or with an error.
|
/// A listener has closed, either gracefully or with an error.
|
||||||
Closed {
|
Closed {
|
||||||
/// Address of the listener which closed.
|
|
||||||
listen_addr: Multiaddr,
|
|
||||||
/// The listener that closed.
|
/// The listener that closed.
|
||||||
listener: TTrans::Listener,
|
listener: TTrans::Listener,
|
||||||
/// The error that happened. `Ok` if gracefully closed.
|
/// The error that happened. `Ok` if gracefully closed.
|
||||||
@ -129,7 +140,7 @@ where
|
|||||||
pub fn new(transport: TTrans) -> Self {
|
pub fn new(transport: TTrans) -> Self {
|
||||||
ListenersStream {
|
ListenersStream {
|
||||||
transport,
|
transport,
|
||||||
listeners: VecDeque::new(),
|
listeners: VecDeque::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,40 +150,30 @@ where
|
|||||||
pub fn with_capacity(transport: TTrans, capacity: usize) -> Self {
|
pub fn with_capacity(transport: TTrans, capacity: usize) -> Self {
|
||||||
ListenersStream {
|
ListenersStream {
|
||||||
transport,
|
transport,
|
||||||
listeners: VecDeque::with_capacity(capacity),
|
listeners: VecDeque::with_capacity(capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start listening on a multiaddress.
|
/// Start listening on a multiaddress.
|
||||||
///
|
///
|
||||||
/// Returns an error if the transport doesn't support the given multiaddress.
|
/// Returns an error if the transport doesn't support the given multiaddress.
|
||||||
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<Multiaddr, TransportError<TTrans::Error>>
|
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<(), TransportError<TTrans::Error>>
|
||||||
where
|
where
|
||||||
TTrans: Clone,
|
TTrans: Clone,
|
||||||
{
|
{
|
||||||
let (listener, new_addr) = self
|
let listener = self.transport.clone().listen_on(addr)?;
|
||||||
.transport
|
self.listeners.push_back(Listener { listener, addresses: SmallVec::new() });
|
||||||
.clone()
|
Ok(())
|
||||||
.listen_on(addr)?;
|
|
||||||
|
|
||||||
self.listeners.push_back(Listener {
|
|
||||||
listener,
|
|
||||||
address: new_addr.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(new_addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the transport passed when building this object.
|
/// Returns the transport passed when building this object.
|
||||||
#[inline]
|
|
||||||
pub fn transport(&self) -> &TTrans {
|
pub fn transport(&self) -> &TTrans {
|
||||||
&self.transport
|
&self.transport
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator that produces the list of addresses we're listening on.
|
/// Returns an iterator that produces the list of addresses we're listening on.
|
||||||
#[inline]
|
pub fn listen_addrs(&self) -> impl Iterator<Item = &Multiaddr> {
|
||||||
pub fn listeners(&self) -> impl Iterator<Item = &Multiaddr> {
|
self.listeners.iter().flat_map(|l| l.addresses.iter())
|
||||||
self.listeners.iter().map(|l| &l.address)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides an API similar to `Stream`, except that it cannot error.
|
/// Provides an API similar to `Stream`, except that it cannot error.
|
||||||
@ -186,28 +187,38 @@ where
|
|||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
if remaining == 0 { break }
|
if remaining == 0 { break }
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(Some((upgrade, send_back_addr)))) => {
|
Ok(Async::Ready(Some(ListenerEvent::Upgrade { upgrade, listen_addr, remote_addr }))) => {
|
||||||
let listen_addr = listener.address.clone();
|
debug_assert!(listener.addresses.contains(&listen_addr));
|
||||||
self.listeners.push_front(listener);
|
self.listeners.push_front(listener);
|
||||||
return Async::Ready(ListenersEvent::Incoming {
|
return Async::Ready(ListenersEvent::Incoming {
|
||||||
upgrade,
|
upgrade,
|
||||||
listen_addr,
|
listen_addr,
|
||||||
send_back_addr,
|
send_back_addr: remote_addr
|
||||||
});
|
})
|
||||||
|
}
|
||||||
|
Ok(Async::Ready(Some(ListenerEvent::NewAddress(a)))) => {
|
||||||
|
if !listener.addresses.contains(&a) {
|
||||||
|
listener.addresses.push(a.clone());
|
||||||
|
}
|
||||||
|
self.listeners.push_front(listener);
|
||||||
|
return Async::Ready(ListenersEvent::NewAddress { listen_addr: a })
|
||||||
|
}
|
||||||
|
Ok(Async::Ready(Some(ListenerEvent::AddressExpired(a)))) => {
|
||||||
|
listener.addresses.retain(|x| x != &a);
|
||||||
|
self.listeners.push_front(listener);
|
||||||
|
return Async::Ready(ListenersEvent::AddressExpired { listen_addr: a })
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(None)) => {
|
Ok(Async::Ready(None)) => {
|
||||||
return Async::Ready(ListenersEvent::Closed {
|
return Async::Ready(ListenersEvent::Closed {
|
||||||
listen_addr: listener.address,
|
|
||||||
listener: listener.listener,
|
listener: listener.listener,
|
||||||
result: Ok(()),
|
result: Ok(()),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Async::Ready(ListenersEvent::Closed {
|
return Async::Ready(ListenersEvent::Closed {
|
||||||
listen_addr: listener.address,
|
|
||||||
listener: listener.listener,
|
listener: listener.listener,
|
||||||
result: Err(err),
|
result: Err(err),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,7 +248,7 @@ where
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
f.debug_struct("ListenersStream")
|
f.debug_struct("ListenersStream")
|
||||||
.field("transport", &self.transport)
|
.field("transport", &self.transport)
|
||||||
.field("listeners", &self.listeners().collect::<Vec<_>>())
|
.field("listen_addrs", &self.listen_addrs().collect::<Vec<_>>())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,19 +260,20 @@ where
|
|||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match self {
|
match self {
|
||||||
ListenersEvent::Incoming {
|
ListenersEvent::NewAddress { listen_addr } => f
|
||||||
ref listen_addr, ..
|
.debug_struct("ListenersEvent::NewAddress")
|
||||||
} => f
|
.field("listen_addr", listen_addr)
|
||||||
|
.finish(),
|
||||||
|
ListenersEvent::AddressExpired { listen_addr } => f
|
||||||
|
.debug_struct("ListenersEvent::AddressExpired")
|
||||||
|
.field("listen_addr", listen_addr)
|
||||||
|
.finish(),
|
||||||
|
ListenersEvent::Incoming { listen_addr, .. } => f
|
||||||
.debug_struct("ListenersEvent::Incoming")
|
.debug_struct("ListenersEvent::Incoming")
|
||||||
.field("listen_addr", listen_addr)
|
.field("listen_addr", listen_addr)
|
||||||
.finish(),
|
.finish(),
|
||||||
ListenersEvent::Closed {
|
ListenersEvent::Closed { result, .. } => f
|
||||||
ref listen_addr,
|
|
||||||
ref result,
|
|
||||||
..
|
|
||||||
} => f
|
|
||||||
.debug_struct("ListenersEvent::Closed")
|
.debug_struct("ListenersEvent::Closed")
|
||||||
.field("listen_addr", listen_addr)
|
|
||||||
.field("result", result)
|
.field("result", result)
|
||||||
.finish(),
|
.finish(),
|
||||||
}
|
}
|
||||||
@ -271,42 +283,29 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::transport;
|
use crate::transport::{self, ListenerEvent};
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use tokio::runtime::current_thread::Runtime;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
use std::io;
|
use std::{io, iter::FromIterator};
|
||||||
use futures::{future::{self}, stream};
|
use futures::{future::{self}, stream};
|
||||||
use crate::tests::dummy_transport::{DummyTransport, ListenerState};
|
use crate::tests::dummy_transport::{DummyTransport, ListenerState};
|
||||||
use crate::tests::dummy_muxer::DummyMuxer;
|
use crate::tests::dummy_muxer::DummyMuxer;
|
||||||
use crate::PeerId;
|
use crate::PeerId;
|
||||||
|
|
||||||
fn set_listener_state(ls: &mut ListenersStream<DummyTransport>, idx: usize, state: ListenerState) {
|
fn set_listener_state(ls: &mut ListenersStream<DummyTransport>, idx: usize, state: ListenerState) {
|
||||||
let l = &mut ls.listeners[idx];
|
ls.listeners[idx].listener = match state {
|
||||||
l.listener =
|
ListenerState::Error =>
|
||||||
match state {
|
Box::new(stream::poll_fn(|| Err(io::Error::new(io::ErrorKind::Other, "oh noes")))),
|
||||||
ListenerState::Error => {
|
ListenerState::Ok(state) => match state {
|
||||||
let stream = stream::poll_fn(|| future::err(io::Error::new(io::ErrorKind::Other, "oh noes")).poll() );
|
Async::NotReady => Box::new(stream::poll_fn(|| Ok(Async::NotReady))),
|
||||||
Box::new(stream)
|
Async::Ready(Some(event)) => Box::new(stream::poll_fn(move || {
|
||||||
}
|
Ok(Async::Ready(Some(event.clone().map(future::ok))))
|
||||||
ListenerState::Ok(r#async) => {
|
})),
|
||||||
match r#async {
|
Async::Ready(None) => Box::new(stream::empty())
|
||||||
Async::NotReady => {
|
}
|
||||||
let stream = stream::poll_fn(|| Ok(Async::NotReady));
|
ListenerState::Events(events) =>
|
||||||
Box::new(stream)
|
Box::new(stream::iter_ok(events.into_iter().map(|e| e.map(future::ok))))
|
||||||
}
|
};
|
||||||
Async::Ready(Some(tup)) => {
|
|
||||||
let addr = l.address.clone();
|
|
||||||
let stream = stream::poll_fn(move || Ok( Async::Ready(Some(tup.clone())) ))
|
|
||||||
.map(move |stream| (future::ok(stream), addr.clone()));
|
|
||||||
Box::new(stream)
|
|
||||||
}
|
|
||||||
Async::Ready(None) => {
|
|
||||||
let stream = stream::empty();
|
|
||||||
Box::new(stream)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -314,18 +313,27 @@ mod tests {
|
|||||||
let mem_transport = transport::MemoryTransport::default();
|
let mem_transport = transport::MemoryTransport::default();
|
||||||
|
|
||||||
let mut listeners = ListenersStream::new(mem_transport);
|
let mut listeners = ListenersStream::new(mem_transport);
|
||||||
let actual_addr = listeners.listen_on("/memory/0".parse().unwrap()).unwrap();
|
listeners.listen_on("/memory/0".parse().unwrap()).unwrap();
|
||||||
|
|
||||||
let dial = mem_transport.dial(actual_addr.clone()).unwrap();
|
let address = {
|
||||||
|
let event = listeners.by_ref().wait().next().expect("some event").expect("no error");
|
||||||
|
if let ListenersEvent::NewAddress { listen_addr, .. } = event {
|
||||||
|
listen_addr
|
||||||
|
} else {
|
||||||
|
panic!("Was expecting the listen address to be reported")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let dial = mem_transport.dial(address.clone()).unwrap();
|
||||||
|
|
||||||
let future = listeners
|
let future = listeners
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(err, _)| err)
|
.map_err(|(err, _)| err)
|
||||||
.and_then(|(event, _)| {
|
.and_then(|(event, _)| {
|
||||||
match event {
|
match event {
|
||||||
Some(ListenersEvent::Incoming { listen_addr, upgrade, send_back_addr }) => {
|
Some(ListenersEvent::Incoming { listen_addr, upgrade, send_back_addr, .. }) => {
|
||||||
assert_eq!(listen_addr, actual_addr);
|
assert_eq!(listen_addr, address);
|
||||||
assert_eq!(send_back_addr, actual_addr);
|
assert_eq!(send_back_addr, address);
|
||||||
upgrade.map(|_| ()).map_err(|_| panic!())
|
upgrade.map(|_| ()).map_err(|_| panic!())
|
||||||
},
|
},
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
@ -348,17 +356,24 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn listener_stream_can_iterate_over_listeners() {
|
fn listener_stream_can_iterate_over_listeners() {
|
||||||
let t = DummyTransport::new();
|
let mut t = DummyTransport::new();
|
||||||
let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
let addr1 = tcp4([127, 0, 0, 1], 1234);
|
||||||
let addr2 = "/ip4/127.0.0.1/tcp/4321".parse::<Multiaddr>().expect("bad multiaddr");
|
let addr2 = tcp4([127, 0, 0, 1], 4321);
|
||||||
let expected_addrs = vec![addr1.to_string(), addr2.to_string()];
|
|
||||||
|
t.set_initial_listener_state(ListenerState::Events(vec![
|
||||||
|
ListenerEvent::NewAddress(addr1.clone()),
|
||||||
|
ListenerEvent::NewAddress(addr2.clone())
|
||||||
|
]));
|
||||||
|
|
||||||
let mut ls = ListenersStream::new(t);
|
let mut ls = ListenersStream::new(t);
|
||||||
ls.listen_on(addr1).expect("listen_on failed");
|
ls.listen_on(tcp4([0, 0, 0, 0], 0)).expect("listen_on");
|
||||||
ls.listen_on(addr2).expect("listen_on failed");
|
|
||||||
|
|
||||||
let listener_addrs = ls.listeners().map(|ma| ma.to_string() ).collect::<Vec<String>>();
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(ListenersEvent::NewAddress { listen_addr, .. })) => {
|
||||||
assert_eq!(listener_addrs, expected_addrs);
|
assert_eq!(addr1, listen_addr)
|
||||||
|
});
|
||||||
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(ListenersEvent::NewAddress { listen_addr, .. })) => {
|
||||||
|
assert_eq!(addr2, listen_addr)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -371,7 +386,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn listener_stream_poll_with_listeners_that_arent_ready_is_not_ready() {
|
fn listener_stream_poll_with_listeners_that_arent_ready_is_not_ready() {
|
||||||
let t = DummyTransport::new();
|
let t = DummyTransport::new();
|
||||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
let addr = tcp4([127, 0, 0, 1], 1234);
|
||||||
let mut ls = ListenersStream::new(t);
|
let mut ls = ListenersStream::new(t);
|
||||||
ls.listen_on(addr).expect("listen_on failed");
|
ls.listen_on(addr).expect("listen_on failed");
|
||||||
set_listener_state(&mut ls, 0, ListenerState::Ok(Async::NotReady));
|
set_listener_state(&mut ls, 0, ListenerState::Ok(Async::NotReady));
|
||||||
@ -385,54 +400,74 @@ mod tests {
|
|||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
let muxer = DummyMuxer::new();
|
let muxer = DummyMuxer::new();
|
||||||
let expected_output = (peer_id.clone(), muxer.clone());
|
let expected_output = (peer_id.clone(), muxer.clone());
|
||||||
t.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some( (peer_id, muxer) ))));
|
|
||||||
|
t.set_initial_listener_state(ListenerState::Events(vec![
|
||||||
|
ListenerEvent::NewAddress(tcp4([127, 0, 0, 1], 9090)),
|
||||||
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: (peer_id.clone(), muxer.clone()),
|
||||||
|
listen_addr: tcp4([127, 0, 0, 1], 9090),
|
||||||
|
remote_addr: tcp4([127, 0, 0, 1], 32000)
|
||||||
|
},
|
||||||
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: (peer_id.clone(), muxer.clone()),
|
||||||
|
listen_addr: tcp4([127, 0, 0, 1], 9090),
|
||||||
|
remote_addr: tcp4([127, 0, 0, 1], 32000)
|
||||||
|
},
|
||||||
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: (peer_id.clone(), muxer.clone()),
|
||||||
|
listen_addr: tcp4([127, 0, 0, 1], 9090),
|
||||||
|
remote_addr: tcp4([127, 0, 0, 1], 32000)
|
||||||
|
}
|
||||||
|
]));
|
||||||
|
|
||||||
let mut ls = ListenersStream::new(t);
|
let mut ls = ListenersStream::new(t);
|
||||||
|
ls.listen_on(tcp4([127, 0, 0, 1], 1234)).expect("listen_on");
|
||||||
let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
ls.listen_on(tcp4([127, 0, 0, 1], 4321)).expect("listen_on");
|
||||||
let addr2 = "/ip4/127.0.0.2/tcp/4321".parse::<Multiaddr>().expect("bad multiaddr");
|
|
||||||
|
|
||||||
ls.listen_on(addr1).expect("listen_on works");
|
|
||||||
ls.listen_on(addr2).expect("listen_on works");
|
|
||||||
assert_eq!(ls.listeners.len(), 2);
|
assert_eq!(ls.listeners.len(), 2);
|
||||||
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(listeners_event) => {
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
assert_matches!(listeners_event, ListenersEvent::Incoming{mut upgrade, listen_addr, ..} => {
|
assert_matches!(listeners_event, ListenersEvent::NewAddress { .. })
|
||||||
assert_eq!(listen_addr.to_string(), "/ip4/127.0.0.2/tcp/4321");
|
});
|
||||||
assert_matches!(upgrade.poll().unwrap(), Async::Ready(tup) => {
|
|
||||||
assert_eq!(tup, expected_output)
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
|
assert_matches!(listeners_event, ListenersEvent::NewAddress { .. })
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
|
assert_matches!(listeners_event, ListenersEvent::Incoming { upgrade, .. } => {
|
||||||
|
assert_matches!(upgrade.wait(), Ok(output) => {
|
||||||
|
assert_eq!(output, expected_output)
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(listeners_event) => {
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
assert_matches!(listeners_event, ListenersEvent::Incoming{mut upgrade, listen_addr, ..} => {
|
assert_matches!(listeners_event, ListenersEvent::Incoming { upgrade, .. } => {
|
||||||
assert_eq!(listen_addr.to_string(), "/ip4/127.0.0.1/tcp/1234");
|
assert_matches!(upgrade.wait(), Ok(output) => {
|
||||||
assert_matches!(upgrade.poll().unwrap(), Async::Ready(tup) => {
|
assert_eq!(output, expected_output)
|
||||||
assert_eq!(tup, expected_output)
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
set_listener_state(&mut ls, 1, ListenerState::Ok(Async::NotReady));
|
set_listener_state(&mut ls, 1, ListenerState::Ok(Async::NotReady));
|
||||||
assert_matches!(ls.poll(), Async::Ready(listeners_event) => {
|
|
||||||
assert_matches!(listeners_event, ListenersEvent::Incoming{mut upgrade, listen_addr, ..} => {
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
assert_eq!(listen_addr.to_string(), "/ip4/127.0.0.1/tcp/1234");
|
assert_matches!(listeners_event, ListenersEvent::Incoming { upgrade, .. } => {
|
||||||
assert_matches!(upgrade.poll().unwrap(), Async::Ready(tup) => {
|
assert_matches!(upgrade.wait(), Ok(output) => {
|
||||||
assert_eq!(tup, expected_output)
|
assert_eq!(output, expected_output)
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn listener_stream_poll_with_closed_listener_emits_closed_event() {
|
fn listener_stream_poll_with_closed_listener_emits_closed_event() {
|
||||||
let t = DummyTransport::new();
|
let t = DummyTransport::new();
|
||||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
let addr = tcp4([127, 0, 0, 1], 1234);
|
||||||
let mut ls = ListenersStream::new(t);
|
let mut ls = ListenersStream::new(t);
|
||||||
ls.listen_on(addr).expect("listen_on failed");
|
ls.listen_on(addr).expect("listen_on failed");
|
||||||
set_listener_state(&mut ls, 0, ListenerState::Ok(Async::Ready(None)));
|
set_listener_state(&mut ls, 0, ListenerState::Ok(Async::Ready(None)));
|
||||||
assert_matches!(ls.poll(), Async::Ready(listeners_event) => {
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
assert_matches!(listeners_event, ListenersEvent::Closed{..})
|
assert_matches!(listeners_event, ListenersEvent::Closed{..})
|
||||||
});
|
});
|
||||||
assert_eq!(ls.listeners.len(), 0); // it's gone
|
assert_eq!(ls.listeners.len(), 0); // it's gone
|
||||||
@ -443,92 +478,25 @@ mod tests {
|
|||||||
let mut t = DummyTransport::new();
|
let mut t = DummyTransport::new();
|
||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
let muxer = DummyMuxer::new();
|
let muxer = DummyMuxer::new();
|
||||||
t.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some( (peer_id, muxer) ))));
|
let event = ListenerEvent::Upgrade {
|
||||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
upgrade: (peer_id, muxer),
|
||||||
|
listen_addr: tcp4([127, 0, 0, 1], 1234),
|
||||||
|
remote_addr: tcp4([127, 0, 0, 1], 32000)
|
||||||
|
};
|
||||||
|
t.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some(event))));
|
||||||
|
let addr = tcp4([127, 0, 0, 1], 1234);
|
||||||
let mut ls = ListenersStream::new(t);
|
let mut ls = ListenersStream::new(t);
|
||||||
ls.listen_on(addr).expect("listen_on failed");
|
ls.listen_on(addr).expect("listen_on failed");
|
||||||
set_listener_state(&mut ls, 0, ListenerState::Error); // simulate an error on the socket
|
set_listener_state(&mut ls, 0, ListenerState::Error); // simulate an error on the socket
|
||||||
assert_matches!(ls.poll(), Async::Ready(listeners_event) => {
|
assert_matches!(ls.by_ref().wait().next(), Some(Ok(listeners_event)) => {
|
||||||
assert_matches!(listeners_event, ListenersEvent::Closed{..})
|
assert_matches!(listeners_event, ListenersEvent::Closed{..})
|
||||||
});
|
});
|
||||||
assert_eq!(ls.listeners.len(), 0); // it's gone
|
assert_eq!(ls.listeners.len(), 0); // it's gone
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn tcp4(ip: [u8; 4], port: u16) -> Multiaddr {
|
||||||
fn listener_stream_poll_chatty_listeners_each_get_their_turn() {
|
let protos = std::iter::once(multiaddr::Protocol::Ip4(ip.into()))
|
||||||
let mut t = DummyTransport::new();
|
.chain(std::iter::once(multiaddr::Protocol::Tcp(port)));
|
||||||
let peer_id = PeerId::random();
|
Multiaddr::from_iter(protos)
|
||||||
let muxer = DummyMuxer::new();
|
|
||||||
t.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some( (peer_id.clone(), muxer) )))); let mut ls = ListenersStream::new(t);
|
|
||||||
|
|
||||||
// Create 4 Listeners
|
|
||||||
for n in 0..4 {
|
|
||||||
let addr = format!("/ip4/127.0.0.{}/tcp/{}", n, n).parse::<Multiaddr>().expect("bad multiaddr");
|
|
||||||
ls.listen_on(addr).expect("listen_on failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poll() processes listeners in reverse order. Each listener is polled
|
|
||||||
// in turn.
|
|
||||||
for n in (0..4).rev() {
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(ListenersEvent::Incoming{listen_addr, ..}) => {
|
|
||||||
assert_eq!(listen_addr.to_string(), format!("/ip4/127.0.0.{}/tcp/{}", n, n))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doing it again yields them in the same order
|
|
||||||
for n in (0..4).rev() {
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(ListenersEvent::Incoming{listen_addr, ..}) => {
|
|
||||||
assert_eq!(listen_addr.to_string(), format!("/ip4/127.0.0.{}/tcp/{}", n, n))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make last listener NotReady; it will become the first element and
|
|
||||||
// retried after trying the other Listeners.
|
|
||||||
set_listener_state(&mut ls, 3, ListenerState::Ok(Async::NotReady));
|
|
||||||
for n in (0..3).rev() {
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(ListenersEvent::Incoming{listen_addr, ..}) => {
|
|
||||||
assert_eq!(listen_addr.to_string(), format!("/ip4/127.0.0.{}/tcp/{}", n, n))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for n in (0..3).rev() {
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(ListenersEvent::Incoming{listen_addr, ..}) => {
|
|
||||||
assert_eq!(listen_addr.to_string(), format!("/ip4/127.0.0.{}/tcp/{}", n, n))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turning the last listener back on means we now have 4 "good"
|
|
||||||
// listeners, and each get their turn.
|
|
||||||
set_listener_state(
|
|
||||||
&mut ls, 3,
|
|
||||||
ListenerState::Ok(Async::Ready(Some( (peer_id, DummyMuxer::new()) )))
|
|
||||||
);
|
|
||||||
for n in (0..4).rev() {
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(ListenersEvent::Incoming{listen_addr, ..}) => {
|
|
||||||
assert_eq!(listen_addr.to_string(), format!("/ip4/127.0.0.{}/tcp/{}", n, n))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn listener_stream_poll_processes_listeners_in_turn() {
|
|
||||||
let mut t = DummyTransport::new();
|
|
||||||
let peer_id = PeerId::random();
|
|
||||||
let muxer = DummyMuxer::new();
|
|
||||||
t.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some( (peer_id, muxer) ))));
|
|
||||||
let mut ls = ListenersStream::new(t);
|
|
||||||
for n in 0..4 {
|
|
||||||
let addr = format!("/ip4/127.0.0.{}/tcp/{}", n, n).parse::<Multiaddr>().expect("bad multiaddr");
|
|
||||||
ls.listen_on(addr).expect("listen_on failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
for n in (0..4).rev() {
|
|
||||||
assert_matches!(ls.poll(), Async::Ready(ListenersEvent::Incoming{listen_addr, ..}) => {
|
|
||||||
assert_eq!(listen_addr.to_string(), format!("/ip4/127.0.0.{}/tcp/{}", n, n));
|
|
||||||
});
|
|
||||||
set_listener_state(&mut ls, 0, ListenerState::Ok(Async::NotReady));
|
|
||||||
}
|
|
||||||
// All Listeners are NotReady, so poll yields NotReady
|
|
||||||
assert_matches!(ls.poll(), Async::NotReady);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,14 +138,24 @@ where
|
|||||||
{
|
{
|
||||||
/// One of the listeners gracefully closed.
|
/// One of the listeners gracefully closed.
|
||||||
ListenerClosed {
|
ListenerClosed {
|
||||||
/// Address of the listener which closed.
|
|
||||||
listen_addr: Multiaddr,
|
|
||||||
/// The listener which closed.
|
/// The listener which closed.
|
||||||
listener: TTrans::Listener,
|
listener: TTrans::Listener,
|
||||||
/// The error that happened. `Ok` if gracefully closed.
|
/// The error that happened. `Ok` if gracefully closed.
|
||||||
result: Result<(), <TTrans::Listener as Stream>::Error>,
|
result: Result<(), <TTrans::Listener as Stream>::Error>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// One of the listeners is now listening on an additional address.
|
||||||
|
NewListenerAddress {
|
||||||
|
/// The new address the listener is now also listening on.
|
||||||
|
listen_addr: Multiaddr
|
||||||
|
},
|
||||||
|
|
||||||
|
/// One of the listeners is no longer listening on some address.
|
||||||
|
ExpiredListenerAddress {
|
||||||
|
/// The expired address.
|
||||||
|
listen_addr: Multiaddr
|
||||||
|
},
|
||||||
|
|
||||||
/// A new connection arrived on a listener.
|
/// A new connection arrived on a listener.
|
||||||
IncomingConnection(IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr, TConnInfo, TPeerId>),
|
IncomingConnection(IncomingConnectionEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr, TConnInfo, TPeerId>),
|
||||||
|
|
||||||
@ -154,7 +164,7 @@ where
|
|||||||
/// This can include, for example, an error during the handshake of the encryption layer, or
|
/// This can include, for example, an error during the handshake of the encryption layer, or
|
||||||
/// the connection unexpectedly closed.
|
/// the connection unexpectedly closed.
|
||||||
IncomingConnectionError {
|
IncomingConnectionError {
|
||||||
/// Address of the listener which received the connection.
|
/// The address of the listener which received the connection.
|
||||||
listen_addr: Multiaddr,
|
listen_addr: Multiaddr,
|
||||||
/// Address used to send back data to the remote.
|
/// Address used to send back data to the remote.
|
||||||
send_back_addr: Multiaddr,
|
send_back_addr: Multiaddr,
|
||||||
@ -244,19 +254,32 @@ where
|
|||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
RawSwarmEvent::ListenerClosed { ref listen_addr, ref result, .. } => {
|
RawSwarmEvent::NewListenerAddress { ref listen_addr } => {
|
||||||
f.debug_struct("ListenerClosed")
|
f.debug_struct("NewListenerAddress")
|
||||||
.field("listen_addr", listen_addr)
|
.field("listen_addr", listen_addr)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
RawSwarmEvent::ExpiredListenerAddress { ref listen_addr } => {
|
||||||
|
f.debug_struct("ExpiredListenerAddress")
|
||||||
|
.field("listen_addr", listen_addr)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
RawSwarmEvent::ListenerClosed { ref result, .. } => {
|
||||||
|
f.debug_struct("ListenerClosed")
|
||||||
.field("result", result)
|
.field("result", result)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
RawSwarmEvent::IncomingConnection( IncomingConnectionEvent { ref listen_addr, ref send_back_addr, .. } ) => {
|
RawSwarmEvent::IncomingConnection(ref event) => {
|
||||||
f.debug_struct("IncomingConnection")
|
f.debug_struct("IncomingConnection")
|
||||||
.field("listen_addr", listen_addr)
|
.field("listen_addr", &event.listen_addr)
|
||||||
.field("send_back_addr", send_back_addr)
|
.field("send_back_addr", &event.send_back_addr)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
RawSwarmEvent::IncomingConnectionError { ref listen_addr, ref send_back_addr, ref error} => {
|
RawSwarmEvent::IncomingConnectionError {
|
||||||
|
ref listen_addr,
|
||||||
|
ref send_back_addr,
|
||||||
|
ref error
|
||||||
|
} => {
|
||||||
f.debug_struct("IncomingConnectionError")
|
f.debug_struct("IncomingConnectionError")
|
||||||
.field("listen_addr", listen_addr)
|
.field("listen_addr", listen_addr)
|
||||||
.field("send_back_addr", send_back_addr)
|
.field("send_back_addr", send_back_addr)
|
||||||
@ -493,7 +516,7 @@ where TTrans: Transport
|
|||||||
upgrade: TTrans::ListenerUpgrade,
|
upgrade: TTrans::ListenerUpgrade,
|
||||||
/// PeerId of the local node.
|
/// PeerId of the local node.
|
||||||
local_peer_id: TPeerId,
|
local_peer_id: TPeerId,
|
||||||
/// Address of the listener which received the connection.
|
/// Addresses of the listener which received the connection.
|
||||||
listen_addr: Multiaddr,
|
listen_addr: Multiaddr,
|
||||||
/// Address used to send back data to the remote.
|
/// Address used to send back data to the remote.
|
||||||
send_back_addr: Multiaddr,
|
send_back_addr: Multiaddr,
|
||||||
@ -647,7 +670,7 @@ impl ConnectedPoint {
|
|||||||
/// Information about an incoming connection currently being negotiated.
|
/// Information about an incoming connection currently being negotiated.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct IncomingInfo<'a> {
|
pub struct IncomingInfo<'a> {
|
||||||
/// Address of the listener that received the connection.
|
/// Listener address that received the connection.
|
||||||
pub listen_addr: &'a Multiaddr,
|
pub listen_addr: &'a Multiaddr,
|
||||||
/// Stack of protocols used to send back data to the remote.
|
/// Stack of protocols used to send back data to the remote.
|
||||||
pub send_back_addr: &'a Multiaddr,
|
pub send_back_addr: &'a Multiaddr,
|
||||||
@ -719,14 +742,13 @@ where
|
|||||||
|
|
||||||
/// Start listening on the given multiaddress.
|
/// Start listening on the given multiaddress.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<Multiaddr, TransportError<TTrans::Error>> {
|
pub fn listen_on(&mut self, addr: Multiaddr) -> Result<(), TransportError<TTrans::Error>> {
|
||||||
self.listeners.listen_on(addr)
|
self.listeners.listen_on(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator that produces the list of addresses we're listening on.
|
/// Returns an iterator that produces the list of addresses we are listening on.
|
||||||
#[inline]
|
pub fn listen_addrs(&self) -> impl Iterator<Item = &Multiaddr> {
|
||||||
pub fn listeners(&self) -> impl Iterator<Item = &Multiaddr> {
|
self.listeners.listen_addrs()
|
||||||
self.listeners.listeners()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns limit on incoming connections.
|
/// Returns limit on incoming connections.
|
||||||
@ -743,14 +765,13 @@ where
|
|||||||
///
|
///
|
||||||
/// For each listener, calls `nat_traversal` with the observed address and returns the outcome.
|
/// For each listener, calls `nat_traversal` with the observed address and returns the outcome.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn nat_traversal<'a>(
|
pub fn nat_traversal<'a>(&'a self, observed_addr: &'a Multiaddr)
|
||||||
&'a self,
|
-> impl Iterator<Item = Multiaddr> + 'a
|
||||||
observed_addr: &'a Multiaddr,
|
where
|
||||||
) -> impl Iterator<Item = Multiaddr> + 'a
|
TMuxer: 'a,
|
||||||
where TMuxer: 'a,
|
THandler: 'a,
|
||||||
THandler: 'a,
|
|
||||||
{
|
{
|
||||||
self.listeners()
|
self.listen_addrs()
|
||||||
.flat_map(move |server| self.transport().nat_traversal(server, observed_addr))
|
.flat_map(move |server| self.transport().nat_traversal(server, observed_addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,10 +840,7 @@ where
|
|||||||
.filter_map(|&(_, ref endpoint)| {
|
.filter_map(|&(_, ref endpoint)| {
|
||||||
match endpoint {
|
match endpoint {
|
||||||
ConnectedPoint::Listener { listen_addr, send_back_addr } => {
|
ConnectedPoint::Listener { listen_addr, send_back_addr } => {
|
||||||
Some(IncomingInfo {
|
Some(IncomingInfo { listen_addr, send_back_addr })
|
||||||
listen_addr,
|
|
||||||
send_back_addr,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
ConnectedPoint::Dialer { .. } => None,
|
ConnectedPoint::Dialer { .. } => None,
|
||||||
}
|
}
|
||||||
@ -986,30 +1004,26 @@ where
|
|||||||
_ => {
|
_ => {
|
||||||
match self.listeners.poll() {
|
match self.listeners.poll() {
|
||||||
Async::NotReady => (),
|
Async::NotReady => (),
|
||||||
Async::Ready(ListenersEvent::Incoming {
|
Async::Ready(ListenersEvent::Incoming { upgrade, listen_addr, send_back_addr }) => {
|
||||||
upgrade, listen_addr, send_back_addr }) =>
|
|
||||||
{
|
|
||||||
let event = IncomingConnectionEvent {
|
let event = IncomingConnectionEvent {
|
||||||
upgrade,
|
upgrade,
|
||||||
local_peer_id:
|
local_peer_id: self.reach_attempts.local_peer_id.clone(),
|
||||||
self.reach_attempts.local_peer_id.clone(),
|
|
||||||
listen_addr,
|
listen_addr,
|
||||||
send_back_addr,
|
send_back_addr,
|
||||||
active_nodes: &mut self.active_nodes,
|
active_nodes: &mut self.active_nodes,
|
||||||
other_reach_attempts: &mut self.reach_attempts.other_reach_attempts,
|
other_reach_attempts: &mut self.reach_attempts.other_reach_attempts,
|
||||||
};
|
};
|
||||||
return Async::Ready(RawSwarmEvent::IncomingConnection(event));
|
return Async::Ready(RawSwarmEvent::IncomingConnection(event));
|
||||||
},
|
|
||||||
Async::Ready(ListenersEvent::Closed {
|
|
||||||
listen_addr, listener, result }) =>
|
|
||||||
{
|
|
||||||
return Async::Ready(RawSwarmEvent::ListenerClosed {
|
|
||||||
listen_addr,
|
|
||||||
listener,
|
|
||||||
result,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
Async::Ready(ListenersEvent::NewAddress { listen_addr }) => {
|
||||||
|
return Async::Ready(RawSwarmEvent::NewListenerAddress { listen_addr })
|
||||||
|
}
|
||||||
|
Async::Ready(ListenersEvent::AddressExpired { listen_addr }) => {
|
||||||
|
return Async::Ready(RawSwarmEvent::ExpiredListenerAddress { listen_addr })
|
||||||
|
}
|
||||||
|
Async::Ready(ListenersEvent::Closed { listener, result }) => {
|
||||||
|
return Async::Ready(RawSwarmEvent::ListenerClosed { listener, result })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ use crate::tests::dummy_handler::{Handler, HandlerState, InEvent, OutEvent};
|
|||||||
use crate::tests::dummy_transport::ListenerState;
|
use crate::tests::dummy_transport::ListenerState;
|
||||||
use crate::tests::dummy_muxer::{DummyMuxer, DummyConnectionState};
|
use crate::tests::dummy_muxer::{DummyMuxer, DummyConnectionState};
|
||||||
use crate::nodes::NodeHandlerEvent;
|
use crate::nodes::NodeHandlerEvent;
|
||||||
|
use crate::transport::ListenerEvent;
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -39,17 +40,6 @@ fn query_transport() {
|
|||||||
assert_eq!(raw_swarm.transport(), &transport2);
|
assert_eq!(raw_swarm.transport(), &transport2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn starts_listening() {
|
|
||||||
let mut raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());
|
|
||||||
let addr = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
|
||||||
let addr2 = addr.clone();
|
|
||||||
assert!(raw_swarm.listen_on(addr).is_ok());
|
|
||||||
let listeners = raw_swarm.listeners().collect::<Vec<&Multiaddr>>();
|
|
||||||
assert_eq!(listeners.len(), 1);
|
|
||||||
assert_eq!(listeners[0], &addr2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn local_node_peer() {
|
fn local_node_peer() {
|
||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
@ -59,9 +49,6 @@ fn local_node_peer() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nat_traversal_transforms_the_observed_address_according_to_the_transport_used() {
|
fn nat_traversal_transforms_the_observed_address_according_to_the_transport_used() {
|
||||||
// the DummyTransport nat_traversal increments the port number by one for Ip4 addresses
|
|
||||||
let transport = DummyTransport::new();
|
|
||||||
let mut raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
|
||||||
let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
||||||
// An unrelated outside address is returned as-is, no transform
|
// An unrelated outside address is returned as-is, no transform
|
||||||
let outside_addr1 = "/memory/0".parse::<Multiaddr>().expect("bad multiaddr");
|
let outside_addr1 = "/memory/0".parse::<Multiaddr>().expect("bad multiaddr");
|
||||||
@ -69,8 +56,26 @@ fn nat_traversal_transforms_the_observed_address_according_to_the_transport_used
|
|||||||
let addr2 = "/ip4/127.0.0.2/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
let addr2 = "/ip4/127.0.0.2/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
||||||
let outside_addr2 = "/ip4/127.0.0.2/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
let outside_addr2 = "/ip4/127.0.0.2/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
|
||||||
|
|
||||||
raw_swarm.listen_on(addr1).unwrap();
|
// the DummyTransport nat_traversal increments the port number by one for Ip4 addresses
|
||||||
raw_swarm.listen_on(addr2).unwrap();
|
let mut transport = DummyTransport::new();
|
||||||
|
let events = vec![
|
||||||
|
ListenerEvent::NewAddress(addr1.clone()),
|
||||||
|
ListenerEvent::NewAddress(addr2.clone())
|
||||||
|
];
|
||||||
|
transport.set_initial_listener_state(ListenerState::Events(events));
|
||||||
|
|
||||||
|
let mut raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||||
|
|
||||||
|
raw_swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let raw_swarm =
|
||||||
|
future::lazy(move || {
|
||||||
|
assert_matches!(raw_swarm.poll(), Async::Ready(RawSwarmEvent::NewListenerAddress {..}));
|
||||||
|
assert_matches!(raw_swarm.poll(), Async::Ready(RawSwarmEvent::NewListenerAddress {..}));
|
||||||
|
Ok::<_, void::Void>(raw_swarm)
|
||||||
|
})
|
||||||
|
.wait()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let natted = raw_swarm
|
let natted = raw_swarm
|
||||||
.nat_traversal(&outside_addr1)
|
.nat_traversal(&outside_addr1)
|
||||||
@ -124,8 +129,15 @@ fn num_incoming_negotiated() {
|
|||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
let muxer = DummyMuxer::new();
|
let muxer = DummyMuxer::new();
|
||||||
|
|
||||||
// Set up listener to see an incoming connection
|
let events = vec![
|
||||||
transport.set_initial_listener_state(ListenerState::Ok(Async::Ready(Some((peer_id, muxer)))));
|
ListenerEvent::NewAddress("/ip4/127.0.0.1/tcp/1234".parse().unwrap()),
|
||||||
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: (peer_id.clone(), muxer.clone()),
|
||||||
|
listen_addr: "/ip4/127.0.0.1/tcp/1234".parse().unwrap(),
|
||||||
|
remote_addr: "/ip4/127.0.0.1/tcp/32111".parse().unwrap()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
transport.set_initial_listener_state(ListenerState::Events(events));
|
||||||
|
|
||||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
|
||||||
swarm.listen_on("/memory/0".parse().unwrap()).unwrap();
|
swarm.listen_on("/memory/0".parse().unwrap()).unwrap();
|
||||||
@ -138,10 +150,10 @@ fn num_incoming_negotiated() {
|
|||||||
let swarm_fut = swarm.clone();
|
let swarm_fut = swarm.clone();
|
||||||
let fut = future::poll_fn(move || -> Poll<_, ()> {
|
let fut = future::poll_fn(move || -> Poll<_, ()> {
|
||||||
let mut swarm_fut = swarm_fut.lock();
|
let mut swarm_fut = swarm_fut.lock();
|
||||||
|
assert_matches!(swarm_fut.poll(), Async::Ready(RawSwarmEvent::NewListenerAddress {..}));
|
||||||
assert_matches!(swarm_fut.poll(), Async::Ready(RawSwarmEvent::IncomingConnection(incoming)) => {
|
assert_matches!(swarm_fut.poll(), Async::Ready(RawSwarmEvent::IncomingConnection(incoming)) => {
|
||||||
incoming.accept(Handler::default());
|
incoming.accept(Handler::default());
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(Async::Ready(()))
|
Ok(Async::Ready(()))
|
||||||
});
|
});
|
||||||
rt.block_on(fut).expect("tokio works");
|
rt.block_on(fut).expect("tokio works");
|
||||||
@ -407,10 +419,18 @@ fn limit_incoming_connections() {
|
|||||||
let peer_id = PeerId::random();
|
let peer_id = PeerId::random();
|
||||||
let muxer = DummyMuxer::new();
|
let muxer = DummyMuxer::new();
|
||||||
let limit = 1;
|
let limit = 1;
|
||||||
transport.set_initial_listener_state(ListenerState::Ok(Async::Ready(
|
|
||||||
Some((peer_id, muxer)))));
|
let mut events = vec![ListenerEvent::NewAddress("/ip4/127.0.0.1/tcp/1234".parse().unwrap())];
|
||||||
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new_with_incoming_limit(
|
events.extend(std::iter::repeat(
|
||||||
transport, PeerId::random(), Some(limit));
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: (peer_id.clone(), muxer.clone()),
|
||||||
|
listen_addr: "/ip4/127.0.0.1/tcp/1234".parse().unwrap(),
|
||||||
|
remote_addr: "/ip4/127.0.0.1/tcp/32111".parse().unwrap()
|
||||||
|
}
|
||||||
|
).take(10));
|
||||||
|
transport.set_initial_listener_state(ListenerState::Events(events));
|
||||||
|
|
||||||
|
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new_with_incoming_limit(transport, PeerId::random(), Some(limit));
|
||||||
assert_eq!(swarm.incoming_limit(), Some(limit));
|
assert_eq!(swarm.incoming_limit(), Some(limit));
|
||||||
swarm.listen_on("/memory/0".parse().unwrap()).unwrap();
|
swarm.listen_on("/memory/0".parse().unwrap()).unwrap();
|
||||||
assert_eq!(swarm.incoming_negotiated().count(), 0);
|
assert_eq!(swarm.incoming_negotiated().count(), 0);
|
||||||
@ -422,6 +442,7 @@ fn limit_incoming_connections() {
|
|||||||
let fut = future::poll_fn(move || -> Poll<_, ()> {
|
let fut = future::poll_fn(move || -> Poll<_, ()> {
|
||||||
let mut swarm_fut = swarm_fut.lock();
|
let mut swarm_fut = swarm_fut.lock();
|
||||||
if i <= limit {
|
if i <= limit {
|
||||||
|
assert_matches!(swarm_fut.poll(), Async::Ready(RawSwarmEvent::NewListenerAddress {..}));
|
||||||
assert_matches!(swarm_fut.poll(),
|
assert_matches!(swarm_fut.poll(),
|
||||||
Async::Ready(RawSwarmEvent::IncomingConnection(incoming)) => {
|
Async::Ready(RawSwarmEvent::IncomingConnection(incoming)) => {
|
||||||
incoming.accept(Handler::default());
|
incoming.accept(Handler::default());
|
||||||
@ -431,9 +452,11 @@ fn limit_incoming_connections() {
|
|||||||
Async::NotReady => (),
|
Async::NotReady => (),
|
||||||
Async::Ready(x) => {
|
Async::Ready(x) => {
|
||||||
match x {
|
match x {
|
||||||
RawSwarmEvent::IncomingConnection(_) => (),
|
RawSwarmEvent::NewListenerAddress {..} => {}
|
||||||
RawSwarmEvent::Connected { .. } => (),
|
RawSwarmEvent::ExpiredListenerAddress {..} => {}
|
||||||
_ => { panic!("Not expected event") },
|
RawSwarmEvent::IncomingConnection(_) => {}
|
||||||
|
RawSwarmEvent::Connected {..} => {}
|
||||||
|
e => panic!("Not expected event: {:?}", e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
//! behave. This includes which protocols are supported and which nodes to try to connect to.
|
//! behave. This includes which protocols are supported and which nodes to try to connect to.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
|
|
||||||
mod behaviour;
|
mod behaviour;
|
||||||
mod swarm;
|
mod swarm;
|
||||||
|
|
||||||
|
@ -147,14 +147,9 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
|
|||||||
/// Starts listening on the given address.
|
/// Starts listening on the given address.
|
||||||
///
|
///
|
||||||
/// Returns an error if the address is not supported.
|
/// Returns an error if the address is not supported.
|
||||||
/// On success, returns an alternative version of the address.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn listen_on(me: &mut Self, addr: Multiaddr) -> Result<Multiaddr, TransportError<TTransport::Error>> {
|
pub fn listen_on(me: &mut Self, addr: Multiaddr) -> Result<(), TransportError<TTransport::Error>> {
|
||||||
let result = me.raw_swarm.listen_on(addr);
|
me.raw_swarm.listen_on(addr)
|
||||||
if let Ok(ref addr) = result {
|
|
||||||
me.listened_addrs.push(addr.clone());
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to dial the given address.
|
/// Tries to dial the given address.
|
||||||
@ -190,7 +185,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
|
|||||||
/// Returns an iterator that produces the list of addresses we're listening on.
|
/// Returns an iterator that produces the list of addresses we're listening on.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn listeners(me: &Self) -> impl Iterator<Item = &Multiaddr> {
|
pub fn listeners(me: &Self) -> impl Iterator<Item = &Multiaddr> {
|
||||||
RawSwarm::listeners(&me.raw_swarm)
|
me.raw_swarm.listen_addrs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator that produces the list of addresses that other nodes can use to reach
|
/// Returns an iterator that produces the list of addresses that other nodes can use to reach
|
||||||
@ -253,7 +248,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
|
|||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll(&mut self) -> Poll<Option<TBehaviour::OutEvent>, io::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, io::Error> {
|
||||||
loop {
|
loop {
|
||||||
let mut raw_swarm_not_ready = false;
|
let mut raw_swarm_not_ready = false;
|
||||||
|
|
||||||
@ -275,6 +270,14 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
|
|||||||
let handler = self.behaviour.new_handler();
|
let handler = self.behaviour.new_handler();
|
||||||
incoming.accept(handler.into_node_handler_builder());
|
incoming.accept(handler.into_node_handler_builder());
|
||||||
},
|
},
|
||||||
|
Async::Ready(RawSwarmEvent::NewListenerAddress { listen_addr }) => {
|
||||||
|
if !self.listened_addrs.contains(&listen_addr) {
|
||||||
|
self.listened_addrs.push(listen_addr.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Async::Ready(RawSwarmEvent::ExpiredListenerAddress { listen_addr }) => {
|
||||||
|
self.listened_addrs.retain(|a| a != &listen_addr)
|
||||||
|
}
|
||||||
Async::Ready(RawSwarmEvent::ListenerClosed { .. }) => {},
|
Async::Ready(RawSwarmEvent::ListenerClosed { .. }) => {},
|
||||||
Async::Ready(RawSwarmEvent::IncomingConnectionError { .. }) => {},
|
Async::Ready(RawSwarmEvent::IncomingConnectionError { .. }) => {},
|
||||||
Async::Ready(RawSwarmEvent::DialError { peer_id, multiaddr, error, new_state }) => {
|
Async::Ready(RawSwarmEvent::DialError { peer_id, multiaddr, error, new_state }) => {
|
||||||
@ -304,7 +307,7 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
|
|||||||
Async::NotReady if raw_swarm_not_ready => return Ok(Async::NotReady),
|
Async::NotReady if raw_swarm_not_ready => return Ok(Async::NotReady),
|
||||||
Async::NotReady => (),
|
Async::NotReady => (),
|
||||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
|
Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
|
||||||
return Ok(Async::Ready(Some(event)));
|
return Ok(Async::Ready(Some(event)))
|
||||||
},
|
},
|
||||||
Async::Ready(NetworkBehaviourAction::DialAddress { address }) => {
|
Async::Ready(NetworkBehaviourAction::DialAddress { address }) => {
|
||||||
let _ = Swarm::dial_addr(self, address);
|
let _ = Swarm::dial_addr(self, address);
|
||||||
|
@ -53,7 +53,6 @@ impl Default for Handler {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub(crate) enum HandlerState {
|
pub(crate) enum HandlerState {
|
||||||
NotReady,
|
|
||||||
Ready(NodeHandlerEvent<usize, OutEvent>),
|
Ready(NodeHandlerEvent<usize, OutEvent>),
|
||||||
Err,
|
Err,
|
||||||
}
|
}
|
||||||
@ -117,7 +116,6 @@ impl NodeHandler for Handler {
|
|||||||
fn poll(&mut self) -> Poll<NodeHandlerEvent<usize, OutEvent>, IoError> {
|
fn poll(&mut self) -> Poll<NodeHandlerEvent<usize, OutEvent>, IoError> {
|
||||||
match self.state.take() {
|
match self.state.take() {
|
||||||
Some(ref state) => match state {
|
Some(ref state) => match state {
|
||||||
HandlerState::NotReady => Ok(Async::NotReady),
|
|
||||||
HandlerState::Ready(event) => Ok(Async::Ready(event.clone())),
|
HandlerState::Ready(event) => Ok(Async::Ready(event.clone())),
|
||||||
HandlerState::Err => Err(io::Error::new(io::ErrorKind::Other, "oh noes")),
|
HandlerState::Err => Err(io::Error::new(io::ErrorKind::Other, "oh noes")),
|
||||||
},
|
},
|
||||||
|
@ -28,13 +28,14 @@ use futures::{
|
|||||||
stream,
|
stream,
|
||||||
};
|
};
|
||||||
use std::io;
|
use std::io;
|
||||||
use crate::{Multiaddr, PeerId, Transport, transport::TransportError};
|
use crate::{Multiaddr, PeerId, Transport, transport::{ListenerEvent, TransportError}};
|
||||||
use crate::tests::dummy_muxer::DummyMuxer;
|
use crate::tests::dummy_muxer::DummyMuxer;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub(crate) enum ListenerState {
|
pub(crate) enum ListenerState {
|
||||||
Ok(Async<Option<(PeerId, DummyMuxer)>>),
|
Ok(Async<Option<ListenerEvent<(PeerId, DummyMuxer)>>>),
|
||||||
Error
|
Error,
|
||||||
|
Events(Vec<ListenerEvent<(PeerId, DummyMuxer)>>)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -69,34 +70,25 @@ impl DummyTransport {
|
|||||||
impl Transport for DummyTransport {
|
impl Transport for DummyTransport {
|
||||||
type Output = (PeerId, DummyMuxer);
|
type Output = (PeerId, DummyMuxer);
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
type Listener = Box<dyn Stream<Item=(Self::ListenerUpgrade, Multiaddr), Error=io::Error> + Send>;
|
type Listener = Box<dyn Stream<Item=ListenerEvent<Self::ListenerUpgrade>, Error=io::Error> + Send>;
|
||||||
type ListenerUpgrade = FutureResult<Self::Output, io::Error>;
|
type ListenerUpgrade = FutureResult<Self::Output, io::Error>;
|
||||||
type Dial = Box<dyn Future<Item = Self::Output, Error = io::Error> + Send>;
|
type Dial = Box<dyn Future<Item = Self::Output, Error = io::Error> + Send>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>>
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
let addr2 = addr.clone();
|
|
||||||
match self.listener_state {
|
match self.listener_state {
|
||||||
ListenerState::Ok(r#async) => {
|
ListenerState::Ok(state) => match state {
|
||||||
let tupelize = move |stream| (future::ok(stream), addr.clone());
|
Async::NotReady => Ok(Box::new(stream::poll_fn(|| Ok(Async::NotReady)))),
|
||||||
Ok(match r#async {
|
Async::Ready(Some(event)) => Ok(Box::new(stream::poll_fn(move || {
|
||||||
Async::NotReady => {
|
Ok(Async::Ready(Some(event.clone().map(future::ok))))
|
||||||
let stream = stream::poll_fn(|| Ok(Async::NotReady)).map(tupelize);
|
}))),
|
||||||
(Box::new(stream), addr2)
|
Async::Ready(None) => Ok(Box::new(stream::empty()))
|
||||||
}
|
},
|
||||||
Async::Ready(Some(tup)) => {
|
|
||||||
let stream = stream::poll_fn(move || Ok( Async::Ready(Some(tup.clone()) ))).map(tupelize);
|
|
||||||
(Box::new(stream), addr2)
|
|
||||||
}
|
|
||||||
Async::Ready(None) => {
|
|
||||||
let stream = stream::empty();
|
|
||||||
(Box::new(stream), addr2)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ListenerState::Error => Err(TransportError::MultiaddrNotSupported(addr)),
|
ListenerState::Error => Err(TransportError::MultiaddrNotSupported(addr)),
|
||||||
|
ListenerState::Events(events) =>
|
||||||
|
Ok(Box::new(stream::iter_ok(events.into_iter().map(|e| e.map(future::ok)))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::either::EitherError;
|
use crate::{
|
||||||
use crate::{nodes::raw_swarm::ConnectedPoint, transport::Transport, transport::TransportError};
|
nodes::raw_swarm::ConnectedPoint,
|
||||||
|
either::EitherError,
|
||||||
|
transport::{Transport, TransportError, ListenerEvent}
|
||||||
|
};
|
||||||
use futures::{future::Either, prelude::*, try_ready};
|
use futures::{future::Either, prelude::*, try_ready};
|
||||||
use multiaddr::Multiaddr;
|
use multiaddr::Multiaddr;
|
||||||
use std::error;
|
use std::error;
|
||||||
@ -29,7 +32,6 @@ use std::error;
|
|||||||
pub struct AndThen<T, C> { transport: T, fun: C }
|
pub struct AndThen<T, C> { transport: T, fun: C }
|
||||||
|
|
||||||
impl<T, C> AndThen<T, C> {
|
impl<T, C> AndThen<T, C> {
|
||||||
#[inline]
|
|
||||||
pub(crate) fn new(transport: T, fun: C) -> Self {
|
pub(crate) fn new(transport: T, fun: C) -> Self {
|
||||||
AndThen { transport, fun }
|
AndThen { transport, fun }
|
||||||
}
|
}
|
||||||
@ -48,40 +50,25 @@ where
|
|||||||
type ListenerUpgrade = AndThenFuture<T::ListenerUpgrade, C, F::Future>;
|
type ListenerUpgrade = AndThenFuture<T::ListenerUpgrade, C, F::Future>;
|
||||||
type Dial = AndThenFuture<T::Dial, C, F::Future>;
|
type Dial = AndThenFuture<T::Dial, C, F::Future>;
|
||||||
|
|
||||||
#[inline]
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
let listener = self.transport.listen_on(addr).map_err(|err| err.map(EitherError::A))?;
|
||||||
let (listening_stream, new_addr) = self.transport.listen_on(addr)
|
|
||||||
.map_err(|err| err.map(EitherError::A))?;
|
|
||||||
|
|
||||||
// Try to negotiate the protocol.
|
// Try to negotiate the protocol.
|
||||||
// Note that failing to negotiate a protocol will never produce a future with an error.
|
// Note that failing to negotiate a protocol will never produce a future with an error.
|
||||||
// Instead the `stream` will produce `Ok(Err(...))`.
|
// Instead the `stream` will produce `Ok(Err(...))`.
|
||||||
// `stream` can only produce an `Err` if `listening_stream` produces an `Err`.
|
// `stream` can only produce an `Err` if `listening_stream` produces an `Err`.
|
||||||
let stream = AndThenStream {
|
let stream = AndThenStream { stream: listener, fun: self.fun };
|
||||||
stream: listening_stream,
|
Ok(stream)
|
||||||
listen_addr: new_addr.clone(),
|
|
||||||
fun: self.fun
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((stream, new_addr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
let dialed_fut = self.transport.dial(addr.clone())
|
let dialed_fut = self.transport.dial(addr.clone()).map_err(|err| err.map(EitherError::A))?;
|
||||||
.map_err(|err| err.map(EitherError::A))?;
|
|
||||||
|
|
||||||
let connected_point = ConnectedPoint::Dialer { address: addr };
|
|
||||||
|
|
||||||
let future = AndThenFuture {
|
let future = AndThenFuture {
|
||||||
inner: Either::A(dialed_fut),
|
inner: Either::A(dialed_fut),
|
||||||
args: Some((self.fun, connected_point))
|
args: Some((self.fun, ConnectedPoint::Dialer { address: addr }))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(future)
|
Ok(future)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
self.transport.nat_traversal(server, observed)
|
self.transport.nat_traversal(server, observed)
|
||||||
}
|
}
|
||||||
@ -91,31 +78,43 @@ where
|
|||||||
///
|
///
|
||||||
/// Applies a function to every stream item.
|
/// Applies a function to every stream item.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AndThenStream<TListener, TMap> { stream: TListener, listen_addr: Multiaddr, fun: TMap }
|
pub struct AndThenStream<TListener, TMap> {
|
||||||
|
stream: TListener,
|
||||||
|
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
|
where
|
||||||
TListener: Stream<Item = (TListUpgr, Multiaddr), Error = TTransErr>,
|
TListener: Stream<Item = ListenerEvent<TListUpgr>, Error = TTransErr>,
|
||||||
TListUpgr: Future<Item = TTransOut, Error = TTransErr>,
|
TListUpgr: Future<Item = TTransOut, Error = TTransErr>,
|
||||||
TMap: FnOnce(TTransOut, ConnectedPoint) -> TMapOut + Clone,
|
TMap: FnOnce(TTransOut, ConnectedPoint) -> TMapOut + Clone,
|
||||||
TMapOut: IntoFuture
|
TMapOut: IntoFuture
|
||||||
{
|
{
|
||||||
type Item = (AndThenFuture<TListUpgr, TMap, TMapOut::Future>, Multiaddr);
|
type Item = ListenerEvent<AndThenFuture<TListUpgr, TMap, TMapOut::Future>>;
|
||||||
type Error = EitherError<TTransErr, TMapOut::Error>;
|
type Error = EitherError<TTransErr, TMapOut::Error>;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
match self.stream.poll().map_err(EitherError::A)? {
|
match self.stream.poll().map_err(EitherError::A)? {
|
||||||
Async::Ready(Some((future, addr))) => {
|
Async::Ready(Some(event)) => {
|
||||||
let f = self.fun.clone();
|
let event = match event {
|
||||||
let p = ConnectedPoint::Listener {
|
ListenerEvent::Upgrade { upgrade, listen_addr, remote_addr } => {
|
||||||
listen_addr: self.listen_addr.clone(),
|
let point = ConnectedPoint::Listener {
|
||||||
send_back_addr: addr.clone()
|
listen_addr: listen_addr.clone(),
|
||||||
|
send_back_addr: remote_addr.clone()
|
||||||
|
};
|
||||||
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: AndThenFuture {
|
||||||
|
inner: Either::A(upgrade),
|
||||||
|
args: Some((self.fun.clone(), point))
|
||||||
|
},
|
||||||
|
listen_addr,
|
||||||
|
remote_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||||
|
ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a)
|
||||||
};
|
};
|
||||||
let future = AndThenFuture {
|
Ok(Async::Ready(Some(event)))
|
||||||
inner: Either::A(future),
|
|
||||||
args: Some((f, p))
|
|
||||||
};
|
|
||||||
Ok(Async::Ready(Some((future, addr))))
|
|
||||||
}
|
}
|
||||||
Async::Ready(None) => Ok(Async::Ready(None)),
|
Async::Ready(None) => Ok(Async::Ready(None)),
|
||||||
Async::NotReady => Ok(Async::NotReady)
|
Async::NotReady => Ok(Async::NotReady)
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::transport::{Transport, TransportError};
|
use crate::transport::{ListenerEvent, Transport, TransportError};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use multiaddr::Multiaddr;
|
use multiaddr::Multiaddr;
|
||||||
use std::{error, fmt, sync::Arc};
|
use std::{error, fmt, sync::Arc};
|
||||||
@ -38,11 +38,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type Dial<O, E> = Box<dyn Future<Item = O, Error = E> + Send>;
|
pub type Dial<O, E> = Box<dyn Future<Item = O, Error = E> + Send>;
|
||||||
pub type Listener<O, E> = Box<dyn Stream<Item = (ListenerUpgrade<O, E>, Multiaddr), Error = E> + Send>;
|
pub type Listener<O, E> = Box<dyn Stream<Item = ListenerEvent<ListenerUpgrade<O, E>>, Error = E> + Send>;
|
||||||
pub type ListenerUpgrade<O, E> = Box<dyn Future<Item = O, Error = E> + Send>;
|
pub type ListenerUpgrade<O, E> = Box<dyn Future<Item = O, Error = E> + Send>;
|
||||||
|
|
||||||
trait Abstract<O, E> {
|
trait Abstract<O, E> {
|
||||||
fn listen_on(&self, addr: Multiaddr) -> Result<(Listener<O, E>, Multiaddr), TransportError<E>>;
|
fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O, E>, TransportError<E>>;
|
||||||
fn dial(&self, addr: Multiaddr) -> Result<Dial<O, E>, TransportError<E>>;
|
fn dial(&self, addr: Multiaddr) -> Result<Dial<O, E>, TransportError<E>>;
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
|
||||||
}
|
}
|
||||||
@ -55,12 +55,12 @@ where
|
|||||||
T::Listener: Send + 'static,
|
T::Listener: Send + 'static,
|
||||||
T::ListenerUpgrade: Send + 'static,
|
T::ListenerUpgrade: Send + 'static,
|
||||||
{
|
{
|
||||||
fn listen_on(&self, addr: Multiaddr) -> Result<(Listener<O, E>, Multiaddr), TransportError<E>> {
|
fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O, E>, TransportError<E>> {
|
||||||
let (listener, new_addr) = Transport::listen_on(self.clone(), addr)?;
|
let listener = Transport::listen_on(self.clone(), addr)?;
|
||||||
let fut = listener.map(|(upgrade, addr)| {
|
let fut = listener.map(|event| event.map(|upgrade| {
|
||||||
(Box::new(upgrade) as ListenerUpgrade<O, E>, addr)
|
Box::new(upgrade) as ListenerUpgrade<O, E>
|
||||||
});
|
}));
|
||||||
Ok((Box::new(fut) as Box<_>, new_addr))
|
Ok(Box::new(fut) as Box<_>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(&self, addr: Multiaddr) -> Result<Dial<O, E>, TransportError<E>> {
|
fn dial(&self, addr: Multiaddr) -> Result<Dial<O, E>, TransportError<E>> {
|
||||||
@ -68,7 +68,6 @@ where
|
|||||||
Ok(Box::new(fut) as Box<_>)
|
Ok(Box::new(fut) as Box<_>)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
Transport::nat_traversal(self, server, observed)
|
Transport::nat_traversal(self, server, observed)
|
||||||
}
|
}
|
||||||
@ -86,7 +85,6 @@ impl<O, E> fmt::Debug for Boxed<O, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<O, E> Clone for Boxed<O, E> {
|
impl<O, E> Clone for Boxed<O, E> {
|
||||||
#[inline]
|
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Boxed {
|
Boxed {
|
||||||
inner: self.inner.clone(),
|
inner: self.inner.clone(),
|
||||||
@ -103,17 +101,14 @@ where E: error::Error,
|
|||||||
type ListenerUpgrade = ListenerUpgrade<O, E>;
|
type ListenerUpgrade = ListenerUpgrade<O, E>;
|
||||||
type Dial = Dial<O, E>;
|
type Dial = Dial<O, E>;
|
||||||
|
|
||||||
#[inline]
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
|
||||||
self.inner.listen_on(addr)
|
self.inner.listen_on(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
self.inner.dial(addr)
|
self.inner.dial(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
self.inner.nat_traversal(server, observed)
|
self.inner.nat_traversal(server, observed)
|
||||||
}
|
}
|
||||||
|
@ -43,15 +43,15 @@ where
|
|||||||
type ListenerUpgrade = EitherFuture<A::ListenerUpgrade, B::ListenerUpgrade>;
|
type ListenerUpgrade = EitherFuture<A::ListenerUpgrade, B::ListenerUpgrade>;
|
||||||
type Dial = EitherFuture<A::Dial, B::Dial>;
|
type Dial = EitherFuture<A::Dial, B::Dial>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let addr = match self.0.listen_on(addr) {
|
let addr = match self.0.listen_on(addr) {
|
||||||
Ok((connec, addr)) => return Ok((EitherListenStream::First(connec), addr)),
|
Ok(listener) => return Ok(EitherListenStream::First(listener)),
|
||||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
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) {
|
let addr = match self.1.listen_on(addr) {
|
||||||
Ok((connec, addr)) => return Ok((EitherListenStream::Second(connec), addr)),
|
Ok(listener) => return Ok(EitherListenStream::Second(listener)),
|
||||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
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))),
|
||||||
};
|
};
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::transport::{Transport, TransportError};
|
use crate::transport::{Transport, TransportError, ListenerEvent};
|
||||||
use multiaddr::Multiaddr;
|
use crate::Multiaddr;
|
||||||
use std::{fmt, io, marker::PhantomData};
|
use std::{fmt, io, marker::PhantomData};
|
||||||
|
|
||||||
/// Implementation of `Transport` that doesn't support any multiaddr.
|
/// Implementation of `Transport` that doesn't support any multiaddr.
|
||||||
@ -55,12 +55,12 @@ impl<TOut> Clone for DummyTransport<TOut> {
|
|||||||
impl<TOut> Transport for DummyTransport<TOut> {
|
impl<TOut> Transport for DummyTransport<TOut> {
|
||||||
type Output = TOut;
|
type Output = TOut;
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
type Listener = futures::stream::Empty<(Self::ListenerUpgrade, Multiaddr), io::Error>;
|
type Listener = futures::stream::Empty<ListenerEvent<Self::ListenerUpgrade>, io::Error>;
|
||||||
type ListenerUpgrade = futures::future::Empty<Self::Output, io::Error>;
|
type ListenerUpgrade = futures::future::Empty<Self::Output, io::Error>;
|
||||||
type Dial = futures::future::Empty<Self::Output, io::Error>;
|
type Dial = futures::future::Empty<Self::Output, io::Error>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
Err(TransportError::MultiaddrNotSupported(addr))
|
Err(TransportError::MultiaddrNotSupported(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,10 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{nodes::raw_swarm::ConnectedPoint, transport::Transport, transport::TransportError};
|
use crate::{
|
||||||
|
nodes::raw_swarm::ConnectedPoint,
|
||||||
|
transport::{Transport, TransportError, ListenerEvent}
|
||||||
|
};
|
||||||
use futures::{prelude::*, try_ready};
|
use futures::{prelude::*, try_ready};
|
||||||
use multiaddr::Multiaddr;
|
use multiaddr::Multiaddr;
|
||||||
|
|
||||||
@ -27,7 +30,6 @@ use multiaddr::Multiaddr;
|
|||||||
pub struct Map<T, F> { transport: T, fun: F }
|
pub struct Map<T, F> { transport: T, fun: F }
|
||||||
|
|
||||||
impl<T, F> Map<T, F> {
|
impl<T, F> Map<T, F> {
|
||||||
#[inline]
|
|
||||||
pub(crate) fn new(transport: T, fun: F) -> Self {
|
pub(crate) fn new(transport: T, fun: F) -> Self {
|
||||||
Map { transport, fun }
|
Map { transport, fun }
|
||||||
}
|
}
|
||||||
@ -44,26 +46,17 @@ where
|
|||||||
type ListenerUpgrade = MapFuture<T::ListenerUpgrade, F>;
|
type ListenerUpgrade = MapFuture<T::ListenerUpgrade, F>;
|
||||||
type Dial = MapFuture<T::Dial, F>;
|
type Dial = MapFuture<T::Dial, F>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let (stream, listen_addr) = self.transport.listen_on(addr)?;
|
let stream = self.transport.listen_on(addr)?;
|
||||||
let stream = MapStream {
|
Ok(MapStream { stream, fun: self.fun })
|
||||||
stream,
|
|
||||||
listen_addr: listen_addr.clone(),
|
|
||||||
fun: self.fun
|
|
||||||
};
|
|
||||||
Ok((stream, listen_addr))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
let future = self.transport.dial(addr.clone())?;
|
let future = self.transport.dial(addr.clone())?;
|
||||||
let p = ConnectedPoint::Dialer { address: addr };
|
let p = ConnectedPoint::Dialer { address: addr };
|
||||||
Ok(MapFuture {
|
Ok(MapFuture { inner: future, args: Some((self.fun, p)) })
|
||||||
inner: future,
|
|
||||||
args: Some((self.fun, p))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
self.transport.nat_traversal(server, observed)
|
self.transport.nat_traversal(server, observed)
|
||||||
}
|
}
|
||||||
@ -73,30 +66,39 @@ where
|
|||||||
///
|
///
|
||||||
/// Maps a function over every stream item.
|
/// Maps a function over every stream item.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MapStream<T, F> { stream: T, listen_addr: Multiaddr, fun: F }
|
pub struct MapStream<T, F> { stream: T, fun: F }
|
||||||
|
|
||||||
impl<T, F, A, B, X> Stream for MapStream<T, F>
|
impl<T, F, A, B, X> Stream for MapStream<T, F>
|
||||||
where
|
where
|
||||||
T: Stream<Item = (X, Multiaddr)>,
|
T: Stream<Item = ListenerEvent<X>>,
|
||||||
X: Future<Item = A>,
|
X: Future<Item = A>,
|
||||||
F: FnOnce(A, ConnectedPoint) -> B + Clone
|
F: FnOnce(A, ConnectedPoint) -> B + Clone
|
||||||
{
|
{
|
||||||
type Item = (MapFuture<X, F>, Multiaddr);
|
type Item = ListenerEvent<MapFuture<X, F>>;
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
match self.stream.poll()? {
|
match self.stream.poll()? {
|
||||||
Async::Ready(Some((future, addr))) => {
|
Async::Ready(Some(event)) => {
|
||||||
let f = self.fun.clone();
|
let event = match event {
|
||||||
let p = ConnectedPoint::Listener {
|
ListenerEvent::Upgrade { upgrade, listen_addr, remote_addr } => {
|
||||||
listen_addr: self.listen_addr.clone(),
|
let point = ConnectedPoint::Listener {
|
||||||
send_back_addr: addr.clone()
|
listen_addr: listen_addr.clone(),
|
||||||
|
send_back_addr: remote_addr.clone()
|
||||||
|
};
|
||||||
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: MapFuture {
|
||||||
|
inner: upgrade,
|
||||||
|
args: Some((self.fun.clone(), point))
|
||||||
|
},
|
||||||
|
listen_addr,
|
||||||
|
remote_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||||
|
ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a)
|
||||||
};
|
};
|
||||||
let future = MapFuture {
|
Ok(Async::Ready(Some(event)))
|
||||||
inner: future,
|
|
||||||
args: Some((f, p))
|
|
||||||
};
|
|
||||||
Ok(Async::Ready(Some((future, addr))))
|
|
||||||
}
|
}
|
||||||
Async::Ready(None) => Ok(Async::Ready(None)),
|
Async::Ready(None) => Ok(Async::Ready(None)),
|
||||||
Async::NotReady => Ok(Async::NotReady)
|
Async::NotReady => Ok(Async::NotReady)
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::transport::{Transport, TransportError};
|
use crate::transport::{Transport, TransportError, ListenerEvent};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use multiaddr::Multiaddr;
|
use multiaddr::Multiaddr;
|
||||||
use std::error;
|
use std::error;
|
||||||
@ -32,7 +32,6 @@ pub struct MapErr<T, F> {
|
|||||||
|
|
||||||
impl<T, F> MapErr<T, F> {
|
impl<T, F> MapErr<T, F> {
|
||||||
/// Internal function that builds a `MapErr`.
|
/// Internal function that builds a `MapErr`.
|
||||||
#[inline]
|
|
||||||
pub(crate) fn new(transport: T, map: F) -> MapErr<T, F> {
|
pub(crate) fn new(transport: T, map: F) -> MapErr<T, F> {
|
||||||
MapErr { transport, map }
|
MapErr { transport, map }
|
||||||
}
|
}
|
||||||
@ -50,53 +49,53 @@ where
|
|||||||
type ListenerUpgrade = MapErrListenerUpgrade<T, F>;
|
type ListenerUpgrade = MapErrListenerUpgrade<T, F>;
|
||||||
type Dial = MapErrDial<T, F>;
|
type Dial = MapErrDial<T, F>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let map = self.map;
|
let map = self.map;
|
||||||
|
|
||||||
match self.transport.listen_on(addr) {
|
match self.transport.listen_on(addr) {
|
||||||
Ok((stream, listen_addr)) => {
|
Ok(stream) => Ok(MapErrListener { inner: stream, map }),
|
||||||
let stream = MapErrListener { inner: stream, map };
|
Err(err) => Err(err.map(map))
|
||||||
Ok((stream, listen_addr))
|
|
||||||
}
|
|
||||||
Err(err) => Err(err.map(map)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
let map = self.map;
|
let map = self.map;
|
||||||
|
|
||||||
match self.transport.dial(addr) {
|
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)),
|
Err(err) => Err(err.map(map)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
self.transport.nat_traversal(server, observed)
|
self.transport.nat_traversal(server, observed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listening stream for `MapErr`.
|
/// Listening stream for `MapErr`.
|
||||||
pub struct MapErrListener<T, F>
|
pub struct MapErrListener<T: Transport, F> {
|
||||||
where T: Transport {
|
|
||||||
inner: T::Listener,
|
inner: T::Listener,
|
||||||
map: F,
|
map: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, F, TErr> Stream for MapErrListener<T, F>
|
impl<T, F, TErr> Stream for MapErrListener<T, F>
|
||||||
where T: Transport,
|
where
|
||||||
|
T: Transport,
|
||||||
F: FnOnce(T::Error) -> TErr + Clone,
|
F: FnOnce(T::Error) -> TErr + Clone,
|
||||||
TErr: error::Error,
|
TErr: error::Error,
|
||||||
{
|
{
|
||||||
type Item = (MapErrListenerUpgrade<T, F>, Multiaddr);
|
type Item = ListenerEvent<MapErrListenerUpgrade<T, F>>;
|
||||||
type Error = TErr;
|
type Error = TErr;
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
match self.inner.poll() {
|
match self.inner.poll() {
|
||||||
Ok(Async::Ready(Some((value, addr)))) => Ok(Async::Ready(
|
Ok(Async::Ready(Some(event))) => {
|
||||||
Some((MapErrListenerUpgrade { inner: value, map: Some(self.map.clone()) }, addr)))),
|
let event = event.map(move |value| {
|
||||||
|
MapErrListenerUpgrade {
|
||||||
|
inner: value,
|
||||||
|
map: Some(self.map.clone())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(Async::Ready(Some(event)))
|
||||||
|
}
|
||||||
Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
|
Ok(Async::Ready(None)) => Ok(Async::Ready(None)),
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||||
Err(err) => Err((self.map.clone())(err)),
|
Err(err) => Err((self.map.clone())(err)),
|
||||||
@ -105,8 +104,7 @@ where T: Transport,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Listening upgrade future for `MapErr`.
|
/// Listening upgrade future for `MapErr`.
|
||||||
pub struct MapErrListenerUpgrade<T, F>
|
pub struct MapErrListenerUpgrade<T: Transport, F> {
|
||||||
where T: Transport {
|
|
||||||
inner: T::ListenerUpgrade,
|
inner: T::ListenerUpgrade,
|
||||||
map: Option<F>,
|
map: Option<F>,
|
||||||
}
|
}
|
||||||
@ -118,12 +116,9 @@ where T: Transport,
|
|||||||
type Item = T::Output;
|
type Item = T::Output;
|
||||||
type Error = TErr;
|
type Error = TErr;
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
match self.inner.poll() {
|
match self.inner.poll() {
|
||||||
Ok(Async::Ready(value)) => {
|
Ok(Async::Ready(value)) => Ok(Async::Ready(value)),
|
||||||
Ok(Async::Ready(value))
|
|
||||||
},
|
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let map = self.map.take().expect("poll() called again after error");
|
let map = self.map.take().expect("poll() called again after error");
|
||||||
@ -134,21 +129,19 @@ where T: Transport,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Dialing future for `MapErr`.
|
/// Dialing future for `MapErr`.
|
||||||
pub struct MapErrDial<T, F>
|
pub struct MapErrDial<T: Transport, F> {
|
||||||
where T: Transport
|
|
||||||
{
|
|
||||||
inner: T::Dial,
|
inner: T::Dial,
|
||||||
map: Option<F>,
|
map: Option<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, F, TErr> Future for MapErrDial<T, F>
|
impl<T, F, TErr> Future for MapErrDial<T, F>
|
||||||
where T: Transport,
|
where
|
||||||
|
T: Transport,
|
||||||
F: FnOnce(T::Error) -> TErr,
|
F: FnOnce(T::Error) -> TErr,
|
||||||
{
|
{
|
||||||
type Item = T::Output;
|
type Item = T::Output;
|
||||||
type Error = TErr;
|
type Error = TErr;
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
match self.inner.poll() {
|
match self.inner.poll() {
|
||||||
Ok(Async::Ready(value)) => {
|
Ok(Async::Ready(value)) => {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{Transport, transport::TransportError};
|
use crate::{Transport, transport::{TransportError, ListenerEvent}};
|
||||||
use bytes::{Bytes, IntoBuf};
|
use bytes::{Bytes, IntoBuf};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use futures::{future::{self, FutureResult}, prelude::*, sync::mpsc, try_ready};
|
use futures::{future::{self, FutureResult}, prelude::*, sync::mpsc, try_ready};
|
||||||
@ -74,7 +74,7 @@ impl Transport for MemoryTransport {
|
|||||||
type ListenerUpgrade = FutureResult<Self::Output, Self::Error>;
|
type ListenerUpgrade = FutureResult<Self::Output, Self::Error>;
|
||||||
type Dial = DialFuture;
|
type Dial = DialFuture;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let port = if let Ok(port) = parse_memory_addr(&addr) {
|
let port = if let Ok(port) = parse_memory_addr(&addr) {
|
||||||
port
|
port
|
||||||
} else {
|
} else {
|
||||||
@ -97,20 +97,22 @@ impl Transport for MemoryTransport {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let actual_addr = Protocol::Memory(port.get()).into();
|
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel(2);
|
let (tx, rx) = mpsc::channel(2);
|
||||||
match hub.entry(port) {
|
match hub.entry(port) {
|
||||||
Entry::Occupied(_) => return Err(TransportError::Other(MemoryTransportError::Unreachable)),
|
Entry::Occupied(_) =>
|
||||||
Entry::Vacant(e) => e.insert(tx),
|
return Err(TransportError::Other(MemoryTransportError::Unreachable)),
|
||||||
|
Entry::Vacant(e) => e.insert(tx)
|
||||||
};
|
};
|
||||||
|
|
||||||
let listener = Listener {
|
let listener = Listener {
|
||||||
port,
|
port,
|
||||||
|
addr: Protocol::Memory(port.get()).into(),
|
||||||
receiver: rx,
|
receiver: rx,
|
||||||
|
tell_listen_addr: true
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((listener, actual_addr))
|
Ok(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<DialFuture, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<DialFuture, TransportError<Self::Error>> {
|
||||||
@ -173,23 +175,35 @@ impl error::Error for MemoryTransportError {}
|
|||||||
pub struct Listener {
|
pub struct Listener {
|
||||||
/// Port we're listening on.
|
/// Port we're listening on.
|
||||||
port: NonZeroU64,
|
port: NonZeroU64,
|
||||||
|
/// The address we are listening on.
|
||||||
|
addr: Multiaddr,
|
||||||
/// Receives incoming connections.
|
/// Receives incoming connections.
|
||||||
receiver: mpsc::Receiver<Channel<Bytes>>,
|
receiver: mpsc::Receiver<Channel<Bytes>>,
|
||||||
|
/// Generate `ListenerEvent::NewAddress` to inform about our listen address.
|
||||||
|
tell_listen_addr: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Listener {
|
impl Stream for Listener {
|
||||||
type Item = (FutureResult<Channel<Bytes>, MemoryTransportError>, Multiaddr);
|
type Item = ListenerEvent<FutureResult<Channel<Bytes>, MemoryTransportError>>;
|
||||||
type Error = MemoryTransportError;
|
type Error = MemoryTransportError;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
|
if self.tell_listen_addr {
|
||||||
|
self.tell_listen_addr = false;
|
||||||
|
return Ok(Async::Ready(Some(ListenerEvent::NewAddress(self.addr.clone()))))
|
||||||
|
}
|
||||||
let channel = try_ready!(Ok(self.receiver.poll()
|
let channel = try_ready!(Ok(self.receiver.poll()
|
||||||
.expect("An unbounded receiver never panics; QED")));
|
.expect("An unbounded receiver never panics; QED")));
|
||||||
let channel = match channel {
|
let channel = match channel {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
None => return Ok(Async::Ready(None)),
|
None => return Ok(Async::Ready(None))
|
||||||
};
|
};
|
||||||
let dialed_addr = Protocol::Memory(self.port.get()).into();
|
let event = ListenerEvent::Upgrade {
|
||||||
Ok(Async::Ready(Some((future::ok(channel), dialed_addr))))
|
upgrade: future::ok(channel),
|
||||||
|
listen_addr: self.addr.clone(),
|
||||||
|
remote_addr: Protocol::Memory(self.port.get()).into()
|
||||||
|
};
|
||||||
|
Ok(Async::Ready(Some(event)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ pub trait Transport {
|
|||||||
/// transport stack. The item must be a [`ListenerUpgrade`](Transport::ListenerUpgrade) future
|
/// transport stack. The item must be a [`ListenerUpgrade`](Transport::ListenerUpgrade) future
|
||||||
/// that resolves to an [`Output`](Transport::Output) value once all protocol upgrades
|
/// that resolves to an [`Output`](Transport::Output) value once all protocol upgrades
|
||||||
/// have been applied.
|
/// have been applied.
|
||||||
type Listener: Stream<Item = (Self::ListenerUpgrade, Multiaddr), Error = Self::Error>;
|
type Listener: Stream<Item = ListenerEvent<Self::ListenerUpgrade>, Error = Self::Error>;
|
||||||
|
|
||||||
/// A pending [`Output`](Transport::Output) for an inbound connection,
|
/// A pending [`Output`](Transport::Output) for an inbound connection,
|
||||||
/// obtained from the [`Listener`](Transport::Listener) stream.
|
/// obtained from the [`Listener`](Transport::Listener) stream.
|
||||||
@ -110,12 +110,9 @@ pub trait Transport {
|
|||||||
/// obtained from [dialing](Transport::dial).
|
/// obtained from [dialing](Transport::dial).
|
||||||
type Dial: Future<Item = Self::Output, Error = Self::Error>;
|
type Dial: Future<Item = Self::Output, Error = Self::Error>;
|
||||||
|
|
||||||
/// Listens on the given [`Multiaddr`], producing a stream of pending, inbound connections.
|
/// Listens on the given [`Multiaddr`], producing a stream of pending, inbound connections
|
||||||
///
|
/// and addresses this transport is listening on (cf. [`ListenerEvent`]).
|
||||||
/// > **Note**: The new [`Multiaddr`] that is returned alongside the connection stream
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>>
|
||||||
/// > is the address that should be advertised to other nodes, as the given address
|
|
||||||
/// > may be subject to changes such as an OS-assigned port number.
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>>
|
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
@ -254,6 +251,80 @@ pub trait Transport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Event produced by [`Transport::Listener`]s.
|
||||||
|
///
|
||||||
|
/// Transports are expected to produce `Upgrade` events only for
|
||||||
|
/// listen addresses which have previously been announced via
|
||||||
|
/// a `NewAddress` event and which have not been invalidated by
|
||||||
|
/// an `AddressExpired` event yet.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum ListenerEvent<T> {
|
||||||
|
/// The transport is listening on a new additional [`Multiaddr`].
|
||||||
|
NewAddress(Multiaddr),
|
||||||
|
/// An upgrade, consisting of the upgrade future, the listener address and the remote address.
|
||||||
|
Upgrade {
|
||||||
|
/// The upgrade.
|
||||||
|
upgrade: T,
|
||||||
|
/// The listening address which produced this upgrade.
|
||||||
|
listen_addr: Multiaddr,
|
||||||
|
/// The remote address which produced this upgrade.
|
||||||
|
remote_addr: Multiaddr
|
||||||
|
},
|
||||||
|
/// A [`Multiaddr`] is no longer used for listening.
|
||||||
|
AddressExpired(Multiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ListenerEvent<T> {
|
||||||
|
/// In case this [`ListenerEvent`] is an upgrade, apply the given function
|
||||||
|
/// to the upgrade and multiaddress and produce another listener event
|
||||||
|
/// based the the function's result.
|
||||||
|
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ListenerEvent<U> {
|
||||||
|
match self {
|
||||||
|
ListenerEvent::Upgrade { upgrade, listen_addr, remote_addr } => {
|
||||||
|
ListenerEvent::Upgrade { upgrade: f(upgrade), listen_addr, remote_addr }
|
||||||
|
}
|
||||||
|
ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a),
|
||||||
|
ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to turn this listener event into upgrade parts.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the event is not actually an upgrade,
|
||||||
|
/// otherwise the upgrade and the remote address.
|
||||||
|
pub fn into_upgrade(self) -> Option<(T, Multiaddr)> {
|
||||||
|
if let ListenerEvent::Upgrade { upgrade, remote_addr, .. } = self {
|
||||||
|
Some((upgrade, remote_addr))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to turn this listener event into the `NewAddress` part.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the event is not actually a `NewAddress`,
|
||||||
|
/// otherwise the address.
|
||||||
|
pub fn into_new_address(self) -> Option<Multiaddr> {
|
||||||
|
if let ListenerEvent::NewAddress(a) = self {
|
||||||
|
Some(a)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to turn this listener event into the `AddressExpired` part.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the event is not actually a `AddressExpired`,
|
||||||
|
/// otherwise the address.
|
||||||
|
pub fn into_address_expired(self) -> Option<Multiaddr> {
|
||||||
|
if let ListenerEvent::AddressExpired(a) = self {
|
||||||
|
Some(a)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An error during [dialing][Transport::dial] or [listening][Transport::listen_on]
|
/// An error during [dialing][Transport::dial] or [listening][Transport::listen_on]
|
||||||
/// on a [`Transport`].
|
/// on a [`Transport`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
//! underlying `Transport`.
|
//! underlying `Transport`.
|
||||||
// TODO: add example
|
// TODO: add example
|
||||||
|
|
||||||
use crate::{Multiaddr, Transport, transport::TransportError};
|
use crate::{Multiaddr, Transport, transport::{TransportError, ListenerEvent}};
|
||||||
use futures::{try_ready, Async, Future, Poll, Stream};
|
use futures::{try_ready, Async, Future, Poll, Stream};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use std::{error, fmt, time::Duration};
|
use std::{error, fmt, time::Duration};
|
||||||
@ -86,8 +86,8 @@ where
|
|||||||
type ListenerUpgrade = TokioTimerMapErr<Timeout<InnerTrans::ListenerUpgrade>>;
|
type ListenerUpgrade = TokioTimerMapErr<Timeout<InnerTrans::ListenerUpgrade>>;
|
||||||
type Dial = TokioTimerMapErr<Timeout<InnerTrans::Dial>>;
|
type Dial = TokioTimerMapErr<Timeout<InnerTrans::Dial>>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let (listener, addr) = self.inner.listen_on(addr)
|
let listener = self.inner.listen_on(addr)
|
||||||
.map_err(|err| err.map(TransportTimeoutError::Other))?;
|
.map_err(|err| err.map(TransportTimeoutError::Other))?;
|
||||||
|
|
||||||
let listener = TimeoutListener {
|
let listener = TimeoutListener {
|
||||||
@ -95,7 +95,7 @@ where
|
|||||||
timeout: self.incoming_timeout,
|
timeout: self.incoming_timeout,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((listener, addr))
|
Ok(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
@ -121,18 +121,18 @@ pub struct TimeoutListener<InnerStream> {
|
|||||||
|
|
||||||
impl<InnerStream, O> Stream for TimeoutListener<InnerStream>
|
impl<InnerStream, O> Stream for TimeoutListener<InnerStream>
|
||||||
where
|
where
|
||||||
InnerStream: Stream<Item = (O, Multiaddr)>,
|
InnerStream: Stream<Item = ListenerEvent<O>>
|
||||||
{
|
{
|
||||||
type Item = (TokioTimerMapErr<Timeout<O>>, Multiaddr);
|
type Item = ListenerEvent<TokioTimerMapErr<Timeout<O>>>;
|
||||||
type Error = TransportTimeoutError<InnerStream::Error>;
|
type Error = TransportTimeoutError<InnerStream::Error>;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
let poll_out = try_ready!(self.inner.poll().map_err(TransportTimeoutError::Other));
|
let poll_out = try_ready!(self.inner.poll().map_err(TransportTimeoutError::Other));
|
||||||
if let Some((inner_fut, addr)) = poll_out {
|
if let Some(event) = poll_out {
|
||||||
let fut = TokioTimerMapErr {
|
let event = event.map(move |inner_fut| {
|
||||||
inner: Timeout::new(inner_fut, self.timeout),
|
TokioTimerMapErr { inner: Timeout::new(inner_fut, self.timeout) }
|
||||||
};
|
});
|
||||||
Ok(Async::Ready(Some((fut, addr))))
|
Ok(Async::Ready(Some(event)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Async::Ready(None))
|
Ok(Async::Ready(None))
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
transport::Transport,
|
transport::{Transport, TransportError, ListenerEvent},
|
||||||
transport::TransportError,
|
|
||||||
upgrade::{
|
upgrade::{
|
||||||
OutboundUpgrade,
|
OutboundUpgrade,
|
||||||
InboundUpgrade,
|
InboundUpgrade,
|
||||||
@ -69,10 +68,10 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let (inbound, addr) = self.inner.listen_on(addr)
|
let inbound = self.inner.listen_on(addr)
|
||||||
.map_err(|err| err.map(TransportUpgradeError::Transport))?;
|
.map_err(|err| err.map(TransportUpgradeError::Transport))?;
|
||||||
Ok((ListenerStream { stream: inbound, upgrade: self.upgrade }, addr))
|
Ok(ListenerStream { stream: inbound, upgrade: self.upgrade })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
@ -157,22 +156,24 @@ pub struct ListenerStream<T, U> {
|
|||||||
|
|
||||||
impl<T, U, F> Stream for ListenerStream<T, U>
|
impl<T, U, F> Stream for ListenerStream<T, U>
|
||||||
where
|
where
|
||||||
T: Stream<Item = (F, Multiaddr)>,
|
T: Stream<Item = ListenerEvent<F>>,
|
||||||
F: Future,
|
F: Future,
|
||||||
F::Item: AsyncRead + AsyncWrite,
|
F::Item: AsyncRead + AsyncWrite,
|
||||||
U: InboundUpgrade<F::Item> + Clone
|
U: InboundUpgrade<F::Item> + Clone
|
||||||
{
|
{
|
||||||
type Item = (ListenerUpgradeFuture<F, U>, Multiaddr);
|
type Item = ListenerEvent<ListenerUpgradeFuture<F, U>>;
|
||||||
type Error = TransportUpgradeError<T::Error, U::Error>;
|
type Error = TransportUpgradeError<T::Error, U::Error>;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
match try_ready!(self.stream.poll().map_err(TransportUpgradeError::Transport)) {
|
match try_ready!(self.stream.poll().map_err(TransportUpgradeError::Transport)) {
|
||||||
Some((x, a)) => {
|
Some(event) => {
|
||||||
let f = ListenerUpgradeFuture {
|
let event = event.map(move |x| {
|
||||||
future: x,
|
ListenerUpgradeFuture {
|
||||||
upgrade: Either::A(Some(self.upgrade.clone()))
|
future: x,
|
||||||
};
|
upgrade: Either::A(Some(self.upgrade.clone()))
|
||||||
Ok(Async::Ready(Some((f, a))))
|
}
|
||||||
|
});
|
||||||
|
Ok(Async::Ready(Some(event)))
|
||||||
}
|
}
|
||||||
None => Ok(Async::Ready(None))
|
None => Ok(Async::Ready(None))
|
||||||
}
|
}
|
||||||
|
@ -116,12 +116,19 @@ fn deny_incoming_connec() {
|
|||||||
RawSwarm::new(transport, local_public_key.into())
|
RawSwarm::new(transport, local_public_key.into())
|
||||||
};
|
};
|
||||||
|
|
||||||
let listen = swarm1.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
swarm1.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let address =
|
||||||
|
if let Async::Ready(RawSwarmEvent::NewListenerAddress { listen_addr, .. }) = swarm1.poll() {
|
||||||
|
listen_addr
|
||||||
|
} else {
|
||||||
|
panic!("Was expecting the listen address to be reported")
|
||||||
|
};
|
||||||
|
|
||||||
swarm2
|
swarm2
|
||||||
.peer(swarm1.local_peer_id().clone())
|
.peer(swarm1.local_peer_id().clone())
|
||||||
.into_not_connected().unwrap()
|
.into_not_connected().unwrap()
|
||||||
.connect(listen.clone(), TestHandler::default().into_node_handler_builder());
|
.connect(address.clone(), TestHandler::default().into_node_handler_builder());
|
||||||
|
|
||||||
let future = future::poll_fn(|| -> Poll<(), io::Error> {
|
let future = future::poll_fn(|| -> Poll<(), io::Error> {
|
||||||
match swarm1.poll() {
|
match swarm1.poll() {
|
||||||
@ -138,7 +145,7 @@ fn deny_incoming_connec() {
|
|||||||
error: RawSwarmReachError::Transport(_)
|
error: RawSwarmReachError::Transport(_)
|
||||||
}) => {
|
}) => {
|
||||||
assert_eq!(peer_id, *swarm1.local_peer_id());
|
assert_eq!(peer_id, *swarm1.local_peer_id());
|
||||||
assert_eq!(multiaddr, listen);
|
assert_eq!(multiaddr, address);
|
||||||
return Ok(Async::Ready(()));
|
return Ok(Async::Ready(()));
|
||||||
},
|
},
|
||||||
Async::Ready(_) => unreachable!(),
|
Async::Ready(_) => unreachable!(),
|
||||||
@ -181,8 +188,20 @@ fn dial_self() {
|
|||||||
RawSwarm::new(transport, local_public_key.into())
|
RawSwarm::new(transport, local_public_key.into())
|
||||||
};
|
};
|
||||||
|
|
||||||
let listen = swarm.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
swarm.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
||||||
swarm.dial(listen.clone(), TestHandler::default().into_node_handler_builder()).unwrap();
|
|
||||||
|
let (address, mut swarm) =
|
||||||
|
future::lazy(move || {
|
||||||
|
if let Async::Ready(RawSwarmEvent::NewListenerAddress { listen_addr, .. }) = swarm.poll() {
|
||||||
|
Ok::<_, void::Void>((listen_addr, swarm))
|
||||||
|
} else {
|
||||||
|
panic!("Was expecting the listen address to be reported")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.wait()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
swarm.dial(address.clone(), TestHandler::default().into_node_handler_builder()).unwrap();
|
||||||
|
|
||||||
let mut got_dial_err = false;
|
let mut got_dial_err = false;
|
||||||
let mut got_inc_err = false;
|
let mut got_inc_err = false;
|
||||||
@ -194,7 +213,7 @@ fn dial_self() {
|
|||||||
error: UnknownPeerDialErr::FoundLocalPeerId,
|
error: UnknownPeerDialErr::FoundLocalPeerId,
|
||||||
handler: _
|
handler: _
|
||||||
}) => {
|
}) => {
|
||||||
assert_eq!(multiaddr, listen);
|
assert_eq!(multiaddr, address);
|
||||||
assert!(!got_dial_err);
|
assert!(!got_dial_err);
|
||||||
got_dial_err = true;
|
got_dial_err = true;
|
||||||
if got_inc_err {
|
if got_inc_err {
|
||||||
@ -206,7 +225,7 @@ fn dial_self() {
|
|||||||
send_back_addr: _,
|
send_back_addr: _,
|
||||||
error: IncomingError::FoundLocalPeerId
|
error: IncomingError::FoundLocalPeerId
|
||||||
}) => {
|
}) => {
|
||||||
assert_eq!(listen_addr, listen);
|
assert_eq!(address, listen_addr);
|
||||||
assert!(!got_inc_err);
|
assert!(!got_inc_err);
|
||||||
got_inc_err = true;
|
got_inc_err = true;
|
||||||
if got_dial_err {
|
if got_dial_err {
|
||||||
@ -214,7 +233,7 @@ fn dial_self() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Async::Ready(RawSwarmEvent::IncomingConnection(inc)) => {
|
Async::Ready(RawSwarmEvent::IncomingConnection(inc)) => {
|
||||||
assert_eq!(*inc.listen_addr(), listen);
|
assert_eq!(*inc.listen_addr(), address);
|
||||||
inc.accept(TestHandler::default().into_node_handler_builder());
|
inc.accept(TestHandler::default().into_node_handler_builder());
|
||||||
},
|
},
|
||||||
Async::Ready(ev) => unreachable!("{:?}", ev),
|
Async::Ready(ev) => unreachable!("{:?}", ev),
|
||||||
|
@ -132,8 +132,29 @@ fn raw_swarm_simultaneous_connect() {
|
|||||||
RawSwarm::new(transport, local_public_key.into_peer_id())
|
RawSwarm::new(transport, local_public_key.into_peer_id())
|
||||||
};
|
};
|
||||||
|
|
||||||
let swarm1_listen = swarm1.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
swarm1.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
||||||
let swarm2_listen = swarm2.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
swarm2.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let (swarm1_listen_addr, swarm2_listen_addr, mut swarm1, mut swarm2) =
|
||||||
|
future::lazy(move || {
|
||||||
|
let swarm1_listen_addr =
|
||||||
|
if let Async::Ready(RawSwarmEvent::NewListenerAddress { listen_addr, .. }) = swarm1.poll() {
|
||||||
|
listen_addr
|
||||||
|
} else {
|
||||||
|
panic!("Was expecting the listen address to be reported")
|
||||||
|
};
|
||||||
|
|
||||||
|
let swarm2_listen_addr =
|
||||||
|
if let Async::Ready(RawSwarmEvent::NewListenerAddress { listen_addr, .. }) = swarm2.poll() {
|
||||||
|
listen_addr
|
||||||
|
} else {
|
||||||
|
panic!("Was expecting the listen address to be reported")
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok::<_, void::Void>((swarm1_listen_addr, swarm2_listen_addr, swarm1, swarm2))
|
||||||
|
})
|
||||||
|
.wait()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut reactor = tokio::runtime::current_thread::Runtime::new().unwrap();
|
let mut reactor = tokio::runtime::current_thread::Runtime::new().unwrap();
|
||||||
|
|
||||||
@ -157,7 +178,7 @@ fn raw_swarm_simultaneous_connect() {
|
|||||||
Async::Ready(_) => {
|
Async::Ready(_) => {
|
||||||
let handler = TestHandler::default().into_node_handler_builder();
|
let handler = TestHandler::default().into_node_handler_builder();
|
||||||
swarm1.peer(swarm2.local_peer_id().clone()).into_not_connected().unwrap()
|
swarm1.peer(swarm2.local_peer_id().clone()).into_not_connected().unwrap()
|
||||||
.connect(swarm2_listen.clone(), handler);
|
.connect(swarm2_listen_addr.clone(), handler);
|
||||||
swarm1_step = 1;
|
swarm1_step = 1;
|
||||||
swarm1_not_ready = false;
|
swarm1_not_ready = false;
|
||||||
},
|
},
|
||||||
@ -170,7 +191,7 @@ fn raw_swarm_simultaneous_connect() {
|
|||||||
Async::Ready(_) => {
|
Async::Ready(_) => {
|
||||||
let handler = TestHandler::default().into_node_handler_builder();
|
let handler = TestHandler::default().into_node_handler_builder();
|
||||||
swarm2.peer(swarm1.local_peer_id().clone()).into_not_connected().unwrap()
|
swarm2.peer(swarm1.local_peer_id().clone()).into_not_connected().unwrap()
|
||||||
.connect(swarm1_listen.clone(), handler);
|
.connect(swarm1_listen_addr.clone(), handler);
|
||||||
swarm2_step = 1;
|
swarm2_step = 1;
|
||||||
swarm2_not_ready = false;
|
swarm2_not_ready = false;
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use libp2p_core::{muxing, Transport};
|
use libp2p_core::{muxing, Transport, transport::ListenerEvent};
|
||||||
use libp2p_tcp::TcpConfig;
|
use libp2p_tcp::TcpConfig;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use std::sync::{Arc, mpsc};
|
use std::sync::{Arc, mpsc};
|
||||||
@ -38,12 +38,21 @@ fn client_to_server_outbound() {
|
|||||||
let transport =
|
let transport =
|
||||||
TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
||||||
|
|
||||||
let (listener, addr) = transport
|
let mut listener = transport
|
||||||
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let addr = listener.by_ref().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
tx.send(addr).unwrap();
|
tx.send(addr).unwrap();
|
||||||
|
|
||||||
let future = listener
|
let future = listener
|
||||||
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(err, _)| panic!("{:?}", err))
|
.map_err(|(err, _)| panic!("{:?}", err))
|
||||||
.and_then(|(client, _)| client.unwrap().0)
|
.and_then(|(client, _)| client.unwrap().0)
|
||||||
@ -69,7 +78,7 @@ fn client_to_server_outbound() {
|
|||||||
let transport = TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
let transport = TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
||||||
|
|
||||||
let future = transport
|
let future = transport
|
||||||
.dial(rx.recv().unwrap())
|
.dial(rx.recv().unwrap().clone())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map_err(|err| panic!("{:?}", err))
|
.map_err(|err| panic!("{:?}", err))
|
||||||
.and_then(|client| muxing::inbound_from_ref_and_wrap(Arc::new(client)))
|
.and_then(|client| muxing::inbound_from_ref_and_wrap(Arc::new(client)))
|
||||||
@ -92,12 +101,22 @@ fn client_to_server_inbound() {
|
|||||||
let transport =
|
let transport =
|
||||||
TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
||||||
|
|
||||||
let (listener, addr) = transport
|
let mut listener = transport
|
||||||
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let addr = listener.by_ref().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
|
|
||||||
tx.send(addr).unwrap();
|
tx.send(addr).unwrap();
|
||||||
|
|
||||||
let future = listener
|
let future = listener
|
||||||
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(err, _)| panic!("{:?}", err))
|
.map_err(|(err, _)| panic!("{:?}", err))
|
||||||
.and_then(|(client, _)| client.unwrap().0)
|
.and_then(|(client, _)| client.unwrap().0)
|
||||||
@ -123,7 +142,7 @@ fn client_to_server_inbound() {
|
|||||||
let transport = TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
let transport = TcpConfig::new().with_upgrade(libp2p_mplex::MplexConfig::new());
|
||||||
|
|
||||||
let future = transport
|
let future = transport
|
||||||
.dial(rx.recv().unwrap())
|
.dial(rx.recv().unwrap().clone())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map_err(|err| panic!("{:?}", err))
|
.map_err(|err| panic!("{:?}", err))
|
||||||
.and_then(|client| muxing::outbound_from_ref_and_wrap(Arc::new(client)))
|
.and_then(|client| muxing::outbound_from_ref_and_wrap(Arc::new(client)))
|
||||||
|
@ -29,4 +29,5 @@ void = "1.0"
|
|||||||
libp2p-mplex = { version = "0.6.0", path = "../../muxers/mplex" }
|
libp2p-mplex = { version = "0.6.0", path = "../../muxers/mplex" }
|
||||||
libp2p-secio = { version = "0.6.0", path = "../../protocols/secio" }
|
libp2p-secio = { version = "0.6.0", path = "../../protocols/secio" }
|
||||||
libp2p-tcp = { version = "0.6.0", path = "../../transports/tcp" }
|
libp2p-tcp = { version = "0.6.0", path = "../../transports/tcp" }
|
||||||
|
rand = "0.6"
|
||||||
tokio = "0.1"
|
tokio = "0.1"
|
||||||
|
@ -24,7 +24,7 @@ use crate::protocol::{RemoteInfo, IdentifyProtocolConfig};
|
|||||||
use futures::{future, prelude::*, stream, AndThen, MapErr};
|
use futures::{future, prelude::*, stream, AndThen, MapErr};
|
||||||
use libp2p_core::{
|
use libp2p_core::{
|
||||||
Multiaddr, PeerId, PublicKey, muxing, Transport,
|
Multiaddr, PeerId, PublicKey, muxing, Transport,
|
||||||
transport::{TransportError, upgrade::TransportUpgradeError},
|
transport::{TransportError, ListenerEvent, upgrade::TransportUpgradeError},
|
||||||
upgrade::{self, OutboundUpgradeApply, UpgradeError}
|
upgrade::{self, OutboundUpgradeApply, UpgradeError}
|
||||||
};
|
};
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
@ -66,7 +66,7 @@ where
|
|||||||
{
|
{
|
||||||
type Output = (PeerId, TMuxer);
|
type Output = (PeerId, TMuxer);
|
||||||
type Error = TransportUpgradeError<TTrans::Error, IoError>; // TODO: better than IoError
|
type Error = TransportUpgradeError<TTrans::Error, IoError>; // TODO: better than IoError
|
||||||
type Listener = stream::Empty<(Self::ListenerUpgrade, Multiaddr), Self::Error>;
|
type Listener = stream::Empty<ListenerEvent<Self::ListenerUpgrade>, Self::Error>;
|
||||||
type ListenerUpgrade = future::Empty<Self::Output, Self::Error>;
|
type ListenerUpgrade = future::Empty<Self::Output, Self::Error>;
|
||||||
type Dial = AndThen<
|
type Dial = AndThen<
|
||||||
MapErr<TTrans::Dial, fn(TTrans::Error) -> Self::Error>,
|
MapErr<TTrans::Dial, fn(TTrans::Error) -> Self::Error>,
|
||||||
@ -75,7 +75,7 @@ where
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
Err(TransportError::MultiaddrNotSupported(addr))
|
Err(TransportError::MultiaddrNotSupported(addr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +222,13 @@ mod tests {
|
|||||||
use crate::{Identify, IdentifyEvent};
|
use crate::{Identify, IdentifyEvent};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use libp2p_core::identity;
|
use libp2p_core::identity;
|
||||||
use libp2p_core::{upgrade, upgrade::OutboundUpgradeExt, upgrade::InboundUpgradeExt, Swarm, Transport};
|
use libp2p_core::{
|
||||||
|
upgrade::{self, OutboundUpgradeExt, InboundUpgradeExt},
|
||||||
|
Multiaddr,
|
||||||
|
Swarm,
|
||||||
|
Transport
|
||||||
|
};
|
||||||
|
use rand::Rng;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -270,8 +276,13 @@ mod tests {
|
|||||||
Swarm::new(transport, Identify::new("c".to_string(), "d".to_string(), node2_public_key.clone()), local_peer_id)
|
Swarm::new(transport, Identify::new("c".to_string(), "d".to_string(), node2_public_key.clone()), local_peer_id)
|
||||||
};
|
};
|
||||||
|
|
||||||
let actual_addr = Swarm::listen_on(&mut swarm1, "/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
let addr: Multiaddr = {
|
||||||
Swarm::dial_addr(&mut swarm2, actual_addr).unwrap();
|
let port = rand::thread_rng().gen_range(49152, std::u16::MAX);
|
||||||
|
format!("/ip4/127.0.0.1/tcp/{}", port).parse().unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
Swarm::listen_on(&mut swarm1, addr.clone()).unwrap();
|
||||||
|
Swarm::dial_addr(&mut swarm2, addr).unwrap();
|
||||||
|
|
||||||
let mut swarm1_good = false;
|
let mut swarm1_good = false;
|
||||||
let mut swarm2_good = false;
|
let mut swarm2_good = false;
|
||||||
|
@ -271,7 +271,12 @@ mod tests {
|
|||||||
use tokio::runtime::current_thread::Runtime;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
use libp2p_tcp::TcpConfig;
|
use libp2p_tcp::TcpConfig;
|
||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
use libp2p_core::{identity, Transport, upgrade::{apply_outbound, apply_inbound}};
|
use libp2p_core::{
|
||||||
|
identity,
|
||||||
|
Transport,
|
||||||
|
transport::ListenerEvent,
|
||||||
|
upgrade::{apply_outbound, apply_inbound}
|
||||||
|
};
|
||||||
use std::{io, sync::mpsc, thread};
|
use std::{io, sync::mpsc, thread};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -286,13 +291,22 @@ mod tests {
|
|||||||
let bg_thread = thread::spawn(move || {
|
let bg_thread = thread::spawn(move || {
|
||||||
let transport = TcpConfig::new();
|
let transport = TcpConfig::new();
|
||||||
|
|
||||||
let (listener, addr) = transport
|
let mut listener = transport
|
||||||
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let addr = listener.by_ref().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
|
|
||||||
tx.send(addr).unwrap();
|
tx.send(addr).unwrap();
|
||||||
|
|
||||||
let future = listener
|
let future = listener
|
||||||
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(err, _)| err)
|
.map_err(|(err, _)| err)
|
||||||
.and_then(|(client, _)| client.unwrap().0)
|
.and_then(|(client, _)| client.unwrap().0)
|
||||||
@ -321,7 +335,7 @@ mod tests {
|
|||||||
|
|
||||||
let transport = TcpConfig::new();
|
let transport = TcpConfig::new();
|
||||||
|
|
||||||
let future = transport.dial(rx.recv().unwrap())
|
let future = transport.dial(rx.recv().unwrap().clone())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.and_then(|socket| {
|
.and_then(|socket| {
|
||||||
apply_outbound(socket, IdentifyProtocolConfig)
|
apply_outbound(socket, IdentifyProtocolConfig)
|
||||||
|
@ -22,13 +22,19 @@
|
|||||||
|
|
||||||
use crate::{Kademlia, KademliaOut};
|
use crate::{Kademlia, KademliaOut};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use libp2p_core::{upgrade, upgrade::InboundUpgradeExt, upgrade::OutboundUpgradeExt, PeerId, Swarm, Transport};
|
use libp2p_core::{
|
||||||
|
multiaddr::Protocol,
|
||||||
|
upgrade::{self, InboundUpgradeExt, OutboundUpgradeExt},
|
||||||
|
PeerId,
|
||||||
|
Swarm,
|
||||||
|
Transport
|
||||||
|
};
|
||||||
use libp2p_core::{nodes::Substream, transport::boxed::Boxed, muxing::StreamMuxerBox};
|
use libp2p_core::{nodes::Substream, transport::boxed::Boxed, muxing::StreamMuxerBox};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
/// Builds swarms, each listening on a port. Does *not* connect the nodes together.
|
/// Builds swarms, each listening on a port. Does *not* connect the nodes together.
|
||||||
/// This is to be used only for testing, and a panic will happen if something goes wrong.
|
/// This is to be used only for testing, and a panic will happen if something goes wrong.
|
||||||
fn build_nodes(num: usize)
|
fn build_nodes(port_base: u64, num: usize)
|
||||||
-> Vec<Swarm<Boxed<(PeerId, StreamMuxerBox), io::Error>, Kademlia<Substream<StreamMuxerBox>>>>
|
-> Vec<Swarm<Boxed<(PeerId, StreamMuxerBox), io::Error>, Kademlia<Substream<StreamMuxerBox>>>>
|
||||||
{
|
{
|
||||||
let mut result: Vec<Swarm<_, _>> = Vec::with_capacity(num);
|
let mut result: Vec<Swarm<_, _>> = Vec::with_capacity(num);
|
||||||
@ -38,7 +44,7 @@ fn build_nodes(num: usize)
|
|||||||
// is about creating the transport
|
// is about creating the transport
|
||||||
let local_key = libp2p_core::identity::Keypair::generate_ed25519();
|
let local_key = libp2p_core::identity::Keypair::generate_ed25519();
|
||||||
let local_public_key = local_key.public();
|
let local_public_key = local_key.public();
|
||||||
let transport = libp2p_tcp::TcpConfig::new()
|
let transport = libp2p_core::transport::MemoryTransport::default()
|
||||||
.with_upgrade(libp2p_secio::SecioConfig::new(local_key))
|
.with_upgrade(libp2p_secio::SecioConfig::new(local_key))
|
||||||
.and_then(move |out, endpoint| {
|
.and_then(move |out, endpoint| {
|
||||||
let peer_id = out.remote_key.into_peer_id();
|
let peer_id = out.remote_key.into_peer_id();
|
||||||
@ -49,15 +55,17 @@ fn build_nodes(num: usize)
|
|||||||
upgrade::apply(out.stream, upgrade, endpoint)
|
upgrade::apply(out.stream, upgrade, endpoint)
|
||||||
.map(|(id, muxer)| (id, StreamMuxerBox::new(muxer)))
|
.map(|(id, muxer)| (id, StreamMuxerBox::new(muxer)))
|
||||||
})
|
})
|
||||||
.map_err(|_| panic!())
|
.map_err(|e| panic!("Failed to create transport: {:?}", e))
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let kad = Kademlia::without_init(local_public_key.clone().into_peer_id());
|
let kad = Kademlia::without_init(local_public_key.clone().into_peer_id());
|
||||||
result.push(Swarm::new(transport, kad, local_public_key.into_peer_id()));
|
result.push(Swarm::new(transport, kad, local_public_key.into_peer_id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
for s in result.iter_mut() {
|
for s in result.iter_mut() {
|
||||||
Swarm::listen_on(s, "/ip4/127.0.0.1/tcp/0".parse().unwrap()).unwrap();
|
Swarm::listen_on(s, Protocol::Memory(port_base + i).into()).unwrap();
|
||||||
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
@ -68,14 +76,12 @@ fn basic_find_node() {
|
|||||||
// Build two nodes. Node #2 only knows about node #1. Node #2 is asked for a random peer ID.
|
// Build two nodes. Node #2 only knows about node #1. Node #2 is asked for a random peer ID.
|
||||||
// Node #2 must return the identity of node #1.
|
// Node #2 must return the identity of node #1.
|
||||||
|
|
||||||
let mut swarms = build_nodes(2);
|
let port_base = rand::random();
|
||||||
|
let mut swarms = build_nodes(port_base, 2);
|
||||||
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
||||||
|
|
||||||
// Connect second to first.
|
// Connect second to first.
|
||||||
{
|
swarms[1].add_not_connected_address(&first_peer_id, Protocol::Memory(port_base).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[0]).next().unwrap().clone();
|
|
||||||
swarms[1].add_not_connected_address(&first_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let search_target = PeerId::random();
|
let search_target = PeerId::random();
|
||||||
swarms[1].find_node(search_target.clone());
|
swarms[1].find_node(search_target.clone());
|
||||||
@ -108,22 +114,17 @@ fn direct_query() {
|
|||||||
// Build three nodes. Node #2 knows about node #1. Node #3 knows about node #2. Node #3 is
|
// Build three nodes. Node #2 knows about node #1. Node #3 knows about node #2. Node #3 is
|
||||||
// asked about a random peer and should return nodes #1 and #2.
|
// asked about a random peer and should return nodes #1 and #2.
|
||||||
|
|
||||||
let mut swarms = build_nodes(3);
|
let port_base = rand::random::<u64>() % (std::u64::MAX - 1);
|
||||||
|
let mut swarms = build_nodes(port_base, 3);
|
||||||
|
|
||||||
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
||||||
let second_peer_id = Swarm::local_peer_id(&swarms[1]).clone();
|
let second_peer_id = Swarm::local_peer_id(&swarms[1]).clone();
|
||||||
|
|
||||||
// Connect second to first.
|
// Connect second to first.
|
||||||
{
|
swarms[1].add_not_connected_address(&first_peer_id, Protocol::Memory(port_base).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[0]).next().unwrap().clone();
|
|
||||||
swarms[1].add_not_connected_address(&first_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect third to second.
|
// Connect third to second.
|
||||||
{
|
swarms[2].add_not_connected_address(&second_peer_id, Protocol::Memory(port_base + 1).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[1]).next().unwrap().clone();
|
|
||||||
swarms[2].add_not_connected_address(&second_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask third to search a random value.
|
// Ask third to search a random value.
|
||||||
let search_target = PeerId::random();
|
let search_target = PeerId::random();
|
||||||
@ -158,29 +159,21 @@ fn indirect_query() {
|
|||||||
// Build four nodes. Node #2 knows about node #1. Node #3 knows about node #2. Node #4 knows
|
// Build four nodes. Node #2 knows about node #1. Node #3 knows about node #2. Node #4 knows
|
||||||
// about node #3. Node #4 is asked about a random peer and should return nodes #1, #2 and #3.
|
// about node #3. Node #4 is asked about a random peer and should return nodes #1, #2 and #3.
|
||||||
|
|
||||||
let mut swarms = build_nodes(4);
|
let port_base = rand::random::<u64>() % (std::u64::MAX - 2);
|
||||||
|
let mut swarms = build_nodes(port_base, 4);
|
||||||
|
|
||||||
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
||||||
let second_peer_id = Swarm::local_peer_id(&swarms[1]).clone();
|
let second_peer_id = Swarm::local_peer_id(&swarms[1]).clone();
|
||||||
let third_peer_id = Swarm::local_peer_id(&swarms[2]).clone();
|
let third_peer_id = Swarm::local_peer_id(&swarms[2]).clone();
|
||||||
|
|
||||||
// Connect second to first.
|
// Connect second to first.
|
||||||
{
|
swarms[1].add_not_connected_address(&first_peer_id, Protocol::Memory(port_base).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[0]).next().unwrap().clone();
|
|
||||||
swarms[1].add_not_connected_address(&first_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect third to second.
|
// Connect third to second.
|
||||||
{
|
swarms[2].add_not_connected_address(&second_peer_id, Protocol::Memory(port_base + 1).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[1]).next().unwrap().clone();
|
|
||||||
swarms[2].add_not_connected_address(&second_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect fourth to third.
|
// Connect fourth to third.
|
||||||
{
|
swarms[3].add_not_connected_address(&third_peer_id, Protocol::Memory(port_base + 2).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[2]).next().unwrap().clone();
|
|
||||||
swarms[3].add_not_connected_address(&third_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask fourth to search a random value.
|
// Ask fourth to search a random value.
|
||||||
let search_target = PeerId::random();
|
let search_target = PeerId::random();
|
||||||
@ -216,7 +209,8 @@ fn unresponsive_not_returned_direct() {
|
|||||||
// Build one node. It contains fake addresses to non-existing nodes. We ask it to find a
|
// Build one node. It contains fake addresses to non-existing nodes. We ask it to find a
|
||||||
// random peer. We make sure that no fake address is returned.
|
// random peer. We make sure that no fake address is returned.
|
||||||
|
|
||||||
let mut swarms = build_nodes(1);
|
let port_base = rand::random();
|
||||||
|
let mut swarms = build_nodes(port_base, 1);
|
||||||
|
|
||||||
// Add fake addresses.
|
// Add fake addresses.
|
||||||
for _ in 0 .. 10 {
|
for _ in 0 .. 10 {
|
||||||
@ -258,7 +252,8 @@ fn unresponsive_not_returned_indirect() {
|
|||||||
// non-existing nodes. We ask node #1 to find a random peer. We make sure that no fake address
|
// non-existing nodes. We ask node #1 to find a random peer. We make sure that no fake address
|
||||||
// is returned.
|
// is returned.
|
||||||
|
|
||||||
let mut swarms = build_nodes(2);
|
let port_base = rand::random();
|
||||||
|
let mut swarms = build_nodes(port_base, 2);
|
||||||
|
|
||||||
// Add fake addresses to first.
|
// Add fake addresses to first.
|
||||||
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
let first_peer_id = Swarm::local_peer_id(&swarms[0]).clone();
|
||||||
@ -270,10 +265,7 @@ fn unresponsive_not_returned_indirect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect second to first.
|
// Connect second to first.
|
||||||
{
|
swarms[1].add_not_connected_address(&first_peer_id, Protocol::Memory(port_base).into());
|
||||||
let listen_addr = Swarm::listeners(&swarms[0]).next().unwrap().clone();
|
|
||||||
swarms[1].add_not_connected_address(&first_peer_id, listen_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask second to search a random value.
|
// Ask second to search a random value.
|
||||||
let search_target = PeerId::random();
|
let search_target = PeerId::random();
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use futures::{future::Either, prelude::*};
|
use futures::{future::Either, prelude::*};
|
||||||
use libp2p_core::{Transport, upgrade::{apply_inbound, apply_outbound}};
|
use libp2p_core::{Transport, transport::ListenerEvent, upgrade::{apply_inbound, apply_outbound}};
|
||||||
use libp2p_noise::{Keypair, X25519, NoiseConfig};
|
use libp2p_noise::{Keypair, X25519, NoiseConfig};
|
||||||
use libp2p_tcp::TcpConfig;
|
use libp2p_tcp::TcpConfig;
|
||||||
use log::info;
|
use log::info;
|
||||||
@ -106,11 +106,19 @@ where
|
|||||||
{
|
{
|
||||||
let message2 = message1.clone();
|
let message2 = message1.clone();
|
||||||
|
|
||||||
let (server, server_address) = server_transport
|
let mut server = server_transport
|
||||||
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
.listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let server_address = server.by_ref().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
let server = server.take(1)
|
let server = server.take(1)
|
||||||
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
.and_then(|client| client.0)
|
.and_then(|client| client.0)
|
||||||
.map_err(|e| panic!("server error: {}", e))
|
.map_err(|e| panic!("server error: {}", e))
|
||||||
.and_then(|(_, client)| {
|
.and_then(|(_, client)| {
|
||||||
@ -122,7 +130,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
||||||
let client = client_transport.dial(server_address).unwrap()
|
let client = client_transport.dial(server_address.clone()).unwrap()
|
||||||
.map_err(|e| panic!("client error: {}", e))
|
.map_err(|e| panic!("client error: {}", e))
|
||||||
.and_then(move |(_, server)| {
|
.and_then(move |(_, server)| {
|
||||||
io::write_all(server, message2).and_then(|(client, _)| io::flush(client))
|
io::write_all(server, message2).and_then(|(client, _)| io::flush(client))
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::{Multiaddr, core::Transport, core::transport::TransportError};
|
use crate::{Multiaddr, core::{Transport, transport::{ListenerEvent, TransportError}}};
|
||||||
use futures::{prelude::*, try_ready};
|
use futures::{prelude::*, try_ready};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@ -65,21 +65,18 @@ where
|
|||||||
type ListenerUpgrade = BandwidthFuture<TInner::ListenerUpgrade>;
|
type ListenerUpgrade = BandwidthFuture<TInner::ListenerUpgrade>;
|
||||||
type Dial = BandwidthFuture<TInner::Dial>;
|
type Dial = BandwidthFuture<TInner::Dial>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let sinks = self.sinks;
|
let sinks = self.sinks;
|
||||||
self.inner
|
self.inner
|
||||||
.listen_on(addr)
|
.listen_on(addr)
|
||||||
.map(|(inner, new_addr)| (BandwidthListener { inner, sinks }, new_addr))
|
.map(move |inner| BandwidthListener { inner, sinks })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
let sinks = self.sinks;
|
let sinks = self.sinks;
|
||||||
self.inner
|
self.inner
|
||||||
.dial(addr)
|
.dial(addr)
|
||||||
.map(move |fut| BandwidthFuture {
|
.map(move |fut| BandwidthFuture { inner: fut, sinks })
|
||||||
inner: fut,
|
|
||||||
sinks,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||||
@ -95,23 +92,23 @@ pub struct BandwidthListener<TInner> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<TInner, TConn> Stream for BandwidthListener<TInner>
|
impl<TInner, TConn> Stream for BandwidthListener<TInner>
|
||||||
where TInner: Stream<Item = (TConn, Multiaddr)>,
|
where
|
||||||
|
TInner: Stream<Item = ListenerEvent<TConn>>,
|
||||||
{
|
{
|
||||||
type Item = (BandwidthFuture<TConn>, Multiaddr);
|
type Item = ListenerEvent<BandwidthFuture<TConn>>;
|
||||||
type Error = TInner::Error;
|
type Error = TInner::Error;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
let (inner, addr) = match try_ready!(self.inner.poll()) {
|
let event = match try_ready!(self.inner.poll()) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return Ok(Async::Ready(None))
|
None => return Ok(Async::Ready(None))
|
||||||
};
|
};
|
||||||
|
|
||||||
let fut = BandwidthFuture {
|
let event = event.map(|inner| {
|
||||||
inner,
|
BandwidthFuture { inner, sinks: self.sinks.clone() }
|
||||||
sinks: self.sinks.clone(),
|
});
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Async::Ready(Some((fut, addr))))
|
Ok(Async::Ready(Some(event)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ impl Transport for CommonTransport {
|
|||||||
type Dial = <InnerImplementation as Transport>::Dial;
|
type Dial = <InnerImplementation as Transport>::Dial;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
self.inner.inner.listen_on(addr)
|
self.inner.inner.listen_on(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,13 +33,11 @@
|
|||||||
//! replaced with respectively an `/ip4/` or an `/ip6/` component.
|
//! replaced with respectively an `/ip4/` or an `/ip6/` component.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use libp2p_core as swarm;
|
|
||||||
|
|
||||||
use futures::{future::{self, Either, FutureResult, JoinAll}, prelude::*, stream, try_ready};
|
use futures::{future::{self, Either, FutureResult, JoinAll}, prelude::*, stream, try_ready};
|
||||||
|
use libp2p_core::{Transport, transport::{TransportError, ListenerEvent}};
|
||||||
use log::{debug, trace, log_enabled, Level};
|
use log::{debug, trace, log_enabled, Level};
|
||||||
use multiaddr::{Protocol, Multiaddr};
|
use multiaddr::{Protocol, Multiaddr};
|
||||||
use std::{error, fmt, io, marker::PhantomData, net::IpAddr};
|
use std::{error, fmt, io, marker::PhantomData, net::IpAddr};
|
||||||
use swarm::{Transport, transport::TransportError};
|
|
||||||
use tokio_dns::{CpuPoolResolver, Resolver};
|
use tokio_dns::{CpuPoolResolver, Resolver};
|
||||||
|
|
||||||
/// Represents the configuration for a DNS transport capability of libp2p.
|
/// Represents the configuration for a DNS transport capability of libp2p.
|
||||||
@ -93,7 +91,7 @@ where
|
|||||||
type Error = DnsErr<T::Error>;
|
type Error = DnsErr<T::Error>;
|
||||||
type Listener = stream::MapErr<
|
type Listener = stream::MapErr<
|
||||||
stream::Map<T::Listener,
|
stream::Map<T::Listener,
|
||||||
fn((T::ListenerUpgrade, Multiaddr)) -> (Self::ListenerUpgrade, Multiaddr)>,
|
fn(ListenerEvent<T::ListenerUpgrade>) -> ListenerEvent<Self::ListenerUpgrade>>,
|
||||||
fn(T::Error) -> Self::Error>;
|
fn(T::Error) -> Self::Error>;
|
||||||
type ListenerUpgrade = future::MapErr<T::ListenerUpgrade, fn(T::Error) -> Self::Error>;
|
type ListenerUpgrade = future::MapErr<T::ListenerUpgrade, fn(T::Error) -> Self::Error>;
|
||||||
type Dial = Either<future::MapErr<T::Dial, fn(T::Error) -> Self::Error>,
|
type Dial = Either<future::MapErr<T::Dial, fn(T::Error) -> Self::Error>,
|
||||||
@ -103,14 +101,14 @@ where
|
|||||||
>>
|
>>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
#[inline]
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
let listener = self.inner.listen_on(addr).map_err(|err| err.map(DnsErr::Underlying))?;
|
||||||
let (listener, new_addr) = self.inner.listen_on(addr)
|
|
||||||
.map_err(|err| err.map(DnsErr::Underlying))?;
|
|
||||||
let listener = listener
|
let listener = listener
|
||||||
.map::<_, fn(_) -> _>(|(upgr, multiaddr)| (upgr.map_err::<fn(_) -> _, _>(DnsErr::Underlying), multiaddr))
|
.map::<_, fn(_) -> _>(|event| event.map(|upgr| {
|
||||||
|
upgr.map_err::<fn(_) -> _, _>(DnsErr::Underlying)
|
||||||
|
}))
|
||||||
.map_err::<_, fn(_) -> _>(DnsErr::Underlying);
|
.map_err::<_, fn(_) -> _>(DnsErr::Underlying);
|
||||||
Ok((listener, new_addr))
|
Ok(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
@ -318,7 +316,7 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use libp2p_tcp::TcpConfig;
|
use libp2p_tcp::TcpConfig;
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use super::swarm::{Transport, transport::TransportError};
|
use libp2p_core::{Transport, transport::TransportError};
|
||||||
use multiaddr::{Protocol, Multiaddr};
|
use multiaddr::{Protocol, Multiaddr};
|
||||||
use super::DnsConfig;
|
use super::DnsConfig;
|
||||||
|
|
||||||
@ -337,7 +335,7 @@ mod tests {
|
|||||||
fn listen_on(
|
fn listen_on(
|
||||||
self,
|
self,
|
||||||
_addr: Multiaddr,
|
_addr: Multiaddr,
|
||||||
) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
use aio_limited::{Limited, Limiter};
|
use aio_limited::{Limited, Limiter};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use futures::try_ready;
|
use futures::try_ready;
|
||||||
use libp2p_core::{Multiaddr, Transport, transport::TransportError};
|
use libp2p_core::{Multiaddr, Transport, transport::{ListenerEvent, TransportError}};
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::{error, fmt, io};
|
use std::{error, fmt, io};
|
||||||
use tokio_executor::Executor;
|
use tokio_executor::Executor;
|
||||||
@ -143,16 +143,18 @@ impl<C: AsyncRead + AsyncWrite> AsyncWrite for Connection<C> {
|
|||||||
pub struct Listener<T: Transport>(RateLimited<T::Listener>);
|
pub struct Listener<T: Transport>(RateLimited<T::Listener>);
|
||||||
|
|
||||||
impl<T: Transport> Stream for Listener<T> {
|
impl<T: Transport> Stream for Listener<T> {
|
||||||
type Item = (ListenerUpgrade<T>, Multiaddr);
|
type Item = ListenerEvent<ListenerUpgrade<T>>;
|
||||||
type Error = RateLimitedErr<T::Error>;
|
type Error = RateLimitedErr<T::Error>;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
match try_ready!(self.0.value.poll().map_err(RateLimitedErr::Underlying)) {
|
match try_ready!(self.0.value.poll().map_err(RateLimitedErr::Underlying)) {
|
||||||
Some((upgrade, addr)) => {
|
Some(event) => {
|
||||||
let r = self.0.rlimiter.clone();
|
let event = event.map(|upgrade| {
|
||||||
let w = self.0.wlimiter.clone();
|
let r = self.0.rlimiter.clone();
|
||||||
let u = ListenerUpgrade(RateLimited::from_parts(upgrade, r, w));
|
let w = self.0.wlimiter.clone();
|
||||||
Ok(Async::Ready(Some((u, addr))))
|
ListenerUpgrade(RateLimited::from_parts(upgrade, r, w))
|
||||||
|
});
|
||||||
|
Ok(Async::Ready(Some(event)))
|
||||||
}
|
}
|
||||||
None => Ok(Async::Ready(None)),
|
None => Ok(Async::Ready(None)),
|
||||||
}
|
}
|
||||||
@ -190,17 +192,14 @@ where
|
|||||||
type ListenerUpgrade = ListenerUpgrade<T>;
|
type ListenerUpgrade = ListenerUpgrade<T>;
|
||||||
type Dial = DialFuture<T::Dial>;
|
type Dial = DialFuture<T::Dial>;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
let r = self.rlimiter;
|
let r = self.rlimiter;
|
||||||
let w = self.wlimiter;
|
let w = self.wlimiter;
|
||||||
self.value
|
self.value
|
||||||
.listen_on(addr)
|
.listen_on(addr)
|
||||||
.map_err(|err| err.map(RateLimitedErr::Underlying))
|
.map_err(|err| err.map(RateLimitedErr::Underlying))
|
||||||
.map(|(listener, a)| {
|
.map(|listener| {
|
||||||
(
|
Listener(RateLimited::from_parts(listener, r.clone(), w.clone()))
|
||||||
Listener(RateLimited::from_parts(listener, r.clone(), w.clone())),
|
|
||||||
a,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,14 +39,13 @@
|
|||||||
//! documentation of `swarm` and of libp2p in general to learn how to use the `Transport` trait.
|
//! documentation of `swarm` and of libp2p in general to learn how to use the `Transport` trait.
|
||||||
|
|
||||||
use futures::{future, future::FutureResult, prelude::*, Async, Poll};
|
use futures::{future, future::FutureResult, prelude::*, Async, Poll};
|
||||||
use libp2p_core as swarm;
|
use libp2p_core::{Transport, transport::{ListenerEvent, TransportError}};
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use multiaddr::{Protocol, Multiaddr, ToMultiaddr};
|
use multiaddr::{Protocol, Multiaddr, ToMultiaddr};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use swarm::{Transport, transport::TransportError};
|
|
||||||
use tk_listen::{ListenExt, SleepOnError};
|
use tk_listen::{ListenExt, SleepOnError};
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_tcp::{ConnectFuture, Incoming, TcpListener, TcpStream};
|
use tokio_tcp::{ConnectFuture, Incoming, TcpListener, TcpStream};
|
||||||
@ -128,37 +127,34 @@ impl Transport for TcpConfig {
|
|||||||
type ListenerUpgrade = FutureResult<Self::Output, io::Error>;
|
type ListenerUpgrade = FutureResult<Self::Output, io::Error>;
|
||||||
type Dial = TcpDialFut;
|
type Dial = TcpDialFut;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
if let Ok(socket_addr) = multiaddr_to_socketaddr(&addr) {
|
if let Ok(socket_addr) = multiaddr_to_socketaddr(&addr) {
|
||||||
let listener = TcpListener::bind(&socket_addr);
|
let listener = TcpListener::bind(&socket_addr);
|
||||||
// We need to build the `Multiaddr` to return from this function. If an error happened,
|
// We need to build the `Multiaddr` to return from this function. If an error happened,
|
||||||
// just return the original multiaddr.
|
// just return the original multiaddr.
|
||||||
let new_addr = match listener {
|
let listen_addr = match listener {
|
||||||
Ok(ref l) => if let Ok(new_s_addr) = l.local_addr() {
|
Ok(ref l) => if let Ok(new_s_addr) = l.local_addr() {
|
||||||
new_s_addr.to_multiaddr().expect(
|
new_s_addr.to_multiaddr()
|
||||||
"multiaddr generated from socket addr is \
|
.expect("multiaddr generated from socket addr is always valid")
|
||||||
always valid",
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
addr
|
addr
|
||||||
},
|
},
|
||||||
Err(_) => addr,
|
Err(_) => addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Now listening on {}", new_addr);
|
debug!("Now listening on {}", listen_addr);
|
||||||
let sleep_on_error = self.sleep_on_error;
|
let sleep_on_error = self.sleep_on_error;
|
||||||
let inner = listener
|
let inner = listener
|
||||||
.map_err(TransportError::Other)?
|
.map_err(TransportError::Other)?
|
||||||
.incoming()
|
.incoming()
|
||||||
.sleep_on_error(sleep_on_error);
|
.sleep_on_error(sleep_on_error);
|
||||||
|
|
||||||
Ok((
|
Ok(TcpListenStream {
|
||||||
TcpListenStream {
|
inner: Ok(inner),
|
||||||
inner: Ok(inner),
|
listen_addr,
|
||||||
config: self,
|
config: self,
|
||||||
},
|
tell_new_addr: true
|
||||||
new_addr,
|
})
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(TransportError::MultiaddrNotSupported(addr))
|
Err(TransportError::MultiaddrNotSupported(addr))
|
||||||
}
|
}
|
||||||
@ -277,20 +273,23 @@ impl Future for TcpDialFut {
|
|||||||
/// Stream that listens on an TCP/IP address.
|
/// Stream that listens on an TCP/IP address.
|
||||||
pub struct TcpListenStream {
|
pub struct TcpListenStream {
|
||||||
inner: Result<SleepOnError<Incoming>, Option<io::Error>>,
|
inner: Result<SleepOnError<Incoming>, Option<io::Error>>,
|
||||||
|
listen_addr: Multiaddr,
|
||||||
/// Original configuration.
|
/// Original configuration.
|
||||||
config: TcpConfig,
|
config: TcpConfig,
|
||||||
|
/// Generate `ListenerEvent::NewAddress` to inform about our listen address.
|
||||||
|
tell_new_addr: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for TcpListenStream {
|
impl Stream for TcpListenStream {
|
||||||
type Item = (FutureResult<TcpTransStream, io::Error>, Multiaddr);
|
type Item = ListenerEvent<FutureResult<TcpTransStream, io::Error>>;
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn poll(
|
fn poll(&mut self) -> Poll<Option<Self::Item>, io::Error> {
|
||||||
&mut self,
|
if self.tell_new_addr {
|
||||||
) -> Poll<
|
self.tell_new_addr = false;
|
||||||
Option<(FutureResult<TcpTransStream, io::Error>, Multiaddr)>,
|
return Ok(Async::Ready(Some(ListenerEvent::NewAddress(self.listen_addr.clone()))))
|
||||||
io::Error,
|
}
|
||||||
> {
|
|
||||||
let inner = match self.inner {
|
let inner = match self.inner {
|
||||||
Ok(ref mut inc) => inc,
|
Ok(ref mut inc) => inc,
|
||||||
Err(ref mut err) => {
|
Err(ref mut err) => {
|
||||||
@ -317,12 +316,23 @@ impl Stream for TcpListenStream {
|
|||||||
|
|
||||||
match apply_config(&self.config, &sock) {
|
match apply_config(&self.config, &sock) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(err) => return Ok(Async::Ready(Some((future::err(err), addr)))),
|
Err(err) => {
|
||||||
|
let event = ListenerEvent::Upgrade {
|
||||||
|
upgrade: future::err(err),
|
||||||
|
listen_addr: self.listen_addr.clone(),
|
||||||
|
remote_addr: addr
|
||||||
|
};
|
||||||
|
return Ok(Async::Ready(Some(event)))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Incoming connection from {}", addr);
|
debug!("Incoming connection from {}", addr);
|
||||||
let ret = future::ok(TcpTransStream { inner: sock });
|
let event = ListenerEvent::Upgrade {
|
||||||
break Ok(Async::Ready(Some((ret, addr))))
|
upgrade: future::ok(TcpTransStream { inner: sock }),
|
||||||
|
listen_addr: self.listen_addr.clone(),
|
||||||
|
remote_addr: addr
|
||||||
|
};
|
||||||
|
break Ok(Async::Ready(Some(event)))
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(None)) => break Ok(Async::Ready(None)),
|
Ok(Async::Ready(None)) => break Ok(Async::Ready(None)),
|
||||||
Ok(Async::NotReady) => break Ok(Async::NotReady),
|
Ok(Async::NotReady) => break Ok(Async::NotReady),
|
||||||
@ -396,7 +406,7 @@ mod tests {
|
|||||||
use multiaddr::Multiaddr;
|
use multiaddr::Multiaddr;
|
||||||
use std;
|
use std;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use super::swarm::Transport;
|
use libp2p_core::{Transport, transport::ListenerEvent};
|
||||||
use tokio_io;
|
use tokio_io;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -457,20 +467,22 @@ mod tests {
|
|||||||
let tcp = TcpConfig::new();
|
let tcp = TcpConfig::new();
|
||||||
let mut rt = Runtime::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let handle = rt.handle();
|
let handle = rt.handle();
|
||||||
let listener = tcp.listen_on(addr).unwrap().0.for_each(|(sock, _)| {
|
let listener = tcp.listen_on(addr).unwrap()
|
||||||
sock.and_then(|sock| {
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
// Define what to do with the socket that just connected to us
|
.for_each(|(sock, _)| {
|
||||||
// Which in this case is read 3 bytes
|
sock.and_then(|sock| {
|
||||||
let handle_conn = tokio_io::io::read_exact(sock, [0; 3])
|
// Define what to do with the socket that just connected to us
|
||||||
.map(|(_, buf)| assert_eq!(buf, [1, 2, 3]))
|
// Which in this case is read 3 bytes
|
||||||
.map_err(|err| panic!("IO error {:?}", err));
|
let handle_conn = tokio_io::io::read_exact(sock, [0; 3])
|
||||||
|
.map(|(_, buf)| assert_eq!(buf, [1, 2, 3]))
|
||||||
|
.map_err(|err| panic!("IO error {:?}", err));
|
||||||
|
|
||||||
// Spawn the future as a concurrent task
|
// Spawn the future as a concurrent task
|
||||||
handle.spawn(handle_conn).unwrap();
|
handle.spawn(handle_conn).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
rt.block_on(listener).unwrap();
|
rt.block_on(listener).unwrap();
|
||||||
rt.run().unwrap();
|
rt.run().unwrap();
|
||||||
@ -497,7 +509,13 @@ mod tests {
|
|||||||
let addr = "/ip4/127.0.0.1/tcp/0".parse::<Multiaddr>().unwrap();
|
let addr = "/ip4/127.0.0.1/tcp/0".parse::<Multiaddr>().unwrap();
|
||||||
assert!(addr.to_string().contains("tcp/0"));
|
assert!(addr.to_string().contains("tcp/0"));
|
||||||
|
|
||||||
let (_, new_addr) = tcp.listen_on(addr).unwrap();
|
let new_addr = tcp.listen_on(addr).unwrap().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
assert!(!new_addr.to_string().contains("tcp/0"));
|
assert!(!new_addr.to_string().contains("tcp/0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +526,13 @@ mod tests {
|
|||||||
let addr: Multiaddr = "/ip6/::1/tcp/0".parse().unwrap();
|
let addr: Multiaddr = "/ip6/::1/tcp/0".parse().unwrap();
|
||||||
assert!(addr.to_string().contains("tcp/0"));
|
assert!(addr.to_string().contains("tcp/0"));
|
||||||
|
|
||||||
let (_, new_addr) = tcp.listen_on(addr).unwrap();
|
let new_addr = tcp.listen_on(addr).unwrap().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
assert!(!new_addr.to_string().contains("tcp/0"));
|
assert!(!new_addr.to_string().contains("tcp/0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ use futures::stream::Stream;
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use multiaddr::{Protocol, Multiaddr};
|
use multiaddr::{Protocol, Multiaddr};
|
||||||
use std::{io, path::PathBuf};
|
use std::{io, path::PathBuf};
|
||||||
use libp2p_core::{Transport, transport::TransportError};
|
use libp2p_core::{Transport, transport::{ListenerEvent, TransportError}};
|
||||||
use tokio_uds::{UnixListener, UnixStream};
|
use tokio_uds::{UnixListener, UnixStream};
|
||||||
|
|
||||||
/// Represents the configuration for a Unix domain sockets transport capability for libp2p.
|
/// Represents the configuration for a Unix domain sockets transport capability for libp2p.
|
||||||
@ -77,7 +77,7 @@ impl Transport for UdsConfig {
|
|||||||
type ListenerUpgrade = FutureResult<Self::Output, io::Error>;
|
type ListenerUpgrade = FutureResult<Self::Output, io::Error>;
|
||||||
type Dial = tokio_uds::ConnectFuture;
|
type Dial = tokio_uds::ConnectFuture;
|
||||||
|
|
||||||
fn listen_on(self, addr: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
if let Ok(path) = multiaddr_to_path(&addr) {
|
if let Ok(path) = multiaddr_to_path(&addr) {
|
||||||
let listener = UnixListener::bind(&path);
|
let listener = UnixListener::bind(&path);
|
||||||
// We need to build the `Multiaddr` to return from this function. If an error happened,
|
// We need to build the `Multiaddr` to return from this function. If an error happened,
|
||||||
@ -87,9 +87,10 @@ impl Transport for UdsConfig {
|
|||||||
debug!("Now listening on {}", addr);
|
debug!("Now listening on {}", addr);
|
||||||
let future = ListenerStream {
|
let future = ListenerStream {
|
||||||
stream: listener.incoming(),
|
stream: listener.incoming(),
|
||||||
addr: addr.clone()
|
addr: addr.clone(),
|
||||||
|
tell_new_addr: true
|
||||||
};
|
};
|
||||||
Ok((future, addr))
|
Ok(future)
|
||||||
}
|
}
|
||||||
Err(_) => return Err(TransportError::MultiaddrNotSupported(addr)),
|
Err(_) => return Err(TransportError::MultiaddrNotSupported(addr)),
|
||||||
}
|
}
|
||||||
@ -143,21 +144,30 @@ fn multiaddr_to_path(addr: &Multiaddr) -> Result<PathBuf, ()> {
|
|||||||
|
|
||||||
pub struct ListenerStream<T> {
|
pub struct ListenerStream<T> {
|
||||||
stream: T,
|
stream: T,
|
||||||
addr: Multiaddr
|
addr: Multiaddr,
|
||||||
|
tell_new_addr: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Stream for ListenerStream<T>
|
impl<T> Stream for ListenerStream<T>
|
||||||
where
|
where
|
||||||
T: Stream
|
T: Stream
|
||||||
{
|
{
|
||||||
type Item = (FutureResult<T::Item, T::Error>, Multiaddr);
|
type Item = ListenerEvent<FutureResult<T::Item, T::Error>>;
|
||||||
type Error = T::Error;
|
type Error = T::Error;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
|
if self.tell_new_addr {
|
||||||
|
self.tell_new_addr = false;
|
||||||
|
return Ok(Async::Ready(Some(ListenerEvent::NewAddress(self.addr.clone()))))
|
||||||
|
}
|
||||||
match try_ready!(self.stream.poll()) {
|
match try_ready!(self.stream.poll()) {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
debug!("incoming connection on {}", self.addr);
|
debug!("incoming connection on {}", self.addr);
|
||||||
Ok(Async::Ready(Some((future::ok(item), self.addr.clone()))))
|
Ok(Async::Ready(Some(ListenerEvent::Upgrade {
|
||||||
|
upgrade: future::ok(item),
|
||||||
|
listen_addr: self.addr.clone(),
|
||||||
|
remote_addr: self.addr.clone()
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
None => Ok(Async::Ready(None))
|
None => Ok(Async::Ready(None))
|
||||||
}
|
}
|
||||||
@ -168,11 +178,10 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use tokio::runtime::current_thread::Runtime;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
use super::{multiaddr_to_path, UdsConfig};
|
use super::{multiaddr_to_path, UdsConfig};
|
||||||
use futures::stream::Stream;
|
use futures::prelude::*;
|
||||||
use futures::Future;
|
|
||||||
use multiaddr::{Protocol, Multiaddr};
|
use multiaddr::{Protocol, Multiaddr};
|
||||||
use std::{self, borrow::Cow, path::Path};
|
use std::{self, borrow::Cow, path::Path};
|
||||||
use libp2p_core::Transport;
|
use libp2p_core::{Transport, transport::ListenerEvent};
|
||||||
use tempfile;
|
use tempfile;
|
||||||
use tokio_io;
|
use tokio_io;
|
||||||
|
|
||||||
@ -206,19 +215,21 @@ mod tests {
|
|||||||
|
|
||||||
let mut rt = Runtime::new().unwrap();
|
let mut rt = Runtime::new().unwrap();
|
||||||
let handle = rt.handle();
|
let handle = rt.handle();
|
||||||
let listener = tcp.listen_on(addr2).unwrap().0.for_each(|(sock, _)| {
|
let listener = tcp.listen_on(addr2).unwrap()
|
||||||
sock.and_then(|sock| {
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
// Define what to do with the socket that just connected to us
|
.for_each(|(sock, _)| {
|
||||||
// Which in this case is read 3 bytes
|
sock.and_then(|sock| {
|
||||||
let handle_conn = tokio_io::io::read_exact(sock, [0; 3])
|
// Define what to do with the socket that just connected to us
|
||||||
.map(|(_, buf)| assert_eq!(buf, [1, 2, 3]))
|
// Which in this case is read 3 bytes
|
||||||
.map_err(|err| panic!("IO error {:?}", err));
|
let handle_conn = tokio_io::io::read_exact(sock, [0; 3])
|
||||||
|
.map(|(_, buf)| assert_eq!(buf, [1, 2, 3]))
|
||||||
|
.map_err(|err| panic!("IO error {:?}", err));
|
||||||
|
|
||||||
// Spawn the future as a concurrent task
|
// Spawn the future as a concurrent task
|
||||||
handle.spawn(handle_conn).unwrap();
|
handle.spawn(handle_conn).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
rt.block_on(listener).unwrap();
|
rt.block_on(listener).unwrap();
|
||||||
rt.run().unwrap();
|
rt.run().unwrap();
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use libp2p_core as swarm;
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use futures::{future, stream};
|
use futures::{future, stream};
|
||||||
use futures::stream::Then as StreamThen;
|
use futures::stream::Then as StreamThen;
|
||||||
@ -31,7 +30,7 @@ use std::io::{Read, Write};
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use stdweb::web::TypedArray;
|
use stdweb::web::TypedArray;
|
||||||
use stdweb::{self, Reference};
|
use stdweb::{self, Reference};
|
||||||
use swarm::{Transport, transport::TransportError};
|
use libp2p_core::{Transport, transport::{ListenerEvent, TransportError}};
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
/// Represents the configuration for a websocket transport capability for libp2p.
|
/// Represents the configuration for a websocket transport capability for libp2p.
|
||||||
@ -56,12 +55,12 @@ impl BrowserWsConfig {
|
|||||||
impl Transport for BrowserWsConfig {
|
impl Transport for BrowserWsConfig {
|
||||||
type Output = BrowserWsConn;
|
type Output = BrowserWsConn;
|
||||||
type Error = IoError; // TODO: better error type?
|
type Error = IoError; // TODO: better error type?
|
||||||
type Listener = stream::Empty<(Self::ListenerUpgrade, Multiaddr), IoError>;
|
type Listener = stream::Empty<ListenerEvent<Self::ListenerUpgrade>, IoError>;
|
||||||
type ListenerUpgrade = future::Empty<Self::Output, IoError>;
|
type ListenerUpgrade = future::Empty<Self::Output, IoError>;
|
||||||
type Dial = Box<Future<Item = Self::Output, Error = IoError> + Send>;
|
type Dial = Box<Future<Item = Self::Output, Error = IoError> + Send>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn listen_on(self, a: Multiaddr) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
fn listen_on(self, a: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
// Listening is never supported.
|
// Listening is never supported.
|
||||||
Err(TransportError::MultiaddrNotSupported(a))
|
Err(TransportError::MultiaddrNotSupported(a))
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,12 @@
|
|||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use futures::{Future, IntoFuture, Sink, Stream};
|
use futures::{Future, IntoFuture, Sink, Stream};
|
||||||
use libp2p_core as swarm;
|
use libp2p_core::{Transport, transport::{ListenerEvent, TransportError}};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use multiaddr::{Protocol, Multiaddr};
|
use multiaddr::{Protocol, Multiaddr};
|
||||||
use rw_stream_sink::RwStreamSink;
|
use rw_stream_sink::RwStreamSink;
|
||||||
use std::{error, fmt};
|
use std::{error, fmt};
|
||||||
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
||||||
use swarm::{Transport, transport::TransportError};
|
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use websocket::client::builder::ClientBuilder;
|
use websocket::client::builder::ClientBuilder;
|
||||||
use websocket::message::OwnedMessage;
|
use websocket::message::OwnedMessage;
|
||||||
@ -71,76 +70,86 @@ where
|
|||||||
{
|
{
|
||||||
type Output = Box<dyn AsyncStream + Send>;
|
type Output = Box<dyn AsyncStream + Send>;
|
||||||
type Error = WsError<T::Error>;
|
type Error = WsError<T::Error>;
|
||||||
type Listener = Box<dyn Stream<Item = (Self::ListenerUpgrade, Multiaddr), Error = Self::Error> + Send>;
|
type Listener = Box<dyn Stream<Item = ListenerEvent<Self::ListenerUpgrade>, Error = Self::Error> + Send>;
|
||||||
type ListenerUpgrade = Box<dyn Future<Item = Self::Output, Error = Self::Error> + Send>;
|
type ListenerUpgrade = Box<dyn Future<Item = Self::Output, Error = Self::Error> + Send>;
|
||||||
type Dial = Box<dyn Future<Item = Self::Output, Error = Self::Error> + Send>;
|
type Dial = Box<dyn Future<Item = Self::Output, Error = Self::Error> + Send>;
|
||||||
|
|
||||||
fn listen_on(
|
fn listen_on(self, original_addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||||
self,
|
|
||||||
original_addr: Multiaddr,
|
|
||||||
) -> Result<(Self::Listener, Multiaddr), TransportError<Self::Error>> {
|
|
||||||
let mut inner_addr = original_addr.clone();
|
let mut inner_addr = original_addr.clone();
|
||||||
match inner_addr.pop() {
|
match inner_addr.pop() {
|
||||||
Some(Protocol::Ws) => {}
|
Some(Protocol::Ws) => {}
|
||||||
_ => return Err(TransportError::MultiaddrNotSupported(original_addr)),
|
_ => return Err(TransportError::MultiaddrNotSupported(original_addr)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (inner_listen, mut new_addr) = self.transport.listen_on(inner_addr)
|
let inner_listen = self.transport.listen_on(inner_addr)
|
||||||
.map_err(|err| err.map(WsError::Underlying))?;
|
.map_err(|err| err.map(WsError::Underlying))?;
|
||||||
new_addr.append(Protocol::Ws);
|
|
||||||
debug!("Listening on {}", new_addr);
|
|
||||||
|
|
||||||
let listen = inner_listen.map_err(WsError::Underlying).map(|(stream, mut client_addr)| {
|
let listen = inner_listen.map_err(WsError::Underlying).map(|event| {
|
||||||
// Need to suffix `/ws` to each client address.
|
match event {
|
||||||
client_addr.append(Protocol::Ws);
|
ListenerEvent::NewAddress(mut a) => {
|
||||||
|
a.append(Protocol::Ws);
|
||||||
|
debug!("Listening on {}", a);
|
||||||
|
ListenerEvent::NewAddress(a)
|
||||||
|
}
|
||||||
|
ListenerEvent::AddressExpired(mut a) => {
|
||||||
|
a.append(Protocol::Ws);
|
||||||
|
ListenerEvent::AddressExpired(a)
|
||||||
|
}
|
||||||
|
ListenerEvent::Upgrade { upgrade, mut listen_addr, mut remote_addr } => {
|
||||||
|
listen_addr.append(Protocol::Ws);
|
||||||
|
remote_addr.append(Protocol::Ws);
|
||||||
|
|
||||||
// Upgrade the listener to websockets like the websockets library requires us to do.
|
// Upgrade the listener to websockets like the websockets library requires us to do.
|
||||||
let upgraded = stream.map_err(WsError::Underlying).and_then(move |stream| {
|
let upgraded = upgrade.map_err(WsError::Underlying).and_then(move |stream| {
|
||||||
debug!("Incoming connection");
|
debug!("Incoming connection");
|
||||||
|
stream.into_ws()
|
||||||
|
.map_err(|e| WsError::WebSocket(Box::new(e.3)))
|
||||||
|
.and_then(|stream| {
|
||||||
|
// Accept the next incoming connection.
|
||||||
|
stream
|
||||||
|
.accept()
|
||||||
|
.map_err(|e| WsError::WebSocket(Box::new(e)))
|
||||||
|
.map(|(client, _http_headers)| {
|
||||||
|
debug!("Upgraded incoming connection to websockets");
|
||||||
|
|
||||||
stream
|
// Plug our own API on top of the `websockets` API.
|
||||||
.into_ws()
|
let framed_data = client
|
||||||
.map_err(|e| WsError::WebSocket(Box::new(e.3)))
|
.map_err(|err| IoError::new(IoErrorKind::Other, err))
|
||||||
.and_then(|stream| {
|
.sink_map_err(|err| IoError::new(IoErrorKind::Other, err))
|
||||||
// Accept the next incoming connection.
|
.with(|data| Ok(OwnedMessage::Binary(data)))
|
||||||
stream
|
.and_then(|recv| {
|
||||||
.accept()
|
match recv {
|
||||||
.map_err(|e| WsError::WebSocket(Box::new(e)))
|
OwnedMessage::Binary(data) => Ok(Some(data)),
|
||||||
.map(|(client, _http_headers)| {
|
OwnedMessage::Text(data) => Ok(Some(data.into_bytes())),
|
||||||
debug!("Upgraded incoming connection to websockets");
|
OwnedMessage::Close(_) => Ok(None),
|
||||||
|
// TODO: handle pings and pongs, which is freaking hard
|
||||||
|
// for now we close the socket when that happens
|
||||||
|
_ => Ok(None)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// TODO: is there a way to merge both lines into one?
|
||||||
|
.take_while(|v| Ok(v.is_some()))
|
||||||
|
.map(|v| v.expect("we only take while this is Some"));
|
||||||
|
|
||||||
// Plug our own API on top of the `websockets` API.
|
let read_write = RwStreamSink::new(framed_data);
|
||||||
let framed_data = client
|
Box::new(read_write) as Box<dyn AsyncStream + Send>
|
||||||
.map_err(|err| IoError::new(IoErrorKind::Other, err))
|
|
||||||
.sink_map_err(|err| IoError::new(IoErrorKind::Other, err))
|
|
||||||
.with(|data| Ok(OwnedMessage::Binary(data)))
|
|
||||||
.and_then(|recv| {
|
|
||||||
match recv {
|
|
||||||
OwnedMessage::Binary(data) => Ok(Some(data)),
|
|
||||||
OwnedMessage::Text(data) => Ok(Some(data.into_bytes())),
|
|
||||||
OwnedMessage::Close(_) => Ok(None),
|
|
||||||
// TODO: handle pings and pongs, which is freaking hard
|
|
||||||
// for now we close the socket when that happens
|
|
||||||
_ => Ok(None)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
// TODO: is there a way to merge both lines into one?
|
|
||||||
.take_while(|v| Ok(v.is_some()))
|
|
||||||
.map(|v| v.expect("we only take while this is Some"));
|
|
||||||
|
|
||||||
let read_write = RwStreamSink::new(framed_data);
|
|
||||||
Box::new(read_write) as Box<dyn AsyncStream + Send>
|
|
||||||
})
|
})
|
||||||
})
|
.map(|s| Box::new(Ok(s).into_future()) as Box<dyn Future<Item = _, Error = _> + Send>)
|
||||||
.map(|s| Box::new(Ok(s).into_future()) as Box<dyn Future<Item = _, Error = _> + Send>)
|
.into_future()
|
||||||
.into_future()
|
.flatten()
|
||||||
.flatten()
|
});
|
||||||
});
|
|
||||||
|
|
||||||
(Box::new(upgraded) as Box<dyn Future<Item = _, Error = _> + Send>, client_addr)
|
ListenerEvent::Upgrade {
|
||||||
|
upgrade: Box::new(upgraded) as Box<dyn Future<Item = _, Error = _> + Send>,
|
||||||
|
listen_addr,
|
||||||
|
remote_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok((Box::new(listen) as Box<_>, new_addr))
|
Ok(Box::new(listen) as Box<_>)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dial(self, original_addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
fn dial(self, original_addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||||
@ -271,25 +280,35 @@ mod tests {
|
|||||||
use libp2p_tcp as tcp;
|
use libp2p_tcp as tcp;
|
||||||
use tokio::runtime::current_thread::Runtime;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
use multiaddr::Multiaddr;
|
use multiaddr::{Multiaddr, Protocol};
|
||||||
use super::swarm::Transport;
|
use libp2p_core::{Transport, transport::ListenerEvent};
|
||||||
use super::WsConfig;
|
use super::WsConfig;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dialer_connects_to_listener_ipv4() {
|
fn dialer_connects_to_listener_ipv4() {
|
||||||
let ws_config = WsConfig::new(tcp::TcpConfig::new());
|
let ws_config = WsConfig::new(tcp::TcpConfig::new());
|
||||||
|
|
||||||
let (listener, addr) = ws_config
|
let mut listener = ws_config.clone()
|
||||||
.clone()
|
|
||||||
.listen_on("/ip4/127.0.0.1/tcp/0/ws".parse().unwrap())
|
.listen_on("/ip4/127.0.0.1/tcp/0/ws".parse().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(addr.to_string().ends_with("/ws"));
|
|
||||||
assert!(!addr.to_string().ends_with("/0/ws"));
|
let addr = listener.by_ref().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
|
assert_eq!(Some(Protocol::Ws), addr.iter().nth(2));
|
||||||
|
assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1));
|
||||||
|
|
||||||
let listener = listener
|
let listener = listener
|
||||||
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(e, _)| e)
|
.map_err(|(e, _)| e)
|
||||||
.and_then(|(c, _)| c.unwrap().0);
|
.and_then(|(c, _)| c.unwrap().0);
|
||||||
let dialer = ws_config.clone().dial(addr).unwrap();
|
|
||||||
|
let dialer = ws_config.clone().dial(addr.clone()).unwrap();
|
||||||
|
|
||||||
let future = listener
|
let future = listener
|
||||||
.select(dialer)
|
.select(dialer)
|
||||||
@ -303,17 +322,27 @@ mod tests {
|
|||||||
fn dialer_connects_to_listener_ipv6() {
|
fn dialer_connects_to_listener_ipv6() {
|
||||||
let ws_config = WsConfig::new(tcp::TcpConfig::new());
|
let ws_config = WsConfig::new(tcp::TcpConfig::new());
|
||||||
|
|
||||||
let (listener, addr) = ws_config
|
let mut listener = ws_config.clone()
|
||||||
.clone()
|
|
||||||
.listen_on("/ip6/::1/tcp/0/ws".parse().unwrap())
|
.listen_on("/ip6/::1/tcp/0/ws".parse().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(addr.to_string().ends_with("/ws"));
|
|
||||||
assert!(!addr.to_string().ends_with("/0/ws"));
|
let addr = listener.by_ref().wait()
|
||||||
|
.next()
|
||||||
|
.expect("some event")
|
||||||
|
.expect("no error")
|
||||||
|
.into_new_address()
|
||||||
|
.expect("listen address");
|
||||||
|
|
||||||
|
assert_eq!(Some(Protocol::Ws), addr.iter().nth(2));
|
||||||
|
assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1));
|
||||||
|
|
||||||
let listener = listener
|
let listener = listener
|
||||||
|
.filter_map(ListenerEvent::into_upgrade)
|
||||||
.into_future()
|
.into_future()
|
||||||
.map_err(|(e, _)| e)
|
.map_err(|(e, _)| e)
|
||||||
.and_then(|(c, _)| c.unwrap().0);
|
.and_then(|(c, _)| c.unwrap().0);
|
||||||
let dialer = ws_config.clone().dial(addr).unwrap();
|
|
||||||
|
let dialer = ws_config.clone().dial(addr.clone()).unwrap();
|
||||||
|
|
||||||
let future = listener
|
let future = listener
|
||||||
.select(dialer)
|
.select(dialer)
|
||||||
|
Reference in New Issue
Block a user