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}