p2p_chat/net/
mailbox.rs

1//! This module defines the codec for the mailbox protocol, which is used for
2//! interacting with mailbox nodes.
3use crate::types::{MailboxRequest, MailboxResponse};
4use futures::prelude::*;
5use libp2p::request_response::{self, Codec, ProtocolSupport};
6use std::io;
7
8/// The codec for the mailbox protocol.
9///
10/// This codec is used by the `libp2p` `request_response` behaviour to encode
11/// and decode mailbox requests and responses.
12#[derive(Clone, Default)]
13pub struct MailboxCodec;
14
15impl MailboxCodec {
16    /// The protocol name for the mailbox protocol.
17    pub const PROTOCOL: &'static str = "/mailbox/1.0.0";
18}
19
20#[async_trait::async_trait]
21impl Codec for MailboxCodec {
22    type Protocol = &'static str;
23    type Request = MailboxRequest;
24    type Response = MailboxResponse;
25
26    /// Reads a length-prefixed JSON-encoded request from the given I/O stream.
27    async fn read_request<T>(&mut self, _: &Self::Protocol, io: &mut T) -> io::Result<Self::Request>
28    where
29        T: AsyncRead + Unpin + Send,
30    {
31        let mut length_buf = [0u8; 4];
32        io.read_exact(&mut length_buf).await?;
33        let length = u32::from_be_bytes(length_buf) as usize;
34
35        let mut data = vec![0u8; length];
36        io.read_exact(&mut data).await?;
37
38        serde_json::from_slice(&data).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
39    }
40
41    /// Reads a length-prefixed JSON-encoded response from the given I/O stream.
42    async fn read_response<T>(
43        &mut self,
44        _: &Self::Protocol,
45        io: &mut T,
46    ) -> io::Result<Self::Response>
47    where
48        T: AsyncRead + Unpin + Send,
49    {
50        let mut length_buf = [0u8; 4];
51        io.read_exact(&mut length_buf).await?;
52        let length = u32::from_be_bytes(length_buf) as usize;
53
54        let mut data = vec![0u8; length];
55        io.read_exact(&mut data).await?;
56
57        serde_json::from_slice(&data).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
58    }
59
60    /// Writes a length-prefixed JSON-encoded request to the given I/O stream.
61    async fn write_request<T>(
62        &mut self,
63        _: &Self::Protocol,
64        io: &mut T,
65        req: Self::Request,
66    ) -> io::Result<()>
67    where
68        T: AsyncWrite + Unpin + Send,
69    {
70        let data =
71            serde_json::to_vec(&req).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
72        let length = data.len() as u32;
73
74        io.write_all(&length.to_be_bytes()).await?;
75        io.write_all(&data).await?;
76        io.flush().await?;
77        Ok(())
78    }
79
80    /// Writes a length-prefixed JSON-encoded response to the given I/O stream.
81    async fn write_response<T>(
82        &mut self,
83        _: &Self::Protocol,
84        io: &mut T,
85        res: Self::Response,
86    ) -> io::Result<()>
87    where
88        T: AsyncWrite + Unpin + Send,
89    {
90        let data =
91            serde_json::to_vec(&res).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
92        let length = data.len() as u32;
93
94        io.write_all(&length.to_be_bytes()).await?;
95        io.write_all(&data).await?;
96        io.flush().await?;
97        Ok(())
98    }
99}
100
101/// The `libp2p` `request_response` behaviour for the mailbox protocol.
102pub type MailboxBehaviour = request_response::Behaviour<MailboxCodec>;
103
104/// Creates a new `MailboxBehaviour`.
105pub fn create_mailbox_behaviour() -> MailboxBehaviour {
106    use std::time::Duration;
107
108    let config = request_response::Config::default().with_request_timeout(Duration::from_secs(2));
109
110    request_response::Behaviour::new([(MailboxCodec::PROTOCOL, ProtocolSupport::Full)], config)
111}