mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-29 01:31:33 +00:00
Merge pull request #60 from tomaka/swarm-docs
Add documentation and README to libp2p-swarm
This commit is contained in:
@ -11,3 +11,8 @@ futures = "0.1"
|
|||||||
smallvec = "0.5"
|
smallvec = "0.5"
|
||||||
tokio-core = "0.1"
|
tokio-core = "0.1"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
libp2p-ping = { path = "../libp2p-ping" }
|
||||||
|
libp2p-tcp-transport = { path = "../libp2p-tcp-transport" }
|
||||||
|
tokio-core = "0.1"
|
||||||
|
105
libp2p-swarm/README.md
Normal file
105
libp2p-swarm/README.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
Transport and protocol upgrade system of *libp2p*.
|
||||||
|
|
||||||
|
This crate contains all the core traits and mechanisms of the transport system of *libp2p*.
|
||||||
|
|
||||||
|
# The `Transport` trait
|
||||||
|
|
||||||
|
The main trait that this crate provides is `Transport`, which provides the `dial` and
|
||||||
|
`listen_on` methods and can be used to dial or listen on a multiaddress. This crate does not
|
||||||
|
provide any concrete (non-dummy, non-adapter) implementation of this trait. It is implemented
|
||||||
|
on structs such as `TcpConfig`, `UdpConfig`, `WebsocketConfig` that are provided by external
|
||||||
|
crates.
|
||||||
|
|
||||||
|
Each implementation of `Transport` only supports *some* multiaddress protocols, for example
|
||||||
|
the `TcpConfig` struct only supports multiaddresses that look like `/ip*/*.*.*.*/tcp/*`. Two
|
||||||
|
implementations of `Transport` can be grouped together with the `or_transport` method, in order
|
||||||
|
to obtain a single object that supports the protocols of both objects at once. This can be done
|
||||||
|
multiple times in order to chain as many implementations as you want.
|
||||||
|
|
||||||
|
// TODO: right now only tcp-transport exists, but we need to add an example for chaining multiple
|
||||||
|
// transports once that makes sense
|
||||||
|
|
||||||
|
# Connection upgrades
|
||||||
|
|
||||||
|
Once a socket has been opened with a remote through a `Transport`, it can be *upgraded*. This
|
||||||
|
consists in negotiating a protocol with the remote (through `multistream-select`), and applying
|
||||||
|
that protocol on the socket.
|
||||||
|
|
||||||
|
A potential connection upgrade is represented with the `ConnectionUpgrade` trait. The trait
|
||||||
|
consists in a protocol name plus a method that turns the socket into an `Output` object whose
|
||||||
|
nature and type is specific to each upgrade.
|
||||||
|
|
||||||
|
There exists two kinds of connection upgrades: middlewares, and actual protocols.
|
||||||
|
|
||||||
|
## Middlewares
|
||||||
|
|
||||||
|
Examples of middleware protocol upgrades include `PlainTextConfig` (dummy upgrade),
|
||||||
|
`SecioConfig` (encyption layer), or `MultiplexConfig`.
|
||||||
|
|
||||||
|
The output of a middleware protocol upgrade must implement the `AsyncRead` and `AsyncWrite`
|
||||||
|
traits, just like sockets do.
|
||||||
|
|
||||||
|
A middleware can be applied by using the `with_upgrade` method of the `Transport` trait. The
|
||||||
|
return value of this method also implements the `Transport` trait, which means that you can
|
||||||
|
call `dial()` and `listen_on()` on it in order to directly obtain an upgraded connection. An
|
||||||
|
error is produced if the remote doesn't support the protocol that you are trying to negotiate.
|
||||||
|
|
||||||
|
```
|
||||||
|
extern crate libp2p_swarm;
|
||||||
|
extern crate libp2p_tcp_transport;
|
||||||
|
extern crate tokio_core;
|
||||||
|
|
||||||
|
use libp2p_swarm::Transport;
|
||||||
|
|
||||||
|
let tokio_core = tokio_core::reactor::Core::new().unwrap();
|
||||||
|
let tcp_transport = libp2p_tcp_transport::Tcp::new(tokio_core.handle()).unwrap();
|
||||||
|
let upgraded = tcp_transport.with_upgrade(libp2p_swarm::PlainText);
|
||||||
|
|
||||||
|
// upgraded.dial(...) // automatically applies the plain text protocol on the socket
|
||||||
|
```
|
||||||
|
|
||||||
|
## Actual protocols
|
||||||
|
|
||||||
|
*Actual protocols* work the same way as middlewares, except that their `Output` doesn't
|
||||||
|
implement the `AsyncRead` and `AsyncWrite` traits. The consequence of this is that the return
|
||||||
|
value of `with_upgrade` **cannot** doesn't implement the `Transport` trait and thus cannot be
|
||||||
|
used as a transport.
|
||||||
|
|
||||||
|
However the value returned by `with_upgrade` still provides methods named `dial` and
|
||||||
|
`listen_on`, which will yield you respectively a `Future` or a `Stream`, which you can use to
|
||||||
|
obtain the `Output`. This `Output` can then be used in a protocol-specific way to use the
|
||||||
|
protocol.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
extern crate futures;
|
||||||
|
extern crate libp2p_ping;
|
||||||
|
extern crate libp2p_swarm;
|
||||||
|
extern crate libp2p_tcp_transport;
|
||||||
|
extern crate tokio_core;
|
||||||
|
|
||||||
|
use futures::Future;
|
||||||
|
use libp2p_ping::Ping;
|
||||||
|
use libp2p_swarm::Transport;
|
||||||
|
|
||||||
|
let mut core = tokio_core::reactor::Core::new().unwrap();
|
||||||
|
|
||||||
|
let ping_finished_future = libp2p_tcp_transport::Tcp::new(core.handle()).unwrap()
|
||||||
|
// We have a `Tcp` struct that implements `Transport`, and apply a `Ping` upgrade on it.
|
||||||
|
.with_upgrade(Ping)
|
||||||
|
// TODO: right now the only available protocol is ping, but we want to replace it with
|
||||||
|
// something that is more simple to use
|
||||||
|
.dial(libp2p_swarm::Multiaddr::new("127.0.0.1:12345").unwrap()).unwrap_or_else(|_| panic!())
|
||||||
|
.and_then(|(mut pinger, service)| {
|
||||||
|
pinger.ping().map_err(|_| panic!()).select(service).map_err(|_| panic!())
|
||||||
|
});
|
||||||
|
|
||||||
|
// Runs until the ping arrives.
|
||||||
|
core.run(ping_finished_future).unwrap();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Grouping protocols
|
||||||
|
|
||||||
|
You can use the `.or_upgrade()` method to group multiple upgrades together. The return value
|
||||||
|
also implements the `ConnectionUpgrade` trait and will choose one of the protocols amongst the
|
||||||
|
ones supported.
|
||||||
|
|
@ -18,7 +18,118 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
//! Transport and I/O primitives for libp2p.
|
// TODO: use this once stable ; for now we just copy-paste the content of the README.md
|
||||||
|
//#![doc(include = "../README.md")]
|
||||||
|
|
||||||
|
//! Transport and protocol upgrade system of *libp2p*.
|
||||||
|
//!
|
||||||
|
//! This crate contains all the core traits and mechanisms of the transport system of *libp2p*.
|
||||||
|
//!
|
||||||
|
//! # The `Transport` trait
|
||||||
|
//!
|
||||||
|
//! The main trait that this crate provides is `Transport`, which provides the `dial` and
|
||||||
|
//! `listen_on` methods and can be used to dial or listen on a multiaddress. This crate does not
|
||||||
|
//! provide any concrete (non-dummy, non-adapter) implementation of this trait. It is implemented
|
||||||
|
//! on structs such as `TcpConfig`, `UdpConfig`, `WebsocketConfig` that are provided by external
|
||||||
|
//! crates.
|
||||||
|
//!
|
||||||
|
//! Each implementation of `Transport` only supports *some* multiaddress protocols, for example
|
||||||
|
//! the `TcpConfig` struct only supports multiaddresses that look like `/ip*/*.*.*.*/tcp/*`. Two
|
||||||
|
//! implementations of `Transport` can be grouped together with the `or_transport` method, in order
|
||||||
|
//! to obtain a single object that supports the protocols of both objects at once. This can be done
|
||||||
|
//! multiple times in order to chain as many implementations as you want.
|
||||||
|
//!
|
||||||
|
//! // TODO: right now only tcp-transport exists, but we need to add an example for chaining multiple
|
||||||
|
//! // transports once that makes sense
|
||||||
|
//!
|
||||||
|
//! # Connection upgrades
|
||||||
|
//!
|
||||||
|
//! Once a socket has been opened with a remote through a `Transport`, it can be *upgraded*. This
|
||||||
|
//! consists in negotiating a protocol with the remote (through `multistream-select`), and applying
|
||||||
|
//! that protocol on the socket.
|
||||||
|
//!
|
||||||
|
//! A potential connection upgrade is represented with the `ConnectionUpgrade` trait. The trait
|
||||||
|
//! consists in a protocol name plus a method that turns the socket into an `Output` object whose
|
||||||
|
//! nature and type is specific to each upgrade.
|
||||||
|
//!
|
||||||
|
//! There exists two kinds of connection upgrades: middlewares, and actual protocols.
|
||||||
|
//!
|
||||||
|
//! ## Middlewares
|
||||||
|
//!
|
||||||
|
//! Examples of middleware protocol upgrades include `PlainTextConfig` (dummy upgrade),
|
||||||
|
//! `SecioConfig` (encyption layer), or `MultiplexConfig`.
|
||||||
|
//!
|
||||||
|
//! The output of a middleware protocol upgrade must implement the `AsyncRead` and `AsyncWrite`
|
||||||
|
//! traits, just like sockets do.
|
||||||
|
//!
|
||||||
|
//! A middleware can be applied by using the `with_upgrade` method of the `Transport` trait. The
|
||||||
|
//! return value of this method also implements the `Transport` trait, which means that you can
|
||||||
|
//! call `dial()` and `listen_on()` on it in order to directly obtain an upgraded connection. An
|
||||||
|
//! error is produced if the remote doesn't support the protocol that you are trying to negotiate.
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! extern crate libp2p_swarm;
|
||||||
|
//! extern crate libp2p_tcp_transport;
|
||||||
|
//! extern crate tokio_core;
|
||||||
|
//!
|
||||||
|
//! use libp2p_swarm::Transport;
|
||||||
|
//!
|
||||||
|
//! # fn main() {
|
||||||
|
//! let tokio_core = tokio_core::reactor::Core::new().unwrap();
|
||||||
|
//! let tcp_transport = libp2p_tcp_transport::Tcp::new(tokio_core.handle()).unwrap();
|
||||||
|
//! let upgraded = tcp_transport.with_upgrade(libp2p_swarm::PlainText);
|
||||||
|
//!
|
||||||
|
//! // upgraded.dial(...) // automatically applies the plain text protocol on the socket
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ## Actual protocols
|
||||||
|
//!
|
||||||
|
//! *Actual protocols* work the same way as middlewares, except that their `Output` doesn't
|
||||||
|
//! implement the `AsyncRead` and `AsyncWrite` traits. The consequence of this is that the return
|
||||||
|
//! value of `with_upgrade` **cannot** doesn't implement the `Transport` trait and thus cannot be
|
||||||
|
//! used as a transport.
|
||||||
|
//!
|
||||||
|
//! However the value returned by `with_upgrade` still provides methods named `dial` and
|
||||||
|
//! `listen_on`, which will yield you respectively a `Future` or a `Stream`, which you can use to
|
||||||
|
//! obtain the `Output`. This `Output` can then be used in a protocol-specific way to use the
|
||||||
|
//! protocol.
|
||||||
|
//!
|
||||||
|
//! ```no_run
|
||||||
|
//! extern crate futures;
|
||||||
|
//! extern crate libp2p_ping;
|
||||||
|
//! extern crate libp2p_swarm;
|
||||||
|
//! extern crate libp2p_tcp_transport;
|
||||||
|
//! extern crate tokio_core;
|
||||||
|
//!
|
||||||
|
//! use futures::Future;
|
||||||
|
//! use libp2p_ping::Ping;
|
||||||
|
//! use libp2p_swarm::Transport;
|
||||||
|
//!
|
||||||
|
//! # fn main() {
|
||||||
|
//! let mut core = tokio_core::reactor::Core::new().unwrap();
|
||||||
|
//!
|
||||||
|
//! let ping_finished_future = libp2p_tcp_transport::Tcp::new(core.handle()).unwrap()
|
||||||
|
//! // We have a `Tcp` struct that implements `Transport`, and apply a `Ping` upgrade on it.
|
||||||
|
//! .with_upgrade(Ping)
|
||||||
|
//! // TODO: right now the only available protocol is ping, but we want to replace it with
|
||||||
|
//! // something that is more simple to use
|
||||||
|
//! .dial(libp2p_swarm::Multiaddr::new("127.0.0.1:12345").unwrap()).unwrap_or_else(|_| panic!())
|
||||||
|
//! .and_then(|(mut pinger, service)| {
|
||||||
|
//! pinger.ping().map_err(|_| panic!()).select(service).map_err(|_| panic!())
|
||||||
|
//! });
|
||||||
|
//!
|
||||||
|
//! // Runs until the ping arrives.
|
||||||
|
//! core.run(ping_finished_future).unwrap();
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ## Grouping protocols
|
||||||
|
//!
|
||||||
|
//! You can use the `.or_upgrade()` method to group multiple upgrades together. The return value
|
||||||
|
//! also implements the `ConnectionUpgrade` trait and will choose one of the protocols amongst the
|
||||||
|
//! ones supported.
|
||||||
|
//!
|
||||||
|
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@ -35,5 +146,6 @@ pub mod muxing;
|
|||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|
||||||
pub use self::connection_reuse::ConnectionReuse;
|
pub use self::connection_reuse::ConnectionReuse;
|
||||||
|
pub use self::multiaddr::Multiaddr;
|
||||||
pub use self::muxing::StreamMuxer;
|
pub use self::muxing::StreamMuxer;
|
||||||
pub use self::transport::{ConnectionUpgrade, PlainText, Transport, UpgradedNode, OrUpgrade};
|
pub use self::transport::{ConnectionUpgrade, PlainText, Transport, UpgradedNode, OrUpgrade};
|
||||||
|
Reference in New Issue
Block a user