From bf0223b3a0d7cb9417807237728e6dc205a6a8ab Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Wed, 21 Dec 2022 20:26:44 +0100 Subject: [PATCH] sdp: move serialization of ice, dtls and header extensions to helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit preparing to put them at session level when max-bundle is set. Drive-by: move m= serialization to helper. BUG=None Change-Id: I04d918ee8eb70c0cc40baf8ebc12054c6b3a2a15 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/288820 Commit-Queue: Philipp Hancke Reviewed-by: Harald Alvestrand Reviewed-by: Henrik Boström Cr-Commit-Position: refs/heads/main@{#38950} --- pc/webrtc_sdp.cc | 179 +++++++++++++++++++++++++++++------------------ pc/webrtc_sdp.h | 1 - 2 files changed, 110 insertions(+), 70 deletions(-) diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc index 69fa62ca37..3b347466d8 100644 --- a/pc/webrtc_sdp.cc +++ b/pc/webrtc_sdp.cc @@ -277,16 +277,26 @@ static void BuildMediaDescription(const ContentInfo* content_info, const std::vector& candidates, int msid_signaling, std::string* message); +static void BuildMediaLine(const cricket::MediaType media_type, + const ContentInfo* content_info, + const MediaContentDescription* media_desc, + std::string* message); static void BuildRtpContentAttributes(const MediaContentDescription* media_desc, const cricket::MediaType media_type, int msid_signaling, std::string* message); +static void BuildRtpHeaderExtensions(const RtpHeaderExtensions& extensions, + std::string* message); static void BuildRtpmap(const MediaContentDescription* media_desc, const cricket::MediaType media_type, std::string* message); static void BuildCandidate(const std::vector& candidates, bool include_ufrag, std::string* message); +static void BuildIceUfragPwd(const TransportInfo* transport_info, + std::string* message); +static void BuildDtlsFingerprintSetup(const TransportInfo* transport_info, + std::string* message); static void BuildIceOptions(const std::vector& transport_options, std::string* message); static bool ParseSessionDescription(absl::string_view message, @@ -1360,19 +1370,66 @@ static void BuildSctpContentAttributes( } } -void BuildMediaDescription(const ContentInfo* content_info, - const TransportInfo* transport_info, - const cricket::MediaType media_type, - const std::vector& candidates, - int msid_signaling, - std::string* message) { - RTC_DCHECK(message != NULL); - if (content_info == NULL || message == NULL) { +void BuildIceUfragPwd(const TransportInfo* transport_info, + std::string* message) { + RTC_DCHECK(transport_info); + + rtc::StringBuilder os; + // RFC 5245 + // ice-pwd-att = "ice-pwd" ":" password + // ice-ufrag-att = "ice-ufrag" ":" ufrag + // ice-ufrag + if (!transport_info->description.ice_ufrag.empty()) { + InitAttrLine(kAttributeIceUfrag, &os); + os << kSdpDelimiterColon << transport_info->description.ice_ufrag; + AddLine(os.str(), message); + } + // ice-pwd + if (!transport_info->description.ice_pwd.empty()) { + InitAttrLine(kAttributeIcePwd, &os); + os << kSdpDelimiterColon << transport_info->description.ice_pwd; + AddLine(os.str(), message); + } +} + +void BuildDtlsFingerprintSetup(const TransportInfo* transport_info, + std::string* message) { + RTC_DCHECK(transport_info); + + rtc::StringBuilder os; + // RFC 4572 + // fingerprint-attribute = + // "fingerprint" ":" hash-func SP fingerprint + // When using max-bundle this is already included at session level. + // Insert the fingerprint attribute. + auto fingerprint = transport_info->description.identity_fingerprint.get(); + if (!fingerprint) { return; } + InitAttrLine(kAttributeFingerprint, &os); + os << kSdpDelimiterColon << fingerprint->algorithm << kSdpDelimiterSpace + << fingerprint->GetRfc4572Fingerprint(); + AddLine(os.str(), message); + + // Inserting setup attribute. + if (transport_info->description.connection_role != + cricket::CONNECTIONROLE_NONE) { + // Making sure we are not using "passive" mode. + cricket::ConnectionRole role = transport_info->description.connection_role; + std::string dtls_role_str; + const bool success = cricket::ConnectionRoleToString(role, &dtls_role_str); + RTC_DCHECK(success); + InitAttrLine(kAttributeSetup, &os); + os << kSdpDelimiterColon << dtls_role_str; + AddLine(os.str(), message); + } +} + +void BuildMediaLine(const cricket::MediaType media_type, + const ContentInfo* content_info, + const MediaContentDescription* media_desc, + std::string* message) { rtc::StringBuilder os; - const MediaContentDescription* media_desc = content_info->media_description(); - RTC_DCHECK(media_desc); // RFC 4566 // m= @@ -1438,15 +1495,29 @@ void BuildMediaDescription(const ContentInfo* content_info, port = rtc::ToString(media_desc->connection_address().port()); } - rtc::SSLFingerprint* fp = - (transport_info) ? transport_info->description.identity_fingerprint.get() - : NULL; - // Add the m and c lines. InitLine(kLineTypeMedia, type, &os); os << " " << port << " " << media_desc->protocol() << fmt; AddLine(os.str(), message); +} +void BuildMediaDescription(const ContentInfo* content_info, + const TransportInfo* transport_info, + const cricket::MediaType media_type, + const std::vector& candidates, + int msid_signaling, + std::string* message) { + RTC_DCHECK(message); + if (!content_info) { + return; + } + rtc::StringBuilder os; + const MediaContentDescription* media_desc = content_info->media_description(); + RTC_DCHECK(media_desc); + + // Add the m line. + BuildMediaLine(media_type, content_info, media_desc, message); + // Add the c line. InitLine(kLineTypeConnection, kConnectionNettype, &os); if (media_desc->connection_address().IsNil()) { os << " " << kConnectionIpv4Addrtype << " " << kDummyAddress; @@ -1495,52 +1566,16 @@ void BuildMediaDescription(const ContentInfo* content_info, // candidates in the SDP to avoid redundancy. BuildCandidate(candidates, false, message); - // Use the transport_info to build the media level ice-ufrag and ice-pwd. + // Use the transport_info to build the media level ice-ufrag, ice-pwd + // and DTLS fingerprint and setup attributes. if (transport_info) { - // RFC 5245 - // ice-pwd-att = "ice-pwd" ":" password - // ice-ufrag-att = "ice-ufrag" ":" ufrag - // ice-ufrag - if (!transport_info->description.ice_ufrag.empty()) { - InitAttrLine(kAttributeIceUfrag, &os); - os << kSdpDelimiterColon << transport_info->description.ice_ufrag; - AddLine(os.str(), message); - } - // ice-pwd - if (!transport_info->description.ice_pwd.empty()) { - InitAttrLine(kAttributeIcePwd, &os); - os << kSdpDelimiterColon << transport_info->description.ice_pwd; - AddLine(os.str(), message); - } + BuildIceUfragPwd(transport_info, message); // draft-petithuguenin-mmusic-ice-attributes-level-03 BuildIceOptions(transport_info->description.transport_options, message); - // RFC 4572 - // fingerprint-attribute = - // "fingerprint" ":" hash-func SP fingerprint - if (fp) { - // Insert the fingerprint attribute. - InitAttrLine(kAttributeFingerprint, &os); - os << kSdpDelimiterColon << fp->algorithm << kSdpDelimiterSpace - << fp->GetRfc4572Fingerprint(); - AddLine(os.str(), message); - - // Inserting setup attribute. - if (transport_info->description.connection_role != - cricket::CONNECTIONROLE_NONE) { - // Making sure we are not using "passive" mode. - cricket::ConnectionRole role = - transport_info->description.connection_role; - std::string dtls_role_str; - const bool success = - cricket::ConnectionRoleToString(role, &dtls_role_str); - RTC_DCHECK(success); - InitAttrLine(kAttributeSetup, &os); - os << kSdpDelimiterColon << dtls_role_str; - AddLine(os.str(), message); - } - } + // Also include the DTLS fingerprint and setup attribute if available. + BuildDtlsFingerprintSetup(transport_info, message); } // RFC 3388 @@ -1576,20 +1611,7 @@ void BuildRtpContentAttributes(const MediaContentDescription* media_desc, InitAttrLine(kAttributeExtmapAllowMixed, &os); AddLine(os.str(), message); } - // RFC 8285 - // a=extmap:["/"] - // The definitions MUST be either all session level or all media level. This - // implementation uses all media level. - for (size_t i = 0; i < media_desc->rtp_header_extensions().size(); ++i) { - const RtpExtension& extension = media_desc->rtp_header_extensions()[i]; - InitAttrLine(kAttributeExtmap, &os); - os << kSdpDelimiterColon << extension.id; - if (extension.encrypt) { - os << kSdpDelimiterSpace << RtpExtension::kEncryptHeaderExtensionsUri; - } - os << kSdpDelimiterSpace << extension.uri; - AddLine(os.str(), message); - } + BuildRtpHeaderExtensions(media_desc->rtp_header_extensions(), message); // RFC 3264 // a=sendrecv || a=sendonly || a=sendrecv || a=inactive @@ -1754,6 +1776,25 @@ void BuildRtpContentAttributes(const MediaContentDescription* media_desc, } } +void BuildRtpHeaderExtensions(const RtpHeaderExtensions& extensions, + std::string* message) { + rtc::StringBuilder os; + + // RFC 8285 + // a=extmap:["/"] + // The definitions MUST be either all session level or all media level. This + // implementation uses all media level. + for (const RtpExtension& extension : extensions) { + InitAttrLine(kAttributeExtmap, &os); + os << kSdpDelimiterColon << extension.id; + if (extension.encrypt) { + os << kSdpDelimiterSpace << RtpExtension::kEncryptHeaderExtensionsUri; + } + os << kSdpDelimiterSpace << extension.uri; + AddLine(os.str(), message); + } +} + void WriteFmtpHeader(int payload_type, rtc::StringBuilder* os) { // fmtp header: a=fmtp:`payload_type` // Add a=fmtp diff --git a/pc/webrtc_sdp.h b/pc/webrtc_sdp.h index cc6813caec..f7759bd139 100644 --- a/pc/webrtc_sdp.h +++ b/pc/webrtc_sdp.h @@ -49,7 +49,6 @@ struct SdpParseError; // Serialize SessionDescription including candidates if // JsepSessionDescription has candidates. // jdesc - The JsepSessionDescription object to be serialized. -// unified_plan_sdp - If set to true, include "a=msid" lines where appropriate. // return - SDP string serialized from the arguments. std::string SdpSerialize(const JsepSessionDescription& jdesc);