Skip to content

Commit 0aa7c07

Browse files
authored
peer_connection: Make sure all packets are read through interceptor (#648)
Instead of reading first packet when probing simulcast directly from RTP stream, rather let SRTP session accept() fn return the RTP header for the first packet. This makes us able to configure interceptor and let all packets travel through the regular path. Fixes #391
1 parent 2a5393d commit 0aa7c07

File tree

6 files changed

+93
-109
lines changed

6 files changed

+93
-109
lines changed

srtp/src/session/mod.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const DEFAULT_SESSION_SRTCP_REPLAY_PROTECTION_WINDOW: usize = 64;
2828
pub struct Session {
2929
local_context: Arc<Mutex<Context>>,
3030
streams_map: Arc<Mutex<HashMap<u32, Arc<Stream>>>>,
31-
new_stream_rx: Arc<Mutex<mpsc::Receiver<Arc<Stream>>>>,
31+
new_stream_rx: Arc<Mutex<mpsc::Receiver<(Arc<Stream>, Option<rtp::header::Header>)>>>,
3232
close_stream_tx: mpsc::Sender<u32>,
3333
close_session_tx: mpsc::Sender<()>,
3434
pub(crate) udp_tx: Arc<dyn Conn + Send + Sync>,
@@ -128,7 +128,7 @@ impl Session {
128128
buf: &mut [u8],
129129
streams_map: &Arc<Mutex<HashMap<u32, Arc<Stream>>>>,
130130
close_stream_tx: &mpsc::Sender<u32>,
131-
new_stream_tx: &mut mpsc::Sender<Arc<Stream>>,
131+
new_stream_tx: &mut mpsc::Sender<(Arc<Stream>, Option<rtp::header::Header>)>,
132132
remote_context: &mut Context,
133133
is_rtp: bool,
134134
) -> Result<()> {
@@ -144,24 +144,28 @@ impl Session {
144144
};
145145

146146
let mut buf = &decrypted[..];
147-
let ssrcs = if is_rtp {
148-
vec![rtp::header::Header::unmarshal(&mut buf)?.ssrc]
147+
let (ssrcs, header) = if is_rtp {
148+
let header = rtp::header::Header::unmarshal(&mut buf)?;
149+
(vec![header.ssrc], Some(header))
149150
} else {
150151
let pkts = rtcp::packet::unmarshal(&mut buf)?;
151-
destination_ssrc(&pkts)
152+
(destination_ssrc(&pkts), None)
152153
};
153154

154155
for ssrc in ssrcs {
155156
let (stream, is_new) =
156157
Session::get_or_create_stream(streams_map, close_stream_tx.clone(), is_rtp, ssrc)
157158
.await;
159+
158160
if is_new {
159161
log::trace!(
160162
"srtp session got new {} stream {}",
161163
if is_rtp { "rtp" } else { "rtcp" },
162164
ssrc
163165
);
164-
new_stream_tx.send(Arc::clone(&stream)).await?;
166+
new_stream_tx
167+
.send((Arc::clone(&stream), header.clone()))
168+
.await?;
165169
}
166170

167171
match stream.buffer.write(&decrypted).await {
@@ -210,14 +214,13 @@ impl Session {
210214
}
211215

212216
/// accept returns a stream to handle RTCP for a single SSRC
213-
pub async fn accept(&self) -> Result<Arc<Stream>> {
217+
pub async fn accept(&self) -> Result<(Arc<Stream>, Option<rtp::header::Header>)> {
214218
let mut new_stream_rx = self.new_stream_rx.lock().await;
215-
let result = new_stream_rx.recv().await;
216-
if let Some(stream) = result {
217-
Ok(stream)
218-
} else {
219-
Err(Error::SessionSrtpAlreadyClosed)
220-
}
219+
220+
new_stream_rx
221+
.recv()
222+
.await
223+
.ok_or(Error::SessionSrtpAlreadyClosed)
221224
}
222225

223226
pub async fn close(&self) -> Result<()> {

srtp/src/session/session_rtcp_test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ async fn test_session_srtcp_accept() -> Result<()> {
8484
let test_payload = rtcp_packet.marshal()?;
8585
sa.write_rtcp(&rtcp_packet).await?;
8686

87-
let read_stream = sb.accept().await?;
87+
let (read_stream, _) = sb.accept().await?;
8888
let ssrc = read_stream.get_ssrc();
8989
assert_eq!(
9090
ssrc, TEST_SSRC,

srtp/src/session/session_rtp_test.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,22 @@ async fn test_session_srtp_accept() -> Result<()> {
8686

8787
let packet = rtp::packet::Packet {
8888
header: rtp::header::Header {
89+
version: 2,
8990
ssrc: TEST_SSRC,
91+
payload_type: 96,
9092
..Default::default()
9193
},
9294
payload: test_payload.clone(),
9395
};
9496
sa.write_rtp(&packet).await?;
9597

96-
let read_stream = sb.accept().await?;
98+
let (read_stream, header) = sb.accept().await?;
9799
let ssrc = read_stream.get_ssrc();
98100
assert_eq!(
99101
ssrc, TEST_SSRC,
100102
"SSRC mismatch during accept exp({TEST_SSRC}) actual({ssrc})"
101103
);
104+
assert_eq!(header, Some(packet.header));
102105

103106
read_stream.read(&mut read_buffer).await?;
104107

webrtc/src/peer_connection/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ use crate::rtp_transceiver::rtp_receiver::RTCRtpReceiver;
8181
use crate::rtp_transceiver::rtp_sender::RTCRtpSender;
8282
use crate::rtp_transceiver::rtp_transceiver_direction::RTCRtpTransceiverDirection;
8383
use crate::rtp_transceiver::{
84-
find_by_mid, handle_unknown_rtp_packet, satisfy_type_and_direction, RTCRtpTransceiver,
85-
RTCRtpTransceiverInit, SSRC,
84+
find_by_mid, satisfy_type_and_direction, RTCRtpTransceiver, RTCRtpTransceiverInit, SSRC,
8685
};
8786
use crate::sctp_transport::sctp_transport_capabilities::SCTPTransportCapabilities;
8887
use crate::sctp_transport::sctp_transport_state::RTCSctpTransportState;

webrtc/src/peer_connection/peer_connection_internal.rs

+71-53
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::VecDeque;
22
use std::sync::Weak;
33

44
use super::*;
5-
use crate::rtp_transceiver::create_stream_info;
5+
use crate::rtp_transceiver::{create_stream_info, PayloadType};
66
use crate::stats::stats_collector::StatsCollector;
77
use crate::stats::{
88
InboundRTPStats, OutboundRTPStats, RTCStatsType, RemoteInboundRTPStats, RemoteOutboundRTPStats,
@@ -15,7 +15,6 @@ use arc_swap::ArcSwapOption;
1515
use portable_atomic::AtomicIsize;
1616
use smol_str::SmolStr;
1717
use tokio::time::Instant;
18-
use util::Unmarshal;
1918

2019
pub(crate) struct PeerConnectionInternal {
2120
/// a value containing the last known greater mid value
@@ -309,8 +308,12 @@ impl PeerConnectionInternal {
309308
}
310309
};
311310

312-
let stream = match srtp_session.accept().await {
313-
Ok(stream) => stream,
311+
let (stream, header) = match srtp_session.accept().await {
312+
Ok((stream, Some(header))) => (stream, header),
313+
Ok((_, None)) => {
314+
log::error!("Accepting RTP session, without RTP header?");
315+
return;
316+
}
314317
Err(err) => {
315318
log::warn!("Failed to accept RTP {}", err);
316319
return;
@@ -338,16 +341,16 @@ impl PeerConnectionInternal {
338341
let pci = Arc::clone(&pci);
339342
tokio::spawn(async move {
340343
let ssrc = stream.get_ssrc();
341-
342344
dtls_transport
343345
.store_simulcast_stream(ssrc, Arc::clone(&stream))
344346
.await;
345347

346-
if let Err(err) = pci.handle_incoming_ssrc(stream, ssrc).await {
348+
if let Err(err) = pci
349+
.handle_incoming_rtp_stream(stream, header.payload_type)
350+
.await
351+
{
347352
log::warn!(
348-
"Incoming unhandled RTP ssrc({}), on_track will not be fired. {}",
349-
ssrc,
350-
err
353+
"Incoming unhandled RTP ssrc({ssrc}), on_track will not be fired. {err}"
351354
);
352355
}
353356

@@ -370,17 +373,18 @@ impl PeerConnectionInternal {
370373
}
371374
};
372375

373-
let stream = match srtcp_session.accept().await {
374-
Ok(stream) => stream,
376+
match srtcp_session.accept().await {
377+
Ok((stream, _)) => {
378+
let ssrc = stream.get_ssrc();
379+
log::warn!(
380+
"Incoming unhandled RTCP ssrc({ssrc}), on_track will not be fired"
381+
);
382+
}
375383
Err(err) => {
376-
log::warn!("Failed to accept RTCP {}", err);
384+
log::warn!("Failed to accept RTCP {err}");
377385
return;
378386
}
379387
};
380-
log::warn!(
381-
"Incoming unhandled RTCP ssrc({}), on_track will not be fired",
382-
stream.get_ssrc()
383-
);
384388
}
385389
});
386390
}
@@ -1002,18 +1006,18 @@ impl PeerConnectionInternal {
10021006
Ok(true)
10031007
}
10041008

1005-
async fn handle_incoming_ssrc(
1009+
async fn handle_incoming_rtp_stream(
10061010
self: &Arc<Self>,
10071011
rtp_stream: Arc<Stream>,
1008-
ssrc: SSRC,
1012+
payload_type: PayloadType,
10091013
) -> Result<()> {
1014+
let ssrc = rtp_stream.get_ssrc();
10101015
let parsed = match self.remote_description().await.and_then(|rd| rd.parsed) {
10111016
Some(r) => r,
10121017
None => return Err(Error::ErrPeerConnRemoteDescriptionNil),
10131018
};
10141019
// If the remote SDP was only one media section the ssrc doesn't have to be explicitly declared
1015-
let handled = self.handle_undeclared_ssrc(ssrc, &parsed).await?;
1016-
if handled {
1020+
if self.handle_undeclared_ssrc(ssrc, &parsed).await? {
10171021
return Ok(());
10181022
}
10191023

@@ -1046,26 +1050,6 @@ impl PeerConnectionInternal {
10461050
})
10471051
.await;
10481052

1049-
// Packets that we read as part of simulcast probing that we need to make available
1050-
// if we do find a track later.
1051-
let mut buffered_packets: VecDeque<(rtp::packet::Packet, Attributes)> = VecDeque::default();
1052-
1053-
let mut buf = vec![0u8; self.setting_engine.get_receive_mtu()];
1054-
let n = rtp_stream.read(&mut buf).await?;
1055-
let mut b = &buf[..n];
1056-
1057-
let (mut mid, mut rid, mut rsid, payload_type) = handle_unknown_rtp_packet(
1058-
b,
1059-
mid_extension_id as u8,
1060-
sid_extension_id as u8,
1061-
rsid_extension_id as u8,
1062-
)?;
1063-
1064-
let packet = rtp::packet::Packet::unmarshal(&mut b).unwrap();
1065-
1066-
// TODO: Can we have attributes on the first packets?
1067-
buffered_packets.push_back((packet, Attributes::new()));
1068-
10691053
let params = self
10701054
.media_engine
10711055
.get_rtp_parameters_by_payload_type(payload_type)
@@ -1089,21 +1073,24 @@ impl PeerConnectionInternal {
10891073
.streams_for_ssrc(ssrc, &stream_info, &icpr)
10901074
.await?;
10911075

1092-
let a = Attributes::new();
1076+
// Packets that we read as part of simulcast probing that we need to make available
1077+
// if we do find a track later.
1078+
let mut buffered_packets: VecDeque<(rtp::packet::Packet, Attributes)> = VecDeque::default();
1079+
let mut buf = vec![0u8; self.setting_engine.get_receive_mtu()];
1080+
10931081
for _ in 0..=SIMULCAST_PROBE_COUNT {
1082+
let (pkt, a) = rtp_interceptor
1083+
.read(&mut buf, &stream_info.attributes)
1084+
.await?;
1085+
let (mid, rid, rsid) = get_stream_mid_rid(
1086+
&pkt.header,
1087+
mid_extension_id as u8,
1088+
sid_extension_id as u8,
1089+
rsid_extension_id as u8,
1090+
)?;
1091+
buffered_packets.push_back((pkt, a.clone()));
1092+
10941093
if mid.is_empty() || (rid.is_empty() && rsid.is_empty()) {
1095-
let (pkt, _) = rtp_interceptor.read(&mut buf, &a).await?;
1096-
let (m, r, rs, _) = handle_unknown_rtp_packet(
1097-
&buf[..n],
1098-
mid_extension_id as u8,
1099-
sid_extension_id as u8,
1100-
rsid_extension_id as u8,
1101-
)?;
1102-
mid = m;
1103-
rid = r;
1104-
rsid = rs;
1105-
1106-
buffered_packets.push_back((pkt, a.clone()));
11071094
continue;
11081095
}
11091096

@@ -1544,3 +1531,34 @@ fn capitalize(s: &str) -> String {
15441531

15451532
result
15461533
}
1534+
1535+
fn get_stream_mid_rid(
1536+
header: &rtp::header::Header,
1537+
mid_extension_id: u8,
1538+
sid_extension_id: u8,
1539+
rsid_extension_id: u8,
1540+
) -> Result<(String, String, String)> {
1541+
if !header.extension {
1542+
return Ok((String::new(), String::new(), String::new()));
1543+
}
1544+
1545+
let mid = if let Some(payload) = header.get_extension(mid_extension_id) {
1546+
String::from_utf8(payload.to_vec())?
1547+
} else {
1548+
String::new()
1549+
};
1550+
1551+
let rid = if let Some(payload) = header.get_extension(sid_extension_id) {
1552+
String::from_utf8(payload.to_vec())?
1553+
} else {
1554+
String::new()
1555+
};
1556+
1557+
let srid = if let Some(payload) = header.get_extension(rsid_extension_id) {
1558+
String::from_utf8(payload.to_vec())?
1559+
} else {
1560+
String::new()
1561+
};
1562+
1563+
Ok((mid, rid, srid))
1564+
}

webrtc/src/rtp_transceiver/mod.rs

-39
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use portable_atomic::{AtomicBool, AtomicU8};
1414
use serde::{Deserialize, Serialize};
1515
use smol_str::SmolStr;
1616
use tokio::sync::{Mutex, OnceCell};
17-
use util::Unmarshal;
1817

1918
use crate::api::media_engine::MediaEngine;
2019
use crate::error::{Error, Result};
@@ -523,41 +522,3 @@ pub(crate) async fn satisfy_type_and_direction(
523522

524523
None
525524
}
526-
527-
/// handle_unknown_rtp_packet consumes a single RTP Packet and returns information that is helpful
528-
/// for demuxing and handling an unknown SSRC (usually for Simulcast)
529-
pub(crate) fn handle_unknown_rtp_packet(
530-
buf: &[u8],
531-
mid_extension_id: u8,
532-
sid_extension_id: u8,
533-
rsid_extension_id: u8,
534-
) -> Result<(String, String, String, PayloadType)> {
535-
let mut reader = buf;
536-
let rp = rtp::packet::Packet::unmarshal(&mut reader)?;
537-
538-
if !rp.header.extension {
539-
return Ok((String::new(), String::new(), String::new(), 0));
540-
}
541-
542-
let payload_type = rp.header.payload_type;
543-
544-
let mid = if let Some(payload) = rp.header.get_extension(mid_extension_id) {
545-
String::from_utf8(payload.to_vec())?
546-
} else {
547-
String::new()
548-
};
549-
550-
let rid = if let Some(payload) = rp.header.get_extension(sid_extension_id) {
551-
String::from_utf8(payload.to_vec())?
552-
} else {
553-
String::new()
554-
};
555-
556-
let srid = if let Some(payload) = rp.header.get_extension(rsid_extension_id) {
557-
String::from_utf8(payload.to_vec())?
558-
} else {
559-
String::new()
560-
};
561-
562-
Ok((mid, rid, srid, payload_type))
563-
}

0 commit comments

Comments
 (0)