Skip to main content

zbus/blocking/connection/
builder.rs

1#[cfg(not(feature = "tokio"))]
2use std::net::TcpStream;
3#[cfg(all(unix, not(feature = "tokio")))]
4use std::os::unix::net::UnixStream;
5#[cfg(feature = "tokio")]
6use tokio::net::TcpStream;
7#[cfg(all(unix, feature = "tokio"))]
8use tokio::net::UnixStream;
9#[cfg(all(windows, not(feature = "tokio")))]
10use uds_windows::UnixStream;
11
12use zvariant::ObjectPath;
13
14#[cfg(feature = "p2p")]
15use crate::Guid;
16use crate::{
17    Error, Result, address::Address, blocking::Connection, conn::AuthMechanism,
18    connection::socket::BoxedSplit, names::WellKnownName, object_server::Interface,
19    utils::block_on,
20};
21
22/// A builder for [`zbus::blocking::Connection`].
23#[derive(Debug)]
24#[must_use]
25pub struct Builder<'a>(crate::connection::Builder<'a>);
26
27impl<'a> Builder<'a> {
28    /// Create a builder for the session/user message bus connection.
29    pub fn session() -> Result<Self> {
30        crate::connection::Builder::session().map(Self)
31    }
32
33    /// Create a builder for the system-wide message bus connection.
34    pub fn system() -> Result<Self> {
35        crate::connection::Builder::system().map(Self)
36    }
37
38    /// Create a builder for an IBus connection.
39    ///
40    /// IBus (Intelligent Input Bus) is an input method framework. This method creates a builder
41    /// that will query the IBus daemon for its D-Bus address using the `ibus address` command.
42    ///
43    /// # Platform Support
44    ///
45    /// This method is available on Unix-like systems where IBus is installed.
46    ///
47    /// # Errors
48    ///
49    /// Returns an error if:
50    /// - The `ibus` command is not found or fails to execute
51    /// - The IBus daemon is not running
52    /// - The command output cannot be parsed as a valid D-Bus address
53    ///
54    /// # Example
55    ///
56    /// ```no_run
57    /// # use std::error::Error;
58    /// # use zbus::blocking::connection;
59    /// #
60    /// let _conn = connection::Builder::ibus()?
61    ///     .build()?;
62    ///
63    /// // Use the connection to interact with IBus services.
64    /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
65    /// ```
66    #[cfg(unix)]
67    pub fn ibus() -> Result<Self> {
68        crate::connection::Builder::ibus().map(Self)
69    }
70
71    /// Create a builder for a connection that will use the given [D-Bus bus address].
72    ///
73    /// [D-Bus bus address]: https://dbus.freedesktop.org/doc/dbus-specification.html#addresses
74    pub fn address<A>(address: A) -> Result<Self>
75    where
76        A: TryInto<Address>,
77        A::Error: Into<Error>,
78    {
79        crate::connection::Builder::address(address).map(Self)
80    }
81
82    /// Create a builder for a connection that will use the given unix stream.
83    ///
84    /// If the default `async-io` feature is disabled, this method will expect a
85    /// [`tokio::net::UnixStream`](https://docs.rs/tokio/latest/tokio/net/struct.UnixStream.html)
86    /// argument.
87    ///
88    /// Since tokio currently [does not support Unix domain sockets][tuds] on Windows, this method
89    /// is not available when the `tokio` feature is enabled and building for Windows target.
90    ///
91    /// [tuds]: https://github.com/tokio-rs/tokio/issues/2201
92    #[cfg(any(unix, not(feature = "tokio")))]
93    pub fn unix_stream(stream: UnixStream) -> Self {
94        Self(crate::connection::Builder::unix_stream(stream))
95    }
96
97    /// Create a builder for a connection that will use the given TCP stream.
98    ///
99    /// If the default `async-io` feature is disabled, this method will expect a
100    /// [`tokio::net::TcpStream`](https://docs.rs/tokio/latest/tokio/net/struct.TcpStream.html)
101    /// argument.
102    pub fn tcp_stream(stream: TcpStream) -> Self {
103        Self(crate::connection::Builder::tcp_stream(stream))
104    }
105
106    /// Create a builder for a connection that will use the given pre-authenticated socket.
107    ///
108    /// This is similar to [`Builder::socket`], except that the socket is either already
109    /// authenticated or does not require authentication.
110    pub fn authenticated_socket<S, G>(socket: S, guid: G) -> Result<Self>
111    where
112        S: Into<BoxedSplit>,
113        G: TryInto<crate::Guid<'a>>,
114        G::Error: Into<Error>,
115    {
116        crate::connection::Builder::authenticated_socket(socket, guid).map(Self)
117    }
118
119    /// Create a builder for a connection that will use the given socket.
120    pub fn socket<S: Into<BoxedSplit>>(socket: S) -> Self {
121        Self(crate::connection::Builder::socket(socket))
122    }
123
124    /// Specify the mechanism to use during authentication.
125    pub fn auth_mechanism(self, auth_mechanism: AuthMechanism) -> Self {
126        Self(self.0.auth_mechanism(auth_mechanism))
127    }
128
129    /// Specify the user id during authentication.
130    ///
131    /// This can be useful when using [`AuthMechanism::External`] with `socat`
132    /// to avoid the host decide what uid to use and instead provide one
133    /// known to have access rights.
134    #[cfg(unix)]
135    pub fn user_id(self, id: u32) -> Self {
136        Self(self.0.user_id(id))
137    }
138
139    /// The to-be-created connection will be a peer-to-peer connection.
140    ///
141    /// This method is only available when the `p2p` feature is enabled.
142    #[cfg(feature = "p2p")]
143    pub fn p2p(self) -> Self {
144        Self(self.0.p2p())
145    }
146
147    /// The to-be-created connection will be a server using the given GUID.
148    ///
149    /// The to-be-created connection will wait for incoming client authentication handshake and
150    /// negotiation messages, for peer-to-peer communications after successful creation.
151    ///
152    /// This method is only available when the `p2p` feature is enabled.
153    ///
154    /// **NOTE:** This method is redundant when using [`Builder::authenticated_socket`] since the
155    /// latter already sets the GUID for the connection and zbus doesn't differentiate between a
156    /// server and a client connection, except for authentication.
157    #[cfg(feature = "p2p")]
158    pub fn server<G>(self, guid: G) -> Result<Self>
159    where
160        G: TryInto<Guid<'a>>,
161        G::Error: Into<Error>,
162    {
163        self.0.server(guid).map(Self)
164    }
165
166    /// Set the capacity of the main (unfiltered) queue.
167    ///
168    /// Since typically you'd want to set this at instantiation time, you can set it through the
169    /// builder.
170    ///
171    /// # Example
172    ///
173    /// ```
174    /// # use std::error::Error;
175    /// # use zbus::blocking::connection;
176    /// #
177    /// let conn = connection::Builder::session()?
178    ///     .max_queued(30)
179    ///     .build()?;
180    /// assert_eq!(conn.max_queued(), 30);
181    ///
182    /// // Do something useful with `conn`..
183    /// # Ok::<_, Box<dyn Error + Send + Sync>>(())
184    /// ```
185    pub fn max_queued(self, max: usize) -> Self {
186        Self(self.0.max_queued(max))
187    }
188
189    /// Register a D-Bus [`Interface`] to be served at a given path.
190    ///
191    /// This is similar to [`zbus::blocking::ObjectServer::at`], except that it allows you to have
192    /// your interfaces available immediately after the connection is established. Typically, this
193    /// is exactly what you'd want. Also in contrast to [`zbus::blocking::ObjectServer::at`], this
194    /// method will replace any previously added interface with the same name at the same path.
195    pub fn serve_at<P, I>(self, path: P, iface: I) -> Result<Self>
196    where
197        I: Interface,
198        P: TryInto<ObjectPath<'a>>,
199        P::Error: Into<Error>,
200    {
201        self.0.serve_at(path, iface).map(Self)
202    }
203
204    /// Register a well-known name for this connection on the bus.
205    ///
206    /// This is similar to [`zbus::blocking::Connection::request_name`], except the name is
207    /// requested as part of the connection setup ([`Builder::build`]), immediately after
208    /// interfaces registered (through [`Builder::serve_at`]) are advertised. Typically
209    /// this is exactly what you want.
210    pub fn name<W>(self, well_known_name: W) -> Result<Self>
211    where
212        W: TryInto<WellKnownName<'a>>,
213        W::Error: Into<Error>,
214    {
215        self.0.name(well_known_name).map(Self)
216    }
217
218    /// Whether the [`zbus::fdo::RequestNameFlags::AllowReplacement`] flag will be set when
219    /// requesting names.
220    pub fn allow_name_replacements(self, allow_replacement: bool) -> Self {
221        Self(self.0.allow_name_replacements(allow_replacement))
222    }
223
224    /// Whether the [`zbus::fdo::RequestNameFlags::ReplaceExisting`] flag will be set when
225    /// requesting names.
226    pub fn replace_existing_names(self, replace_existing: bool) -> Self {
227        Self(self.0.replace_existing_names(replace_existing))
228    }
229
230    /// Set the unique name of the connection.
231    ///
232    /// This method is only available when the `bus-impl` feature is enabled.
233    ///
234    /// # Panics
235    ///
236    /// This method panics if the to-be-created connection is not a peer-to-peer connection.
237    /// It will always panic if the connection is to a message bus as it's the bus that assigns
238    /// peers their unique names. This is mainly provided for bus implementations. All other users
239    /// should not need to use this method.
240    #[cfg(feature = "bus-impl")]
241    pub fn unique_name<U>(self, unique_name: U) -> Result<Self>
242    where
243        U: TryInto<crate::names::UniqueName<'a>>,
244        U::Error: Into<Error>,
245    {
246        self.0.unique_name(unique_name).map(Self)
247    }
248
249    /// Set a timeout for method calls.
250    ///
251    /// Method calls will return
252    /// `zbus::Error::InputOutput(std::io::Error(kind: ErrorKind::TimedOut))` if a client does not
253    /// receive an answer from a service in time.
254    pub fn method_timeout(self, timeout: std::time::Duration) -> Self {
255        Self(self.0.method_timeout(timeout))
256    }
257
258    /// Build the connection, consuming the builder.
259    ///
260    /// # Errors
261    ///
262    /// Until server-side bus connection is supported, attempting to build such a connection will
263    /// result in a [`Error::Unsupported`] error.
264    pub fn build(self) -> Result<Connection> {
265        block_on(self.0.build()).map(Into::into)
266    }
267}