Merge pull request #74 from pop-os/network_jammy
feat(network): improve state handling & add disconnect option
This commit is contained in:
commit
22b729b966
4 changed files with 173 additions and 142 deletions
|
|
@ -20,7 +20,7 @@ use cosmic::{
|
||||||
widget::{button, divider, icon, toggler},
|
widget::{button, divider, icon, toggler},
|
||||||
Element, Theme,
|
Element, Theme,
|
||||||
};
|
};
|
||||||
use cosmic_dbus_networkmanager::interface::enums::DeviceState;
|
use cosmic_dbus_networkmanager::interface::enums::{ActiveConnectionState, DeviceState};
|
||||||
use futures::channel::mpsc::UnboundedSender;
|
use futures::channel::mpsc::UnboundedSender;
|
||||||
|
|
||||||
use crate::network_manager::NetworkManagerState;
|
use crate::network_manager::NetworkManagerState;
|
||||||
|
|
@ -47,12 +47,26 @@ enum NewConnectionState {
|
||||||
Failure(AccessPoint),
|
Failure(AccessPoint),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NewConnectionState {
|
||||||
|
pub fn ssid(&self) -> &str {
|
||||||
|
&match self {
|
||||||
|
NewConnectionState::EnterPassword {
|
||||||
|
access_point,
|
||||||
|
password: _,
|
||||||
|
} => access_point,
|
||||||
|
NewConnectionState::Waiting(ap) => ap,
|
||||||
|
NewConnectionState::Failure(ap) => ap,
|
||||||
|
}
|
||||||
|
.ssid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Into<AccessPoint> for NewConnectionState {
|
impl Into<AccessPoint> for NewConnectionState {
|
||||||
fn into(self) -> AccessPoint {
|
fn into(self) -> AccessPoint {
|
||||||
match self {
|
match self {
|
||||||
NewConnectionState::EnterPassword {
|
NewConnectionState::EnterPassword {
|
||||||
access_point,
|
access_point,
|
||||||
password,
|
password: _,
|
||||||
} => access_point,
|
} => access_point,
|
||||||
NewConnectionState::Waiting(access_point) => access_point,
|
NewConnectionState::Waiting(access_point) => access_point,
|
||||||
NewConnectionState::Failure(access_point) => access_point,
|
NewConnectionState::Failure(access_point) => access_point,
|
||||||
|
|
@ -100,6 +114,7 @@ impl CosmicNetworkApplet {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum Message {
|
enum Message {
|
||||||
ActivateKnownWifi(String),
|
ActivateKnownWifi(String),
|
||||||
|
Disconnect(String),
|
||||||
TogglePopup,
|
TogglePopup,
|
||||||
ToggleAirplaneMode(bool),
|
ToggleAirplaneMode(bool),
|
||||||
ToggleWiFi(bool),
|
ToggleWiFi(bool),
|
||||||
|
|
@ -137,6 +152,7 @@ impl Application for CosmicNetworkApplet {
|
||||||
match message {
|
match message {
|
||||||
Message::TogglePopup => {
|
Message::TogglePopup => {
|
||||||
if let Some(p) = self.popup.take() {
|
if let Some(p) = self.popup.take() {
|
||||||
|
self.show_visible_networks = false;
|
||||||
return destroy_popup(p);
|
return destroy_popup(p);
|
||||||
} else {
|
} else {
|
||||||
// TODO request update of state maybe
|
// TODO request update of state maybe
|
||||||
|
|
@ -184,17 +200,14 @@ impl Application for CosmicNetworkApplet {
|
||||||
self.nm_state = state;
|
self.nm_state = state;
|
||||||
self.update_icon_name();
|
self.update_icon_name();
|
||||||
}
|
}
|
||||||
NetworkManagerEvent::WiFiEnabled(enabled) => {
|
NetworkManagerEvent::WiFiEnabled(state) => {
|
||||||
if !enabled {
|
self.nm_state = state;
|
||||||
self.nm_state.clear();
|
|
||||||
}
|
|
||||||
self.nm_state.wifi_enabled = enabled;
|
|
||||||
}
|
}
|
||||||
NetworkManagerEvent::WirelessAccessPoints(access_points) => {
|
NetworkManagerEvent::WirelessAccessPoints(state) => {
|
||||||
self.nm_state.wireless_access_points = access_points;
|
self.nm_state = state;
|
||||||
}
|
}
|
||||||
NetworkManagerEvent::ActiveConns(conns) => {
|
NetworkManagerEvent::ActiveConns(state) => {
|
||||||
self.nm_state.active_conns = conns;
|
self.nm_state = state;
|
||||||
self.update_icon_name();
|
self.update_icon_name();
|
||||||
}
|
}
|
||||||
NetworkManagerEvent::RequestResponse {
|
NetworkManagerEvent::RequestResponse {
|
||||||
|
|
@ -204,26 +217,21 @@ impl Application for CosmicNetworkApplet {
|
||||||
} => {
|
} => {
|
||||||
if success {
|
if success {
|
||||||
match req {
|
match req {
|
||||||
NetworkManagerRequest::SetAirplaneMode(_)
|
NetworkManagerRequest::SelectAccessPoint(ssid)
|
||||||
| NetworkManagerRequest::SetWiFi(_) => {}
|
| NetworkManagerRequest::Password(ssid, _) => {
|
||||||
NetworkManagerRequest::SelectAccessPoint(_)
|
if self
|
||||||
| NetworkManagerRequest::Password(_, _) => {
|
.new_connection
|
||||||
self.new_connection.take();
|
.as_ref()
|
||||||
self.show_visible_networks = false;
|
.map(|c| c.ssid() == ssid)
|
||||||
|
.unwrap_or_default()
|
||||||
|
{
|
||||||
|
self.new_connection.take();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match req {
|
match req {
|
||||||
NetworkManagerRequest::SetAirplaneMode(_)
|
|
||||||
| NetworkManagerRequest::SetWiFi(_) => {}
|
|
||||||
NetworkManagerRequest::SelectAccessPoint(_) => {
|
|
||||||
if let Some(NewConnectionState::Waiting(access_point)) =
|
|
||||||
self.new_connection.as_ref()
|
|
||||||
{
|
|
||||||
self.new_connection
|
|
||||||
.replace(NewConnectionState::Failure(access_point.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NetworkManagerRequest::Password(_, _) => {
|
NetworkManagerRequest::Password(_, _) => {
|
||||||
if let Some(NewConnectionState::EnterPassword {
|
if let Some(NewConnectionState::EnterPassword {
|
||||||
access_point,
|
access_point,
|
||||||
|
|
@ -234,6 +242,7 @@ impl Application for CosmicNetworkApplet {
|
||||||
.replace(NewConnectionState::Failure(access_point.clone()));
|
.replace(NewConnectionState::Failure(access_point.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.nm_state = state;
|
self.nm_state = state;
|
||||||
|
|
@ -292,6 +301,13 @@ impl Application for CosmicNetworkApplet {
|
||||||
}
|
}
|
||||||
Message::ActivateKnownWifi(ssid) => {
|
Message::ActivateKnownWifi(ssid) => {
|
||||||
let tx = if let Some(tx) = self.nm_sender.as_ref() {
|
let tx = if let Some(tx) = self.nm_sender.as_ref() {
|
||||||
|
self.nm_state
|
||||||
|
.known_access_points
|
||||||
|
.iter_mut()
|
||||||
|
.find(|c| c.ssid == ssid)
|
||||||
|
.map(|ap| {
|
||||||
|
ap.working = true;
|
||||||
|
});
|
||||||
tx
|
tx
|
||||||
} else {
|
} else {
|
||||||
return Command::none();
|
return Command::none();
|
||||||
|
|
@ -301,6 +317,24 @@ impl Application for CosmicNetworkApplet {
|
||||||
Message::CancelNewConnection => {
|
Message::CancelNewConnection => {
|
||||||
self.new_connection.take();
|
self.new_connection.take();
|
||||||
}
|
}
|
||||||
|
Message::Disconnect(ssid) => {
|
||||||
|
let tx = if let Some(tx) = self.nm_sender.as_ref() {
|
||||||
|
self.nm_state
|
||||||
|
.active_conns
|
||||||
|
.iter_mut()
|
||||||
|
.find(|c| c.name() == ssid)
|
||||||
|
.map(|ap| match ap {
|
||||||
|
ActiveConnectionInfo::WiFi { state, .. } => {
|
||||||
|
*state = ActiveConnectionState::Deactivating;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
tx
|
||||||
|
} else {
|
||||||
|
return Command::none();
|
||||||
|
};
|
||||||
|
let _ = tx.unbounded_send(NetworkManagerRequest::Disconnect(ssid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
@ -341,7 +375,7 @@ impl Application for CosmicNetworkApplet {
|
||||||
}
|
}
|
||||||
ActiveConnectionInfo::Wired {
|
ActiveConnectionInfo::Wired {
|
||||||
name,
|
name,
|
||||||
hw_address,
|
hw_address: _,
|
||||||
speed,
|
speed,
|
||||||
ip_addresses,
|
ip_addresses,
|
||||||
} => {
|
} => {
|
||||||
|
|
@ -366,7 +400,10 @@ impl Application for CosmicNetworkApplet {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ActiveConnectionInfo::WiFi {
|
ActiveConnectionInfo::WiFi {
|
||||||
name, ip_addresses, ..
|
name,
|
||||||
|
ip_addresses,
|
||||||
|
state,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
let mut ipv4 = Vec::with_capacity(ip_addresses.len());
|
let mut ipv4 = Vec::with_capacity(ip_addresses.len());
|
||||||
for addr in ip_addresses {
|
for addr in ip_addresses {
|
||||||
|
|
@ -376,52 +413,81 @@ impl Application for CosmicNetworkApplet {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
known_wifi = known_wifi.push(column![button(Button::Secondary)
|
let mut btn_content = vec![
|
||||||
.custom(vec![
|
icon("network-wireless-symbolic", 24)
|
||||||
icon("network-wireless-symbolic", 24)
|
.style(Svg::Custom(|theme| svg::Appearance {
|
||||||
.style(Svg::Custom(|theme| svg::Appearance {
|
color: Some(theme.palette().text),
|
||||||
color: Some(theme.palette().text),
|
}))
|
||||||
}))
|
.width(Length::Units(24))
|
||||||
.width(Length::Units(24))
|
.height(Length::Units(24))
|
||||||
.height(Length::Units(24))
|
.into(),
|
||||||
.into(),
|
column![text(name).size(14), Column::with_children(ipv4)]
|
||||||
column![text(name).size(14), Column::with_children(ipv4)]
|
.width(Length::Fill)
|
||||||
.into(),
|
.into(),
|
||||||
|
];
|
||||||
|
match state {
|
||||||
|
ActiveConnectionState::Activating
|
||||||
|
| ActiveConnectionState::Deactivating => {
|
||||||
|
btn_content.push(
|
||||||
|
icon("process-working-symbolic", 24)
|
||||||
|
.style(Svg::Custom(|theme| svg::Appearance {
|
||||||
|
color: Some(theme.palette().text),
|
||||||
|
}))
|
||||||
|
.width(Length::Units(24))
|
||||||
|
.height(Length::Units(24))
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ActiveConnectionState::Activated => btn_content.push(
|
||||||
text(format!("{}", fl!("connected")))
|
text(format!("{}", fl!("connected")))
|
||||||
.size(14)
|
.size(14)
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Units(24))
|
|
||||||
.horizontal_alignment(Horizontal::Right)
|
.horizontal_alignment(Horizontal::Right)
|
||||||
.vertical_alignment(Vertical::Center)
|
.vertical_alignment(Vertical::Center)
|
||||||
.into()
|
.into(),
|
||||||
])
|
),
|
||||||
.padding([8, 24])
|
_ => {}
|
||||||
.style(button_style.clone())]);
|
};
|
||||||
|
known_wifi = known_wifi.push(
|
||||||
|
column![button(Button::Secondary)
|
||||||
|
.custom(btn_content)
|
||||||
|
.padding([8, 24])
|
||||||
|
.style(button_style.clone())
|
||||||
|
.on_press(Message::Disconnect(name.clone()))]
|
||||||
|
.align_items(Alignment::Center),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
for known in &self.nm_state.known_access_points {
|
for known in &self.nm_state.known_access_points {
|
||||||
let mut btn = button(Button::Secondary)
|
let mut btn_content = vec![
|
||||||
.custom(vec![
|
icon("network-wireless-symbolic", 24)
|
||||||
icon("network-wireless-symbolic", 24)
|
.style(Svg::Custom(|theme| svg::Appearance {
|
||||||
|
color: Some(theme.palette().text),
|
||||||
|
}))
|
||||||
|
.width(Length::Units(24))
|
||||||
|
.height(Length::Units(24))
|
||||||
|
.into(),
|
||||||
|
text(&known.ssid).size(14).width(Length::Fill).into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if known.working {
|
||||||
|
btn_content.push(
|
||||||
|
icon("process-working-symbolic", 24)
|
||||||
.style(Svg::Custom(|theme| svg::Appearance {
|
.style(Svg::Custom(|theme| svg::Appearance {
|
||||||
color: Some(theme.palette().text),
|
color: Some(theme.palette().text),
|
||||||
}))
|
}))
|
||||||
.width(Length::Units(24))
|
.width(Length::Units(24))
|
||||||
.height(Length::Units(24))
|
.height(Length::Units(24))
|
||||||
.into(),
|
.into(),
|
||||||
text(&known.ssid).size(14).into(),
|
);
|
||||||
])
|
}
|
||||||
|
|
||||||
|
let mut btn = button(Button::Secondary)
|
||||||
|
.custom(btn_content)
|
||||||
.padding([8, 24])
|
.padding([8, 24])
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.style(button_style.clone());
|
.style(button_style.clone());
|
||||||
btn = match known.state {
|
btn = match known.state {
|
||||||
// DeviceState::Prepare => todo!(),
|
|
||||||
// DeviceState::Config => todo!(),
|
|
||||||
// DeviceState::NeedAuth => todo!(),
|
|
||||||
// DeviceState::IpConfig => todo!(),
|
|
||||||
// DeviceState::IpCheck => todo!(),
|
|
||||||
// DeviceState::Secondaries => todo!(),
|
|
||||||
DeviceState::Failed
|
DeviceState::Failed
|
||||||
| DeviceState::Unknown
|
| DeviceState::Unknown
|
||||||
| DeviceState::Unmanaged
|
| DeviceState::Unmanaged
|
||||||
|
|
@ -429,6 +495,9 @@ impl Application for CosmicNetworkApplet {
|
||||||
| DeviceState::NeedAuth => {
|
| DeviceState::NeedAuth => {
|
||||||
btn.on_press(Message::ActivateKnownWifi(known.ssid.clone()))
|
btn.on_press(Message::ActivateKnownWifi(known.ssid.clone()))
|
||||||
}
|
}
|
||||||
|
DeviceState::Activated => {
|
||||||
|
btn.on_press(Message::Disconnect(known.ssid.clone()))
|
||||||
|
}
|
||||||
_ => btn,
|
_ => btn,
|
||||||
};
|
};
|
||||||
known_wifi = known_wifi.push(row![btn].align_items(Alignment::Center));
|
known_wifi = known_wifi.push(row![btn].align_items(Alignment::Center));
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ pub async fn handle_wireless_device(device: WirelessDevice<'_>) -> zbus::Result<
|
||||||
ssid,
|
ssid,
|
||||||
strength,
|
strength,
|
||||||
state: state,
|
state: state,
|
||||||
|
working: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -55,4 +56,5 @@ pub struct AccessPoint {
|
||||||
pub ssid: String,
|
pub ssid: String,
|
||||||
pub strength: u8,
|
pub strength: u8,
|
||||||
pub state: DeviceState,
|
pub state: DeviceState,
|
||||||
|
pub working: bool,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use cosmic_dbus_networkmanager::{
|
use cosmic_dbus_networkmanager::{
|
||||||
active_connection::ActiveConnection,
|
active_connection::ActiveConnection,
|
||||||
device::SpecificDevice,
|
device::SpecificDevice,
|
||||||
interface::enums::{ApFlags, ApSecurityFlags},
|
interface::enums::{ActiveConnectionState, ApFlags, ApSecurityFlags},
|
||||||
};
|
};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
|
|
@ -19,6 +19,10 @@ pub async fn active_connections(
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let addresses: Vec<_> = ipv4.iter().map(|d| d.address).collect();
|
let addresses: Vec<_> = ipv4.iter().map(|d| d.address).collect();
|
||||||
|
let state = connection
|
||||||
|
.state()
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|_| ActiveConnectionState::Unknown);
|
||||||
|
|
||||||
if connection.vpn().await.unwrap_or_default() {
|
if connection.vpn().await.unwrap_or_default() {
|
||||||
info.push(ActiveConnectionInfo::Vpn {
|
info.push(ActiveConnectionInfo::Vpn {
|
||||||
|
|
@ -51,6 +55,7 @@ pub async fn active_connections(
|
||||||
flags: access_point.flags().await?,
|
flags: access_point.flags().await?,
|
||||||
rsn_flags: access_point.rsn_flags().await?,
|
rsn_flags: access_point.rsn_flags().await?,
|
||||||
wpa_flags: access_point.wpa_flags().await?,
|
wpa_flags: access_point.wpa_flags().await?,
|
||||||
|
state,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,6 +97,7 @@ pub enum ActiveConnectionInfo {
|
||||||
flags: ApFlags,
|
flags: ApFlags,
|
||||||
rsn_flags: ApSecurityFlags,
|
rsn_flags: ApSecurityFlags,
|
||||||
wpa_flags: ApSecurityFlags,
|
wpa_flags: ApSecurityFlags,
|
||||||
|
state: ActiveConnectionState,
|
||||||
},
|
},
|
||||||
Vpn {
|
Vpn {
|
||||||
name: String,
|
name: String,
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,13 @@ use std::{collections::HashMap, fmt::Debug, hash::Hash, ops::Deref, time::Durati
|
||||||
|
|
||||||
use cosmic::iced::{self, subscription};
|
use cosmic::iced::{self, subscription};
|
||||||
use cosmic_dbus_networkmanager::{
|
use cosmic_dbus_networkmanager::{
|
||||||
active_connection::ActiveConnection,
|
|
||||||
device::SpecificDevice,
|
device::SpecificDevice,
|
||||||
interface::{
|
interface::{active_connection::ActiveConnectionProxy, enums, enums::DeviceType},
|
||||||
active_connection::ActiveConnectionProxy, enums, enums::DeviceType,
|
nm::NetworkManager,
|
||||||
settings::connection::ConnectionSettingsProxy,
|
settings::{connection::Settings, NetworkManagerSettings},
|
||||||
},
|
|
||||||
nm::{self, NetworkManager},
|
|
||||||
settings::{
|
|
||||||
connection::{ConnectionSettings, Secrets, Settings},
|
|
||||||
NetworkManagerSettings,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
|
channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender},
|
||||||
future::ok,
|
|
||||||
FutureExt, StreamExt,
|
FutureExt, StreamExt,
|
||||||
};
|
};
|
||||||
use tokio::{process::Command, time::timeout};
|
use tokio::{process::Command, time::timeout};
|
||||||
|
|
@ -91,6 +83,22 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
let (update, should_exit) = futures::select! {
|
let (update, should_exit) = futures::select! {
|
||||||
req = req => {
|
req = req => {
|
||||||
match req {
|
match req {
|
||||||
|
Some(NetworkManagerRequest::Disconnect(ssid)) => {
|
||||||
|
let mut success = false;
|
||||||
|
for c in network_manager.active_connections().await.unwrap_or_default() {
|
||||||
|
if c.id().await.unwrap_or_default() == ssid {
|
||||||
|
if let Ok(_) = network_manager.deactivate_connection(&c).await {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some((id,
|
||||||
|
NetworkManagerEvent::RequestResponse {
|
||||||
|
req: NetworkManagerRequest::Disconnect(ssid.clone()),
|
||||||
|
success,
|
||||||
|
state: NetworkManagerState::new(&conn).await.unwrap_or_default(),
|
||||||
|
})), false)
|
||||||
|
}
|
||||||
Some(NetworkManagerRequest::SetAirplaneMode(airplane_mode)) => {
|
Some(NetworkManagerRequest::SetAirplaneMode(airplane_mode)) => {
|
||||||
// wifi
|
// wifi
|
||||||
let mut success = network_manager.set_wireless_enabled(!airplane_mode).await.is_ok();
|
let mut success = network_manager.set_wireless_enabled(!airplane_mode).await.is_ok();
|
||||||
|
|
@ -103,7 +111,7 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
.is_ok();
|
.is_ok();
|
||||||
let response = NetworkManagerEvent::RequestResponse {
|
let response = NetworkManagerEvent::RequestResponse {
|
||||||
req: NetworkManagerRequest::SetAirplaneMode(airplane_mode),
|
req: NetworkManagerRequest::SetAirplaneMode(airplane_mode),
|
||||||
success: true,
|
success,
|
||||||
state: NetworkManagerState::new(&conn).await.unwrap_or_default(),
|
state: NetworkManagerState::new(&conn).await.unwrap_or_default(),
|
||||||
};
|
};
|
||||||
(Some((id, response)), false)
|
(Some((id, response)), false)
|
||||||
|
|
@ -256,9 +264,6 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
// find known connection with matching ssid and activate
|
// find known connection with matching ssid and activate
|
||||||
let mut status = (None, false);
|
let mut status = (None, false);
|
||||||
|
|
||||||
let devices = network_manager.devices().await.ok().unwrap_or_default();
|
|
||||||
|
|
||||||
|
|
||||||
for c in s.list_connections().await.unwrap_or_default() {
|
for c in s.list_connections().await.unwrap_or_default() {
|
||||||
let settings = match c.get_settings().await.ok() {
|
let settings = match c.get_settings().await.ok() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
|
|
@ -279,17 +284,15 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
let success = if let Ok(path) = network_manager.deref().activate_connection(c.deref().path(), &ObjectPath::try_from("/").unwrap(), &ObjectPath::try_from("/").unwrap()).await {
|
let success = if let Ok(path) = network_manager.deref().activate_connection(c.deref().path(), &ObjectPath::try_from("/").unwrap(), &ObjectPath::try_from("/").unwrap()).await {
|
||||||
let dummy = ActiveConnectionProxy::new(&conn).await.unwrap();
|
let dummy = ActiveConnectionProxy::new(&conn).await.unwrap();
|
||||||
let active = ActiveConnectionProxy::builder(&conn).path(path).unwrap().destination(dummy.destination()).unwrap().interface(dummy.interface()).unwrap().build().await.unwrap();
|
let active = ActiveConnectionProxy::builder(&conn).path(path).unwrap().destination(dummy.destination()).unwrap().interface(dummy.interface()).unwrap().build().await.unwrap();
|
||||||
let state = enums::ActiveConnectionState::from(active.state().await.unwrap_or_default());
|
let mut state = enums::ActiveConnectionState::from(active.state().await.unwrap_or_default());
|
||||||
let s = if let enums::ActiveConnectionState::Activating = state {
|
while let enums::ActiveConnectionState::Activating = state {
|
||||||
if let Ok(Some(s)) = timeout(Duration::from_secs(10), active.receive_state_changed().await.next()).await {
|
if let Ok(Some(s)) = timeout(Duration::from_secs(20), active.receive_state_changed().await.next()).await {
|
||||||
s.get().await.unwrap_or_default().into()
|
state = s.get().await.unwrap_or_default().into();
|
||||||
} else {
|
} else {
|
||||||
state
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
state
|
|
||||||
};
|
};
|
||||||
matches!(s, enums::ActiveConnectionState::Activated)
|
matches!(state, enums::ActiveConnectionState::Activated)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
@ -301,59 +304,6 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut ap = None;
|
|
||||||
|
|
||||||
for d in &devices {
|
|
||||||
if let Ok(Some(SpecificDevice::Wireless(wireless_device))) =
|
|
||||||
d.downcast_to_device().await {
|
|
||||||
for a in wireless_device.access_points().await.ok().unwrap_or_default() {
|
|
||||||
if String::from_utf8(a.ssid().await.unwrap_or_default()).unwrap_or_default() == ssid {
|
|
||||||
ap = Some(a);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if status.0.is_none() {
|
|
||||||
|
|
||||||
for device in network_manager.devices().await.ok().unwrap_or_default() {
|
|
||||||
if matches!(device.device_type().await.unwrap_or(DeviceType::Other), DeviceType::Wifi) {
|
|
||||||
let conn_settings: HashMap<&str, HashMap<&str, zvariant::Value>> = HashMap::from([
|
|
||||||
("802-11-wireless".into(), HashMap::from([
|
|
||||||
("ssid".into(), Value::Array(ssid.as_bytes().into())),
|
|
||||||
])),
|
|
||||||
("connection".into(), HashMap::from([
|
|
||||||
("id".into(), Value::Str(ssid.as_str().into())),
|
|
||||||
("type".into(), Value::Str("802-11-wireless".into())),
|
|
||||||
])),
|
|
||||||
]);
|
|
||||||
let success = if let Ok((_, path)) = network_manager.add_and_activate_connection(conn_settings, device.path(), &ap.as_ref().map(|ap| ap.path().clone()).unwrap_or_else(||ObjectPath::try_from("/").unwrap().into_owned())).await {
|
|
||||||
let dummy = ActiveConnectionProxy::new(&conn).await.unwrap();
|
|
||||||
let active = ActiveConnectionProxy::builder(&conn).path(path).unwrap().destination(dummy.destination()).unwrap().interface(dummy.interface()).unwrap().build().await.unwrap();
|
|
||||||
let state = enums::ActiveConnectionState::from(active.state().await.unwrap_or_default());
|
|
||||||
let s = if let enums::ActiveConnectionState::Activating = state {
|
|
||||||
if let Ok(Some(s)) = timeout(Duration::from_secs(10), active.receive_state_changed().await.next()).await {
|
|
||||||
s.get().await.unwrap_or_default().into()
|
|
||||||
} else {
|
|
||||||
state
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state
|
|
||||||
};
|
|
||||||
matches!(s, enums::ActiveConnectionState::Activated)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
status = (Some((id, NetworkManagerEvent::RequestResponse {
|
|
||||||
req: NetworkManagerRequest::SelectAccessPoint(ssid.clone()),
|
|
||||||
success,
|
|
||||||
state: NetworkManagerState::new(&conn).await.unwrap_or_default(),
|
|
||||||
})), false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if status.0.is_none() {
|
if status.0.is_none() {
|
||||||
status = (Some((id, NetworkManagerEvent::RequestResponse {
|
status = (Some((id, NetworkManagerEvent::RequestResponse {
|
||||||
|
|
@ -369,9 +319,7 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
_ = active_conns_changed.next().boxed().fuse() => {
|
_ = active_conns_changed.next().boxed().fuse() => {
|
||||||
let active_conns = active_connections(network_manager.active_connections().await.unwrap_or_default()).await.unwrap_or_default();
|
(Some((id, NetworkManagerEvent::ActiveConns(NetworkManagerState::new(&conn).await.unwrap_or_default()))), false)
|
||||||
|
|
||||||
(Some((id, NetworkManagerEvent::ActiveConns(active_conns))), false)
|
|
||||||
}
|
}
|
||||||
_ = devices_changed.next().boxed().fuse() => {
|
_ = devices_changed.next().boxed().fuse() => {
|
||||||
let devices = network_manager.devices().await.ok().unwrap_or_default();
|
let devices = network_manager.devices().await.ok().unwrap_or_default();
|
||||||
|
|
@ -388,11 +336,16 @@ async fn start_listening<I: Copy + Debug>(
|
||||||
for f in wireless_access_point_futures {
|
for f in wireless_access_point_futures {
|
||||||
wireless_access_points.append(&mut f.await);
|
wireless_access_points.append(&mut f.await);
|
||||||
}
|
}
|
||||||
(Some((id, NetworkManagerEvent::WirelessAccessPoints(wireless_access_points))), false)
|
(Some((id, NetworkManagerEvent::WirelessAccessPoints(NetworkManagerState::new(&conn).await.unwrap_or_default()))), false)
|
||||||
}
|
}
|
||||||
enabled = wireless_enabled_changed.next().boxed().fuse() => {
|
enabled = wireless_enabled_changed.next().boxed().fuse() => {
|
||||||
let update = if let Some(update) = enabled {
|
let update = if let Some(update) = enabled {
|
||||||
update.get().await.ok().map(|update| (id, NetworkManagerEvent::WiFiEnabled(update)))
|
if let Ok(_) = update.get().await {
|
||||||
|
Some((id, NetworkManagerEvent::WiFiEnabled(NetworkManagerState::new(&conn).await.unwrap_or_default())))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -420,6 +373,7 @@ pub enum NetworkManagerRequest {
|
||||||
SetAirplaneMode(bool),
|
SetAirplaneMode(bool),
|
||||||
SetWiFi(bool),
|
SetWiFi(bool),
|
||||||
SelectAccessPoint(String),
|
SelectAccessPoint(String),
|
||||||
|
Disconnect(String),
|
||||||
Password(String, String),
|
Password(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,9 +388,9 @@ pub enum NetworkManagerEvent {
|
||||||
sender: UnboundedSender<NetworkManagerRequest>,
|
sender: UnboundedSender<NetworkManagerRequest>,
|
||||||
state: NetworkManagerState,
|
state: NetworkManagerState,
|
||||||
},
|
},
|
||||||
WiFiEnabled(bool),
|
WiFiEnabled(NetworkManagerState),
|
||||||
WirelessAccessPoints(Vec<AccessPoint>),
|
WirelessAccessPoints(NetworkManagerState),
|
||||||
ActiveConns(Vec<ActiveConnectionInfo>),
|
ActiveConns(NetworkManagerState),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue