wireguard_uapi/xplatform/client/
unix.rs1use crate::get;
2use crate::xplatform::error::GetDeviceError;
3use crate::xplatform::error::SetDeviceError;
4use crate::xplatform::parser::parse;
5use crate::xplatform::set;
6use std::io::BufRead;
7use std::io::Write;
8use std::os::unix::net::UnixStream;
9use std::path::Path;
10
11const GET_CMD: &str = "get=1\n\n";
12const SET_CMD: &str = "set=1\n";
13
14pub struct Client<P: AsRef<Path>> {
15 path: P,
16}
17
18impl<P: AsRef<Path>> Client<P> {
19 pub fn create(path: P) -> Self {
21 Self { path }
22 }
23
24 pub fn get(&self) -> Result<get::Device, GetDeviceError> {
25 let mut stream = UnixStream::connect(&self.path)?;
26
27 stream.write_all(GET_CMD.as_bytes())?;
28
29 let reader = std::io::BufReader::new(stream);
30 let response_lines = reader.lines();
31
32 Ok(parse(response_lines)?)
33 }
34
35 pub fn set(&self, set_request: set::Device) -> Result<(), SetDeviceError> {
36 let mut stream = UnixStream::connect(&self.path)?;
37
38 stream.write_all(SET_CMD.as_bytes())?;
39 stream.write_fmt(format_args!("{set_request}"))?;
42 stream.write_all(b"\n")?;
43
44 let reader = std::io::BufReader::new(stream);
45 let mut response_lines = reader.lines();
46
47 let errno_line = response_lines
50 .next()
51 .ok_or(SetDeviceError::EmptyResponse)??;
52
53 let (raw_key, raw_value) = {
54 let mut tokens = errno_line.trim().splitn(2, '=');
55 let raw_key = tokens.next().unwrap();
56 let raw_value = match tokens.next() {
57 Some(val) => val,
58 None => return Err(SetDeviceError::InvalidResponse(errno_line)),
59 };
60
61 (raw_key, raw_value)
62 };
63
64 match (raw_key, raw_value) {
65 ("errno", "0") => {}
66 ("errno", val) => return Err(SetDeviceError::ServerError(val.to_string())),
67 (_, _) => return Err(SetDeviceError::InvalidResponse(errno_line)),
68 }
69
70 let empty_line = response_lines
71 .next()
72 .ok_or(SetDeviceError::EmptyResponse)??;
73 if !empty_line.is_empty() {
74 return Err(SetDeviceError::InvalidEndOfResponse(empty_line));
75 }
76
77 Ok(())
78 }
79}