diff --git a/libp2p-ping/Cargo.toml b/libp2p-ping/Cargo.toml index dd8c831a..53e6c122 100644 --- a/libp2p-ping/Cargo.toml +++ b/libp2p-ping/Cargo.toml @@ -14,4 +14,5 @@ rand = "0.3" tokio-io = "0.1" [dev-dependencies] +libp2p-tcp-transport = { path = "../libp2p-tcp-transport" } tokio-core = "0.1" diff --git a/libp2p-ping/README.md b/libp2p-ping/README.md new file mode 100644 index 00000000..620235c7 --- /dev/null +++ b/libp2p-ping/README.md @@ -0,0 +1,54 @@ +Handles the `/ipfs/ping/1.0.0` protocol. This allows pinging a remote node and waiting for an +answer. + +# Usage + +Create a `Ping` struct, which implements the `ConnectionUpgrade` trait. When used as a +connection upgrade, it will produce a tuple of type `(Pinger, impl Future)` which +are named the *pinger* and the *ponger*. + +The *pinger* has a method named `ping` which will send a ping to the remote, while the *ponger* +is a future that will process the data received on the socket and will be signalled only when +the connection closes. + +# About timeouts + +For technical reasons, this crate doesn't handle timeouts. The action of pinging returns a +future that is signalled only when the remote answers. If the remote is not responsive, the +future will never be signalled. + +For implementation reasons, resources allocated for a ping are only ever fully reclaimed after +a pong has been received by the remote. Therefore if you repeatidely ping a non-responsive +remote you will end up using more and memory memory (albeit the amount is very very small every +time), even if you destroy the future returned by `ping`. + +This is probably not a problem in practice, because the nature of the ping protocol is to +determine whether a remote is still alive, and any reasonable user of this crate will close +connections to non-responsive remotes. + +# Example + +```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::TcpConfig::new(core.handle()) + .with_upgrade(Ping) + .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(); +``` + diff --git a/libp2p-ping/src/lib.rs b/libp2p-ping/src/lib.rs index 8d87a7b2..ef7eb909 100644 --- a/libp2p-ping/src/lib.rs +++ b/libp2p-ping/src/lib.rs @@ -18,6 +18,9 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +// TODO: use this once stable ; for now we just copy-paste the content of the README.md +//#![doc(include = "../README.md")] + //! Handles the `/ipfs/ping/1.0.0` protocol. This allows pinging a remote node and waiting for an //! answer. //! @@ -46,6 +49,34 @@ //! determine whether a remote is still alive, and any reasonable user of this crate will close //! connections to non-responsive remotes. //! +//! # Example +//! +//! ```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::TcpConfig::new(core.handle()) +//! .with_upgrade(Ping) +//! .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(); +//! # } +//! ``` +//! extern crate bytes; extern crate futures;