Enhance NetworkBehaviour docs (#1362)

* add docs about deriving NetworkBehaviour

* add commentary to the chat example

also minor stuff like reordering to match the struct elements, note why the listening address is
reported in poll.

* fix remove the warning on the example ignored field

* Apply suggestions from code review

Thanks for suggestions!

Co-Authored-By: Max Inden <mail@max-inden.de>

* chore cleanup added docs after suggestions

* fix print all listening addresses in examples/chat

not that there should be more than one but it makes sense to repeat the full example here.

* chore remove confusing writing on printing the listening addrs

* fix use intra-docs, spelling

Co-Authored-By: Roman S. Borschel <roman@parity.io>

Co-authored-by: Max Inden <mail@max-inden.de>
Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
This commit is contained in:
Joonas Koivunen 2020-01-14 13:48:16 +02:00 committed by Roman Borschel
parent 3f968cbf92
commit 7df3e74d79
3 changed files with 42 additions and 16 deletions

View File

@ -79,13 +79,30 @@ fn main() -> Result<(), Box<dyn Error>> {
// We create a custom network behaviour that combines floodsub and mDNS.
// In the future, we want to improve libp2p to make this easier to do.
// Use the derive to generate delegating NetworkBehaviour impl and require the
// NetworkBehaviourEventProcess implementations below.
#[derive(NetworkBehaviour)]
struct MyBehaviour<TSubstream: AsyncRead + AsyncWrite> {
floodsub: Floodsub<TSubstream>,
mdns: Mdns<TSubstream>,
// Struct fields which do not implement NetworkBehaviour need to be ignored
#[behaviour(ignore)]
#[allow(dead_code)]
ignored_member: bool,
}
impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<FloodsubEvent> for MyBehaviour<TSubstream> {
// Called when `floodsub` produces an event.
fn inject_event(&mut self, message: FloodsubEvent) {
if let FloodsubEvent::Message(message) = message {
println!("Received: '{:?}' from {:?}", String::from_utf8_lossy(&message.data), message.source);
}
}
}
impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<MdnsEvent> for MyBehaviour<TSubstream> {
// Called when `mdns` produces an event.
fn inject_event(&mut self, event: MdnsEvent) {
match event {
MdnsEvent::Discovered(list) =>
@ -102,21 +119,13 @@ fn main() -> Result<(), Box<dyn Error>> {
}
}
impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<FloodsubEvent> for MyBehaviour<TSubstream> {
// Called when `floodsub` produces an event.
fn inject_event(&mut self, message: FloodsubEvent) {
if let FloodsubEvent::Message(message) = message {
println!("Received: '{:?}' from {:?}", String::from_utf8_lossy(&message.data), message.source);
}
}
}
// Create a Swarm to manage peers and events
let mut swarm = {
let mdns = task::block_on(Mdns::new())?;
let mut behaviour = MyBehaviour {
floodsub: Floodsub::new(local_peer_id.clone()),
mdns
mdns,
ignored_member: false,
};
behaviour.floodsub.subscribe(floodsub_topic.clone());
@ -152,8 +161,8 @@ fn main() -> Result<(), Box<dyn Error>> {
Poll::Ready(None) => return Poll::Ready(Ok(())),
Poll::Pending => {
if !listening {
if let Some(a) = Swarm::listeners(&swarm).next() {
println!("Listening on {:?}", a);
for addr in Swarm::listeners(&swarm) {
println!("Listening on {:?}", addr);
listening = true;
}
}

View File

@ -26,7 +26,8 @@ use quote::quote;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, Data, DataStruct, Ident};
/// The interface that satisfies Rust.
/// Generates a delegating `NetworkBehaviour` implementation for the struct this is used for. See
/// the trait documentation for better description.
#[proc_macro_derive(NetworkBehaviour, attributes(behaviour))]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);

View File

@ -26,6 +26,23 @@ use std::{error, task::Context, task::Poll};
///
/// This trait has been designed to be composable. Multiple implementations can be combined into
/// one that handles all the behaviours at once.
///
/// # Deriving `NetworkBehaviour`
///
/// Crate users can implement this trait by using the the `#[derive(NetworkBehaviour)]`
/// proc macro re-exported by the `libp2p` crate. The macro generates a delegating `trait`
/// implementation for the `struct`, which delegates method calls to all trait members. Any events
/// generated by struct members are delegated to [`NetworkBehaviourEventProcess`] implementations
/// which are expected to be provided by the user.
///
/// Optionally one can implement a custom `poll` function, which needs to be tagged with the
/// `#[behaviour(poll_method = "poll")]` attribute, and would be called last with no parameters.
///
/// By default the derive sets the `NetworkBehaviour::OutEvent` as `()` but this can be overriden
/// with `#[behaviour(out_event = "AnotherType")]`.
///
/// `#[behaviour(ignore)]` can be added on a struct field to disable generation of delegation to
/// the fields which do not implement `NetworkBehaviour`.
pub trait NetworkBehaviour {
/// Handler for all the protocols the network behaviour supports.
type ProtocolsHandler: IntoProtocolsHandler;
@ -163,9 +180,8 @@ pub trait PollParameters {
fn local_peer_id(&self) -> &PeerId;
}
/// Used when deriving `NetworkBehaviour`. When deriving `NetworkBehaviour`, must be implemented
/// for all the possible event types generated by the various fields.
// TODO: document how the custom behaviour works and link this here
/// When deriving [`NetworkBehaviour`] this trait must be implemented for all the possible event types
/// generated by the inner behaviours.
pub trait NetworkBehaviourEventProcess<TEvent> {
/// Called when one of the fields of the type you're deriving `NetworkBehaviour` on generates
/// an event.