Have Transport::Listeners produce ListenerEvents. (#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:
Toralf Wittner
2019-04-10 10:29:21 +02:00
committed by GitHub
parent 98b2517403
commit 6917b8f543
36 changed files with 935 additions and 701 deletions

View File

@ -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),
} }
} }

View File

@ -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
}
}
}

View File

@ -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);
} }
} }

View File

@ -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 })
}
} }
} }
} }

View File

@ -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)
} }
}, },
} }

View File

@ -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;

View File

@ -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);

View File

@ -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")),
}, },

View File

@ -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)))))
} }
} }

View File

@ -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)

View File

@ -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)
} }

View File

@ -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))),
}; };

View File

@ -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))
} }

View File

@ -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)

View File

@ -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)) => {

View File

@ -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)))
} }
} }

View File

@ -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)]

View File

@ -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))
} }

View File

@ -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))
} }

View File

@ -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),

View File

@ -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;
}, },

View File

@ -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)))

View File

@ -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"

View File

@ -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))
} }

View File

@ -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;

View File

@ -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)

View File

@ -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();

View File

@ -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))

View File

@ -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)))
} }
} }

View File

@ -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)
} }

View File

@ -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!()
} }

View File

@ -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,
)
}) })
} }

View File

@ -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"));
} }

View File

@ -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();

View File

@ -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))
} }

View File

@ -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)