Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass the host name in libp2p-websockets #177

Merged
merged 3 commits into from
May 8, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion websocket/src/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ use tokio_io::{AsyncRead, AsyncWrite};
/// Represents the configuration for a websocket transport capability for libp2p.
///
/// This implementation of `Transport` accepts any address that looks like
/// `/ip4/.../tcp/.../ws` or `/ip6/.../tcp/.../ws`, and connect to the corresponding IP and port.
/// `/ip4/.../tcp/.../ws`, `/ip6/.../tcp/.../ws`, `/dns4/.../ws` or `/dns6/.../ws`, and connect to
/// the corresponding IP and port.
///
/// If the underlying multiaddress uses `/dns4` or `/dns6`, then the domain name will be passed in
/// the headers of the request. This is important is the listener is behind an HTTP proxy.
#[derive(Debug, Clone)]
pub struct BrowserWsConfig;

Expand Down Expand Up @@ -339,6 +343,18 @@ fn multiaddr_to_target(addr: &Multiaddr) -> Result<String, ()> {
(&AddrComponent::IP6(ref ip), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
Ok(format!("wss://[{}]:{}/", ip, port))
}
(&AddrComponent::DNS4(ref ns), &AddrComponent::TCP(port), &AddrComponent::WS) => {
Ok(format!("ws://{}:{}/", ns, port))
}
(&AddrComponent::DNS6(ref ns), &AddrComponent::TCP(port), &AddrComponent::WS) => {
Ok(format!("ws://{}:{}/", ns, port))
}
(&AddrComponent::DNS4(ref ns), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
Ok(format!("wss://{}:{}/", ns, port))
}
(&AddrComponent::DNS6(ref ns), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
Ok(format!("wss://{}:{}/", ns, port))
}
_ => Err(()),
}
}
Expand Down
47 changes: 40 additions & 7 deletions websocket/src/desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ use websocket::stream::async::Stream as AsyncStream;
/// This implementation of `Transport` accepts any address that ends with `/ws` or `/wss`, and will
/// try to pass the underlying multiaddress to the underlying `Transport`.
///
/// Note that the underlying multiaddr is `/dns4/...` or `/dns6/...`, then this library will
/// pass the domain name in the headers of the request. This is important is the listener is behind
/// an HTTP proxy.
///
/// > **Note**: `/wss` is only supported for dialing and not listening.
#[derive(Debug, Clone)]
pub struct WsConfig<T> {
Expand Down Expand Up @@ -159,6 +163,8 @@ where

debug!(target: "libp2p-websocket", "Dialing {} through inner transport", inner_addr);

let ws_addr = client_addr_to_ws(&inner_addr, is_wss);

let inner_dial = match self.transport.dial(inner_addr) {
Ok(d) => d,
Err((transport, old_addr)) => {
Expand All @@ -177,13 +183,8 @@ where
let dial = inner_dial
.into_future()
.and_then(move |(connec, client_addr)| {
// We pass a dummy address to `ClientBuilder` because it is never used anywhere
// in the negotiation anyway, and we use `async_connect_on` to pass a stream.
ClientBuilder::new(if is_wss {
"wss://127.0.0.1"
} else {
"ws://127.0.0.1"
}).expect("hard-coded ws address is always valid")
ClientBuilder::new(&ws_addr)
.expect("generated ws address is always valid")
.async_connect_on(connec)
.map_err(|err| IoError::new(IoErrorKind::Other, err))
.map(|(client, _)| {
Expand Down Expand Up @@ -245,6 +246,38 @@ where
}
}

fn client_addr_to_ws(client_addr: &Multiaddr, is_wss: bool) -> String {
let inner = {
let protocols: Vec<_> = client_addr.iter().collect();

if protocols.len() != 2 {
"127.0.0.1".to_owned()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we error in case the address does not conform to the required format?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whatever this function returns, what we do in reality is pass the inner multiaddress to the underlying transport, then negotiate websockets over the socket provided by the underlying transport. Therefore the actual IP address here doesn't matter.

} else {
match (&protocols[0], &protocols[1]) {
(&AddrComponent::IP4(ref ip), &AddrComponent::TCP(port)) => {
format!("{}:{}", ip, port)
}
(&AddrComponent::IP6(ref ip), &AddrComponent::TCP(port)) => {
format!("[{}]:{}", ip, port)
}
(&AddrComponent::DNS4(ref ns), &AddrComponent::TCP(port)) => {
format!("{}:{}", ns, port)
}
(&AddrComponent::DNS6(ref ns), &AddrComponent::TCP(port)) => {
format!("{}:{}", ns, port)
}
_ => "127.0.0.1".to_owned(),
}
}
};

if is_wss {
format!("wss://{}", inner)
} else {
format!("ws://{}", inner)
}
}

#[cfg(test)]
mod tests {
extern crate libp2p_tcp_transport as tcp;
Expand Down