Skip to content

Commit

Permalink
Add a websocket transport
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaka committed Jan 2, 2018
1 parent 1801cd0 commit 777e5a9
Show file tree
Hide file tree
Showing 12 changed files with 707 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -5,6 +5,7 @@ members = [
"libp2p-secio",
"libp2p-swarm",
"libp2p-tcp-transport",
"libp2p-websocket",
"multistream-select",
"datastore",
"futures-mutex",
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -23,6 +23,7 @@ Architecture of the crates of this repository:
`ConnectionUpgrade` trait of `libp2p-swarm`.
- `libp2p-swarm`: Core library that contains all the traits of *libp2p* and plugs things together.
- `libp2p-tcp-transport`: Implementation of the `Transport` trait of `libp2p-swarm` for TCP/IP.
- `libp2p-websocket`: Implementation of the `Transport` trait of `libp2p-swarm` for Websockets.
- `multistream-select`: Implementation of the `multistream-select` protocol, which is used to
negotiate a protocol over a newly-established connection with a peer, or after a connection
upgrade.
Expand Down
1 change: 1 addition & 0 deletions example/Cargo.toml
Expand Up @@ -10,5 +10,6 @@ multiplex = { path = "../multiplex-rs" }
libp2p-secio = { path = "../libp2p-secio" }
libp2p-swarm = { path = "../libp2p-swarm" }
libp2p-tcp-transport = { path = "../libp2p-tcp-transport" }
libp2p-websocket = { path = "../libp2p-websocket" }
tokio-core = "0.1"
tokio-io = "0.1"
7 changes: 7 additions & 0 deletions example/examples/echo-dialer.rs
Expand Up @@ -23,6 +23,7 @@ extern crate futures;
extern crate libp2p_secio as secio;
extern crate libp2p_swarm as swarm;
extern crate libp2p_tcp_transport as tcp;
extern crate libp2p_websocket as websocket;
extern crate multiplex;
extern crate tokio_core;
extern crate tokio_io;
Expand All @@ -34,6 +35,7 @@ use swarm::{UpgradeExt, SimpleProtocol, Transport, MuxedTransport};
use tcp::TcpConfig;
use tokio_core::reactor::Core;
use tokio_io::codec::length_delimited;
use websocket::WsConfig;

fn main() {
// Determine which address to dial.
Expand All @@ -46,6 +48,11 @@ fn main() {
// We start by creating a `TcpConfig` that indicates that we want TCP/IP.
let transport = TcpConfig::new(core.handle())

// In addition to TCP/IP, we also want to support the Websockets protocol on top of TCP/IP.
// The parameter passed to `WsConfig::new()` must be an implementation of `Transport` to be
// used for the underlying multiaddress.
.or_transport(WsConfig::new(TcpConfig::new(core.handle())))

// On top of TCP/IP, we will use either the plaintext protocol or the secio protocol,
// depending on which one the remote supports.
.with_upgrade({
Expand Down
6 changes: 6 additions & 0 deletions example/examples/echo-server.rs
Expand Up @@ -23,6 +23,7 @@ extern crate futures;
extern crate libp2p_secio as secio;
extern crate libp2p_swarm as swarm;
extern crate libp2p_tcp_transport as tcp;
extern crate libp2p_websocket as websocket;
extern crate multiplex;
extern crate tokio_core;
extern crate tokio_io;
Expand All @@ -34,6 +35,7 @@ use swarm::{Transport, UpgradeExt, SimpleProtocol};
use tcp::TcpConfig;
use tokio_core::reactor::Core;
use tokio_io::codec::length_delimited;
use websocket::WsConfig;

fn main() {
// Determine which address to listen to.
Expand All @@ -45,6 +47,10 @@ fn main() {
// Now let's build the transport stack.
// We start by creating a `TcpConfig` that indicates that we want TCP/IP.
let transport = TcpConfig::new(core.handle())
// In addition to TCP/IP, we also want to support the Websockets protocol on top of TCP/IP.
// The parameter passed to `WsConfig::new()` must be an implementation of `Transport` to be
// used for the underlying multiaddress.
.or_transport(WsConfig::new(TcpConfig::new(core.handle())))

// On top of TCP/IP, we will use either the plaintext protocol or the secio protocol,
// depending on which one the remote supports.
Expand Down
1 change: 1 addition & 0 deletions libp2p-swarm/src/connection_reuse.rs
Expand Up @@ -199,6 +199,7 @@ where S: Stream<Item = (F, Multiaddr), Error = IoError>,
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
match self.listener.poll() {
Ok(Async::Ready(Some((upgrade, client_addr)))) => {
println!("ready stream");
self.current_upgrades.push((upgrade, client_addr));
}
Ok(Async::NotReady) => (),
Expand Down
1 change: 1 addition & 0 deletions libp2p-tcp-transport/src/lib.rs
Expand Up @@ -109,6 +109,7 @@ impl Transport for TcpConfig {
let future = future::result(listener).map(|listener| {
// Pull out a stream of sockets for incoming connections
listener.incoming().map(|(sock, addr)| {
println!("incoming tcp stream");
let addr = addr.to_multiaddr()
.expect("generating a multiaddr from a socket addr never fails");
(Ok(sock).into_future(), addr)
Expand Down
21 changes: 21 additions & 0 deletions libp2p-websocket/Cargo.toml
@@ -0,0 +1,21 @@
[package]
name = "libp2p-websocket"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]

[dependencies]
libp2p-swarm = { path = "../libp2p-swarm" }
futures = "0.1"
multiaddr = "0.2.0"
rw-stream-sink = { path = "../rw-stream-sink" }
tokio-io = "0.1"

[target.'cfg(not(target_os = "emscripten"))'.dependencies]
websocket = { version = "0.20.2", default-features = false, features = ["async"] }

[target.'cfg(target_os = "emscripten")'.dependencies]
stdweb = { version = "0.1.3", default-features = false }

[target.'cfg(not(target_os = "emscripten"))'.dev-dependencies]
libp2p-tcp-transport = { path = "../libp2p-tcp-transport" }
tokio-core = "0.1"
43 changes: 43 additions & 0 deletions libp2p-websocket/README.md
@@ -0,0 +1,43 @@
Implementation of the libp2p `Transport` trait for Websockets.

See the documentation of `swarm` and of libp2p in general to learn how to use the `Transport`
trait.

This library is used in a different way depending on whether you are compiling for emscripten
or for a different operating system.

# Emscripten

On emscripten, you can create a `WsConfig` object with `WsConfig::new()`. It can then be used
as a transport.

Listening on a websockets multiaddress isn't supported on emscripten. Dialing a multiaddress
which uses `ws` on top of TCP/IP will automatically use the `XMLHttpRequest` Javascript object.

```rust
use libp2p_websocket::WsConfig;

let ws_config = WsConfig::new();
// let _ = ws_config.dial(Multiaddr::new("/ip4/40.41.42.43/tcp/12345/ws").unwrap());
```

# Other operating systems

On other operating systems, this library doesn't open any socket by itself. Instead it must be
plugged on top of another implementation of `Transport` such as TCP/IP.

This underlying transport must be passed to the `WsConfig::new()` function.

```rust
extern crate libp2p_tcp_transport;
extern crate libp2p_websocket;
extern crate tokio_core;

use libp2p_websocket::WsConfig;
use libp2p_tcp_transport::TcpConfig;
use tokio_core::reactor::Core;

let core = Core::new().unwrap();
let ws_config = WsConfig::new(TcpConfig::new(core.handle()));
// let _ = ws_config.dial(Multiaddr::new("/ip4/40.41.42.43/tcp/12345/ws").unwrap());
```

0 comments on commit 777e5a9

Please sign in to comment.