What is the `NetworkBehaviourEventProcess` abstraction?

With the following code block from the Rust chat example, can someone explain to me (or point me to docs that explain) what the NetworkBehaviourEventProcess abstraction is exactly. And what the generic-like traits it requires (FloodsubEvent, and MdnsEvent in this particular example). Again, I feel like this is already explained somewhere, so any links are helpful.

I’ve also ready the Introduction :: libp2p Documentation docs (just FYI)

    impl NetworkBehaviourEventProcess<FloodsubEvent> for ChatBehavior {
        fn inject_event(&mut self, message: FloodsubEvent) {
            if let FloodsubEvent::Message(message) = message {
                info!("Received: '{:?}' from {:?}", String::from_utf8_lossy(&message.data), message.source);
            }
        }
    }

    impl NetworkBehaviourEventProcess<MdnsEvent> for ChatBehavior {
        fn inject_event(&mut self, event: MdnsEvent) {
            match event {
                MdnsEvent::Discovered(list) => 
                    for (peer, _) in list {
                        self.floodsub.add_node_to_partial_view(peer);
                    }
                MdnsEvent::Expired(list) => 
                    for (peer, _) in list {
                        if !self.mdns.has_node(&peer) {
                            self.floodsub.remove_node_from_partial_view(&peer);
                        }
                    }
            }
        }
    }

Hi @aar3,

Max here, one of the maintainers of rust-libp2p. I am sorry for the late reply. In case you ever feel like not getting your Rust related questions answered, feel free to open up an issue on rust-libp2p directly. Next to your actual question.

Let’s start off with a high level perspective by talking about NetworkBehaviour. From the docs:

A behaviour for the network. Allows customizing the swarm.

Ok, this is a bit abstract. Said in a more simplified way, a NetworkBehaviour allows a user of rust-libp2 to implement different application protocols. Some examples which rust-libp2p already provides are, as you mentioned, FloodSub (a gossip protocol) and Mdns (a way to discover nodes on the local network).

The NetworkBehaviour docs continue like so:

This trait has been designed to be composable. Multiple implementations can be combined into one that handles all the behaviours at once.

Instead of having to run multiple rust-libp2p instances in order to run different user protocols, you can combine different NetworkBehaviours into a single one, thus only needing to run a single rust-libp2p instance.

So how does one combine NetworkBehaviours?

One way is via the NetworkBehaviour derive macro which you saw in the chat example. As a user you just need to define an overarching struct with all the NetworkBehaviours that you want to combine:

    struct MyBehaviour {
        floodsub: Floodsub,
        mdns: Mdns,
    }

and then add the derive attribute:

    #[derive(NetworkBehaviour)]
    struct MyBehaviour {
        floodsub: Floodsub,
        mdns: Mdns,
    }

and the derive macro will implement all the NetworkBehaviour trait methods.

One thing that the derive macro can not know is how to combine the events generated by each individual NetworkBehaviour. This is where you as the user and the NetworkBehaviourEventProcess trait come into play.

E.g. in the chat example you implement this trait for your combined behaviour:

    impl NetworkBehaviourEventProcess<FloodsubEvent> for MyBehaviour {
        // 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);
            }
        }
    }

By implemnting the NetworkBehaviourEventProcess you specify what should happen with each event emitted by the individual NetworkBehaviours that you combine. In this particular case you specify that for each FloodsubEvent::Message you want the content to be printed to stdout.

Let me know in case the above is of some help or whether you have further questions.

Thanks for such a sufficient and concise answer @mxinden :slight_smile: