Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2011 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 static void BuildRtpMap(const MediaContentDescription* media_desc, | 242 static void BuildRtpMap(const MediaContentDescription* media_desc, |
| 243 const MediaType media_type, | 243 const MediaType media_type, |
| 244 std::string* message); | 244 std::string* message); |
| 245 static void BuildCandidate(const std::vector<Candidate>& candidates, | 245 static void BuildCandidate(const std::vector<Candidate>& candidates, |
| 246 bool include_ufrag, | 246 bool include_ufrag, |
| 247 std::string* message); | 247 std::string* message); |
| 248 static void BuildIceOptions(const std::vector<std::string>& transport_options, | 248 static void BuildIceOptions(const std::vector<std::string>& transport_options, |
| 249 std::string* message); | 249 std::string* message); |
| 250 static bool IsRtp(const std::string& protocol); | 250 static bool IsRtp(const std::string& protocol); |
| 251 static bool IsDtlsSctp(const std::string& protocol); | 251 static bool IsDtlsSctp(const std::string& protocol); |
| 252 static bool ParseSessionDescription(const std::string& message, size_t* pos, | 252 static bool ParseSessionDescription(const std::string& message, |
| 253 size_t* pos, | |
| 253 std::string* session_id, | 254 std::string* session_id, |
| 254 std::string* session_version, | 255 std::string* session_version, |
| 255 TransportDescription* session_td, | 256 TransportDescription* session_td, |
| 256 RtpHeaderExtensions* session_extmaps, | 257 RtpHeaderExtensions* session_extmaps, |
| 258 rtc::SocketAddress* connection_addr, | |
| 257 cricket::SessionDescription* desc, | 259 cricket::SessionDescription* desc, |
| 258 SdpParseError* error); | 260 SdpParseError* error); |
| 259 static bool ParseGroupAttribute(const std::string& line, | 261 static bool ParseGroupAttribute(const std::string& line, |
| 260 cricket::SessionDescription* desc, | 262 cricket::SessionDescription* desc, |
| 261 SdpParseError* error); | 263 SdpParseError* error); |
| 262 static bool ParseMediaDescription( | 264 static bool ParseMediaDescription( |
| 263 const std::string& message, | 265 const std::string& message, |
| 264 const TransportDescription& session_td, | 266 const TransportDescription& session_td, |
| 265 const RtpHeaderExtensions& session_extmaps, | 267 const RtpHeaderExtensions& session_extmaps, |
| 266 size_t* pos, cricket::SessionDescription* desc, | 268 size_t* pos, |
| 269 const rtc::SocketAddress& session_connection_addr, | |
| 270 cricket::SessionDescription* desc, | |
| 267 std::vector<JsepIceCandidate*>* candidates, | 271 std::vector<JsepIceCandidate*>* candidates, |
| 268 SdpParseError* error); | 272 SdpParseError* error); |
| 269 static bool ParseContent(const std::string& message, | 273 static bool ParseContent(const std::string& message, |
| 270 const MediaType media_type, | 274 const MediaType media_type, |
| 271 int mline_index, | 275 int mline_index, |
| 272 const std::string& protocol, | 276 const std::string& protocol, |
| 273 const std::vector<int>& payload_types, | 277 const std::vector<int>& payload_types, |
| 274 size_t* pos, | 278 size_t* pos, |
| 275 std::string* content_name, | 279 std::string* content_name, |
| 276 bool* bundle_only, | 280 bool* bundle_only, |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 706 } else if (family == AF_INET6) { | 710 } else if (family == AF_INET6) { |
| 707 addr_type->assign(kConnectionIpv6Addrtype); | 711 addr_type->assign(kConnectionIpv6Addrtype); |
| 708 } | 712 } |
| 709 current_preference = preference; | 713 current_preference = preference; |
| 710 current_family = family; | 714 current_family = family; |
| 711 *port = it->address().PortAsString(); | 715 *port = it->address().PortAsString(); |
| 712 *ip = it->address().ipaddr().ToString(); | 716 *ip = it->address().ipaddr().ToString(); |
| 713 } | 717 } |
| 714 } | 718 } |
| 715 | 719 |
| 716 // Update |mline|'s default destination and append a c line after it. | |
| 717 static void UpdateMediaDefaultDestination( | |
| 718 const std::vector<Candidate>& candidates, | |
| 719 const std::string& mline, | |
| 720 std::string* message) { | |
| 721 std::string new_lines; | |
| 722 AddLine(mline, &new_lines); | |
| 723 // RFC 4566 | |
| 724 // m=<media> <port> <proto> <fmt> ... | |
| 725 std::vector<std::string> fields; | |
| 726 rtc::split(mline, kSdpDelimiterSpace, &fields); | |
| 727 if (fields.size() < 3) { | |
| 728 return; | |
| 729 } | |
| 730 | |
| 731 std::ostringstream os; | |
| 732 std::string rtp_port, rtp_ip, addr_type; | |
| 733 GetDefaultDestination(candidates, ICE_CANDIDATE_COMPONENT_RTP, | |
| 734 &rtp_port, &rtp_ip, &addr_type); | |
| 735 // Found default RTP candidate. | |
| 736 // RFC 5245 | |
| 737 // The default candidates are added to the SDP as the default | |
| 738 // destination for media. For streams based on RTP, this is done by | |
| 739 // placing the IP address and port of the RTP candidate into the c and m | |
| 740 // lines, respectively. | |
| 741 // Update the port in the m line. | |
| 742 // If this is a m-line with port equal to 0, we don't change it. | |
| 743 if (fields[1] != kMediaPortRejected) { | |
| 744 new_lines.replace(fields[0].size() + 1, | |
| 745 fields[1].size(), | |
| 746 rtp_port); | |
| 747 } | |
| 748 // Add the c line. | |
| 749 // RFC 4566 | |
| 750 // c=<nettype> <addrtype> <connection-address> | |
| 751 InitLine(kLineTypeConnection, kConnectionNettype, &os); | |
| 752 os << " " << addr_type << " " << rtp_ip; | |
| 753 AddLine(os.str(), &new_lines); | |
| 754 message->append(new_lines); | |
| 755 } | |
| 756 | |
| 757 // Gets "a=rtcp" line if found default RTCP candidate from |candidates|. | 720 // Gets "a=rtcp" line if found default RTCP candidate from |candidates|. |
| 758 static std::string GetRtcpLine(const std::vector<Candidate>& candidates) { | 721 static std::string GetRtcpLine(const std::vector<Candidate>& candidates) { |
| 759 std::string rtcp_line, rtcp_port, rtcp_ip, addr_type; | 722 std::string rtcp_line, rtcp_port, rtcp_ip, addr_type; |
| 760 GetDefaultDestination(candidates, ICE_CANDIDATE_COMPONENT_RTCP, | 723 GetDefaultDestination(candidates, ICE_CANDIDATE_COMPONENT_RTCP, |
| 761 &rtcp_port, &rtcp_ip, &addr_type); | 724 &rtcp_port, &rtcp_ip, &addr_type); |
| 762 // Found default RTCP candidate. | 725 // Found default RTCP candidate. |
| 763 // RFC 5245 | 726 // RFC 5245 |
| 764 // If the agent is utilizing RTCP, it MUST encode the RTCP candidate | 727 // If the agent is utilizing RTCP, it MUST encode the RTCP candidate |
| 765 // using the a=rtcp attribute as defined in RFC 3605. | 728 // using the a=rtcp attribute as defined in RFC 3605. |
| 766 | 729 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 895 return message; | 858 return message; |
| 896 } | 859 } |
| 897 | 860 |
| 898 bool SdpDeserialize(const std::string& message, | 861 bool SdpDeserialize(const std::string& message, |
| 899 JsepSessionDescription* jdesc, | 862 JsepSessionDescription* jdesc, |
| 900 SdpParseError* error) { | 863 SdpParseError* error) { |
| 901 std::string session_id; | 864 std::string session_id; |
| 902 std::string session_version; | 865 std::string session_version; |
| 903 TransportDescription session_td("", ""); | 866 TransportDescription session_td("", ""); |
| 904 RtpHeaderExtensions session_extmaps; | 867 RtpHeaderExtensions session_extmaps; |
| 868 rtc::SocketAddress session_connection_addr; | |
| 905 cricket::SessionDescription* desc = new cricket::SessionDescription(); | 869 cricket::SessionDescription* desc = new cricket::SessionDescription(); |
| 906 std::vector<JsepIceCandidate*> candidates; | 870 std::vector<JsepIceCandidate*> candidates; |
| 907 size_t current_pos = 0; | 871 size_t current_pos = 0; |
| 908 | 872 |
| 909 // Session Description | 873 // Session Description |
| 910 if (!ParseSessionDescription(message, ¤t_pos, &session_id, | 874 if (!ParseSessionDescription(message, ¤t_pos, &session_id, |
| 911 &session_version, &session_td, &session_extmaps, | 875 &session_version, &session_td, &session_extmaps, |
| 912 desc, error)) { | 876 &session_connection_addr, desc, error)) { |
| 913 delete desc; | 877 delete desc; |
| 914 return false; | 878 return false; |
| 915 } | 879 } |
| 916 | 880 |
| 917 // Media Description | 881 // Media Description |
| 918 if (!ParseMediaDescription(message, session_td, session_extmaps, ¤t_pos, | 882 if (!ParseMediaDescription(message, session_td, session_extmaps, ¤t_pos, |
| 919 desc, &candidates, error)) { | 883 session_connection_addr, desc, &candidates, |
| 884 error)) { | |
| 920 delete desc; | 885 delete desc; |
| 921 for (std::vector<JsepIceCandidate*>::const_iterator | 886 for (std::vector<JsepIceCandidate*>::const_iterator |
| 922 it = candidates.begin(); it != candidates.end(); ++it) { | 887 it = candidates.begin(); it != candidates.end(); ++it) { |
| 923 delete *it; | 888 delete *it; |
| 924 } | 889 } |
| 925 return false; | 890 return false; |
| 926 } | 891 } |
| 927 | 892 |
| 928 jdesc->Initialize(desc, session_id, session_version); | 893 jdesc->Initialize(desc, session_id, session_version); |
| 929 | 894 |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1309 // the candidates. | 1274 // the candidates. |
| 1310 // | 1275 // |
| 1311 // A port value of 0 indicates that the m= section is rejected. | 1276 // A port value of 0 indicates that the m= section is rejected. |
| 1312 // RFC 3264 | 1277 // RFC 3264 |
| 1313 // To reject an offered stream, the port number in the corresponding stream in | 1278 // To reject an offered stream, the port number in the corresponding stream in |
| 1314 // the answer MUST be set to zero. | 1279 // the answer MUST be set to zero. |
| 1315 // | 1280 // |
| 1316 // However, the BUNDLE draft adds a new meaning to port zero, when used along | 1281 // However, the BUNDLE draft adds a new meaning to port zero, when used along |
| 1317 // with a=bundle-only. | 1282 // with a=bundle-only. |
| 1318 const std::string& port = | 1283 const std::string& port = |
| 1319 (content_info->rejected || content_info->bundle_only) ? kMediaPortRejected | 1284 (content_info->rejected || content_info->bundle_only) |
| 1320 : kDummyPort; | 1285 ? kMediaPortRejected |
| 1286 : (media_desc->connection_address().IsNil() | |
| 1287 ? kDummyPort | |
| 1288 : std::to_string(media_desc->connection_address().port())); | |
|
Taylor Brandstetter
2017/03/18 00:46:07
Can use rtc::ToString; std::to_string may not be a
Zhi Huang
2017/03/18 19:27:55
Good to know that.
But if use the if/else, the po
| |
| 1321 | 1289 |
| 1322 rtc::SSLFingerprint* fp = (transport_info) ? | 1290 rtc::SSLFingerprint* fp = (transport_info) ? |
| 1323 transport_info->description.identity_fingerprint.get() : NULL; | 1291 transport_info->description.identity_fingerprint.get() : NULL; |
| 1324 | 1292 |
| 1325 // Add the m and c lines. | 1293 // Add the m and c lines. |
| 1326 InitLine(kLineTypeMedia, type, &os); | 1294 InitLine(kLineTypeMedia, type, &os); |
| 1327 os << " " << port << " " << media_desc->protocol() << fmt; | 1295 os << " " << port << " " << media_desc->protocol() << fmt; |
| 1328 std::string mline = os.str(); | 1296 AddLine(os.str(), message); |
| 1329 UpdateMediaDefaultDestination(candidates, mline, message); | 1297 |
| 1298 InitLine(kLineTypeConnection, kConnectionNettype, &os); | |
|
Taylor Brandstetter
2017/03/18 00:46:07
Should handle the "IsNil" case explicitly here, an
Zhi Huang
2017/03/18 19:27:55
Done.
| |
| 1299 if (media_desc->connection_address().family() == AF_INET) { | |
| 1300 os << " " << kConnectionIpv4Addrtype << " " | |
| 1301 << media_desc->connection_address().ipaddr().ToString(); | |
| 1302 } else { | |
| 1303 os << " " << kConnectionIpv6Addrtype << " " | |
| 1304 << media_desc->connection_address().ipaddr().ToString(); | |
| 1305 } | |
| 1306 AddLine(os.str(), message); | |
| 1330 | 1307 |
| 1331 // RFC 4566 | 1308 // RFC 4566 |
| 1332 // b=AS:<bandwidth> | 1309 // b=AS:<bandwidth> |
| 1333 if (media_desc->bandwidth() >= 1000) { | 1310 if (media_desc->bandwidth() >= 1000) { |
| 1334 InitLine(kLineTypeSessionBandwidth, kApplicationSpecificMaximum, &os); | 1311 InitLine(kLineTypeSessionBandwidth, kApplicationSpecificMaximum, &os); |
| 1335 os << kSdpDelimiterColon << (media_desc->bandwidth() / 1000); | 1312 os << kSdpDelimiterColon << (media_desc->bandwidth() / 1000); |
| 1336 AddLine(os.str(), message); | 1313 AddLine(os.str(), message); |
| 1337 } | 1314 } |
| 1338 | 1315 |
| 1339 // Add the a=bundle-only line. | 1316 // Add the a=bundle-only line. |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1893 bool IsRtp(const std::string& protocol) { | 1870 bool IsRtp(const std::string& protocol) { |
| 1894 return protocol.empty() || | 1871 return protocol.empty() || |
| 1895 (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos); | 1872 (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos); |
| 1896 } | 1873 } |
| 1897 | 1874 |
| 1898 bool IsDtlsSctp(const std::string& protocol) { | 1875 bool IsDtlsSctp(const std::string& protocol) { |
| 1899 // This intentionally excludes "SCTP" and "SCTP/DTLS". | 1876 // This intentionally excludes "SCTP" and "SCTP/DTLS". |
| 1900 return protocol.find(cricket::kMediaProtocolDtlsSctp) != std::string::npos; | 1877 return protocol.find(cricket::kMediaProtocolDtlsSctp) != std::string::npos; |
| 1901 } | 1878 } |
| 1902 | 1879 |
| 1903 bool ParseSessionDescription(const std::string& message, size_t* pos, | 1880 bool ParseConnectionData(const std::string& line, |
| 1881 rtc::SocketAddress* addr, | |
| 1882 SdpParseError* error) { | |
| 1883 // Parse the line from left to right. | |
| 1884 std::string token; | |
| 1885 std::string rightpart; | |
| 1886 // RFC 4566 | |
| 1887 // c=<nettype> <addrtype> <connection-address> | |
| 1888 // Skip the "c=" | |
| 1889 if (!rtc::tokenize_first(line, kSdpDelimiterEqual, &token, &rightpart)) { | |
| 1890 return ParseFailed(line, "Failed to parse the network type.", error); | |
| 1891 } | |
| 1892 | |
| 1893 // Extract and verify the <nettype> | |
| 1894 if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpace, &token, &rightpart) || | |
| 1895 token != kConnectionNettype) { | |
| 1896 return ParseFailed(line, | |
| 1897 "Failed to parse the connection data. The network type " | |
| 1898 "is not currently supported.", | |
| 1899 error); | |
| 1900 } | |
| 1901 | |
| 1902 // Extract the "<addrtype>" and "<connection-address>". | |
| 1903 if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpace, &token, &rightpart)) { | |
| 1904 return ParseFailed(line, "Failed to parse the address type.", error); | |
| 1905 } | |
| 1906 | |
| 1907 // The rightpart part should be the IP address without the slash which is used | |
| 1908 // for multicast. | |
| 1909 if (rightpart.find('/') != std::string::npos) { | |
| 1910 return ParseFailed(line, | |
| 1911 "Failed to parse the connection data. Multicast is not " | |
| 1912 "currently supported.", | |
| 1913 error); | |
| 1914 } | |
| 1915 addr->SetIP(rightpart); | |
| 1916 | |
| 1917 // Verify that the addrtype matches the type of the parsed address. | |
| 1918 if ((addr->family() == AF_INET && token != "IP4") || | |
| 1919 (addr->family() == AF_INET6 && token != "IP6")) { | |
| 1920 addr->Clear(); | |
| 1921 return ParseFailed( | |
| 1922 line, | |
| 1923 "Failed to parse the connection data. The address type is mismatching.", | |
| 1924 error); | |
| 1925 } | |
| 1926 return true; | |
| 1927 } | |
| 1928 | |
| 1929 bool ParseSessionDescription(const std::string& message, | |
| 1930 size_t* pos, | |
| 1904 std::string* session_id, | 1931 std::string* session_id, |
| 1905 std::string* session_version, | 1932 std::string* session_version, |
| 1906 TransportDescription* session_td, | 1933 TransportDescription* session_td, |
| 1907 RtpHeaderExtensions* session_extmaps, | 1934 RtpHeaderExtensions* session_extmaps, |
| 1935 rtc::SocketAddress* connection_addr, | |
| 1908 cricket::SessionDescription* desc, | 1936 cricket::SessionDescription* desc, |
| 1909 SdpParseError* error) { | 1937 SdpParseError* error) { |
| 1910 std::string line; | 1938 std::string line; |
| 1911 | 1939 |
| 1912 desc->set_msid_supported(false); | 1940 desc->set_msid_supported(false); |
| 1913 | 1941 |
| 1914 // RFC 4566 | 1942 // RFC 4566 |
| 1915 // v= (protocol version) | 1943 // v= (protocol version) |
| 1916 if (!GetLineWithType(message, pos, &line, kLineTypeVersion)) { | 1944 if (!GetLineWithType(message, pos, &line, kLineTypeVersion)) { |
| 1917 return ParseFailedExpectLine(message, *pos, kLineTypeVersion, | 1945 return ParseFailedExpectLine(message, *pos, kLineTypeVersion, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1955 // e=* (email address) | 1983 // e=* (email address) |
| 1956 GetLineWithType(message, pos, &line, kLineTypeSessionEmail); | 1984 GetLineWithType(message, pos, &line, kLineTypeSessionEmail); |
| 1957 | 1985 |
| 1958 // RFC 4566 | 1986 // RFC 4566 |
| 1959 // p=* (phone number) | 1987 // p=* (phone number) |
| 1960 GetLineWithType(message, pos, &line, kLineTypeSessionPhone); | 1988 GetLineWithType(message, pos, &line, kLineTypeSessionPhone); |
| 1961 | 1989 |
| 1962 // RFC 4566 | 1990 // RFC 4566 |
| 1963 // c=* (connection information -- not required if included in | 1991 // c=* (connection information -- not required if included in |
| 1964 // all media) | 1992 // all media) |
| 1965 GetLineWithType(message, pos, &line, kLineTypeConnection); | 1993 if (GetLineWithType(message, pos, &line, kLineTypeConnection)) { |
| 1994 if (!ParseConnectionData(line, connection_addr, error)) { | |
| 1995 return false; | |
| 1996 } | |
| 1997 } | |
| 1966 | 1998 |
| 1967 // RFC 4566 | 1999 // RFC 4566 |
| 1968 // b=* (zero or more bandwidth information lines) | 2000 // b=* (zero or more bandwidth information lines) |
| 1969 while (GetLineWithType(message, pos, &line, kLineTypeSessionBandwidth)) { | 2001 while (GetLineWithType(message, pos, &line, kLineTypeSessionBandwidth)) { |
| 1970 // By pass zero or more b lines. | 2002 // By pass zero or more b lines. |
| 1971 } | 2003 } |
| 1972 | 2004 |
| 1973 // RFC 4566 | 2005 // RFC 4566 |
| 1974 // One or more time descriptions ("t=" and "r=" lines; see below) | 2006 // One or more time descriptions ("t=" and "r=" lines; see below) |
| 1975 // t= (time the session is active) | 2007 // t= (time the session is active) |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2259 *content_name = cricket::CN_DATA; | 2291 *content_name = cricket::CN_DATA; |
| 2260 break; | 2292 break; |
| 2261 default: | 2293 default: |
| 2262 RTC_NOTREACHED(); | 2294 RTC_NOTREACHED(); |
| 2263 break; | 2295 break; |
| 2264 } | 2296 } |
| 2265 if (!ParseContent(message, media_type, mline_index, protocol, payload_types, | 2297 if (!ParseContent(message, media_type, mline_index, protocol, payload_types, |
| 2266 pos, content_name, bundle_only, media_desc, transport, | 2298 pos, content_name, bundle_only, media_desc, transport, |
| 2267 candidates, error)) { | 2299 candidates, error)) { |
| 2268 delete media_desc; | 2300 delete media_desc; |
| 2269 return NULL; | 2301 return nullptr; |
| 2270 } | 2302 } |
| 2271 // Sort the codecs according to the m-line fmt list. | 2303 // Sort the codecs according to the m-line fmt list. |
| 2272 std::unordered_map<int, int> payload_type_preferences; | 2304 std::unordered_map<int, int> payload_type_preferences; |
| 2273 // "size + 1" so that the lowest preference payload type has a preference of | 2305 // "size + 1" so that the lowest preference payload type has a preference of |
| 2274 // 1, which is greater than the default (0) for payload types not in the fmt | 2306 // 1, which is greater than the default (0) for payload types not in the fmt |
| 2275 // list. | 2307 // list. |
| 2276 int preference = static_cast<int>(payload_types.size() + 1); | 2308 int preference = static_cast<int>(payload_types.size() + 1); |
| 2277 for (int pt : payload_types) { | 2309 for (int pt : payload_types) { |
| 2278 payload_type_preferences[pt] = preference--; | 2310 payload_type_preferences[pt] = preference--; |
| 2279 } | 2311 } |
| 2280 std::vector<typename C::CodecType> codecs = media_desc->codecs(); | 2312 std::vector<typename C::CodecType> codecs = media_desc->codecs(); |
| 2281 std::sort(codecs.begin(), codecs.end(), [&payload_type_preferences]( | 2313 std::sort(codecs.begin(), codecs.end(), [&payload_type_preferences]( |
| 2282 const typename C::CodecType& a, | 2314 const typename C::CodecType& a, |
| 2283 const typename C::CodecType& b) { | 2315 const typename C::CodecType& b) { |
| 2284 return payload_type_preferences[a.id] > payload_type_preferences[b.id]; | 2316 return payload_type_preferences[a.id] > payload_type_preferences[b.id]; |
| 2285 }); | 2317 }); |
| 2286 media_desc->set_codecs(codecs); | 2318 media_desc->set_codecs(codecs); |
| 2287 return media_desc; | 2319 return media_desc; |
| 2288 } | 2320 } |
| 2289 | 2321 |
| 2290 bool ParseMediaDescription(const std::string& message, | 2322 bool ParseMediaDescription(const std::string& message, |
| 2291 const TransportDescription& session_td, | 2323 const TransportDescription& session_td, |
| 2292 const RtpHeaderExtensions& session_extmaps, | 2324 const RtpHeaderExtensions& session_extmaps, |
| 2293 size_t* pos, | 2325 size_t* pos, |
| 2326 const rtc::SocketAddress& session_connection_addr, | |
| 2294 cricket::SessionDescription* desc, | 2327 cricket::SessionDescription* desc, |
| 2295 std::vector<JsepIceCandidate*>* candidates, | 2328 std::vector<JsepIceCandidate*>* candidates, |
| 2296 SdpParseError* error) { | 2329 SdpParseError* error) { |
| 2297 RTC_DCHECK(desc != NULL); | 2330 RTC_DCHECK(desc != NULL); |
| 2298 std::string line; | 2331 std::string line; |
| 2299 int mline_index = -1; | 2332 int mline_index = -1; |
| 2300 | 2333 |
| 2301 // Zero or more media descriptions | 2334 // Zero or more media descriptions |
| 2302 // RFC 4566 | 2335 // RFC 4566 |
| 2303 // m=<media> <port> <proto> <fmt> | 2336 // m=<media> <port> <proto> <fmt> |
| 2304 while (GetLineWithType(message, pos, &line, kLineTypeMedia)) { | 2337 while (GetLineWithType(message, pos, &line, kLineTypeMedia)) { |
| 2305 ++mline_index; | 2338 ++mline_index; |
| 2306 | 2339 |
| 2307 std::vector<std::string> fields; | 2340 std::vector<std::string> fields; |
| 2308 rtc::split(line.substr(kLinePrefixLength), | 2341 rtc::split(line.substr(kLinePrefixLength), |
| 2309 kSdpDelimiterSpace, &fields); | 2342 kSdpDelimiterSpace, &fields); |
| 2310 | 2343 |
| 2311 const size_t expected_min_fields = 4; | 2344 const size_t expected_min_fields = 4; |
| 2312 if (fields.size() < expected_min_fields) { | 2345 if (fields.size() < expected_min_fields) { |
| 2313 return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); | 2346 return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); |
| 2314 } | 2347 } |
| 2315 bool port_rejected = false; | 2348 bool port_rejected = false; |
| 2316 // RFC 3264 | 2349 // RFC 3264 |
| 2317 // To reject an offered stream, the port number in the corresponding stream | 2350 // To reject an offered stream, the port number in the corresponding stream |
| 2318 // in the answer MUST be set to zero. | 2351 // in the answer MUST be set to zero. |
| 2319 if (fields[1] == kMediaPortRejected) { | 2352 if (fields[1] == kMediaPortRejected) { |
| 2320 port_rejected = true; | 2353 port_rejected = true; |
| 2321 } | 2354 } |
| 2322 | 2355 |
| 2356 int port = 0; | |
| 2357 if (!rtc::FromString<int>(fields[1], &port) || !IsValidPort(port)) { | |
| 2358 return ParseFailed(line, "The port number is invalid", error); | |
| 2359 } | |
| 2323 std::string protocol = fields[2]; | 2360 std::string protocol = fields[2]; |
| 2324 | 2361 |
| 2325 // <fmt> | 2362 // <fmt> |
| 2326 std::vector<int> payload_types; | 2363 std::vector<int> payload_types; |
| 2327 if (IsRtp(protocol)) { | 2364 if (IsRtp(protocol)) { |
| 2328 for (size_t j = 3 ; j < fields.size(); ++j) { | 2365 for (size_t j = 3 ; j < fields.size(); ++j) { |
| 2329 // TODO(wu): Remove when below bug is fixed. | 2366 // TODO(wu): Remove when below bug is fixed. |
| 2330 // https://bugzilla.mozilla.org/show_bug.cgi?id=996329 | 2367 // https://bugzilla.mozilla.org/show_bug.cgi?id=996329 |
| 2331 if (fields[j].empty() && j == fields.size() - 1) { | 2368 if (fields[j].empty() && j == fields.size() - 1) { |
| 2332 continue; | 2369 continue; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2413 return ParseFailed("", | 2450 return ParseFailed("", |
| 2414 "The a=extmap MUST be either all session level or " | 2451 "The a=extmap MUST be either all session level or " |
| 2415 "all media level.", | 2452 "all media level.", |
| 2416 error); | 2453 error); |
| 2417 } | 2454 } |
| 2418 for (size_t i = 0; i < session_extmaps.size(); ++i) { | 2455 for (size_t i = 0; i < session_extmaps.size(); ++i) { |
| 2419 content->AddRtpHeaderExtension(session_extmaps[i]); | 2456 content->AddRtpHeaderExtension(session_extmaps[i]); |
| 2420 } | 2457 } |
| 2421 } | 2458 } |
| 2422 content->set_protocol(protocol); | 2459 content->set_protocol(protocol); |
| 2460 | |
| 2461 // Use the session level connection address if the media level addresses are | |
| 2462 // not specified. | |
| 2463 rtc::SocketAddress address; | |
| 2464 address = content->connection_address().IsNil() | |
| 2465 ? session_connection_addr | |
| 2466 : content->connection_address(); | |
| 2467 address.SetPort(port); | |
| 2468 content->set_connection_address(address); | |
| 2469 | |
| 2423 desc->AddContent(content_name, | 2470 desc->AddContent(content_name, |
| 2424 IsDtlsSctp(protocol) ? cricket::NS_JINGLE_DRAFT_SCTP | 2471 IsDtlsSctp(protocol) ? cricket::NS_JINGLE_DRAFT_SCTP |
| 2425 : cricket::NS_JINGLE_RTP, | 2472 : cricket::NS_JINGLE_RTP, |
| 2426 content_rejected, bundle_only, content.release()); | 2473 content_rejected, bundle_only, content.release()); |
| 2427 // Create TransportInfo with the media level "ice-pwd" and "ice-ufrag". | 2474 // Create TransportInfo with the media level "ice-pwd" and "ice-ufrag". |
| 2428 TransportInfo transport_info(content_name, transport); | 2475 TransportInfo transport_info(content_name, transport); |
| 2429 | 2476 |
| 2430 if (!desc->AddTransportInfo(transport_info)) { | 2477 if (!desc->AddTransportInfo(transport_info)) { |
| 2431 std::ostringstream description; | 2478 std::ostringstream description; |
| 2432 description << "Failed to AddTransportInfo with content name: " | 2479 description << "Failed to AddTransportInfo with content name: " |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2661 return ParseFailed(line, description.str(), error); | 2708 return ParseFailed(line, description.str(), error); |
| 2662 } | 2709 } |
| 2663 // Prevent integer overflow. | 2710 // Prevent integer overflow. |
| 2664 b = std::min(b, INT_MAX / 1000); | 2711 b = std::min(b, INT_MAX / 1000); |
| 2665 media_desc->set_bandwidth(b * 1000); | 2712 media_desc->set_bandwidth(b * 1000); |
| 2666 } | 2713 } |
| 2667 } | 2714 } |
| 2668 continue; | 2715 continue; |
| 2669 } | 2716 } |
| 2670 | 2717 |
| 2718 // Parse the media level connection data. | |
| 2719 if (IsLineType(line, kLineTypeConnection)) { | |
| 2720 rtc::SocketAddress addr; | |
| 2721 if (!ParseConnectionData(line, &addr, error)) { | |
| 2722 return false; | |
| 2723 } | |
| 2724 media_desc->set_connection_address(addr); | |
| 2725 continue; | |
| 2726 } | |
| 2727 | |
| 2671 if (!IsLineType(line, kLineTypeAttributes)) { | 2728 if (!IsLineType(line, kLineTypeAttributes)) { |
| 2672 // TODO: Handle other lines if needed. | 2729 // TODO: Handle other lines if needed. |
| 2673 LOG(LS_INFO) << "Ignored line: " << line; | 2730 LOG(LS_INFO) << "Ignored line: " << line; |
| 2674 continue; | 2731 continue; |
| 2675 } | 2732 } |
| 2676 | 2733 |
| 2677 // Handle attributes common to SCTP and RTP. | 2734 // Handle attributes common to SCTP and RTP. |
| 2678 if (HasAttribute(line, kAttributeMid)) { | 2735 if (HasAttribute(line, kAttributeMid)) { |
| 2679 // RFC 3388 | 2736 // RFC 3388 |
| 2680 // mid-attribute = "a=mid:" identification-tag | 2737 // mid-attribute = "a=mid:" identification-tag |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3234 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( | 3291 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( |
| 3235 media_desc, payload_type, feedback_param); | 3292 media_desc, payload_type, feedback_param); |
| 3236 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | 3293 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
| 3237 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( | 3294 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( |
| 3238 media_desc, payload_type, feedback_param); | 3295 media_desc, payload_type, feedback_param); |
| 3239 } | 3296 } |
| 3240 return true; | 3297 return true; |
| 3241 } | 3298 } |
| 3242 | 3299 |
| 3243 } // namespace webrtc | 3300 } // namespace webrtc |
| OLD | NEW |