use anyhow::{Context, Result};
use clap::Parser;
use portredirect::app_data::ClientAppData;
use portredirect::client::run_client::run_client;
use portredirect::get_config_dir;
use secrecy::SecretString;
use std::net::ToSocketAddrs;
use tracing::{info, span, Level};
#[derive(Parser)]
struct Args {
#[clap(long)]
destination_host: String,
#[clap(long)]
destination_port: u16,
#[clap(long)]
quic_remote_host: String,
#[clap(long)]
quic_remote_port: u16,
#[clap(long, default_value = "0.0.0.0")]
quic_local_host: String,
#[clap(long, default_value = "0")]
quic_local_port: u16,
#[clap(long)]
provide_metrics: bool,
#[clap(long)]
quic_remote_hostname_match: Option<String>,
#[clap(long)]
quic_psk: SecretString,
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_max_level(Level::DEBUG)
.with_target(true)
.with_line_number(true)
.init();
let _enter = span!(Level::INFO, "prclient_main").entered();
let args = Args::parse();
let config_dir = get_config_dir(None)?; info!("Configuration directory: {:?}", config_dir);
let destination_addr = format!("{}:{}", args.destination_host, args.destination_port);
let quic_local_addr = format!("{}:{}", args.quic_local_host, args.quic_local_port)
.to_socket_addrs()
.context("constructing QUIC local address")?
.next()
.expect("Unable to resolve local address");
let quic_remote_addr = format!("{}:{}", args.quic_remote_host, args.quic_remote_port)
.to_socket_addrs()
.context("constructing QUIC remote address")?
.next()
.expect("Unable to resolve remote address");
info!(
destination = %destination_addr,
local = %quic_local_addr,
remote = %quic_remote_addr,
"Initializing QUIC Client"
);
let forward_destination = destination_addr
.to_socket_addrs()
.context("resolving destination address")?
.next()
.context("resolving destination address")?;
let app_config = ClientAppData::new(args.quic_psk, forward_destination);
rustls::crypto::ring::default_provider()
.install_default()
.expect("Failed to install rustls crypto provider");
run_client(
app_config,
quic_local_addr,
quic_remote_addr,
args.provide_metrics,
)
.await?;
Ok(())
}