use std::process::ExitCode;
use ghast_auth::connect::{Connector, DEFAULT_MINECRAFT_PORT, ProxyPolicy, TargetAddr};
use ghast_auth::offline::OfflineProfile;
use ghast_auth::socks5::Socks5Proxy;
#[tokio::main(flavor = "current_thread")]
async fn main() -> ExitCode {
match run().await {
Ok(()) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("error: {e}");
ExitCode::FAILURE
}
}
}
async fn run() -> Result<(), Box<dyn std::error::Error>> {
let mut args = std::env::args().skip(1);
let usage = "usage: offline_socks5 <username> <host[:port]> [socks5h://user:pass@proxy:port]";
let name = args.next().ok_or(usage)?;
let server = args.next().ok_or(usage)?;
let proxy = args.next().map(|p| p.parse::<Socks5Proxy>()).transpose()?;
let profile = OfflineProfile::new(name)?;
println!(
"username {} -> offline UUID {}",
profile.name(),
profile.uuid()
);
let target = TargetAddr::parse_with_default_port(&server, DEFAULT_MINECRAFT_PORT)?;
let connector = Connector::new()
.with_optional_proxy(proxy)
.with_policy(ProxyPolicy::RequireProxyExceptLocal);
let via = match connector.plan(&target) {
Some(true) => "through the proxy",
Some(false) => "directly",
None => "nowhere (a proxy is required for this target)",
};
println!("connecting to {target} {via}");
let stream = connector.connect(&target).await?;
println!(
"connected: local {} -> peer {} (TCP_NODELAY = {})",
stream.local_addr()?,
stream.peer_addr()?,
stream.nodelay()?
);
Ok(())
}