geph4client/
lib.rs

1use std::sync::atomic::Ordering;
2use std::{io::Write, sync::atomic::AtomicUsize};
3
4mod config;
5mod fronts;
6
7mod socks2http;
8
9use colored::Colorize;
10
11use pad::{Alignment, PadStr};
12
13use smol::channel::Sender;
14use structopt::StructOpt;
15
16use crate::{config::Opt, connect::ConnectDaemon, debugpack::DebugPack};
17mod binderproxy;
18mod china;
19mod connect;
20
21mod debugpack;
22mod main_bridgetest;
23
24mod sync;
25
26// #[global_allocator]
27// pub static ALLOCATOR: Cap<std::alloc::System> = Cap::new(std::alloc::System, usize::max_value());
28
29pub fn dispatch() -> anyhow::Result<()> {
30    std::env::remove_var("http_proxy");
31    std::env::remove_var("https_proxy");
32
33    let (send_logs, recv_logs) = smol::channel::bounded(1000);
34    config_logging(send_logs);
35    let version = env!("CARGO_PKG_VERSION");
36    log::info!("geph4-client v{} starting...", version);
37    std::env::set_var("GEPH_VERSION", version);
38
39    let opt = Opt::from_args();
40    smolscale::block_on(async move {
41        match opt {
42            Opt::Connect(opt) => {
43                let daemon = ConnectDaemon::start(opt).await?;
44                loop {
45                    let log = recv_logs.recv().await?;
46                    daemon.debug().add_logline(&log);
47                }
48            }
49            Opt::Sync(opt) => sync::main_sync(opt.clone()).await,
50            Opt::BinderProxy(opt) => binderproxy::main_binderproxy(opt.clone()).await,
51            Opt::BridgeTest(opt) => main_bridgetest::main_bridgetest(opt.clone()).await,
52            Opt::DebugPack(opt) => {
53                let pack = DebugPack::new(&opt.common.debugpack_path)?;
54                pack.backup(&opt.export_to)?;
55                Ok(())
56            }
57        }
58    })
59}
60
61static LONGEST_LINE_EVER: AtomicUsize = AtomicUsize::new(0);
62
63fn config_logging(logs: Sender<String>) {
64    if let Err(e) =
65        env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(
66            "geph4client=debug,geph4_protocol=debug,melprot=debug,warn,geph5=debug",
67        ))
68        .format_timestamp_millis()
69        .format(move |buf, record| {
70            let preamble = format!(
71                "[{} {}]:",
72                record.module_path().unwrap_or("none").dimmed(),
73                match record.level() {
74                    log::Level::Error => "ERRO".red(),
75                    log::Level::Warn => "WARN".bright_yellow(),
76                    log::Level::Info => "INFO".bright_green(),
77                    log::Level::Debug => "DEBG".bright_blue(),
78                    log::Level::Trace => "TRAC".bright_black(),
79                },
80            );
81            let len = strip_ansi_escapes::strip(&preamble).unwrap().len();
82            let longest = LONGEST_LINE_EVER.fetch_max(len, Ordering::SeqCst);
83            let preamble = ""
84                .pad_to_width_with_alignment(longest.saturating_sub(len), Alignment::Right)
85                + &preamble;
86            let line = format!("{} {}", preamble, record.args());
87            writeln!(buf, "{}", line).unwrap();
88            let _ = logs.try_send(
89                String::from_utf8_lossy(&strip_ansi_escapes::strip(line).unwrap()).to_string(),
90            );
91            Ok(())
92        })
93        .format_target(false)
94        .try_init()
95    {
96        log::debug!("{}", e);
97    }
98}