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}