Skip to main content

zbus/connection/
mod.rs

1//! Connection API.
2use async_broadcast::{InactiveReceiver, Receiver, Sender as Broadcaster, broadcast};
3use enumflags2::BitFlags;
4use event_listener::{Event, EventListener};
5use std::{
6    collections::HashMap,
7    future::Future,
8    io,
9    sync::{
10        Arc, OnceLock, Weak,
11        atomic::{AtomicBool, Ordering},
12    },
13    time::Duration,
14};
15use tracing::{Instrument, debug, info_span, instrument, trace, trace_span, warn};
16use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, OwnedUniqueName, WellKnownName};
17use zvariant::ObjectPath;
18
19use futures_lite::StreamExt;
20use ordered_stream::OrderedFuture;
21
22use crate::{
23    DBusError, Error, Executor, MatchRule, ObjectServer, OwnedGuid, OwnedMatchRule, Result, Task,
24    async_lock::{Mutex, Semaphore, SemaphorePermit},
25    fdo::{ConnectionCredentials, ReleaseNameReply, RequestNameFlags, RequestNameReply},
26    is_flatpak,
27    message::{Flags, Message, Type},
28    timeout::timeout,
29};
30
31mod builder;
32pub use builder::Builder;
33
34pub mod socket;
35pub use socket::Socket;
36
37mod socket_reader;
38use socket_reader::{SocketReader, SocketStatus};
39
40mod pending_method_calls;
41use pending_method_calls::PendingMethodCalls;
42
43pub(crate) mod handshake;
44pub use handshake::AuthMechanism;
45use handshake::Authenticated;
46
47const DEFAULT_MAX_QUEUED: usize = 64;
48
49/// Inner state shared by Connection and WeakConnection
50#[derive(Debug)]
51pub(crate) struct ConnectionInner {
52    server_guid: OwnedGuid,
53    #[cfg(unix)]
54    cap_unix_fd: bool,
55    #[cfg(feature = "p2p")]
56    bus_conn: bool,
57    unique_name: OnceLock<OwnedUniqueName>,
58    registered_names: Mutex<HashMap<WellKnownName<'static>, NameStatus>>,
59
60    socket_status: Arc<SocketStatus>,
61    socket_write: Mutex<Box<dyn socket::WriteHalf>>,
62
63    // Our executor
64    executor: Executor<'static>,
65
66    // Socket reader task
67    #[allow(unused)]
68    socket_reader_task: OnceLock<Task<()>>,
69
70    pub(crate) msg_receiver: InactiveReceiver<Result<Message>>,
71    msg_senders: Arc<Mutex<HashMap<Option<OwnedMatchRule>, MsgBroadcaster>>>,
72    pending_method_calls: PendingMethodCalls,
73
74    subscriptions: Mutex<Subscriptions>,
75
76    object_server: OnceLock<ObjectServer>,
77    object_server_dispatch_task: OnceLock<Task<()>>,
78
79    drop_event: Event,
80
81    method_timeout: Option<Duration>,
82    // Cache the credentials.
83    credentials: OnceLock<Arc<ConnectionCredentials>>,
84}
85
86impl Drop for ConnectionInner {
87    fn drop(&mut self) {
88        // Notify anyone waiting that the connection is going away. Since we're being dropped, it's
89        // not possible for any new listeners to be created after this notification, so this is
90        // race-free.
91        self.drop_event.notify(usize::MAX);
92    }
93}
94
95type Subscriptions = HashMap<OwnedMatchRule, (u64, InactiveReceiver<Result<Message>>)>;
96
97pub(crate) type MsgBroadcaster = Broadcaster<Result<Message>>;
98
99/// A D-Bus connection.
100///
101/// A connection to a D-Bus bus, or a direct peer.
102///
103/// Once created, the connection is authenticated and negotiated and messages can be sent or
104/// received, such as [method calls] or [signals].
105///
106/// For higher-level message handling (typed functions, introspection, documentation reasons etc),
107/// it is recommended to wrap the low-level D-Bus messages into Rust functions with the
108/// [`macro@crate::proxy`] and [`macro@crate::interface`] macros instead of doing it directly on a
109/// `Connection`.
110///
111/// Typically, a connection is made to the session bus with [`Connection::session`], or to the
112/// system bus with [`Connection::system`]. Then the connection is used with [`crate::Proxy`]
113/// instances or the on-demand [`ObjectServer`] instance that can be accessed through
114/// [`Connection::object_server`].
115///
116/// `Connection` implements [`Clone`] and cloning it is a very cheap operation, as the underlying
117/// data is not cloned. This makes it very convenient to share the connection between different
118/// parts of your code. `Connection` also implements [`std::marker::Sync`] and [`std::marker::Send`]
119/// so you can send and share a connection instance across threads as well.
120///
121/// `Connection` keeps internal queues of incoming message. The default capacity of each of these is
122/// 64. The capacity of the main (unfiltered) queue is configurable through the [`set_max_queued`]
123/// method. When the queue is full, no more messages can be received until room is created for more.
124/// This is why it's important to ensure that all [`crate::MessageStream`] and
125/// [`crate::blocking::MessageIterator`] instances are continuously polled and iterated on,
126/// respectively.
127///
128/// For sending messages you can use the [`Connection::send`] method.
129///
130/// To gracefully close a connection while waiting for any outstanding method calls to complete,
131/// use [`Connection::graceful_shutdown`]. To immediately close a connection in a way that will
132/// disrupt any outstanding method calls, use [`Connection::close`]. If you do not need the
133/// shutdown to be immediate and do not care about waiting for outstanding method calls, you can
134/// also simply drop the `Connection` instance, which will act similarly to spawning
135/// `graceful_shutdown` in the background.
136///
137/// [method calls]: struct.Connection.html#method.call_method
138/// [signals]: struct.Connection.html#method.emit_signal
139/// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
140/// [`set_max_queued`]: struct.Connection.html#method.set_max_queued
141///
142/// ### Examples
143///
144/// #### Get the session bus ID
145///
146/// ```
147/// # zbus::block_on(async {
148/// use zbus::Connection;
149///
150/// let connection = Connection::session().await?;
151///
152/// let reply_body = connection
153///     .call_method(
154///         Some("org.freedesktop.DBus"),
155///         "/org/freedesktop/DBus",
156///         Some("org.freedesktop.DBus"),
157///         "GetId",
158///         &(),
159///     )
160///     .await?
161///     .body();
162///
163/// let id: &str = reply_body.deserialize()?;
164/// println!("Unique ID of the bus: {}", id);
165/// # Ok::<(), zbus::Error>(())
166/// # }).unwrap();
167/// ```
168///
169/// #### Monitoring all messages
170///
171/// Let's eavesdrop on the session bus 😈 using the [Monitor] interface:
172///
173/// ```rust,no_run
174/// # zbus::block_on(async {
175/// use futures_util::stream::TryStreamExt;
176/// use zbus::{Connection, MessageStream};
177///
178/// let connection = Connection::session().await?;
179///
180/// connection
181///     .call_method(
182///         Some("org.freedesktop.DBus"),
183///         "/org/freedesktop/DBus",
184///         Some("org.freedesktop.DBus.Monitoring"),
185///         "BecomeMonitor",
186///         &(&[] as &[&str], 0u32),
187///     )
188///     .await?;
189///
190/// let mut stream = MessageStream::from(connection);
191/// while let Some(msg) = stream.try_next().await? {
192///     println!("Got message: {}", msg);
193/// }
194///
195/// # Ok::<(), zbus::Error>(())
196/// # }).unwrap();
197/// ```
198///
199/// This should print something like:
200///
201/// ```console
202/// Got message: Signal NameAcquired from org.freedesktop.DBus
203/// Got message: Signal NameLost from org.freedesktop.DBus
204/// Got message: Method call GetConnectionUnixProcessID from :1.1324
205/// Got message: Error org.freedesktop.DBus.Error.NameHasNoOwner:
206///              Could not get PID of name ':1.1332': no such name from org.freedesktop.DBus
207/// Got message: Method call AddMatch from :1.918
208/// Got message: Method return from org.freedesktop.DBus
209/// ```
210///
211/// [Monitor]: https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-become-monitor
212#[derive(Clone, Debug)]
213#[must_use = "Dropping a `Connection` will close the underlying socket."]
214pub struct Connection {
215    pub(crate) inner: Arc<ConnectionInner>,
216}
217
218impl Connection {
219    /// Send `msg` to the peer.
220    pub async fn send(&self, msg: &Message) -> Result<()> {
221        #[cfg(unix)]
222        if !msg.data().fds().is_empty() && !self.inner.cap_unix_fd {
223            return Err(Error::Unsupported);
224        }
225
226        self.inner.socket_status.activity_event.notify(usize::MAX);
227        let mut write = self.inner.socket_write.lock().await;
228
229        write.send_message(msg).await
230    }
231
232    /// Send a method call.
233    ///
234    /// Create a method-call message, send it over the connection, then wait for the reply.
235    ///
236    /// On successful reply, an `Ok(Message)` is returned. On error, an `Err` is returned. D-Bus
237    /// error replies are returned as [`Error::MethodError`].
238    pub async fn call_method<'d, 'p, 'i, 'm, D, P, I, M, B>(
239        &self,
240        destination: Option<D>,
241        path: P,
242        interface: Option<I>,
243        method_name: M,
244        body: &B,
245    ) -> Result<Message>
246    where
247        D: TryInto<BusName<'d>>,
248        P: TryInto<ObjectPath<'p>>,
249        I: TryInto<InterfaceName<'i>>,
250        M: TryInto<MemberName<'m>>,
251        D::Error: Into<Error>,
252        P::Error: Into<Error>,
253        I::Error: Into<Error>,
254        M::Error: Into<Error>,
255        B: serde::ser::Serialize + zvariant::DynamicType,
256    {
257        let method = self
258            .call_method_raw(
259                destination,
260                path,
261                interface,
262                method_name,
263                BitFlags::empty(),
264                body,
265            )
266            .await?
267            .expect("no reply");
268
269        if let Some(tout) = self.method_timeout() {
270            timeout(method, tout).await
271        } else {
272            method.await
273        }
274    }
275
276    /// Send a method call.
277    ///
278    /// Send the given message, which must be a method call, over the connection and return an
279    /// object that allows the reply to be retrieved.  Typically you'd want to use
280    /// [`Connection::call_method`] instead.
281    ///
282    /// If the `flags` do not contain `MethodFlags::NoReplyExpected`, the return value is
283    /// guaranteed to be `Ok(Some(_))`, if there was no error encountered.
284    ///
285    /// INTERNAL NOTE: If this method is ever made pub, flags should become `BitFlags<MethodFlags>`.
286    pub(crate) async fn call_method_raw<'d, 'p, 'i, 'm, D, P, I, M, B>(
287        &self,
288        destination: Option<D>,
289        path: P,
290        interface: Option<I>,
291        method_name: M,
292        flags: BitFlags<Flags>,
293        body: &B,
294    ) -> Result<
295        Option<
296            impl Future<Output = Result<Message>>
297            + OrderedFuture<Output = Result<Message>, Ordering = crate::message::Sequence>,
298        >,
299    >
300    where
301        D: TryInto<BusName<'d>>,
302        P: TryInto<ObjectPath<'p>>,
303        I: TryInto<InterfaceName<'i>>,
304        M: TryInto<MemberName<'m>>,
305        D::Error: Into<Error>,
306        P::Error: Into<Error>,
307        I::Error: Into<Error>,
308        M::Error: Into<Error>,
309        B: serde::ser::Serialize + zvariant::DynamicType,
310    {
311        let _permit = acquire_serial_num_semaphore().await;
312
313        let mut builder = Message::method_call(path, method_name)?;
314        if let Some(sender) = self.unique_name() {
315            builder = builder.sender(sender)?
316        }
317        if let Some(destination) = destination {
318            builder = builder.destination(destination)?
319        }
320        if let Some(interface) = interface {
321            builder = builder.interface(interface)?
322        }
323        for flag in flags {
324            builder = builder.with_flags(flag)?;
325        }
326        let msg = builder.build(body)?;
327
328        let serial = msg.primary_header().serial_num();
329        if flags.contains(Flags::NoReplyExpected) {
330            self.send(&msg).await?;
331
332            Ok(None)
333        } else {
334            let pending_call = self.inner.pending_method_calls.register_call(serial);
335            self.send(&msg).await?;
336
337            Ok(Some(pending_call))
338        }
339    }
340
341    /// Emit a signal.
342    ///
343    /// Create a signal message, and send it over the connection.
344    pub async fn emit_signal<'d, 'p, 'i, 'm, D, P, I, M, B>(
345        &self,
346        destination: Option<D>,
347        path: P,
348        interface: I,
349        signal_name: M,
350        body: &B,
351    ) -> Result<()>
352    where
353        D: TryInto<BusName<'d>>,
354        P: TryInto<ObjectPath<'p>>,
355        I: TryInto<InterfaceName<'i>>,
356        M: TryInto<MemberName<'m>>,
357        D::Error: Into<Error>,
358        P::Error: Into<Error>,
359        I::Error: Into<Error>,
360        M::Error: Into<Error>,
361        B: serde::ser::Serialize + zvariant::DynamicType,
362    {
363        let _permit = acquire_serial_num_semaphore().await;
364
365        let mut b = Message::signal(path, interface, signal_name)?;
366        if let Some(sender) = self.unique_name() {
367            b = b.sender(sender)?;
368        }
369        if let Some(destination) = destination {
370            b = b.destination(destination)?;
371        }
372        let m = b.build(body)?;
373
374        self.send(&m).await
375    }
376
377    /// Reply to a message.
378    ///
379    /// Given an existing message (likely a method call), send a reply back to the caller with the
380    /// given `body`.
381    pub async fn reply<B>(&self, call: &zbus::message::Header<'_>, body: &B) -> Result<()>
382    where
383        B: serde::ser::Serialize + zvariant::DynamicType,
384    {
385        let _permit = acquire_serial_num_semaphore().await;
386
387        let mut b = Message::method_return(call)?;
388        if let Some(sender) = self.unique_name() {
389            b = b.sender(sender)?;
390        }
391        let m = b.build(body)?;
392        self.send(&m).await
393    }
394
395    /// Reply an error to a message.
396    ///
397    /// Given an existing message (likely a method call), send an error reply back to the caller
398    /// with the given `error_name` and `body`.
399    pub async fn reply_error<'e, E, B>(
400        &self,
401        call: &zbus::message::Header<'_>,
402        error_name: E,
403        body: &B,
404    ) -> Result<()>
405    where
406        B: serde::ser::Serialize + zvariant::DynamicType,
407        E: TryInto<ErrorName<'e>>,
408        E::Error: Into<Error>,
409    {
410        let _permit = acquire_serial_num_semaphore().await;
411
412        let mut b = Message::error(call, error_name)?;
413        if let Some(sender) = self.unique_name() {
414            b = b.sender(sender)?;
415        }
416        let m = b.build(body)?;
417        self.send(&m).await
418    }
419
420    /// Reply an error to a message.
421    ///
422    /// Given an existing message (likely a method call), send an error reply back to the caller
423    /// using one of the standard interface reply types.
424    pub async fn reply_dbus_error(
425        &self,
426        call: &zbus::message::Header<'_>,
427        err: impl DBusError,
428    ) -> Result<()> {
429        let _permit = acquire_serial_num_semaphore().await;
430
431        let m = err.create_reply(call)?;
432        self.send(&m).await
433    }
434
435    /// Register a well-known name for this connection.
436    ///
437    /// When connecting to a bus, the name is requested from the bus. In case of p2p connection, the
438    /// name (if requested) is used for self-identification.
439    ///
440    /// You can request multiple names for the same connection. Use [`Connection::release_name`] for
441    /// deregistering names registered through this method.
442    ///
443    /// Note that exclusive ownership without queueing is requested (using
444    /// [`RequestNameFlags::ReplaceExisting`] and [`RequestNameFlags::DoNotQueue`] flags) since that
445    /// is the most typical case. If that is not what you want, you should use
446    /// [`Connection::request_name_with_flags`] instead (but make sure then that name is requested
447    /// **after** you've set up your service implementation with the `ObjectServer`).
448    ///
449    /// # Caveats
450    ///
451    /// The associated `ObjectServer` will only handle method calls destined for the unique name of
452    /// this connection or any of the registered well-known names. If no well-known name is
453    /// registered, the method calls destined to all well-known names will be handled.
454    ///
455    /// Since names registered through any other means than `Connection` or [`Builder`]
456    /// API are not known to the connection, method calls destined to those names will only be
457    /// handled by the associated `ObjectServer` if none of the names are registered through
458    /// `Connection*` API. Simply put, either register all the names through `Connection*` API or
459    /// none of them.
460    ///
461    /// # Errors
462    ///
463    /// Fails with `zbus::Error::NameTaken` if the name is already owned by another peer.
464    pub async fn request_name<'w, W>(&self, well_known_name: W) -> Result<()>
465    where
466        W: TryInto<WellKnownName<'w>>,
467        W::Error: Into<Error>,
468    {
469        self.request_name_with_flags(well_known_name, BitFlags::default())
470            .await
471            .map(|_| ())
472    }
473
474    /// Register a well-known name for this connection.
475    ///
476    /// This is the same as [`Connection::request_name`] but allows to specify the flags to use when
477    /// requesting the name.
478    ///
479    /// If the [`RequestNameFlags::DoNotQueue`] flag is not specified and request ends up in the
480    /// queue, you can use [`crate::fdo::NameAcquiredStream`] to be notified when the name is
481    /// acquired. A queued name request can be cancelled using [`Connection::release_name`].
482    ///
483    /// If the [`RequestNameFlags::AllowReplacement`] flag is specified, the requested name can be
484    /// lost if another peer requests the same name. You can use [`crate::fdo::NameLostStream`] to
485    /// be notified when the name is lost
486    ///
487    /// # Example
488    ///
489    /// ```
490    /// #
491    /// # zbus::block_on(async {
492    /// use zbus::{Connection, fdo::{DBusProxy, RequestNameFlags, RequestNameReply}};
493    /// use enumflags2::BitFlags;
494    /// use futures_util::stream::StreamExt;
495    ///
496    /// let name = "org.freedesktop.zbus.QueuedNameTest";
497    /// let conn1 = Connection::session().await?;
498    /// // This should just work right away.
499    /// conn1.request_name_with_flags(name, RequestNameFlags::DoNotQueue.into()).await?;
500    ///
501    /// let conn2 = Connection::session().await?;
502    /// // A second request from the another connection will fail with `DoNotQueue` flag, which is
503    /// // implicit with `request_name` method.
504    /// assert!(conn2.request_name(name).await.is_err());
505    ///
506    /// // Now let's try w/o `DoNotQueue` and we should be queued.
507    /// let reply = conn2
508    ///     .request_name_with_flags(name, RequestNameFlags::AllowReplacement.into())
509    ///     .await?;
510    /// assert_eq!(reply, RequestNameReply::InQueue);
511    /// // Another request should just give us the same response.
512    /// let reply = conn2
513    ///     // The flags on subsequent requests will however be ignored.
514    ///     .request_name_with_flags(name, BitFlags::empty())
515    ///     .await?;
516    /// assert_eq!(reply, RequestNameReply::InQueue);
517    /// let mut acquired_stream = DBusProxy::new(&conn2)
518    ///     .await?
519    ///     .receive_name_acquired()
520    ///     .await?;
521    /// assert!(conn1.release_name(name).await?);
522    /// // This would have waited forever if `conn1` hadn't just release the name.
523    /// let acquired = acquired_stream.next().await.unwrap();
524    /// assert_eq!(acquired.args().unwrap().name, name);
525    ///
526    /// // conn2 made the mistake of being too nice and allowed name replacemnt, so conn1 should be
527    /// // able to take it back.
528    /// let mut lost_stream = DBusProxy::new(&conn2)
529    ///     .await?
530    ///     .receive_name_lost()
531    ///     .await?;
532    /// conn1.request_name(name).await?;
533    /// let lost = lost_stream.next().await.unwrap();
534    /// assert_eq!(lost.args().unwrap().name, name);
535    ///
536    /// # Ok::<(), zbus::Error>(())
537    /// # }).unwrap();
538    /// ```
539    ///
540    /// # Caveats
541    ///
542    /// * Same as that of [`Connection::request_name`].
543    /// * If you wish to track changes to name ownership after this call, make sure that the
544    ///   [`crate::fdo::NameAcquired`] and/or [`crate::fdo::NameLostStream`] instance(s) are created
545    ///   **before** calling this method. Otherwise, you may loose the signal if it's emitted after
546    ///   this call but just before the stream instance get created.
547    pub async fn request_name_with_flags<'w, W>(
548        &self,
549        well_known_name: W,
550        flags: BitFlags<RequestNameFlags>,
551    ) -> Result<RequestNameReply>
552    where
553        W: TryInto<WellKnownName<'w>>,
554        W::Error: Into<Error>,
555    {
556        let well_known_name = well_known_name.try_into().map_err(Into::into)?;
557
558        // Warn if requesting a name before setting up the object server, as this can cause
559        // method calls to be lost.
560        if self.is_bus() && self.inner.object_server.get().is_none() {
561            warn!(
562                "Requesting name `{well_known_name}` before setting up the object server. \
563                Method calls arriving before interfaces are registered may be lost. \
564                Consider using `connection::Builder::serve_at()` and `::name()` instead.",
565            );
566        }
567        // We keep the lock until the end of this function so that the (possibly) spawned task
568        // doesn't end up accessing the name entry before it's inserted.
569        let mut names = self.inner.registered_names.lock().await;
570
571        match names.get(&well_known_name) {
572            Some(NameStatus::Owner(_)) => return Ok(RequestNameReply::AlreadyOwner),
573            Some(NameStatus::Queued(_)) => return Ok(RequestNameReply::InQueue),
574            None => (),
575        }
576
577        if !self.is_bus() {
578            names.insert(well_known_name.to_owned(), NameStatus::Owner(None));
579
580            return Ok(RequestNameReply::PrimaryOwner);
581        }
582
583        let acquired_match_rule = MatchRule::fdo_signal_builder("NameAcquired")
584            .arg(0, well_known_name.as_ref())
585            .unwrap()
586            .build();
587        let mut acquired_stream = self.add_match(acquired_match_rule.into(), None).await?;
588        let lost_match_rule = MatchRule::fdo_signal_builder("NameLost")
589            .arg(0, well_known_name.as_ref())
590            .unwrap()
591            .build();
592        let mut lost_stream = self.add_match(lost_match_rule.into(), None).await?;
593        let reply = self
594            .call_method(
595                Some("org.freedesktop.DBus"),
596                "/org/freedesktop/DBus",
597                Some("org.freedesktop.DBus"),
598                "RequestName",
599                &(well_known_name.clone(), flags),
600            )
601            .await?
602            .body()
603            .deserialize::<RequestNameReply>()?;
604        let lost_task_name = format!("monitor_name_lost{{name={well_known_name}}}");
605        let lost_task_name_span = info_span!("monitor_name_lost", name = %well_known_name);
606        let name_lost_fut = if flags.contains(RequestNameFlags::AllowReplacement) {
607            let weak_conn = WeakConnection::from(self);
608            let well_known_name = well_known_name.to_owned();
609            Some(
610                async move {
611                    loop {
612                        let signal = lost_stream.next().await;
613                        let inner = match weak_conn.upgrade() {
614                            Some(conn) => conn.inner.clone(),
615                            None => break,
616                        };
617
618                        match signal {
619                            Some(signal) => match signal {
620                                Ok(_) => {
621                                    tracing::info!(
622                                        "Connection `{}` lost name `{}`",
623                                        // SAFETY: This is bus connection so unique name can't be
624                                        // None.
625                                        inner.unique_name.get().unwrap(),
626                                        well_known_name
627                                    );
628                                    inner.registered_names.lock().await.remove(&well_known_name);
629
630                                    break;
631                                }
632                                Err(e) => warn!("Failed to parse `NameLost` signal: {}", e),
633                            },
634                            None => {
635                                trace!("`NameLost` signal stream closed");
636                                // This is a very strange state we end up in. Now the name is
637                                // question remains in the queue
638                                // forever. Maybe we can do better here but I
639                                // think it's a very unlikely scenario anyway.
640                                //
641                                // Can happen if the connection is lost/dropped but then the whole
642                                // `Connection` instance will go away soon anyway and hence this
643                                // strange state along with it.
644                                break;
645                            }
646                        }
647                    }
648                }
649                .instrument(lost_task_name_span),
650            )
651        } else {
652            None
653        };
654        let status = match reply {
655            RequestNameReply::InQueue => {
656                let weak_conn = WeakConnection::from(self);
657                let well_known_name = well_known_name.to_owned();
658                let task_name = format!("monitor_name_acquired{{name={well_known_name}}}");
659                let task_name_span = info_span!("monitor_name_acquired", name = %well_known_name);
660                let task = self.executor().spawn(
661                    async move {
662                        loop {
663                            let signal = acquired_stream.next().await;
664                            let inner = match weak_conn.upgrade() {
665                                Some(conn) => conn.inner.clone(),
666                                None => break,
667                            };
668                            match signal {
669                                Some(signal) => match signal {
670                                    Ok(_) => {
671                                        let mut names = inner.registered_names.lock().await;
672                                        if let Some(status) = names.get_mut(&well_known_name) {
673                                            let task = name_lost_fut.map(|fut| {
674                                                inner.executor.spawn(fut, &lost_task_name)
675                                            });
676                                            *status = NameStatus::Owner(task);
677
678                                            break;
679                                        }
680                                        // else the name was released in the meantime. :shrug:
681                                    }
682                                    Err(e) => warn!("Failed to parse `NameAcquired` signal: {}", e),
683                                },
684                                None => {
685                                    trace!("`NameAcquired` signal stream closed");
686                                    // See comment above for similar state in case of `NameLost`
687                                    // stream.
688                                    break;
689                                }
690                            }
691                        }
692                    }
693                    .instrument(task_name_span),
694                    &task_name,
695                );
696
697                NameStatus::Queued(task)
698            }
699            RequestNameReply::PrimaryOwner | RequestNameReply::AlreadyOwner => {
700                let task = name_lost_fut.map(|fut| self.executor().spawn(fut, &lost_task_name));
701
702                NameStatus::Owner(task)
703            }
704            RequestNameReply::Exists => return Err(Error::NameTaken),
705        };
706
707        names.insert(well_known_name.to_owned(), status);
708
709        Ok(reply)
710    }
711
712    /// Deregister a previously registered well-known name for this service on the bus.
713    ///
714    /// Use this method to deregister a well-known name, registered through
715    /// [`Connection::request_name`].
716    ///
717    /// Unless an error is encountered, returns `Ok(true)` if name was previously registered with
718    /// the bus through `self` and it has now been successfully deregistered, `Ok(false)` if name
719    /// was not previously registered or already deregistered.
720    pub async fn release_name<'w, W>(&self, well_known_name: W) -> Result<bool>
721    where
722        W: TryInto<WellKnownName<'w>>,
723        W::Error: Into<Error>,
724    {
725        let well_known_name: WellKnownName<'w> = well_known_name.try_into().map_err(Into::into)?;
726        let mut names = self.inner.registered_names.lock().await;
727        // FIXME: Should be possible to avoid cloning/allocation here
728        if names.remove(&well_known_name.to_owned()).is_none() {
729            return Ok(false);
730        };
731
732        if !self.is_bus() {
733            return Ok(true);
734        }
735
736        self.call_method(
737            Some("org.freedesktop.DBus"),
738            "/org/freedesktop/DBus",
739            Some("org.freedesktop.DBus"),
740            "ReleaseName",
741            &well_known_name,
742        )
743        .await?
744        .body()
745        .deserialize::<ReleaseNameReply>()
746        .map(|r| r == ReleaseNameReply::Released)
747    }
748
749    /// Check if `self` is a connection to a message bus.
750    ///
751    /// This will return `false` for p2p connections. When the `p2p` feature is disabled, this will
752    /// always return `true`.
753    pub fn is_bus(&self) -> bool {
754        #[cfg(feature = "p2p")]
755        {
756            self.inner.bus_conn
757        }
758        #[cfg(not(feature = "p2p"))]
759        {
760            true
761        }
762    }
763
764    /// The unique name of the connection, if set/applicable.
765    ///
766    /// The unique name is assigned by the message bus, or set manually using
767    /// [`Connection::set_unique_name`].
768    pub fn unique_name(&self) -> Option<&OwnedUniqueName> {
769        self.inner.unique_name.get()
770    }
771
772    /// Set the unique name of the connection (if not already set).
773    ///
774    /// This is mainly provided for bus implementations. All other users should not need to use this
775    /// method. Hence why this method is only available when the `bus-impl` feature is enabled.
776    ///
777    /// # Panics
778    ///
779    /// This method panics if the unique name is already set. It will always panic if the connection
780    /// is to a message bus as it's the bus that assigns peers their unique names.
781    #[cfg(feature = "bus-impl")]
782    pub fn set_unique_name<U>(&self, unique_name: U) -> Result<()>
783    where
784        U: TryInto<OwnedUniqueName>,
785        U::Error: Into<Error>,
786    {
787        let name = unique_name.try_into().map_err(Into::into)?;
788        self.set_unique_name_(name);
789
790        Ok(())
791    }
792
793    /// The capacity of the main (unfiltered) queue.
794    pub fn max_queued(&self) -> usize {
795        self.inner.msg_receiver.capacity()
796    }
797
798    /// Set the capacity of the main (unfiltered) queue.
799    pub fn set_max_queued(&mut self, max: usize) {
800        self.inner.msg_receiver.clone().set_capacity(max);
801    }
802
803    /// The server's GUID.
804    pub fn server_guid(&self) -> &OwnedGuid {
805        &self.inner.server_guid
806    }
807
808    /// The underlying executor.
809    ///
810    /// When a connection is built with internal_executor set to false, zbus will not spawn a
811    /// thread to run the executor. You're responsible to continuously [tick the executor][tte].
812    /// Failure to do so will result in hangs.
813    ///
814    /// # Examples
815    ///
816    /// Here is how one would typically run the zbus executor through tokio's scheduler:
817    ///
818    /// ```
819    /// use zbus::connection::Builder;
820    /// use tokio::task::spawn;
821    ///
822    /// # struct SomeIface;
823    /// #
824    /// # #[zbus::interface]
825    /// # impl SomeIface {
826    /// # }
827    /// #
828    /// #[tokio::main]
829    /// async fn main() {
830    ///     let conn = Builder::session()
831    ///         .unwrap()
832    ///         .internal_executor(false)
833    /// #         // This is only for testing a deadlock that used to happen with this combo.
834    /// #         .serve_at("/some/iface", SomeIface)
835    /// #         .unwrap()
836    ///         .build()
837    ///         .await
838    ///         .unwrap();
839    ///     {
840    ///        let conn = conn.clone();
841    ///        spawn(async move {
842    ///            loop {
843    ///                conn.executor().tick().await;
844    ///            }
845    ///        });
846    ///     }
847    ///
848    ///     // All your other async code goes here.
849    /// }
850    /// ```
851    ///
852    /// **Note**: zbus 2.1 added support for tight integration with tokio. This means, if you use
853    /// zbus with tokio, you do not need to worry about this at all. All you need to do is enable
854    /// `tokio` feature. You should also disable the (default) `async-io` feature in your
855    /// `Cargo.toml` to avoid unused dependencies. Also note that **prior** to zbus 3.0, disabling
856    /// `async-io` was required to enable tight `tokio` integration.
857    ///
858    /// [tte]: https://docs.rs/async-executor/1.4.1/async_executor/struct.Executor.html#method.tick
859    pub fn executor(&self) -> &Executor<'static> {
860        &self.inner.executor
861    }
862
863    /// Get a reference to the associated [`ObjectServer`].
864    ///
865    /// The `ObjectServer` is created on-demand.
866    ///
867    /// **Note**: Once the `ObjectServer` is created, it will be replying to all method calls
868    /// received on `self`. If you want to manually reply to method calls, do not use this
869    /// method (or any of the `ObjectServer` related API).
870    pub fn object_server(&self) -> &ObjectServer {
871        self.ensure_object_server(true)
872    }
873
874    pub(crate) fn ensure_object_server(&self, start: bool) -> &ObjectServer {
875        self.inner
876            .object_server
877            .get_or_init(move || self.setup_object_server(start, None))
878    }
879
880    fn setup_object_server(&self, start: bool, started_event: Option<Event>) -> ObjectServer {
881        if start {
882            self.start_object_server(started_event);
883        }
884
885        ObjectServer::new(self)
886    }
887
888    #[instrument(skip(self))]
889    pub(crate) fn start_object_server(&self, started_event: Option<Event>) {
890        self.inner.object_server_dispatch_task.get_or_init(|| {
891            trace!("starting ObjectServer task");
892            let weak_conn = WeakConnection::from(self);
893
894            self.inner.executor.spawn(
895                async move {
896                    let mut stream = match weak_conn.upgrade() {
897                        Some(conn) => {
898                            let mut builder = MatchRule::builder().msg_type(Type::MethodCall);
899                            if let Some(unique_name) = conn.unique_name() {
900                                builder = builder.destination(&**unique_name).expect("unique name");
901                            }
902                            let rule = builder.build();
903                            match conn.add_match(rule.into(), None).await {
904                                Ok(stream) => stream,
905                                Err(e) => {
906                                    // Very unlikely but can happen I guess if connection is closed.
907                                    debug!("Failed to create message stream: {}", e);
908
909                                    return;
910                                }
911                            }
912                        }
913                        None => {
914                            trace!("Connection is gone, stopping associated object server task");
915
916                            return;
917                        }
918                    };
919                    if let Some(started_event) = started_event {
920                        started_event.notify(1);
921                    }
922
923                    trace!("waiting for incoming method call messages..");
924                    while let Some(msg) = stream.next().await.and_then(|m| {
925                        if let Err(e) = &m {
926                            debug!("Error while reading from object server stream: {:?}", e);
927                        }
928                        m.ok()
929                    }) {
930                        if let Some(conn) = weak_conn.upgrade() {
931                            let hdr = msg.header();
932                            // If we're connected to a bus, skip the destination check as the
933                            // server will only send us method calls destined to us.
934                            if !conn.is_bus() {
935                                match hdr.destination() {
936                                    // Unique name is already checked by the match rule.
937                                    Some(BusName::Unique(_)) | None => (),
938                                    Some(BusName::WellKnown(dest)) => {
939                                        let names = conn.inner.registered_names.lock().await;
940                                        // destination doesn't matter if no name has been registered
941                                        // (probably means the name is registered through external
942                                        // means).
943                                        if !names.is_empty() && !names.contains_key(dest) {
944                                            trace!(
945                                                "Got a method call for a different destination: {}",
946                                                dest
947                                            );
948
949                                            continue;
950                                        }
951                                    }
952                                }
953                            }
954                            let server = conn.object_server();
955                            if let Err(e) = server.dispatch_call(&msg, &hdr).await {
956                                debug!(
957                                    "Error dispatching message. Message: {:?}, error: {:?}",
958                                    msg, e
959                                );
960                            }
961                        } else {
962                            // If connection is completely gone, no reason to keep running the task
963                            // anymore.
964                            trace!("Connection is gone, stopping associated object server task");
965                            break;
966                        }
967                    }
968                }
969                .instrument(info_span!("obj_server_task")),
970                "obj_server_task",
971            )
972        });
973    }
974
975    pub(crate) async fn add_match(
976        &self,
977        rule: OwnedMatchRule,
978        max_queued: Option<usize>,
979    ) -> Result<Receiver<Result<Message>>> {
980        use std::collections::hash_map::Entry;
981
982        if self.inner.msg_senders.lock().await.is_empty() {
983            // This only happens if socket reader task has errored out.
984            return Err(Error::InputOutput(Arc::new(io::Error::new(
985                io::ErrorKind::BrokenPipe,
986                "Socket reader task has errored out",
987            ))));
988        }
989
990        let mut subscriptions = self.inner.subscriptions.lock().await;
991        let msg_type = rule.msg_type().unwrap_or(Type::Signal);
992        match subscriptions.entry(rule.clone()) {
993            Entry::Vacant(e) => {
994                let max_queued = max_queued.unwrap_or(DEFAULT_MAX_QUEUED);
995                let (sender, mut receiver) = broadcast(max_queued);
996                receiver.set_await_active(false);
997                if self.is_bus() && msg_type == Type::Signal {
998                    self.call_method(
999                        Some("org.freedesktop.DBus"),
1000                        "/org/freedesktop/DBus",
1001                        Some("org.freedesktop.DBus"),
1002                        "AddMatch",
1003                        &e.key(),
1004                    )
1005                    .await?;
1006                }
1007                e.insert((1, receiver.clone().deactivate()));
1008                self.inner
1009                    .msg_senders
1010                    .lock()
1011                    .await
1012                    .insert(Some(rule), sender);
1013
1014                Ok(receiver)
1015            }
1016            Entry::Occupied(mut e) => {
1017                let (num_subscriptions, receiver) = e.get_mut();
1018                *num_subscriptions += 1;
1019                if let Some(max_queued) = max_queued {
1020                    if max_queued > receiver.capacity() {
1021                        receiver.set_capacity(max_queued);
1022                    }
1023                }
1024
1025                Ok(receiver.activate_cloned())
1026            }
1027        }
1028    }
1029
1030    pub(crate) async fn remove_match(&self, rule: OwnedMatchRule) -> Result<bool> {
1031        use std::collections::hash_map::Entry;
1032        let mut subscriptions = self.inner.subscriptions.lock().await;
1033        // TODO when it becomes stable, use HashMap::raw_entry and only require expr: &str
1034        // (both here and in add_match)
1035        let msg_type = rule.msg_type().unwrap_or(Type::Signal);
1036        match subscriptions.entry(rule) {
1037            Entry::Vacant(_) => Ok(false),
1038            Entry::Occupied(mut e) => {
1039                let rule = e.key().inner().clone();
1040                e.get_mut().0 -= 1;
1041                if e.get().0 == 0 {
1042                    if self.is_bus() && msg_type == Type::Signal {
1043                        self.call_method(
1044                            Some("org.freedesktop.DBus"),
1045                            "/org/freedesktop/DBus",
1046                            Some("org.freedesktop.DBus"),
1047                            "RemoveMatch",
1048                            &rule,
1049                        )
1050                        .await?;
1051                    }
1052                    e.remove();
1053                    self.inner
1054                        .msg_senders
1055                        .lock()
1056                        .await
1057                        .remove(&Some(rule.into()));
1058                }
1059                Ok(true)
1060            }
1061        }
1062    }
1063
1064    pub(crate) fn queue_remove_match(&self, rule: OwnedMatchRule) {
1065        let conn = self.clone();
1066        let task_name = format!("Remove match `{}`", *rule);
1067        let remove_match =
1068            async move { conn.remove_match(rule).await }.instrument(trace_span!("{}", task_name));
1069        self.inner.executor.spawn(remove_match, &task_name).detach()
1070    }
1071
1072    /// The method_timeout (if any). See [Builder::method_timeout] for details.
1073    pub fn method_timeout(&self) -> Option<Duration> {
1074        self.inner.method_timeout
1075    }
1076
1077    pub(crate) async fn new(
1078        auth: Authenticated,
1079        #[allow(unused)] bus_connection: bool,
1080        executor: Executor<'static>,
1081        method_timeout: Option<Duration>,
1082    ) -> Result<Self> {
1083        #[cfg(unix)]
1084        let cap_unix_fd = auth.cap_unix_fd;
1085
1086        macro_rules! create_msg_broadcast_channel {
1087            ($size:expr) => {{
1088                let (msg_sender, msg_receiver) = broadcast($size);
1089                let mut msg_receiver = msg_receiver.deactivate();
1090                msg_receiver.set_await_active(false);
1091
1092                (msg_sender, msg_receiver)
1093            }};
1094        }
1095        // The unfiltered message channel.
1096        let (msg_sender, msg_receiver) = create_msg_broadcast_channel!(DEFAULT_MAX_QUEUED);
1097        let mut msg_senders = HashMap::new();
1098        msg_senders.insert(None, msg_sender);
1099
1100        let msg_senders = Arc::new(Mutex::new(msg_senders));
1101        let pending_method_calls = PendingMethodCalls::default();
1102        let subscriptions = Mutex::new(HashMap::new());
1103
1104        let connection = Self {
1105            inner: Arc::new(ConnectionInner {
1106                socket_status: Arc::new(SocketStatus {
1107                    activity_event: Event::new(),
1108                    closed: AtomicBool::new(false),
1109                    closed_event: Event::new(),
1110                }),
1111                socket_write: Mutex::new(auth.socket_write),
1112                server_guid: auth.server_guid,
1113                #[cfg(unix)]
1114                cap_unix_fd,
1115                #[cfg(feature = "p2p")]
1116                bus_conn: bus_connection,
1117                unique_name: OnceLock::new(),
1118                subscriptions,
1119                object_server: OnceLock::new(),
1120                object_server_dispatch_task: OnceLock::new(),
1121                executor,
1122                socket_reader_task: OnceLock::new(),
1123                msg_senders,
1124                pending_method_calls,
1125                msg_receiver,
1126                registered_names: Mutex::new(HashMap::new()),
1127                drop_event: Event::new(),
1128                method_timeout,
1129                credentials: OnceLock::new(),
1130            }),
1131        };
1132
1133        if let Some(unique_name) = auth.unique_name {
1134            connection.set_unique_name_(unique_name);
1135        }
1136
1137        Ok(connection)
1138    }
1139
1140    /// Create a `Connection` to the session/user message bus.
1141    pub async fn session() -> Result<Self> {
1142        Builder::session()?.build().await
1143    }
1144
1145    /// Create a `Connection` to the system-wide message bus.
1146    pub async fn system() -> Result<Self> {
1147        Builder::system()?.build().await
1148    }
1149
1150    /// Return a listener, notified on various connection activity.
1151    ///
1152    /// This function is meant for the caller to implement idle or timeout on inactivity.
1153    pub fn monitor_activity(&self) -> EventListener {
1154        self.inner.socket_status.activity_event.listen()
1155    }
1156
1157    /// Returns `true` if the connection has been closed.
1158    ///
1159    /// A connection is considered closed either when the remote peer disconnects, an I/O error
1160    /// occurs on the socket, or [`Connection::close`] is called.
1161    pub fn is_closed(&self) -> bool {
1162        self.inner.socket_status.closed.load(Ordering::Relaxed)
1163    }
1164
1165    /// Waits until the connection is closed.
1166    ///
1167    /// A connection is considered closed either when the remote peer disconnects, an I/O error
1168    /// occurs on the socket, or [`Connection::close`] is called.
1169    ///
1170    /// Returns immediately if the connection is already closed.
1171    pub async fn closed(&self) {
1172        loop {
1173            let listener = self.inner.socket_status.closed_event.listen();
1174            if self.inner.socket_status.closed.load(Ordering::Acquire) {
1175                return;
1176            }
1177            listener.await;
1178        }
1179    }
1180
1181    /// Return the peer credentials.
1182    ///
1183    /// The fields are populated on the best effort basis. Some or all fields may not even make
1184    /// sense for certain sockets or on certain platforms and hence will be set to `None`.
1185    ///
1186    /// This method caches the credentials on the first call for you.
1187    ///
1188    /// # Caveats
1189    ///
1190    /// Currently `linux_security_label` field is not populated.
1191    pub async fn peer_creds(&self) -> io::Result<&Arc<ConnectionCredentials>> {
1192        let mut socket_write = self.inner.socket_write.lock().await;
1193
1194        // Keeping the `socket_write` lock guard ensures that this isn't racy.
1195        if let Some(creds) = self.inner.credentials.get() {
1196            return Ok(creds);
1197        }
1198
1199        self.inner
1200            .credentials
1201            .set(socket_write.peer_credentials().await.map(Arc::new)?)
1202            .expect("credentials cache set more than once");
1203
1204        Ok(self
1205            .inner
1206            .credentials
1207            .get()
1208            .expect("credentials should have been set"))
1209    }
1210
1211    /// Return the peer credentials.
1212    ///
1213    /// The fields are populated on the best effort basis. Some or all fields may not even make
1214    /// sense for certain sockets or on certain platforms and hence will be set to `None`.
1215    ///
1216    /// # Caveats
1217    ///
1218    /// Currently `linux_security_label` field is not populated.
1219    #[deprecated(since = "5.13.0", note = "Use `peer_creds` instead")]
1220    pub async fn peer_credentials(&self) -> io::Result<ConnectionCredentials> {
1221        self.inner
1222            .socket_write
1223            .lock()
1224            .await
1225            .peer_credentials()
1226            .await
1227    }
1228
1229    /// Close the connection.
1230    ///
1231    /// After this call, all reading and writing operations will fail.
1232    pub async fn close(self) -> Result<()> {
1233        self.inner.socket_status.activity_event.notify(usize::MAX);
1234        let result = self
1235            .inner
1236            .socket_write
1237            .lock()
1238            .await
1239            .close()
1240            .await
1241            .map_err(Into::into);
1242        self.inner
1243            .socket_status
1244            .closed
1245            .store(true, Ordering::Release);
1246        self.inner.socket_status.closed_event.notify(usize::MAX);
1247        result
1248    }
1249
1250    /// Gracefully close the connection, waiting for all other references to be dropped.
1251    ///
1252    /// This will not disrupt any incoming or outgoing method calls, and will await their
1253    /// completion.
1254    ///
1255    /// # Caveats
1256    ///
1257    /// * This will not prevent new incoming messages from keeping the connection alive (and
1258    ///   indefinitely delaying this method's completion).
1259    ///
1260    /// * The shutdown will not complete until the underlying connection is fully dropped, so beware
1261    ///   of deadlocks if you are holding any other clones of this `Connection`.
1262    ///
1263    /// # Example
1264    ///
1265    /// ```
1266    /// # use std::error::Error;
1267    /// # use zbus::connection::Builder;
1268    /// # use zbus::interface;
1269    /// #
1270    /// # struct MyInterface;
1271    /// #
1272    /// # #[interface(name = "foo.bar.baz")]
1273    /// # impl MyInterface {
1274    /// #     async fn do_thing(&self) {}
1275    /// # }
1276    /// #
1277    /// # #[tokio::main]
1278    /// # async fn main() -> Result<(), Box<dyn Error>> {
1279    /// let conn = Builder::session()?
1280    ///     .name("foo.bar.baz")?
1281    ///     .serve_at("/foo/bar/baz", MyInterface)?
1282    ///     .build()
1283    ///     .await?;
1284    ///
1285    /// # let some_exit_condition = std::future::ready(());
1286    /// some_exit_condition.await;
1287    ///
1288    /// conn.graceful_shutdown().await;
1289    /// #
1290    /// # Ok(())
1291    /// # }
1292    /// ```
1293    pub async fn graceful_shutdown(self) {
1294        let listener = self.inner.drop_event.listen();
1295        drop(self);
1296        listener.await;
1297    }
1298
1299    pub(crate) fn init_socket_reader(
1300        &self,
1301        socket_read: Box<dyn socket::ReadHalf>,
1302        already_read: Vec<u8>,
1303        #[cfg(unix)] already_received_fds: Vec<std::os::fd::OwnedFd>,
1304    ) {
1305        let inner = &self.inner;
1306        inner
1307            .socket_reader_task
1308            .set(
1309                SocketReader::new(
1310                    socket_read,
1311                    inner.msg_senders.clone(),
1312                    inner.pending_method_calls.clone(),
1313                    already_read,
1314                    #[cfg(unix)]
1315                    already_received_fds,
1316                    inner.socket_status.clone(),
1317                )
1318                .spawn(&inner.executor),
1319            )
1320            .expect("Attempted to set `socket_reader_task` twice");
1321    }
1322
1323    fn set_unique_name_(&self, name: OwnedUniqueName) {
1324        self.inner
1325            .unique_name
1326            .set(name)
1327            // programmer (probably our) error if this fails.
1328            .expect("unique name already set");
1329    }
1330}
1331
1332#[cfg(feature = "blocking-api")]
1333impl From<crate::blocking::Connection> for Connection {
1334    fn from(conn: crate::blocking::Connection) -> Self {
1335        conn.into_inner()
1336    }
1337}
1338
1339// Internal API that allows keeping a weak connection ref around.
1340#[derive(Debug, Clone)]
1341pub(crate) struct WeakConnection {
1342    inner: Weak<ConnectionInner>,
1343}
1344
1345impl WeakConnection {
1346    /// Upgrade to a Connection.
1347    pub fn upgrade(&self) -> Option<Connection> {
1348        self.inner.upgrade().map(|inner| Connection { inner })
1349    }
1350}
1351
1352impl From<&Connection> for WeakConnection {
1353    fn from(conn: &Connection) -> Self {
1354        Self {
1355            inner: Arc::downgrade(&conn.inner),
1356        }
1357    }
1358}
1359
1360#[derive(Debug)]
1361enum NameStatus {
1362    // The task waits for name lost signal if owner allows replacement.
1363    Owner(#[allow(unused)] Option<Task<()>>),
1364    // The task waits for name acquisition signal.
1365    Queued(#[allow(unused)] Task<()>),
1366}
1367
1368static SERIAL_NUM_SEMAPHORE: Semaphore = Semaphore::new(1);
1369
1370// Make message creation and sending an atomic operation, using an async
1371// semaphore if flatpak portal is detected to workaround an xdg-dbus-proxy issue:
1372//
1373// https://github.com/flatpak/xdg-dbus-proxy/issues/46
1374async fn acquire_serial_num_semaphore() -> Option<SemaphorePermit<'static>> {
1375    if is_flatpak() {
1376        Some(SERIAL_NUM_SEMAPHORE.acquire().await)
1377    } else {
1378        None
1379    }
1380}
1381
1382#[cfg(test)]
1383mod tests {
1384    use super::*;
1385    use crate::fdo::DBusProxy;
1386    use ntest::timeout;
1387    use std::{pin::pin, time::Duration};
1388    use test_log::test;
1389
1390    #[cfg(windows)]
1391    #[test]
1392    fn connect_autolaunch_session_bus() {
1393        let addr =
1394            crate::win32::autolaunch_bus_address().expect("Unable to get session bus address");
1395
1396        crate::block_on(async { addr.connect().await }).expect("Unable to connect to session bus");
1397    }
1398
1399    #[cfg(target_os = "macos")]
1400    #[test]
1401    fn connect_launchd_session_bus() {
1402        use crate::address::{Address, Transport, transport::Launchd};
1403        crate::block_on(async {
1404            let addr = Address::from(Transport::Launchd(Launchd::new(
1405                "DBUS_LAUNCHD_SESSION_BUS_SOCKET",
1406            )));
1407            addr.connect().await
1408        })
1409        .expect("Unable to connect to session bus");
1410    }
1411
1412    #[test]
1413    #[timeout(15000)]
1414    fn disconnect_on_drop() {
1415        // Reproducer for https://github.com/z-galaxy/zbus/issues/308 where setting up the
1416        // objectserver would cause the connection to not disconnect on drop.
1417        crate::utils::block_on(test_disconnect_on_drop());
1418    }
1419
1420    async fn test_disconnect_on_drop() {
1421        #[derive(Default)]
1422        struct MyInterface {}
1423
1424        #[crate::interface(name = "dev.peelz.FooBar.Baz")]
1425        impl MyInterface {
1426            fn do_thing(&self) {}
1427        }
1428        let name = "dev.peelz.foobar";
1429        let connection = Builder::session()
1430            .unwrap()
1431            .name(name)
1432            .unwrap()
1433            .serve_at("/dev/peelz/FooBar", MyInterface::default())
1434            .unwrap()
1435            .build()
1436            .await
1437            .unwrap();
1438
1439        let connection2 = Connection::session().await.unwrap();
1440        let dbus = DBusProxy::new(&connection2).await.unwrap();
1441        let mut stream = dbus
1442            .receive_name_owner_changed_with_args(&[(0, name), (2, "")])
1443            .await
1444            .unwrap();
1445
1446        drop(connection);
1447
1448        // If the connection is not dropped, this will hang forever.
1449        stream.next().await.unwrap();
1450
1451        // Let's still make sure the name is gone.
1452        let name_has_owner = dbus.name_has_owner(name.try_into().unwrap()).await.unwrap();
1453        assert!(!name_has_owner);
1454    }
1455
1456    #[tokio::test(start_paused = true)]
1457    #[timeout(15000)]
1458    async fn test_graceful_shutdown() {
1459        // If we have a second reference, it should wait until we drop it.
1460        let connection = Connection::session().await.unwrap();
1461        let clone = connection.clone();
1462        let mut shutdown = pin!(connection.graceful_shutdown());
1463        // Due to start_paused above, tokio will auto-advance time once the runtime is idle.
1464        // See https://docs.rs/tokio/latest/tokio/time/fn.pause.html.
1465        tokio::select! {
1466            _ = tokio::time::sleep(Duration::from_secs(u64::MAX)) => {},
1467            _ = &mut shutdown => {
1468                panic!("Graceful shutdown unexpectedly completed");
1469            }
1470        }
1471
1472        drop(clone);
1473        shutdown.await;
1474
1475        // An outstanding method call should also be sufficient to keep the connection alive.
1476        struct GracefulInterface {
1477            method_called: Event,
1478            wait_before_return: Option<EventListener>,
1479            announce_done: Event,
1480        }
1481
1482        #[crate::interface(name = "dev.peelz.TestGracefulShutdown")]
1483        impl GracefulInterface {
1484            async fn do_thing(&mut self) {
1485                self.method_called.notify(1);
1486                if let Some(listener) = self.wait_before_return.take() {
1487                    listener.await;
1488                }
1489                self.announce_done.notify(1);
1490            }
1491        }
1492
1493        let method_called = Event::new();
1494        let method_called_listener = method_called.listen();
1495
1496        let trigger_return = Event::new();
1497        let wait_before_return = Some(trigger_return.listen());
1498
1499        let announce_done = Event::new();
1500        let done_listener = announce_done.listen();
1501
1502        let interface = GracefulInterface {
1503            method_called,
1504            wait_before_return,
1505            announce_done,
1506        };
1507
1508        let name = "dev.peelz.TestGracefulShutdown";
1509        let obj = "/dev/peelz/TestGracefulShutdown";
1510        let connection = Builder::session()
1511            .unwrap()
1512            .name(name)
1513            .unwrap()
1514            .serve_at(obj, interface)
1515            .unwrap()
1516            .build()
1517            .await
1518            .unwrap();
1519
1520        // Call the method from another connection - it won't return until we tell it to.
1521        let client_conn = Connection::session().await.unwrap();
1522        tokio::spawn(async move {
1523            client_conn
1524                .call_method(Some(name), obj, Some(name), "DoThing", &())
1525                .await
1526                .unwrap();
1527        });
1528
1529        // Avoid races - make sure we've actually received the method call before we drop our
1530        // Connection handle.
1531        method_called_listener.await;
1532
1533        let mut shutdown = pin!(connection.graceful_shutdown());
1534        tokio::select! {
1535            _ = tokio::time::sleep(Duration::from_secs(u64::MAX)) => {},
1536            _ = &mut shutdown => {
1537                // While that method call is outstanding, graceful shutdown should not complete.
1538                panic!("Graceful shutdown unexpectedly completed");
1539            }
1540        }
1541
1542        // If we let the call complete, then the shutdown should complete eventually.
1543        trigger_return.notify(1);
1544        shutdown.await;
1545
1546        // The method call should have been allowed to finish properly.
1547        done_listener.await;
1548    }
1549}
1550
1551#[cfg(feature = "p2p")]
1552#[cfg(test)]
1553mod p2p_tests {
1554    use event_listener::Event;
1555    use futures_util::TryStreamExt;
1556    use ntest::timeout;
1557    use test_log::test;
1558    use zvariant::{Endian, NATIVE_ENDIAN};
1559
1560    use super::{Builder, Connection, socket};
1561    use crate::{Guid, Message, MessageStream, Result, conn::AuthMechanism};
1562
1563    // Same numbered client and server are already paired up.
1564    async fn test_p2p(
1565        server1: Connection,
1566        client1: Connection,
1567        server2: Connection,
1568        client2: Connection,
1569    ) -> Result<()> {
1570        let forward1 = {
1571            let stream = MessageStream::from(server1.clone());
1572            let sink = client2.clone();
1573
1574            stream.try_for_each(move |msg| {
1575                let sink = sink.clone();
1576                async move { sink.send(&msg).await }
1577            })
1578        };
1579        let forward2 = {
1580            let stream = MessageStream::from(client2.clone());
1581            let sink = server1.clone();
1582
1583            stream.try_for_each(move |msg| {
1584                let sink = sink.clone();
1585                async move { sink.send(&msg).await }
1586            })
1587        };
1588        let _forward_task = client1.executor().spawn(
1589            async move { futures_util::try_join!(forward1, forward2) },
1590            "forward_task",
1591        );
1592
1593        let server_ready = Event::new();
1594        let server_ready_listener = server_ready.listen();
1595        let client_done = Event::new();
1596        let client_done_listener = client_done.listen();
1597
1598        let server_future = async move {
1599            let mut stream = MessageStream::from(&server2);
1600            server_ready.notify(1);
1601            let method = loop {
1602                let m = stream.try_next().await?.unwrap();
1603                if m.to_string() == "Method call Test" {
1604                    assert_eq!(m.body().deserialize::<u64>().unwrap(), 64);
1605                    break m;
1606                }
1607            };
1608
1609            // Send another message first to check the queueing function on client side.
1610            server2
1611                .emit_signal(None::<()>, "/", "org.zbus.p2p", "ASignalForYou", &())
1612                .await?;
1613            server2.reply(&method.header(), &("yay")).await?;
1614            client_done_listener.await;
1615
1616            Ok(())
1617        };
1618
1619        let client_future = async move {
1620            let mut stream = MessageStream::from(&client1);
1621            server_ready_listener.await;
1622            // We want to set non-native endian to ensure that:
1623            // 1. the message is actually encoded with the specified endian.
1624            // 2. the server side is able to decode it and replies in the same encoding.
1625            let endian = match NATIVE_ENDIAN {
1626                Endian::Little => Endian::Big,
1627                Endian::Big => Endian::Little,
1628            };
1629            let method = Message::method_call("/", "Test")?
1630                .interface("org.zbus.p2p")?
1631                .endian(endian)
1632                .build(&64u64)?;
1633            client1.send(&method).await?;
1634            // Check we didn't miss the signal that was sent during the call.
1635            let m = stream.try_next().await?.unwrap();
1636            client_done.notify(1);
1637            assert_eq!(m.to_string(), "Signal ASignalForYou");
1638            let reply = stream.try_next().await?.unwrap();
1639            assert_eq!(reply.to_string(), "Method return");
1640            // Check if the reply was in the non-native endian.
1641            assert_eq!(Endian::from(reply.primary_header().endian_sig()), endian);
1642            reply.body().deserialize::<String>()
1643        };
1644
1645        let (val, _) = futures_util::try_join!(client_future, server_future,)?;
1646        assert_eq!(val, "yay");
1647
1648        Ok(())
1649    }
1650
1651    #[test]
1652    #[timeout(15000)]
1653    fn tcp_p2p() {
1654        crate::utils::block_on(test_tcp_p2p()).unwrap();
1655    }
1656
1657    async fn test_tcp_p2p() -> Result<()> {
1658        let (server1, client1) = tcp_p2p_pipe().await?;
1659        let (server2, client2) = tcp_p2p_pipe().await?;
1660
1661        test_p2p(server1, client1, server2, client2).await
1662    }
1663
1664    async fn tcp_p2p_pipe() -> Result<(Connection, Connection)> {
1665        let guid = Guid::generate();
1666
1667        #[cfg(not(feature = "tokio"))]
1668        let (server_conn_builder, client_conn_builder) = {
1669            let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
1670            let addr = listener.local_addr().unwrap();
1671            let p1 = std::net::TcpStream::connect(addr).unwrap();
1672            let p0 = listener.incoming().next().unwrap().unwrap();
1673
1674            (
1675                Builder::tcp_stream(p0)
1676                    .server(guid)
1677                    .unwrap()
1678                    .p2p()
1679                    .auth_mechanism(AuthMechanism::Anonymous),
1680                Builder::tcp_stream(p1).p2p(),
1681            )
1682        };
1683
1684        #[cfg(feature = "tokio")]
1685        let (server_conn_builder, client_conn_builder) = {
1686            let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
1687            let addr = listener.local_addr().unwrap();
1688            let p1 = tokio::net::TcpStream::connect(addr).await.unwrap();
1689            let p0 = listener.accept().await.unwrap().0;
1690
1691            (
1692                Builder::tcp_stream(p0)
1693                    .server(guid)
1694                    .unwrap()
1695                    .p2p()
1696                    .auth_mechanism(AuthMechanism::Anonymous),
1697                Builder::tcp_stream(p1).p2p(),
1698            )
1699        };
1700
1701        futures_util::try_join!(server_conn_builder.build(), client_conn_builder.build())
1702    }
1703
1704    #[cfg(unix)]
1705    #[test]
1706    #[timeout(15000)]
1707    fn unix_p2p() {
1708        crate::utils::block_on(test_unix_p2p()).unwrap();
1709    }
1710
1711    #[cfg(unix)]
1712    async fn test_unix_p2p() -> Result<()> {
1713        let (server1, client1) = unix_p2p_pipe().await?;
1714        let (server2, client2) = unix_p2p_pipe().await?;
1715
1716        test_p2p(server1, client1, server2, client2).await
1717    }
1718
1719    #[cfg(unix)]
1720    async fn unix_p2p_pipe() -> Result<(Connection, Connection)> {
1721        #[cfg(not(feature = "tokio"))]
1722        use std::os::unix::net::UnixStream;
1723        #[cfg(feature = "tokio")]
1724        use tokio::net::UnixStream;
1725        #[cfg(all(windows, not(feature = "tokio")))]
1726        use uds_windows::UnixStream;
1727
1728        let guid = Guid::generate();
1729
1730        let (p0, p1) = UnixStream::pair().unwrap();
1731
1732        futures_util::try_join!(
1733            Builder::unix_stream(p1).p2p().build(),
1734            Builder::unix_stream(p0).server(guid).unwrap().p2p().build(),
1735        )
1736    }
1737
1738    #[cfg(any(
1739        all(feature = "vsock", not(feature = "tokio")),
1740        feature = "tokio-vsock"
1741    ))]
1742    #[test]
1743    #[timeout(15000)]
1744    fn vsock_connect() {
1745        let _ = crate::utils::block_on(test_vsock_connect()).unwrap();
1746    }
1747
1748    #[cfg(any(
1749        all(feature = "vsock", not(feature = "tokio")),
1750        feature = "tokio-vsock"
1751    ))]
1752    async fn test_vsock_connect() -> Result<(Connection, Connection)> {
1753        #[cfg(feature = "tokio-vsock")]
1754        use futures_util::StreamExt;
1755
1756        let guid = Guid::generate();
1757
1758        #[cfg(all(feature = "vsock", not(feature = "tokio")))]
1759        let listener = vsock::VsockListener::bind_with_cid_port(vsock::VMADDR_CID_LOCAL, u32::MAX)?;
1760        #[cfg(feature = "tokio-vsock")]
1761        let listener = tokio_vsock::VsockListener::bind(tokio_vsock::VsockAddr::new(1, u32::MAX))?;
1762
1763        let addr = listener.local_addr()?;
1764        let addr = format!("vsock:cid={},port={},guid={guid}", addr.cid(), addr.port());
1765
1766        let server = async {
1767            #[cfg(all(feature = "vsock", not(feature = "tokio")))]
1768            let server =
1769                crate::Task::spawn_blocking(move || listener.incoming().next(), "").await?;
1770            #[cfg(feature = "tokio-vsock")]
1771            let server = listener.incoming().next().await;
1772            Builder::vsock_stream(server.unwrap()?)
1773                .server(guid)?
1774                .p2p()
1775                .auth_mechanism(AuthMechanism::Anonymous)
1776                .build()
1777                .await
1778        };
1779
1780        let client = crate::connection::Builder::address(addr.as_str())?
1781            .p2p()
1782            .build();
1783
1784        futures_util::try_join!(server, client)
1785    }
1786
1787    #[cfg(any(
1788        all(feature = "vsock", not(feature = "tokio")),
1789        feature = "tokio-vsock"
1790    ))]
1791    #[test]
1792    #[timeout(15000)]
1793    fn vsock_p2p() {
1794        crate::utils::block_on(test_vsock_p2p()).unwrap();
1795    }
1796
1797    #[cfg(any(
1798        all(feature = "vsock", not(feature = "tokio")),
1799        feature = "tokio-vsock"
1800    ))]
1801    async fn test_vsock_p2p() -> Result<()> {
1802        let (server1, client1) = vsock_p2p_pipe().await?;
1803        let (server2, client2) = vsock_p2p_pipe().await?;
1804
1805        test_p2p(server1, client1, server2, client2).await
1806    }
1807
1808    #[cfg(all(feature = "vsock", not(feature = "tokio")))]
1809    async fn vsock_p2p_pipe() -> Result<(Connection, Connection)> {
1810        let guid = Guid::generate();
1811
1812        let listener =
1813            vsock::VsockListener::bind_with_cid_port(vsock::VMADDR_CID_LOCAL, u32::MAX).unwrap();
1814        let addr = listener.local_addr().unwrap();
1815        let client = vsock::VsockStream::connect(&addr).unwrap();
1816        let server = listener.incoming().next().unwrap().unwrap();
1817
1818        futures_util::try_join!(
1819            Builder::vsock_stream(server)
1820                .server(guid)
1821                .unwrap()
1822                .p2p()
1823                .auth_mechanism(AuthMechanism::Anonymous)
1824                .build(),
1825            Builder::vsock_stream(client).p2p().build(),
1826        )
1827    }
1828
1829    #[cfg(feature = "tokio-vsock")]
1830    async fn vsock_p2p_pipe() -> Result<(Connection, Connection)> {
1831        use futures_util::StreamExt;
1832        use tokio_vsock::VsockAddr;
1833
1834        let guid = Guid::generate();
1835
1836        let listener = tokio_vsock::VsockListener::bind(VsockAddr::new(1, u32::MAX)).unwrap();
1837        let addr = listener.local_addr().unwrap();
1838        let client = tokio_vsock::VsockStream::connect(addr).await.unwrap();
1839        let server = listener.incoming().next().await.unwrap().unwrap();
1840
1841        futures_util::try_join!(
1842            Builder::vsock_stream(server)
1843                .server(guid)
1844                .unwrap()
1845                .p2p()
1846                .auth_mechanism(AuthMechanism::Anonymous)
1847                .build(),
1848            Builder::vsock_stream(client).p2p().build(),
1849        )
1850    }
1851
1852    #[test]
1853    #[timeout(15000)]
1854    fn channel_pair() {
1855        crate::utils::block_on(test_channel_pair()).unwrap();
1856    }
1857
1858    async fn test_channel_pair() -> Result<()> {
1859        let (server1, client1) = create_channel_pair().await;
1860        let (server2, client2) = create_channel_pair().await;
1861
1862        test_p2p(server1, client1, server2, client2).await
1863    }
1864
1865    async fn create_channel_pair() -> (Connection, Connection) {
1866        let (a, b) = socket::Channel::pair();
1867
1868        let guid = crate::Guid::generate();
1869        let conn1 = Builder::authenticated_socket(a, guid.clone())
1870            .unwrap()
1871            .p2p()
1872            .build()
1873            .await
1874            .unwrap();
1875        let conn2 = Builder::authenticated_socket(b, guid)
1876            .unwrap()
1877            .p2p()
1878            .build()
1879            .await
1880            .unwrap();
1881
1882        (conn1, conn2)
1883    }
1884}