//! This example uses the asynchronous proxy instances.
//!
//! The client configuration must be passed as a string blob, including any certificates/keys inline (PEM format). A basic username/password authentication handler is also included.
//!
use async_std::task;
static CONFIG_STR: &str = "
client
dev tun
persist-tun
persist-key
proto udp
remote my-server 1194
resolv-retry infinite
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
-----BEGIN OpenVPN Static key V1-----
-----END OpenVPN Static key V1-----
key-direction 1
remote-cert-tls server
auth-user-pass
pull
";
fn main() {
task::block_on(async {
let connection = zbus::Connection::system().await.unwrap();
let config_manager = openvpn3_rs::ConfigurationProxy::new(&connection)
.await
.unwrap();
let config = config_manager
.import("My VPN", CONFIG_STR, true, false)
.await
.unwrap();
let sessions_manager = openvpn3_rs::SessionsProxy::new(&connection).await.unwrap();
let session = sessions_manager.new_tunnel(&config.path()).await.unwrap();
let mut ready = false;
while !ready {
// If the session is ready, the `ready()` method will return Ok(), otherwise an error will be returned with more details.
if let Err(err) = session.ready().await {
let err_str = err.to_string();
if err_str.contains("Missing user credentials") {
// This loop queries the session for which credentials are needed. This example covers username/password authentication.
let ui_type_group = session.user_input_queue_get_type_group().await.unwrap();
for (ca_type, ca_group) in ui_type_group {
let ui_queue_ids = session
.user_input_queue_check(ca_type, ca_group)
.await
.unwrap();
for id in ui_queue_ids {
let (ca_type, ca_group, id, name, _description, _hidden_input) =
session
.user_input_queue_fetch(ca_type, ca_group, id)
.await
.unwrap();
if name == "username" {
session
.user_input_provide(ca_type, ca_group, id, "smith")
.await
.unwrap();
}
if name == "password" {
session
.user_input_provide(ca_type, ca_group, id, "hunter2")
.await
.unwrap();
}
}
}
} else if err_str.contains("Backend VPN process is not ready") {
task::sleep(std::time::Duration::from_secs(1)).await;
}
} else {
ready = true;
}
}
session.connect().await.unwrap();
// wait for signal to disconnect
session.disconnect().await.unwrap();
});
}