nip_55/uds_req_res/
client.rs

1use super::{UdsRequest, UdsResponse};
2use tokio::io::{AsyncReadExt, AsyncWriteExt};
3use tokio::net::UnixStream;
4
5#[derive(Clone)]
6pub struct UnixDomainSocketClientTransport {
7    uds_address: String,
8}
9
10impl UnixDomainSocketClientTransport {
11    pub fn new(uds_address: impl Into<String>) -> Self {
12        Self {
13            uds_address: uds_address.into(),
14        }
15    }
16
17    pub async fn send_request<Request: UdsRequest, Response: UdsResponse>(
18        &self,
19        request: Request,
20    ) -> Result<Response, UdsClientError> {
21        let serialized_request =
22            serde_json::to_vec(&request).map_err(|_| UdsClientError::RequestSerializationError)?;
23        let serialize_response = self.send_and_receive_bytes(serialized_request).await?;
24        serde_json::from_slice::<Response>(&serialize_response)
25            .map_err(|e| UdsClientError::MalformedResponse(e.into()))
26    }
27
28    async fn send_and_receive_bytes(
29        &self,
30        serialized_request: Vec<u8>,
31    ) -> Result<Vec<u8>, UdsClientError> {
32        // Open up a UDS connection to the server.
33        let mut socket = UnixStream::connect(&self.uds_address)
34            .await
35            .map_err(|_| UdsClientError::ServerNotRunning)?;
36
37        socket
38            .write_all(&serialized_request)
39            .await
40            .map_err(|_| UdsClientError::UdsSocketError)?;
41        socket
42            .shutdown()
43            .await
44            .map_err(|_| UdsClientError::UdsSocketError)?;
45
46        // Read the response from the server.
47        // TODO: Add a timeout to this read operation.
48        let mut buf = Vec::new();
49        socket
50            .read_to_end(&mut buf)
51            .await
52            .map_err(|_| UdsClientError::UdsSocketError)?;
53        Ok(buf)
54    }
55}
56
57/// Error that can occur when communicating with a Unix domain socket server.
58#[derive(Debug)]
59pub enum UdsClientError {
60    /// A Unix domain socket server is not running on the specified address.
61    ServerNotRunning,
62
63    /// An I/O error occurred while writing to or reading from the Unix domain socket.
64    UdsSocketError,
65
66    /// An error occurred while serializing the request.
67    RequestSerializationError,
68
69    /// Received a response from the server that that cannot be parsed.
70    MalformedResponse(anyhow::Error),
71}
72
73impl std::fmt::Display for UdsClientError {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        match self {
76            Self::ServerNotRunning => {
77                write!(f, "Unix domain socket server not running.")
78            }
79            Self::UdsSocketError => {
80                write!(f, "Error writing to or reading from Unix domain socket.")
81            }
82            Self::RequestSerializationError => {
83                write!(f, "Error serializing the request.")
84            }
85            Self::MalformedResponse(malformed_response_error) => {
86                write!(
87                    f,
88                    "Received a response from the server that that cannot be parsed ({malformed_response_error})."
89                )
90            }
91        }
92    }
93}
94
95impl std::error::Error for UdsClientError {}