Rewrite available wifi code into something much cleaner
This commit is contained in:
parent
f3a20ec7b2
commit
585946bbfa
1 changed files with 47 additions and 117 deletions
|
|
@ -1,135 +1,65 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
use crate::task;
|
||||||
use cosmic_dbus_networkmanager::{
|
use cosmic_dbus_networkmanager::{
|
||||||
device::SpecificDevice, interface::enums::ApSecurityFlags, nm::NetworkManager,
|
device::{wireless::WirelessDevice, SpecificDevice},
|
||||||
|
nm::NetworkManager,
|
||||||
};
|
};
|
||||||
use futures_util::{StreamExt, TryFutureExt};
|
use futures_util::StreamExt;
|
||||||
use gtk4::{
|
use gtk4::{
|
||||||
glib, prelude::*, Align, Button, Dialog, HeaderBar, Image, Label, Orientation, ScrolledWindow,
|
glib::{source::PRIORITY_DEFAULT, MainContext, Sender},
|
||||||
Spinner,
|
prelude::*,
|
||||||
};
|
|
||||||
use itertools::Itertools;
|
|
||||||
use slotmap::{DefaultKey, SlotMap};
|
|
||||||
use std::{
|
|
||||||
rc::Rc,
|
|
||||||
sync::{
|
|
||||||
atomic::{AtomicBool, Ordering},
|
|
||||||
Arc,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
|
|
||||||
pub fn add_available_wifi(target: >k4::Box) {}
|
pub fn add_available_wifi(target: >k4::Box) {
|
||||||
|
let (tx, rx) = MainContext::channel::<Vec<AccessPoint>>(PRIORITY_DEFAULT);
|
||||||
|
task::spawn(scan_for_wifi(tx));
|
||||||
|
rx.attach(None, |aps| Continue(true));
|
||||||
|
}
|
||||||
|
|
||||||
async fn scan_for_devices(tx: UnboundedSender<SlotMap<DefaultKey, AccessPoint>>) {
|
async fn scan_for_wifi(tx: Sender<Vec<AccessPoint>>) -> zbus::Result<()> {
|
||||||
let sys_conn = match Connection::system().await {
|
let conn = Connection::system().await?;
|
||||||
Ok(conn) => conn,
|
let network_manager = NetworkManager::new(&conn).await?;
|
||||||
Err(err) => {
|
loop {
|
||||||
//error!(%err, "Failed to connect to system dbus session");
|
let devices = network_manager.devices().await?;
|
||||||
return;
|
for device in devices {
|
||||||
}
|
if let Ok(Some(SpecificDevice::Wireless(wireless_device))) =
|
||||||
};
|
device.downcast_to_device().await
|
||||||
let nm = match NetworkManager::new(&sys_conn).await {
|
{
|
||||||
Ok(p) => p,
|
handle_wireless_device(wireless_device, tx.clone()).await?;
|
||||||
Err(err) => {
|
|
||||||
//error!(%err, "Failed to set up connection to NetworkManager dbus");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let devices = match nm.devices().await {
|
|
||||||
Ok(d) => d,
|
|
||||||
Err(err) => {
|
|
||||||
//error!(%err, "Failed to get devices from NetworkManager");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut all_aps = SlotMap::new();
|
|
||||||
|
|
||||||
for d in devices {
|
|
||||||
if let Ok(Some(SpecificDevice::Wireless(w))) = d.downcast_to_device().await {
|
|
||||||
let id = d
|
|
||||||
.active_connection()
|
|
||||||
.and_then(|ac| async move { ac.id().await })
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|_| "unknown".to_string());
|
|
||||||
if let Err(err) = w.request_scan(std::collections::HashMap::new()).await {
|
|
||||||
//error!(%err, %id, "Wi-Fi scan failed");
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let mut scan_changed = w.receive_last_scan_changed().await;
|
|
||||||
if let Some(t) = scan_changed.next().await {
|
|
||||||
if let Ok(t) = t.get().await {
|
|
||||||
if t == -1 {
|
|
||||||
//error!(%id, "Getting access point failed");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match w.get_access_points().await {
|
|
||||||
Ok(aps) => {
|
|
||||||
if !aps.is_empty() {
|
|
||||||
for ap in AccessPoint::from_list(aps).await {
|
|
||||||
all_aps.insert(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
//error!(%err, %id, "Getting access points failed");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||||
|
|
||||||
if let Err(err) = tx.send(all_aps) {
|
|
||||||
//error!(%err, "failed to send AP list");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
async fn handle_wireless_device(
|
||||||
pub struct AccessPoint {
|
device: WirelessDevice<'_>,
|
||||||
pub ssid: String,
|
tx: Sender<Vec<AccessPoint>>,
|
||||||
pub hw_address: String,
|
) -> zbus::Result<()> {
|
||||||
pub strength: u8,
|
device
|
||||||
pub wpa_flags: ApSecurityFlags,
|
.request_scan(std::collections::HashMap::new())
|
||||||
}
|
.await?;
|
||||||
|
let mut scan_changed = device.receive_last_scan_changed().await;
|
||||||
impl AccessPoint {
|
if let Some(t) = scan_changed.next().await {
|
||||||
pub async fn new(
|
if let Ok(-1) = t.get().await {
|
||||||
ap: cosmic_dbus_networkmanager::access_point::AccessPoint<'_>,
|
return Ok(());
|
||||||
) -> Option<Self> {
|
|
||||||
Some(Self {
|
|
||||||
ssid: ap
|
|
||||||
.ssid()
|
|
||||||
.await
|
|
||||||
.map(|x| String::from_utf8_lossy(&x).into_owned())
|
|
||||||
.ok()?,
|
|
||||||
hw_address: ap.hw_address().await.ok()?,
|
|
||||||
strength: ap.strength().await.ok()?,
|
|
||||||
wpa_flags: ap.wpa_flags().await.ok()?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn from_list(
|
|
||||||
aps: Vec<cosmic_dbus_networkmanager::access_point::AccessPoint<'_>>,
|
|
||||||
) -> Vec<Self> {
|
|
||||||
let mut out = Vec::<Self>::with_capacity(aps.len());
|
|
||||||
for ap in aps {
|
|
||||||
if let Some(ap) = Self::new(ap).await {
|
|
||||||
out.push(ap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let mut ret = out
|
|
||||||
.into_iter()
|
|
||||||
.sorted_by(|a, b| a.strength.cmp(&b.strength))
|
|
||||||
.rev()
|
|
||||||
.unique_by(|ap| ap.ssid.clone())
|
|
||||||
.collect::<Vec<Self>>();
|
|
||||||
// for some reason adding .rev() messes up unique_by, so we do this instead
|
|
||||||
ret.reverse();
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
|
let access_points = device.get_access_points().await?;
|
||||||
|
let mut aps = Vec::with_capacity(access_points.len());
|
||||||
|
for ap in access_points {
|
||||||
|
aps.push(AccessPoint {
|
||||||
|
ssid: String::from_utf8_lossy(&ap.ssid().await?.clone()).into_owned(),
|
||||||
|
strength: ap.strength().await?,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccessPoint {
|
||||||
|
ssid: String,
|
||||||
|
strength: u8,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue