niom-turn/src/bin/smoke_client.rs

65 lines
2.2 KiB
Rust

use bytes::BytesMut;
use std::net::SocketAddr;
use tokio::net::UdpSocket;
use niom_turn::constants::*;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();
let server: SocketAddr = "127.0.0.1:3478".parse()?;
let local = UdpSocket::bind("0.0.0.0:0").await?;
// Build a minimal STUN Binding Request with USERNAME and placeholder MESSAGE-INTEGRITY
let username = "testuser";
let password = "secretpassword"; // matches server's in-memory creds
let mut buf = BytesMut::new();
buf.extend_from_slice(&METHOD_BINDING.to_be_bytes()); // Binding Request
buf.extend_from_slice(&0u16.to_be_bytes()); // length placeholder
buf.extend_from_slice(&MAGIC_COOKIE_U32.to_be_bytes());
let trans = [7u8; 12];
buf.extend_from_slice(&trans);
// USERNAME
let uname = username.as_bytes();
buf.extend_from_slice(&ATTR_USERNAME.to_be_bytes());
buf.extend_from_slice(&(uname.len() as u16).to_be_bytes());
buf.extend_from_slice(uname);
while (buf.len() % 4) != 0 { buf.extend_from_slice(&[0u8]); }
// MESSAGE-INTEGRITY placeholder
let mi_attr_offset = buf.len();
buf.extend_from_slice(&ATTR_MESSAGE_INTEGRITY.to_be_bytes());
buf.extend_from_slice(&(20u16).to_be_bytes());
let mi_val_pos = buf.len();
buf.extend_from_slice(&[0u8;20]);
while (buf.len() % 4) != 0 { buf.extend_from_slice(&[0u8]); }
// fix length
let total_len = (buf.len() - 20) as u16;
let len_bytes = total_len.to_be_bytes();
buf[2] = len_bytes[0];
buf[3] = len_bytes[1];
// compute HMAC over bytes up to MI attribute header
{
use hmac::{Hmac, Mac};
use sha1::Sha1;
type HmacSha1 = Hmac<Sha1>;
let mut mac = HmacSha1::new_from_slice(password.as_bytes()).expect("HMAC key");
mac.update(&buf[..mi_attr_offset]);
let res = mac.finalize().into_bytes();
for i in 0..20 { buf[mi_val_pos + i] = res[i]; }
}
// send
local.send_to(&buf, server).await?;
let mut r = vec![0u8; 1500];
let (len, addr) = local.recv_from(&mut r).await?;
println!("got {} bytes from {}", len, addr);
// dump hex
println!("{:02x?}", &r[..len]);
Ok(())
}