Skip to main content

monocoque_core/
ipc.rs

1//! IPC transport via Unix domain sockets.
2//!
3//! Provides Unix domain socket support for inter-process communication
4//! with zero-copy and low-latency characteristics.
5
6#[cfg(unix)]
7use compio::net::{UnixListener, UnixStream};
8#[cfg(unix)]
9use std::path::Path;
10
11#[cfg(unix)]
12/// Connect to a Unix domain socket.
13///
14/// # Examples
15///
16/// ```no_run
17/// use monocoque_core::ipc;
18///
19/// #[compio::main]
20/// async fn main() -> std::io::Result<()> {
21///     let stream = ipc::connect("/tmp/socket.sock").await?;
22///     Ok(())
23/// }
24/// ```
25pub async fn connect<P: AsRef<Path>>(path: P) -> std::io::Result<UnixStream> {
26    UnixStream::connect(path).await
27}
28
29#[cfg(unix)]
30/// Bind a Unix domain socket listener.
31///
32/// Returns the listener ready to accept connections.
33///
34/// # Examples
35///
36/// ```no_run
37/// use monocoque_core::ipc;
38///
39/// #[compio::main]
40/// async fn main() -> std::io::Result<()> {
41///     let listener = ipc::bind("/tmp/socket.sock").await?;
42///     Ok(())
43/// }
44/// ```
45pub async fn bind<P: AsRef<Path>>(path: P) -> std::io::Result<UnixListener> {
46    // Remove existing socket file if it exists
47    let path_ref = path.as_ref();
48    if path_ref.exists() {
49        std::fs::remove_file(path_ref)?;
50    }
51
52    UnixListener::bind(path).await
53}
54
55#[cfg(unix)]
56/// Accept a connection on a Unix domain socket listener.
57pub async fn accept(listener: &UnixListener) -> std::io::Result<UnixStream> {
58    let (stream, _addr) = listener.accept().await?;
59    Ok(stream)
60}
61
62#[cfg(test)]
63#[cfg(unix)]
64mod tests {
65    use super::*;
66
67    #[compio::test]
68    async fn test_ipc_connect_bind() {
69        let path = "/tmp/monocoque_test_ipc.sock";
70
71        // Clean up any existing socket
72        let _ = std::fs::remove_file(path);
73
74        let listener = bind(path).await.unwrap();
75
76        // Spawn accept task
77        let accept_handle = compio::runtime::spawn(async move { accept(&listener).await });
78
79        // Give listener time to start
80        compio::time::sleep(std::time::Duration::from_millis(10)).await;
81
82        // Connect
83        let client = connect(path).await.unwrap();
84
85        // Wait for accept
86        let server = accept_handle.await.unwrap();
87
88        assert!(client.peer_addr().is_ok());
89        assert!(server.local_addr().is_ok());
90
91        // Cleanup
92        drop(client);
93        drop(server);
94        let _ = std::fs::remove_file(path);
95    }
96}