wayle_network/core/connection/
mod.rs1mod monitoring;
2mod types;
3
4use std::sync::Arc;
5
6use derive_more::Debug;
7use futures::{Stream, StreamExt};
8use tokio_util::sync::CancellationToken;
9use tracing::warn;
10pub(crate) use types::{ActiveConnectionParams, LiveActiveConnectionParams};
11pub use types::{ActiveConnectionStateChangedEvent, VpnConnectionStateChangedEvent};
12use wayle_core::{Property, unwrap_dbus};
13use wayle_traits::{ModelMonitoring, Reactive};
14use zbus::{Connection, zvariant::OwnedObjectPath};
15
16use crate::{
17 error::Error,
18 proxy::active_connection::{ConnectionActiveProxy, vpn::VPNConnectionProxy},
19 types::{
20 flags::NMActivationStateFlags,
21 states::{
22 NMActiveConnectionState, NMActiveConnectionStateReason, NMVpnConnectionState,
23 NMVpnConnectionStateReason,
24 },
25 },
26};
27
28#[derive(Debug, Clone)]
34pub struct ActiveConnection {
35 #[debug(skip)]
36 pub(crate) zbus_connection: Connection,
37
38 #[debug(skip)]
40 pub(crate) cancellation_token: Option<CancellationToken>,
41
42 pub object_path: OwnedObjectPath,
44
45 pub connection_path: Property<OwnedObjectPath>,
47
48 pub specific_object: Property<OwnedObjectPath>,
52
53 pub id: Property<String>,
55
56 pub uuid: Property<String>,
58
59 pub type_: Property<String>,
61
62 pub devices: Property<Vec<OwnedObjectPath>>,
65
66 pub state: Property<NMActiveConnectionState>,
68
69 pub state_flags: Property<NMActivationStateFlags>,
71
72 pub default: Property<bool>,
75
76 pub ip4_config: Property<OwnedObjectPath>,
80
81 pub dhcp4_config: Property<OwnedObjectPath>,
85
86 pub default6: Property<bool>,
89
90 pub ip6_config: Property<OwnedObjectPath>,
94
95 pub dhcp6_config: Property<OwnedObjectPath>,
99
100 pub vpn: Property<bool>,
102
103 pub controller: Property<OwnedObjectPath>,
105}
106
107impl Reactive for ActiveConnection {
108 type Context<'a> = ActiveConnectionParams<'a>;
109 type LiveContext<'a> = LiveActiveConnectionParams<'a>;
110 type Error = Error;
111
112 async fn get(params: Self::Context<'_>) -> Result<Self, Self::Error> {
113 Self::from_path(params.connection, params.path, None).await
114 }
115
116 async fn get_live(params: Self::LiveContext<'_>) -> Result<Arc<Self>, Self::Error> {
117 let active_connection = Self::from_path(
118 params.connection,
119 params.path.clone(),
120 Some(params.cancellation_token.child_token()),
121 )
122 .await?;
123 let active_connection = Arc::new(active_connection);
124
125 active_connection.clone().start_monitoring().await?;
126
127 Ok(active_connection)
128 }
129}
130
131impl ActiveConnection {
132 async fn from_path(
133 connection: &Connection,
134 path: OwnedObjectPath,
135 cancellation_token: Option<CancellationToken>,
136 ) -> Result<Self, Error> {
137 let connection_proxy = ConnectionActiveProxy::new(connection, &path).await?;
138
139 if connection_proxy.connection().await.is_err() {
140 warn!(
141 "Active Connection at path '{}' does not exist.",
142 path.clone()
143 );
144 return Err(Error::ObjectNotFound(path.clone()));
145 }
146
147 let (
148 connection_path,
149 specific_object,
150 id,
151 uuid,
152 type_,
153 devices,
154 state,
155 state_flags,
156 default,
157 ip4_config,
158 dhcp4_config,
159 default6,
160 ip6_config,
161 dhcp6_config,
162 vpn,
163 controller,
164 ) = tokio::join!(
165 connection_proxy.connection(),
166 connection_proxy.specific_object(),
167 connection_proxy.id(),
168 connection_proxy.uuid(),
169 connection_proxy.type_(),
170 connection_proxy.devices(),
171 connection_proxy.state(),
172 connection_proxy.state_flags(),
173 connection_proxy.default(),
174 connection_proxy.ip4_config(),
175 connection_proxy.dhcp4_config(),
176 connection_proxy.default6(),
177 connection_proxy.ip6_config(),
178 connection_proxy.dhcp6_config(),
179 connection_proxy.vpn(),
180 connection_proxy.controller(),
181 );
182
183 let connection_path = unwrap_dbus!(connection_path, path);
184 let specific_object = unwrap_dbus!(specific_object, path);
185 let id = unwrap_dbus!(id, path);
186 let uuid = unwrap_dbus!(uuid, path);
187 let type_ = unwrap_dbus!(type_, path);
188 let devices = unwrap_dbus!(devices, path);
189 let state = NMActiveConnectionState::from_u32(unwrap_dbus!(state, path));
190 let state_flags =
191 NMActivationStateFlags::from_bits_truncate(unwrap_dbus!(state_flags, path));
192 let default = unwrap_dbus!(default, path);
193 let ip4_config = unwrap_dbus!(ip4_config, path);
194 let dhcp4_config = unwrap_dbus!(dhcp4_config, path);
195 let default6 = unwrap_dbus!(default6, path);
196 let ip6_config = unwrap_dbus!(ip6_config, path);
197 let dhcp6_config = unwrap_dbus!(dhcp6_config, path);
198 let vpn = unwrap_dbus!(vpn, path);
199 let controller = unwrap_dbus!(controller, path);
200
201 Ok(Self {
202 connection_path: Property::new(connection_path),
203 specific_object: Property::new(specific_object),
204 id: Property::new(id),
205 uuid: Property::new(uuid),
206 type_: Property::new(type_),
207 devices: Property::new(devices),
208 state: Property::new(state),
209 state_flags: Property::new(state_flags),
210 default: Property::new(default),
211 ip4_config: Property::new(ip4_config),
212 dhcp4_config: Property::new(dhcp4_config),
213 default6: Property::new(default6),
214 ip6_config: Property::new(ip6_config),
215 dhcp6_config: Property::new(dhcp6_config),
216 vpn: Property::new(vpn),
217 controller: Property::new(controller),
218 zbus_connection: connection.clone(),
219 object_path: path,
220 cancellation_token,
221 })
222 }
223
224 pub async fn active_connection_state_changed_signal(
229 &self,
230 ) -> Result<impl Stream<Item = ActiveConnectionStateChangedEvent>, Error> {
231 let proxy = ConnectionActiveProxy::new(&self.zbus_connection, &self.object_path).await?;
232 let stream = proxy.receive_active_connection_state_changed().await?;
233
234 Ok(stream.filter_map(|signal| async move {
235 signal
236 .args()
237 .ok()
238 .map(|args| ActiveConnectionStateChangedEvent {
239 state: NMActiveConnectionState::from_u32(args.state),
240 reason: NMActiveConnectionStateReason::from_u32(args.reason),
241 })
242 }))
243 }
244
245 pub async fn vpn_connection_state_changed_signal(
250 &self,
251 ) -> Result<impl Stream<Item = VpnConnectionStateChangedEvent>, Error> {
252 let proxy = VPNConnectionProxy::new(&self.zbus_connection, &self.object_path).await?;
253 let stream = proxy.receive_vpn_connection_state_changed().await?;
254
255 Ok(stream.filter_map(|signal| async move {
256 signal
257 .args()
258 .ok()
259 .map(|args| VpnConnectionStateChangedEvent {
260 state: NMVpnConnectionState::from_u32(args.state),
261 reason: NMVpnConnectionStateReason::from_u32(args.reason),
262 })
263 }))
264 }
265}