1 use stun::agent::*; 2 use stun::client::*; 3 use stun::message::*; 4 use stun::xoraddr::*; 5 use stun::Error; 6 7 use clap::{App, Arg}; 8 use std::sync::Arc; 9 use tokio::net::UdpSocket; 10 11 #[tokio::main] main() -> Result<(), Error>12async fn main() -> Result<(), Error> { 13 let mut app = App::new("STUN Client") 14 .version("0.1.0") 15 .author("Rain Liu <[email protected]>") 16 .about("An example of STUN Client") 17 .arg( 18 Arg::with_name("FULLHELP") 19 .help("Prints more detailed help information") 20 .long("fullhelp"), 21 ) 22 .arg( 23 Arg::with_name("server") 24 .required_unless("FULLHELP") 25 .takes_value(true) 26 .default_value("stun.l.google.com:19302") 27 .long("server") 28 .help("STUN Server"), 29 ); 30 31 let matches = app.clone().get_matches(); 32 33 if matches.is_present("FULLHELP") { 34 app.print_long_help().unwrap(); 35 std::process::exit(0); 36 } 37 38 let server = matches.value_of("server").unwrap(); 39 40 let (handler_tx, mut handler_rx) = tokio::sync::mpsc::unbounded_channel(); 41 42 let conn = UdpSocket::bind("0:0").await?; 43 println!("Local address: {}", conn.local_addr()?); 44 45 println!("Connecting to: {server}"); 46 conn.connect(server).await?; 47 48 let mut client = ClientBuilder::new().with_conn(Arc::new(conn)).build()?; 49 50 let mut msg = Message::new(); 51 msg.build(&[Box::<TransactionId>::default(), Box::new(BINDING_REQUEST)])?; 52 53 client.send(&msg, Some(Arc::new(handler_tx))).await?; 54 55 if let Some(event) = handler_rx.recv().await { 56 let msg = event.event_body?; 57 let mut xor_addr = XorMappedAddress::default(); 58 xor_addr.get_from(&msg)?; 59 println!("Got response: {xor_addr}"); 60 } 61 62 client.close().await?; 63 64 Ok(()) 65 } 66