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