Chromium Code Reviews| Index: webrtc/pc/webrtcsdp.cc |
| diff --git a/webrtc/pc/webrtcsdp.cc b/webrtc/pc/webrtcsdp.cc |
| index 13d09a6ee96efd33219e6e7df89ba5983cb49d7e..4ae085c084de934bec0c8533da626d2f60484ccc 100644 |
| --- a/webrtc/pc/webrtcsdp.cc |
| +++ b/webrtc/pc/webrtcsdp.cc |
| @@ -249,11 +249,13 @@ static void BuildIceOptions(const std::vector<std::string>& transport_options, |
| std::string* message); |
| static bool IsRtp(const std::string& protocol); |
| static bool IsDtlsSctp(const std::string& protocol); |
| -static bool ParseSessionDescription(const std::string& message, size_t* pos, |
| +static bool ParseSessionDescription(const std::string& message, |
| + size_t* pos, |
| std::string* session_id, |
| std::string* session_version, |
| TransportDescription* session_td, |
| RtpHeaderExtensions* session_extmaps, |
| + rtc::SocketAddress* connection_addr, |
| cricket::SessionDescription* desc, |
| SdpParseError* error); |
| static bool ParseGroupAttribute(const std::string& line, |
| @@ -263,12 +265,15 @@ static bool ParseMediaDescription( |
| const std::string& message, |
| const TransportDescription& session_td, |
| const RtpHeaderExtensions& session_extmaps, |
| - size_t* pos, cricket::SessionDescription* desc, |
| + size_t* pos, |
| + const rtc::SocketAddress& session_connection_addr, |
| + cricket::SessionDescription* desc, |
| std::vector<JsepIceCandidate*>* candidates, |
| SdpParseError* error); |
| static bool ParseContent(const std::string& message, |
| const MediaType media_type, |
| int mline_index, |
| + int port, |
| const std::string& protocol, |
| const std::vector<int>& payload_types, |
| size_t* pos, |
| @@ -713,7 +718,7 @@ static void GetDefaultDestination( |
| } |
| } |
| -// Update |mline|'s default destination and append a c line after it. |
| +// Update |mline|'s default destination. |
| static void UpdateMediaDefaultDestination( |
|
Taylor Brandstetter
2017/03/17 00:20:42
Since this is now done in JsepSessionDescription,
Zhi Huang
2017/03/17 23:42:06
You are right. I should remove this.
|
| const std::vector<Candidate>& candidates, |
| const std::string& mline, |
| @@ -745,12 +750,6 @@ static void UpdateMediaDefaultDestination( |
| fields[1].size(), |
| rtp_port); |
| } |
| - // Add the c line. |
| - // RFC 4566 |
| - // c=<nettype> <addrtype> <connection-address> |
| - InitLine(kLineTypeConnection, kConnectionNettype, &os); |
| - os << " " << addr_type << " " << rtp_ip; |
| - AddLine(os.str(), &new_lines); |
| message->append(new_lines); |
| } |
| @@ -902,6 +901,7 @@ bool SdpDeserialize(const std::string& message, |
| std::string session_version; |
| TransportDescription session_td("", ""); |
| RtpHeaderExtensions session_extmaps; |
| + rtc::SocketAddress session_connection_addr; |
| cricket::SessionDescription* desc = new cricket::SessionDescription(); |
| std::vector<JsepIceCandidate*> candidates; |
| size_t current_pos = 0; |
| @@ -909,14 +909,15 @@ bool SdpDeserialize(const std::string& message, |
| // Session Description |
| if (!ParseSessionDescription(message, ¤t_pos, &session_id, |
| &session_version, &session_td, &session_extmaps, |
| - desc, error)) { |
| + &session_connection_addr, desc, error)) { |
| delete desc; |
| return false; |
| } |
| // Media Description |
| if (!ParseMediaDescription(message, session_td, session_extmaps, ¤t_pos, |
| - desc, &candidates, error)) { |
| + session_connection_addr, desc, &candidates, |
| + error)) { |
| delete desc; |
| for (std::vector<JsepIceCandidate*>::const_iterator |
| it = candidates.begin(); it != candidates.end(); ++it) { |
| @@ -1328,6 +1329,16 @@ void BuildMediaDescription(const ContentInfo* content_info, |
| std::string mline = os.str(); |
| UpdateMediaDefaultDestination(candidates, mline, message); |
| + InitLine(kLineTypeConnection, kConnectionNettype, &os); |
| + if (media_desc->connection_address().family() == AF_INET) { |
| + os << " " << kConnectionIpv4Addrtype << " " |
| + << media_desc->connection_address().ipaddr().ToString(); |
| + } else { |
| + os << " " << kConnectionIpv6Addrtype << " " |
| + << media_desc->connection_address().ipaddr().ToString(); |
| + } |
| + AddLine(os.str(), message); |
| + |
| // RFC 4566 |
| // b=AS:<bandwidth> |
| if (media_desc->bandwidth() >= 1000) { |
| @@ -1900,11 +1911,62 @@ bool IsDtlsSctp(const std::string& protocol) { |
| return protocol.find(cricket::kMediaProtocolDtlsSctp) != std::string::npos; |
| } |
| -bool ParseSessionDescription(const std::string& message, size_t* pos, |
| +bool ParseConnectionData(const std::string& line, |
| + rtc::SocketAddress* addr, |
| + SdpParseError* error) { |
| + // Parse the line from left to right. |
| + std::string token; |
| + std::string rightpart; |
| + // RFC 4566 |
| + // c=<nettype> <addrtype> <connection-address> |
| + // Skip the "c=" |
| + if (!rtc::tokenize_first(line, kSdpDelimiterEqual, &token, &rightpart)) { |
| + return ParseFailed(line, "Failed to parse the network type.", error); |
| + } |
| + |
| + // Extract and verify the <nettype> |
| + if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpace, &token, &rightpart) || |
| + token != kConnectionNettype) { |
| + return ParseFailed(line, |
| + "Failed to parse the connection data. The network type " |
| + "is not currently supported.", |
| + error); |
| + } |
| + |
| + // Extract the "<addrtype>" and "<connection-address>". |
| + if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpace, &token, &rightpart)) { |
| + return ParseFailed(line, "Failed to parse the address type.", error); |
| + } |
| + |
| + // The rightpart part should be the IP address without the slash which is used |
| + // for multicast. |
| + if (rightpart.find('/') != std::string::npos) { |
| + return ParseFailed(line, |
| + "Failed to parse the connection data. Multicast is not " |
| + "currently supported.", |
| + error); |
| + } |
| + addr->SetIP(rightpart); |
| + |
| + // Verify that the addrtype matches the type of the parsed address. |
| + if ((addr->family() == AF_INET && token != "IP4") || |
| + (addr->family() == AF_INET6 && token != "IP6")) { |
| + addr->Clear(); |
| + return ParseFailed( |
| + line, |
| + "Failed to parse the connection data. The address type is mismatching.", |
| + error); |
| + } |
| + return true; |
| +} |
| + |
| +bool ParseSessionDescription(const std::string& message, |
| + size_t* pos, |
| std::string* session_id, |
| std::string* session_version, |
| TransportDescription* session_td, |
| RtpHeaderExtensions* session_extmaps, |
| + rtc::SocketAddress* connection_addr, |
| cricket::SessionDescription* desc, |
| SdpParseError* error) { |
| std::string line; |
| @@ -1962,7 +2024,11 @@ bool ParseSessionDescription(const std::string& message, size_t* pos, |
| // RFC 4566 |
| // c=* (connection information -- not required if included in |
| // all media) |
| - GetLineWithType(message, pos, &line, kLineTypeConnection); |
| + if (GetLineWithType(message, pos, &line, kLineTypeConnection)) { |
| + if (!ParseConnectionData(line, connection_addr, error)) { |
| + return false; |
| + } |
| + } |
| // RFC 4566 |
| // b=* (zero or more bandwidth information lines) |
| @@ -2239,6 +2305,7 @@ template <class C> |
| static C* ParseContentDescription(const std::string& message, |
| const MediaType media_type, |
| int mline_index, |
| + int port, |
| const std::string& protocol, |
| const std::vector<int>& payload_types, |
| size_t* pos, |
| @@ -2262,11 +2329,11 @@ static C* ParseContentDescription(const std::string& message, |
| RTC_NOTREACHED(); |
| break; |
| } |
| - if (!ParseContent(message, media_type, mline_index, protocol, payload_types, |
| - pos, content_name, bundle_only, media_desc, transport, |
| - candidates, error)) { |
| + if (!ParseContent(message, media_type, mline_index, port, protocol, |
| + payload_types, pos, content_name, bundle_only, media_desc, |
| + transport, candidates, error)) { |
| delete media_desc; |
| - return NULL; |
| + return nullptr; |
| } |
| // Sort the codecs according to the m-line fmt list. |
| std::unordered_map<int, int> payload_type_preferences; |
| @@ -2291,6 +2358,7 @@ bool ParseMediaDescription(const std::string& message, |
| const TransportDescription& session_td, |
| const RtpHeaderExtensions& session_extmaps, |
| size_t* pos, |
| + const rtc::SocketAddress& session_connection_addr, |
| cricket::SessionDescription* desc, |
| std::vector<JsepIceCandidate*>* candidates, |
| SdpParseError* error) { |
| @@ -2320,6 +2388,7 @@ bool ParseMediaDescription(const std::string& message, |
| port_rejected = true; |
| } |
| + int port = atoi(fields[1].c_str()); |
|
Taylor Brandstetter
2017/03/17 00:20:42
Can use "rtc::FromString<int>" and check for parse
Zhi Huang
2017/03/17 23:42:06
Done.
|
| std::string protocol = fields[2]; |
| // <fmt> |
| @@ -2352,18 +2421,18 @@ bool ParseMediaDescription(const std::string& message, |
| bool bundle_only = false; |
| if (HasAttribute(line, kMediaTypeVideo)) { |
| content.reset(ParseContentDescription<VideoContentDescription>( |
| - message, cricket::MEDIA_TYPE_VIDEO, mline_index, protocol, |
| + message, cricket::MEDIA_TYPE_VIDEO, mline_index, port, protocol, |
|
Taylor Brandstetter
2017/03/17 00:20:42
To avoid having to add the port as an argument eve
Zhi Huang
2017/03/17 23:42:06
Yes, but I need to create a copy of those since th
|
| payload_types, pos, &content_name, &bundle_only, &transport, |
| candidates, error)); |
| } else if (HasAttribute(line, kMediaTypeAudio)) { |
| content.reset(ParseContentDescription<AudioContentDescription>( |
| - message, cricket::MEDIA_TYPE_AUDIO, mline_index, protocol, |
| + message, cricket::MEDIA_TYPE_AUDIO, mline_index, port, protocol, |
| payload_types, pos, &content_name, &bundle_only, &transport, |
| candidates, error)); |
| } else if (HasAttribute(line, kMediaTypeData)) { |
| DataContentDescription* data_desc = |
| ParseContentDescription<DataContentDescription>( |
| - message, cricket::MEDIA_TYPE_DATA, mline_index, protocol, |
| + message, cricket::MEDIA_TYPE_DATA, mline_index, port, protocol, |
| payload_types, pos, &content_name, &bundle_only, &transport, |
| candidates, error); |
| content.reset(data_desc); |
| @@ -2420,6 +2489,13 @@ bool ParseMediaDescription(const std::string& message, |
| } |
| } |
| content->set_protocol(protocol); |
| + |
| + // Use the session level connection address if the media level addresses are |
| + // not specified. |
| + if (content->connection_address().IsNil()) { |
| + content->set_connection_address(session_connection_addr); |
|
Taylor Brandstetter
2017/03/17 00:20:42
If this condition is hit, the port from the m= lin
Zhi Huang
2017/03/17 23:42:06
Fixed.
|
| + } |
| + |
| desc->AddContent(content_name, |
| IsDtlsSctp(protocol) ? cricket::NS_JINGLE_DRAFT_SCTP |
| : cricket::NS_JINGLE_RTP, |
| @@ -2595,6 +2671,7 @@ void AddAudioAttribute(const std::string& name, const std::string& value, |
| bool ParseContent(const std::string& message, |
| const MediaType media_type, |
| int mline_index, |
| + int port, |
| const std::string& protocol, |
| const std::vector<int>& payload_types, |
| size_t* pos, |
| @@ -2668,6 +2745,17 @@ bool ParseContent(const std::string& message, |
| continue; |
| } |
| + // Parse the media level connection data. |
| + if (IsLineType(line, kLineTypeConnection)) { |
| + rtc::SocketAddress addr; |
| + if (!ParseConnectionData(line, &addr, error)) { |
| + return false; |
| + } |
| + addr.SetPort(port); |
| + media_desc->set_connection_address(addr); |
| + continue; |
| + } |
| + |
| if (!IsLineType(line, kLineTypeAttributes)) { |
| // TODO: Handle other lines if needed. |
| LOG(LS_INFO) << "Ignored line: " << line; |