Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion nmrs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
All notable changes to the `nmrs` crate will be documented in this file.

## [Unreleased]
### Changed
### Changed
- Dedupe DBus proxy construction across connection logic ([#165](https://github.com/cachebag/nmrs/pull/165))
- Added contextual logging throughout VPN, connection, and device operations to preserve error context and improve debugging capabilities ([#168](https://github.com/cachebag/nmrs/pull/168))

### Fixed
- VPN operations no longer silently swallow D-Bus errors - now log warnings when proxy creation or method calls fail ([#168](https://github.com/cachebag/nmrs/pull/168))
- Connection cleanup operations (disconnect, deactivate, delete) now log failures instead of ignoring them ([#168](https://github.com/cachebag/nmrs/pull/168))
- VPN error mapping now attempts to extract actual connection state reasons instead of defaulting to `Unknown` ([#168](http://github.com/cachebag/nmrs/pull/168))
- MAC address retrieval errors are now logged with appropriate context ([#168](https://github.com/cachebag/nmrs/pull/168))
- Access point property retrieval failures are now logged for better diagnostics ([#168](https://github.com/cachebag/nmrs/pull/168))

## [1.2.0] - 2026-01-05
### Added
Expand Down
28 changes: 23 additions & 5 deletions nmrs/src/core/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,13 @@ pub(crate) async fn disconnect_wifi_and_wait(
.await?;

debug!("Sending disconnect request");
let _ = raw.call_method("Disconnect", &()).await;
match raw.call_method("Disconnect", &()).await {
Ok(_) => debug!("Disconnect method called successfully"),
Err(e) => warn!(
"Disconnect method call failed (device may already be disconnected): {}",
e
),
}

// Wait for disconnect using signal-based monitoring
wait_for_device_disconnect(&dev).await?;
Expand Down Expand Up @@ -416,7 +422,10 @@ async fn ensure_disconnected(

if let Ok(conns) = nm.active_connections().await {
for conn_path in conns {
let _ = nm.deactivate_connection(conn_path).await;
match nm.deactivate_connection(conn_path.clone()).await {
Ok(_) => debug!("Connection deactivated during cleanup"),
Err(e) => warn!("Failed to deactivate connection during cleanup: {}", e),
}
}
}

Expand Down Expand Up @@ -463,8 +472,14 @@ async fn connect_via_saved(
warn!("Saved connection activation failed: {e}");
warn!("Deleting saved connection and retrying with fresh credentials");

let _ = nm.deactivate_connection(active_conn).await;
let _ = delete_connection(conn, saved.clone()).await;
match nm.deactivate_connection(active_conn.clone()).await {
Ok(_) => debug!("Connection deactivated during cleanup"),
Err(e) => warn!("Failed to deactivate connection during cleanup: {}", e),
}
match delete_connection(conn, saved.clone()).await {
Ok(_) => debug!("Saved connection deleted"),
Err(e) => warn!("Failed to delete saved connection during recovery: {}", e),
}

let opts = ConnectionOptions {
autoconnect: true,
Expand Down Expand Up @@ -493,7 +508,10 @@ async fn connect_via_saved(
warn!("activate_connection() failed: {e}");
warn!("Saved connection may be corrupted, deleting and retrying with fresh connection");

let _ = delete_connection(conn, saved.clone()).await;
match delete_connection(conn, saved.clone()).await {
Ok(_) => debug!("Saved connection deleted"),
Err(e) => warn!("Failed to delete saved connection during recovery: {}", e),
}

let opts = ConnectionOptions {
autoconnect: true,
Expand Down
53 changes: 40 additions & 13 deletions nmrs/src/core/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! and enabling/disabling Wi-Fi. Uses D-Bus signals for efficient state
//! monitoring instead of polling.

use log::debug;
use log::{debug, warn};
use zbus::Connection;

use crate::api::models::{ConnectionError, Device, DeviceIdentity, DeviceState};
Expand All @@ -30,21 +30,48 @@ pub(crate) async fn list_devices(conn: &Connection) -> Result<Vec<Device>> {

let interface = d_proxy.interface().await?;
let raw_type = d_proxy.device_type().await?;
let current_mac = d_proxy
.hw_address()
.await
.unwrap_or_else(|_| String::from("00:00:00:00:00:00"));
// PermHwAddress may not be available on all systems/devices
// If not available, fall back to HwAddress
let perm_mac = d_proxy
.perm_hw_address()
.await
.unwrap_or_else(|_| current_mac.clone());
let current_mac = match d_proxy.hw_address().await {
Ok(addr) => addr,
Err(e) => {
warn!(
"Failed to get hardware address for device {}: {}",
interface, e
);
String::from("00:00:00:00:00:00")
}
};

let perm_mac = match d_proxy.perm_hw_address().await {
Ok(addr) => addr,
Err(e) => {
debug!(
"Permanent hardware address not available for device {}: {}",
interface, e
);
current_mac.clone()
}
};

let device_type = raw_type.into();
let raw_state = d_proxy.state().await?;
let state = raw_state.into();
let managed = d_proxy.managed().await.ok();
let driver = d_proxy.driver().await.ok();
let managed = match d_proxy.managed().await {
Ok(m) => Some(m),
Err(e) => {
debug!(
"Failed to get 'managed' property for device {}: {}",
interface, e
);
None
}
};
let driver = match d_proxy.driver().await {
Ok(d) => Some(d),
Err(e) => {
debug!("Failed to get driver for device {}: {}", interface, e);
None
}
};

devices.push(Device {
path: p.to_string(),
Expand Down
Loading
Loading