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}