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
2 changes: 2 additions & 0 deletions nmrs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
All notable changes to the `nmrs` crate will be documented in this file.

## [Unreleased]
### Changed
- Dedupe DBus proxy construction across connection logic ([#165](https://github.com/cachebag/nmrs/pull/165))

## [1.2.0] - 2026-01-05
### Added
Expand Down
38 changes: 19 additions & 19 deletions nmrs/src/core/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::core::state_wait::{wait_for_connection_activation, wait_for_device_di
use crate::dbus::{NMAccessPointProxy, NMDeviceProxy, NMProxy, NMWirelessProxy};
use crate::monitoring::info::current_ssid;
use crate::types::constants::{device_state, device_type, timeouts};
use crate::util::utils::decode_ssid_or_empty;
use crate::util::utils::{decode_ssid_or_empty, nm_proxy};
use crate::Result;

/// Decision on whether to reuse a saved connection or create a fresh one.
Expand Down Expand Up @@ -210,25 +210,25 @@ pub(crate) async fn forget(conn: &Connection, ssid: &str) -> Result<()> {

debug!("Starting connection deletion phase...");

let settings: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path("/org/freedesktop/NetworkManager/Settings")?
.interface("org.freedesktop.NetworkManager.Settings")?
.build()
.await?;
let settings = nm_proxy(
conn,
"/org/freedesktop/NetworkManager/Settings",
"org.freedesktop.NetworkManager.Settings",
)
.await?;

let list_reply = settings.call_method("ListConnections", &()).await?;
let conns: Vec<OwnedObjectPath> = list_reply.body().deserialize()?;

let mut deleted_count = 0;

for cpath in conns {
let cproxy: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(cpath.clone())?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await?;
let cproxy = nm_proxy(
conn,
cpath.clone(),
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await?;

if let Ok(msg) = cproxy.call_method("GetSettings", &()).await {
let body = msg.body();
Expand Down Expand Up @@ -314,12 +314,12 @@ pub(crate) async fn disconnect_wifi_and_wait(
return Ok(());
}

let raw: zbus::proxy::Proxy = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(dev_path.clone())?
.interface("org.freedesktop.NetworkManager.Device")?
.build()
.await?;
let raw = nm_proxy(
conn,
dev_path.clone(),
"org.freedesktop.NetworkManager.Device",
)
.await?;

debug!("Sending disconnect request");
let _ = raw.call_method("Disconnect", &()).await;
Expand Down
19 changes: 9 additions & 10 deletions nmrs/src/core/connection_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::collections::HashMap;
use zbus::Connection;
use zvariant::{OwnedObjectPath, Value};

use crate::util::utils::nm_proxy;
use crate::Result;

/// Finds the D-Bus path of a saved connection by SSID.
Expand All @@ -22,9 +23,8 @@ pub(crate) async fn get_saved_connection_path(
conn: &Connection,
ssid: &str,
) -> Result<Option<OwnedObjectPath>> {
let settings = zbus::proxy::Proxy::new(
let settings = nm_proxy(
conn,
"org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager/Settings",
"org.freedesktop.NetworkManager.Settings",
)
Expand All @@ -34,9 +34,8 @@ pub(crate) async fn get_saved_connection_path(
let conns: Vec<OwnedObjectPath> = reply.body().deserialize()?;

for cpath in conns {
let cproxy = zbus::proxy::Proxy::new(
let cproxy = nm_proxy(
conn,
"org.freedesktop.NetworkManager",
cpath.as_str(),
"org.freedesktop.NetworkManager.Settings.Connection",
)
Expand Down Expand Up @@ -70,12 +69,12 @@ pub(crate) async fn has_saved_connection(conn: &Connection, ssid: &str) -> Resul
/// Calls the Delete method on the connection settings object.
/// This permanently removes the saved connection from NetworkManager.
pub(crate) async fn delete_connection(conn: &Connection, conn_path: OwnedObjectPath) -> Result<()> {
let cproxy: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(conn_path.clone())?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await?;
let cproxy = nm_proxy(
conn,
conn_path.clone(),
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await?;

cproxy.call_method("Delete", &()).await?;
debug!("Deleted connection: {}", conn_path.as_str());
Expand Down
167 changes: 82 additions & 85 deletions nmrs/src/core/vpn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::api::models::{
use crate::builders::build_wireguard_connection;
use crate::core::state_wait::wait_for_connection_activation;
use crate::dbus::{NMActiveConnectionProxy, NMProxy};
use crate::util::utils::nm_proxy;
use crate::Result;

/// Connects to a WireGuard connection.
Expand Down Expand Up @@ -62,15 +63,15 @@ pub(crate) async fn connect_vpn(conn: &Connection, creds: VpnCredentials) -> Res

// Use Settings API to add connection first, then activate separately
// This avoids NetworkManager's device validation when using add_and_activate_connection
let settings_proxy: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path("/org/freedesktop/NetworkManager/Settings")?
.interface("org.freedesktop.NetworkManager.Settings")?
.build()
.await?;
let settings_api = nm_proxy(
conn,
"/org/freedesktop/NetworkManager/Settings",
"org.freedesktop.NetworkManager.Settings",
)
.await?;

debug!("Adding connection via Settings API");
let add_reply = settings_proxy
let add_reply = settings_api
.call_method("AddConnection", &(settings,))
.await?;
let conn_path: OwnedObjectPath = add_reply.body().deserialize()?;
Expand Down Expand Up @@ -148,12 +149,12 @@ pub(crate) async fn disconnect_vpn(conn: &Connection, name: &str) -> Result<()>
};

for ac_path in active_conns {
let ac_proxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(ac_path.clone())?
.interface("org.freedesktop.NetworkManager.Connection.Active")?
.build()
.await
let ac_proxy = match nm_proxy(
conn,
ac_path.clone(),
"org.freedesktop.NetworkManager.Connection.Active",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand All @@ -167,12 +168,12 @@ pub(crate) async fn disconnect_vpn(conn: &Connection, name: &str) -> Result<()>
Err(_) => continue,
};

let cproxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(conn_path.clone())?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await
let cproxy = match nm_proxy(
conn,
conn_path.clone(),
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand Down Expand Up @@ -227,12 +228,12 @@ pub(crate) async fn disconnect_vpn(conn: &Connection, name: &str) -> Result<()>
pub(crate) async fn list_vpn_connections(conn: &Connection) -> Result<Vec<VpnConnection>> {
let nm = NMProxy::new(conn).await?;

let settings: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path("/org/freedesktop/NetworkManager/Settings")?
.interface("org.freedesktop.NetworkManager.Settings")?
.build()
.await?;
let settings = nm_proxy(
conn,
"/org/freedesktop/NetworkManager/Settings",
"org.freedesktop.NetworkManager.Settings",
)
.await?;

let list_reply = settings.call_method("ListConnections", &()).await?;
let saved_conns: Vec<OwnedObjectPath> = list_reply.body().deserialize()?;
Expand All @@ -242,12 +243,12 @@ pub(crate) async fn list_vpn_connections(conn: &Connection) -> Result<Vec<VpnCon
let mut active_wg_map: HashMap<String, (DeviceState, Option<String>)> = HashMap::new();

for ac_path in active_conns {
let ac_proxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(ac_path.clone())?
.interface("org.freedesktop.NetworkManager.Connection.Active")?
.build()
.await
let ac_proxy = match nm_proxy(
conn,
ac_path.clone(),
"org.freedesktop.NetworkManager.Connection.Active",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand All @@ -261,12 +262,12 @@ pub(crate) async fn list_vpn_connections(conn: &Connection) -> Result<Vec<VpnCon
Err(_) => continue,
};

let cproxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(conn_path)?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await
let cproxy = match nm_proxy(
conn,
conn_path,
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand Down Expand Up @@ -314,12 +315,12 @@ pub(crate) async fn list_vpn_connections(conn: &Connection) -> Result<Vec<VpnCon
.await
{
if let Some(dev_path) = dev_paths.first() {
match zbus::proxy::Builder::<zbus::Proxy>::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(dev_path.clone())?
.interface("org.freedesktop.NetworkManager.Device")?
.build()
.await
match nm_proxy(
conn,
dev_path.clone(),
"org.freedesktop.NetworkManager.Device",
)
.await
{
Ok(dev_proxy) => dev_proxy.get_property::<String>("Interface").await.ok(),
Err(_) => None,
Expand All @@ -337,12 +338,12 @@ pub(crate) async fn list_vpn_connections(conn: &Connection) -> Result<Vec<VpnCon
let mut wg_conns = Vec::new();

for cpath in saved_conns {
let cproxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(cpath.clone())?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await
let cproxy = match nm_proxy(
conn,
cpath.clone(),
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand Down Expand Up @@ -403,23 +404,23 @@ pub(crate) async fn forget_vpn(conn: &Connection, name: &str) -> Result<()> {

let _ = disconnect_vpn(conn, name).await;

let settings: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path("/org/freedesktop/NetworkManager/Settings")?
.interface("org.freedesktop.NetworkManager.Settings")?
.build()
.await?;
let settings = nm_proxy(
conn,
"/org/freedesktop/NetworkManager/Settings",
"org.freedesktop.NetworkManager.Settings",
)
.await?;

let list_reply = settings.call_method("ListConnections", &()).await?;
let conns: Vec<OwnedObjectPath> = list_reply.body().deserialize()?;

for cpath in conns {
let cproxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(cpath.clone())?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await
let cproxy = match nm_proxy(
conn,
cpath.clone(),
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand Down Expand Up @@ -469,12 +470,12 @@ pub(crate) async fn get_vpn_info(conn: &Connection, name: &str) -> Result<VpnCon
let active_conns = nm.active_connections().await?;

for ac_path in active_conns {
let ac_proxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(ac_path.clone())?
.interface("org.freedesktop.NetworkManager.Connection.Active")?
.build()
.await
let ac_proxy = match nm_proxy(
conn,
ac_path.clone(),
"org.freedesktop.NetworkManager.Connection.Active",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand All @@ -488,12 +489,12 @@ pub(crate) async fn get_vpn_info(conn: &Connection, name: &str) -> Result<VpnCon
Err(_) => continue,
};

let cproxy: zbus::Proxy<'_> = match zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(conn_path)?
.interface("org.freedesktop.NetworkManager.Settings.Connection")?
.build()
.await
let cproxy = match nm_proxy(
conn,
conn_path,
"org.freedesktop.NetworkManager.Settings.Connection",
)
.await
{
Ok(p) => p,
Err(_) => continue,
Expand Down Expand Up @@ -540,12 +541,12 @@ pub(crate) async fn get_vpn_info(conn: &Connection, name: &str) -> Result<VpnCon
// Device/interface
let dev_paths: Vec<OwnedObjectPath> = ac_proxy.get_property("Devices").await?;
let interface = if let Some(dev_path) = dev_paths.first() {
let dev_proxy: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(dev_path.clone())?
.interface("org.freedesktop.NetworkManager.Device")?
.build()
.await?;
let dev_proxy = nm_proxy(
conn,
dev_path.clone(),
"org.freedesktop.NetworkManager.Device",
)
.await?;
Some(dev_proxy.get_property::<String>("Interface").await?)
} else {
None
Expand Down Expand Up @@ -574,12 +575,8 @@ pub(crate) async fn get_vpn_info(conn: &Connection, name: &str) -> Result<VpnCon
// IPv4 config
let ip4_path: OwnedObjectPath = ac_proxy.get_property("Ip4Config").await?;
let (ip4_address, dns_servers) = if ip4_path.as_str() != "/" {
let ip4_proxy: zbus::Proxy<'_> = zbus::proxy::Builder::new(conn)
.destination("org.freedesktop.NetworkManager")?
.path(ip4_path)?
.interface("org.freedesktop.NetworkManager.IP4Config")?
.build()
.await?;
let ip4_proxy =
nm_proxy(conn, ip4_path, "org.freedesktop.NetworkManager.IP4Config").await?;

let ip4_address = if let Ok(addr_array) = ip4_proxy
.get_property::<Vec<HashMap<String, zvariant::Value>>>("AddressData")
Expand Down
Loading
Loading