use virtual_net::IpAddr;
use crate::ApiOpts;
use super::AsyncCliCommand;
#[derive(clap::Parser, Debug)]
pub struct CmdConnect {
#[clap(flatten)]
api: ApiOpts,
#[clap(long)]
pub promiscuous: bool,
#[clap(long)]
pub print: bool,
#[clap(long)]
pub leave_down: bool,
#[clap(long)]
pub leave_postfix: bool,
#[clap(long)]
pub ip: Vec<IpAddr>,
#[clap(index = 1)]
pub url: url::Url,
}
impl CmdConnect {
#[cfg(all(target_os = "linux", feature = "tun-tap"))]
async fn exec(mut self) -> Result<(), anyhow::Error> {
use crate::net::TunTapSocket;
use virtual_mio::Selector;
use wasmer_deploy_schema::{AppId, NetworkIdEncodingMethod, WELL_KNOWN_VPN};
if !self.leave_postfix {
self.url.set_path(WELL_KNOWN_VPN);
}
if self.print {
println!("websocket-url: {}", self.url.as_str());
return Ok(());
}
print!("Connecting...");
let socket = TunTapSocket::create(
Selector::new(),
self.url.clone(),
self.leave_down == false,
self.ip,
)
.await
.map_err(|err| {
println!("failed");
err
})?;
println!("\rConnected to {} ", self.url.as_str());
for cidr in socket.ips().iter() {
println!("Your IP: {}/{}", cidr.ip, cidr.prefix);
}
for route in socket.routes().iter() {
println!(
"Gateway: {}/{} -> {}",
route.cidr.ip, route.cidr.prefix, route.via_router
);
}
for cidr in socket.ips().iter() {
if let Some((app_id, _)) =
AppId::from_ip(&cidr.ip, NetworkIdEncodingMethod::PrivateProjection)
{
let ip = app_id.into_ip(
cidr.ip,
0x00_1001,
NetworkIdEncodingMethod::PrivateProjection,
);
println!("Instance: {}/{}", ip, cidr.prefix);
}
}
println!("Press ctrl-c to terminate");
socket.await?;
Ok(())
}
#[cfg(not(all(target_os = "linux", feature = "tun-tap")))]
async fn exec(self) -> Result<(), anyhow::Error> {
Err(anyhow::anyhow!(
"This CLI does not support the 'connect' command: only available on Linux (feature: tun-tap)"
))
}
}
impl AsyncCliCommand for CmdConnect {
fn run_async(self) -> futures::future::BoxFuture<'static, Result<(), anyhow::Error>> {
Box::pin(self.exec())
}
}