Refactor GetLine function to use string_view

Bug: webrtc:13579
Change-Id: I01b7a2e20b7ff976aa50f7dd068431eb288e6fae
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261904
Reviewed-by: Ali Tofigh <alito@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36861}
This commit is contained in:
Niels Möller
2022-05-12 10:21:37 +02:00
committed by WebRTC LUCI CQ
parent 2f0f285d53
commit 810057cf96

View File

@ -218,7 +218,6 @@ static const char kSdpDelimiterColonChar = ':';
static const char kSdpDelimiterSemicolon[] = ";";
static const char kSdpDelimiterSemicolonChar = ';';
static const char kSdpDelimiterSlashChar = '/';
static const char kNewLine[] = "\n";
static const char kNewLineChar = '\n';
static const char kReturnChar = '\r';
static const char kLineBreak[] = "\r\n";
@ -401,7 +400,7 @@ static bool ParseFailed(absl::string_view message,
SdpParseError* error) {
// Get the first line of `message` from `line_start`.
absl::string_view first_line;
size_t line_end = message.find(kNewLine, line_start);
size_t line_end = message.find(kNewLineChar, line_start);
if (line_end != std::string::npos) {
if (line_end > 0 && (message.at(line_end - 1) == kReturnChar)) {
--line_end;
@ -490,19 +489,25 @@ static bool AddLine(absl::string_view line, std::string* message) {
return true;
}
static bool GetLine(absl::string_view message, size_t* pos, std::string* line) {
size_t line_begin = *pos;
size_t line_end = message.find(kNewLine, line_begin);
// Trim return character, if any.
static absl::string_view TrimReturnChar(absl::string_view line) {
if (!line.empty() && line.back() == kReturnChar) {
line.remove_suffix(1);
}
return line;
}
// Gets line of `message` starting at `pos`, and checks overall SDP syntax. On
// success, advances `pos` to the next line.
static absl::optional<absl::string_view> GetLine(absl::string_view message,
size_t* pos) {
size_t line_end = message.find(kNewLineChar, *pos);
if (line_end == absl::string_view::npos) {
return false;
return absl::nullopt;
}
// Update the new start position
*pos = line_end + 1;
if (line_end > 0 && (message.at(line_end - 1) == kReturnChar)) {
--line_end;
}
*line = std::string(message.substr(line_begin, (line_end - line_begin)));
const char* cline = line->c_str();
absl::string_view line =
TrimReturnChar(message.substr(*pos, line_end - *pos));
// RFC 4566
// An SDP session description consists of a number of lines of text of
// the form:
@ -516,14 +521,13 @@ static bool GetLine(absl::string_view message, size_t* pos, std::string* line) {
//
// If a session has no meaningful name, the value "s= " SHOULD be used
// (i.e., a single space as the session name).
if (line->length() < 3 || !islower(cline[0]) ||
cline[1] != kSdpDelimiterEqualChar ||
(cline[0] != kLineTypeSessionName &&
cline[2] == kSdpDelimiterSpaceChar)) {
*pos = line_begin;
return false;
if (line.length() < 3 || !islower(static_cast<unsigned char>(line[0])) ||
line[1] != kSdpDelimiterEqualChar ||
(line[0] != kLineTypeSessionName && line[2] == kSdpDelimiterSpaceChar)) {
return absl::nullopt;
}
return true;
*pos = line_end + 1;
return line;
}
// Init `os` to "`type`=`value`".
@ -563,18 +567,12 @@ static bool IsLineType(absl::string_view line, const char type) {
return IsLineType(line, type, 0);
}
static bool GetLineWithType(absl::string_view message,
size_t* pos,
std::string* line,
const char type) {
if (!IsLineType(message, type, *pos)) {
return false;
static absl::optional<absl::string_view>
GetLineWithType(absl::string_view message, size_t* pos, const char type) {
if (IsLineType(message, type, *pos)) {
return GetLine(message, pos);
}
if (!GetLine(message, pos, line))
return false;
return true;
return absl::nullopt;
}
static bool HasAttribute(absl::string_view line, absl::string_view attribute) {
@ -1038,20 +1036,21 @@ bool ParseCandidate(absl::string_view message,
bool is_raw) {
RTC_DCHECK(candidate != NULL);
// Get the first line from `message`.
std::string first_line = std::string(message);
size_t pos = 0;
GetLine(message, &pos, &first_line);
// Makes sure `message` contains only one line.
if (message.size() > first_line.size()) {
std::string left, right;
if (rtc::tokenize_first(message, kNewLineChar, &left, &right) &&
!right.empty()) {
return ParseFailed(message, 0, "Expect one line only", error);
}
absl::string_view first_line;
size_t line_end = message.find(kNewLineChar);
if (line_end == absl::string_view::npos) {
first_line = message;
} else if (line_end + 1 == message.size()) {
first_line = message.substr(0, line_end);
} else {
return ParseFailed(message, 0, "Expect one line only", error);
}
// Trim return char, if any.
first_line = TrimReturnChar(first_line);
// From WebRTC draft section 4.8.1.1 candidate-attribute should be
// candidate:<candidate> when trickled, but we still support
// a=candidate:<blah>CRLF for backward compatibility and for parsing a line
@ -2097,69 +2096,74 @@ bool ParseSessionDescription(absl::string_view message,
rtc::SocketAddress* connection_addr,
cricket::SessionDescription* desc,
SdpParseError* error) {
std::string line;
absl::optional<absl::string_view> line;
desc->set_msid_supported(false);
desc->set_extmap_allow_mixed(false);
// RFC 4566
// v= (protocol version)
if (!GetLineWithType(message, pos, &line, kLineTypeVersion)) {
line = GetLineWithType(message, pos, kLineTypeVersion);
if (!line) {
return ParseFailedExpectLine(message, *pos, kLineTypeVersion, std::string(),
error);
}
// RFC 4566
// o=<username> <sess-id> <sess-version> <nettype> <addrtype>
// <unicast-address>
if (!GetLineWithType(message, pos, &line, kLineTypeOrigin)) {
line = GetLineWithType(message, pos, kLineTypeOrigin);
if (!line) {
return ParseFailedExpectLine(message, *pos, kLineTypeOrigin, std::string(),
error);
}
std::vector<std::string> fields;
rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields);
rtc::split(line->substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields);
const size_t expected_fields = 6;
if (fields.size() != expected_fields) {
return ParseFailedExpectFieldNum(line, expected_fields, error);
return ParseFailedExpectFieldNum(*line, expected_fields, error);
}
*session_id = fields[1];
*session_version = fields[2];
// RFC 4566
// s= (session name)
if (!GetLineWithType(message, pos, &line, kLineTypeSessionName)) {
line = GetLineWithType(message, pos, kLineTypeSessionName);
if (!line) {
return ParseFailedExpectLine(message, *pos, kLineTypeSessionName,
std::string(), error);
}
// absl::optional lines
// optional lines
// Those are the optional lines, so shouldn't return false if not present.
// RFC 4566
// i=* (session information)
GetLineWithType(message, pos, &line, kLineTypeSessionInfo);
GetLineWithType(message, pos, kLineTypeSessionInfo);
// RFC 4566
// u=* (URI of description)
GetLineWithType(message, pos, &line, kLineTypeSessionUri);
GetLineWithType(message, pos, kLineTypeSessionUri);
// RFC 4566
// e=* (email address)
GetLineWithType(message, pos, &line, kLineTypeSessionEmail);
GetLineWithType(message, pos, kLineTypeSessionEmail);
// RFC 4566
// p=* (phone number)
GetLineWithType(message, pos, &line, kLineTypeSessionPhone);
GetLineWithType(message, pos, kLineTypeSessionPhone);
// RFC 4566
// c=* (connection information -- not required if included in
// all media)
if (GetLineWithType(message, pos, &line, kLineTypeConnection)) {
if (!ParseConnectionData(line, connection_addr, error)) {
if (absl::optional<absl::string_view> cline =
GetLineWithType(message, pos, kLineTypeConnection);
cline.has_value()) {
if (!ParseConnectionData(*cline, connection_addr, error)) {
return false;
}
}
// RFC 4566
// b=* (zero or more bandwidth information lines)
while (GetLineWithType(message, pos, &line, kLineTypeSessionBandwidth)) {
while (GetLineWithType(message, pos, kLineTypeSessionBandwidth).has_value()) {
// By pass zero or more b lines.
}
@ -2168,80 +2172,81 @@ bool ParseSessionDescription(absl::string_view message,
// t= (time the session is active)
// r=* (zero or more repeat times)
// Ensure there's at least one time description
if (!GetLineWithType(message, pos, &line, kLineTypeTiming)) {
if (!GetLineWithType(message, pos, kLineTypeTiming).has_value()) {
return ParseFailedExpectLine(message, *pos, kLineTypeTiming, std::string(),
error);
}
while (GetLineWithType(message, pos, &line, kLineTypeRepeatTimes)) {
while (GetLineWithType(message, pos, kLineTypeRepeatTimes).has_value()) {
// By pass zero or more r lines.
}
// Go through the rest of the time descriptions
while (GetLineWithType(message, pos, &line, kLineTypeTiming)) {
while (GetLineWithType(message, pos, &line, kLineTypeRepeatTimes)) {
while (GetLineWithType(message, pos, kLineTypeTiming).has_value()) {
while (GetLineWithType(message, pos, kLineTypeRepeatTimes).has_value()) {
// By pass zero or more r lines.
}
}
// RFC 4566
// z=* (time zone adjustments)
GetLineWithType(message, pos, &line, kLineTypeTimeZone);
GetLineWithType(message, pos, kLineTypeTimeZone);
// RFC 4566
// k=* (encryption key)
GetLineWithType(message, pos, &line, kLineTypeEncryptionKey);
GetLineWithType(message, pos, kLineTypeEncryptionKey);
// RFC 4566
// a=* (zero or more session attribute lines)
while (GetLineWithType(message, pos, &line, kLineTypeAttributes)) {
if (HasAttribute(line, kAttributeGroup)) {
if (!ParseGroupAttribute(line, desc, error)) {
while (absl::optional<absl::string_view> aline =
GetLineWithType(message, pos, kLineTypeAttributes)) {
if (HasAttribute(*aline, kAttributeGroup)) {
if (!ParseGroupAttribute(*aline, desc, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeIceUfrag)) {
if (!GetValue(line, kAttributeIceUfrag, &(session_td->ice_ufrag),
} else if (HasAttribute(*aline, kAttributeIceUfrag)) {
if (!GetValue(*aline, kAttributeIceUfrag, &(session_td->ice_ufrag),
error)) {
return false;
}
} else if (HasAttribute(line, kAttributeIcePwd)) {
if (!GetValue(line, kAttributeIcePwd, &(session_td->ice_pwd), error)) {
} else if (HasAttribute(*aline, kAttributeIcePwd)) {
if (!GetValue(*aline, kAttributeIcePwd, &(session_td->ice_pwd), error)) {
return false;
}
} else if (HasAttribute(line, kAttributeIceLite)) {
} else if (HasAttribute(*aline, kAttributeIceLite)) {
session_td->ice_mode = cricket::ICEMODE_LITE;
} else if (HasAttribute(line, kAttributeIceOption)) {
if (!ParseIceOptions(line, &(session_td->transport_options), error)) {
} else if (HasAttribute(*aline, kAttributeIceOption)) {
if (!ParseIceOptions(*aline, &(session_td->transport_options), error)) {
return false;
}
} else if (HasAttribute(line, kAttributeFingerprint)) {
} else if (HasAttribute(*aline, kAttributeFingerprint)) {
if (session_td->identity_fingerprint.get()) {
return ParseFailed(
line,
*aline,
"Can't have multiple fingerprint attributes at the same level.",
error);
}
std::unique_ptr<rtc::SSLFingerprint> fingerprint;
if (!ParseFingerprintAttribute(line, &fingerprint, error)) {
if (!ParseFingerprintAttribute(*aline, &fingerprint, error)) {
return false;
}
session_td->identity_fingerprint = std::move(fingerprint);
} else if (HasAttribute(line, kAttributeSetup)) {
if (!ParseDtlsSetup(line, &(session_td->connection_role), error)) {
} else if (HasAttribute(*aline, kAttributeSetup)) {
if (!ParseDtlsSetup(*aline, &(session_td->connection_role), error)) {
return false;
}
} else if (HasAttribute(line, kAttributeMsidSemantics)) {
} else if (HasAttribute(*aline, kAttributeMsidSemantics)) {
std::string semantics;
if (!GetValue(line, kAttributeMsidSemantics, &semantics, error)) {
if (!GetValue(*aline, kAttributeMsidSemantics, &semantics, error)) {
return false;
}
desc->set_msid_supported(
CaseInsensitiveFind(semantics, kMediaStreamSemantic));
} else if (HasAttribute(line, kAttributeExtmapAllowMixed)) {
} else if (HasAttribute(*aline, kAttributeExtmapAllowMixed)) {
desc->set_extmap_allow_mixed(true);
} else if (HasAttribute(line, kAttributeExtmap)) {
} else if (HasAttribute(*aline, kAttributeExtmap)) {
RtpExtension extmap;
if (!ParseExtmap(line, &extmap, error)) {
if (!ParseExtmap(*aline, &extmap, error)) {
return false;
}
session_extmaps->push_back(extmap);
@ -2607,22 +2612,23 @@ bool ParseMediaDescription(
std::vector<std::unique_ptr<JsepIceCandidate>>* candidates,
SdpParseError* error) {
RTC_DCHECK(desc != NULL);
std::string line;
int mline_index = -1;
int msid_signaling = 0;
// Zero or more media descriptions
// RFC 4566
// m=<media> <port> <proto> <fmt>
while (GetLineWithType(message, pos, &line, kLineTypeMedia)) {
while (absl::optional<absl::string_view> mline =
GetLineWithType(message, pos, kLineTypeMedia)) {
++mline_index;
std::vector<std::string> fields;
rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields);
rtc::split(mline->substr(kLinePrefixLength), kSdpDelimiterSpaceChar,
&fields);
const size_t expected_min_fields = 4;
if (fields.size() < expected_min_fields) {
return ParseFailedExpectMinFieldNum(line, expected_min_fields, error);
return ParseFailedExpectMinFieldNum(*mline, expected_min_fields, error);
}
bool port_rejected = false;
// RFC 3264
@ -2634,7 +2640,7 @@ bool ParseMediaDescription(
int port = 0;
if (!rtc::FromString<int>(fields[1], &port) || !IsValidPort(port)) {
return ParseFailed(line, "The port number is invalid", error);
return ParseFailed(*mline, "The port number is invalid", error);
}
const std::string& protocol = fields[2];
@ -2643,7 +2649,7 @@ bool ParseMediaDescription(
if (cricket::IsRtpProtocol(protocol)) {
for (size_t j = 3; j < fields.size(); ++j) {
int pl = 0;
if (!GetPayloadTypeFromString(line, fields[j], &pl, error)) {
if (!GetPayloadTypeFromString(*mline, fields[j], &pl, error)) {
return false;
}
payload_types.push_back(pl);
@ -2664,7 +2670,7 @@ bool ParseMediaDescription(
const std::string& media_type = fields[0];
if ((media_type == kMediaTypeVideo || media_type == kMediaTypeAudio) &&
!cricket::IsRtpProtocol(protocol)) {
return ParseFailed(line, "Unsupported protocol for media type", error);
return ParseFailed(*mline, "Unsupported protocol for media type", error);
}
if (media_type == kMediaTypeVideo) {
content = ParseContentDescription<VideoContentDescription>(
@ -2703,10 +2709,11 @@ bool ParseMediaDescription(
data_desc->set_protocol(protocol);
content = std::move(data_desc);
} else {
return ParseFailed(line, "Unsupported protocol for media type", error);
return ParseFailed(*mline, "Unsupported protocol for media type",
error);
}
} else {
RTC_LOG(LS_WARNING) << "Unsupported media type: " << line;
RTC_LOG(LS_WARNING) << "Unsupported media type: " << *mline;
auto unsupported_desc =
std::make_unique<UnsupportedContentDescription>(media_type);
if (!ParseContent(message, cricket::MEDIA_TYPE_UNSUPPORTED, mline_index,
@ -2971,7 +2978,6 @@ bool ParseContent(absl::string_view message,
// The media level "ice-ufrag" and "ice-pwd".
// The candidates before update the media level "ice-pwd" and "ice-ufrag".
Candidates candidates_orig;
std::string line;
std::string mline_id;
// Tracks created out of the ssrc attributes.
StreamParamsVec tracks;
@ -2987,7 +2993,8 @@ bool ParseContent(absl::string_view message,
// Loop until the next m line
while (!IsLineType(message, kLineTypeMedia, *pos)) {
if (!GetLine(message, pos, &line)) {
absl::optional<absl::string_view> line = GetLine(message, pos);
if (!line.has_value()) {
if (*pos >= message.size()) {
break; // Done parsing
} else {
@ -2997,14 +3004,14 @@ bool ParseContent(absl::string_view message,
// RFC 4566
// b=* (zero or more bandwidth information lines)
if (IsLineType(line, kLineTypeSessionBandwidth)) {
if (IsLineType(*line, kLineTypeSessionBandwidth)) {
std::string bandwidth;
std::string bandwidth_type;
if (!rtc::tokenize_first(line.substr(kLinePrefixLength),
if (!rtc::tokenize_first(line->substr(kLinePrefixLength),
kSdpDelimiterColonChar, &bandwidth_type,
&bandwidth)) {
return ParseFailed(
line,
*line,
"b= syntax error, does not match b=<modifier>:<bandwidth-value>.",
error);
}
@ -3014,7 +3021,7 @@ bool ParseContent(absl::string_view message,
continue;
}
int b = 0;
if (!GetValueFromString(line, bandwidth, &b, error)) {
if (!GetValueFromString(*line, bandwidth, &b, error)) {
return false;
}
// TODO(deadbeef): Historically, applications may be setting a value
@ -3029,7 +3036,7 @@ bool ParseContent(absl::string_view message,
}
if (b < 0) {
return ParseFailed(
line, "b=" + bandwidth_type + " value can't be negative.", error);
*line, "b=" + bandwidth_type + " value can't be negative.", error);
}
// Convert values. Prevent integer overflow.
if (bandwidth_type == kApplicationSpecificBandwidth) {
@ -3043,36 +3050,36 @@ bool ParseContent(absl::string_view message,
}
// Parse the media level connection data.
if (IsLineType(line, kLineTypeConnection)) {
if (IsLineType(*line, kLineTypeConnection)) {
rtc::SocketAddress addr;
if (!ParseConnectionData(line, &addr, error)) {
if (!ParseConnectionData(*line, &addr, error)) {
return false;
}
media_desc->set_connection_address(addr);
continue;
}
if (!IsLineType(line, kLineTypeAttributes)) {
if (!IsLineType(*line, kLineTypeAttributes)) {
// TODO(deadbeef): Handle other lines if needed.
RTC_LOG(LS_VERBOSE) << "Ignored line: " << line;
RTC_LOG(LS_VERBOSE) << "Ignored line: " << *line;
continue;
}
// Handle attributes common to SCTP and RTP.
if (HasAttribute(line, kAttributeMid)) {
if (HasAttribute(*line, kAttributeMid)) {
// RFC 3388
// mid-attribute = "a=mid:" identification-tag
// identification-tag = token
// Use the mid identification-tag as the content name.
if (!GetSingleTokenValue(line, kAttributeMid, &mline_id, error)) {
if (!GetSingleTokenValue(*line, kAttributeMid, &mline_id, error)) {
return false;
}
*content_name = mline_id;
} else if (HasAttribute(line, kAttributeBundleOnly)) {
} else if (HasAttribute(*line, kAttributeBundleOnly)) {
*bundle_only = true;
} else if (HasAttribute(line, kAttributeCandidate)) {
} else if (HasAttribute(*line, kAttributeCandidate)) {
Candidate candidate;
if (!ParseCandidate(line, &candidate, error, false)) {
if (!ParseCandidate(*line, &candidate, error, false)) {
return false;
}
// ParseCandidate will parse non-standard ufrag and password attributes,
@ -3082,30 +3089,30 @@ bool ParseContent(absl::string_view message,
candidate.set_username(std::string());
candidate.set_password(std::string());
candidates_orig.push_back(candidate);
} else if (HasAttribute(line, kAttributeIceUfrag)) {
if (!GetValue(line, kAttributeIceUfrag, &transport->ice_ufrag, error)) {
} else if (HasAttribute(*line, kAttributeIceUfrag)) {
if (!GetValue(*line, kAttributeIceUfrag, &transport->ice_ufrag, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeIcePwd)) {
if (!GetValue(line, kAttributeIcePwd, &transport->ice_pwd, error)) {
} else if (HasAttribute(*line, kAttributeIcePwd)) {
if (!GetValue(*line, kAttributeIcePwd, &transport->ice_pwd, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeIceOption)) {
if (!ParseIceOptions(line, &transport->transport_options, error)) {
} else if (HasAttribute(*line, kAttributeIceOption)) {
if (!ParseIceOptions(*line, &transport->transport_options, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeFmtp)) {
if (!ParseFmtpAttributes(line, media_type, media_desc, error)) {
} else if (HasAttribute(*line, kAttributeFmtp)) {
if (!ParseFmtpAttributes(*line, media_type, media_desc, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeFingerprint)) {
} else if (HasAttribute(*line, kAttributeFingerprint)) {
std::unique_ptr<rtc::SSLFingerprint> fingerprint;
if (!ParseFingerprintAttribute(line, &fingerprint, error)) {
if (!ParseFingerprintAttribute(*line, &fingerprint, error)) {
return false;
}
transport->identity_fingerprint = std::move(fingerprint);
} else if (HasAttribute(line, kAttributeSetup)) {
if (!ParseDtlsSetup(line, &(transport->connection_role), error)) {
} else if (HasAttribute(*line, kAttributeSetup)) {
if (!ParseDtlsSetup(*line, &(transport->connection_role), error)) {
return false;
}
} else if (cricket::IsDtlsSctp(protocol) &&
@ -3113,23 +3120,23 @@ bool ParseContent(absl::string_view message,
//
// SCTP specific attributes
//
if (HasAttribute(line, kAttributeSctpPort)) {
if (HasAttribute(*line, kAttributeSctpPort)) {
if (media_desc->as_sctp()->use_sctpmap()) {
return ParseFailed(
line, "sctp-port attribute can't be used with sctpmap.", error);
*line, "sctp-port attribute can't be used with sctpmap.", error);
}
int sctp_port;
if (!ParseSctpPort(line, &sctp_port, error)) {
if (!ParseSctpPort(*line, &sctp_port, error)) {
return false;
}
media_desc->as_sctp()->set_port(sctp_port);
} else if (HasAttribute(line, kAttributeMaxMessageSize)) {
} else if (HasAttribute(*line, kAttributeMaxMessageSize)) {
int max_message_size;
if (!ParseSctpMaxMessageSize(line, &max_message_size, error)) {
if (!ParseSctpMaxMessageSize(*line, &max_message_size, error)) {
return false;
}
media_desc->as_sctp()->set_max_message_size(max_message_size);
} else if (HasAttribute(line, kAttributeSctpmap)) {
} else if (HasAttribute(*line, kAttributeSctpmap)) {
// Ignore a=sctpmap: from early versions of draft-ietf-mmusic-sctp-sdp
continue;
}
@ -3137,132 +3144,133 @@ bool ParseContent(absl::string_view message,
//
// RTP specific attributes
//
if (HasAttribute(line, kAttributeRtcpMux)) {
if (HasAttribute(*line, kAttributeRtcpMux)) {
media_desc->set_rtcp_mux(true);
} else if (HasAttribute(line, kAttributeRtcpReducedSize)) {
} else if (HasAttribute(*line, kAttributeRtcpReducedSize)) {
media_desc->set_rtcp_reduced_size(true);
} else if (HasAttribute(line, kAttributeRtcpRemoteEstimate)) {
} else if (HasAttribute(*line, kAttributeRtcpRemoteEstimate)) {
media_desc->set_remote_estimate(true);
} else if (HasAttribute(line, kAttributeSsrcGroup)) {
if (!ParseSsrcGroupAttribute(line, &ssrc_groups, error)) {
} else if (HasAttribute(*line, kAttributeSsrcGroup)) {
if (!ParseSsrcGroupAttribute(*line, &ssrc_groups, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeSsrc)) {
if (!ParseSsrcAttribute(line, &ssrc_infos, msid_signaling, error)) {
} else if (HasAttribute(*line, kAttributeSsrc)) {
if (!ParseSsrcAttribute(*line, &ssrc_infos, msid_signaling, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeCrypto)) {
if (!ParseCryptoAttribute(line, media_desc, error)) {
} else if (HasAttribute(*line, kAttributeCrypto)) {
if (!ParseCryptoAttribute(*line, media_desc, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeRtpmap)) {
if (!ParseRtpmapAttribute(line, media_type, payload_types, media_desc,
} else if (HasAttribute(*line, kAttributeRtpmap)) {
if (!ParseRtpmapAttribute(*line, media_type, payload_types, media_desc,
error)) {
return false;
}
} else if (HasAttribute(line, kCodecParamMaxPTime)) {
if (!GetValue(line, kCodecParamMaxPTime, &maxptime_as_string, error)) {
} else if (HasAttribute(*line, kCodecParamMaxPTime)) {
if (!GetValue(*line, kCodecParamMaxPTime, &maxptime_as_string, error)) {
return false;
}
} else if (HasAttribute(line, kAttributePacketization)) {
if (!ParsePacketizationAttribute(line, media_type, media_desc, error)) {
} else if (HasAttribute(*line, kAttributePacketization)) {
if (!ParsePacketizationAttribute(*line, media_type, media_desc,
error)) {
return false;
}
} else if (HasAttribute(line, kAttributeRtcpFb)) {
if (!ParseRtcpFbAttribute(line, media_type, media_desc, error)) {
} else if (HasAttribute(*line, kAttributeRtcpFb)) {
if (!ParseRtcpFbAttribute(*line, media_type, media_desc, error)) {
return false;
}
} else if (HasAttribute(line, kCodecParamPTime)) {
if (!GetValue(line, kCodecParamPTime, &ptime_as_string, error)) {
} else if (HasAttribute(*line, kCodecParamPTime)) {
if (!GetValue(*line, kCodecParamPTime, &ptime_as_string, error)) {
return false;
}
} else if (HasAttribute(line, kAttributeSendOnly)) {
} else if (HasAttribute(*line, kAttributeSendOnly)) {
media_desc->set_direction(RtpTransceiverDirection::kSendOnly);
} else if (HasAttribute(line, kAttributeRecvOnly)) {
} else if (HasAttribute(*line, kAttributeRecvOnly)) {
media_desc->set_direction(RtpTransceiverDirection::kRecvOnly);
} else if (HasAttribute(line, kAttributeInactive)) {
} else if (HasAttribute(*line, kAttributeInactive)) {
media_desc->set_direction(RtpTransceiverDirection::kInactive);
} else if (HasAttribute(line, kAttributeSendRecv)) {
} else if (HasAttribute(*line, kAttributeSendRecv)) {
media_desc->set_direction(RtpTransceiverDirection::kSendRecv);
} else if (HasAttribute(line, kAttributeExtmapAllowMixed)) {
} else if (HasAttribute(*line, kAttributeExtmapAllowMixed)) {
media_desc->set_extmap_allow_mixed_enum(
MediaContentDescription::kMedia);
} else if (HasAttribute(line, kAttributeExtmap)) {
} else if (HasAttribute(*line, kAttributeExtmap)) {
RtpExtension extmap;
if (!ParseExtmap(line, &extmap, error)) {
if (!ParseExtmap(*line, &extmap, error)) {
return false;
}
media_desc->AddRtpHeaderExtension(extmap);
} else if (HasAttribute(line, kAttributeXGoogleFlag)) {
} else if (HasAttribute(*line, kAttributeXGoogleFlag)) {
// Experimental attribute. Conference mode activates more aggressive
// AEC and NS settings.
// TODO(deadbeef): expose API to set these directly.
std::string flag_value;
if (!GetValue(line, kAttributeXGoogleFlag, &flag_value, error)) {
if (!GetValue(*line, kAttributeXGoogleFlag, &flag_value, error)) {
return false;
}
if (flag_value.compare(kValueConference) == 0)
media_desc->set_conference_mode(true);
} else if (HasAttribute(line, kAttributeMsid)) {
if (!ParseMsidAttribute(line, &stream_ids, &track_id, error)) {
} else if (HasAttribute(*line, kAttributeMsid)) {
if (!ParseMsidAttribute(*line, &stream_ids, &track_id, error)) {
return false;
}
*msid_signaling |= cricket::kMsidSignalingMediaSection;
} else if (HasAttribute(line, kAttributeRid)) {
} else if (HasAttribute(*line, kAttributeRid)) {
const size_t kRidPrefixLength =
kLinePrefixLength + arraysize(kAttributeRid);
if (line.size() <= kRidPrefixLength) {
RTC_LOG(LS_INFO) << "Ignoring empty RID attribute: " << line;
if (line->size() <= kRidPrefixLength) {
RTC_LOG(LS_INFO) << "Ignoring empty RID attribute: " << *line;
continue;
}
RTCErrorOr<RidDescription> error_or_rid_description =
deserializer.DeserializeRidDescription(
line.substr(kRidPrefixLength));
line->substr(kRidPrefixLength));
// Malformed a=rid lines are discarded.
if (!error_or_rid_description.ok()) {
RTC_LOG(LS_INFO) << "Ignoring malformed RID line: '" << line
RTC_LOG(LS_INFO) << "Ignoring malformed RID line: '" << *line
<< "'. Error: "
<< error_or_rid_description.error().message();
continue;
}
rids.push_back(error_or_rid_description.MoveValue());
} else if (HasAttribute(line, kAttributeSimulcast)) {
} else if (HasAttribute(*line, kAttributeSimulcast)) {
const size_t kSimulcastPrefixLength =
kLinePrefixLength + arraysize(kAttributeSimulcast);
if (line.size() <= kSimulcastPrefixLength) {
return ParseFailed(line, "Simulcast attribute is empty.", error);
if (line->size() <= kSimulcastPrefixLength) {
return ParseFailed(*line, "Simulcast attribute is empty.", error);
}
if (!simulcast.empty()) {
return ParseFailed(line, "Multiple Simulcast attributes specified.",
return ParseFailed(*line, "Multiple Simulcast attributes specified.",
error);
}
RTCErrorOr<SimulcastDescription> error_or_simulcast =
deserializer.DeserializeSimulcastDescription(
line.substr(kSimulcastPrefixLength));
line->substr(kSimulcastPrefixLength));
if (!error_or_simulcast.ok()) {
return ParseFailed(line,
return ParseFailed(*line,
std::string("Malformed simulcast line: ") +
error_or_simulcast.error().message(),
error);
}
simulcast = error_or_simulcast.value();
} else if (HasAttribute(line, kAttributeRtcp)) {
} else if (HasAttribute(*line, kAttributeRtcp)) {
// Ignore and do not log a=rtcp line.
// JSEP section 5.8.2 (media section parsing) says to ignore it.
continue;
} else {
// Unrecognized attribute in RTP protocol.
RTC_LOG(LS_VERBOSE) << "Ignored line: " << line;
RTC_LOG(LS_VERBOSE) << "Ignored line: " << *line;
continue;
}
} else {
// Only parse lines that we are interested of.
RTC_LOG(LS_VERBOSE) << "Ignored line: " << line;
RTC_LOG(LS_VERBOSE) << "Ignored line: " << *line;
continue;
}
}