1pub mod conn;
2pub mod shared_tcp;
3pub mod shared_udp;
4pub mod stun;
5#[cfg(test)]
6mod tests;
7pub mod turn;
8pub mod upnp;
9
10pub use upnp::{
12 DEFAULT_LEASE_DURATION, DEFAULT_UPNP_DISCOVERY_TIMEOUT, MAX_LEASE_DURATION, MIN_LEASE_DURATION,
13 UpnpPortMapper,
14};
15
16use crate::config::{BufferDropStrategy, IceServer, IceTransportPolicy, RtcConfiguration};
17use crate::transports::ice::turn::{TurnClient, TurnCredentials};
18use crate::transports::{PacketReceiver, get_local_ip};
19use bytes::Bytes;
20use futures::future::BoxFuture;
21use futures::stream::{FuturesUnordered, StreamExt};
22use std::collections::{HashMap, VecDeque};
23use std::io::ErrorKind;
24use std::net::{IpAddr, SocketAddr};
25use std::sync::Arc;
26use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
27
28use std::time::{Duration, Instant};
29
30use anyhow::{Context, Result, anyhow, bail};
31use tokio::net::{TcpListener, TcpStream, UdpSocket, lookup_host};
32use tokio::sync::{Mutex, broadcast, mpsc, oneshot, watch};
33use tokio::time::timeout;
34use tracing::{debug, instrument, trace, warn};
35
36#[cfg(any(test, feature = "simulator"))]
37use self::stun::random_u32;
38use self::stun::{
39 StunAttribute, StunClass, StunDecoded, StunMessage, StunMethod, random_bytes, random_u64,
40};
41
42pub(crate) const MAX_STUN_MESSAGE: usize = 1500;
43#[cfg(any(test, feature = "simulator"))]
44static PACKET_LOSS_RATE: AtomicU32 = AtomicU32::new(u32::MAX);
45
46pub(crate) fn should_drop_packet() -> bool {
47 #[cfg(not(any(test, feature = "simulator")))]
48 return false;
49
50 #[cfg(any(test, feature = "simulator"))]
51 {
52 let mut rate = PACKET_LOSS_RATE.load(Ordering::Relaxed);
53 if rate == u32::MAX {
54 rate = std::env::var("RUSTRTC_PACKET_LOSS")
55 .ok()
56 .and_then(|s| s.parse::<f64>().ok())
57 .map(|f| (f * 100.0) as u32)
58 .unwrap_or(0);
59 PACKET_LOSS_RATE.store(rate, Ordering::Relaxed);
60 }
61
62 if rate == 0 {
63 return false;
64 }
65
66 let rand_val = random_u32() % 10000;
67 let drop = rand_val < rate;
68 if drop {
69 trace!("SIMULATOR: Dropping packet (rate={}%)", rate as f64 / 100.0);
70 }
71 drop
72 }
73}
74
75#[cfg(any(test, feature = "simulator"))]
83async fn simulate_stun_respond_delay(sender: &IceSocketWrapper) {
84 let spec = match std::env::var("RUSTRTC_STUN_RESPOND_DELAY_MS").ok() {
85 Some(s) => s,
86 None => return,
87 };
88 let Ok(ms) = spec.trim().parse::<u64>() else {
89 return;
90 };
91 if ms == 0 {
92 return;
93 }
94 if matches!(
95 sender,
96 IceSocketWrapper::Turn(_, _)
97 | IceSocketWrapper::TcpListener(_)
98 | IceSocketWrapper::TcpStream(_, _, _)
99 ) {
100 return;
101 }
102 trace!("SIMULATOR: delaying STUN response by {}ms", ms);
103 tokio::time::sleep(Duration::from_millis(ms)).await;
104}
105
106#[derive(Debug)]
108struct BufferStats {
109 pub packets_received: AtomicU64,
110 pub packets_dropped: AtomicU64,
111 pub current_size: AtomicU32,
112 pub peak_size: AtomicU32,
113 pub last_log_time: parking_lot::Mutex<Instant>,
114}
115
116impl Default for BufferStats {
117 fn default() -> Self {
118 Self {
119 packets_received: AtomicU64::new(0),
120 packets_dropped: AtomicU64::new(0),
121 current_size: AtomicU32::new(0),
122 peak_size: AtomicU32::new(0),
123 last_log_time: parking_lot::Mutex::new(Instant::now()),
124 }
125 }
126}
127
128#[derive(Debug)]
129enum IceCommand {
130 StartGathering,
131 RunChecks,
132}
133
134#[derive(Debug, Clone)]
135pub struct IceTransport {
136 inner: Arc<IceTransportInner>,
137}
138
139pub(crate) struct IceTransportInner {
140 state: watch::Sender<IceTransportState>,
141 _state_rx_keeper: watch::Receiver<IceTransportState>,
142 gathering_state: watch::Sender<IceGathererState>,
143 _gathering_state_rx_keeper: watch::Receiver<IceGathererState>,
150 role: parking_lot::Mutex<IceRole>,
151 selected_pair: parking_lot::Mutex<Option<IceCandidatePair>>,
152 local_candidates: Mutex<Vec<IceCandidate>>,
153 remote_candidates: parking_lot::Mutex<Vec<IceCandidate>>,
154 gather_state: parking_lot::Mutex<IceGathererState>,
155 config: RtcConfiguration,
156 gatherer: IceGatherer,
157 local_parameters: parking_lot::Mutex<IceParameters>,
158 remote_parameters: parking_lot::Mutex<Option<IceParameters>>,
159 pending_transactions: parking_lot::Mutex<HashMap<[u8; 12], oneshot::Sender<StunDecoded>>>,
160 data_receiver: parking_lot::Mutex<Option<Arc<dyn PacketReceiver>>>,
161 buffered_packets: parking_lot::Mutex<VecDeque<(Vec<u8>, SocketAddr)>>,
164 buffer_stats: Arc<BufferStats>,
166 selected_socket: watch::Sender<Option<IceSocketWrapper>>,
167 _socket_rx_keeper: watch::Receiver<Option<IceSocketWrapper>>,
168 selected_rtcp_socket: watch::Sender<Option<IceSocketWrapper>>,
169 _rtcp_socket_rx_keeper: watch::Receiver<Option<IceSocketWrapper>>,
170 selected_pair_notifier: watch::Sender<Option<IceCandidatePair>>,
171 _selected_pair_rx_keeper: watch::Receiver<Option<IceCandidatePair>>,
172 created_at: Instant,
174 last_received_nanos: AtomicU64,
178 candidate_tx: broadcast::Sender<IceCandidate>,
179 cmd_tx: mpsc::UnboundedSender<IceCommand>,
180 checking_pairs: Mutex<std::collections::HashSet<(SocketAddr, SocketAddr)>>,
181 nomination_complete: watch::Sender<Option<bool>>,
185 _nomination_complete_rx: watch::Receiver<Option<bool>>,
186 turn_refresh_in_progress: std::sync::atomic::AtomicBool,
190 upnp_refresh_in_progress: std::sync::atomic::AtomicBool,
193}
194
195impl std::fmt::Debug for IceTransportInner {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 f.debug_struct("IceTransportInner")
198 .field("state", &self.state)
199 .field("role", &self.role)
200 .field("selected_pair", &self.selected_pair)
201 .field("local_candidates", &self.local_candidates)
202 .field("remote_candidates", &self.remote_candidates)
203 .field("gather_state", &self.gather_state)
204 .field("config", &self.config)
205 .field("gatherer", &self.gatherer)
206 .field("local_parameters", &self.local_parameters)
207 .field("remote_parameters", &self.remote_parameters)
208 .field("pending_transactions", &self.pending_transactions)
209 .field("data_receiver", &"PacketReceiver")
210 .field("buffered_packets", &self.buffered_packets.lock().len())
211 .field("buffer_stats", &self.buffer_stats)
212 .field("selected_socket", &self.selected_socket)
213 .field("selected_rtcp_socket", &self.selected_rtcp_socket)
214 .field("selected_pair_notifier", &self.selected_pair_notifier)
215 .field("candidate_tx", &self.candidate_tx)
216 .field("cmd_tx", &self.cmd_tx)
217 .field("nomination_complete", &self.nomination_complete)
218 .finish()
219 }
220}
221
222struct IceTransportRunner {
223 inner: Arc<IceTransportInner>,
224 socket_rx: mpsc::UnboundedReceiver<IceSocketWrapper>,
225 candidate_rx: broadcast::Receiver<IceCandidate>,
226 cmd_rx: mpsc::UnboundedReceiver<IceCommand>,
227 state_rx: watch::Receiver<IceTransportState>,
228}
229
230impl IceTransportRunner {
231 async fn run(mut self) {
232 let mut interval = tokio::time::interval_at(
233 tokio::time::Instant::now() + Duration::from_secs(1),
234 Duration::from_secs(1),
235 );
236 let mut turn_refresh_interval = tokio::time::interval_at(
244 tokio::time::Instant::now() + Duration::from_secs(25),
245 Duration::from_secs(25),
246 );
247 let mut upnp_refresh_interval = tokio::time::interval_at(
251 tokio::time::Instant::now() + self.inner.config.upnp_refresh_interval,
252 self.inner.config.upnp_refresh_interval,
253 );
254 let mut read_futures: FuturesUnordered<BoxFuture<'static, ()>> = FuturesUnordered::new();
255 let mut gathering_future: BoxFuture<'static, ()> = Box::pin(futures::future::pending());
256 let mut turn_refresh_future: BoxFuture<'static, ()> = Box::pin(futures::future::pending());
257 let mut upnp_refresh_future: BoxFuture<'static, ()> = Box::pin(futures::future::pending());
258
259 loop {
260 tokio::select! {
261 res = self.state_rx.changed() => {
262 if res.is_err() {
263 break;
264 }
265 if matches!(*self.state_rx.borrow(), IceTransportState::Closed | IceTransportState::Failed) {
266 break;
267 }
268 }
269 Some(socket) = self.socket_rx.recv() => {
270 match socket {
271 IceSocketWrapper::Udp(s) => {
272 read_futures.push(Box::pin(Self::run_udp_read_loop(s, self.inner.clone())));
273 }
274 IceSocketWrapper::SharedUdp(handle) => {
275 read_futures.push(Box::pin(Self::run_shared_udp_read_loop(handle, self.inner.clone())));
276 }
277 IceSocketWrapper::TcpListener(l) => {
278 read_futures.push(Box::pin(Self::run_tcp_listen_loop(l, self.inner.clone())));
279 }
280 IceSocketWrapper::TcpStream(read, write, peer) => {
281 read_futures.push(Box::pin(Self::run_tcp_read_loop(
282 read,
283 write,
284 peer,
285 self.inner.clone(),
286 )));
287 }
288 IceSocketWrapper::Turn(c, addr) => {
289 read_futures.push(Box::pin(Self::run_turn_read_loop(c, addr, self.inner.clone())));
290 }
291 }
292 }
293 res = self.candidate_rx.recv() => {
294 match res {
295 Ok(_) => {
296 let inner = self.inner.clone();
297 read_futures.push(Box::pin(async move {
298 perform_connectivity_checks_async(inner).await;
299 }));
300 }
301 Err(broadcast::error::RecvError::Closed) => break,
302 Err(broadcast::error::RecvError::Lagged(_)) => continue,
303 }
304 }
305 Some(cmd) = self.cmd_rx.recv() => {
306 trace!("Runner received command: {:?}", cmd);
307 match cmd {
308 IceCommand::StartGathering => {
309 let inner = self.inner.clone();
310 gathering_future = Box::pin(async move {
311 if let Err(e) = inner.gatherer.gather().await {
312 debug!("Gathering failed: {}", e);
313 }
314 {
315 let mut buffer = inner.local_candidates.lock().await;
316 *buffer = inner.gatherer.local_candidates();
317 }
318 *inner.gather_state.lock() = IceGathererState::Complete;
319 let _ = inner.gathering_state.send(IceGathererState::Complete);
320 });
321 }
322 IceCommand::RunChecks => {
323 let inner = self.inner.clone();
324 let rt_handle = inner.config.runtime_handle.clone();
330 crate::spawn_rtc(
331 rt_handle.as_ref(),
332 tracing::Span::current(),
333 async move {
334 perform_connectivity_checks_async(inner).await;
335 },
336 );
337 }
338 }
339 }
340 _ = interval.tick() => {
341 if let Some(f) = Self::run_keepalive_tick(&self.inner).await {
342 read_futures.push(f);
343 }
344 }
345 _ = turn_refresh_interval.tick() => {
346 if !self
353 .inner
354 .turn_refresh_in_progress
355 .load(std::sync::atomic::Ordering::SeqCst)
356 {
357 let inner = self.inner.clone();
358 turn_refresh_future = Box::pin(async move {
359 Self::run_turn_refresh(&inner).await;
360 });
361 }
362 }
363 _ = &mut turn_refresh_future => {
364 turn_refresh_future = Box::pin(futures::future::pending());
365 }
366 _ = upnp_refresh_interval.tick() => {
367 if !self
372 .inner
373 .upnp_refresh_in_progress
374 .swap(true, std::sync::atomic::Ordering::SeqCst)
375 {
376 let inner = self.inner.clone();
377 upnp_refresh_future = Box::pin(async move {
378 inner.gatherer.renew_upnp_mappings().await;
379 inner
380 .upnp_refresh_in_progress
381 .store(false, std::sync::atomic::Ordering::SeqCst);
382 });
383 }
384 }
385 _ = &mut upnp_refresh_future => {
386 upnp_refresh_future = Box::pin(futures::future::pending());
387 }
388 Some(_) = read_futures.next() => {
389 }
391 _ = &mut gathering_future => {
392 gathering_future = Box::pin(futures::future::pending());
393 }
394 }
395 }
396 }
397
398 async fn run_udp_read_loop(socket: Arc<UdpSocket>, inner: Arc<IceTransportInner>) {
399 let mut buf = [0u8; 1500];
400 let mut marshal_buf = Vec::with_capacity(1500);
401 let mut state_rx = inner.state.subscribe();
402 let sender = IceSocketWrapper::Udp(socket.clone());
403 trace!("Read loop started for {:?}", socket.local_addr());
404 loop {
405 tokio::select! {
406 res = socket.readable() => {
407 if let Err(e) = res {
408 debug!("Socket readable wait error: {}", e);
409 break;
410 }
411
412 loop {
413 let (len, addr) = match socket.try_recv_from(&mut buf) {
414 Ok(v) => v,
415 Err(e) if e.kind() == ErrorKind::WouldBlock => {
416 break;
417 }
418 Err(e) => {
419 debug!("Socket recv error: {}", e);
420 return;
421 }
422 };
423
424 let packet = &buf[..len];
425 if len > 0 {
426 handle_packet(
427 packet,
428 addr,
429 inner.clone(),
430 sender.clone(),
431 &mut marshal_buf,
432 )
433 .await;
434 }
435 }
436 }
437 res = state_rx.changed() => {
438 if res.is_err() || matches!(*state_rx.borrow(), IceTransportState::Closed | IceTransportState::Failed) {
439 trace!("Read loop stopping (IceTransport Closed or Failed)");
441 break;
442 }
443 }
444 }
445 }
446 }
447
448 async fn run_shared_udp_read_loop(
452 handle: Arc<shared_udp::SharedUdpHandle>,
453 inner: Arc<IceTransportInner>,
454 ) {
455 let mut state_rx = inner.state.subscribe();
456 let mut marshal_buf = Vec::with_capacity(1500);
457 let sender = IceSocketWrapper::SharedUdp(handle.clone());
458 trace!("Shared UDP read loop started");
459 loop {
460 let packet_opt = tokio::select! {
461 biased;
462 res = state_rx.changed() => {
463 if res.is_err()
464 || matches!(
465 *state_rx.borrow(),
466 IceTransportState::Closed | IceTransportState::Failed
467 )
468 {
469 debug!("Shared UDP read loop stopping (IceTransport Closed or Failed)");
470 break;
471 }
472 continue;
473 }
474 pkt = handle.recv() => pkt,
475 };
476 match packet_opt {
477 Some((packet, addr)) => {
478 handle_packet(
479 &packet,
480 addr,
481 inner.clone(),
482 sender.clone(),
483 &mut marshal_buf,
484 )
485 .await;
486 }
487 None => break,
488 }
489 }
490 }
491
492 async fn run_turn_read_loop(
493 client: Arc<TurnClient>,
494 relayed_addr: SocketAddr,
495 inner: Arc<IceTransportInner>,
496 ) {
497 let mut buf = [0u8; 1500];
498 let mut marshal_buf = Vec::with_capacity(1500);
499 let mut state_rx = inner.state.subscribe();
500 trace!("Read loop started for TURN client {}", relayed_addr);
501 loop {
502 let recv_future = async { client.recv(&mut buf).await };
503
504 tokio::select! {
505 result = recv_future => {
506 match result {
507 Ok(len) => {
508 if len > 0 {
509 IceTransport::handle_turn_packet(&buf[..len], &inner, &client, relayed_addr, &mut marshal_buf).await;
510 }
511 }
512 Err(e) => {
513 if e.to_string().contains("deadline has elapsed") {
514 continue;
515 }
516 debug!("TURN client recv error: {}", e);
517 break;
518 }
519 }
520 }
521 res = state_rx.changed() => {
522 if res.is_err() || matches!(*state_rx.borrow(), IceTransportState::Closed | IceTransportState::Failed) {
523 trace!("TURN Read loop stopping (IceTransport Closed or Failed)");
524 break;
525 }
526 }
527 }
528 }
529 }
530
531 async fn run_tcp_listen_loop(listener: Arc<TcpListener>, inner: Arc<IceTransportInner>) {
532 let mut state_rx = inner.state.subscribe();
533 let local_addr = match listener.local_addr() {
534 Ok(a) => a,
535 Err(e) => {
536 debug!("TCP listener local_addr error: {}", e);
537 return;
538 }
539 };
540 trace!("TCP listen loop started for {:?}", local_addr);
541 loop {
542 tokio::select! {
543 accept_res = listener.accept() => {
544 match accept_res {
545 Ok((stream, peer_addr)) => {
546 trace!("TCP accepted connection from {}", peer_addr);
547 let wrapper = split_tcp_stream(stream, peer_addr);
548 inner.gatherer.store_tcp_stream(local_addr, wrapper.clone());
549 let _ = inner.gatherer.socket_tx.send(wrapper);
550 }
551 Err(e) => {
552 debug!("TCP accept error: {}", e);
553 break;
554 }
555 }
556 }
557 res = state_rx.changed() => {
558 if res.is_err() || matches!(*state_rx.borrow(), IceTransportState::Closed | IceTransportState::Failed) {
559 debug!("TCP listen loop stopping (IceTransport Closed or Failed)");
560 break;
561 }
562 }
563 }
564 }
565 }
566
567 async fn run_tcp_read_loop(
568 read: Arc<Mutex<TcpReadHalf>>,
569 write: Arc<Mutex<TcpWriteHalf>>,
570 peer_addr: SocketAddr,
571 inner: Arc<IceTransportInner>,
572 ) {
573 let mut buf = [0u8; 65_535];
574 let mut marshal_buf = Vec::with_capacity(1500);
575 let mut state_rx = inner.state.subscribe();
576 let sender = IceSocketWrapper::TcpStream(read, write, peer_addr);
577 trace!("TCP read loop started for peer {}", peer_addr);
578 loop {
579 tokio::select! {
580 result = sender.recv_from(&mut buf) => {
581 match result {
582 Ok((len, addr)) => {
583 if len > 0 {
584 handle_packet(
585 &buf[..len],
586 addr,
587 inner.clone(),
588 sender.clone(),
589 &mut marshal_buf,
590 )
591 .await;
592 }
593 }
594 Err(e) => {
595 debug!("TCP recv error from {}: {}", peer_addr, e);
596 break;
597 }
598 }
599 }
600 res = state_rx.changed() => {
601 if res.is_err() || matches!(*state_rx.borrow(), IceTransportState::Closed | IceTransportState::Failed) {
602 debug!("TCP read loop stopping (IceTransport Closed or Failed)");
603 break;
604 }
605 }
606 }
607 }
608 }
609
610 async fn run_keepalive_tick(inner: &Arc<IceTransportInner>) -> Option<BoxFuture<'static, ()>> {
614 let state = *inner.state.borrow();
615 if state == IceTransportState::Connected || state == IceTransportState::Disconnected {
616 if inner.config.transport_mode == crate::TransportMode::WebRtc {
617 let last_nanos = inner.last_received_nanos.load(Ordering::Relaxed);
618 let now_nanos = inner.created_at.elapsed().as_nanos() as u64;
619 let elapsed = Duration::from_nanos(now_nanos.saturating_sub(last_nanos));
620 let ice_conn_timeout = inner.config.ice_connection_timeout;
621 let tcp_selected = inner
622 .selected_pair
623 .lock()
624 .as_ref()
625 .map(|pair| pair.local.transport == "tcp")
626 .unwrap_or(false);
627 let disconnect_threshold = if tcp_selected {
630 ice_conn_timeout.saturating_sub(Duration::from_secs(1))
631 } else {
632 inner.config.ice_disconnect_threshold
633 };
634 if elapsed > ice_conn_timeout {
635 let _ = inner.state.send(IceTransportState::Failed);
636 } else if elapsed > disconnect_threshold {
637 if state != IceTransportState::Disconnected {
638 let _ = inner.state.send(IceTransportState::Disconnected);
639 }
640 } else if state == IceTransportState::Disconnected {
641 let _ = inner.state.send(IceTransportState::Connected);
642 }
643 }
644
645 let pair_opt = inner.selected_pair.lock().clone();
647 if let Some(pair) = pair_opt {
648 let socket = inner
649 ._socket_rx_keeper
650 .borrow()
651 .clone()
652 .or_else(|| resolve_socket(inner, &pair));
653 if let Some(socket) = socket {
654 let tx_id = random_bytes::<12>();
655 let mut msg = StunMessage::binding_request(tx_id, Some("rustrtc"));
656
657 let remote_params = inner.remote_parameters.lock().clone();
658 if let Some(params) = remote_params {
659 let username = format!(
660 "{}:{}",
661 params.username_fragment,
662 inner.local_parameters.lock().username_fragment
663 );
664 msg.attributes.push(StunAttribute::Username(username));
665 msg.attributes
666 .push(StunAttribute::Priority(pair.local.priority));
667
668 if let Ok(bytes) = msg.encode(Some(params.password.as_bytes()), true) {
669 let (tx, rx) = oneshot::channel();
671 {
672 let mut map = inner.pending_transactions.lock();
673 map.insert(tx_id, tx);
674 }
675
676 let inner_weak = Arc::downgrade(inner);
677 let cleanup: BoxFuture<'static, ()> = Box::pin(async move {
678 let _ = timeout(Duration::from_secs(5), rx).await;
679 if let Some(inner) = inner_weak.upgrade() {
680 let mut map = inner.pending_transactions.lock();
681 map.remove(&tx_id);
682 }
683 });
684
685 let _ = socket.send_to(&bytes, pair.remote.address).await;
686 return Some(cleanup);
687 }
688 } else if inner.config.transport_mode != crate::TransportMode::WebRtc
689 && let Ok(bytes) = msg.encode(None, false)
690 {
691 let _ = socket.send_to(&bytes, pair.remote.address).await;
692 }
693 }
694 }
695 }
696 None
697 }
698
699 async fn run_turn_refresh(inner: &Arc<IceTransportInner>) {
715 if inner
719 .turn_refresh_in_progress
720 .swap(true, std::sync::atomic::Ordering::SeqCst)
721 {
722 return;
723 }
724 struct RefreshGuard<'a>(&'a std::sync::atomic::AtomicBool);
727 impl Drop for RefreshGuard<'_> {
728 fn drop(&mut self) {
729 self.0.store(false, std::sync::atomic::Ordering::SeqCst);
730 }
731 }
732 let _guard = RefreshGuard(&inner.turn_refresh_in_progress);
733
734 let state = *inner.state.borrow();
735 if state != IceTransportState::Connected && state != IceTransportState::Disconnected {
736 return;
737 }
738
739 let all_clients: Vec<(SocketAddr, Arc<TurnClient>)> = {
740 let clients = inner.gatherer.turn_clients.lock();
741 clients.iter().map(|(k, v)| (*k, v.clone())).collect()
742 };
743
744 if all_clients.is_empty() {
745 return;
746 }
747
748 let pair_opt = inner.selected_pair.lock().clone();
749
750 let remote_addr_for_perm = pair_opt.as_ref().map(|p| p.remote.address);
751
752 for (relay_local_addr, client) in all_clients {
753 Self::refresh_one_turn_client(inner, relay_local_addr, &client, remote_addr_for_perm)
754 .await;
755 }
756 }
757
758 async fn refresh_one_turn_client(
759 inner: &Arc<IceTransportInner>,
760 _relay_local_addr: SocketAddr,
761 client: &Arc<TurnClient>,
762 remote_addr_opt: Option<SocketAddr>,
763 ) {
764 async fn send_and_await_inner(
765 client: &Arc<TurnClient>,
766 inner: &Arc<IceTransportInner>,
767 bytes: Vec<u8>,
768 tx_id: [u8; 12],
769 ) -> Option<StunDecoded> {
770 let (tx, rx) = oneshot::channel();
771 inner.pending_transactions.lock().insert(tx_id, tx);
772 if let Err(e) = client.send(&bytes).await {
773 debug!("TURN refresh send failed: {}", e);
774 inner.pending_transactions.lock().remove(&tx_id);
775 return None;
776 }
777 match timeout(Duration::from_secs(5), rx).await {
778 Ok(Ok(msg)) => Some(msg),
779 _ => {
780 inner.pending_transactions.lock().remove(&tx_id);
781 None
782 }
783 }
784 }
785
786 'alloc: for attempt in 0..2u8 {
789 match client.create_refresh_packet().await {
790 Ok((bytes, tx_id)) => {
791 match send_and_await_inner(client, inner, bytes, tx_id).await {
792 Some(msg) if msg.class == StunClass::SuccessResponse => {
793 trace!("TURN allocation refreshed successfully");
794 break 'alloc;
795 }
796 Some(msg)
797 if matches!(msg.error_code, Some(401) | Some(438)) && attempt == 0 =>
798 {
799 if let (Some(realm), Some(nonce)) = (msg.realm, msg.nonce) {
801 debug!(
802 "TURN Refresh got {}: updating nonce, retrying",
803 msg.error_code.unwrap_or(0)
804 );
805 client.update_nonce(realm, nonce).await;
806 }
807 continue 'alloc;
808 }
809 Some(msg) => {
810 debug!("TURN Refresh failed: error={:?}", msg.error_code);
811 }
812 None => {
813 debug!("TURN Refresh timeout or send error");
814 }
815 }
816 }
817 Err(e) => debug!("TURN Refresh packet creation failed: {}", e),
818 }
819 break;
820 }
821
822 if let Some(remote_addr) = remote_addr_opt {
826 'perm: for attempt in 0..2u8 {
827 match client.create_permission_packet(remote_addr).await {
828 Ok((bytes, tx_id)) => {
829 match send_and_await_inner(client, inner, bytes, tx_id).await {
830 Some(msg) if msg.class == StunClass::SuccessResponse => {
831 trace!("TURN permission refreshed for {}", remote_addr);
832 break 'perm;
833 }
834 Some(msg)
835 if matches!(msg.error_code, Some(401) | Some(438))
836 && attempt == 0 =>
837 {
838 if let (Some(realm), Some(nonce)) = (msg.realm, msg.nonce) {
839 debug!(
840 "TURN CreatePermission got {}: updating nonce, retrying",
841 msg.error_code.unwrap_or(0)
842 );
843 client.update_nonce(realm, nonce).await;
844 }
845 continue 'perm;
846 }
847 Some(msg) => {
848 debug!(
849 "TURN CreatePermission refresh failed: error={:?}",
850 msg.error_code
851 );
852 }
853 None => {
854 debug!("TURN CreatePermission refresh timeout or send error");
855 }
856 }
857 }
858 Err(e) => debug!("TURN CreatePermission packet creation failed: {}", e),
859 }
860 break;
861 }
862 }
863
864 let bound_peers = client.bound_peers().await;
867 let num_bindings = bound_peers.len();
868 for peer in bound_peers {
869 if let Some(channel) = client.get_channel(peer).await {
870 'chan: for attempt in 0..2u8 {
871 match client.create_channel_rebind_packet(peer, channel).await {
872 Ok((bytes, tx_id)) => {
873 match send_and_await_inner(client, inner, bytes, tx_id).await {
874 Some(msg) if msg.class == StunClass::SuccessResponse => {
875 trace!(
876 "TURN ChannelBind refreshed: {} -> ch {}",
877 peer, channel
878 );
879 break 'chan;
880 }
881 Some(msg)
882 if matches!(msg.error_code, Some(401) | Some(438))
883 && attempt == 0 =>
884 {
885 if let (Some(realm), Some(nonce)) = (msg.realm, msg.nonce) {
886 debug!(
887 "TURN ChannelBind got {}: updating nonce, retrying ch {}",
888 msg.error_code.unwrap_or(0),
889 channel
890 );
891 client.update_nonce(realm, nonce).await;
892 }
893 continue 'chan;
894 }
895 Some(msg) => {
896 debug!(
897 "TURN ChannelBind refresh failed: ch={} error={:?}",
898 channel, msg.error_code
899 );
900 }
901 None => {
902 debug!(
903 "TURN ChannelBind refresh timeout or send error: ch={}",
904 channel
905 );
906 }
907 }
908 }
909 Err(e) => {
910 debug!("TURN ChannelBind refresh packet creation failed: {}", e);
911 }
912 }
913 break;
914 }
915 }
916 }
917
918 debug!(
919 "TURN refresh done: allocation + {} permission + {} channel bindings",
920 if remote_addr_opt.is_some() { 1 } else { 0 },
921 num_bindings
922 );
923 }
924}
925
926impl IceTransport {
927 pub fn new(config: RtcConfiguration) -> (Self, impl std::future::Future<Output = ()> + Send) {
928 let (candidate_tx, _) = broadcast::channel(100);
929 let (socket_tx, socket_rx) = tokio::sync::mpsc::unbounded_channel();
930 let gatherer = IceGatherer::new(config.clone(), candidate_tx.clone(), socket_tx);
931 let (state_tx, state_rx) = watch::channel(IceTransportState::New);
932 let runner_state_rx = state_tx.subscribe();
933 let (gathering_state_tx, gathering_state_rx) = watch::channel(IceGathererState::New);
934 let (selected_socket_tx, selected_socket_rx) = watch::channel(None);
935 let (selected_rtcp_socket_tx, selected_rtcp_socket_rx) = watch::channel(None);
936 let (selected_pair_tx, selected_pair_rx) = watch::channel(None);
937 let (cmd_tx, cmd_rx) = mpsc::unbounded_channel();
938 let (nomination_complete_tx, nomination_complete_rx) = watch::channel(None);
939
940 let inner = IceTransportInner {
941 state: state_tx,
942 _state_rx_keeper: state_rx,
943 gathering_state: gathering_state_tx,
944 _gathering_state_rx_keeper: gathering_state_rx,
945 role: parking_lot::Mutex::new(IceRole::Controlled),
946 selected_pair: parking_lot::Mutex::new(None),
947 local_candidates: Mutex::new(Vec::new()),
948 remote_candidates: parking_lot::Mutex::new(Vec::new()),
949 gather_state: parking_lot::Mutex::new(IceGathererState::New),
950 config: config.clone(),
951 gatherer,
952 local_parameters: parking_lot::Mutex::new(IceParameters::generate()),
953 remote_parameters: parking_lot::Mutex::new(None),
954 pending_transactions: parking_lot::Mutex::new(HashMap::new()),
955 data_receiver: parking_lot::Mutex::new(None),
956 buffered_packets: parking_lot::Mutex::new(VecDeque::new()),
957 selected_socket: selected_socket_tx,
958 _socket_rx_keeper: selected_socket_rx,
959 selected_rtcp_socket: selected_rtcp_socket_tx,
960 _rtcp_socket_rx_keeper: selected_rtcp_socket_rx,
961 selected_pair_notifier: selected_pair_tx,
962 _selected_pair_rx_keeper: selected_pair_rx,
963 created_at: Instant::now(),
964 last_received_nanos: AtomicU64::new(0),
965 candidate_tx: candidate_tx.clone(),
966 cmd_tx,
967 checking_pairs: Mutex::new(std::collections::HashSet::new()),
968 nomination_complete: nomination_complete_tx,
969 _nomination_complete_rx: nomination_complete_rx,
970 turn_refresh_in_progress: std::sync::atomic::AtomicBool::new(false),
971 upnp_refresh_in_progress: std::sync::atomic::AtomicBool::new(false),
972 buffer_stats: Arc::new(BufferStats::default()),
973 };
974 let inner = Arc::new(inner);
975 inner.gatherer.set_transport(Arc::downgrade(&inner));
976
977 let runner = IceTransportRunner {
978 inner: inner.clone(),
979 socket_rx,
980 candidate_rx: candidate_tx.subscribe(),
981 cmd_rx,
982 state_rx: runner_state_rx,
983 };
984
985 (Self { inner }, runner.run())
986 }
987
988 pub fn state(&self) -> IceTransportState {
989 *self.inner.state.borrow()
990 }
991
992 pub fn subscribe_state(&self) -> watch::Receiver<IceTransportState> {
993 self.inner.state.subscribe()
994 }
995
996 pub fn subscribe_gathering_state(&self) -> watch::Receiver<IceGathererState> {
997 self.inner.gathering_state.subscribe()
998 }
999
1000 pub fn subscribe_candidates(&self) -> broadcast::Receiver<IceCandidate> {
1001 self.inner.candidate_tx.subscribe()
1002 }
1003
1004 pub fn subscribe_selected_socket(&self) -> watch::Receiver<Option<IceSocketWrapper>> {
1005 self.inner.selected_socket.subscribe()
1006 }
1007
1008 pub(crate) fn subscribe_selected_rtcp_socket(
1009 &self,
1010 ) -> watch::Receiver<Option<IceSocketWrapper>> {
1011 self.inner.selected_rtcp_socket.subscribe()
1012 }
1013
1014 pub fn subscribe_selected_pair(&self) -> watch::Receiver<Option<IceCandidatePair>> {
1015 self.inner.selected_pair_notifier.subscribe()
1016 }
1017
1018 pub fn subscribe_nomination_complete(&self) -> watch::Receiver<Option<bool>> {
1022 self.inner.nomination_complete.subscribe()
1023 }
1024
1025 pub fn nudge_passive_tcp_nomination(&self) {
1028 if *self.inner.role.lock() != IceRole::Controlled {
1029 return;
1030 }
1031 if self.inner.nomination_complete.borrow().is_some() {
1032 return;
1033 }
1034 let inner = self.inner.clone();
1035 debug!("ICE: nudging passive TCP nomination (controlled, awaiting inbound TCP)");
1036 let rt_handle = inner.config.runtime_handle.clone();
1037 crate::spawn_rtc(
1038 rt_handle.as_ref(),
1039 tracing::Span::current(),
1040 async move {
1041 let streams: Vec<_> = inner
1042 .gatherer
1043 .tcp_streams
1044 .lock()
1045 .values()
1046 .cloned()
1047 .collect();
1048 for wrapper in streams {
1049 if let IceSocketWrapper::TcpStream(_, _, peer) = wrapper {
1050 complete_controlled_inbound_tcp_nomination(&wrapper, peer, inner).await;
1051 return;
1052 }
1053 }
1054 },
1055 );
1056 }
1057
1058 pub fn gather_state(&self) -> IceGathererState {
1059 self.inner.gatherer.state()
1060 }
1061
1062 pub fn role(&self) -> IceRole {
1063 *self.inner.role.lock()
1064 }
1065
1066 pub fn local_candidates(&self) -> Vec<IceCandidate> {
1067 self.inner.gatherer.local_candidates()
1068 }
1069
1070 pub(crate) fn local_rtcp_addr(&self) -> Option<SocketAddr> {
1071 self.inner
1072 .gatherer
1073 .local_candidates()
1074 .into_iter()
1075 .find(|candidate| candidate.component == 2)
1076 .map(|candidate| candidate.address)
1077 }
1078
1079 pub fn remote_candidates(&self) -> Vec<IceCandidate> {
1080 self.inner.remote_candidates.lock().clone()
1081 }
1082
1083 pub fn local_parameters(&self) -> IceParameters {
1084 self.inner.local_parameters.lock().clone()
1085 }
1086
1087 pub fn set_remote_parameters(&self, params: IceParameters) {
1088 *self.inner.remote_parameters.lock() = Some(params);
1089 }
1090
1091 fn start_keepalive(&self) {
1092 }
1094
1095 pub fn start_gathering(&self) -> Result<()> {
1096 {
1097 let mut state = self.inner.gather_state.lock();
1098 if *state == IceGathererState::Complete || *state == IceGathererState::Gathering {
1099 return Ok(());
1100 }
1101 *state = IceGathererState::Gathering;
1102 let _ = self.inner.gathering_state.send(IceGathererState::Gathering);
1103 }
1104
1105 let _ = self.inner.cmd_tx.send(IceCommand::StartGathering);
1106 Ok(())
1107 }
1108
1109 pub fn start(&self, remote: IceParameters) -> Result<()> {
1110 self.start_gathering()?;
1111 self.start_keepalive();
1112 {
1113 let mut params = self.inner.remote_parameters.lock();
1114 *params = Some(remote);
1115 }
1116 if let Err(e) = self.inner.state.send(IceTransportState::Checking) {
1117 debug!("start: failed to set state to Checking: {}", e);
1118 }
1119 self.try_connectivity_checks();
1120 Ok(())
1121 }
1122
1123 pub async fn start_direct(&self, remote_addr: SocketAddr) -> Result<()> {
1124 self.start_gathering()?;
1125 self.start_keepalive();
1126
1127 let mut rx = self.subscribe_candidates();
1130 let start = Instant::now();
1131 let timeout_dur = Duration::from_secs(2);
1132
1133 let is_suitable = |c: &IceCandidate| -> bool {
1134 if !remote_addr.ip().is_loopback() && c.address.ip().is_loopback() {
1135 return false;
1136 }
1137 true
1138 };
1139
1140 let mut best_local: Option<IceCandidate> = None;
1141
1142 {
1144 let candidates = self.inner.gatherer.local_candidates();
1145 for c in candidates {
1146 if is_suitable(&c) {
1147 best_local = Some(c);
1148 break;
1149 }
1150 }
1151 }
1152
1153 if best_local.is_none() {
1155 loop {
1156 let remaining = timeout_dur
1157 .checked_sub(start.elapsed())
1158 .unwrap_or(Duration::ZERO);
1159 if remaining.is_zero() {
1160 break;
1161 }
1162
1163 match timeout(remaining, rx.recv()).await {
1164 Ok(Ok(c)) => {
1165 if is_suitable(&c) {
1166 best_local = Some(c);
1167 break;
1168 }
1169 }
1170 _ => break,
1171 }
1172 }
1173 }
1174
1175 let local = if let Some(best) = best_local {
1177 best
1178 } else if let Some(first) = self.inner.gatherer.local_candidates().first() {
1179 first.clone()
1180 } else {
1181 bail!("No local candidates gathered for direct connection");
1182 };
1183
1184 let remote = IceCandidate::host(remote_addr, 1);
1185 let pair = IceCandidatePair::new(local, remote);
1186
1187 *self.inner.selected_pair.lock() = Some(pair.clone());
1188 let _ = self.inner.selected_pair_notifier.send(Some(pair.clone()));
1189 if let Some(socket) = resolve_socket(&self.inner, &pair) {
1190 let _ = self.inner.selected_socket.send(Some(socket.clone()));
1191 publish_selected_rtcp_socket(&self.inner, Some(socket));
1192 }
1193 let _ = self.inner.state.send(IceTransportState::Connected);
1194 Ok(())
1195 }
1196
1197 pub async fn setup_direct_rtp(&self, remote_addr: SocketAddr) -> Result<SocketAddr> {
1201 self.setup_direct_rtp_with_rtcp(remote_addr, false).await
1202 }
1203
1204 pub(crate) async fn setup_direct_rtp_with_rtcp(
1205 &self,
1206 remote_addr: SocketAddr,
1207 bind_rtcp: bool,
1208 ) -> Result<SocketAddr> {
1209 let bind_ip = if let Some(bind_ip_str) = &self.inner.config.bind_ip {
1210 bind_ip_str.parse::<IpAddr>().unwrap_or_else(|_| {
1211 get_local_ip().unwrap_or(IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED))
1212 })
1213 } else if let Ok(ip) = get_local_ip() {
1214 ip
1215 } else {
1216 IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED)
1217 };
1218
1219 let socket = self.inner.gatherer.bind_socket(bind_ip).await?;
1220 let local_addr = socket.local_addr()?;
1221 let socket = Arc::new(socket);
1222
1223 self.inner.gatherer.sockets.lock().push(socket.clone());
1225
1226 let _ = self
1228 .inner
1229 .gatherer
1230 .socket_tx
1231 .send(IceSocketWrapper::Udp(socket.clone()));
1232
1233 let mut cand_addr = local_addr;
1235 let mut upnp_external_addr = None;
1236
1237 if self.inner.config.enable_upnp && !local_addr.ip().is_loopback() && !local_addr.is_ipv6()
1239 {
1240 let mut mapper = UpnpPortMapper::with_lease_duration(
1241 local_addr,
1242 self.inner.config.upnp_lease_duration,
1243 );
1244 if let Err(e) = mapper.discover().await {
1245 trace!("UPnP discovery failed for RTP mode: {}", e);
1246 } else if let Ok(ext_addr) = mapper.add_mapping(0).await {
1247 debug!(
1248 "UPnP mapping created for RTP mode: {} -> {}",
1249 local_addr, ext_addr
1250 );
1251 cand_addr.set_ip(ext_addr.ip());
1252 cand_addr.set_port(ext_addr.port());
1253 upnp_external_addr = Some(ext_addr);
1254 self.inner.gatherer.upnp_mappers.lock().push(mapper);
1255 } else {
1256 debug!("UPnP mapping failed for RTP mode, using local address");
1257 }
1258 }
1259
1260 if upnp_external_addr.is_none() {
1262 if let Some(ext_ip) = &self.inner.config.external_ip {
1263 if let Ok(parsed_ip) = ext_ip.parse::<IpAddr>()
1264 && !bind_ip.is_loopback()
1265 {
1266 cand_addr.set_ip(parsed_ip);
1267 }
1268 } else if bind_ip.is_unspecified()
1269 && let Ok(local_ip) = get_local_ip()
1270 {
1271 cand_addr.set_ip(local_ip);
1272 }
1273 }
1274
1275 if upnp_external_addr.is_none()
1277 && let Some(ext_port) = self.inner.config.external_port
1278 && !bind_ip.is_loopback()
1279 {
1280 cand_addr.set_port(ext_port);
1281 }
1282
1283 let mut local_candidate = IceCandidate::host(cand_addr, 1);
1284 if cand_addr != local_addr {
1285 local_candidate.related_address = Some(local_addr);
1286 }
1287 let mut rtcp_socket = None;
1288 let mut rtcp_candidate = None;
1289 if bind_rtcp {
1290 let (rtcp, candidate) =
1291 bind_direct_rtcp_socket(&self.inner, local_addr, cand_addr.ip()).await?;
1292 rtcp_socket = Some(rtcp);
1293 rtcp_candidate = Some(candidate);
1294 }
1295 self.inner.gatherer.push_candidate(local_candidate.clone());
1296 if let Some(candidate) = rtcp_candidate {
1297 self.inner.gatherer.push_candidate(candidate);
1298 }
1299
1300 *self.inner.gatherer.state.lock() = IceGathererState::Complete;
1302 let _ = self.inner.gathering_state.send(IceGathererState::Complete);
1303
1304 let remote_candidate = IceCandidate::host(remote_addr, 1);
1306 let pair = IceCandidatePair::new(local_candidate, remote_candidate);
1307 *self.inner.selected_pair.lock() = Some(pair.clone());
1308 let _ = self.inner.selected_pair_notifier.send(Some(pair));
1309 let _ = self
1310 .inner
1311 .selected_socket
1312 .send(Some(IceSocketWrapper::Udp(socket.clone())));
1313 let rtcp_socket = rtcp_socket.unwrap_or_else(|| socket.clone());
1314 let _ = self
1315 .inner
1316 .selected_rtcp_socket
1317 .send(Some(IceSocketWrapper::Udp(rtcp_socket)));
1318 let _ = self.inner.state.send(IceTransportState::Connected);
1319
1320 Ok(cand_addr)
1321 }
1322
1323 pub async fn setup_direct_rtp_offer(&self) -> Result<SocketAddr> {
1327 self.setup_direct_rtp_offer_with_rtcp(false).await
1328 }
1329
1330 pub(crate) async fn setup_direct_rtp_offer_with_rtcp(
1331 &self,
1332 bind_rtcp: bool,
1333 ) -> Result<SocketAddr> {
1334 let bind_ip = if let Some(bind_ip_str) = &self.inner.config.bind_ip {
1335 bind_ip_str.parse::<IpAddr>().unwrap_or_else(|_| {
1336 get_local_ip().unwrap_or(IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED))
1337 })
1338 } else if let Ok(ip) = get_local_ip() {
1339 ip
1340 } else {
1341 IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED)
1342 };
1343
1344 let socket = self.inner.gatherer.bind_socket(bind_ip).await?;
1345 let local_addr = socket.local_addr()?;
1346 let socket = Arc::new(socket);
1347
1348 self.inner.gatherer.sockets.lock().push(socket.clone());
1349 let _ = self
1350 .inner
1351 .gatherer
1352 .socket_tx
1353 .send(IceSocketWrapper::Udp(socket));
1354
1355 let mut cand_addr = local_addr;
1356 let mut upnp_external_addr = None;
1357
1358 if self.inner.config.enable_upnp && !local_addr.ip().is_loopback() && !local_addr.is_ipv6()
1360 {
1361 let mut mapper = UpnpPortMapper::with_lease_duration(
1362 local_addr,
1363 self.inner.config.upnp_lease_duration,
1364 );
1365 if let Err(e) = mapper.discover().await {
1366 trace!("UPnP discovery failed for RTP offer mode: {}", e);
1367 } else if let Ok(ext_addr) = mapper.add_mapping(0).await {
1368 debug!(
1369 "UPnP mapping created for RTP offer mode: {} -> {}",
1370 local_addr, ext_addr
1371 );
1372 cand_addr.set_ip(ext_addr.ip());
1373 cand_addr.set_port(ext_addr.port());
1374 upnp_external_addr = Some(ext_addr);
1375 self.inner.gatherer.upnp_mappers.lock().push(mapper);
1376 } else {
1377 debug!("UPnP mapping failed for RTP offer mode, using local address");
1378 }
1379 }
1380
1381 if upnp_external_addr.is_none() {
1383 if let Some(ext_ip) = &self.inner.config.external_ip {
1384 if let Ok(parsed_ip) = ext_ip.parse::<IpAddr>()
1385 && !bind_ip.is_loopback()
1386 {
1387 cand_addr.set_ip(parsed_ip);
1388 }
1389 } else if bind_ip.is_unspecified()
1390 && let Ok(local_ip) = get_local_ip()
1391 {
1392 cand_addr.set_ip(local_ip);
1393 }
1394 }
1395
1396 if upnp_external_addr.is_none()
1398 && let Some(ext_port) = self.inner.config.external_port
1399 && !bind_ip.is_loopback()
1400 {
1401 cand_addr.set_port(ext_port);
1402 }
1403
1404 let mut local_candidate = IceCandidate::host(cand_addr, 1);
1405 if cand_addr != local_addr {
1406 local_candidate.related_address = Some(local_addr);
1407 }
1408 let mut rtcp_socket = None;
1409 let mut rtcp_candidate = None;
1410 if bind_rtcp {
1411 let (rtcp, candidate) =
1412 bind_direct_rtcp_socket(&self.inner, local_addr, cand_addr.ip()).await?;
1413 rtcp_socket = Some(rtcp);
1414 rtcp_candidate = Some(candidate);
1415 }
1416 self.inner.gatherer.push_candidate(local_candidate);
1417 if let Some(candidate) = rtcp_candidate {
1418 self.inner.gatherer.push_candidate(candidate);
1419 }
1420 if let Some(rtcp_socket) = rtcp_socket {
1421 let _ = self
1422 .inner
1423 .selected_rtcp_socket
1424 .send(Some(IceSocketWrapper::Udp(rtcp_socket)));
1425 }
1426
1427 *self.inner.gatherer.state.lock() = IceGathererState::Complete;
1428 let _ = self.inner.gathering_state.send(IceGathererState::Complete);
1429
1430 Ok(cand_addr)
1431 }
1432
1433 pub fn complete_direct_rtp(&self, remote_addr: SocketAddr) {
1436 let remote_candidate = IceCandidate::host(remote_addr, 1);
1437 let local_candidate = self
1438 .inner
1439 .gatherer
1440 .local_candidates()
1441 .into_iter()
1442 .find(|candidate| candidate.component == 1)
1443 .unwrap_or_else(|| {
1444 IceCandidate::host(
1445 SocketAddr::new(IpAddr::V4(std::net::Ipv4Addr::LOCALHOST), 0),
1446 1,
1447 )
1448 });
1449 let pair = IceCandidatePair::new(local_candidate, remote_candidate);
1450 *self.inner.selected_pair.lock() = Some(pair.clone());
1451 let _ = self.inner.selected_pair_notifier.send(Some(pair.clone()));
1452 if let Some(socket) = resolve_socket(&self.inner, &pair) {
1453 let _ = self.inner.selected_socket.send(Some(socket.clone()));
1454 publish_selected_rtcp_socket(&self.inner, Some(socket));
1455 }
1456 let _ = self.inner.state.send(IceTransportState::Connected);
1457 }
1458
1459 fn destroy_turn_allocations_best_effort(&self) {
1466 let clients: Vec<Arc<TurnClient>> = {
1471 let map = self.inner.gatherer.turn_clients.lock();
1472 map.values().cloned().collect()
1473 };
1474 for client in &clients {
1475 if let Ok((bytes, _tx_id)) = client.create_destroy_packet_sync()
1476 && client.try_send_sync(&bytes)
1477 {
1478 trace!("TURN allocation destroy Refresh(LIFETIME=0) sent (best-effort)");
1479 }
1480 }
1481 }
1482
1483 pub fn stop(&self) {
1484 self.destroy_turn_allocations_best_effort();
1491
1492 if let Ok(handle) = tokio::runtime::Handle::try_current() {
1496 let upnp_clone = self.inner.gatherer.clone();
1497 handle.spawn(async move {
1498 upnp_clone.cleanup_upnp_mappings().await;
1499 });
1500 }
1501
1502 let _ = self.inner.state.send(IceTransportState::Closed);
1503 let _ = self.inner.selected_socket.send(None);
1504 let _ = self.inner.selected_rtcp_socket.send(None);
1505 let _ = self.inner.selected_pair_notifier.send(None);
1506 *self.inner.selected_pair.lock() = None;
1507 self.inner.gatherer.sockets.lock().clear();
1508 self.inner.gatherer.tcp_listeners.lock().clear();
1509 self.inner.gatherer.tcp_streams.lock().clear();
1510 self.inner.gatherer.shared_tcp_regs.lock().clear();
1511 self.inner.gatherer.shared_udp_regs.lock().clear();
1512 self.inner.gatherer.turn_clients.lock().clear();
1513 *self.inner.gatherer.shared_udp_socket.lock() = None;
1516 }
1517
1518 #[cfg(test)]
1523 pub fn force_state_for_test(&self, state: IceTransportState) {
1524 let _ = self.inner.state.send(state);
1525 }
1526
1527 pub fn set_role(&self, role: IceRole) {
1528 *self.inner.role.lock() = role;
1529 }
1530
1531 pub fn add_remote_candidate(&self, candidate: IceCandidate) {
1532 let mut list = self.inner.remote_candidates.lock();
1533 list.push(candidate);
1534 drop(list);
1535 self.try_connectivity_checks();
1536 }
1537
1538 pub fn select_pair(&self, pair: IceCandidatePair) {
1539 *self.inner.selected_pair.lock() = Some(pair.clone());
1540 let _ = self.inner.selected_pair_notifier.send(Some(pair.clone()));
1541 if let Some(socket) = resolve_socket(&self.inner, &pair) {
1542 let _ = self.inner.selected_socket.send(Some(socket.clone()));
1543 publish_selected_rtcp_socket(&self.inner, Some(socket));
1544 }
1545 let _ = self.inner.state.send(IceTransportState::Connected);
1546 }
1547
1548 pub fn config(&self) -> &RtcConfiguration {
1549 &self.inner.config
1550 }
1551
1552 pub fn get_selected_socket(&self) -> Option<IceSocketWrapper> {
1553 if let Some(socket) = self.inner._socket_rx_keeper.borrow().clone() {
1554 return Some(socket);
1555 }
1556 let pair = self.inner.selected_pair.lock().clone()?;
1557 resolve_socket(&self.inner, &pair)
1558 }
1559
1560 pub fn get_selected_pair(&self) -> Option<IceCandidatePair> {
1561 self.inner.selected_pair.lock().clone()
1562 }
1563
1564 pub async fn set_data_receiver(&self, receiver: Arc<dyn PacketReceiver>) {
1565 {
1566 let mut rx_lock = self.inner.data_receiver.lock();
1567 *rx_lock = Some(receiver.clone());
1568 }
1569
1570 let packets: Vec<_> = {
1571 let mut buffer = self.inner.buffered_packets.lock();
1572 if buffer.is_empty() {
1573 return;
1574 }
1575 debug!(
1576 count = buffer.len(),
1577 "Flushing buffered RTP packets to newly registered data_receiver"
1578 );
1579 buffer.drain(..).collect()
1580 };
1581
1582 let mut marshal_buf = Vec::new();
1583 for (packet, addr) in packets {
1584 receiver
1585 .receive(Bytes::from(packet), addr, &mut marshal_buf)
1586 .await;
1587 }
1588 }
1589
1590 fn try_connectivity_checks(&self) {
1591 let _ = self.inner.cmd_tx.send(IceCommand::RunChecks);
1592 }
1593
1594 async fn handle_turn_packet(
1595 packet: &[u8],
1596 inner: &Arc<IceTransportInner>,
1597 client: &Arc<TurnClient>,
1598 relayed_addr: SocketAddr,
1599 marshal_buf: &mut Vec<u8>,
1600 ) {
1601 if packet.len() >= 4 {
1603 let channel_num = u16::from_be_bytes([packet[0], packet[1]]);
1604 if (0x4000..=0x7FFF).contains(&channel_num) {
1605 let len = u16::from_be_bytes([packet[2], packet[3]]) as usize;
1606 if packet.len() >= 4 + len {
1607 let data = &packet[4..4 + len];
1608 if let Some(peer_addr) = client.get_peer(channel_num).await {
1609 handle_packet(
1610 data,
1611 peer_addr,
1612 inner.clone(),
1613 IceSocketWrapper::Turn(client.clone(), relayed_addr),
1614 marshal_buf,
1615 )
1616 .await;
1617 }
1618 }
1619 return;
1620 }
1621 }
1622
1623 if let Ok(msg) = StunMessage::decode(packet) {
1624 if msg.class == StunClass::Indication && msg.method == StunMethod::Data {
1625 if let Some(data) = &msg.data
1626 && let Some(peer_addr) = msg.xor_peer_address
1627 {
1628 handle_packet(
1629 data,
1630 peer_addr,
1631 inner.clone(),
1632 IceSocketWrapper::Turn(client.clone(), relayed_addr),
1633 marshal_buf,
1634 )
1635 .await;
1636 }
1637 } else {
1638 handle_packet(
1640 packet,
1641 relayed_addr,
1642 inner.clone(),
1643 IceSocketWrapper::Turn(client.clone(), relayed_addr),
1644 marshal_buf,
1645 )
1646 .await;
1647 }
1648 }
1649 }
1650}
1651
1652async fn perform_connectivity_checks_async(inner: Arc<IceTransportInner>) {
1653 let state = *inner.state.borrow();
1654 if state != IceTransportState::Checking {
1655 return;
1656 }
1657
1658 if inner.selected_pair.lock().is_some() {
1660 return;
1661 }
1662
1663 let remotes = inner.remote_candidates.lock().clone();
1664 let role = *inner.role.lock();
1665
1666 if remotes.is_empty() {
1667 return;
1668 }
1669
1670 let mut locals = inner.gatherer.local_candidates();
1671
1672 if locals.is_empty() && role == IceRole::Controlling {
1676 use std::net::{IpAddr, Ipv4Addr};
1677 for remote in &remotes {
1678 if remote.transport == "tcp" && remote.tcp_type == Some(TcpType::Passive) {
1679 locals.push(IceCandidate::tcp(
1680 SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
1681 remote.component,
1682 "active",
1683 ));
1684 }
1685 }
1686 }
1687
1688 if locals.is_empty() {
1689 return;
1690 }
1691
1692 let mut pairs = Vec::new();
1693
1694 for local in &locals {
1695 for remote in &remotes {
1696 if local.transport != remote.transport {
1697 continue;
1698 }
1699 if local.component != remote.component {
1700 continue;
1701 }
1702 if local.address.ip().is_loopback() && !remote.address.ip().is_loopback() {
1704 continue;
1705 }
1706 if local.address.is_ipv4() != remote.address.is_ipv4() {
1707 continue;
1708 }
1709 if role == IceRole::Controlled
1713 && local.transport == "tcp"
1714 && local.tcp_type == Some(TcpType::Passive)
1715 {
1716 continue;
1717 }
1718 pairs.push(IceCandidatePair::new(local.clone(), remote.clone()));
1719 }
1720 }
1721
1722 pairs.sort_by_key(|p| std::cmp::Reverse(p.priority(role)));
1724
1725 if inner.config.prefer_srflx_over_natted_host {
1732 let is_private_ip = |ip: std::net::IpAddr| -> bool {
1733 match ip {
1734 std::net::IpAddr::V4(v4) => v4.is_private(),
1735 std::net::IpAddr::V6(v6) => v6.is_unique_local(),
1736 }
1737 };
1738 let is_behind_nat = |pair: &IceCandidatePair| -> bool {
1739 pair.local.typ == IceCandidateType::Host
1740 && is_private_ip(pair.local.address.ip())
1741 && !(pair.remote.typ == IceCandidateType::Host
1742 && is_private_ip(pair.remote.address.ip()))
1743 };
1744 pairs.sort_by(|a, b| {
1745 let a_natted = is_behind_nat(a);
1746 let b_natted = is_behind_nat(b);
1747 if a_natted != b_natted {
1748 return a_natted.cmp(&b_natted);
1749 }
1750 b.priority(role).cmp(&a.priority(role))
1751 });
1752 }
1753
1754 let mut pairs_to_check = Vec::new();
1755 {
1756 let mut checking = inner.checking_pairs.lock().await;
1757 for pair in pairs {
1758 let key = (pair.local.address, pair.remote.address);
1759 if !checking.contains(&key) {
1760 checking.insert(key);
1761 pairs_to_check.push(pair);
1762 }
1763 }
1764 }
1765
1766 if pairs_to_check.is_empty() {
1767 return;
1768 }
1769 let mut checks = futures::stream::FuturesUnordered::new();
1770
1771 for pair in pairs_to_check {
1772 let inner = inner.clone();
1773 let local = pair.local.clone();
1774 let remote = pair.remote.clone();
1775
1776 checks.push(async move {
1777 let key = (local.address, remote.address);
1778 let res = perform_binding_check(&local, &remote, &inner, role, false).await;
1779
1780 {
1781 let mut checking = inner.checking_pairs.lock().await;
1782 checking.remove(&key);
1783 }
1784
1785 match res {
1786 Ok(_) => Some(IceCandidatePair::new(local, remote)),
1787 Err(e) => {
1788 debug!(
1789 "ICE connectivity check failed: {} -> {}: {}",
1790 local.address, remote.address, e
1791 );
1792 None
1793 }
1794 }
1795 });
1796 }
1797
1798 if checks.is_empty() {
1799 return;
1800 }
1801
1802 use futures::stream::StreamExt;
1803 let mut successful_pairs: Vec<IceCandidatePair> = Vec::new();
1804
1805 const NOMINATION_GRACE: Duration = Duration::from_millis(200);
1812 loop {
1813 let next = if successful_pairs.is_empty() {
1814 checks.next().await
1815 } else {
1816 tokio::select! {
1817 biased;
1818 res = checks.next() => res,
1819 _ = tokio::time::sleep(NOMINATION_GRACE) => break,
1820 }
1821 };
1822
1823 match next {
1824 Some(pair) => {
1825 if let Some(pair) = pair {
1826 let key = (pair.local.address, pair.remote.address);
1828 if !successful_pairs
1829 .iter()
1830 .any(|p| (p.local.address, p.remote.address) == key)
1831 {
1832 successful_pairs.push(pair);
1833 }
1834 }
1835 }
1836 None => break,
1837 }
1838 }
1839
1840 if successful_pairs.is_empty() {
1841 return;
1846 }
1847
1848 successful_pairs.sort_by_key(|p| std::cmp::Reverse(p.priority(role)));
1850
1851 for p in &successful_pairs {
1852 debug!(
1853 "ICE successful pair ({}): local {} {:?} -> remote {} {:?}",
1854 if role == IceRole::Controlling {
1855 "controlling"
1856 } else {
1857 "controlled"
1858 },
1859 p.local.address, p.local.typ, p.remote.address, p.remote.typ
1860 );
1861 }
1862
1863 if role == IceRole::Controlling {
1864 let _ = inner.state.send(IceTransportState::Connected);
1866
1867 const NOMINATION_GRACE: Duration = Duration::from_millis(200);
1885 let mut nom_checks = futures::stream::FuturesUnordered::new();
1886 for pair in &successful_pairs {
1887 let inner_c = inner.clone();
1888 let local = pair.local.clone();
1889 let remote = pair.remote.clone();
1890 debug!(
1891 "Controlling agent nominating pair: {} -> {}",
1892 local.address, remote.address
1893 );
1894 nom_checks.push(async move {
1895 let result = perform_binding_check(&local, &remote, &inner_c, role, true).await;
1896 (IceCandidatePair::new(local, remote), result)
1897 });
1898 }
1899
1900 let highest_priority = successful_pairs[0].clone();
1901 let mut successful_nominations: Vec<IceCandidatePair> = Vec::new();
1902 let mut in_flight = nom_checks.len();
1903 loop {
1904 let next = if successful_nominations.is_empty() {
1905 nom_checks.next().await
1906 } else {
1907 tokio::select! {
1908 biased;
1909 res = nom_checks.next() => res,
1910 _ = tokio::time::sleep(NOMINATION_GRACE) => None,
1911 }
1912 };
1913 let Some((pair, result)) = next else { break };
1914 in_flight -= 1;
1915 match result {
1916 Ok(_) => {
1917 debug!(
1918 "Nomination succeeded: {} -> {}",
1919 pair.local.address, pair.remote.address
1920 );
1921 let key = (pair.local.address, pair.remote.address);
1922 if !successful_nominations
1923 .iter()
1924 .any(|p| (p.local.address, p.remote.address) == key)
1925 {
1926 successful_nominations.push(pair.clone());
1927 }
1928 if pair.local.address == highest_priority.local.address
1931 && pair.remote.address == highest_priority.remote.address
1932 {
1933 break;
1934 }
1935 }
1936 Err(e) => {
1937 debug!(
1938 "Nomination failed for {} -> {}: {}",
1939 pair.local.address, pair.remote.address, e
1940 );
1941 }
1942 }
1943 if in_flight == 0 {
1944 break;
1945 }
1946 }
1947
1948 successful_nominations.sort_by_key(|p| std::cmp::Reverse(p.priority(role)));
1951 let final_pair = successful_nominations
1952 .first()
1953 .cloned()
1954 .unwrap_or_else(|| successful_pairs[0].clone());
1955 let nominated = !successful_nominations.is_empty();
1956 *inner.selected_pair.lock() = Some(final_pair.clone());
1957 let _ = inner.selected_pair_notifier.send(Some(final_pair.clone()));
1958 if let Some(socket) = resolve_socket(&inner, &final_pair) {
1959 let _ = inner.selected_socket.send(Some(socket.clone()));
1960 publish_selected_rtcp_socket(&inner, Some(socket));
1961 }
1962 debug!(
1963 "ICE checks complete. Selected pair: {} -> {}",
1964 final_pair.local.address, final_pair.remote.address
1965 );
1966
1967 if nominated {
1968 let _ = inner.nomination_complete.send(Some(true));
1969 } else {
1970 debug!(
1971 "All {} nomination attempts failed",
1972 successful_pairs.len()
1973 );
1974 let _ = inner.nomination_complete.send(Some(false));
1975 let _ = inner.state.send(IceTransportState::Failed);
1976 }
1977 } else {
1978 if inner.nomination_complete.borrow().is_some() {
1987 debug!("ICE checks complete (controlled): keeping peer-nominated pair");
1988 return;
1989 }
1990 let pair = &successful_pairs[0];
1991 *inner.selected_pair.lock() = Some(pair.clone());
1992 let _ = inner.selected_pair_notifier.send(Some(pair.clone()));
1993 if let Some(socket) = resolve_socket(&inner, pair) {
1994 let _ = inner.selected_socket.send(Some(socket.clone()));
1995 publish_selected_rtcp_socket(&inner, Some(socket));
1996 }
1997 let _ = inner.state.send(IceTransportState::Connected);
1998 if pair.local.transport == "tcp" {
1999 let _ = inner.nomination_complete.send(Some(true));
2000 }
2001 debug!(
2002 "ICE checks complete. Selected pair: {} -> {}",
2003 pair.local.address, pair.remote.address
2004 );
2005 }
2006}
2007
2008fn resolve_socket(inner: &IceTransportInner, pair: &IceCandidatePair) -> Option<IceSocketWrapper> {
2009 if pair.local.typ == IceCandidateType::Relay {
2010 let clients = inner.gatherer.turn_clients.lock();
2011 clients
2012 .get(&pair.local.address)
2013 .map(|c| IceSocketWrapper::Turn(c.clone(), pair.local.address))
2014 } else if pair.local.transport == "tcp" {
2015 let streams = inner.gatherer.tcp_streams.lock();
2019 for wrapper in streams.values() {
2020 if let IceSocketWrapper::TcpStream(_, _, peer) = wrapper
2021 && *peer == pair.remote.address
2022 {
2023 return Some(wrapper.clone());
2024 }
2025 }
2026 drop(streams);
2027 inner.gatherer.get_tcp_socket(pair.local.base_address())
2028 } else {
2029 if pair.local.typ == IceCandidateType::Host
2031 && let Some(shared) = inner.gatherer.shared_udp_socket.lock().clone()
2032 {
2033 return Some(shared);
2034 }
2035 let socket = inner.gatherer.get_socket(pair.local.base_address());
2036 if socket.is_none() {
2037 debug!(
2038 "resolve_socket: failed to find socket for {}",
2039 pair.local.base_address()
2040 );
2041 }
2042 socket.map(IceSocketWrapper::Udp)
2043 }
2044}
2045
2046fn publish_selected_socket(
2047 inner: &IceTransportInner,
2048 pair: &IceCandidatePair,
2049 inbound: Option<&IceSocketWrapper>,
2050) {
2051 let socket = match inbound {
2054 Some(s @ IceSocketWrapper::TcpStream(_, _, _)) => Some(s.clone()),
2055 _ => resolve_socket(inner, pair),
2056 };
2057 if let Some(socket) = socket {
2058 debug!(
2059 pair_local = %pair.local.address,
2060 pair_remote = %pair.remote.address,
2061 socket = %socket.diag(),
2062 inbound_tcp = matches!(inbound, Some(IceSocketWrapper::TcpStream(_, _, _))),
2063 "ICE: published selected socket"
2064 );
2065 let _ = inner.selected_socket.send(Some(socket.clone()));
2066 publish_selected_rtcp_socket(inner, Some(socket));
2067 }
2068}
2069
2070async fn complete_controlled_inbound_tcp_nomination(
2071 sender: &IceSocketWrapper,
2072 addr: SocketAddr,
2073 inner: Arc<IceTransportInner>,
2074) {
2075 if *inner.role.lock() != IceRole::Controlled {
2076 return;
2077 }
2078 let IceSocketWrapper::TcpStream(read, _, _) = sender else {
2079 return;
2080 };
2081 if inner.nomination_complete.borrow().is_some() {
2082 if let Some(pair) = inner.selected_pair.lock().clone() {
2083 publish_selected_socket(&inner, &pair, Some(sender));
2084 }
2085 return;
2086 }
2087
2088 let local_addr: SocketAddr = {
2089 let s = read.lock().await;
2090 s.local_addr()
2091 .unwrap_or_else(|_| "0.0.0.0:0".parse().unwrap())
2092 };
2093
2094 let locals = inner.gatherer.local_candidates();
2095 let local_cand = locals.iter().find(|c| {
2096 c.base_address() == local_addr
2097 || (c.transport == "tcp"
2098 && c.base_address().port() == local_addr.port()
2099 && (c.base_address().ip().is_unspecified() || local_addr.ip().is_unspecified()))
2100 });
2101
2102 let pair = {
2103 let remotes = inner.remote_candidates.lock();
2104 let remote_cand = remotes.iter().find(|c| c.address == addr);
2105 if let (Some(l), Some(r)) = (local_cand, remote_cand) {
2106 Some(IceCandidatePair::new(l.clone(), r.clone()))
2107 } else {
2108 None
2109 }
2110 };
2111
2112 if let Some(pair) = pair {
2113 trace!(
2114 "Controlled agent selected pair via inbound TCP nomination: {} -> {}",
2115 pair.local.address, pair.remote.address
2116 );
2117 *inner.selected_pair.lock() = Some(pair.clone());
2118 let _ = inner.selected_pair_notifier.send(Some(pair.clone()));
2119 publish_selected_socket(&inner, &pair, Some(sender));
2120 let _ = inner.state.send(IceTransportState::Connected);
2121 } else {
2122 debug!(
2123 "Inbound TCP nomination: synthesizing pair for {} -> {}",
2124 local_addr, addr
2125 );
2126 let local_cand = locals.iter().find(|c| {
2127 c.transport == "tcp"
2128 && c.tcp_type == Some(TcpType::Passive)
2129 && (c.base_address().port() == local_addr.port()
2130 || c.address.port() == local_addr.port())
2131 });
2132 let remote_cand = {
2133 let remotes = inner.remote_candidates.lock();
2134 remotes.iter().find(|c| c.address == addr).cloned()
2135 };
2136 if let (Some(l), Some(r)) = (local_cand, remote_cand) {
2137 let pair = IceCandidatePair::new(l.clone(), r.clone());
2138 *inner.selected_pair.lock() = Some(pair.clone());
2139 let _ = inner.selected_pair_notifier.send(Some(pair.clone()));
2140 publish_selected_socket(&inner, &pair, Some(sender));
2141 let _ = inner.state.send(IceTransportState::Connected);
2142 } else {
2143 let _ = inner.selected_socket.send(Some(sender.clone()));
2144 publish_selected_rtcp_socket(&inner, Some(sender.clone()));
2145 }
2146 }
2147 let _ = inner.nomination_complete.send(Some(true));
2148 let pair_summary = inner
2149 .selected_pair
2150 .lock()
2151 .as_ref()
2152 .map(|p| format!("{} -> {}", p.local.address, p.remote.address))
2153 .unwrap_or_else(|| format!("(no pair) peer={addr}"));
2154 debug!(
2155 peer = %addr,
2156 local_bind = %local_addr,
2157 pair = %pair_summary,
2158 socket = %sender.diag(),
2159 "ICE: passive TCP nomination complete"
2160 );
2161}
2162
2163fn resolve_rtcp_socket(inner: &IceTransportInner) -> Option<IceSocketWrapper> {
2164 let candidate = inner
2165 .gatherer
2166 .local_candidates()
2167 .into_iter()
2168 .find(|candidate| candidate.component == 2)?;
2169
2170 if candidate.typ == IceCandidateType::Relay {
2171 let clients = inner.gatherer.turn_clients.lock();
2172 clients
2173 .get(&candidate.address)
2174 .map(|client| IceSocketWrapper::Turn(client.clone(), candidate.address))
2175 } else if candidate.transport == "tcp" {
2176 inner.gatherer.get_tcp_socket(candidate.base_address())
2177 } else {
2178 let socket = inner.gatherer.get_socket(candidate.base_address());
2179 if socket.is_none() {
2180 debug!(
2181 "resolve_rtcp_socket: failed to find socket for {}",
2182 candidate.base_address()
2183 );
2184 }
2185 socket.map(IceSocketWrapper::Udp)
2186 }
2187}
2188
2189fn publish_selected_rtcp_socket(inner: &IceTransportInner, fallback: Option<IceSocketWrapper>) {
2190 if let Some(socket) = resolve_rtcp_socket(inner).or(fallback) {
2191 let _ = inner.selected_rtcp_socket.send(Some(socket));
2192 }
2193}
2194
2195async fn bind_direct_rtcp_socket(
2196 inner: &IceTransportInner,
2197 rtp_base: SocketAddr,
2198 advertised_ip: IpAddr,
2199) -> Result<(Arc<UdpSocket>, IceCandidate)> {
2200 let rtcp_bind_addr = rtp_base
2201 .port()
2202 .checked_add(1)
2203 .map(|port| SocketAddr::new(rtp_base.ip(), port));
2204 let rtcp = if let Some(addr) = rtcp_bind_addr {
2205 match UdpSocket::bind(addr).await {
2206 Ok(socket) => socket,
2207 Err(err) => {
2208 debug!(
2209 "Failed to bind RTCP socket on {}, falling back to ephemeral port: {}",
2210 addr, err
2211 );
2212 UdpSocket::bind(SocketAddr::new(rtp_base.ip(), 0)).await?
2213 }
2214 }
2215 } else {
2216 UdpSocket::bind(SocketAddr::new(rtp_base.ip(), 0)).await?
2217 };
2218 let local_rtcp_addr = rtcp.local_addr()?;
2219 let rtcp = Arc::new(rtcp);
2220 inner.gatherer.sockets.lock().push(rtcp.clone());
2221 let _ = inner
2222 .gatherer
2223 .socket_tx
2224 .send(IceSocketWrapper::Udp(rtcp.clone()));
2225
2226 let mut rtcp_cand_addr = local_rtcp_addr;
2227 rtcp_cand_addr.set_ip(advertised_ip);
2228 let mut candidate = IceCandidate::host(rtcp_cand_addr, 2);
2229 if rtcp_cand_addr != local_rtcp_addr {
2230 candidate.related_address = Some(local_rtcp_addr);
2231 }
2232 Ok((rtcp, candidate))
2233}
2234
2235async fn handle_packet(
2236 packet: &[u8],
2237 addr: SocketAddr,
2238 inner: Arc<IceTransportInner>,
2239 sender: IceSocketWrapper,
2240 marshal_buf: &mut Vec<u8>,
2241) {
2242 if should_drop_packet() {
2243 return;
2244 }
2245 inner.last_received_nanos.store(
2246 inner.created_at.elapsed().as_nanos() as u64,
2247 Ordering::Relaxed,
2248 );
2249 let b = packet[0];
2250 if b < 2 {
2251 match StunMessage::decode(packet) {
2253 Ok(msg) => {
2254 if msg.class == StunClass::Request {
2255 handle_stun_request(&sender, &msg, addr, inner).await;
2265 } else if msg.class == StunClass::SuccessResponse {
2266 let mut map = inner.pending_transactions.lock();
2267 if let Some(tx) = map.remove(&msg.transaction_id) {
2268 let _ = tx.send(msg);
2269 } else {
2270 trace!(
2271 "Unmatched transaction {:?} Pending transactions: {:?}",
2272 msg.transaction_id,
2273 map.keys()
2274 );
2275 }
2276 } else if msg.class == StunClass::ErrorResponse {
2277 trace!("Received STUN Error Response from {}", addr);
2278 debug!(
2279 "Received STUN Error Response from {}: {:?}",
2280 addr, msg.error_code
2281 );
2282 if let Some(code) = msg.error_code {
2283 if code == 401 {
2284 let remote_params = inner.remote_parameters.lock().clone();
2285 debug!(
2286 "STUN 401 received. Current remote params: {:?}",
2287 remote_params
2288 );
2289 }
2290 trace!("Error code: {}", code);
2291 }
2292 let mut map = inner.pending_transactions.lock();
2296 if let Some(tx) = map.remove(&msg.transaction_id) {
2297 let _ = tx.send(msg);
2298 }
2299 }
2300 }
2301 Err(e) => {
2302 debug!("Failed to decode STUN packet from {}: {}", addr, e);
2303 }
2304 }
2305 } else {
2306 let receiver = inner.data_receiver.lock().clone();
2308 if let Some(rx) = receiver {
2309 rx.receive(Bytes::copy_from_slice(packet), addr, marshal_buf)
2310 .await;
2311 } else {
2312 let mut buffer = inner.buffered_packets.lock();
2313 let stats = inner.buffer_stats.clone();
2314 let capacity = inner.config.rtp_buffer_capacity;
2315
2316 stats.packets_received.fetch_add(1, Ordering::Relaxed);
2317
2318 if buffer.len() >= capacity {
2319 match inner.config.buffer_drop_strategy {
2320 BufferDropStrategy::DropOldest => {
2321 buffer.pop_front();
2322 buffer.push_back((packet.to_vec(), addr));
2323 }
2324 BufferDropStrategy::DropNew => {
2325 let dropped = stats.packets_dropped.load(Ordering::Relaxed);
2329 if dropped == 0 || dropped.is_multiple_of(1000) {
2330 tracing::warn!(src = %addr, capacity, "RTP buffer full — dropping inbound packet (DropNew strategy)");
2331 }
2332 }
2333 }
2334 stats.packets_dropped.fetch_add(1, Ordering::Relaxed);
2335 } else {
2336 buffer.push_back((packet.to_vec(), addr));
2337 }
2338
2339 let current_size = buffer.len() as u32;
2341 stats.current_size.store(current_size, Ordering::Relaxed);
2342
2343 let mut peak = stats.peak_size.load(Ordering::Relaxed);
2345 while current_size > peak {
2346 match stats.peak_size.compare_exchange_weak(
2347 peak,
2348 current_size,
2349 Ordering::Relaxed,
2350 Ordering::Relaxed,
2351 ) {
2352 Ok(_) => break,
2353 Err(current) => peak = current,
2354 }
2355 }
2356
2357 let mut last_log = stats.last_log_time.lock();
2359 if last_log.elapsed() >= inner.config.buffer_stats_log_interval {
2360 let received = stats.packets_received.load(Ordering::Relaxed);
2361 let dropped = stats.packets_dropped.load(Ordering::Relaxed);
2362 let peak_size = stats.peak_size.load(Ordering::Relaxed);
2363 trace!(
2364 "Buffer stats: received={}, dropped={}, current={}, peak={}, capacity={}",
2365 received, dropped, current_size, peak_size, capacity
2366 );
2367 *last_log = Instant::now();
2368 }
2369 }
2370 }
2371}
2372
2373async fn handle_stun_request(
2374 sender: &IceSocketWrapper,
2375 msg: &StunDecoded,
2376 addr: SocketAddr,
2377 inner: Arc<IceTransportInner>,
2378) {
2379 let response = StunMessage::binding_success_response(msg.transaction_id, addr);
2380
2381 #[cfg(any(test, feature = "simulator"))]
2382 simulate_stun_respond_delay(sender).await;
2383
2384 let password = inner.local_parameters.lock().password.clone();
2385 if let Ok(bytes) = response.encode(Some(password.as_bytes()), true) {
2386 match sender.send_to(&bytes, addr).await {
2387 Ok(_) => trace!("Sent STUN Response to {}", addr),
2388 Err(e) => {
2389 if let Some(io_err) = e.downcast_ref::<std::io::Error>() {
2390 match io_err.kind() {
2391 std::io::ErrorKind::HostUnreachable
2392 | std::io::ErrorKind::NetworkUnreachable => {
2393 debug!("Failed to send STUN Response to {}: {}", addr, e);
2394 }
2395 _ => {
2396 if io_err.raw_os_error() == Some(65)
2397 || io_err.raw_os_error() == Some(49)
2398 {
2399 debug!("Failed to send STUN Response to {}: {}", addr, e);
2400 } else {
2401 debug!("Failed to send STUN Response to {}: {}", addr, e);
2402 }
2403 }
2404 }
2405 } else {
2406 debug!("Failed to send STUN Response to {}: {}", addr, e);
2407 }
2408 }
2409 }
2410 } else {
2411 debug!("Failed to encode STUN Response");
2412 }
2413
2414 let mut known = false;
2416 {
2417 let remotes = inner.remote_candidates.lock();
2418 for cand in remotes.iter() {
2419 if cand.address == addr {
2420 known = true;
2421 break;
2422 }
2423 }
2424 }
2425
2426 if !known {
2427 debug!("Discovered peer reflexive candidate: {}", addr);
2428 let transport = match sender {
2429 IceSocketWrapper::Udp(_) | IceSocketWrapper::SharedUdp(_) => "udp",
2430 IceSocketWrapper::TcpListener(_) | IceSocketWrapper::TcpStream(_, _, _) => "tcp",
2431 IceSocketWrapper::Turn(_, _) => "udp",
2432 };
2433 let mut candidate = IceCandidate::host(addr, 1); candidate.typ = IceCandidateType::PeerReflexive;
2435 candidate.transport = transport.to_string();
2436 candidate.foundation = IceCandidate::compute_foundation(
2437 IceCandidateType::PeerReflexive,
2438 candidate.base_address(),
2439 transport,
2440 );
2441 candidate.priority = if transport == "tcp" {
2442 IceCandidate::priority_for_tcp(IceCandidateType::PeerReflexive, 1, TcpType::Passive)
2443 } else {
2444 IceCandidate::priority_for(IceCandidateType::PeerReflexive, 1)
2445 };
2446
2447 let mut list = inner.remote_candidates.lock();
2448 list.push(candidate);
2449 drop(list);
2450
2451 let _ = inner.cmd_tx.send(IceCommand::RunChecks);
2452 }
2453 if inner.config.enable_latching
2461 && inner.config.transport_mode != crate::TransportMode::WebRtc
2462 {
2463 let current_pair = inner.selected_pair.lock().clone();
2464 if let Some(pair) = current_pair
2465 && pair.remote.address.port() == addr.port()
2466 && pair.remote.address.ip() != addr.ip()
2467 {
2468 debug!(
2469 "RTP latching: updating remote address from {} to {}",
2470 pair.remote.address, addr
2471 );
2472 let mut new_remote = pair.remote.clone();
2473 new_remote.address = addr;
2474 let new_pair = IceCandidatePair::new(pair.local.clone(), new_remote);
2475 *inner.selected_pair.lock() = Some(new_pair.clone());
2476 let _ = inner.selected_pair_notifier.send(Some(new_pair.clone()));
2477 publish_selected_socket(&inner, &new_pair, Some(sender));
2478 }
2479 }
2480
2481 complete_controlled_inbound_tcp_nomination(sender, addr, inner.clone()).await;
2482
2483 if msg.use_candidate {
2484 let role = *inner.role.lock();
2485 if role == IceRole::Controlled {
2486 if matches!(sender, IceSocketWrapper::TcpStream(_, _, _)) {
2488 return;
2489 }
2490 let already_nominated = inner.nomination_complete.borrow().is_some();
2501 let local_addr: SocketAddr = match sender {
2509 IceSocketWrapper::Udp(s) => s
2510 .local_addr()
2511 .unwrap_or_else(|_| "0.0.0.0:0".parse().unwrap()),
2512 IceSocketWrapper::SharedUdp(h) => h
2513 .local_addr()
2514 .unwrap_or_else(|_| "0.0.0.0:0".parse().unwrap()),
2515 IceSocketWrapper::TcpListener(l) => l
2516 .local_addr()
2517 .unwrap_or_else(|_| "0.0.0.0:0".parse().unwrap()),
2518 IceSocketWrapper::TcpStream(read, _, _) => {
2519 let s = read.lock().await;
2520 s.local_addr()
2521 .unwrap_or_else(|_| "0.0.0.0:0".parse().unwrap())
2522 }
2523 IceSocketWrapper::Turn(_, addr) => *addr,
2524 };
2525
2526 let locals = inner.gatherer.local_candidates();
2527 let local_cand = locals.iter().find(|c| c.base_address() == local_addr);
2528
2529 let pair = {
2530 let remotes = inner.remote_candidates.lock();
2531 let remote_cand = remotes.iter().find(|c| c.address == addr);
2532 if let (Some(l), Some(r)) = (local_cand, remote_cand) {
2533 Some(IceCandidatePair::new(l.clone(), r.clone()))
2534 } else {
2535 None
2536 }
2537 };
2538
2539 if let Some(pair) = pair {
2540 let should_select = {
2541 let selected = inner.selected_pair.lock();
2542 match selected.as_ref() {
2543 Some(cur) => {
2544 let same = cur.local.address == pair.local.address
2545 && cur.remote.address == pair.remote.address;
2546 if same {
2547 false
2548 } else if already_nominated {
2549 debug!(
2559 "Ignoring post-nomination UseCandidate {} -> {} (frozen on {} -> {})",
2560 pair.local.address,
2561 pair.remote.address,
2562 cur.local.address,
2563 cur.remote.address
2564 );
2565 false
2566 } else {
2567 true
2568 }
2569 }
2570 None => true,
2571 }
2572 };
2573 if should_select {
2574 debug!(
2575 "Controlled agent selected pair via UseCandidate: {} -> {}",
2576 pair.local.address, pair.remote.address
2577 );
2578 *inner.selected_pair.lock() = Some(pair.clone());
2579 let _ = inner.selected_pair_notifier.send(Some(pair.clone()));
2580 publish_selected_socket(&inner, &pair, Some(sender));
2581 } else {
2582 trace!(
2583 "Controlled agent keeping current pair (UseCandidate {} -> {})",
2584 pair.local.address, pair.remote.address
2585 );
2586 }
2587 let _ = inner.state.send(IceTransportState::Connected);
2588 let _ = inner.nomination_complete.send(Some(true));
2589 } else {
2590 debug!(
2591 "Received UseCandidate but could not find UDP pair for {} -> {}",
2592 local_addr, addr
2593 );
2594 let _ = inner.nomination_complete.send(Some(true));
2595 }
2596 }
2597 }
2598}
2599
2600struct TransactionGuard<'a> {
2601 map: &'a parking_lot::Mutex<HashMap<[u8; 12], oneshot::Sender<StunDecoded>>>,
2602 tx_id: [u8; 12],
2603}
2604
2605impl<'a> Drop for TransactionGuard<'a> {
2606 fn drop(&mut self) {
2607 let mut map = self.map.lock();
2609 map.remove(&self.tx_id);
2610 }
2611}
2612
2613async fn perform_binding_check(
2614 local: &IceCandidate,
2615 remote: &IceCandidate,
2616 inner: &Arc<IceTransportInner>,
2617 role: IceRole,
2618 nominated: bool,
2619) -> Result<()> {
2620 if local.transport == "tcp" && remote.transport == "tcp" {
2622 return perform_tcp_binding_check(local, remote, inner, role, nominated).await;
2623 }
2624
2625 if role == IceRole::Controlled && local.transport == "tcp" {
2627 return Ok(());
2628 }
2629
2630 if remote.transport != "udp" {
2632 bail!("only UDP connectivity checks are supported");
2633 }
2634
2635 let local_params = inner.local_parameters.lock().clone();
2636 let remote_params = match inner.remote_parameters.lock().clone() {
2637 Some(p) => p,
2638 None => bail!("no remote params"),
2639 };
2640
2641 let tx_id = random_bytes::<12>();
2642 let mut msg = StunMessage::binding_request(tx_id, Some("rustrtc"));
2645 let username = format!(
2646 "{}:{}",
2647 remote_params.username_fragment, local_params.username_fragment
2648 );
2649 msg.attributes.push(StunAttribute::Username(username));
2650 msg.attributes.push(StunAttribute::Priority(local.priority));
2651 match role {
2652 IceRole::Controlling => {
2653 msg.attributes
2654 .push(StunAttribute::IceControlling(local_params.tie_breaker));
2655 if nominated {
2656 msg.attributes.push(StunAttribute::UseCandidate);
2657 }
2658 }
2659 IceRole::Controlled => msg
2660 .attributes
2661 .push(StunAttribute::IceControlled(local_params.tie_breaker)),
2662 }
2663 let bytes = msg.encode(Some(remote_params.password.as_bytes()), true)?;
2664
2665 let (tx, mut rx) = oneshot::channel();
2666 {
2667 let mut map = inner.pending_transactions.lock();
2668 map.insert(tx_id, tx);
2669 }
2670
2671 let _guard = TransactionGuard {
2673 map: &inner.pending_transactions,
2674 tx_id,
2675 };
2676
2677 let (socket, turn_client) = if local.typ == IceCandidateType::Relay {
2678 let gatherer = &inner.gatherer;
2679 let clients = gatherer.turn_clients.lock();
2680 let client = clients.get(&local.address).cloned();
2681 (None, client)
2682 } else {
2683 let socket = inner.gatherer.get_socket(local.base_address());
2684 (socket, None)
2685 };
2686
2687 if local.typ == IceCandidateType::Relay {
2688 let client = turn_client
2689 .as_ref()
2690 .ok_or_else(|| anyhow!("TURN client not found for relay candidate"))?;
2691
2692 let (perm_bytes, perm_tx_id) = client.create_permission_packet(remote.address).await?;
2693
2694 let (perm_tx, perm_rx) = oneshot::channel();
2695 {
2696 let mut map = inner.pending_transactions.lock();
2697 map.insert(perm_tx_id, perm_tx);
2698 }
2699
2700 trace!("Sending CreatePermission to TURN server");
2701 if let Err(e) = client.send(&perm_bytes).await {
2702 debug!("CreatePermission send failed: {}", e);
2703 return Err(e);
2704 }
2705
2706 match timeout(inner.config.stun_timeout, perm_rx).await {
2707 Ok(Ok(msg)) => {
2708 if msg.class == StunClass::ErrorResponse {
2709 bail!("CreatePermission failed: {:?}", msg.error_code);
2710 }
2711
2712 if client.get_channel(remote.address).await.is_none()
2714 && let Ok((bind_bytes, bind_tx_id, channel_num)) =
2715 client.create_channel_bind_packet(remote.address).await
2716 {
2717 let (bind_tx, bind_rx) = oneshot::channel();
2718 {
2719 let mut map = inner.pending_transactions.lock();
2720 map.insert(bind_tx_id, bind_tx);
2721 }
2722
2723 if client.send(&bind_bytes).await.is_ok() {
2724 let client_clone = client.clone();
2725 let remote_addr = remote.address;
2726 let inner_weak = Arc::downgrade(inner);
2727 let timeout_dur = inner.config.stun_timeout;
2728
2729 match timeout(timeout_dur, bind_rx).await {
2730 Ok(Ok(msg)) => {
2731 if msg.class == StunClass::SuccessResponse {
2732 client_clone.add_channel(remote_addr, channel_num).await;
2733 }
2734 }
2735 _ => {
2736 if let Some(inner) = inner_weak.upgrade() {
2738 let mut map = inner.pending_transactions.lock();
2739 map.remove(&bind_tx_id);
2740 }
2741 }
2742 }
2743 }
2744 }
2745 }
2746 _ => {
2747 let mut map = inner.pending_transactions.lock();
2748 map.remove(&perm_tx_id);
2749 bail!("CreatePermission timeout");
2750 }
2751 }
2752 } else if socket.is_none() {
2753 bail!("no socket found for local candidate");
2754 }
2755
2756 let start = Instant::now();
2757 let mut rto = Duration::from_millis(500);
2758 let max_timeout = if nominated {
2759 inner.config.nomination_timeout
2760 } else {
2761 inner.config.stun_timeout
2762 };
2763
2764 loop {
2765 if let Some(client) = &turn_client {
2766 let sent = if let Some(channel) = client.get_channel(remote.address).await {
2767 client.send_channel_data(channel, &bytes).await
2768 } else {
2769 client.send_indication(remote.address, &bytes).await
2770 };
2771
2772 if let Err(e) = sent {
2773 debug!("TURN send failed: {}", e);
2774 return Err(e);
2775 }
2776 } else if local.transport == "tcp" {
2777 let tcp_stream = match TcpStream::connect(remote.address).await {
2779 Ok(stream) => {
2780 stream.set_nodelay(true).ok();
2781 stream
2782 }
2783 Err(e) => {
2784 debug!("TCP connect to {} failed: {}", remote.address, e);
2785 return Err(e.into());
2786 }
2787 };
2788 use tokio::io::{AsyncReadExt, AsyncWriteExt};
2789 let mut tcp_stream = tcp_stream;
2790 let mut framed = Vec::with_capacity(2 + bytes.len());
2791 let flen = bytes.len() as u16;
2792 framed.extend_from_slice(&flen.to_be_bytes());
2793 framed.extend_from_slice(&bytes);
2794 tcp_stream.write_all(&framed).await?;
2795 match timeout(inner.config.stun_timeout, async {
2797 let mut len_buf = [0u8; 2];
2798 tcp_stream.read_exact(&mut len_buf).await?;
2799 let resp_len = u16::from_be_bytes(len_buf) as usize;
2800 let mut resp_buf = vec![0u8; resp_len];
2801 tcp_stream.read_exact(&mut resp_buf).await?;
2802 StunMessage::decode(&resp_buf).map_err(|e| anyhow!(e))
2803 })
2804 .await
2805 {
2806 Ok(Ok(parsed)) => {
2807 if parsed.class == StunClass::SuccessResponse {
2808 return Ok(());
2809 }
2810 return Err(anyhow!("TCP binding check failed: unexpected response"));
2811 }
2812 Ok(Err(e)) => return Err(e),
2813 Err(_) => return Err(anyhow!("TCP binding check timeout")),
2814 }
2815 } else if let Some(socket) = &socket
2816 && let Err(e) = socket.send_to(&bytes, remote.address).await
2817 {
2818 let is_fatal = matches!(
2819 e.kind(),
2820 std::io::ErrorKind::BrokenPipe
2821 | std::io::ErrorKind::ConnectionReset
2822 | std::io::ErrorKind::NotConnected
2823 );
2824 if is_fatal {
2825 debug!(
2826 "socket.send_to {} fatal error, aborting nomination: {}",
2827 remote.address, e
2828 );
2829 return Err(e.into());
2830 }
2831 }
2834
2835 let timeout_fut = tokio::time::sleep(max_timeout.saturating_sub(start.elapsed()));
2836 let rto_fut = tokio::time::sleep(rto);
2837
2838 tokio::select! {
2839 res = &mut rx => {
2840 let parsed = match res {
2841 Ok(msg) => msg,
2842 Err(_) => bail!("channel closed"),
2843 };
2844
2845 if parsed.transaction_id != tx_id {
2846 bail!("binding response transaction mismatch");
2847 }
2848 if parsed.method != StunMethod::Binding {
2849 bail!("unexpected STUN method in binding response");
2850 }
2851 if parsed.class != StunClass::SuccessResponse {
2852 bail!("binding request failed");
2853 }
2854 return Ok(());
2855 }
2856 _ = timeout_fut => {
2857 bail!("timeout");
2858 }
2859 _ = rto_fut => {
2860 if start.elapsed() >= max_timeout {
2861 continue;
2862 }
2863 trace!("Retransmitting STUN Request to {} tx={:?}", remote.address, tx_id);
2864 rto = std::cmp::min(rto * 2, Duration::from_millis(1600));
2865 }
2866 }
2867 }
2868}
2869
2870fn frame_stun_for_tcp(data: &[u8]) -> Vec<u8> {
2880 let len = data.len() as u16;
2881 let mut framed = Vec::with_capacity(2 + data.len());
2882 framed.extend_from_slice(&len.to_be_bytes());
2883 framed.extend_from_slice(data);
2884 framed
2885}
2886
2887type TcpReadHalf = tokio::net::tcp::OwnedReadHalf;
2888type TcpWriteHalf = tokio::net::tcp::OwnedWriteHalf;
2889
2890fn split_tcp_stream(stream: TcpStream, peer: SocketAddr) -> IceSocketWrapper {
2891 if let Err(e) = stream.set_nodelay(true) {
2892 debug!("TCP set_nodelay failed: {}", e);
2893 }
2894 let (read, write) = stream.into_split();
2895 IceSocketWrapper::TcpStream(
2896 Arc::new(Mutex::new(read)),
2897 Arc::new(Mutex::new(write)),
2898 peer,
2899 )
2900}
2901
2902pub(crate) async fn attach_demuxed_tcp_stream(
2903 inner: Arc<IceTransportInner>,
2904 stream: TcpStream,
2905 peer_addr: SocketAddr,
2906 listen_addr: SocketAddr,
2907 first_packet: Vec<u8>,
2908) {
2909 let wrapper = split_tcp_stream(stream, peer_addr);
2910 inner
2911 .gatherer
2912 .store_tcp_stream(listen_addr, wrapper.clone());
2913 let _ = inner.gatherer.socket_tx.send(wrapper.clone());
2914 let mut marshal_buf = Vec::new();
2915 handle_packet(&first_packet, peer_addr, inner, wrapper, &mut marshal_buf).await;
2916}
2917
2918pub(crate) async fn tcp_write_all(write: &Arc<Mutex<TcpWriteHalf>>, data: &[u8]) -> Result<()> {
2919 let mut offset = 0;
2920 while offset < data.len() {
2921 let guard = write.lock().await;
2922 loop {
2923 match guard.try_write(&data[offset..]) {
2924 Ok(0) => guard.writable().await?,
2925 Ok(n) => {
2926 offset += n;
2927 break;
2928 }
2929 Err(e) if e.kind() == ErrorKind::WouldBlock => guard.writable().await?,
2930 Err(e) => return Err(anyhow!("TCP write failed: {}", e)),
2931 }
2932 }
2933 }
2934 Ok(())
2935}
2936
2937async fn perform_tcp_binding_check(
2938 local: &IceCandidate,
2939 remote: &IceCandidate,
2940 inner: &Arc<IceTransportInner>,
2941 role: IceRole,
2942 nominated: bool,
2943) -> Result<()> {
2944 debug!(
2945 "perform_tcp_binding_check: {} -> {}",
2946 local.address, remote.address
2947 );
2948 let local_params = inner.local_parameters.lock().clone();
2949 let remote_params = match inner.remote_parameters.lock().clone() {
2950 Some(p) => p,
2951 None => bail!("no remote params"),
2952 };
2953
2954 let tx_id = random_bytes::<12>();
2955 let mut msg = StunMessage::binding_request(tx_id, Some("rustrtc"));
2956 let username = format!(
2957 "{}:{}",
2958 remote_params.username_fragment, local_params.username_fragment
2959 );
2960 msg.attributes.push(StunAttribute::Username(username));
2961 msg.attributes.push(StunAttribute::Priority(local.priority));
2962 match role {
2963 IceRole::Controlling => {
2964 msg.attributes
2965 .push(StunAttribute::IceControlling(local_params.tie_breaker));
2966 if nominated {
2967 msg.attributes.push(StunAttribute::UseCandidate);
2968 }
2969 }
2970 IceRole::Controlled => msg
2971 .attributes
2972 .push(StunAttribute::IceControlled(local_params.tie_breaker)),
2973 }
2974 let bytes = msg.encode(Some(remote_params.password.as_bytes()), true)?;
2975
2976 let connect_timeout = inner.config.stun_timeout;
2978 let stream = timeout(connect_timeout, TcpStream::connect(remote.address))
2979 .await
2980 .map_err(|_| anyhow!("TCP connect timeout to {}", remote.address))?
2981 .map_err(|e| anyhow!("TCP connect to {} failed: {}", remote.address, e))?;
2982
2983 let local_addr = stream.local_addr()?;
2984 let wrapper = split_tcp_stream(stream, remote.address);
2985 let write = match &wrapper {
2986 IceSocketWrapper::TcpStream(_, write, _) => write.clone(),
2987 _ => bail!("split_tcp_stream invariant"),
2988 };
2989
2990 inner.gatherer.store_tcp_stream(local_addr, wrapper.clone());
2992 let _ = inner.gatherer.socket_tx.send(wrapper);
2993
2994 let (tx, mut rx) = oneshot::channel();
2996 {
2997 let mut map = inner.pending_transactions.lock();
2998 map.insert(tx_id, tx);
2999 }
3000 let _guard = TransactionGuard {
3001 map: &inner.pending_transactions,
3002 tx_id,
3003 };
3004
3005 {
3007 let framed = frame_stun_for_tcp(&bytes);
3008 tcp_write_all(&write, &framed).await?;
3009 }
3010
3011 let start = Instant::now();
3013 let mut rto = Duration::from_millis(500);
3014 let max_timeout = if nominated {
3015 inner.config.nomination_timeout
3016 } else {
3017 inner.config.stun_timeout
3018 };
3019
3020 loop {
3021 let timeout_fut = tokio::time::sleep(max_timeout.saturating_sub(start.elapsed()));
3022 let rto_fut = tokio::time::sleep(rto);
3023
3024 tokio::select! {
3025 res = &mut rx => {
3026 let parsed = match res {
3027 Ok(msg) => msg,
3028 Err(_) => bail!("channel closed"),
3029 };
3030 if parsed.transaction_id != tx_id {
3031 bail!("binding response transaction mismatch");
3032 }
3033 if parsed.method != StunMethod::Binding {
3034 bail!("unexpected STUN method in binding response");
3035 }
3036 if parsed.class != StunClass::SuccessResponse {
3037 bail!("binding request failed");
3038 }
3039 return Ok(());
3040 }
3041 _ = timeout_fut => {
3042 bail!("timeout");
3043 }
3044 _ = rto_fut => {
3045 if start.elapsed() >= max_timeout {
3046 continue;
3047 }
3048 trace!("TCP Retransmitting STUN Request to {} tx={:?}", remote.address, tx_id);
3049 rto = std::cmp::min(rto * 2, Duration::from_millis(1600));
3050 let framed = frame_stun_for_tcp(&bytes);
3051 let _ = tcp_write_all(&write, &framed).await;
3052 }
3053 }
3054 }
3055}
3056
3057#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3058pub enum IceTransportState {
3059 New,
3060 Checking,
3061 Connected,
3062 Completed,
3063 Failed,
3064 Disconnected,
3065 Closed,
3066}
3067
3068#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3069pub enum IceGathererState {
3070 New,
3071 Gathering,
3072 Complete,
3073}
3074
3075#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3076pub enum IceRole {
3077 Controlling,
3078 Controlled,
3079}
3080
3081#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3083pub enum TcpType {
3084 Active,
3085 Passive,
3086 So,
3087}
3088
3089impl TcpType {
3090 fn as_str(&self) -> &'static str {
3091 match self {
3092 TcpType::Active => "active",
3093 TcpType::Passive => "passive",
3094 TcpType::So => "so",
3095 }
3096 }
3097
3098 fn from_str(s: &str) -> Option<Self> {
3099 match s {
3100 "active" => Some(TcpType::Active),
3101 "passive" => Some(TcpType::Passive),
3102 "so" => Some(TcpType::So),
3103 _ => None,
3104 }
3105 }
3106}
3107
3108#[derive(Debug, Clone, PartialEq, Eq)]
3109pub struct IceCandidate {
3110 pub foundation: String,
3111 pub priority: u32,
3112 pub address: SocketAddr,
3113 pub typ: IceCandidateType,
3114 pub transport: String,
3115 pub tcp_type: Option<TcpType>,
3116 pub related_address: Option<SocketAddr>,
3117 pub component: u16,
3118}
3119
3120impl IceCandidate {
3121 fn compute_foundation(typ: IceCandidateType, base_addr: SocketAddr, transport: &str) -> String {
3122 use std::collections::hash_map::DefaultHasher;
3123 use std::hash::{Hash, Hasher};
3124
3125 let mut hasher = DefaultHasher::new();
3126 typ.hash(&mut hasher);
3127 base_addr.ip().hash(&mut hasher);
3128 transport.hash(&mut hasher);
3129 format!("{:x}", hasher.finish())
3130 }
3131
3132 pub fn with_tcp_type(mut self, tcp_type: TcpType) -> Self {
3134 self.tcp_type = Some(tcp_type);
3135 self.transport = "tcp".into();
3136 self
3137 }
3138
3139 pub fn host(address: SocketAddr, component: u16) -> Self {
3140 Self {
3141 foundation: Self::compute_foundation(IceCandidateType::Host, address, "udp"),
3142 priority: IceCandidate::priority_for(IceCandidateType::Host, component),
3143 address,
3144 typ: IceCandidateType::Host,
3145 transport: "udp".into(),
3146 tcp_type: None,
3147 related_address: None,
3148 component,
3149 }
3150 }
3151
3152 pub fn host_tcp(address: SocketAddr, component: u16, tcp_type: TcpType) -> Self {
3153 Self {
3154 foundation: Self::compute_foundation(IceCandidateType::Host, address, "tcp"),
3155 priority: IceCandidate::priority_for_tcp(IceCandidateType::Host, component, tcp_type),
3156 address,
3157 typ: IceCandidateType::Host,
3158 transport: "tcp".into(),
3159 tcp_type: Some(tcp_type),
3160 related_address: None,
3161 component,
3162 }
3163 }
3164
3165 pub fn tcp(address: SocketAddr, component: u16, tcptype_str: &str) -> Self {
3166 let transport = "tcp";
3167 let tcp_type = TcpType::from_str(tcptype_str).unwrap_or(TcpType::Passive);
3168 Self {
3169 foundation: Self::compute_foundation(IceCandidateType::Host, address, transport),
3170 priority: IceCandidate::priority_for_tcp(IceCandidateType::Host, component, tcp_type),
3171 address,
3172 typ: IceCandidateType::Host,
3173 transport: transport.into(),
3174 tcp_type: Some(tcp_type),
3175 related_address: None,
3176 component,
3177 }
3178 }
3179
3180 pub fn base_address(&self) -> SocketAddr {
3181 if self.typ == IceCandidateType::ServerReflexive || self.typ == IceCandidateType::Host {
3182 self.related_address.unwrap_or(self.address)
3183 } else {
3184 self.address
3185 }
3186 }
3187
3188 fn server_reflexive(base: SocketAddr, mapped: SocketAddr, component: u16) -> Self {
3189 Self {
3190 foundation: Self::compute_foundation(IceCandidateType::ServerReflexive, base, "udp"),
3191 priority: IceCandidate::priority_for(IceCandidateType::ServerReflexive, component),
3192 address: mapped,
3193 typ: IceCandidateType::ServerReflexive,
3194 transport: "udp".into(),
3195 tcp_type: None,
3196 related_address: Some(base),
3197 component,
3198 }
3199 }
3200
3201 fn relay(mapped: SocketAddr, component: u16, transport: &str) -> Self {
3202 Self {
3203 foundation: Self::compute_foundation(IceCandidateType::Relay, mapped, transport),
3204 priority: IceCandidate::priority_for(IceCandidateType::Relay, component),
3205 address: mapped,
3206 typ: IceCandidateType::Relay,
3207 transport: transport.into(),
3208 tcp_type: None,
3209 related_address: None,
3210 component,
3211 }
3212 }
3213
3214 fn priority_for(typ: IceCandidateType, component: u16) -> u32 {
3215 let type_pref = match typ {
3216 IceCandidateType::Host => 126u32,
3217 IceCandidateType::PeerReflexive => 110u32,
3218 IceCandidateType::ServerReflexive => 100u32,
3219 IceCandidateType::Relay => 0u32,
3220 };
3221 let local_pref = 65_535u32;
3222 let component = component.min(256) as u32;
3223 (type_pref << 24) | (local_pref << 8) | (256 - component)
3224 }
3225
3226 fn priority_for_tcp(typ: IceCandidateType, component: u16, tcp_type: TcpType) -> u32 {
3231 let type_pref = match typ {
3232 IceCandidateType::Host => 126u32,
3233 IceCandidateType::PeerReflexive => 110u32,
3234 IceCandidateType::ServerReflexive => 100u32,
3235 IceCandidateType::Relay => 0u32,
3236 };
3237 let local_pref = match tcp_type {
3239 TcpType::Passive => 65535u32,
3240 TcpType::Active => 65534u32,
3241 TcpType::So => 65533u32,
3242 };
3243 let component = component.min(256) as u32;
3244 (type_pref << 24) | (local_pref << 8) | (256 - component)
3245 }
3246
3247 pub fn to_sdp(&self) -> String {
3248 let mut parts = vec![
3249 self.foundation.clone(),
3250 self.component.to_string(),
3251 self.transport.to_ascii_lowercase(),
3252 self.priority.to_string(),
3253 self.address.ip().to_string(),
3254 self.address.port().to_string(),
3255 "typ".into(),
3256 self.typ.as_str().into(),
3257 ];
3258 if let Some(tcp_type) = self.tcp_type {
3259 parts.push("tcptype".into());
3260 parts.push(tcp_type.as_str().into());
3261 }
3262 if let Some(addr) = self.related_address
3263 && self.typ != IceCandidateType::Host
3264 {
3265 parts.push("raddr".into());
3266 parts.push(addr.ip().to_string());
3267 parts.push("rport".into());
3268 parts.push(addr.port().to_string());
3269 }
3270 parts.join(" ")
3271 }
3272
3273 pub fn from_sdp(sdp: &str) -> Result<Self> {
3274 let parts: Vec<&str> = sdp.split_whitespace().collect();
3275 if parts.len() < 8 {
3276 bail!("invalid candidate");
3277 }
3278 let start_idx = 0;
3280
3281 let foundation = parts[start_idx]
3282 .trim_start_matches("candidate:")
3283 .to_string();
3284 let component = parts[start_idx + 1].parse::<u16>()?;
3285 let transport = parts[start_idx + 2].to_ascii_lowercase();
3286 let priority = parts[start_idx + 3].parse::<u32>()?;
3287 let ip_str = parts[start_idx + 4];
3288 let port = parts[start_idx + 5].parse::<u16>()?;
3289 let typ_str = parts[start_idx + 7];
3290
3291 let address = if ip_str.contains(':') {
3293 format!("[{}]:{}", ip_str, port).parse()?
3294 } else {
3295 format!("{}:{}", ip_str, port).parse()?
3296 };
3297
3298 let typ = match typ_str {
3299 "host" => IceCandidateType::Host,
3300 "srflx" => IceCandidateType::ServerReflexive,
3301 "prflx" => IceCandidateType::PeerReflexive,
3302 "relay" => IceCandidateType::Relay,
3303 _ => bail!("unknown type"),
3304 };
3305
3306 let tcp_type = if transport == "tcp" {
3308 let mut i = 8;
3310 loop {
3311 if i + 1 >= parts.len() {
3312 break None;
3313 }
3314 match parts[i] {
3315 "tcptype" => {
3316 break TcpType::from_str(parts[i + 1]);
3317 }
3318 _ => {
3319 i += 2;
3320 }
3321 }
3322 }
3323 } else {
3324 None
3325 };
3326
3327 Ok(Self {
3328 foundation,
3329 priority,
3330 address,
3331 typ,
3332 transport,
3333 tcp_type,
3334 related_address: None,
3335 component,
3336 })
3337 }
3338}
3339
3340#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3341pub enum IceCandidateType {
3342 Host,
3343 ServerReflexive,
3344 PeerReflexive,
3345 Relay,
3346}
3347
3348impl IceCandidateType {
3349 fn as_str(&self) -> &'static str {
3350 match self {
3351 IceCandidateType::Host => "host",
3352 IceCandidateType::ServerReflexive => "srflx",
3353 IceCandidateType::PeerReflexive => "prflx",
3354 IceCandidateType::Relay => "relay",
3355 }
3356 }
3357}
3358
3359#[derive(Debug, Clone, PartialEq, Eq)]
3360pub struct IceCandidatePair {
3361 pub local: IceCandidate,
3362 pub remote: IceCandidate,
3363 pub nominated: bool,
3364}
3365
3366impl IceCandidatePair {
3367 pub fn new(local: IceCandidate, remote: IceCandidate) -> Self {
3368 Self {
3369 local,
3370 remote,
3371 nominated: false,
3372 }
3373 }
3374
3375 pub fn priority(&self, role: IceRole) -> u64 {
3376 let g = self.local.priority as u64;
3377 let d = self.remote.priority as u64;
3378 let (g, d) = match role {
3379 IceRole::Controlling => (g, d),
3380 IceRole::Controlled => (d, g),
3381 };
3382 (1u64 << 32) * std::cmp::min(g, d) + 2 * std::cmp::max(g, d) + if g > d { 1 } else { 0 }
3383 }
3384}
3385
3386#[derive(Debug, Clone)]
3387pub struct IceParameters {
3388 pub username_fragment: String,
3389 pub password: String,
3390 pub ice_lite: bool,
3391 pub tie_breaker: u64,
3392}
3393
3394impl IceParameters {
3395 pub fn new(username_fragment: impl Into<String>, password: impl Into<String>) -> Self {
3396 Self {
3397 username_fragment: username_fragment.into(),
3398 password: password.into(),
3399 ice_lite: false,
3400 tie_breaker: random_u64(),
3401 }
3402 }
3403
3404 fn generate() -> Self {
3405 let ufrag = hex_encode(&random_bytes::<8>());
3406 let pwd = hex_encode(&random_bytes::<16>());
3407 Self {
3408 username_fragment: ufrag,
3409 password: pwd,
3410 ice_lite: false,
3411 tie_breaker: random_u64(),
3412 }
3413 }
3414}
3415
3416#[derive(Debug, Clone)]
3417pub struct IceTransportBuilder {
3418 config: RtcConfiguration,
3419 role: IceRole,
3420 servers: Vec<IceServer>,
3421}
3422
3423impl IceTransportBuilder {
3424 pub fn new(config: RtcConfiguration) -> Self {
3425 Self {
3426 config,
3427 role: IceRole::Controlled,
3428 servers: Vec::new(),
3429 }
3430 }
3431
3432 pub fn role(mut self, role: IceRole) -> Self {
3433 self.role = role;
3434 self
3435 }
3436
3437 pub fn server(mut self, server: IceServer) -> Self {
3438 self.servers.push(server);
3439 self
3440 }
3441
3442 pub fn build(self) -> (IceTransport, impl std::future::Future<Output = ()> + Send) {
3443 let mut config = self.config.clone();
3444 config.ice_servers.extend(self.servers);
3445 let (transport, runner) = IceTransport::new(config);
3446 transport.set_role(self.role);
3447 if let Err(err) = transport.start_gathering() {
3448 debug!("ICE gather failed: {}", err);
3449 }
3450 (transport, runner)
3451 }
3452}
3453
3454#[derive(Debug, Clone)]
3455struct IceGatherer {
3456 state: Arc<parking_lot::Mutex<IceGathererState>>,
3457 local_candidates: Arc<parking_lot::Mutex<Vec<IceCandidate>>>,
3458 sockets: Arc<parking_lot::Mutex<Vec<Arc<UdpSocket>>>>,
3459 tcp_listeners: Arc<parking_lot::Mutex<Vec<Arc<TcpListener>>>>,
3460 tcp_streams: Arc<parking_lot::Mutex<HashMap<SocketAddr, IceSocketWrapper>>>,
3461 shared_tcp_regs: Arc<parking_lot::Mutex<Vec<shared_tcp::SharedTcpRegistration>>>,
3462 shared_udp_regs: Arc<parking_lot::Mutex<Vec<shared_udp::SharedUdpRegistration>>>,
3463 shared_udp_socket: Arc<parking_lot::Mutex<Option<IceSocketWrapper>>>,
3466 transport_inner: Arc<parking_lot::Mutex<Option<std::sync::Weak<IceTransportInner>>>>,
3467 turn_clients: Arc<parking_lot::Mutex<HashMap<SocketAddr, Arc<TurnClient>>>>,
3468 upnp_mappers: Arc<parking_lot::Mutex<Vec<UpnpPortMapper>>>,
3469 config: RtcConfiguration,
3470 candidate_tx: broadcast::Sender<IceCandidate>,
3471 socket_tx: tokio::sync::mpsc::UnboundedSender<IceSocketWrapper>,
3472}
3473
3474impl IceGatherer {
3475 fn new(
3476 config: RtcConfiguration,
3477 candidate_tx: broadcast::Sender<IceCandidate>,
3478 socket_tx: tokio::sync::mpsc::UnboundedSender<IceSocketWrapper>,
3479 ) -> Self {
3480 Self {
3481 state: Arc::new(parking_lot::Mutex::new(IceGathererState::New)),
3482 local_candidates: Arc::new(parking_lot::Mutex::new(Vec::new())),
3483 sockets: Arc::new(parking_lot::Mutex::new(Vec::new())),
3484 tcp_listeners: Arc::new(parking_lot::Mutex::new(Vec::new())),
3485 tcp_streams: Arc::new(parking_lot::Mutex::new(HashMap::new())),
3486 shared_tcp_regs: Arc::new(parking_lot::Mutex::new(Vec::new())),
3487 shared_udp_regs: Arc::new(parking_lot::Mutex::new(Vec::new())),
3488 shared_udp_socket: Arc::new(parking_lot::Mutex::new(None)),
3489 transport_inner: Arc::new(parking_lot::Mutex::new(None)),
3490 turn_clients: Arc::new(parking_lot::Mutex::new(HashMap::new())),
3491 upnp_mappers: Arc::new(parking_lot::Mutex::new(Vec::new())),
3492 config,
3493 candidate_tx,
3494 socket_tx,
3495 }
3496 }
3497
3498 fn set_transport(&self, inner: std::sync::Weak<IceTransportInner>) {
3499 *self.transport_inner.lock() = Some(inner);
3500 }
3501
3502 fn push_tcp_passive_candidate(&self, local_addr: SocketAddr, bind_ip: IpAddr) {
3503 if let Some(ext_ip) = &self.config.external_ip
3504 && let Ok(parsed_ip) = ext_ip.parse::<IpAddr>()
3505 {
3506 if !bind_ip.is_loopback() {
3507 let mut ext_addr = local_addr;
3508 ext_addr.set_ip(parsed_ip);
3509 let mut cand = IceCandidate::tcp(ext_addr, 1, "passive");
3510 cand.related_address = Some(local_addr);
3511 self.push_candidate(cand);
3512 } else {
3513 self.push_candidate(IceCandidate::tcp(local_addr, 1, "passive"));
3514 }
3515 } else if bind_ip.is_unspecified() {
3516 let mut cand_addr = local_addr;
3517 if let Ok(local_ip) = get_local_ip() {
3518 cand_addr.set_ip(local_ip);
3519 }
3520 let mut cand = IceCandidate::tcp(cand_addr, 1, "passive");
3521 cand.related_address = Some(local_addr);
3522 self.push_candidate(cand);
3523 } else {
3524 self.push_candidate(IceCandidate::tcp(local_addr, 1, "passive"));
3525 }
3526 }
3527
3528 #[allow(dead_code)]
3530 pub fn upnp_mappers(&self) -> Arc<parking_lot::Mutex<Vec<UpnpPortMapper>>> {
3531 self.upnp_mappers.clone()
3532 }
3533
3534 #[allow(dead_code)]
3536 pub async fn cleanup_upnp_mappings(&self) {
3537 let mappers = self.upnp_mappers.lock().clone();
3538 for mapper in mappers {
3539 if let Err(e) = mapper.cleanup().await {
3540 trace!("Failed to clean up UPnP mappings: {}", e);
3541 }
3542 }
3543 self.upnp_mappers.lock().clear();
3544 }
3545
3546 pub async fn renew_upnp_mappings(&self) {
3552 let mappers = self.upnp_mappers.lock().clone();
3553 for mapper in mappers {
3554 if let Err(e) = mapper.renew_all_stale().await {
3555 warn!("Failed to refresh UPnP mappings: {}", e);
3556 }
3557 }
3558 }
3559
3560 fn state(&self) -> IceGathererState {
3561 *self.state.lock()
3562 }
3563
3564 fn local_candidates(&self) -> Vec<IceCandidate> {
3565 self.local_candidates.lock().clone()
3566 }
3567
3568 async fn bind_socket(&self, ip: IpAddr) -> Result<UdpSocket> {
3569 if let (Some(start), Some(end)) = (self.config.rtp_start_port, self.config.rtp_end_port) {
3570 let start = start.saturating_add(start % 2);
3571 let end = end - (end % 2);
3572
3573 if start > end {
3574 bail!("No usable even RTP ports in range {}..={}", start, end);
3575 }
3576
3577 let port_count = (((end - start) / 2) + 1) as u64;
3578 let start_index = (random_u64() % port_count) as u16;
3579 let mut port = start + (start_index * 2);
3580
3581 for _ in 0..port_count {
3582 match UdpSocket::bind(SocketAddr::new(ip, port)).await {
3583 Ok(socket) => return Ok(socket),
3584 Err(_) => {
3585 port = port.saturating_add(2);
3586 if port > end {
3587 port = start;
3588 }
3589 }
3590 }
3591 }
3592 bail!("No available even RTP ports in range {}..={}", start, end)
3593 } else {
3594 UdpSocket::bind(SocketAddr::new(ip, 0))
3595 .await
3596 .map_err(|e| anyhow!(e))
3597 }
3598 }
3599
3600 fn get_socket(&self, addr: SocketAddr) -> Option<Arc<UdpSocket>> {
3601 let found = {
3602 let sockets = self.sockets.lock();
3603 sockets.iter().find_map(|socket| {
3604 let local = socket.local_addr().ok()?;
3605 let matches =
3606 local == addr || (local.ip().is_unspecified() && local.port() == addr.port());
3607 matches.then(|| socket.clone())
3608 })
3609 };
3610 if let Some(s) = found {
3611 return Some(s);
3612 }
3613 if let Some(IceSocketWrapper::SharedUdp(handle)) = self.shared_udp_socket.lock().clone()
3617 && let Ok(local) = handle.local_addr()
3618 && (local == addr || (local.ip().is_unspecified() && local.port() == addr.port()))
3619 {
3620 return Some(handle.socket().clone());
3621 }
3622 let available: Vec<String> = self
3624 .sockets
3625 .lock()
3626 .iter()
3627 .map(|s| {
3628 s.local_addr()
3629 .map(|a| a.to_string())
3630 .unwrap_or_else(|_| "error".to_string())
3631 })
3632 .collect();
3633 trace!(
3634 "get_socket: no socket found for {}, available: {:?}",
3635 addr, available
3636 );
3637 None
3638 }
3639
3640 fn get_tcp_socket(&self, addr: SocketAddr) -> Option<IceSocketWrapper> {
3641 let streams = self.tcp_streams.lock();
3642 for (local_addr, wrapper) in streams.iter() {
3643 if *local_addr == addr {
3644 return Some(wrapper.clone());
3645 }
3646 if local_addr.ip().is_unspecified() && local_addr.port() == addr.port() {
3648 return Some(wrapper.clone());
3649 }
3650 }
3651 trace!(
3652 "get_tcp_socket: no TCP stream found for {}, available: {:?}",
3653 addr,
3654 streams.keys().collect::<Vec<_>>()
3655 );
3656 None
3657 }
3658
3659 fn store_tcp_stream(&self, local_addr: SocketAddr, wrapper: IceSocketWrapper) {
3660 self.tcp_streams.lock().insert(local_addr, wrapper);
3661 }
3662
3663 #[instrument(skip(self))]
3664 async fn gather(&self) -> Result<()> {
3665 {
3666 let mut state = self.state.lock();
3667 if *state == IceGathererState::Complete {
3668 return Ok(());
3669 }
3670 *state = IceGathererState::Gathering;
3671 }
3672
3673 let host_fut = async {
3675 if self.config.ice_transport_policy == IceTransportPolicy::All {
3676 if self.config.ice_gather_udp_hosts {
3677 if let Err(e) = self.gather_host_candidates().await {
3678 debug!("Host gathering failed: {}", e);
3679 }
3680 } else if self.config.ice_tcp_policy == crate::config::IceTcpPolicy::Enabled {
3681 let has_tcp_listen_range = match (
3685 self.config.tcp_port_range_start,
3686 self.config.tcp_port_range_end,
3687 ) {
3688 (Some(s), Some(e)) => s > 0 && e > 0 && s <= e,
3689 _ => false,
3690 };
3691 if !has_tcp_listen_range
3692 && let Err(e) = self.gather_tcp_active_candidates().await
3693 {
3694 debug!("TCP active gathering failed: {}", e);
3695 }
3696 }
3697 }
3698 };
3699
3700 host_fut.await;
3701
3702 if (self.config.tcp_port_range_start.is_some() || self.config.tcp_port_range_end.is_some())
3704 && let Err(e) = self.gather_tcp_host_candidates().await
3705 {
3706 debug!("TCP host gathering failed: {}", e);
3707 }
3708
3709 let stun_public_ip = if self.config.enable_upnp {
3715 timeout(Duration::from_secs(5), self.gather_servers_and_get_public_ip())
3716 .await
3717 .unwrap_or_else(|_| {
3718 debug!("STUN/TURN gathering timed out after 5s, skipping UPnP double-NAT detection");
3719 None
3720 })
3721 } else {
3722 if let Err(e) = self.gather_servers().await {
3723 debug!("Server gathering failed: {}", e);
3724 }
3725 None
3726 };
3727
3728 if self.config.enable_upnp
3730 && self.config.ice_transport_policy == IceTransportPolicy::All
3731 && let Err(e) = self.gather_upnp_candidates(stun_public_ip).await
3732 {
3733 debug!("UPnP gathering failed: {}", e);
3734 }
3735
3736 *self.state.lock() = IceGathererState::Complete;
3737 Ok(())
3738 }
3739
3740 async fn gather_shared_udp_host_candidate(&self) -> Result<()> {
3745 let port = self
3746 .config
3747 .ice_udp_mux_port
3748 .ok_or_else(|| anyhow!("ice_udp_mux is enabled but ice_udp_mux_port is not set"))?;
3749
3750 let bind_ip = if let Some(bind_ip_str) = &self.config.bind_ip {
3751 bind_ip_str
3752 .parse::<IpAddr>()
3753 .with_context(|| format!("invalid bind_ip {}", bind_ip_str))?
3754 } else {
3755 IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED)
3758 };
3759
3760 if self.config.disable_ipv6 && bind_ip.is_ipv6() {
3761 bail!("disable_ipv6 is set but bind_ip is IPv6");
3762 }
3763
3764 let bind_addr = SocketAddr::new(bind_ip, port);
3765
3766 let inner = self
3767 .transport_inner
3768 .lock()
3769 .as_ref()
3770 .and_then(|weak| weak.upgrade())
3771 .context("ICE transport unavailable during shared UDP gather")?;
3772 let ufrag = inner.local_parameters.lock().username_fragment.clone();
3773
3774 let (local_addr, handle, registration) = shared_udp::acquire(bind_addr, ufrag).await?;
3775
3776 self.shared_udp_regs.lock().push(registration);
3777
3778 let wrapper = IceSocketWrapper::SharedUdp(Arc::new(handle));
3779 *self.shared_udp_socket.lock() = Some(wrapper.clone());
3780 let _ = self.socket_tx.send(wrapper);
3781
3782 let mut cand_addr = local_addr;
3784 if let Some(ext_ip) = &self.config.external_ip
3785 && let Ok(parsed_ip) = ext_ip.parse::<IpAddr>()
3786 {
3787 if !bind_ip.is_loopback() {
3788 cand_addr.set_ip(parsed_ip);
3789 }
3790 } else if bind_ip.is_unspecified()
3791 && let Ok(local_ip) = get_local_ip()
3792 {
3793 cand_addr.set_ip(local_ip);
3794 }
3795
3796 let mut cand = IceCandidate::host(cand_addr, 1);
3797 if cand_addr != local_addr {
3798 cand.related_address = Some(local_addr);
3799 }
3800 self.push_candidate(cand);
3801 Ok(())
3802 }
3803
3804 async fn gather_host_candidates(&self) -> Result<()> {
3805 let mut bind_ips = Vec::new();
3806
3807 if let Some(bind_ip_str) = &self.config.bind_ip {
3808 if let Ok(ip) = bind_ip_str.parse::<IpAddr>() {
3809 bind_ips.push(ip);
3810 }
3811 } else if self.config.transport_mode != crate::TransportMode::WebRtc {
3812 if let Ok(ip) = get_local_ip() {
3816 bind_ips.push(ip);
3817 } else {
3818 bind_ips.push(IpAddr::V4(std::net::Ipv4Addr::UNSPECIFIED));
3819 }
3820 } else {
3821 if self.config.ice_include_loopback_candidates {
3825 bind_ips.push(IpAddr::V4(std::net::Ipv4Addr::LOCALHOST));
3826 }
3827
3828 use local_ip_address::list_afinet_netifas;
3829 if let Ok(interfaces) = list_afinet_netifas() {
3830 for (name, addr) in interfaces {
3831 if let IpAddr::V4(ip) = addr
3832 && !ip.is_loopback()
3833 && !bind_ips.contains(&IpAddr::V4(ip))
3834 {
3835 if name.starts_with("utun")
3837 || name.starts_with("gif")
3838 || name.starts_with("stf")
3839 || name.starts_with("awdl")
3840 || name.starts_with("llw")
3841 {
3842 continue;
3843 }
3844 bind_ips.push(IpAddr::V4(ip));
3845 }
3846 }
3847 }
3848 }
3849
3850 if self.config.ice_udp_mux
3851 && let Err(e) = self.gather_shared_udp_host_candidate().await
3852 {
3853 debug!("Shared UDP mux host candidate failed: {}", e);
3854 }
3855
3856 for ip in &bind_ips {
3857 let ip = *ip;
3858 if self.config.ice_udp_mux {
3861 continue;
3862 }
3863 match self.bind_socket(ip).await {
3864 Ok(socket) => {
3865 if let Ok(addr) = socket.local_addr() {
3866 let socket = Arc::new(socket);
3867 self.sockets.lock().push(socket.clone());
3868 let _ = self.socket_tx.send(IceSocketWrapper::Udp(socket));
3869
3870 if let Some(ext_ip) = &self.config.external_ip
3871 && let Ok(parsed_ip) = ext_ip.parse::<IpAddr>()
3872 {
3873 if !ip.is_loopback() {
3874 let mut ext_addr = addr;
3875 ext_addr.set_ip(parsed_ip);
3876 let mut cand = IceCandidate::host(ext_addr, 1);
3877 cand.related_address = Some(addr);
3878 self.push_candidate(cand);
3879 } else {
3880 self.push_candidate(IceCandidate::host(addr, 1));
3881 }
3882 } else if ip.is_unspecified() {
3883 let mut cand_addr = addr;
3885 if let Ok(local_ip) = get_local_ip() {
3886 cand_addr.set_ip(local_ip);
3887 }
3888 let mut cand = IceCandidate::host(cand_addr, 1);
3889 cand.related_address = Some(addr);
3890 self.push_candidate(cand);
3891 } else {
3892 self.push_candidate(IceCandidate::host(addr, 1));
3893 }
3894 }
3895 }
3896 Err(e) => {
3897 if self.config.bind_ip.is_some() {
3898 debug!("Failed to bind to requested bind_ip {}: {}", ip, e);
3899 } else if !ip.is_loopback() && !ip.is_unspecified() {
3900 debug!("Failed to bind socket on {}: {}", ip, e);
3901 }
3902 }
3903 }
3904 }
3905
3906 if self.config.ice_tcp_policy != crate::config::IceTcpPolicy::Disabled {
3908 for ip in &bind_ips {
3909 let ip = *ip;
3910 match TcpListener::bind(SocketAddr::new(ip, 0)).await {
3911 Ok(listener) => {
3912 if let Ok(addr) = listener.local_addr() {
3913 let listener = Arc::new(listener);
3914 self.tcp_listeners.lock().push(listener.clone());
3915 let _ = self.socket_tx.send(IceSocketWrapper::TcpListener(listener));
3916
3917 let tcp_type = TcpType::Passive;
3918 let mut cand = IceCandidate::host_tcp(addr, 1, tcp_type);
3919 if ip.is_unspecified()
3920 && let Ok(local_ip) = get_local_ip()
3921 {
3922 let mut cand_addr = addr;
3923 cand_addr.set_ip(local_ip);
3924 let mut ext_cand = IceCandidate::host_tcp(cand_addr, 1, tcp_type);
3925 ext_cand.related_address = Some(addr);
3926 cand = ext_cand;
3927 }
3928 self.push_candidate(cand);
3929 }
3930 }
3931 Err(e) => {
3932 debug!("Failed to bind TCP listener on {}: {}", ip, e);
3933 }
3934 }
3935 }
3936 }
3937
3938 Ok(())
3939 }
3940
3941 async fn gather_tcp_active_candidates(&self) -> Result<()> {
3945 use std::net::{IpAddr, Ipv4Addr};
3946
3947 const ACTIVE_PLACEHOLDER_PORT: u16 = 9;
3948
3949 let mut bind_ips = Vec::new();
3950 if self.config.ice_include_loopback_candidates {
3951 bind_ips.push(IpAddr::V4(Ipv4Addr::LOCALHOST));
3952 }
3953 if let Ok(local_ip) = get_local_ip()
3954 && !bind_ips.contains(&local_ip)
3955 {
3956 bind_ips.push(local_ip);
3957 }
3958
3959 for ip in bind_ips {
3960 self.push_candidate(IceCandidate::tcp(
3961 SocketAddr::new(ip, ACTIVE_PLACEHOLDER_PORT),
3962 1,
3963 "active",
3964 ));
3965 }
3966 self.push_candidate(IceCandidate::tcp(
3967 SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), ACTIVE_PLACEHOLDER_PORT),
3968 1,
3969 "active",
3970 ));
3971 Ok(())
3972 }
3973
3974 async fn gather_tcp_host_candidates(&self) -> Result<()> {
3975 let start = self.config.tcp_port_range_start.unwrap_or(0);
3976 let end = self.config.tcp_port_range_end.unwrap_or(0);
3977
3978 if start == 0 || end == 0 || start > end {
3979 return Ok(());
3980 }
3981
3982 let bind_ips = if let Some(bind_ip_str) = &self.config.bind_ip {
3983 if let Ok(ip) = bind_ip_str.parse::<IpAddr>() {
3984 vec![ip]
3985 } else {
3986 return Ok(());
3987 }
3988 } else {
3989 let mut ips = Vec::new();
3990 if self.config.ice_include_loopback_candidates {
3991 ips.push(IpAddr::V4(std::net::Ipv4Addr::LOCALHOST));
3992 }
3993 use local_ip_address::list_afinet_netifas;
3994 if let Ok(interfaces) = list_afinet_netifas() {
3995 for (name, addr) in interfaces {
3996 if let IpAddr::V4(ip) = addr
3997 && !ip.is_loopback()
3998 && !ips.contains(&IpAddr::V4(ip))
3999 {
4000 if name.starts_with("utun")
4001 || name.starts_with("gif")
4002 || name.starts_with("stf")
4003 || name.starts_with("awdl")
4004 || name.starts_with("llw")
4005 {
4006 continue;
4007 }
4008 ips.push(IpAddr::V4(ip));
4009 }
4010 }
4011 }
4012 ips
4013 };
4014
4015 let use_shared_listener = start == end;
4019
4020 for ip in bind_ips {
4021 if use_shared_listener {
4022 let addr = SocketAddr::new(ip, start);
4023 let inner = self
4024 .transport_inner
4025 .lock()
4026 .as_ref()
4027 .and_then(|weak| weak.upgrade())
4028 .context("ICE transport unavailable during TCP gather")?;
4029 let ufrag = inner.local_parameters.lock().username_fragment.clone();
4030 match shared_tcp::acquire(addr, ufrag, Arc::downgrade(&inner)).await {
4031 Ok((local_addr, registration)) => {
4032 self.shared_tcp_regs.lock().push(registration);
4033 self.push_tcp_passive_candidate(local_addr, ip);
4034 break;
4035 }
4036 Err(e) => {
4037 debug!("shared TCP listener acquire on {} failed: {}", addr, e);
4038 }
4039 }
4040 continue;
4041 }
4042
4043 for port in start..=end {
4044 let addr = SocketAddr::new(ip, port);
4045 match TcpListener::bind(addr).await {
4046 Ok(listener) => {
4047 let local_addr = match listener.local_addr() {
4048 Ok(a) => a,
4049 Err(_) => continue,
4050 };
4051 let listener = Arc::new(listener);
4052 self.tcp_listeners.lock().push(listener.clone());
4053 let _ = self.socket_tx.send(IceSocketWrapper::TcpListener(listener));
4054
4055 self.push_tcp_passive_candidate(local_addr, ip);
4056 break;
4057 }
4058 Err(_) => continue,
4059 }
4060 }
4061 }
4062
4063 Ok(())
4064 }
4065
4066 async fn gather_upnp_candidates(&self, stun_public_ip: Option<IpAddr>) -> Result<()> {
4067 let sockets = self.sockets.lock().clone();
4068 let timeout = self.config.upnp_discovery_timeout;
4069 let mut tasks = FuturesUnordered::new();
4070
4071 for socket in sockets {
4072 let local_addr = match socket.local_addr() {
4073 Ok(addr) => addr,
4074 Err(_) => continue,
4075 };
4076
4077 if local_addr.ip().is_loopback() {
4079 continue;
4080 }
4081
4082 if local_addr.is_ipv6() {
4084 continue;
4085 }
4086
4087 let this = self.clone();
4088 let stun_ip = stun_public_ip;
4089 tasks.push(async move {
4090 let mut mapper = UpnpPortMapper::with_lease_duration(
4092 local_addr,
4093 this.config.upnp_lease_duration,
4094 );
4095
4096 if let Err(e) = mapper.discover_with_timeout(timeout).await {
4098 trace!("UPnP discovery failed for {}: {}", local_addr, e);
4099 return;
4100 }
4101
4102 match mapper.add_mapping(0).await {
4104 Ok(external_addr) => {
4105 let is_private = is_private_ip(&external_addr.ip());
4107
4108 let candidate_addr = if is_private {
4110 if let Some(public_ip) = stun_ip {
4111 let mut addr = external_addr;
4112 addr.set_ip(public_ip);
4113 debug!(
4114 "UPnP double-NAT detected: {} is private, using STUN public IP {} -> {}",
4115 external_addr.ip(),
4116 public_ip,
4117 addr
4118 );
4119 addr
4120 } else {
4121 debug!(
4122 "UPnP returned private IP {} but no STUN public IP available",
4123 external_addr.ip()
4124 );
4125 external_addr
4126 }
4127 } else {
4128 external_addr
4129 };
4130
4131 let candidate =
4133 IceCandidate::server_reflexive(local_addr, candidate_addr, 1);
4134 this.push_candidate(candidate);
4135
4136 this.upnp_mappers.lock().push(mapper);
4138
4139 debug!(
4140 "UPnP candidate gathered: {} -> {}",
4141 local_addr, candidate_addr
4142 );
4143 }
4144 Err(e) => {
4145 debug!("UPnP mapping failed for {}: {}", local_addr, e);
4146 }
4147 }
4148 });
4149 }
4150
4151 while tasks.next().await.is_some() {}
4152
4153 Ok(())
4154 }
4155
4156 async fn gather_servers(&self) -> Result<()> {
4157 let mut tasks = FuturesUnordered::new();
4158
4159 for server in &self.config.ice_servers {
4160 for url in &server.urls {
4161 let server = server.clone();
4162 let url = url.clone();
4163 let this = self.clone();
4164
4165 tasks.push(async move {
4166 let uri = match IceServerUri::parse(&url) {
4167 Ok(uri) => uri,
4168 Err(err) => {
4169 debug!("invalid ICE server URI {}: {}", url, err);
4170 return;
4171 }
4172 };
4173
4174 match uri.kind {
4175 IceUriKind::Stun => {
4176 if this.config.ice_transport_policy == IceTransportPolicy::All {
4177 match this.probe_stun(&uri).await {
4178 Ok(Some(candidate)) => this.push_candidate(candidate),
4179 Ok(None) => {}
4180 Err(e) => debug!("STUN probe failed for {}: {}", url, e),
4181 }
4182 }
4183 }
4184 IceUriKind::Turn => match this.probe_turn(&uri, &server).await {
4185 Ok(Some(candidate)) => this.push_candidate(candidate),
4186 Ok(None) => {}
4187 Err(e) => debug!("TURN probe failed for {}: {}", url, e),
4188 },
4189 }
4190 });
4191 }
4192 }
4193
4194 while tasks.next().await.is_some() {}
4195 Ok(())
4196 }
4197
4198 async fn gather_servers_and_get_public_ip(&self) -> Option<IpAddr> {
4201 let mut tasks = FuturesUnordered::new();
4202 let public_ip: Arc<parking_lot::Mutex<Option<IpAddr>>> =
4203 Arc::new(parking_lot::Mutex::new(None));
4204
4205 for server in &self.config.ice_servers {
4206 for url in &server.urls {
4207 let server = server.clone();
4208 let url = url.clone();
4209 let this = self.clone();
4210 let public_ip_clone = public_ip.clone();
4211
4212 tasks.push(async move {
4213 let uri = match IceServerUri::parse(&url) {
4214 Ok(uri) => uri,
4215 Err(err) => {
4216 debug!("invalid ICE server URI {}: {}", url, err);
4217 return;
4218 }
4219 };
4220
4221 match uri.kind {
4222 IceUriKind::Stun => {
4223 if this.config.ice_transport_policy == IceTransportPolicy::All {
4224 match this.probe_stun(&uri).await {
4225 Ok(Some(candidate)) => {
4226 if !is_private_ip(&candidate.address.ip()) {
4228 let mut ip = public_ip_clone.lock();
4229 if ip.is_none() {
4230 *ip = Some(candidate.address.ip());
4231 }
4232 }
4233 this.push_candidate(candidate);
4234 }
4235 Ok(None) => {}
4236 Err(e) => debug!("STUN probe failed for {}: {}", url, e),
4237 }
4238 }
4239 }
4240 IceUriKind::Turn => match this.probe_turn(&uri, &server).await {
4241 Ok(Some(candidate)) => this.push_candidate(candidate),
4242 Ok(None) => {}
4243 Err(e) => debug!("TURN probe failed for {}: {}", url, e),
4244 },
4245 }
4246 });
4247 }
4248 }
4249
4250 while tasks.next().await.is_some() {}
4251 let ip = *public_ip.lock();
4252 if let Some(ip) = &ip {
4253 debug!("STUN public IP for UPnP double-NAT detection: {}", ip);
4254 } else {
4255 debug!("No STUN public IP available for UPnP double-NAT detection");
4256 }
4257 ip
4258 }
4259
4260 async fn probe_stun(&self, uri: &IceServerUri) -> Result<Option<IceCandidate>> {
4261 let addr = uri.resolve(self.config.disable_ipv6).await?;
4262
4263 let bind_ip = if addr.is_ipv6() {
4265 self.local_candidates
4266 .lock()
4267 .iter()
4268 .filter(|c| c.typ == IceCandidateType::Host)
4269 .filter_map(|c| match c.address.ip() {
4270 IpAddr::V6(ip) if !ip.is_loopback() && !ip.is_unspecified() => {
4271 Some(IpAddr::V6(ip))
4272 }
4273 _ => None,
4274 })
4275 .next()
4276 .unwrap_or(IpAddr::V6(std::net::Ipv6Addr::UNSPECIFIED))
4277 } else {
4278 self.local_candidates
4279 .lock()
4280 .iter()
4281 .filter(|c| c.typ == IceCandidateType::Host)
4282 .filter_map(|c| match c.address.ip() {
4283 IpAddr::V4(ip) if !ip.is_loopback() && !ip.is_unspecified() => {
4284 Some(IpAddr::V4(ip))
4285 }
4286 _ => None,
4287 })
4288 .next()
4289 .unwrap_or(IpAddr::V4(std::net::Ipv4Addr::new(0, 0, 0, 0)))
4290 };
4291
4292 let socket = match uri.transport {
4293 IceTransportProtocol::Udp => self.bind_socket(bind_ip).await?,
4294 IceTransportProtocol::Tcp => self.bind_socket(bind_ip).await?,
4295 };
4296 let local_addr = socket.local_addr()?;
4297 let tx_id = random_bytes::<12>();
4298 let message = StunMessage::binding_request(tx_id, Some("rustrtc"));
4299 let bytes = message.encode(None, true)?;
4300 socket.send_to(&bytes, addr).await?;
4301 let mut buf = [0u8; MAX_STUN_MESSAGE];
4302 let (len, from) = timeout(self.config.stun_timeout, socket.recv_from(&mut buf)).await??;
4303 if from.ip() != addr.ip() {
4304 return Ok(None);
4305 }
4306 let parsed = StunMessage::decode(&buf[..len])?;
4307 if let Some(mapped) = parsed.xor_mapped_address {
4308 let socket = Arc::new(socket);
4309 self.sockets.lock().push(socket.clone());
4310 let _ = self.socket_tx.send(IceSocketWrapper::Udp(socket));
4311 return Ok(Some(IceCandidate::server_reflexive(local_addr, mapped, 1)));
4312 }
4313 Ok(None)
4314 }
4315
4316 async fn probe_turn(
4317 &self,
4318 uri: &IceServerUri,
4319 server: &IceServer,
4320 ) -> Result<Option<IceCandidate>> {
4321 let credentials = TurnCredentials::from_server(server)?;
4322 let client = TurnClient::connect(uri, self.config.disable_ipv6).await?;
4323 let allocation = client.allocate(credentials).await?;
4324 let relayed_addr = allocation.relayed_address;
4325 debug!(
4326 "TURN allocation granted: relayed={}, lifetime={}s",
4327 relayed_addr, allocation.lifetime_secs
4328 );
4329
4330 let client = Arc::new(client);
4331 self.turn_clients
4332 .lock()
4333 .insert(relayed_addr, client.clone());
4334 let _ = self
4335 .socket_tx
4336 .send(IceSocketWrapper::Turn(client, relayed_addr));
4337
4338 Ok(Some(IceCandidate::relay(
4339 relayed_addr,
4340 1,
4341 allocation.transport.as_str(),
4342 )))
4343 }
4344
4345 fn push_candidate(&self, candidate: IceCandidate) {
4346 if self.config.disable_ipv6 && candidate.address.is_ipv6() {
4347 return;
4348 }
4349 let mut candidates = self.local_candidates.lock();
4350 if candidates.iter().any(|c| c.address == candidate.address) {
4351 return;
4352 }
4353 tracing::debug!(
4354 "Gathered local candidate: {} type={:?}",
4355 candidate.address,
4356 candidate.typ
4357 );
4358 candidates.push(candidate.clone());
4359 drop(candidates);
4360 let _ = self.candidate_tx.send(candidate);
4361 }
4362}
4363
4364#[derive(Debug, Clone, PartialEq, Eq)]
4365pub(crate) struct IceServerUri {
4366 kind: IceUriKind,
4367 host: String,
4368 port: u16,
4369 transport: IceTransportProtocol,
4370}
4371
4372impl IceServerUri {
4373 fn parse(input: &str) -> Result<Self> {
4374 let (scheme, rest) = input
4375 .split_once(':')
4376 .ok_or_else(|| anyhow!("missing scheme"))?;
4377 let (host_part, query) = match rest.split_once('?') {
4378 Some(parts) => parts,
4379 None => (rest, ""),
4380 };
4381 let (host, port) = if let Some((h, p)) = host_part.rsplit_once(':') {
4382 let port = p.parse::<u16>().context("invalid port")?;
4383 (h.to_string(), port)
4384 } else {
4385 (host_part.to_string(), default_port_for_scheme(scheme)?)
4386 };
4387 let mut transport = default_transport_for_scheme(scheme)?;
4388 if !query.is_empty() {
4389 for pair in query.split('&') {
4390 if let Some((k, v)) = pair.split_once('=')
4391 && k == "transport"
4392 {
4393 transport = match v.to_ascii_lowercase().as_str() {
4394 "udp" => IceTransportProtocol::Udp,
4395 "tcp" => IceTransportProtocol::Tcp,
4396 other => bail!("unsupported transport {}", other),
4397 };
4398 }
4399 }
4400 }
4401 if scheme.starts_with("stun") && query.contains("transport") {
4402 bail!("stun URI must not include transport parameter");
4403 }
4404 let kind = match scheme {
4405 "stun" | "stuns" => IceUriKind::Stun,
4406 "turn" | "turns" => IceUriKind::Turn,
4407 other => bail!("unsupported scheme {}", other),
4408 };
4409 Ok(Self {
4410 kind,
4411 host,
4412 port,
4413 transport,
4414 })
4415 }
4416
4417 async fn resolve(&self, disable_ipv6: bool) -> Result<SocketAddr> {
4418 let target = format!("{}:{}", self.host, self.port);
4419 let addrs = timeout(Duration::from_secs(5), lookup_host(&target))
4420 .await
4421 .map_err(|_| anyhow!("DNS lookup timed out for {}", target))??;
4422
4423 for addr in addrs {
4424 if disable_ipv6 && addr.is_ipv6() {
4425 continue;
4426 }
4427 return Ok(addr);
4428 }
4429 Err(anyhow!(
4430 "{} unresolved (disable_ipv6={})",
4431 self.host,
4432 disable_ipv6
4433 ))
4434 }
4435}
4436
4437#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4438enum IceUriKind {
4439 Stun,
4440 Turn,
4441}
4442
4443#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4444pub(crate) enum IceTransportProtocol {
4445 Udp,
4446 Tcp,
4447}
4448
4449impl IceTransportProtocol {
4450 fn as_str(&self) -> &'static str {
4451 match self {
4452 IceTransportProtocol::Udp => "udp",
4453 IceTransportProtocol::Tcp => "tcp",
4454 }
4455 }
4456}
4457
4458fn default_port_for_scheme(scheme: &str) -> Result<u16> {
4459 Ok(match scheme {
4460 "stun" | "turn" => 3478,
4461 "stuns" | "turns" => 5349,
4462 other => bail!("unsupported scheme {}", other),
4463 })
4464}
4465
4466fn default_transport_for_scheme(scheme: &str) -> Result<IceTransportProtocol> {
4467 Ok(match scheme {
4468 "stun" | "turn" => IceTransportProtocol::Udp,
4469 "stuns" | "turns" => IceTransportProtocol::Tcp,
4470 other => bail!("unsupported scheme {}", other),
4471 })
4472}
4473
4474fn is_private_ip(ip: &IpAddr) -> bool {
4476 match ip {
4477 IpAddr::V4(ipv4) => {
4478 let octets = ipv4.octets();
4479 octets[0] == 10
4481 || (octets[0] == 172 && (16..=31).contains(&octets[1]))
4483 || (octets[0] == 192 && octets[1] == 168)
4485 || (octets[0] == 169 && octets[1] == 254)
4487 || octets[0] == 127
4489 }
4490 IpAddr::V6(ipv6) => {
4491 ipv6.segments()[0] & 0xfe00 == 0xfc00
4493 || ipv6.segments()[0] & 0xffc0 == 0xfe80
4495 || *ipv6 == std::net::Ipv6Addr::LOCALHOST
4497 }
4498 }
4499}
4500
4501fn hex_encode(bytes: &[u8]) -> String {
4502 const TABLE: &[u8; 16] = b"0123456789abcdef";
4503 let mut out = String::with_capacity(bytes.len() * 2);
4504 for byte in bytes {
4505 out.push(TABLE[(byte >> 4) as usize] as char);
4506 out.push(TABLE[(byte & 0x0f) as usize] as char);
4507 }
4508 out
4509}
4510
4511#[derive(Debug, Clone)]
4512pub enum IceSocketWrapper {
4513 Udp(Arc<UdpSocket>),
4514 SharedUdp(Arc<shared_udp::SharedUdpHandle>),
4518 TcpListener(Arc<TcpListener>),
4519 TcpStream(
4520 Arc<Mutex<TcpReadHalf>>,
4521 Arc<Mutex<TcpWriteHalf>>,
4522 SocketAddr,
4523 ),
4524 Turn(Arc<TurnClient>, SocketAddr),
4525}
4526
4527impl IceSocketWrapper {
4528 pub fn diag(&self) -> String {
4530 match self {
4531 IceSocketWrapper::Udp(s) => format!(
4532 "udp:{}",
4533 s.local_addr()
4534 .map(|a| a.to_string())
4535 .unwrap_or_else(|_| "?".into())
4536 ),
4537 IceSocketWrapper::SharedUdp(h) => format!(
4538 "udp-mux:{}",
4539 h.local_addr()
4540 .map(|a| a.to_string())
4541 .unwrap_or_else(|_| "?".into())
4542 ),
4543 IceSocketWrapper::TcpListener(l) => format!(
4544 "tcp-listen:{}",
4545 l.local_addr()
4546 .map(|a| a.to_string())
4547 .unwrap_or_else(|_| "?".into())
4548 ),
4549 IceSocketWrapper::TcpStream(_, _, peer) => format!("tcp-stream:peer={peer}"),
4550 IceSocketWrapper::Turn(_, addr) => format!("turn:{addr}"),
4551 }
4552 }
4553
4554 pub fn try_send_to(&self, data: &[u8], addr: SocketAddr) -> Result<usize> {
4558 match self {
4559 IceSocketWrapper::Udp(s) => match s.try_send_to(data, addr) {
4560 Ok(len) => Ok(len),
4561 Err(e) => {
4562 let reason = match s.local_addr() {
4563 Ok(local) => format!("UDP {} -> {} failed: {}", local, addr, e),
4564 Err(_) => format!("UDP -> {} failed: {}", addr, e),
4565 };
4566 Err(anyhow!(reason))
4567 }
4568 },
4569 IceSocketWrapper::SharedUdp(h) => {
4570 h.register_peer(addr);
4574 match h.socket().try_send_to(data, addr) {
4575 Ok(len) => Ok(len),
4576 Err(e) => {
4577 let reason = match h.local_addr() {
4578 Ok(local) => format!("shared UDP {} -> {} failed: {}", local, addr, e),
4579 Err(_) => format!("shared UDP -> {} failed: {}", addr, e),
4580 };
4581 Err(anyhow!(reason))
4582 }
4583 }
4584 }
4585 _ => Err(anyhow::anyhow!(
4588 "IceSocketWrapper::try_send_to not supported for this transport variant"
4589 )),
4590 }
4591 }
4592
4593 pub async fn send_to(&self, data: &[u8], addr: SocketAddr) -> Result<usize> {
4594 match self {
4595 IceSocketWrapper::Udp(s) => loop {
4596 match s.try_send_to(data, addr) {
4597 Ok(len) => return Ok(len),
4598 Err(e) if e.kind() == ErrorKind::WouldBlock => {
4599 s.writable().await?;
4600 continue;
4601 }
4602 Err(e) => {
4603 if let Some(code) = e.raw_os_error()
4604 && code == 55
4605 {
4606 s.writable().await?;
4607 continue;
4608 }
4609 let reason = anyhow!("UDP {} -> {} failed: {}", s.local_addr()?, addr, e);
4610 return Err(reason);
4611 }
4612 }
4613 },
4614 IceSocketWrapper::SharedUdp(h) => {
4615 let dest = addr;
4616 h.send_to(data, dest).await.map_err(anyhow::Error::from)
4617 }
4618 IceSocketWrapper::TcpListener(_) => {
4619 bail!("send_to not supported on TcpListener")
4620 }
4621 IceSocketWrapper::TcpStream(_, write, _) => {
4622 let len = data.len();
4623 if len > 0xFFFF {
4624 bail!("STUN message too large for TCP framing");
4625 }
4626 let header = (len as u16).to_be_bytes();
4627 let mut framed = Vec::with_capacity(2 + len);
4628 framed.extend_from_slice(&header);
4629 framed.extend_from_slice(data);
4630 tcp_write_all(write, &framed).await?;
4631 Ok(data.len())
4632 }
4633 IceSocketWrapper::Turn(c, _) => {
4634 if let Some(channel) = c.get_channel(addr).await {
4635 c.send_channel_data(channel, data).await?;
4636 } else {
4637 c.send_indication(addr, data).await?;
4638 }
4639 Ok(data.len())
4640 }
4641 }
4642 }
4643
4644 pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
4645 match self {
4646 IceSocketWrapper::Udp(s) => s.recv_from(buf).await.map_err(|e| e.into()),
4647 IceSocketWrapper::SharedUdp(h) => match h.recv().await {
4648 Some((data, addr)) => {
4649 if data.len() > buf.len() {
4650 return Err(anyhow::anyhow!(
4651 "shared UDP packet too large: {} > {}",
4652 data.len(),
4653 buf.len()
4654 ));
4655 }
4656 let len = data.len();
4657 buf[..len].copy_from_slice(&data);
4658 Ok((len, addr))
4659 }
4660 None => Err(anyhow::anyhow!("shared UDP channel closed")),
4661 },
4662 IceSocketWrapper::TcpStream(read, _, peer) => {
4663 use tokio::io::AsyncReadExt;
4664 let mut stream = read.lock().await;
4665 let mut len_buf = [0u8; 2];
4666 stream.read_exact(&mut len_buf).await?;
4667 let len = u16::from_be_bytes(len_buf) as usize;
4668 if len > buf.len() {
4669 return Err(anyhow::anyhow!(
4670 "TCP STUN message too large: {} > {}",
4671 len,
4672 buf.len()
4673 ));
4674 }
4675 stream.read_exact(&mut buf[..len]).await?;
4676 Ok((len, *peer))
4677 }
4678 IceSocketWrapper::TcpListener(_) => Err(anyhow::anyhow!(
4679 "recv_from not supported on TcpListener wrapper directly"
4680 )),
4681 IceSocketWrapper::Turn(_, _) => Err(anyhow::anyhow!(
4682 "recv_from not supported on TURN wrapper directly"
4683 )),
4684 }
4685 }
4686}