wayle_network/core/access_point/
mod.rs1use std::sync::Arc;
2
3use derive_more::Debug;
4use tokio_util::sync::CancellationToken;
5use wayle_core::{Property, unwrap_dbus, unwrap_dbus_or};
6use wayle_traits::{ModelMonitoring, Reactive};
7use zbus::{Connection, zvariant::OwnedObjectPath};
8
9use self::types::{AccessPointParams, Bssid, LiveAccessPointParams};
10use crate::{
11 error::Error,
12 proxy::access_point::AccessPointProxy,
13 types::{
14 flags::{NM80211ApFlags, NM80211ApSecurityFlags},
15 wifi::NM80211Mode,
16 },
17};
18
19pub(crate) mod monitoring;
20pub(crate) mod types;
21
22pub use self::types::{SecurityType, Ssid};
23
24#[derive(Debug, Clone)]
30pub struct AccessPoint {
31 #[debug(skip)]
32 pub(crate) connection: Connection,
33 #[debug(skip)]
34 pub(crate) object_path: OwnedObjectPath,
35 #[debug(skip)]
36 pub(crate) cancellation_token: Option<CancellationToken>,
37 pub flags: Property<NM80211ApFlags>,
39
40 pub wpa_flags: Property<NM80211ApSecurityFlags>,
43
44 pub rsn_flags: Property<NM80211ApSecurityFlags>,
47
48 pub ssid: Property<Ssid>,
51
52 pub frequency: Property<u32>,
54
55 pub bssid: Property<Bssid>,
57
58 pub mode: Property<NM80211Mode>,
60
61 pub max_bitrate: Property<u32>,
63
64 pub bandwidth: Property<u32>,
66
67 pub strength: Property<u8>,
69
70 pub last_seen: Property<i32>,
74
75 pub security: Property<SecurityType>,
79
80 pub is_hidden: Property<bool>,
82}
83
84impl Reactive for AccessPoint {
85 type Context<'a> = AccessPointParams<'a>;
86 type LiveContext<'a> = LiveAccessPointParams<'a>;
87 type Error = Error;
88
89 async fn get(params: Self::Context<'_>) -> Result<Self, Self::Error> {
90 let ap = Self::from_path(params.connection, params.path.clone(), None)
91 .await
92 .map_err(|e| match e {
93 Error::ObjectNotFound(_) => e,
94 _ => Error::ObjectCreationFailed {
95 object_type: String::from("AccessPoint"),
96 object_path: params.path.clone(),
97 source: e.into(),
98 },
99 })?;
100
101 Ok(ap)
102 }
103
104 async fn get_live(params: Self::LiveContext<'_>) -> Result<Arc<Self>, Self::Error> {
105 let access_point = Self::from_path(
106 params.connection,
107 params.path.clone(),
108 Some(params.cancellation_token.child_token()),
109 )
110 .await
111 .map_err(|e| match e {
112 Error::ObjectNotFound(_) => e,
113 _ => Error::ObjectCreationFailed {
114 object_type: String::from("AccessPoint"),
115 object_path: params.path.clone(),
116 source: e.into(),
117 },
118 })?;
119 let access_point = Arc::new(access_point);
120 access_point.clone().start_monitoring().await?;
121
122 Ok(access_point)
123 }
124}
125
126impl PartialEq for AccessPoint {
127 fn eq(&self, other: &Self) -> bool {
128 self.bssid.get() == other.bssid.get()
129 }
130}
131
132impl AccessPoint {
133 pub fn object_path(&self) -> &OwnedObjectPath {
135 &self.object_path
136 }
137
138 async fn from_path(
139 connection: &Connection,
140 path: OwnedObjectPath,
141 cancellation_token: Option<CancellationToken>,
142 ) -> Result<Self, Error> {
143 let ap_proxy = AccessPointProxy::new(connection, &path)
144 .await
145 .map_err(Error::DbusError)?;
146
147 if ap_proxy.strength().await.is_err() {
148 return Err(Error::ObjectNotFound(path.clone()));
149 }
150
151 let (
152 flags,
153 wpa_flags,
154 rsn_flags,
155 ssid,
156 frequency,
157 hw_address,
158 mode,
159 max_bitrate,
160 bandwidth,
161 strength,
162 last_seen,
163 ) = tokio::join!(
164 ap_proxy.flags(),
165 ap_proxy.wpa_flags(),
166 ap_proxy.rsn_flags(),
167 ap_proxy.ssid(),
168 ap_proxy.frequency(),
169 ap_proxy.hw_address(),
170 ap_proxy.mode(),
171 ap_proxy.max_bitrate(),
172 ap_proxy.bandwidth(),
173 ap_proxy.strength(),
174 ap_proxy.last_seen(),
175 );
176
177 let flags = NM80211ApFlags::from_bits_truncate(unwrap_dbus!(flags, path));
178 let wpa_flags = NM80211ApSecurityFlags::from_bits_truncate(unwrap_dbus!(wpa_flags, path));
179 let rsn_flags = NM80211ApSecurityFlags::from_bits_truncate(unwrap_dbus!(rsn_flags, path));
180 let ssid = Ssid::new(unwrap_dbus!(ssid, path));
181 let frequency = unwrap_dbus!(frequency, path);
182 let hw_address = Bssid::new(unwrap_dbus!(hw_address, path).into_bytes());
183 let mode = NM80211Mode::from_u32(unwrap_dbus!(mode, path));
184 let max_bitrate = unwrap_dbus!(max_bitrate, path);
185 let bandwidth = unwrap_dbus!(bandwidth, path);
186 let strength = unwrap_dbus!(strength, path);
187 let last_seen = unwrap_dbus_or!(last_seen, path, -1);
188
189 let security = SecurityType::from_flags(flags, wpa_flags, rsn_flags);
190 let is_hidden = ssid.is_empty();
191
192 Ok(Self {
193 connection: connection.clone(),
194 object_path: path.clone(),
195 cancellation_token,
196 flags: Property::new(flags),
197 wpa_flags: Property::new(wpa_flags),
198 rsn_flags: Property::new(rsn_flags),
199 ssid: Property::new(ssid),
200 frequency: Property::new(frequency),
201 bssid: Property::new(hw_address),
202 mode: Property::new(mode),
203 max_bitrate: Property::new(max_bitrate),
204 bandwidth: Property::new(bandwidth),
205 strength: Property::new(strength),
206 last_seen: Property::new(last_seen),
207 security: Property::new(security),
208 is_hidden: Property::new(is_hidden),
209 })
210 }
211}