product_os_vpn/
lib.rs

1use std::fs;
2use std::net::SocketAddr;
3use std::path::Path;
4
5use std::sync::Arc;
6use parking_lot::Mutex;
7
8use product_os_configuration::VPNProvider;
9pub use product_os_configuration::VPN as VPNConfig;
10
11use product_os_utilities::ProductOSError;
12use crate::protocols::NetworkProtocol;
13pub use crate::protocols::Status;
14
15mod protocols;
16mod providers;
17
18
19#[derive(Clone)]
20pub struct ProductOSVPN {
21    provider: Arc<Mutex<dyn providers::Provider + Send + Sync>>,
22    credentials: Credentials,
23    configs_path: String,
24    configs_source: ConfigurationSource,
25    network_protocol: NetworkProtocol
26}
27
28#[derive(Clone)]
29pub struct Credentials {
30    credentials_path: String,
31    identifier: String,
32    key: String
33}
34
35#[derive(Clone)]
36pub struct ConfigurationSource {
37    archive: Option<String>,
38    page: Option<String>
39}
40
41
42impl ProductOSVPN {
43    pub fn new(config: product_os_configuration::VPN) -> Self {
44        let relative_path_res = std::env::current_dir();
45        let relative_path_root = match relative_path_res {
46            Ok(path) => path.into_os_string().into_string().unwrap(),
47            Err(_) => panic!("Problem getting current working directory")
48        };
49
50        let mut configs_path = match config.config_path.chars().nth(0).unwrap().to_string().as_str() {
51            "/" => config.config_path.to_owned(),
52            _ => {
53                let mut path = relative_path_root.clone();
54                path.push_str("/");
55                path.push_str(config.config_path.as_str());
56                path
57            }
58        };
59
60        if !configs_path.ends_with("/") {
61            configs_path.push_str("/");
62        }
63
64        let creds_path = match config.credentials_path.chars().nth(0).unwrap().to_string().as_str() {
65            "/" => config.credentials_path.to_owned(),
66            _ => {
67                let mut path = relative_path_root.clone();
68                path.push_str("/");
69                path.push_str(config.credentials_path.as_str());
70                path
71            }
72        };
73
74        let path_configs_path = Path::new(configs_path.as_str());
75        if !path_configs_path.exists() || !path_configs_path.is_dir() {
76            match fs::create_dir_all(path_configs_path) {
77                Ok(_) => {}
78                Err(e) => panic!("Config path {:?} does not exist and could not be created: {}", path_configs_path, e.to_string())
79            }
80        };
81
82        let credentials = Credentials {
83            credentials_path: creds_path,
84            identifier: config.identifier,
85            key: config.key
86        };
87
88        let configs_source = ConfigurationSource {
89            archive: config.config_server_archive,
90            page: config.config_server_page
91        };
92
93        let network_protocol = match config.network_protocol {
94            product_os_configuration::NetworkProtocol::UDP => NetworkProtocol::TCP,
95            product_os_configuration::NetworkProtocol::TCP => NetworkProtocol::UDP,
96            product_os_configuration::NetworkProtocol::ANY => {
97                match std::time::SystemTime::now().duration_since(std::time::SystemTime::UNIX_EPOCH) {
98                    Ok(n) => {
99                        match n.as_secs().rem_euclid(2) {
100                            0 => NetworkProtocol::TCP,
101                            _ => NetworkProtocol::UDP
102                        }
103                    },
104                    Err(_) => panic!("SystemTime before UNIX EPOCH!"),
105                }
106            }
107        };
108
109        let provider = match config.provider {
110            VPNProvider::NordVPN => {
111                configs_path.push_str("nordvpn/");
112                Arc::new(Mutex::new(providers::nordvpn::NordVPN::new(configs_path.to_owned(), credentials.credentials_path.to_owned(),
113                                                                     config.bind_host, configs_source.to_owned(), network_protocol.clone())))
114            }
115        };
116
117        Self {
118            provider,
119            credentials,
120            configs_path,
121            configs_source,
122            network_protocol
123        }
124    }
125
126    pub fn connect(&mut self) -> Status {
127        let provider_unlocked = self.provider.clone();
128        let mut provider = provider_unlocked.lock();
129
130        provider.connect()
131    }
132
133    pub fn disconnect(&mut self) -> Status {
134        let provider_unlocked = self.provider.clone();
135        let mut provider = provider_unlocked.lock();
136
137        provider.disconnect()
138    }
139
140    pub fn get_status(&self) -> Status {
141        let provider_unlocked = self.provider.clone();
142        let provider = provider_unlocked.lock();
143
144        provider.get_status()
145    }
146
147    pub async fn update_configuration(&mut self, download: bool, extract: bool) -> Result<(), ProductOSError> {
148        let provider_unlocked = self.provider.clone();
149        let mut provider = provider_unlocked.lock();
150
151        provider.refresh_config(download, extract).await
152    }
153
154    pub fn get_host(&self) -> String {
155        let provider_unlocked = self.provider.clone();
156        let provider = provider_unlocked.lock();
157
158        provider.get_host()
159    }
160
161    pub fn get_port(&self) -> u16 {
162        let provider_unlocked = self.provider.clone();
163        let provider = provider_unlocked.lock();
164
165        provider.get_port()
166    }
167
168    pub fn get_address(&self) -> SocketAddr {
169        let provider_unlocked = self.provider.clone();
170        let provider = provider_unlocked.lock();
171
172        product_os_utilities::ProductOSUtilities::get_socket_address(provider.get_host().as_str(), provider.get_port(), true)
173    }
174}