Skip to main content

bitwarden_ipc/
ipc_client_trait.rs

1use bitwarden_threading::cancellation_token::CancellationToken;
2
3use crate::{
4    broadcast::{BroadcastGroup, EndpointSendResult},
5    error::{AlreadyRunningError, BroadcastError, SendError, SubscribeError},
6    ipc_client::IpcClientSubscription,
7    message::OutgoingMessage,
8    rpc::exec::handler::ErasedRpcHandler,
9};
10
11/// Dyn-compatible trait for IPC client operations.
12///
13/// This trait provides the core IPC operations that consumers can use without
14/// being tied to a specific concrete `IpcClient` implementation. For generic
15/// convenience methods (typed subscriptions, RPC requests), use the
16/// [`IpcClientExt`](crate::IpcClientExt) extension trait which is automatically
17/// implemented for all `IpcClient` implementors.
18#[async_trait::async_trait]
19pub trait IpcClient: Send + Sync {
20    /// Start the IPC client, which will begin listening for incoming messages and processing them.
21    async fn start(
22        &self,
23        cancellation_token: Option<CancellationToken>,
24    ) -> Result<(), AlreadyRunningError>;
25
26    /// Check if the IPC client task is currently running.
27    fn is_running(&self) -> bool;
28
29    /// Send a message over IPC.
30    ///
31    /// Returning an error means this particular send failed. The client only stops processing
32    /// messages when the underlying error is fatal (see
33    /// [`IpcErrorKind`](crate::IpcErrorKind)); recoverable errors leave the client running, so the
34    /// send can be retried and existing subscriptions remain valid.
35    ///
36    /// Payloads are limited to 5 MiB. Payloads larger than one crypto provider message are split
37    /// into separately encrypted fragments that the receiving client reassembles. A peer that
38    /// predates fragmentation receives the fragments as messages on an unknown topic. Topics
39    /// `IpcFragment` and `IpcFragment/<topic>` are reserved for fragments, and sending on them
40    /// returns an error.
41    async fn send(&self, message: OutgoingMessage) -> Result<(), SendError>;
42
43    /// Send a message to every member of `group`, fire-and-forget.
44    ///
45    /// The communication backend resolves the group into its current members at send time, and
46    /// each member then receives the message exactly as if it had been passed to
47    /// [`send`](Self::send): encrypted over that endpoint's own session.
48    ///
49    /// Returns an error, without sending anything, if the group cannot be resolved. Otherwise
50    /// returns one [`EndpointSendResult`] per resolved endpoint, in resolution order. A failed send
51    /// to one endpoint, including [`SendError::Unreachable`], does not stop delivery to the others.
52    /// A fatal error is the exception: it stops the client, as it does for [`send`](Self::send),
53    /// and the endpoints after it are not attempted, so the results end at the failed endpoint.
54    async fn broadcast(
55        &self,
56        group: BroadcastGroup,
57        payload: Vec<u8>,
58        topic: Option<String>,
59    ) -> Result<Vec<EndpointSendResult>, BroadcastError>;
60
61    /// Subscribe to receive messages, optionally filtered by topic.
62    /// Setting the topic to `None` will receive all messages.
63    async fn subscribe(
64        &self,
65        topic: Option<String>,
66    ) -> Result<IpcClientSubscription, SubscribeError>;
67
68    /// Register an RPC handler using its type-erased form.
69    /// Prefer using
70    /// [`IpcClientExt::register_rpc_handler`](crate::IpcClientExt::register_rpc_handler)
71    /// instead.
72    #[doc(hidden)]
73    async fn register_rpc_handler_erased(&self, name: &str, handler: Box<dyn ErasedRpcHandler>);
74}