tuic-client 1.0.0-alpha0

Minimalistic TUIC client implementation as a reference
use self::{
    config::{Config, ConfigError},
    connection::Endpoint,
    socks5::Server as Socks5Server,
};
use env_logger::Builder as LoggerBuilder;
use quinn::{ConnectError, ConnectionError};
use rustls::Error as RustlsError;
use std::{env, io::Error as IoError, process};
use thiserror::Error;
use tuic_quinn::Error as ModelError;

mod config;
mod connection;
mod socks5;
mod utils;

#[tokio::main]
async fn main() {
    let cfg = match Config::parse(env::args_os()) {
        Ok(cfg) => cfg,
        Err(ConfigError::Version(msg) | ConfigError::Help(msg)) => {
            println!("{msg}");
            process::exit(0);
        }
        Err(err) => {
            eprintln!("{err}");
            process::exit(1);
        }
    };

    LoggerBuilder::new()
        .filter_level(cfg.log_level)
        .format_module_path(false)
        .format_target(false)
        .init();

    match Endpoint::set_config(cfg.relay) {
        Ok(()) => {}
        Err(err) => {
            eprintln!("{err}");
            process::exit(1);
        }
    }

    match Socks5Server::set_config(cfg.local).await {
        Ok(()) => {}
        Err(err) => {
            eprintln!("{err}");
            process::exit(1);
        }
    }

    Socks5Server::start().await;
}

#[derive(Debug, Error)]
pub enum Error {
    #[error(transparent)]
    Io(#[from] IoError),
    #[error(transparent)]
    Connect(#[from] ConnectError),
    #[error(transparent)]
    Connection(#[from] ConnectionError),
    #[error(transparent)]
    Model(#[from] ModelError),
    #[error("load native certificates error: {0}")]
    LoadNativeCerts(IoError),
    #[error(transparent)]
    Rustls(#[from] RustlsError),
    #[error("{0}: {1}")]
    Socket(&'static str, IoError),
    #[error("timeout establishing connection")]
    Timeout,
    #[error("cannot resolve the server name")]
    DnsResolve,
    #[error("received packet from an unexpected source")]
    WrongPacketSource,
    #[error("invalid socks5 authentication")]
    InvalidSocks5Auth,
}