1use super::{IceSocketWrapper, should_drop_packet};
2use crate::errors::RtcResult;
3use crate::stats::{StatsEntry, StatsId, StatsKind, StatsProvider};
4use crate::transports::PacketReceiver;
5use anyhow::Result;
6use async_trait::async_trait;
7use bytes::Bytes;
8use parking_lot::{Mutex, RwLock};
9use serde_json::json;
10use std::net::SocketAddr;
11use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU32, AtomicU64, Ordering};
12use std::sync::{Arc, Weak};
13use tokio::sync::watch;
14use tracing::{trace, warn};
15
16#[derive(Debug)]
41struct RtpCandidateState {
42 addr: SocketAddr,
43 #[allow(dead_code)]
44 ssrc: u32,
45 first_seq: u16,
46 last_seq: u16,
47 first_ts: u32,
48 packet_count: u8,
49 consecutive_count: u8,
51 has_marker: bool,
52}
53
54#[derive(Debug)]
56struct RtpProbationState {
57 candidates: Vec<RtpCandidateState>,
58 total_packets: u8,
59 max_packets: u8,
62}
63
64pub struct IceConn {
65 pub socket_rx: watch::Receiver<Option<IceSocketWrapper>>,
66 rtcp_socket_rx: watch::Receiver<Option<IceSocketWrapper>>,
67 pub remote_addr: RwLock<SocketAddr>,
68 pub remote_rtcp_addr: RwLock<Option<SocketAddr>>,
69 pub dtls_receiver: RwLock<Option<Weak<dyn PacketReceiver>>>,
70 pub rtp_receiver: RwLock<Option<Weak<dyn PacketReceiver>>>,
71 pub latch_on_rtp: AtomicBool,
72 pub rtp_latched: AtomicBool,
73 pub rtcp_latched: AtomicBool,
74 pub expected_ssrc: AtomicU32,
75 pub rtp_rx_count: AtomicU64,
76 pub label: Option<String>,
77 first_rtp_rx_logged: AtomicBool,
80 first_rtcp_rx_logged: AtomicBool,
83 first_out_seen: AtomicBool,
85 both_ways_logged: AtomicBool,
87 pub rx_packets: AtomicU64,
88 pub rx_bytes: AtomicU64,
89 pub tx_packets: AtomicU64,
90 pub tx_bytes: AtomicU64,
91 probation: Mutex<Option<RtpProbationState>>,
95 probation_max_packets: AtomicU8,
98}
99
100impl IceConn {
101 pub fn new(
102 socket_rx: watch::Receiver<Option<IceSocketWrapper>>,
103 remote_addr: SocketAddr,
104 label: Option<String>,
105 ) -> Arc<Self> {
106 Self::new_with_rtcp(socket_rx.clone(), socket_rx, remote_addr, label, None)
107 }
108
109 pub(crate) fn new_with_rtcp(
110 socket_rx: watch::Receiver<Option<IceSocketWrapper>>,
111 rtcp_socket_rx: watch::Receiver<Option<IceSocketWrapper>>,
112 remote_addr: SocketAddr,
113 label: Option<String>,
114 probation_max_packets: Option<u8>,
115 ) -> Arc<Self> {
116 Arc::new(Self {
117 socket_rx,
118 rtcp_socket_rx,
119 remote_addr: RwLock::new(remote_addr),
120 remote_rtcp_addr: RwLock::new(None),
121 dtls_receiver: RwLock::new(None),
122 rtp_receiver: RwLock::new(None),
123 latch_on_rtp: AtomicBool::new(false),
124 rtp_latched: AtomicBool::new(false),
125 rtcp_latched: AtomicBool::new(false),
126 expected_ssrc: AtomicU32::new(0),
127 rtp_rx_count: AtomicU64::new(0),
128 label,
129 first_rtp_rx_logged: AtomicBool::new(false),
130 first_rtcp_rx_logged: AtomicBool::new(false),
131 first_out_seen: AtomicBool::new(false),
132 both_ways_logged: AtomicBool::new(false),
133 rx_packets: AtomicU64::new(0),
134 rx_bytes: AtomicU64::new(0),
135 tx_packets: AtomicU64::new(0),
136 tx_bytes: AtomicU64::new(0),
137 probation: Mutex::new(None),
138 probation_max_packets: AtomicU8::new(probation_max_packets.unwrap_or(0)),
139 })
140 }
141
142 pub fn set_probation_max_packets(&self, max: Option<u8>) {
143 self.probation_max_packets
144 .store(max.unwrap_or(0), Ordering::Relaxed);
145 }
146
147 pub fn mark_first_outbound(&self) {
150 if self.first_out_seen.swap(true, Ordering::Relaxed) {
151 return;
152 }
153 let label_str = self.label.as_deref().unwrap_or("unknown");
154 tracing::trace!("IceConn: first outbound RTP sent label={}", label_str);
155 self.maybe_log_both_ways(label_str);
156 }
157
158 fn maybe_log_both_ways(&self, label_str: &str) {
161 if self.both_ways_logged.load(Ordering::Relaxed) {
162 return;
163 }
164 let inbound_seen = self.first_rtp_rx_logged.load(Ordering::Relaxed)
165 || self.first_rtcp_rx_logged.load(Ordering::Relaxed);
166 if self.first_out_seen.load(Ordering::Relaxed) && inbound_seen
167 && self
168 .both_ways_logged
169 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
170 .is_ok()
171 {
172 tracing::trace!(
173 "IceConn: media confirmed both directions (outbound + inbound) label={}",
174 label_str
175 );
176 }
177 }
178
179 pub fn enable_latch_on_rtp(&self) {
180 self.latch_on_rtp.store(true, Ordering::Relaxed);
181 let max = self.probation_max_packets.load(Ordering::Relaxed);
182 if max > 0 {
183 let mut p = self.probation.lock();
185 if p.is_none() {
186 *p = Some(RtpProbationState {
187 candidates: Vec::new(),
188 total_packets: 0,
189 max_packets: max,
190 });
191 }
192 } else {
193 self.probation.lock().take();
195 }
196 }
197
198 pub fn set_expected_ssrc(&self, ssrc: u32) {
202 self.expected_ssrc.store(ssrc, Ordering::Relaxed);
203 }
204
205 pub fn set_remote_rtcp_addr(&self, addr: Option<SocketAddr>) {
206 *self.remote_rtcp_addr.write() = addr;
207 self.rtcp_latched.store(false, Ordering::Relaxed);
208 }
209
210 pub fn local_addr(&self) -> SocketAddr {
214 let socket = self.socket_rx.borrow();
215 match socket.as_ref() {
216 Some(IceSocketWrapper::Udp(s)) => s.local_addr().unwrap_or(SocketAddr::from(([0, 0, 0, 0], 0))),
217 Some(IceSocketWrapper::SharedUdp(h)) => h.local_addr().unwrap_or(SocketAddr::from(([0, 0, 0, 0], 0))),
218 _ => SocketAddr::from(([0, 0, 0, 0], 0)),
219 }
220 }
221
222 pub(crate) fn set_remote_addr_from_selected_pair(
223 &self,
224 addr: SocketAddr,
225 reason: &'static str,
226 ) {
227 let current = *self.remote_addr.read();
228 if self.latch_on_rtp.load(Ordering::Relaxed)
229 && self.rtp_latched.load(Ordering::Relaxed)
230 && current != addr
231 {
232 warn!(
233 "IceConn: preserving latched RTP remote {} instead of selected-pair remote {} ({})",
234 current, addr, reason
235 );
236 return;
237 }
238
239 *self.remote_addr.write() = addr;
240 }
241
242 pub(crate) fn set_remote_addr_from_signaling(&self, addr: SocketAddr, reason: &'static str) {
243 self.reset_latch();
244 *self.remote_addr.write() = addr;
245 trace!(
246 "IceConn: signaling RTP remote set to {} ({}), latch reset",
247 addr, reason
248 );
249 }
250
251 pub fn reset_latch(&self) {
254 self.rtp_latched.store(false, Ordering::Relaxed);
255 self.rtcp_latched.store(false, Ordering::Relaxed);
256 let max = self.probation_max_packets.load(Ordering::Relaxed);
257 *self.probation.lock() = if self.latch_on_rtp.load(Ordering::Relaxed) && max > 0 {
258 Some(RtpProbationState {
259 candidates: Vec::new(),
260 total_packets: 0,
261 max_packets: max,
262 })
263 } else {
264 None
265 };
266 }
267
268 pub fn set_dtls_receiver(&self, receiver: Arc<dyn PacketReceiver>) {
269 *self.dtls_receiver.write() = Some(Arc::downgrade(&receiver));
270 }
271
272 pub fn set_rtp_receiver(&self, receiver: Arc<dyn PacketReceiver>) {
273 *self.rtp_receiver.write() = Some(Arc::downgrade(&receiver));
274 }
275
276 pub fn try_send(&self, buf: &[u8]) -> Result<usize> {
280 if should_drop_packet() {
281 return Ok(buf.len());
282 }
283 let socket = self.socket_rx.borrow().clone();
284 let Some(socket) = socket else {
285 let mut socket_rx = self.socket_rx.clone();
287 let socket = socket_rx.borrow_and_update().clone();
288 let Some(socket) = socket else {
289 tracing::trace!("IceConn: try_send failed - no selected socket");
290 return Err(anyhow::anyhow!("No selected socket"));
291 };
292 return Self::do_try_send(socket, buf, &self.remote_addr);
293 };
294 Self::do_try_send(socket, buf, &self.remote_addr)
295 }
296
297 fn do_try_send(
298 socket: IceSocketWrapper,
299 buf: &[u8],
300 remote_addr: &parking_lot::RwLock<SocketAddr>,
301 ) -> Result<usize> {
302 let remote = *remote_addr.read();
303 if remote.port() == 0 {
304 return Err(anyhow::anyhow!("Remote address not set"));
305 }
306 let n = socket.try_send_to(buf, remote)?;
307 Ok(n)
311 }
312
313 pub async fn send(&self, buf: &[u8]) -> Result<usize> {
314 if should_drop_packet() {
315 return Ok(buf.len());
316 }
317 let socket_rx = self.socket_rx.clone();
318 let socket_opt = socket_rx.borrow().clone();
319
320 if let Some(socket) = socket_opt {
321 let remote = *self.remote_addr.read();
322 if remote.port() == 0 {
323 return Err(anyhow::anyhow!("Remote address not set"));
324 }
325 let n = socket.send_to(buf, remote).await?;
326 self.tx_packets.fetch_add(1, Ordering::Relaxed);
327 self.tx_bytes.fetch_add(n as u64, Ordering::Relaxed);
328 Ok(n)
329 } else {
330 let mut socket_rx = self.socket_rx.clone();
332 let socket_opt = socket_rx.borrow_and_update().clone();
333 if let Some(socket) = socket_opt {
334 let remote = *self.remote_addr.read();
335 if remote.port() == 0 {
336 return Err(anyhow::anyhow!("Remote address not set"));
337 }
338 let n = socket.send_to(buf, remote).await?;
339 self.tx_packets.fetch_add(1, Ordering::Relaxed);
340 self.tx_bytes.fetch_add(n as u64, Ordering::Relaxed);
341 Ok(n)
342 } else {
343 tracing::trace!("IceConn: send failed - no selected socket");
344 Err(anyhow::anyhow!("No selected socket"))
345 }
346 }
347 }
348
349 pub async fn send_dtls_record_batch(&self, records: &[Vec<u8>]) -> Result<usize> {
352 if records.is_empty() {
353 return Ok(0);
354 }
355 if should_drop_packet() {
356 return Ok(records.iter().map(|r| r.len()).sum());
357 }
358
359 let remote = *self.remote_addr.read();
360 if remote.port() == 0 {
361 return Err(anyhow::anyhow!("Remote address not set"));
362 }
363
364 let socket_rx = self.socket_rx.clone();
365 let mut socket_opt = socket_rx.borrow().clone();
366 if socket_opt.is_none() {
367 let mut rx = self.socket_rx.clone();
368 socket_opt = rx.borrow_and_update().clone();
369 }
370
371 let Some(socket) = socket_opt else {
372 tracing::trace!("IceConn: send_dtls_record_batch failed - no selected socket");
373 return Err(anyhow::anyhow!("No selected socket"));
374 };
375
376 let total_payload: usize = records.iter().map(|r| r.len()).sum();
377 self.tx_packets
378 .fetch_add(records.len() as u64, Ordering::Relaxed);
379
380 match &socket {
381 IceSocketWrapper::TcpStream(_, write, _) => {
382 let mut framed = Vec::new();
383 for record in records {
384 if record.len() > 0xFFFF {
385 return Err(anyhow::anyhow!("DTLS record too large for TCP framing"));
386 }
387 framed.extend_from_slice(&(record.len() as u16).to_be_bytes());
388 framed.extend_from_slice(record);
389 }
390 super::tcp_write_all(write, &framed).await?;
391 self.tx_bytes
392 .fetch_add(framed.len() as u64, Ordering::Relaxed);
393 Ok(total_payload)
394 }
395 _ => {
396 let mut total = 0usize;
397 for record in records {
398 total += self.send(record).await?;
399 }
400 Ok(total)
401 }
402 }
403 }
404
405 pub async fn send_rtcp(&self, buf: &[u8]) -> Result<usize> {
406 let rtcp_addr = *self.remote_rtcp_addr.read();
407 let remote = if let Some(rtcp_addr) = rtcp_addr {
408 rtcp_addr
409 } else {
410 *self.remote_addr.read()
411 };
412
413 if remote.port() == 0 {
414 return Err(anyhow::anyhow!("Remote address not set"));
415 }
416
417 let mut socket_rx = if rtcp_addr.is_some() {
418 self.rtcp_socket_rx.clone()
419 } else {
420 self.socket_rx.clone()
421 };
422 let mut socket_opt = socket_rx.borrow().clone();
423 if socket_opt.is_none() {
424 socket_opt = socket_rx.borrow_and_update().clone();
425 }
426
427 if socket_opt.is_none() && rtcp_addr.is_some() {
428 let mut fallback_rx = self.socket_rx.clone();
429 socket_opt = fallback_rx.borrow().clone();
430 if socket_opt.is_none() {
431 socket_opt = fallback_rx.borrow_and_update().clone();
432 }
433 }
434
435 if let Some(socket) = socket_opt {
436 let n = socket.send_to(buf, remote).await?;
437 self.tx_packets.fetch_add(1, Ordering::Relaxed);
438 self.tx_bytes.fetch_add(n as u64, Ordering::Relaxed);
439 Ok(n)
440 } else {
441 tracing::trace!("IceConn: send_rtcp failed - no selected socket");
442 Err(anyhow::anyhow!("No selected socket"))
443 }
444 }
445}
446
447#[async_trait]
448impl PacketReceiver for IceConn {
449 async fn receive(&self, packet: Bytes, addr: SocketAddr, marshal_buf: &mut Vec<u8>) {
450 if packet.is_empty() {
451 return;
452 }
453
454 self.rx_packets.fetch_add(1, Ordering::Relaxed);
455 self.rx_bytes
456 .fetch_add(packet.len() as u64, Ordering::Relaxed);
457
458 let first_byte = packet[0];
459 let current_remote = *self.remote_addr.read();
461
462 let socket_is_inbound_tcp = {
466 let socket_rx = self.socket_rx.clone();
467 matches!(
468 socket_rx.borrow().as_ref(),
469 Some(IceSocketWrapper::TcpStream(_, _, _))
470 )
471 };
472 if current_remote.port() == 0 || (socket_is_inbound_tcp && current_remote != addr) {
473 *self.remote_addr.write() = addr;
474 } else if addr != current_remote {
475 tracing::trace!(
480 "IceConn: Received packet from new address {:?} (byte={}) - ignoring address change",
481 addr,
482 first_byte
483 );
484 }
485
486 if (20..64).contains(&first_byte) {
487 let receiver = {
489 let rx_lock = self.dtls_receiver.read();
490 if let Some(rx) = &*rx_lock {
491 rx.upgrade()
492 } else {
493 None
494 }
495 };
496
497 if let Some(strong_rx) = receiver {
498 strong_rx.receive(packet, addr, marshal_buf).await;
500 } else {
501 trace!("IceConn: Received DTLS packet but no receiver registered");
502 }
503 } else if (128..192).contains(&first_byte) {
504 let is_rtcp = packet.len() >= 2 && (200..=211).contains(&packet[1]);
506
507 if self.latch_on_rtp.load(Ordering::Relaxed) {
508 if is_rtcp {
509 let mut remote_rtcp_addr = self.remote_rtcp_addr.write();
512 if let Some(current_rtcp_remote) = *remote_rtcp_addr
513 && addr != current_rtcp_remote
514 && !self.rtcp_latched.load(Ordering::Relaxed)
515 {
516 *remote_rtcp_addr = Some(addr);
517 self.rtcp_latched.store(true, Ordering::Relaxed);
518 }
519 } else if !self.rtp_latched.load(Ordering::Relaxed) && packet.len() >= 12 {
520 let expected = self.expected_ssrc.load(Ordering::Relaxed);
521 let pkt_ssrc =
522 u32::from_be_bytes([packet[8], packet[9], packet[10], packet[11]]);
523
524 let ssrc_ok = expected == 0 || pkt_ssrc == expected;
525
526 if ssrc_ok {
527 let seq = u16::from_be_bytes([packet[2], packet[3]]);
528 let ts = u32::from_be_bytes([packet[4], packet[5], packet[6], packet[7]]);
529 let marker = (packet[1] & 0x80) != 0;
530
531 let mut probation_guard = self.probation.lock();
532 if let Some(ref mut prob) = *probation_guard {
533 prob.total_packets = prob.total_packets.saturating_add(1);
534
535 let pos = prob.candidates.iter().position(|c| c.addr == addr);
536 if let Some(i) = pos {
537 let c = &mut prob.candidates[i];
538 if seq == c.last_seq.wrapping_add(1) {
539 c.consecutive_count = c.consecutive_count.saturating_add(1);
540 } else {
541 c.consecutive_count = 0;
543 }
544 c.last_seq = seq;
545 c.packet_count = c.packet_count.saturating_add(1);
546 if marker {
547 c.has_marker = true;
548 }
549 if ts < c.first_ts {
550 c.first_ts = ts;
551 }
552 if seq < c.first_seq {
553 c.first_seq = seq;
554 }
555 } else {
556 prob.candidates.push(RtpCandidateState {
557 addr,
558 ssrc: pkt_ssrc,
559 first_seq: seq,
560 last_seq: seq,
561 first_ts: ts,
562 packet_count: 1,
563 consecutive_count: 0,
564 has_marker: marker,
565 });
566 }
567
568 if addr != current_remote {
569 *self.remote_addr.write() = addr;
570 }
571
572 let total = prob.total_packets;
573 let winner: Option<SocketAddr>;
574
575 let marker_winner = prob
578 .candidates
579 .iter()
580 .filter(|c| c.has_marker)
581 .min_by_key(|c| c.first_seq);
582
583 if let Some(mw) = marker_winner {
584 winner = Some(mw.addr);
585 } else if total >= prob.max_packets {
586 winner = prob
590 .candidates
591 .iter()
592 .max_by(|a, b| {
593 a.packet_count
594 .cmp(&b.packet_count)
595 .then(b.first_seq.cmp(&a.first_seq))
596 })
597 .map(|c| c.addr);
598 } else {
599 winner = if total >= 3 {
603 prob.candidates
604 .iter()
605 .find(|c| c.consecutive_count >= 2)
606 .map(|c| c.addr)
607 } else {
608 None
609 };
610 }
611
612 if let Some(win_addr) = winner {
613 *probation_guard = None; drop(probation_guard);
616
617 if win_addr != current_remote {
618 *self.remote_addr.write() = win_addr;
619 }
620 self.rtp_latched.store(true, Ordering::Relaxed);
621 trace!(
622 "IceConn: RTP latched to {} after probation \
623 (expected_ssrc={}, total_obs={})",
624 win_addr, expected, total
625 );
626 }
627 } else {
628 if addr != current_remote {
632 *self.remote_addr.write() = addr;
633 }
634 self.rtp_latched.store(true, Ordering::Relaxed);
635 trace!(
636 "IceConn: RTP latched to {} immediately \
637 (expected_ssrc={})",
638 addr, expected
639 );
640 }
641 }
642 }
643 }
644 let receiver = {
645 let rx_lock = self.rtp_receiver.read();
646 if let Some(rx) = &*rx_lock {
647 rx.upgrade()
648 } else {
649 None
650 }
651 };
652
653 if let Some(strong_rx) = receiver {
654 self.rtp_rx_count.fetch_add(1, Ordering::Relaxed);
655 let label_str = self.label.as_deref().unwrap_or("unknown");
656 if is_rtcp {
657 if self
658 .first_rtcp_rx_logged
659 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
660 .is_ok()
661 {
662 tracing::debug!(
663 "IceConn: first inbound RTCP ({} bytes) from {} label={} — remote alive",
664 packet.len(),
665 addr,
666 label_str
667 );
668 }
669 } else if self
670 .first_rtp_rx_logged
671 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
672 .is_ok()
673 {
674 tracing::debug!(
675 "IceConn: first inbound RTP ({} bytes) from {} label={}",
676 packet.len(),
677 addr,
678 label_str
679 );
680 }
681 self.maybe_log_both_ways(label_str);
682 strong_rx.receive(packet, addr, marshal_buf).await;
683 } else {
684 trace!(
685 "IceConn: No RTP receiver registered for packet from {}",
686 addr
687 );
688 }
689 }
690 }
691}
692
693#[async_trait]
694impl StatsProvider for IceConn {
695 async fn collect(&self) -> RtcResult<Vec<StatsEntry>> {
696 let rx_packets = self.rx_packets.load(Ordering::Relaxed);
697 let rx_bytes = self.rx_bytes.load(Ordering::Relaxed);
698 let tx_packets = self.tx_packets.load(Ordering::Relaxed);
699 let tx_bytes = self.tx_bytes.load(Ordering::Relaxed);
700 let label = self.label.as_deref().unwrap_or("unknown");
701 let id = StatsId::new(format!("ice-conn-{}", label));
702 let entry = StatsEntry::new(id, StatsKind::Transport)
703 .with_value("label", json!(label))
704 .with_value("rxPackets", json!(rx_packets))
705 .with_value("rxBytes", json!(rx_bytes))
706 .with_value("txPackets", json!(tx_packets))
707 .with_value("txBytes", json!(tx_bytes));
708 Ok(vec![entry])
709 }
710}
711
712#[cfg(test)]
713mod tests {
714 use super::*;
715 use bytes::Bytes;
716 use std::net::{IpAddr, Ipv4Addr};
717 use tokio::io::AsyncReadExt;
718 use tokio::io::AsyncWriteExt;
719 use tokio::net::UdpSocket;
720 use tokio::sync::watch;
721
722 #[tokio::test]
723 async fn test_ice_conn_send_rtcp_mux() {
724 let socket = UdpSocket::bind("127.0.0.1:0").await.unwrap();
725 let socket_wrapper = IceSocketWrapper::Udp(Arc::new(socket));
726 let (_tx, rx) = watch::channel(Some(socket_wrapper));
727
728 let receiver = UdpSocket::bind("127.0.0.1:0").await.unwrap();
729 let receiver_addr = receiver.local_addr().unwrap();
730
731 let conn = IceConn::new(rx, receiver_addr, None);
732
733 conn.send_rtcp(b"hello").await.unwrap();
735
736 let mut buf = [0u8; 1024];
737 let (len, _) = receiver.recv_from(&mut buf).await.unwrap();
738 assert_eq!(&buf[..len], b"hello");
739 }
740
741 #[tokio::test]
742 async fn test_ice_conn_send_rtcp_no_mux() {
743 let rtp_socket = Arc::new(UdpSocket::bind("127.0.0.1:0").await.unwrap());
744 let rtp_socket_addr = rtp_socket.local_addr().unwrap();
745 let socket_wrapper = IceSocketWrapper::Udp(rtp_socket);
746 let (_tx, rx) = watch::channel(Some(socket_wrapper));
747
748 let rtcp_socket = Arc::new(UdpSocket::bind("127.0.0.1:0").await.unwrap());
749 let rtcp_socket_addr = rtcp_socket.local_addr().unwrap();
750 let rtcp_socket_wrapper = IceSocketWrapper::Udp(rtcp_socket);
751 let (_rtcp_tx, rtcp_rx) = watch::channel(Some(rtcp_socket_wrapper));
752
753 let rtp_receiver = UdpSocket::bind("127.0.0.1:0").await.unwrap();
754 let rtp_addr = rtp_receiver.local_addr().unwrap();
755
756 let rtcp_receiver = UdpSocket::bind("127.0.0.1:0").await.unwrap();
757 let rtcp_addr = rtcp_receiver.local_addr().unwrap();
758
759 let conn = IceConn::new_with_rtcp(rx, rtcp_rx, rtp_addr, None, None);
760 conn.set_remote_rtcp_addr(Some(rtcp_addr));
761
762 conn.send(b"rtp").await.unwrap();
764 let mut buf = [0u8; 1024];
765 let (len, rtp_src) = rtp_receiver.recv_from(&mut buf).await.unwrap();
766 assert_eq!(&buf[..len], b"rtp");
767 assert_eq!(rtp_src, rtp_socket_addr);
768
769 conn.send_rtcp(b"rtcp").await.unwrap();
771 let (len, rtcp_src) = rtcp_receiver.recv_from(&mut buf).await.unwrap();
772 assert_eq!(&buf[..len], b"rtcp");
773 assert_eq!(rtcp_src, rtcp_socket_addr);
774 }
775
776 #[tokio::test]
777 async fn test_changed_signaling_remote_resets_latch_and_retargets_send() {
778 let socket = Arc::new(UdpSocket::bind("127.0.0.1:0").await.unwrap());
779 let socket_wrapper = IceSocketWrapper::Udp(socket);
780 let (_tx, rx) = watch::channel(Some(socket_wrapper));
781
782 let old_receiver = UdpSocket::bind("127.0.0.1:0").await.unwrap();
783 let old_addr = old_receiver.local_addr().unwrap();
784 let new_receiver = UdpSocket::bind("127.0.0.1:0").await.unwrap();
785 let new_addr = new_receiver.local_addr().unwrap();
786
787 let conn = IceConn::new(rx, old_addr, None);
788 conn.enable_latch_on_rtp();
789 conn.rtp_latched.store(true, Ordering::Relaxed);
790
791 conn.set_remote_addr_from_signaling(new_addr, "test SDP endpoint change");
792
793 assert_eq!(*conn.remote_addr.read(), new_addr);
794 assert!(!conn.rtp_latched.load(Ordering::Relaxed));
795
796 conn.send(b"retargeted").await.unwrap();
797 let mut buf = [0u8; 32];
798 let (len, _) = tokio::time::timeout(
799 std::time::Duration::from_millis(100),
800 new_receiver.recv_from(&mut buf),
801 )
802 .await
803 .expect("new signaling endpoint should receive RTP")
804 .unwrap();
805 assert_eq!(&buf[..len], b"retargeted");
806 assert!(
807 tokio::time::timeout(
808 std::time::Duration::from_millis(20),
809 old_receiver.recv_from(&mut buf),
810 )
811 .await
812 .is_err(),
813 "old signaling endpoint must stop receiving after retarget"
814 );
815 }
816
817 struct NoopReceiver;
818
819 #[async_trait]
820 impl PacketReceiver for NoopReceiver {
821 async fn receive(&self, _packet: Bytes, _addr: SocketAddr, _buf: &mut Vec<u8>) {}
822 }
823
824 #[tokio::test]
825 async fn test_ice_conn_latches_remote_addr_on_rtp() {
826 let (_tx, rx) = watch::channel(None);
827 let initial_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4000);
828 let latched_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5000);
829 let conn = IceConn::new(rx, initial_addr, None);
830 conn.enable_latch_on_rtp();
831 conn.set_rtp_receiver(Arc::new(NoopReceiver));
832
833 let pkt = Bytes::from_static(&[
835 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, ]);
840 let mut marshal_buf = Vec::new();
841 conn.receive(pkt, latched_addr, &mut marshal_buf).await;
842
843 assert_eq!(*conn.remote_addr.read(), latched_addr);
844 }
845
846 #[tokio::test]
847 async fn test_rtcp_does_not_override_rtp_remote_addr() {
848 let (_tx, rx) = watch::channel(None);
849 let rtp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4000);
850 let rtcp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4001);
851 let conn = IceConn::new(rx, rtp_addr, None);
852 conn.enable_latch_on_rtp();
853 conn.set_rtp_receiver(Arc::new(NoopReceiver));
854 conn.set_remote_rtcp_addr(Some(rtcp_addr));
855
856 let rtp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5000);
857 let rtp_pkt = Bytes::from_static(&[
859 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
860 ]);
861 let mut marshal_buf = Vec::new();
862 conn.receive(rtp_pkt, rtp_src, &mut marshal_buf).await;
863 assert_eq!(*conn.remote_addr.read(), rtp_src);
864 assert!(conn.rtp_latched.load(Ordering::Relaxed));
865
866 let rtcp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5001);
867 conn.receive(
868 Bytes::from_static(&[0x80, 0xC8, 0x00, 0x00]),
869 rtcp_src,
870 &mut marshal_buf,
871 )
872 .await;
873
874 assert_eq!(
875 *conn.remote_addr.read(),
876 rtp_src,
877 "RTCP should not override RTP remote address"
878 );
879 }
880
881 #[tokio::test]
882 async fn test_rtcp_latches_rtcp_addr_in_non_mux_mode() {
883 let (_tx, rx) = watch::channel(None);
884 let rtp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4000);
885 let initial_rtcp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4001);
886 let conn = IceConn::new(rx, rtp_addr, None);
887 conn.enable_latch_on_rtp();
888 conn.set_rtp_receiver(Arc::new(NoopReceiver));
889 conn.set_remote_rtcp_addr(Some(initial_rtcp_addr));
890
891 let rtp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5000);
892 let rtp_pkt = Bytes::from_static(&[
893 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
894 ]);
895 let mut marshal_buf = Vec::new();
896 conn.receive(rtp_pkt, rtp_src, &mut marshal_buf).await;
897
898 let rtcp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5001);
899 conn.receive(
900 Bytes::from_static(&[0x80, 0xC8, 0x00, 0x00]),
901 rtcp_src,
902 &mut marshal_buf,
903 )
904 .await;
905
906 assert_eq!(
907 *conn.remote_rtcp_addr.read(),
908 Some(rtcp_src),
909 "RTCP should latch its own destination"
910 );
911 assert!(conn.rtcp_latched.load(Ordering::Relaxed));
912 }
913
914 #[tokio::test]
915 async fn test_rtcp_does_not_re_latch_after_locked() {
916 let (_tx, rx) = watch::channel(None);
917 let rtp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4000);
918 let conn = IceConn::new(rx, rtp_addr, None);
919 conn.enable_latch_on_rtp();
920 conn.set_rtp_receiver(Arc::new(NoopReceiver));
921 conn.set_remote_rtcp_addr(Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4001)));
922
923 let rtp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5000);
924 let rtp_pkt = Bytes::from_static(&[
925 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
926 ]);
927 let mut marshal_buf = Vec::new();
928 conn.receive(rtp_pkt, rtp_src, &mut marshal_buf).await;
929
930 let rtcp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5001);
931 conn.receive(
932 Bytes::from_static(&[0x80, 0xC8, 0x00, 0x00]),
933 rtcp_src,
934 &mut marshal_buf,
935 )
936 .await;
937 assert_eq!(*conn.remote_rtcp_addr.read(), Some(rtcp_src));
938
939 let rogue_rtcp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 6001);
940 conn.receive(
941 Bytes::from_static(&[0x80, 0xC8, 0x00, 0x00]),
942 rogue_rtcp_src,
943 &mut marshal_buf,
944 )
945 .await;
946
947 assert_eq!(
948 *conn.remote_rtcp_addr.read(),
949 Some(rtcp_src),
950 "RTCP should not re-latch after already latched"
951 );
952 }
953
954 #[tokio::test]
955 async fn test_rtcp_ignored_in_mux_mode() {
956 let (_tx, rx) = watch::channel(None);
957 let rtp_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 4000);
958 let conn = IceConn::new(rx, rtp_addr, None);
959 conn.enable_latch_on_rtp();
960 conn.set_rtp_receiver(Arc::new(NoopReceiver));
961
962 let rtp_src = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 5000);
963 let rtp_pkt = Bytes::from_static(&[
964 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
965 ]);
966 let mut marshal_buf = Vec::new();
967 conn.receive(rtp_pkt, rtp_src, &mut marshal_buf).await;
968 assert_eq!(*conn.remote_addr.read(), rtp_src);
969
970 conn.receive(
971 Bytes::from_static(&[0x80, 0xC8, 0x00, 0x00]),
972 rtp_src,
973 &mut marshal_buf,
974 )
975 .await;
976 assert_eq!(*conn.remote_addr.read(), rtp_src);
977 assert!(
978 conn.remote_rtcp_addr.read().is_none(),
979 "RTCP address should remain None in mux mode"
980 );
981 }
982
983 #[tokio::test]
984 async fn test_ssrc_based_latch_ignores_port_mismatch() {
985 let (_tx, rx) = watch::channel(None);
989 let sdp_addr: SocketAddr = "10.17.230.54:4162".parse().unwrap();
990 let real_addr: SocketAddr = "112.96.43.157:17687".parse().unwrap();
991 let expected_ssrc: u32 = 787_088_145;
992
993 let conn = IceConn::new(rx, sdp_addr, None);
994 conn.enable_latch_on_rtp();
995 conn.set_expected_ssrc(expected_ssrc);
996 conn.set_rtp_receiver(Arc::new(NoopReceiver));
997
998 let mut pkt = vec![0x80u8, 0x00, 0x10, 0x98, 0x00, 0x00, 0x00, 0xa0];
1000 pkt.extend_from_slice(&expected_ssrc.to_be_bytes()); let mut pkt2 = vec![0x80u8, 0x00, 0x10, 0x99, 0x00, 0x00, 0x00, 0xa1];
1005 pkt2.extend_from_slice(&expected_ssrc.to_be_bytes());
1006 let mut marshal_buf = Vec::new();
1007 conn.receive(Bytes::from(pkt.clone()), real_addr, &mut marshal_buf)
1008 .await;
1009 conn.receive(Bytes::from(pkt2.clone()), real_addr, &mut marshal_buf)
1010 .await;
1011
1012 let mut pkt3 = vec![0x80u8, 0x00, 0x10, 0x9a, 0x00, 0x00, 0x00, 0xa2];
1014 pkt3.extend_from_slice(&expected_ssrc.to_be_bytes());
1015 conn.receive(Bytes::from(pkt3), real_addr, &mut marshal_buf)
1016 .await;
1017
1018 assert_eq!(
1019 *conn.remote_addr.read(),
1020 real_addr,
1021 "Should latch to real NAT address when SSRC matches"
1022 );
1023 assert!(
1024 conn.rtp_latched.load(Ordering::Relaxed),
1025 "rtp_latched should be set after SSRC match"
1026 );
1027 }
1028
1029 #[tokio::test]
1030 async fn test_ssrc_based_latch_ignores_wrong_ssrc() {
1031 let (_tx, rx) = watch::channel(None);
1033 let sdp_addr: SocketAddr = "10.17.230.54:4162".parse().unwrap();
1034 let rogue_addr: SocketAddr = "1.2.3.4:9999".parse().unwrap();
1035 let expected_ssrc: u32 = 787_088_145;
1036 let wrong_ssrc: u32 = 99_999_999;
1037
1038 let conn = IceConn::new(rx, sdp_addr, None);
1039 conn.enable_latch_on_rtp();
1040 conn.set_expected_ssrc(expected_ssrc);
1041 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1042
1043 let mut pkt = vec![0x80u8, 0x00, 0x10, 0x98, 0x00, 0x00, 0x00, 0xa0];
1044 pkt.extend_from_slice(&wrong_ssrc.to_be_bytes());
1045
1046 let mut marshal_buf = Vec::new();
1047 conn.receive(Bytes::from(pkt), rogue_addr, &mut marshal_buf)
1048 .await;
1049
1050 assert_eq!(
1051 *conn.remote_addr.read(),
1052 sdp_addr,
1053 "Should NOT latch when SSRC does not match"
1054 );
1055 assert!(
1056 !conn.rtp_latched.load(Ordering::Relaxed),
1057 "rtp_latched should remain false for wrong SSRC"
1058 );
1059 }
1060
1061 #[tokio::test]
1062 async fn test_address_based_latch_fallback_when_no_expected_ssrc() {
1063 let (_tx, rx) = watch::channel(None);
1066 let initial_addr: SocketAddr = "10.0.0.1:4000".parse().unwrap();
1067 let new_addr: SocketAddr = "10.0.0.2:5000".parse().unwrap();
1068
1069 let conn = IceConn::new(rx, initial_addr, None);
1070 conn.enable_latch_on_rtp();
1071 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1072 for seq in 1u16..=3 {
1076 let pkt = Bytes::from(vec![
1077 0x80,
1078 0x00,
1079 (seq >> 8) as u8,
1080 seq as u8,
1081 0x00,
1082 0x00,
1083 0x00,
1084 seq as u8,
1085 0x00,
1086 0x00,
1087 0x01,
1088 0x23,
1089 ]);
1090 let mut marshal_buf = Vec::new();
1091 conn.receive(pkt, new_addr, &mut marshal_buf).await;
1092 }
1093
1094 assert_eq!(*conn.remote_addr.read(), new_addr);
1095 assert!(conn.rtp_latched.load(Ordering::Relaxed));
1096 }
1097
1098 #[tokio::test]
1104 async fn test_probation_marker_wins_over_first_arriving_packet() {
1105 let (_tx, rx) = watch::channel(None);
1106 let sdp_addr: SocketAddr = "223.104.80.120:4000".parse().unwrap();
1107 let port_4114: SocketAddr = "223.104.80.120:4114".parse().unwrap();
1108 let port_4014: SocketAddr = "223.104.80.120:4014".parse().unwrap();
1109 let ssrc: u32 = 0x6c0d_1ca5;
1110
1111 let conn = IceConn::new(rx, sdp_addr, None);
1112 conn.set_probation_max_packets(Some(6));
1113 conn.enable_latch_on_rtp();
1114 conn.set_expected_ssrc(ssrc);
1115 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1116
1117 let mut pkt_4114 = vec![0x80u8, 0x08, 0x53, 0xCA, 0x00, 0x00, 0x00, 0xA0];
1119 pkt_4114.extend_from_slice(&ssrc.to_be_bytes());
1120 let mut marshal_buf = Vec::new();
1121 conn.receive(Bytes::from(pkt_4114), port_4114, &mut marshal_buf)
1122 .await;
1123
1124 assert!(
1126 !conn.rtp_latched.load(Ordering::Relaxed),
1127 "Should not latch after just one packet with no marker"
1128 );
1129
1130 let mut pkt_4014 = vec![0x80u8, 0x88, 0x53, 0xC9, 0x00, 0x00, 0x00, 0xA0];
1132 pkt_4014.extend_from_slice(&ssrc.to_be_bytes());
1133 conn.receive(Bytes::from(pkt_4014), port_4014, &mut marshal_buf)
1134 .await;
1135
1136 assert!(
1137 conn.rtp_latched.load(Ordering::Relaxed),
1138 "Should latch after marker packet"
1139 );
1140 assert_eq!(
1141 *conn.remote_addr.read(),
1142 port_4014,
1143 "Should latch to port 4014 (marker=true), not port 4114 (first arrived)"
1144 );
1145 }
1146
1147 #[tokio::test]
1150 async fn test_probation_consecutive_dominance() {
1151 let (_tx, rx) = watch::channel(None);
1152 let sdp_addr: SocketAddr = "10.0.0.1:4000".parse().unwrap();
1153 let real_src: SocketAddr = "10.0.0.1:5000".parse().unwrap();
1154 let stray_src: SocketAddr = "10.0.0.1:5001".parse().unwrap();
1155
1156 let conn = IceConn::new(rx, sdp_addr, None);
1157 conn.set_probation_max_packets(Some(6));
1158 conn.enable_latch_on_rtp();
1159 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1160
1161 let stray = Bytes::from(vec![
1163 0x80, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x02,
1164 ]);
1165 let mut marshal_buf = Vec::new();
1166 conn.receive(stray, stray_src, &mut marshal_buf).await;
1167
1168 for seq in 1u16..=3 {
1170 let pkt = Bytes::from(vec![
1171 0x80, 0x00, 0x00, seq as u8, 0x00, 0x00, 0x00, seq as u8, 0x00, 0x00, 0x00, 0x01,
1172 ]);
1173 conn.receive(pkt, real_src, &mut marshal_buf).await;
1174 }
1175
1176 assert!(
1177 conn.rtp_latched.load(Ordering::Relaxed),
1178 "Should latch after consecutive dominance"
1179 );
1180 assert_eq!(
1181 *conn.remote_addr.read(),
1182 real_src,
1183 "Should latch to the source with consecutive packets"
1184 );
1185 }
1186
1187 #[tokio::test]
1190 async fn test_probation_timeout_fallback_selects_dominant() {
1191 let (_tx, rx) = watch::channel(None);
1192 let sdp_addr: SocketAddr = "10.0.0.1:4000".parse().unwrap();
1193 let dominant: SocketAddr = "10.0.0.1:5000".parse().unwrap();
1194 let minor: SocketAddr = "10.0.0.1:5001".parse().unwrap();
1195
1196 let probation_max = 6u8;
1197 let conn = IceConn::new(rx, sdp_addr, None);
1198 conn.set_probation_max_packets(Some(probation_max));
1199 conn.enable_latch_on_rtp();
1200 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1201
1202 let minor_pkt = Bytes::from(vec![
1204 0x80, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x02,
1205 ]);
1206 let mut marshal_buf = Vec::new();
1207 conn.receive(minor_pkt, minor, &mut marshal_buf).await;
1208
1209 for i in 0..(probation_max - 1) {
1211 let seq = i * 2 + 10;
1214 let pkt = Bytes::from(vec![
1215 0x80, 0x00, 0x00, seq, 0x00, 0x00, 0x00, seq, 0x00, 0x00, 0x00, 0x01,
1216 ]);
1217 conn.receive(pkt, dominant, &mut marshal_buf).await;
1218 }
1219
1220 assert!(
1221 conn.rtp_latched.load(Ordering::Relaxed),
1222 "Should latch after PROBATION_MAX_PACKETS total packets"
1223 );
1224 assert_eq!(
1225 *conn.remote_addr.read(),
1226 dominant,
1227 "Should latch to source with most packets"
1228 );
1229 }
1230
1231 #[tokio::test]
1234 async fn test_probation_latch_is_sticky_after_commit() {
1235 let (_tx, rx) = watch::channel(None);
1236 let sdp_addr: SocketAddr = "10.0.0.1:4000".parse().unwrap();
1237 let good_src: SocketAddr = "10.0.0.1:5000".parse().unwrap();
1238 let rogue_src: SocketAddr = "10.0.0.1:6000".parse().unwrap();
1239
1240 let conn = IceConn::new(rx, sdp_addr, None);
1241 conn.set_probation_max_packets(Some(6));
1242 conn.enable_latch_on_rtp();
1243 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1244
1245 let pkt = Bytes::from(vec![
1247 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
1248 ]);
1249 let mut marshal_buf = Vec::new();
1250 conn.receive(pkt, good_src, &mut marshal_buf).await;
1251 assert!(conn.rtp_latched.load(Ordering::Relaxed));
1252 assert_eq!(*conn.remote_addr.read(), good_src);
1253
1254 for seq in 2u8..=5 {
1256 let rogue_pkt = Bytes::from(vec![
1257 0x80, 0x00, 0x00, seq, 0x00, 0x00, 0x00, seq, 0x00, 0x00, 0x00, 0x99,
1258 ]);
1259 conn.receive(rogue_pkt, rogue_src, &mut marshal_buf).await;
1260 }
1261 assert_eq!(
1262 *conn.remote_addr.read(),
1263 good_src,
1264 "Latched address must not change after latch is committed"
1265 );
1266 }
1267
1268 #[tokio::test]
1271 async fn test_reset_latch_allows_re_latching() {
1272 let (_tx, rx) = watch::channel(None);
1273 let sdp_addr: SocketAddr = "10.0.0.1:4000".parse().unwrap();
1274 let first_src: SocketAddr = "10.0.0.1:5000".parse().unwrap();
1275 let second_src: SocketAddr = "10.0.0.2:5000".parse().unwrap();
1276
1277 let conn = IceConn::new(rx, sdp_addr, None);
1278 conn.set_probation_max_packets(Some(6));
1279 conn.enable_latch_on_rtp();
1280 conn.set_rtp_receiver(Arc::new(NoopReceiver));
1281
1282 let pkt = Bytes::from(vec![
1283 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
1284 ]);
1285 let mut marshal_buf = Vec::new();
1286 conn.receive(pkt.clone(), first_src, &mut marshal_buf).await;
1287 assert_eq!(*conn.remote_addr.read(), first_src);
1288
1289 conn.reset_latch();
1290 assert!(!conn.rtp_latched.load(Ordering::Relaxed));
1291
1292 let pkt2 = Bytes::from(vec![
1294 0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
1295 ]);
1296 conn.receive(pkt2, second_src, &mut marshal_buf).await;
1297 assert_eq!(
1298 *conn.remote_addr.read(),
1299 second_src,
1300 "Should re-latch to new source after reset_latch()"
1301 );
1302 }
1303
1304 async fn tcp_loopback_pair() -> (tokio::net::TcpStream, IceSocketWrapper) {
1311 let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
1312 let server_addr = listener.local_addr().unwrap();
1313
1314 let client_stream = tokio::net::TcpStream::connect(server_addr).await.unwrap();
1315 let (server_stream, _) = listener.accept().await.unwrap();
1316
1317 let wrapper = {
1318 let (read, write) = client_stream.into_split();
1319 IceSocketWrapper::TcpStream(
1320 Arc::new(tokio::sync::Mutex::new(read)),
1321 Arc::new(tokio::sync::Mutex::new(write)),
1322 server_addr,
1323 )
1324 };
1325
1326 (server_stream, wrapper)
1327 }
1328
1329 #[tokio::test]
1332 async fn test_tcp_rfc4571_framing_roundtrip() {
1333 let (mut server_stream, wrapper) = tcp_loopback_pair().await;
1334
1335 let payload = b"hello rfc4571";
1336 let len = payload.len() as u16;
1337 let mut expected_frame = Vec::with_capacity(2 + payload.len());
1338 expected_frame.extend_from_slice(&len.to_be_bytes());
1339 expected_frame.extend_from_slice(payload);
1340
1341 wrapper
1343 .send_to(payload, server_stream.local_addr().unwrap())
1344 .await
1345 .unwrap();
1346
1347 let mut len_buf = [0u8; 2];
1349 let s = &mut server_stream;
1350 s.read_exact(&mut len_buf).await.unwrap();
1351 let frame_len = u16::from_be_bytes(len_buf) as usize;
1352 let mut frame = vec![0u8; frame_len];
1353 s.read_exact(&mut frame).await.unwrap();
1354 assert_eq!(&frame, payload);
1355 }
1356
1357 #[tokio::test]
1360 async fn test_tcp_rfc4571_multiple_writes() {
1361 let (mut server_stream, wrapper) = tcp_loopback_pair().await;
1362
1363 let msgs: &[&[u8]] = &[b"msg-a", b"msg-bb", b"msg-ccc"];
1364 for msg in msgs {
1365 wrapper
1366 .send_to(msg, server_stream.local_addr().unwrap())
1367 .await
1368 .unwrap();
1369 }
1370
1371 let s = &mut server_stream;
1372 for expected in msgs {
1373 let mut len_buf = [0u8; 2];
1374 s.read_exact(&mut len_buf).await.unwrap();
1375 let frame_len = u16::from_be_bytes(len_buf) as usize;
1376 let mut frame = vec![0u8; frame_len];
1377 s.read_exact(&mut frame).await.unwrap();
1378 assert_eq!(&frame, expected);
1379 }
1380 }
1381
1382 #[tokio::test]
1385 async fn test_tcp_recv_from_rfc4571() {
1386 let (mut server_stream, wrapper) = tcp_loopback_pair().await;
1387 let server_addr = server_stream.local_addr().unwrap();
1388
1389 let payload = b"recv-test-payload";
1390 let len = payload.len() as u16;
1391 let mut frame = Vec::with_capacity(2 + payload.len());
1392 frame.extend_from_slice(&len.to_be_bytes());
1393 frame.extend_from_slice(payload);
1394
1395 server_stream.writable().await.unwrap();
1397 let s = &mut server_stream;
1398 s.write_all(&frame).await.unwrap();
1399
1400 let mut buf = [0u8; 2048];
1402 let (n, addr) = wrapper.recv_from(&mut buf).await.unwrap();
1403 assert_eq!(&buf[..n], payload);
1404 assert_eq!(addr, server_addr);
1405 }
1406
1407 #[tokio::test]
1410 async fn test_send_dtls_record_batch_tcp() {
1411 let (mut server_stream, wrapper) = tcp_loopback_pair().await;
1412 let server_addr = server_stream.local_addr().unwrap();
1413
1414 let (socket_tx, socket_rx) = watch::channel(Some(wrapper));
1415 let conn = IceConn::new(socket_rx, server_addr, Some("test-tcp".into()));
1416 drop(socket_tx);
1417
1418 let records: Vec<Vec<u8>> = vec![
1419 b"dtls-record-1".to_vec(),
1420 b"dtls-record-22".to_vec(),
1421 b"dtls-record-333".to_vec(),
1422 ];
1423
1424 conn.send_dtls_record_batch(&records).await.unwrap();
1425
1426 let s = &mut server_stream;
1427 for expected in &records {
1428 let mut len_buf = [0u8; 2];
1429 s.read_exact(&mut len_buf).await.unwrap();
1430 let frame_len = u16::from_be_bytes(len_buf) as usize;
1431 let mut frame = vec![0u8; frame_len];
1432 s.read_exact(&mut frame).await.unwrap();
1433 assert_eq!(&frame, expected.as_slice());
1434 }
1435 }
1436
1437 #[tokio::test]
1440 async fn test_send_dtls_record_batch_udp_fallback() {
1441 let udp = Arc::new(tokio::net::UdpSocket::bind("127.0.0.1:0").await.unwrap());
1442 let wrapper = IceSocketWrapper::Udp(udp.clone());
1443 let (socket_tx, socket_rx) = watch::channel(Some(wrapper));
1444
1445 let receiver = tokio::net::UdpSocket::bind("127.0.0.1:0").await.unwrap();
1446 let receiver_addr = receiver.local_addr().unwrap();
1447
1448 let conn = IceConn::new(socket_rx, receiver_addr, None);
1449 drop(socket_tx);
1450
1451 let records: Vec<Vec<u8>> = vec![b"rec-a".to_vec(), b"rec-b".to_vec()];
1452 conn.send_dtls_record_batch(&records).await.unwrap();
1453
1454 let mut buf = [0u8; 2048];
1456 for expected in &records {
1457 let (len, _) = receiver.recv_from(&mut buf).await.unwrap();
1458 assert_eq!(&buf[..len], expected.as_slice());
1459 }
1460 }
1461}