dg_network_manager 1.0.0

Network Manager DBUS API
Documentation
use super::DeviceClient;
use crate::dbus_api::wifi_p2p_peer::WifiP2PPeerClient;
use std::collections::HashMap;
use std::io::{Error, ErrorKind};
use std::sync::Arc;
use zbus::proxy::CacheProperties;
use zbus::zvariant::{OwnedObjectPath, Value};
use zbus::{Connection, Result as ZResult, proxy};

#[proxy(
    interface = "org.freedesktop.NetworkManager.Device.WifiP2P",
    default_service = "org.freedesktop.NetworkManager"
)]
pub trait WifiP2P {
    // Methods
    fn start_find(&self, options: HashMap<&str, Value<'_>>) -> ZResult<()>;
    fn stop_find(&self) -> ZResult<()>;

    // Properties
    #[zbus(property)]
    fn hw_address(&self) -> ZResult<String>;

    #[zbus(property)]
    fn peers(&self) -> ZResult<Vec<OwnedObjectPath>>;
}

#[derive(Debug, Clone)]
pub struct WifiP2PClient {
    device: DeviceClient,
    proxy: WifiP2PProxy<'static>,
}

impl WifiP2PClient {
    pub async fn new(connection: Arc<Connection>, service_path: String) -> Result<Self, Error> {
        let device = DeviceClient::new(connection.clone(), service_path.clone()).await?;

        let proxy = WifiP2PProxy::builder(&connection)
            .path(service_path)
            .map_err(|e| Error::new(ErrorKind::InvalidInput, e.to_string()))?
            .cache_properties(CacheProperties::Yes)
            .build()
            .await
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?;

        // Verify we can access wifi_p2p-specific properties
        proxy
            .hw_address()
            .await
            .map_err(|e| Error::new(ErrorKind::NotFound, e.to_string()))?;

        Ok(Self { device, proxy })
    }

    // Forward common device methods to the base device client
    pub fn service_path(&self) -> &str {
        self.device.service_path()
    }

    pub async fn interface(&self) -> Result<String, Error> {
        self.device.interface().await
    }

    pub async fn disconnect(&self) -> Result<(), Error> {
        self.device.disconnect().await
    }

    // WifiP2P-specific methods
    pub async fn start_find(&self, options: HashMap<&str, Value<'_>>) -> Result<(), Error> {
        self.proxy
            .start_find(options)
            .await
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
    }

    pub async fn stop_find(&self) -> Result<(), Error> {
        self.proxy
            .stop_find()
            .await
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
    }

    pub async fn hw_address(&self) -> Result<String, Error> {
        self.proxy
            .hw_address()
            .await
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
    }

    pub async fn peers(&self) -> Result<Vec<OwnedObjectPath>, Error> {
        self.proxy
            .peers()
            .await
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))
    }

    // Helper method to get peers
    pub async fn get_peers(
        &self,
        connection: &Connection,
    ) -> Result<Vec<WifiP2PPeerClient>, Error> {
        let peer_paths = self.peers().await?;

        let mut peers = Vec::new();
        for path in peer_paths {
            match WifiP2PPeerClient::new(connection, path.to_string()).await {
                Ok(peer) => peers.push(peer),
                Err(_) => continue,
            }
        }

        Ok(peers)
    }
}