slop
This commit is contained in:
@@ -7,7 +7,6 @@ use std::{
|
||||
|
||||
use bytes::Bytes;
|
||||
use dashmap::DashMap;
|
||||
use str0m::net::DatagramRecv;
|
||||
use tokio::{
|
||||
net::UdpSocket,
|
||||
sync::mpsc::{self, Receiver},
|
||||
@@ -24,6 +23,10 @@ pub struct WebrtcProxy {
|
||||
clients_addr: Arc<DashMap<SocketAddr, tokio::sync::mpsc::Sender<(Bytes, SocketAddr)>>>,
|
||||
socket: Arc<UdpSocket>,
|
||||
public_addr: SocketAddr,
|
||||
/// Trickle-ICE candidate channels for WHIP ingest.
|
||||
/// Keyed by stream_key_id; sender stored here so PATCH handler
|
||||
/// can forward candidates to the detach task.
|
||||
pub trickle_tx: Arc<DashMap<i32, tokio::sync::mpsc::UnboundedSender<String>>>,
|
||||
}
|
||||
|
||||
const STUN_MAGIC: u32 = 0x2112A442;
|
||||
@@ -61,6 +64,7 @@ impl WebrtcProxy {
|
||||
clients_ufrag: Arc::new(DashMap::new()),
|
||||
clients_addr: Arc::new(DashMap::new()),
|
||||
public_addr,
|
||||
trickle_tx: Arc::new(DashMap::new()),
|
||||
})
|
||||
}
|
||||
pub async fn run(self) {
|
||||
@@ -79,8 +83,9 @@ impl WebrtcProxy {
|
||||
};
|
||||
let data = Bytes::copy_from_slice(&buf[..b]);
|
||||
|
||||
// By addr
|
||||
if let Some(tx) = by_addr.get(&from) {
|
||||
// By addr
|
||||
if let Some(tx) = by_addr.get(&from) {
|
||||
debug!("proxy: routing {} bytes by addr {}:{} → channel", b, from.ip(), from.port());
|
||||
match tx.try_send((data, from)) {
|
||||
Ok(_) => continue,
|
||||
Err(e) => {
|
||||
@@ -97,18 +102,24 @@ impl WebrtcProxy {
|
||||
};
|
||||
};
|
||||
|
||||
let Some(ufrag) = self::WebrtcProxy::ufrag(&data) else {
|
||||
let Some((part1, part2)) = self::WebrtcProxy::ufrag_pair(&data) else {
|
||||
debug!("huh, packet isnt stun or added as client.");
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some((_, tx)) = by_ufrag.remove(&ufrag) else {
|
||||
// warn!("STUN packet ({}), isnt registored", ufrag);
|
||||
// Try both parts of the STUN username — the first packet
|
||||
// might be a response to OUR STUN request (remote:local)
|
||||
// or an incoming request from the remote peer (local:remote).
|
||||
let part2_lookup = part2.clone();
|
||||
let entry = by_ufrag.remove(&part1).or_else(|| {
|
||||
part2_lookup.and_then(|p2| by_ufrag.remove(&p2))
|
||||
});
|
||||
let Some((_, tx)) = entry else {
|
||||
warn!("STUN packet ({}/{:?}), isnt registored", part1, part2);
|
||||
continue;
|
||||
};
|
||||
|
||||
by_addr.insert(from, tx.clone());
|
||||
debug!("got ufrag {}", ufrag);
|
||||
info!("proxy: STUN match → promoted {} → ufrag={} (match was {}/{})", from, part1, part1, part2.as_deref().unwrap_or("-"));
|
||||
debug!("sending data");
|
||||
if let Err(e) = tx.try_send((data, from)) {
|
||||
match e {
|
||||
@@ -136,29 +147,34 @@ impl WebrtcProxy {
|
||||
pub fn public_addr(&self) -> SocketAddr {
|
||||
self.public_addr
|
||||
}
|
||||
pub fn ufrag(b: &Bytes) -> Option<String> {
|
||||
if b.len() <= 20 {
|
||||
return None;
|
||||
}
|
||||
let magic = u32::from_be_bytes(b[4..8].try_into().ok()?);
|
||||
if magic != STUN_MAGIC {
|
||||
return None;
|
||||
}
|
||||
// attribies start at 20
|
||||
let mut pos = 20usize;
|
||||
while (pos + 4) <= b.len() {
|
||||
let attr_type: u16 = u16::from_be_bytes(b[pos..pos + 2].try_into().ok()?);
|
||||
let attr_len: u16 = u16::from_be_bytes(b[pos + 2..pos + 4].try_into().ok()?);
|
||||
pos = pos + 4;
|
||||
if attr_type == 0x0006 {
|
||||
let value = std::str::from_utf8(b[pos..pos + (attr_len as usize)].try_into().ok()?);
|
||||
let local = value.unwrap().split(":").next();
|
||||
return Some(local.unwrap().to_string());
|
||||
pub fn ufrag_pair(b: &Bytes) -> Option<(String, Option<String>)> {
|
||||
if b.len() <= 20 {
|
||||
return None;
|
||||
}
|
||||
pos += (attr_len as usize + 3) & !3;
|
||||
let magic = u32::from_be_bytes(b[4..8].try_into().ok()?);
|
||||
if magic != STUN_MAGIC {
|
||||
return None;
|
||||
}
|
||||
// attribies start at 20
|
||||
let mut pos = 20usize;
|
||||
while (pos + 4) <= b.len() {
|
||||
let attr_type: u16 = u16::from_be_bytes(b[pos..pos + 2].try_into().ok()?);
|
||||
let attr_len: u16 = u16::from_be_bytes(b[pos + 2..pos + 4].try_into().ok()?);
|
||||
pos += 4;
|
||||
if attr_type == 0x0006 {
|
||||
let value = std::str::from_utf8(
|
||||
b[pos..pos + (attr_len as usize)].try_into().ok()?,
|
||||
)
|
||||
.ok()?;
|
||||
let mut parts = value.split(':');
|
||||
let first = parts.next()?.to_string();
|
||||
let second = parts.next().map(|s| s.to_string());
|
||||
return Some((first, second));
|
||||
}
|
||||
pos += (attr_len as usize + 3) & !3;
|
||||
}
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
async fn resolve_domain(domain: &str) -> Result<std::net::IpAddr, Box<dyn Error>> {
|
||||
|
||||
Reference in New Issue
Block a user