openvpn3_rs/helpers/
client.rs

1use super::{Configuration, Session};
2
3use crate::{
4    sessions::{LogStream, SessionManagerEventStream},
5    ConfigurationProxy, NetCfgProxy, Result, SessionsProxy,
6};
7
8use futures_util::future;
9use zbus::{fdo::PeerProxy, zvariant::OwnedObjectPath, Connection};
10
11/// OpenVPN 3 Client
12///
13/// Provides convenience methods for creating and managing OpenVPN tunnels.
14#[derive(Clone, Debug)]
15pub struct OpenVPN3<'a> {
16    connection: Connection,
17    peer_proxy: PeerProxy<'a>,
18    sessions_proxy: SessionsProxy<'a>,
19    configuration_manager_proxy: ConfigurationProxy<'a>,
20}
21impl<'a> OpenVPN3<'a> {
22    /// Create a new `OpenVPN3` instance.
23    pub async fn connect() -> Result<OpenVPN3<'a>> {
24        let connection = Connection::system().await?;
25        let sessions_proxy = SessionsProxy::new(&connection).await?;
26        let peer_proxy = PeerProxy::builder(&connection)
27            .destination("net.openvpn.v3.sessions")?
28            .path(sessions_proxy.path().to_owned())?
29            .build()
30            .await?;
31        let configuration_manager_proxy = ConfigurationProxy::new(&connection).await?;
32
33        Ok(OpenVPN3 {
34            connection,
35            peer_proxy,
36            sessions_proxy,
37            configuration_manager_proxy,
38        })
39    }
40
41    /// Fetch all available configuration profiles that are available to the user.
42    pub async fn configurations(&'a self) -> Result<Vec<Configuration<'a>>> {
43        let configs = self
44            .configuration_manager_proxy
45            .fetch_available_configs()
46            .await?;
47
48        futures_util::future::join_all(configs.into_iter().map(|object_path| {
49            Configuration::new(
50                self.connection.clone(),
51                /*&self.sessions_proxy,*/
52                /*&self.configuration_manager_proxy,*/
53                object_path,
54            )
55        }))
56        .await
57        .into_iter()
58        .collect::<Result<_>>()
59    }
60
61    /// Import a configuration profile.
62    pub async fn import<'c>(
63        &self,
64        name: &str,
65        config_str: &str,
66        single_use: bool,
67        persistent: bool,
68    ) -> Result<Configuration<'c>> {
69        self.ping().await?;
70
71        let proxy = self
72            .configuration_manager_proxy
73            .import(name, config_str, single_use, persistent)
74            .await?;
75
76        Ok(Configuration::new(
77            self.connection.clone(),
78            OwnedObjectPath::from(proxy.path().clone()),
79        )
80        .await?)
81
82        /* Ok(Configuration {
83            conn: self.connection.clone(),
84            path: OwnedObjectPath::from(proxy.path().clone()),
85            proxy,
86            sessions_proxy: self.sessions_proxy,
87            //_configuration_manager_proxy: &self.configuration_manager_proxy,
88        }) */
89    }
90
91    /// Fetch all sessions that are available to the user.
92    pub async fn sessions(&'a self) -> Result<Vec<Session<'a>>> {
93        self.ping().await?;
94
95        let sessions = self.sessions_proxy.fetch_available_sessions().await?;
96
97        futures_util::future::join_all(sessions.into_iter().map(|object_path| {
98            Session::new(
99                self.connection.clone(),
100                /*&self.sessions_proxy,*/ object_path,
101            )
102        }))
103        .await
104        .into_iter()
105        .collect::<Result<_>>()
106    }
107
108    pub async fn interfaces(&'a self) -> Result<Vec<String>> {
109        self.ping().await?;
110
111        let interfaces = self.sessions_proxy.fetch_managed_interfaces().await?;
112        Ok(interfaces)
113    }
114
115    pub async fn net_cfg_manager(&'a self) -> Result<NetCfgProxy<'static>> {
116        Ok(NetCfgProxy::new(&self.connection).await?)
117    }
118
119    pub async fn event_stream(&self) -> Result<SessionManagerEventStream<'a>> {
120        Ok(self.sessions_proxy.receive_session_manager_event().await?)
121    }
122
123    pub async fn log_stream(&self) -> Result<LogStream<'a>> {
124        Ok(self.sessions_proxy.receive_log().await?)
125    }
126
127    async fn ping(&'a self) -> Result<()> {
128        let mut attempts = 10;
129
130        while attempts > 0 {
131            let results = future::join(self.peer_proxy.ping(), self.sessions_proxy.version()).await;
132
133            if results.0.is_ok() && results.1.is_ok() {
134                return Ok(());
135            }
136
137            attempts -= 1;
138        }
139
140        Ok(())
141    }
142}