| 1 | use static_assertions::assert_impl_all; |
| 2 | #[cfg (not(feature = "tokio" ))] |
| 3 | use std::net::TcpStream; |
| 4 | #[cfg (all(unix, not(feature = "tokio" )))] |
| 5 | use std::os::unix::net::UnixStream; |
| 6 | #[cfg (feature = "tokio" )] |
| 7 | use tokio::net::TcpStream; |
| 8 | #[cfg (all(unix, feature = "tokio" ))] |
| 9 | use tokio::net::UnixStream; |
| 10 | #[cfg (all(windows, not(feature = "tokio" )))] |
| 11 | use uds_windows::UnixStream; |
| 12 | |
| 13 | use zvariant::{ObjectPath, Str}; |
| 14 | |
| 15 | #[cfg (feature = "p2p" )] |
| 16 | use crate::Guid; |
| 17 | use 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 ] |
| 25 | pub struct Builder<'a>(crate::connection::Builder<'a>); |
| 26 | |
| 27 | assert_impl_all!(Builder<'_>: Send, Sync, Unpin); |
| 28 | |
| 29 | impl<'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 | } |
| 240 | |