Change some nat_traversals to consider a prefix. (#550)

Change some `nat_traversal`s to consider a prefix.

Transports should consider only the relevant address prefix.
This commit is contained in:
Toralf Wittner 2018-10-15 16:29:32 +02:00 committed by GitHub
parent e179951c74
commit 2c98d06942
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 87 deletions

View File

@ -116,8 +116,12 @@ pub trait Transport {
/// a remote node observes for one of our dialers.
///
/// For example, if `server` is `/ip4/0.0.0.0/tcp/3000` and `observed` is
/// `/ip4/80.81.82.83/tcp/29601`, then we should return `/ip4/80.81.82.83/tcp/3000`. Each
/// implementation of `Transport` is only responsible for handling the protocols it supports.
/// `/ip4/80.81.82.83/tcp/29601`, then we should return `/ip4/80.81.82.83/tcp/3000`.
///
/// Each implementation of `Transport` is only responsible for handling the protocols it
/// supports and should only consider the prefix of `observed` necessary to perform the
/// address translation (e.g. `/ip4/80.81.82.83`) but should otherwise preserve `server`
/// as is.
///
/// Returns `None` if nothing can be determined. This happens if this trait implementation
/// doesn't recognize the protocols, or if `server` and `observed` are related.

View File

@ -120,6 +120,11 @@ impl fmt::Display for Multiaddr {
}
impl Multiaddr {
/// Create a new, empty multiaddress.
pub fn empty() -> Multiaddr {
Multiaddr { bytes: Vec::new() }
}
/// Returns the raw bytes representation of the multiaddr.
#[inline]
pub fn into_bytes(self) -> Vec<u8> {

View File

@ -54,7 +54,6 @@ use futures::{future, future::FutureResult, prelude::*, Async, Poll};
use multiaddr::{Protocol, Multiaddr, ToMultiaddr};
use std::fmt;
use std::io::{Error as IoError, Read, Write};
use std::iter;
use std::net::SocketAddr;
use std::time::Duration;
use swarm::Transport;
@ -194,40 +193,21 @@ impl Transport for TcpConfig {
}
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
// Check that `server` only has two components and retreive them.
let mut server_protocols_iter = server.iter();
let server_proto1 = server_protocols_iter.next()?;
let server_proto2 = server_protocols_iter.next()?;
if server_protocols_iter.next().is_some() {
return None;
let mut address = Multiaddr::empty();
// Use the observed IP address.
match server.iter().zip(observed.iter()).next() {
Some((Protocol::Ip4(_), x@Protocol::Ip4(_))) => address.append(x),
Some((Protocol::Ip6(_), x@Protocol::Ip6(_))) => address.append(x),
_ => return None
}
// Check that `observed` only has two components and retreive them.
let mut observed_protocols_iter = observed.iter();
let observed_proto1 = observed_protocols_iter.next()?;
let observed_proto2 = observed_protocols_iter.next()?;
if observed_protocols_iter.next().is_some() {
return None;
// Carry over everything else from the server address.
for proto in server.iter().skip(1) {
address.append(proto)
}
// Check that `server` is a valid TCP/IP address.
match (&server_proto1, &server_proto2) {
(&Protocol::Ip4(_), &Protocol::Tcp(_))
| (&Protocol::Ip6(_), &Protocol::Tcp(_)) => {}
_ => return None,
}
// Check that `observed` is a valid TCP/IP address.
match (&observed_proto1, &observed_proto2) {
(&Protocol::Ip4(_), &Protocol::Tcp(_))
| (&Protocol::Ip6(_), &Protocol::Tcp(_)) => {}
_ => return None,
}
let result = iter::once(observed_proto1.clone())
.chain(iter::once(server_proto2.clone()))
.collect();
Some(result)
Some(address)
}
}

View File

@ -209,49 +209,40 @@ impl Transport for BrowserWsConfig {
}
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
let mut server_protocols = server.iter();
let server_proto0 = server_protocols.next()?;
let server_proto1 = server_protocols.next()?;
let server_proto2 = server_protocols.next()?;
if server_protocols.next().is_some() {
return None;
let mut address = Multiaddr::empty();
let mut iter = server.iter().zip(observed.iter());
// Use the observed IP address.
match iter.next() {
Some((Protocol::Ip4(_), x@Protocol::Ip4(_))) => address.append(x),
Some((Protocol::Ip6(_), x@Protocol::Ip6(_))) => address.append(x),
_ => return None
}
let mut observed_protocols = observed.iter();
let obs_proto0 = observed_protocols.next()?;
let obs_proto1 = observed_protocols.next()?;
let obs_proto2 = observed_protocols.next()?;
if observed_protocols.next().is_some() {
return None;
// Skip over next protocol (assumed to contain port information).
if iter.next().is_none() {
return None
}
// Check that `server` is a valid TCP/IP address.
match (&server_proto0, &server_proto1, &server_proto2) {
(&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Ws)
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Ws)
| (&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Wss)
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Wss) => {}
_ => return None,
// Check for WS/WSS.
//
// Note that it will still work if the server uses WSS while the client uses
// WS, or vice-versa.
match iter.next() {
Some((x@Protocol::Ws, Protocol::Ws)) => address.append(x),
Some((x@Protocol::Ws, Protocol::Wss)) => address.append(x),
Some((x@Protocol::Wss, Protocol::Ws)) => address.append(x),
Some((x@Protocol::Wss, Protocol::Wss)) => address.append(x),
_ => return None
}
// Check that `observed` is a valid TCP/IP address.
match (&obs_proto0, &obs_proto1, &obs_proto2) {
(&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Ws)
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Ws)
| (&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Wss)
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Wss) => {}
_ => return None,
// Carry over everything else from the server address.
for proto in server.iter().skip(3) {
address.append(proto)
}
// Note that it will still work if the server uses WSS while the client uses WS,
// or vice-versa.
let result = iter::once(obs_proto0)
.chain(iter::once(server_proto1))
.chain(iter::once(server_proto2))
.collect();
Some(result)
Some(address)
}
}

View File

@ -236,25 +236,7 @@ where
}
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
let mut server = server.clone();
let last_proto = match server.pop() {
Some(v @ Protocol::Ws) | Some(v @ Protocol::Wss) => v,
_ => return None,
};
let mut observed = observed.clone();
match observed.pop() {
Some(Protocol::Ws) => false,
Some(Protocol::Wss) => true,
_ => return None,
};
self.transport
.nat_traversal(&server, &observed)
.map(move |mut result| {
result.append(last_proto);
result
})
self.transport.nat_traversal(server, observed)
}
}