use std::sync::Arc; use clap::{App, Arg}; use stun::agent::*; use stun::client::*; use stun::message::*; use stun::xoraddr::*; use stun::Error; use tokio::net::UdpSocket; #[tokio::main] async fn main() -> Result<(), Error> { let mut app = App::new("STUN Client") .version("0.1.0") .author("Rain Liu ") .about("An example of STUN Client") .arg( Arg::with_name("FULLHELP") .help("Prints more detailed help information") .long("fullhelp"), ) .arg( Arg::with_name("server") .required_unless("FULLHELP") .takes_value(true) .default_value("stun.l.google.com:19302") .long("server") .help("STUN Server"), ); let matches = app.clone().get_matches(); if matches.is_present("FULLHELP") { app.print_long_help().unwrap(); std::process::exit(0); } let server = matches.value_of("server").unwrap(); let (handler_tx, mut handler_rx) = tokio::sync::mpsc::unbounded_channel(); let conn = UdpSocket::bind("0:0").await?; println!("Local address: {}", conn.local_addr()?); println!("Connecting to: {server}"); conn.connect(server).await?; let mut client = ClientBuilder::new().with_conn(Arc::new(conn)).build()?; let mut msg = Message::new(); msg.build(&[Box::::default(), Box::new(BINDING_REQUEST)])?; client.send(&msg, Some(Arc::new(handler_tx))).await?; if let Some(event) = handler_rx.recv().await { let msg = event.event_body?; let mut xor_addr = XorMappedAddress::default(); xor_addr.get_from(&msg)?; println!("Got response: {xor_addr}"); } client.close().await?; Ok(()) }