diff --git a/core/src/lib.rs b/core/src/lib.rs index 770a312d..a5e668ec 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. +// Copyright 2017-2018 Parity Technologies (UK) Ltd. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -23,145 +23,34 @@ //! This crate contains all the core traits and mechanisms of the transport and swarm systems //! of *libp2p*. //! -//! # The `Transport` trait +//! # Overview //! -//! 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. The `swarm` crate -//! itself does not provide any concrete (i.e. non-dummy, non-adapter) implementation of this trait. -//! It is implemented on structs that are provided by external crates, such as `TcpConfig` from -//! `tcp-transport`, `UdpConfig`, or `WebsocketConfig` (note: as of the writing of this -//! documentation, the last two structs don't exist yet). +//! This documentation focuses on the concepts of *libp2p-core*, and is interesting mostly if you +//! want to extend *libp2p* with new protocols. If you only want to use libp2p, you might find the +//! documentation of the main *libp2p* crate more interesting. //! -//! Each implementation of `Transport` only supports *some* multiaddress protocols, for example -//! the `TcpConfig` struct only supports multiaddresses that look like `/ip*/*.*.*.*/tcp/*`. It is -//! possible to group two implementations of `Transport` 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 a row in order to chain as many implementations as you want. +//! The main concepts of libp2p are: //! -//! // TODO: right now only tcp-transport exists, we need to add an example for chaining -//! // multiple transports once that makes sense -//! -//! ## The `MuxedTransport` trait -//! -//! The `MuxedTransport` trait is an extension to the `Transport` trait, and is implemented on -//! transports that can receive incoming connections on streams that have been opened with `dial()`. -//! -//! The trait provides the `next_incoming()` method, which returns a future that will resolve to -//! the next substream that arrives from a dialed node. -//! -//! > **Note**: This trait is mainly implemented for transports that provide stream muxing -//! > capabilities, but it can also be implemented in a dummy way by returning an empty -//! > iterator. -//! -//! # 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 three kinds of connection upgrades: middlewares, muxers, and actual protocols. -//! -//! ## Middlewares -//! -//! Examples of middleware connection upgrades include `PlainTextConfig` (dummy upgrade) or -//! `SecioConfig` (encryption layer, provided by the `secio` crate). -//! -//! The output of a middleware connection upgrade implements the `AsyncRead` and `AsyncWrite` -//! traits, just like sockets do. -//! -//! A middleware can be applied on a transport 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 or a listener that will yield upgraded connections. Similarly, the -//! `next_incoming()` method will automatically apply the upgrade on both the dialer and the -//! listener. An error is produced if the remote doesn't support the protocol corresponding to the -//! connection upgrade. -//! -//! ``` -//! extern crate libp2p_core; -//! extern crate libp2p_tcp_transport; -//! -//! use libp2p_core::Transport; -//! -//! # fn main() { -//! let tcp_transport = libp2p_tcp_transport::TcpConfig::new(); -//! let upgraded = tcp_transport.with_upgrade(libp2p_core::upgrade::DeniedUpgrade); -//! -//! // upgraded.dial(...) // automatically applies the plain text protocol on the socket -//! # } -//! ``` -//! -//! ## Muxers -//! -//! The concept of *muxing* consists in using a single stream as if it was multiple substreams. -//! -//! If the output of the connection upgrade instead implements the `StreamMuxer` and `Clone` -//! traits, then you can turn the `UpgradedNode` struct into a `ConnectionReuse` struct by calling -//! `ConnectionReuse::from(upgraded_node)`. -//! -//! The `ConnectionReuse` struct then implements the `Transport` and `MuxedTransport` traits, and -//! can be used to dial or listen to multiaddresses, just like any other transport. The only -//! difference is that dialing a node will try to open a new substream on an existing connection -//! instead of opening a new one every time. -//! -//! > **Note**: Right now the `ConnectionReuse` struct is not fully implemented. -//! -//! TODO: add an example once the multiplex pull request is merged -//! -//! ## Actual protocols -//! -//! *Actual protocols* work the same way as middlewares, except that their `Output` doesn't -//! implement the `AsyncRead` and `AsyncWrite` traits. This means that that the return value of -//! `with_upgrade` does **not** implement the `Transport` trait and thus cannot be used as a -//! transport. -//! -//! However the `UpgradedNode` struct returned by `with_upgrade` still provides methods named -//! `dial`, `listen_on`, and `next_incoming`, which will yield you 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_core; -//! extern crate libp2p_tcp_transport; -//! extern crate tokio; -//! -//! use futures::{Future, Stream}; -//! use libp2p_ping::protocol::Ping; -//! use libp2p_core::{Transport, upgrade::apply_outbound}; -//! use tokio::runtime::current_thread::Runtime; -//! -//! # fn main() { -//! let ping_dialer = libp2p_tcp_transport::TcpConfig::new() -//! // We have a `TcpConfig` struct that implements `Dialer`, and apply a `Ping` upgrade on it. -//! .and_then(|socket, _| { -//! apply_outbound(socket, Ping::default()).map_err(|e| e.into_io_error()) -//! }) -//! // TODO: right now the only available protocol is ping, but we want to replace it with -//! // something that is more simple to use -//! .dial("/ip4/127.0.0.1/tcp/12345".parse::().unwrap()).unwrap_or_else(|_| panic!()) -//! .and_then(|mut pinger| { -//! pinger.ping(()); -//! let f = pinger.into_future().map(|_| ()).map_err(|(e, _)| e); -//! Box::new(f) as Box> -//! }); -//! -//! // Runs until the ping arrives. -//! let mut rt = Runtime::new().unwrap(); -//! let _ = rt.block_on(ping_dialer).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. +//! - A `PeerId` is a unique global identifier for a node on the network. Each node must have a +//! different `PeerId`. Normally, a `PeerId` is the hash of the public key used to negotiate +//! encryption on the communication channel, thereby guaranteeing that they cannot be spoofed. +//! - The `Transport` trait defines how to reach a remote node or listen for incoming remote +//! connections. See the `transport` module. +//! - The `Swarm` struct contains all active and pending connections to remotes and manages the +//! state of all the substreams that have been opened, and all the upgrades that were built upon +//! these substreams. +//! - Use the `NetworkBehaviour` trait to customize the behaviour of a `Swarm`. It is the +//! `NetworkBehaviour` that controls what happens on the network. Multiple types that implement +//! `NetworkBehaviour` can be composed into a single behaviour. +//! - The `Topology` trait is implemented for types that hold the layout of a network. When other +//! components need the network layout to operate, they are passed an instance of a `Topology`. +//! - The `StreamMuxer` trait is implemented on structs that hold a connection to a remote and can +//! subdivide this connection into multiple substreams. See the `muxing` module. +//! - The `UpgradeInfo`, `InboundUpgrade` and `OutboundUpgrade` traits define how to upgrade each +//! individual substream to use a protocol. See the `upgrade` module. +//! - The `ProtocolsHandler` trait defines how each active connection to a remote should behave: +//! how to handle incoming substreams, which protocols are supported, when to open a new +//! outbound substream, etc. See the `protocols_handler` trait. //! extern crate bs58;