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