Skip to content

Commit 92208f2

Browse files
authored
fix: accept any session name in SDP, not just "s=-"
1 parent 01cee0b commit 92208f2

2 files changed

Lines changed: 116 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Unreleased
22

3+
* Accept any non-empty SDP session name (`s=`), not just `s=-` (RFC 8866 section 5.3)
4+
35
# 0.20.0
46

57
* Update dimpl to 0.6.2 and sctp-proto to 0.9.1

src/sdp/parser.rs

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ where
3131
/// 1. First line must be v=0
3232
/// 2. The second SDP line MUST be an "o=" line The sess-id MUST be representable by a 64-bit signed
3333
/// integer, and the initial value MUST be less than (2**62)-1
34-
/// 3. Third line a single dash SHOULD be used as the session name, e.g. "s=-"
34+
/// 3. Third line is the session name. The "s=" field MUST NOT be empty and SHOULD contain
35+
/// ISO 10646 characters (RFC 8866 section 5.3).
3536
///
3637
/// Session is over when we find a "t=" line MUST be added, both <start-time> and <stop-time>
3738
/// SHOULD be set to zero, e.g. "t=0 0".
@@ -43,7 +44,8 @@ where
4344
(
4445
typed_line('v', token('0')), // v=0
4546
originator_line(), // o=- 6564425948916445306 2 IN IP4 127.0.0.1
46-
typed_line('s', token('-')), // s=-
47+
// The "s=" field MUST NOT be empty (RFC 8866 section 5.3)
48+
typed_line('s', any_value()),
4749
many::<Vec<_>, _, _>(ignored_session_line()),
4850
optional(bandwidth_line()), // b=CT:1234
4951
typed_line('t', string("0 0")), // t=0 0
@@ -1034,6 +1036,58 @@ mod test {
10341036
);
10351037
}
10361038

1039+
#[test]
1040+
fn session_parser_named_session() {
1041+
// A session name other than "-".
1042+
let sdp = "v=0\r\n\
1043+
o=publisher 4489045141692799359 2 IN IP4 127.0.0.1\r\n\
1044+
s=NamedPublishSession\r\n\
1045+
t=0 0\r\n\
1046+
a=group:BUNDLE 0 1\r\n\
1047+
a=extmap-allow-mixed\r\n\
1048+
a=msid-semantic: WMS\r\n";
1049+
assert_eq!(
1050+
session_parser().parse(sdp),
1051+
Ok((
1052+
Session {
1053+
id: 4_489_045_141_692_799_359.into(),
1054+
bw: None,
1055+
attrs: vec![
1056+
SessionAttribute::Group {
1057+
typ: "BUNDLE".into(),
1058+
mids: vec!["0".into(), "1".into()],
1059+
},
1060+
SessionAttribute::Unused("extmap-allow-mixed".into()),
1061+
SessionAttribute::Unused("msid-semantic: WMS".into()),
1062+
],
1063+
},
1064+
""
1065+
))
1066+
);
1067+
}
1068+
1069+
#[test]
1070+
fn session_parser_space_session_name() {
1071+
// "If a session has no meaningful name, the value "s= " SHOULD be used
1072+
// (i.e., a single space as the session name)." (RFC 8866 section 5.3)
1073+
let sdp = "v=0\n\
1074+
o=- 6564425948916445306 2 IN IP4 127.0.0.1\n\
1075+
s= \n\
1076+
t=0 0\n\
1077+
";
1078+
assert_eq!(
1079+
session_parser().parse(sdp),
1080+
Ok((
1081+
Session {
1082+
id: 6_564_425_948_916_445_306.into(),
1083+
bw: None,
1084+
attrs: vec![],
1085+
},
1086+
""
1087+
))
1088+
);
1089+
}
1090+
10371091
#[test]
10381092
fn parse_sdp_firefox() {
10391093
let sdp = "v=0\r\n\
@@ -1163,6 +1217,64 @@ mod test {
11631217
assert!(parsed.is_ok());
11641218
}
11651219

1220+
#[test]
1221+
fn parse_offer_sdp_ffmpeg_whip() {
1222+
// ffmpeg -re \
1223+
// -f lavfi -i "testsrc=size=640x480:rate=30" \
1224+
// -f lavfi -i "sine=frequency=440:sample_rate=48000" \
1225+
// -c:v libx264 -profile:v baseline -pix_fmt yuv420p -g 60 -tune zerolatency \
1226+
// -c:a libopus -ar 48000 -ac 2 \
1227+
// -f whip "http://127.0.0.1:8080/whip"
1228+
let sdp = "v=0\r\n\
1229+
o=FFmpeg 4489045141692799359 2 IN IP4 127.0.0.1\r\n\
1230+
s=FFmpegPublishSession\r\n\
1231+
t=0 0\r\n\
1232+
a=group:BUNDLE 0 1\r\n\
1233+
a=extmap-allow-mixed\r\n\
1234+
a=msid-semantic: WMS\r\n\
1235+
m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n\
1236+
c=IN IP4 0.0.0.0\r\n\
1237+
a=ice-ufrag:08a9c3f4\r\n\
1238+
a=ice-pwd:a202d23be47d1decaa6f67d04d4e6c16\r\n\
1239+
a=fingerprint:sha-256 21:69:7C:46:D3:DC:4D:D3:66:61:5C:C5:6A:0B:F7:36\
1240+
:BD:91:A9:2A:FF:BC:1A:59:D9:38:38:C8:E2:A4:8D:AF\r\n\
1241+
a=setup:passive\r\n\
1242+
a=mid:0\r\n\
1243+
a=sendonly\r\n\
1244+
a=msid:FFmpeg audio\r\n\
1245+
a=rtcp-mux\r\n\
1246+
a=rtpmap:111 opus/48000/2\r\n\
1247+
a=ssrc:3166090378 cname:FFmpeg\r\n\
1248+
a=ssrc:3166090378 msid:FFmpeg audio\r\n\
1249+
m=video 9 UDP/TLS/RTP/SAVPF 106 105\r\n\
1250+
c=IN IP4 0.0.0.0\r\n\
1251+
a=ice-ufrag:08a9c3f4\r\n\
1252+
a=ice-pwd:a202d23be47d1decaa6f67d04d4e6c16\r\n\
1253+
a=fingerprint:sha-256 21:69:7C:46:D3:DC:4D:D3:66:61:5C:C5:6A:0B:F7:36\
1254+
:BD:91:A9:2A:FF:BC:1A:59:D9:38:38:C8:E2:A4:8D:AF\r\n\
1255+
a=setup:passive\r\n\
1256+
a=mid:1\r\n\
1257+
a=sendonly\r\n\
1258+
a=msid:FFmpeg video\r\n\
1259+
a=rtcp-mux\r\n\
1260+
a=rtcp-rsize\r\n\
1261+
a=rtpmap:106 H264/90000\r\n\
1262+
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001e\r\n\
1263+
a=rtcp-fb:106 nack\r\n\
1264+
a=rtpmap:105 rtx/90000\r\n\
1265+
a=fmtp:105 apt=106\r\n\
1266+
a=ssrc-group:FID 3166090379 3166090380\r\n\
1267+
a=ssrc:3166090379 cname:FFmpeg\r\n\
1268+
a=ssrc:3166090379 msid:FFmpeg video\r\n\
1269+
";
1270+
1271+
let (sdp, _) = sdp_parser().parse(sdp).unwrap();
1272+
1273+
assert_eq!(sdp.media_lines.len(), 2);
1274+
assert_eq!(sdp.media_lines[0].mid().to_string(), "0");
1275+
assert_eq!(sdp.media_lines[1].mid().to_string(), "1");
1276+
}
1277+
11661278
#[test]
11671279
fn parse_safari_data_channel() {
11681280
let sdp = "v=0\r\n\

0 commit comments

Comments
 (0)