Skip to main content

acktor_ipc/
ipc_method.rs

1//! Traits for Inter-Process Communication (IPC) and some pre-implemented IPC methods.
2//!
3
4use std::io::Error;
5use std::pin::Pin;
6use std::sync::Arc;
7
8use bytes::Bytes;
9
10#[cfg(feature = "pipe")]
11#[cfg_attr(docsrs, doc(cfg(feature = "pipe")))]
12pub mod pipe;
13
14#[cfg(feature = "websocket")]
15#[cfg_attr(docsrs, doc(cfg(feature = "websocket")))]
16pub mod websocket;
17
18/// A boxed `Send` future returning `Result<T, std::io::Error>`, used as the return type
19/// of dyn-compatible trait methods in this module.
20pub type IoFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'a>>;
21
22/// Describes the behavior of an IPC listener which accepts incoming IPC connections.
23///
24/// A [`Node`][crate::node::Node] uses a listener to accept inbound connections. Outbound
25/// connections are initiated by calling [`IpcConnection::connect`] on a concrete connection
26/// type directly.
27pub trait IpcListener: Send + Sync + 'static {
28    /// Returns the local endpoint the listener is bound to.
29    fn local_endpoint(&self) -> &str;
30
31    /// Accepts an incoming IPC connection.
32    ///
33    /// # Cancel safety
34    ///
35    /// This method is **not** guaranteed to be cancel safe. If the returned future is dropped
36    /// before it completes, it may leave a peer-side connection in a partially-initialized state
37    /// (e.g. mid-handshake).
38    fn accept(&self) -> IoFuture<'_, Box<dyn IpcConnection>>;
39}
40
41/// Describes the behavior of an IPC connection.
42///
43/// An IPC connection should be a duplex communication channel between two end points. If the
44/// underlying protocol is not duplex, the implementation should simulate the duplex behavior,
45/// e.g., by using two separate connections.
46///
47/// Implementations are responsible for message framing: one call to [`send`](Self::send) must
48/// correspond to exactly one call to [`recv`](Self::recv) on the remote end, regardless of how
49/// the underlying transport delivers bytes.
50pub trait IpcConnection: Send + Sync + 'static {
51    /// Connects to an IPC listener at a specific endpoint.
52    ///
53    /// This is a constructor-style method that returns a concrete connection, so it requires
54    /// `Self: Sized`.
55    fn connect(endpoint: &str) -> impl Future<Output = Result<Self, Error>> + Send
56    where
57        Self: Sized;
58
59    /// Returns the peer endpoint of the IPC connection.
60    fn peer_endpoint(&self) -> &str;
61
62    /// Closes the IPC connection.
63    fn close(&mut self) -> IoFuture<'_, ()>;
64
65    /// Sends a message to the other end of the connection.
66    ///
67    /// The entire `buf` is delivered as a single framed message.
68    fn send(&mut self, buf: Bytes) -> IoFuture<'_, ()>;
69
70    /// Receives the next message from the other end of the connection.
71    ///
72    /// Returns the message payload as a [`Bytes`] value; implementations should return a slice
73    /// of their internal read buffer whenever possible to avoid copying.
74    ///
75    /// # Cancel safety
76    ///
77    /// The implementation should be cancel safe. If the method is used as the event in a
78    /// [`tokio::select!`](tokio::select) statement and some other branch completes first, then
79    /// it is guaranteed that no data was read from the underlying connection.
80    fn recv(&mut self) -> IoFuture<'_, Bytes>;
81}
82
83impl<T> IpcListener for Box<T>
84where
85    T: IpcListener + ?Sized,
86{
87    fn local_endpoint(&self) -> &str {
88        (**self).local_endpoint()
89    }
90
91    fn accept(&self) -> IoFuture<'_, Box<dyn IpcConnection>> {
92        (**self).accept()
93    }
94}
95
96impl<T> IpcListener for Arc<T>
97where
98    T: IpcListener + ?Sized,
99{
100    fn local_endpoint(&self) -> &str {
101        (**self).local_endpoint()
102    }
103
104    fn accept(&self) -> IoFuture<'_, Box<dyn IpcConnection>> {
105        (**self).accept()
106    }
107}