mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-27 08:41:36 +00:00
[tcp] Port-reuse, async-io, if-watch (#1887)
* Update tomls. * Let transports decide when to translate. * Improve tcp transport. * Update stuff. * Remove background task. Enhance documentation. To avoid spawning a background task and thread within `TcpConfig::new()`, with communication via unbounded channels, a `TcpConfig` now keeps track of the listening addresses for port reuse in an `Arc<RwLock>`. Furthermore, an `IfWatcher` is only used by a `TcpListenStream` if it listens on any interface and directly polls the `IfWatcher` both for initialisation and new events. Includes some documentation and test enhancements. * Reintroduce feature flags for tokio vs async-io. To avoid having an extra reactor thread running for tokio users and to make sure all TCP I/O uses the mio-based tokio reactor. Thereby run tests with both backends. * Add missing files. * Fix docsrs attributes. * Update transports/tcp/src/lib.rs Co-authored-by: Max Inden <mail@max-inden.de> * Restore chat-tokio example. * Forward poll_write_vectored for tokio's AsyncWrite. * Update changelogs. Co-authored-by: David Craven <david@craven.ch> Co-authored-by: Max Inden <mail@max-inden.de>
This commit is contained in:
@ -428,6 +428,8 @@ mod tests {
|
||||
fn dial(self, _: Multiaddr) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> { None }
|
||||
}
|
||||
|
||||
async_std::task::block_on(async move {
|
||||
@ -466,6 +468,8 @@ mod tests {
|
||||
fn dial(self, _: Multiaddr) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> { None }
|
||||
}
|
||||
|
||||
async_std::task::block_on(async move {
|
||||
|
@ -477,4 +477,11 @@ where
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
match self {
|
||||
EitherTransport::Left(a) => a.address_translation(server, observed),
|
||||
EitherTransport::Right(b) => b.address_translation(server, observed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ use crate::{
|
||||
Executor,
|
||||
Multiaddr,
|
||||
PeerId,
|
||||
address_translation,
|
||||
connection::{
|
||||
ConnectionId,
|
||||
ConnectionLimit,
|
||||
@ -176,30 +175,27 @@ where
|
||||
self.listeners.listen_addrs()
|
||||
}
|
||||
|
||||
/// Call this function in order to know which address remotes should dial to
|
||||
/// access your local node.
|
||||
/// Maps the given `observed_addr`, representing an address of the local
|
||||
/// node observed by a remote peer, onto the locally known listen addresses
|
||||
/// to yield one or more addresses of the local node that may be publicly
|
||||
/// reachable.
|
||||
///
|
||||
/// When receiving an observed address on a tcp connection that we initiated, the observed
|
||||
/// address contains our tcp dial port, not our tcp listen port. We know which port we are
|
||||
/// listening on, thereby we can replace the port within the observed address.
|
||||
///
|
||||
/// When receiving an observed address on a tcp connection that we did **not** initiated, the
|
||||
/// observed address should contain our listening port. In case it differs from our listening
|
||||
/// port there might be a proxy along the path.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `observed_addr` - should be an address a remote observes you as, which can be obtained for
|
||||
/// example with the identify protocol.
|
||||
/// I.e. this method incorporates the view of other peers into the listen
|
||||
/// addresses seen by the local node to account for possible IP and port
|
||||
/// mappings performed by intermediate network devices in an effort to
|
||||
/// obtain addresses for the local peer that are also reachable for peers
|
||||
/// other than the peer who reported the `observed_addr`.
|
||||
///
|
||||
/// The translation is transport-specific. See [`Transport::address_translation`].
|
||||
pub fn address_translation<'a>(&'a self, observed_addr: &'a Multiaddr)
|
||||
-> impl Iterator<Item = Multiaddr> + 'a
|
||||
where
|
||||
TMuxer: 'a,
|
||||
THandler: 'a,
|
||||
{
|
||||
let transport = self.listeners.transport();
|
||||
let mut addrs: Vec<_> = self.listen_addrs()
|
||||
.filter_map(move |server| address_translation(server, observed_addr))
|
||||
.filter_map(move |server| transport.address_translation(server, observed_addr))
|
||||
.collect();
|
||||
|
||||
// remove duplicates
|
||||
|
@ -128,6 +128,11 @@ pub trait Transport {
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Performs a transport-specific mapping of an address `observed` by
|
||||
/// a remote onto a local `listen` address to yield an address for
|
||||
/// the local node that may be reachable for other peers.
|
||||
fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
|
||||
|
||||
/// Boxes the transport, including custom transport errors.
|
||||
fn boxed(self) -> boxed::Boxed<Self::Output>
|
||||
where
|
||||
|
@ -69,6 +69,10 @@ where
|
||||
};
|
||||
Ok(future)
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.transport.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom `Stream` to avoid boxing.
|
||||
|
@ -51,6 +51,7 @@ type ListenerUpgrade<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>;
|
||||
trait Abstract<O> {
|
||||
fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O>, TransportError<io::Error>>;
|
||||
fn dial(&self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>;
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
|
||||
}
|
||||
|
||||
impl<T, O> Abstract<O> for T
|
||||
@ -78,6 +79,10 @@ where
|
||||
.map_err(|e| e.map(box_err))?;
|
||||
Ok(Box::pin(fut) as Dial<_>)
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
Transport::address_translation(self, server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O> fmt::Debug for Boxed<O> {
|
||||
@ -108,6 +113,10 @@ impl<O> Transport for Boxed<O> {
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
self.inner.dial(addr)
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.inner.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
fn box_err<E: Error + Send + Sync + 'static>(e: E) -> io::Error {
|
||||
|
@ -74,4 +74,12 @@ where
|
||||
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
if let Some(addr) = self.0.address_translation(server, observed) {
|
||||
Some(addr)
|
||||
} else {
|
||||
self.1.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ impl<TOut> Transport for DummyTransport<TOut> {
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
|
||||
fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `AsyncRead` and `AsyncWrite`. Not meant to be instanciated.
|
||||
|
@ -57,6 +57,10 @@ where
|
||||
let p = ConnectedPoint::Dialer { address: addr };
|
||||
Ok(MapFuture { inner: future, args: Some((self.fun, p)) })
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.transport.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom `Stream` implementation to avoid boxing.
|
||||
|
@ -64,6 +64,10 @@ where
|
||||
Err(err) => Err(err.map(map)),
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.transport.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Listening stream for `MapErr`.
|
||||
|
@ -191,6 +191,10 @@ impl Transport for MemoryTransport {
|
||||
|
||||
DialFuture::new(port).ok_or(TransportError::Other(MemoryTransportError::Unreachable))
|
||||
}
|
||||
|
||||
fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can be produced from the `MemoryTransport`.
|
||||
|
@ -74,4 +74,12 @@ where
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
if let Some(inner) = &self.0 {
|
||||
inner.address_translation(server, observed)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,10 @@ where
|
||||
timer: Delay::new(self.outgoing_timeout),
|
||||
})
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.inner.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can be removed and replaced with an `impl Stream` once impl Trait is fully stable
|
||||
|
@ -334,6 +334,10 @@ where
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
self.0.listen_on(addr)
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.0.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
/// An inbound or outbound upgrade.
|
||||
@ -383,6 +387,10 @@ where
|
||||
upgrade: self.upgrade
|
||||
})
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.inner.address_translation(server, observed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors produced by a transport upgrade.
|
||||
|
Reference in New Issue
Block a user