Skip to main content

running_process_platform_internal/platform/
ipc.rs

1//! Local endpoint, listener, connection, peer, handoff, and security primitives.
2//!
3//! Endpoint strings and protocol policy remain with callers. These opaque
4//! values own the selected host transport so callers never name Unix sockets,
5//! Windows named pipes, `interprocess` types, file descriptors, or handles.
6
7#[cfg(feature = "ipc")]
8pub use crate::{
9    ipc_current_user_id as current_user_id, IpcEndpoint as Endpoint, IpcListener as Listener,
10    IpcListenerNonblockingMode as ListenerNonblockingMode, IpcPeerIdentity as PeerIdentity,
11    IpcStream as Stream,
12};
13
14#[cfg(feature = "ipc-async")]
15pub use crate::{IpcAsyncListener as AsyncListener, IpcAsyncStream as AsyncStream};
16
17#[cfg(all(test, feature = "ipc"))]
18mod tests {
19    use std::io::{Read, Write};
20
21    use super::{current_user_id, Endpoint, Listener, Stream};
22
23    #[test]
24    fn sync_bind_accept_connect_and_peer_identity_round_trip() {
25        let endpoint = Endpoint::test("sync-roundtrip").expect("test endpoint");
26        let listener = Listener::bind(&endpoint).expect("bind");
27        let expected_user = current_user_id().expect("current user identity");
28        let server = std::thread::spawn(move || {
29            let mut stream = listener.accept().expect("accept");
30            let peer = stream.peer_identity().expect("peer identity");
31            assert_eq!(peer.user_id, expected_user);
32            let mut request = [0_u8; 4];
33            stream.read_exact(&mut request).expect("read request");
34            assert_eq!(&request, b"ping");
35            stream.write_all(b"pong").expect("write response");
36        });
37
38        let mut client = Stream::connect(&endpoint).expect("connect");
39        client.write_all(b"ping").expect("write request");
40        let mut response = [0_u8; 4];
41        client.read_exact(&mut response).expect("read response");
42        assert_eq!(&response, b"pong");
43        server.join().expect("server thread");
44    }
45
46    #[cfg(feature = "ipc-async")]
47    #[tokio::test]
48    async fn async_bind_accept_connect_and_peer_identity_round_trip() {
49        use super::{AsyncListener, AsyncStream};
50        use tokio::io::{AsyncReadExt, AsyncWriteExt};
51
52        let endpoint = Endpoint::test("async-roundtrip").expect("test endpoint");
53        let listener = AsyncListener::bind(&endpoint).expect("bind");
54        let expected_user = current_user_id().expect("current user identity");
55        let server = tokio::spawn(async move {
56            let mut stream = listener.accept().await.expect("accept");
57            let peer = stream.peer_identity().expect("peer identity");
58            assert_eq!(peer.user_id, expected_user);
59            let mut request = [0_u8; 4];
60            stream.read_exact(&mut request).await.expect("read request");
61            assert_eq!(&request, b"ping");
62            stream.write_all(b"pong").await.expect("write response");
63        });
64
65        let mut client = AsyncStream::connect(&endpoint).await.expect("connect");
66        client.write_all(b"ping").await.expect("write request");
67        let mut response = [0_u8; 4];
68        client
69            .read_exact(&mut response)
70            .await
71            .expect("read response");
72        assert_eq!(&response, b"pong");
73        server.await.expect("server task");
74    }
75}