Sending messages

The core of our application has been built. All that's left is to add a UI that takes user input, creates a DchatMsg and sends it over the network.

Let's start by creating a send() function inside Dchat. This will introduce us to a new p2p method that is essential to our chat app: p2p.broadcast().

    async fn send(&self, msg: String) -> Result<()> {
        let dchatmsg = DchatMsg { msg };
        self.p2p.broadcast(dchatmsg).await?;
        Ok(())
    }

We pass a String called msg that will be taken from user input. We use this input to initialize a message of the type DchatMsg that the network can now support. Finally, we pass the message into p2p.broadcast().

Here's what happens under the hood:

    pub async fn broadcast<M: Message + Clone>(&self, message: M) -> Result<()> {
        let chans = self.channels.lock().await;
        let iter = chans.values();
        let mut futures = FuturesUnordered::new();

        for channel in iter {
            futures.push(channel.send(message.clone()).map_err(|e| {
                format!(
                    "P2P::broadcast: Broadcasting message to {} failed: {}",
                    channel.address(),
                    e
                )
            }));
        }

        if futures.is_empty() {
            error!(target: "net::p2p::broadcast()", "P2P::broadcast: No connected channels found");
            return Ok(())
        }

        while let Some(entry) = futures.next().await {
            if let Err(e) = entry {
                error!(target: "net::p2p::broadcast()", "{}", e);
            }
        }

        Ok(())
    }

This is pretty straightforward: broadcast() takes a generic Message type and sends it across all the channels that our node has access to.

All that's left to do is to create a UI.