ashpd/desktop/
network_monitor.rs

1//! **Note** This portal doesn't work for sandboxed applications.
2//! # Examples
3//!
4//! ```rust,no_run
5//! use ashpd::desktop::network_monitor::NetworkMonitor;
6//!
7//! async fn run() -> ashpd::Result<()> {
8//!     let proxy = NetworkMonitor::new().await?;
9//!
10//!     println!("{}", proxy.can_reach("www.google.com", 80).await?);
11//!     println!("{}", proxy.is_available().await?);
12//!     println!("{:#?}", proxy.connectivity().await?);
13//!     println!("{}", proxy.is_metered().await?);
14//!     println!("{:#?}", proxy.status().await?);
15//!
16//!     Ok(())
17//! }
18//! ```
19
20use std::fmt;
21
22use futures_util::Stream;
23use serde_repr::Deserialize_repr;
24use zbus::zvariant::{DeserializeDict, Type};
25
26use crate::{proxy::Proxy, Error};
27
28#[derive(DeserializeDict, Type, Debug)]
29/// The network status, composed of the availability, metered & connectivity
30#[zvariant(signature = "dict")]
31pub struct NetworkStatus {
32    /// Whether the network is considered available.
33    available: bool,
34    /// Whether the network is considered metered.
35    metered: bool,
36    /// More detailed information about the host's network connectivity
37    connectivity: Connectivity,
38}
39
40impl NetworkStatus {
41    /// Returns whether the network is considered available.
42    pub fn is_available(&self) -> bool {
43        self.available
44    }
45
46    /// Returns whether the network is considered metered.
47    pub fn is_metered(&self) -> bool {
48        self.metered
49    }
50
51    /// Returns more detailed information about the host's network connectivity.
52    pub fn connectivity(&self) -> Connectivity {
53        self.connectivity
54    }
55}
56
57#[cfg_attr(feature = "glib", derive(glib::Enum))]
58#[cfg_attr(feature = "glib", enum_type(name = "AshpdConnectivity"))]
59#[derive(Deserialize_repr, PartialEq, Eq, Debug, Clone, Copy, Type)]
60#[repr(u32)]
61/// Host's network activity
62pub enum Connectivity {
63    /// The host is not configured with a route to the internet.
64    Local = 1,
65    /// The host is connected to a network, but can't reach the full internet.
66    Limited = 2,
67    /// The host is behind a captive portal and cannot reach the full internet.
68    CaptivePortal = 3,
69    /// The host connected to a network, and can reach the full internet.
70    FullNetwork = 4,
71}
72
73impl fmt::Display for Connectivity {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        let connectivity = match self {
76            Self::Local => "local",
77            Self::Limited => "limited",
78            Self::CaptivePortal => "captive portal",
79            Self::FullNetwork => "full network",
80        };
81        f.write_str(connectivity)
82    }
83}
84
85/// The interface provides network status information to sandboxed applications.
86///
87/// It is not a portal in the strict sense, since it does not involve user
88/// interaction. Applications are expected to use this interface indirectly,
89/// via a library API such as the GLib [`gio::NetworkMonitor`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/gio/struct.NetworkMonitor.html) interface.
90///
91/// Wrapper of the DBus interface: [`org.freedesktop.portal.NetworkMonitor`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html).
92#[derive(Debug)]
93#[doc(alias = "org.freedesktop.portal.NetworkMonitor")]
94pub struct NetworkMonitor<'a>(Proxy<'a>);
95
96impl<'a> NetworkMonitor<'a> {
97    /// Create a new instance of [`NetworkMonitor`].
98    pub async fn new() -> Result<NetworkMonitor<'a>, Error> {
99        let proxy = Proxy::new_desktop("org.freedesktop.portal.NetworkMonitor").await?;
100        Ok(Self(proxy))
101    }
102
103    /// Returns whether the given hostname is believed to be reachable.
104    ///
105    /// # Arguments
106    ///
107    /// * `hostname` - The hostname to reach.
108    /// * `port` - The port to reach.
109    ///
110    /// # Required version
111    ///
112    /// The method requires the 3nd version implementation of the portal and
113    /// would fail with [`Error::RequiresVersion`] otherwise.
114    ///
115    /// # Specifications
116    ///
117    /// See also [`CanReach`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html#org-freedesktop-portal-networkmonitor-canreach).
118    #[doc(alias = "CanReach")]
119    pub async fn can_reach(&self, hostname: &str, port: u32) -> Result<bool, Error> {
120        self.0
121            .call_versioned("CanReach", &(hostname, port), 3)
122            .await
123    }
124
125    /// Returns whether the network is considered available.
126    /// That is, whether the system as a default route for at least one of IPv4
127    /// or IPv6.
128    ///
129    /// # Required version
130    ///
131    /// The method requires the 2nd version implementation of the portal and
132    /// would fail with [`Error::RequiresVersion`] otherwise.
133    ///
134    /// # Specifications
135    ///
136    /// See also [`GetAvailable`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html#org-freedesktop-portal-networkmonitor-getavailable).
137    #[doc(alias = "GetAvailable")]
138    #[doc(alias = "get_available")]
139    pub async fn is_available(&self) -> Result<bool, Error> {
140        self.0.call_versioned("GetAvailable", &(), 2).await
141    }
142
143    /// Returns more detailed information about the host's network connectivity.
144    ///
145    /// # Required version
146    ///
147    /// The method requires the 2nd version implementation of the portal and
148    /// would fail with [`Error::RequiresVersion`] otherwise.
149    ///
150    /// # Specifications
151    ///
152    /// See also [`GetConnectivity`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html#org-freedesktop-portal-networkmonitor-getconnectivity).
153    #[doc(alias = "GetConnectivity")]
154    #[doc(alias = "get_connectivity")]
155    pub async fn connectivity(&self) -> Result<Connectivity, Error> {
156        self.0.call_versioned("GetConnectivity", &(), 2).await
157    }
158
159    /// Returns whether the network is considered metered.
160    /// That is, whether the system as traffic flowing through the default
161    /// connection that is subject to limitations by service providers.
162    ///
163    /// # Required version
164    ///
165    /// The method requires the 2nd version implementation of the portal and
166    /// would fail with [`Error::RequiresVersion`] otherwise.
167    ///
168    /// # Specifications
169    ///
170    /// See also [`GetMetered`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html#org-freedesktop-portal-networkmonitor-getmetered).
171    #[doc(alias = "GetMetered")]
172    #[doc(alias = "get_metered")]
173    pub async fn is_metered(&self) -> Result<bool, Error> {
174        self.0.call_versioned("GetMetered", &(), 2).await
175    }
176
177    /// Returns the three values all at once.
178    ///
179    /// # Required version
180    ///
181    /// The method requires the 3nd version implementation of the portal and
182    /// would fail with [`Error::RequiresVersion`] otherwise.
183    ///
184    /// # Specifications
185    ///
186    /// See also [`GetStatus`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html#org-freedesktop-portal-networkmonitor-getstatus).
187    #[doc(alias = "GetStatus")]
188    #[doc(alias = "get_status")]
189    pub async fn status(&self) -> Result<NetworkStatus, Error> {
190        self.0.call_versioned("GetStatus", &(), 3).await
191    }
192
193    /// Emitted when the network configuration changes.
194    ///
195    /// # Specifications
196    ///
197    /// See also [`changed`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.NetworkMonitor.html#org-freedesktop-portal-networkmonitor-changed).
198    pub async fn receive_changed(&self) -> Result<impl Stream<Item = ()>, Error> {
199        self.0.signal("changed").await
200    }
201}
202
203impl<'a> std::ops::Deref for NetworkMonitor<'a> {
204    type Target = zbus::Proxy<'a>;
205
206    fn deref(&self) -> &Self::Target {
207        &self.0
208    }
209}