openvpn3_rs/helpers/
session.rs1use crate::{
4 proxy::sessions_node::{AttentionRequiredStream, LogStream, StatusChangeStream},
5 sessions_node::{
6 constants::{ClientAttentionGroup, ClientAttentionType},
7 result::{Statistics, Status, UserInputQueueTypeGroup},
8 },
9 Error, Result, SessionsNodeProxy,
10};
11
12use zbus::{
13 zvariant::{ObjectPath, OwnedObjectPath, OwnedValue},
14 CacheProperties, Connection,
15};
16
17#[derive(Clone, Debug)]
19pub struct Session<'a> {
20 pub(crate) proxy: SessionsNodeProxy<'a>,
21}
22
23impl<'a> Session<'a> {
24 const DBUS_INTERFACE: &'static str = "net.openvpn.v3.sessions";
25
26 pub(crate) async fn new(
28 conn: Connection,
29 session_path: OwnedObjectPath,
30 ) -> Result<Session<'a>> {
31 let proxy = SessionsNodeProxy::builder(&conn)
32 .destination(Self::DBUS_INTERFACE)?
33 .path(session_path.clone())?
34 .cache_properties(CacheProperties::No)
35 .build()
36 .await?;
37
38 Ok(Self { proxy })
39 }
40
41 pub fn path(&'a self) -> &ObjectPath {
43 self.proxy.path()
44 }
45
46 pub async fn ready(&'a self) -> Result<()> {
47 Ok(self.proxy.ready().await.map_err(|err| {
48 let err_str = err.to_string();
49
50 if err_str.contains("net.openvpn.v3.sessions.error: Backend VPN process is not ready") {
51 Error::BackendNotReady
52 } else if err_str.contains("net.openvpn.v3.error.ready: Missing user credentials") {
53 Error::MissingUserCredentials
54 } else {
55 Error::Zbus(err)
56 }
57 })?)
58 }
59
60 pub async fn connect(&'a self) -> Result<()> {
62 Ok(self.proxy.connect().await?)
63 }
64
65 pub async fn pause(&'a self, reason: &str) -> Result<()> {
67 Ok(self.proxy.pause(reason).await?)
68 }
69
70 pub async fn resume(&'a self) -> Result<()> {
72 Ok(self.proxy.resume().await?)
73 }
74
75 pub async fn restart(&'a self) -> Result<()> {
77 Ok(self.proxy.restart().await?)
78 }
79
80 pub async fn disconnect(&'a self) -> Result<()> {
82 Ok(self.proxy.disconnect().await?)
83 }
84
85 pub async fn status(&'a self) -> Result<Status> {
87 Ok(self.proxy.status().await?)
88 }
89
90 pub async fn statistics(&'a self) -> Result<Statistics> {
92 Ok(self.proxy.statistics().await?)
93 }
94
95 pub async fn get_property<T>(&'a self, property_name: &str) -> Result<T>
97 where
98 T: TryFrom<OwnedValue>,
99 T::Error: Into<zbus::Error>,
100 {
101 Ok(self.proxy.get_property(property_name).await?)
102 }
103
104 pub async fn user_input_queue_get_type_group(&'a self) -> Result<Vec<UserInputQueueTypeGroup>> {
105 Ok(self.proxy.user_input_queue_get_type_group().await?)
106 }
107
108 pub async fn user_input_queue_check(
109 &'a self,
110 qtype: ClientAttentionType,
111 qgroup: ClientAttentionGroup,
112 ) -> Result<Vec<u32>> {
113 Ok(self.proxy.user_input_queue_check(qtype, qgroup).await?)
114 }
115
116 pub async fn user_input_queue_fetch(
128 &'a self,
129 qtype: ClientAttentionType,
130 qgroup: ClientAttentionGroup,
131 qid: u32,
132 ) -> Result<UserInputSlot<'a>> {
133 Ok(UserInputSlot::new(&self.proxy, qtype, qgroup, qid).await?)
134 }
135
136 pub async fn fetch_user_input_slots(&'a self) -> Result<Vec<UserInputSlot>> {
142 let mut slots = Vec::new();
143
144 for (qtype, qgroup) in self.user_input_queue_get_type_group().await? {
145 for qid in self.user_input_queue_check(qtype, qgroup).await? {
146 slots.push(UserInputSlot::new(&self.proxy, qtype, qgroup, qid).await?)
147 }
148 }
149
150 Ok(slots)
151 }
152
153 pub async fn attention_required_stream(&self) -> Result<AttentionRequiredStream<'a>> {
155 Ok(self.proxy.receive_attention_required().await?)
156 }
157
158 pub async fn status_change_stream(&self) -> Result<StatusChangeStream<'a>> {
160 Ok(self.proxy.receive_status_change().await?)
161 }
162
163 pub async fn log_stream(&self) -> Result<LogStream<'a>> {
167 self.proxy.log_forward(true).await?;
168 Ok(self.proxy.receive_log().await?)
169 }
170}
171
172pub struct UserInputSlot<'a> {
176 proxy: &'a SessionsNodeProxy<'a>,
177 qtype: ClientAttentionType,
178 qgroup: ClientAttentionGroup,
179 qid: u32,
180 variable_name: String,
181 label: String,
182 mask: bool,
183}
184
185impl<'a> UserInputSlot<'a> {
186 pub async fn new(
195 proxy: &'a SessionsNodeProxy<'_>,
196 qtype: ClientAttentionType,
197 qgroup: ClientAttentionGroup,
198 qid: u32,
199 ) -> Result<UserInputSlot<'a>> {
200 let qslot = proxy.user_input_queue_fetch(qtype, qgroup, qid).await?;
201
202 if qtype != qslot.0 || qgroup != qslot.1 || qid != qslot.2 {
204 return Err(Error::UserInputSlotMismatch);
205 }
206
207 Ok(Self {
208 proxy,
209 qtype,
210 qgroup,
211 qid,
212 variable_name: qslot.3,
213 label: qslot.4,
214 mask: qslot.5,
215 })
216 }
217
218 pub async fn provide_input(&'a self, value: &str) -> Result<()> {
224 Ok(self
225 .proxy
226 .user_input_provide(self.qtype, self.qgroup, self.qid, value)
227 .await?)
228 }
229
230 pub fn type_group(&'a self) -> UserInputQueueTypeGroup {
232 (self.qtype, self.qgroup)
233 }
234
235 pub fn variable_name(&'a self) -> &str {
237 &self.variable_name
238 }
239
240 pub fn label(&'a self) -> &str {
242 &self.label
243 }
244
245 pub fn input_mask(&'a self) -> bool {
247 self.mask
248 }
249}