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