| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2004 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 |
| 11 #include "webrtc/pc/mediasession.h" | 11 #include "webrtc/pc/mediasession.h" |
| 12 | 12 |
| 13 #include <algorithm> // For std::find_if, std::sort. | 13 #include <algorithm> // For std::find_if, std::sort. |
| 14 #include <functional> | 14 #include <functional> |
| 15 #include <map> | 15 #include <map> |
| 16 #include <memory> | 16 #include <memory> |
| 17 #include <set> | 17 #include <set> |
| 18 #include <unordered_map> | 18 #include <unordered_map> |
| 19 #include <utility> | 19 #include <utility> |
| 20 | 20 |
| 21 #include "webrtc/base/base64.h" | 21 #include "webrtc/base/base64.h" |
| 22 #include "webrtc/base/checks.h" | 22 #include "webrtc/base/checks.h" |
| 23 #include "webrtc/base/helpers.h" | 23 #include "webrtc/base/helpers.h" |
| 24 #include "webrtc/base/logging.h" | 24 #include "webrtc/base/logging.h" |
| 25 #include "webrtc/base/optional.h" |
| 25 #include "webrtc/base/stringutils.h" | 26 #include "webrtc/base/stringutils.h" |
| 26 #include "webrtc/common_types.h" | 27 #include "webrtc/common_types.h" |
| 27 #include "webrtc/common_video/h264/profile_level_id.h" | 28 #include "webrtc/common_video/h264/profile_level_id.h" |
| 28 #include "webrtc/media/base/cryptoparams.h" | 29 #include "webrtc/media/base/cryptoparams.h" |
| 29 #include "webrtc/media/base/mediaconstants.h" | 30 #include "webrtc/media/base/mediaconstants.h" |
| 30 #include "webrtc/p2p/base/p2pconstants.h" | 31 #include "webrtc/p2p/base/p2pconstants.h" |
| 31 #include "webrtc/pc/channelmanager.h" | 32 #include "webrtc/pc/channelmanager.h" |
| 32 #include "webrtc/pc/srtpfilter.h" | 33 #include "webrtc/pc/srtpfilter.h" |
| 33 | 34 |
| 34 namespace { | 35 namespace { |
| (...skipping 1388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 return NULL; | 1424 return NULL; |
| 1424 } | 1425 } |
| 1425 } | 1426 } |
| 1426 | 1427 |
| 1427 return offer.release(); | 1428 return offer.release(); |
| 1428 } | 1429 } |
| 1429 | 1430 |
| 1430 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( | 1431 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( |
| 1431 const SessionDescription* offer, const MediaSessionOptions& options, | 1432 const SessionDescription* offer, const MediaSessionOptions& options, |
| 1432 const SessionDescription* current_description) const { | 1433 const SessionDescription* current_description) const { |
| 1434 if (!offer) { |
| 1435 return nullptr; |
| 1436 } |
| 1433 // The answer contains the intersection of the codecs in the offer with the | 1437 // The answer contains the intersection of the codecs in the offer with the |
| 1434 // codecs we support. As indicated by XEP-0167, we retain the same payload ids | 1438 // codecs we support. As indicated by XEP-0167, we retain the same payload ids |
| 1435 // from the offer in the answer. | 1439 // from the offer in the answer. |
| 1436 std::unique_ptr<SessionDescription> answer(new SessionDescription()); | 1440 std::unique_ptr<SessionDescription> answer(new SessionDescription()); |
| 1437 | 1441 |
| 1438 StreamParamsVec current_streams; | 1442 StreamParamsVec current_streams; |
| 1439 GetCurrentStreamParams(current_description, ¤t_streams); | 1443 GetCurrentStreamParams(current_description, ¤t_streams); |
| 1440 | 1444 |
| 1441 if (offer) { | 1445 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE |
| 1442 ContentInfos::const_iterator it = offer->contents().begin(); | 1446 // group in the answer with the appropriate content names. |
| 1443 for (; it != offer->contents().end(); ++it) { | 1447 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE); |
| 1444 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) { | 1448 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE); |
| 1445 if (!AddAudioContentForAnswer(offer, options, current_description, | 1449 // Transport info shared by the bundle group. |
| 1446 ¤t_streams, answer.get())) { | 1450 std::unique_ptr<TransportInfo> bundle_transport; |
| 1447 return NULL; | 1451 |
| 1448 } | 1452 ContentInfos::const_iterator it = offer->contents().begin(); |
| 1449 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) { | 1453 for (; it != offer->contents().end(); ++it) { |
| 1450 if (!AddVideoContentForAnswer(offer, options, current_description, | 1454 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) { |
| 1451 ¤t_streams, answer.get())) { | 1455 if (!AddAudioContentForAnswer(offer, options, current_description, |
| 1452 return NULL; | 1456 bundle_transport.get(), ¤t_streams, |
| 1453 } | 1457 answer.get())) { |
| 1454 } else { | 1458 return NULL; |
| 1455 RTC_DCHECK(IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)); | |
| 1456 if (!AddDataContentForAnswer(offer, options, current_description, | |
| 1457 ¤t_streams, answer.get())) { | |
| 1458 return NULL; | |
| 1459 } | |
| 1460 } | 1459 } |
| 1460 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) { |
| 1461 if (!AddVideoContentForAnswer(offer, options, current_description, |
| 1462 bundle_transport.get(), ¤t_streams, |
| 1463 answer.get())) { |
| 1464 return NULL; |
| 1465 } |
| 1466 } else { |
| 1467 RTC_DCHECK(IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)); |
| 1468 if (!AddDataContentForAnswer(offer, options, current_description, |
| 1469 bundle_transport.get(), ¤t_streams, |
| 1470 answer.get())) { |
| 1471 return NULL; |
| 1472 } |
| 1473 } |
| 1474 // See if we can add the newly generated m= section to the BUNDLE group in |
| 1475 // the answer. |
| 1476 ContentInfo& added = answer->contents().back(); |
| 1477 if (!added.rejected && options.bundle_enabled && offer_bundle && |
| 1478 offer_bundle->HasContentName(added.name)) { |
| 1479 answer_bundle.AddContentName(added.name); |
| 1480 bundle_transport.reset( |
| 1481 new TransportInfo(*answer->GetTransportInfoByName(added.name))); |
| 1461 } | 1482 } |
| 1462 } | 1483 } |
| 1463 | 1484 |
| 1464 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE | 1485 // Only put BUNDLE group in answer if nonempty. |
| 1465 // group in the answer with the appropriate content names. | 1486 if (answer_bundle.FirstContentName()) { |
| 1466 if (offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled) { | 1487 answer->AddGroup(answer_bundle); |
| 1467 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE); | 1488 |
| 1468 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE); | 1489 // Share the same ICE credentials and crypto params across all contents, |
| 1469 for (ContentInfos::const_iterator content = answer->contents().begin(); | 1490 // as BUNDLE requires. |
| 1470 content != answer->contents().end(); ++content) { | 1491 if (!UpdateTransportInfoForBundle(answer_bundle, answer.get())) { |
| 1471 if (!content->rejected && offer_bundle->HasContentName(content->name)) { | 1492 LOG(LS_ERROR) << "CreateAnswer failed to UpdateTransportInfoForBundle."; |
| 1472 answer_bundle.AddContentName(content->name); | 1493 return NULL; |
| 1473 } | |
| 1474 } | 1494 } |
| 1475 if (answer_bundle.FirstContentName()) { | |
| 1476 answer->AddGroup(answer_bundle); | |
| 1477 | 1495 |
| 1478 // Share the same ICE credentials and crypto params across all contents, | 1496 if (!UpdateCryptoParamsForBundle(answer_bundle, answer.get())) { |
| 1479 // as BUNDLE requires. | 1497 LOG(LS_ERROR) << "CreateAnswer failed to UpdateCryptoParamsForBundle."; |
| 1480 if (!UpdateTransportInfoForBundle(answer_bundle, answer.get())) { | 1498 return NULL; |
| 1481 LOG(LS_ERROR) << "CreateAnswer failed to UpdateTransportInfoForBundle."; | |
| 1482 return NULL; | |
| 1483 } | |
| 1484 | |
| 1485 if (!UpdateCryptoParamsForBundle(answer_bundle, answer.get())) { | |
| 1486 LOG(LS_ERROR) << "CreateAnswer failed to UpdateCryptoParamsForBundle."; | |
| 1487 return NULL; | |
| 1488 } | |
| 1489 } | 1499 } |
| 1490 } | 1500 } |
| 1491 | 1501 |
| 1492 return answer.release(); | 1502 return answer.release(); |
| 1493 } | 1503 } |
| 1494 | 1504 |
| 1495 const AudioCodecs& MediaSessionDescriptionFactory::GetAudioCodecsForOffer( | 1505 const AudioCodecs& MediaSessionDescriptionFactory::GetAudioCodecsForOffer( |
| 1496 const RtpTransceiverDirection& direction) const { | 1506 const RtpTransceiverDirection& direction) const { |
| 1497 // If stream is inactive - generate list as if sendrecv. | 1507 // If stream is inactive - generate list as if sendrecv. |
| 1498 if (direction.send == direction.recv) { | 1508 if (direction.send == direction.recv) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1627 LOG(LS_ERROR) | 1637 LOG(LS_ERROR) |
| 1628 << "Failed to AddTransportOffer, content name=" << content_name; | 1638 << "Failed to AddTransportOffer, content name=" << content_name; |
| 1629 } | 1639 } |
| 1630 return ret; | 1640 return ret; |
| 1631 } | 1641 } |
| 1632 | 1642 |
| 1633 TransportDescription* MediaSessionDescriptionFactory::CreateTransportAnswer( | 1643 TransportDescription* MediaSessionDescriptionFactory::CreateTransportAnswer( |
| 1634 const std::string& content_name, | 1644 const std::string& content_name, |
| 1635 const SessionDescription* offer_desc, | 1645 const SessionDescription* offer_desc, |
| 1636 const TransportOptions& transport_options, | 1646 const TransportOptions& transport_options, |
| 1637 const SessionDescription* current_desc) const { | 1647 const SessionDescription* current_desc, |
| 1648 bool require_transport_attributes) const { |
| 1638 if (!transport_desc_factory_) | 1649 if (!transport_desc_factory_) |
| 1639 return NULL; | 1650 return NULL; |
| 1640 const TransportDescription* offer_tdesc = | 1651 const TransportDescription* offer_tdesc = |
| 1641 GetTransportDescription(content_name, offer_desc); | 1652 GetTransportDescription(content_name, offer_desc); |
| 1642 const TransportDescription* current_tdesc = | 1653 const TransportDescription* current_tdesc = |
| 1643 GetTransportDescription(content_name, current_desc); | 1654 GetTransportDescription(content_name, current_desc); |
| 1644 return | 1655 return transport_desc_factory_->CreateAnswer(offer_tdesc, transport_options, |
| 1645 transport_desc_factory_->CreateAnswer(offer_tdesc, transport_options, | 1656 require_transport_attributes, |
| 1646 current_tdesc); | 1657 current_tdesc); |
| 1647 } | 1658 } |
| 1648 | 1659 |
| 1649 bool MediaSessionDescriptionFactory::AddTransportAnswer( | 1660 bool MediaSessionDescriptionFactory::AddTransportAnswer( |
| 1650 const std::string& content_name, | 1661 const std::string& content_name, |
| 1651 const TransportDescription& transport_desc, | 1662 const TransportDescription& transport_desc, |
| 1652 SessionDescription* answer_desc) const { | 1663 SessionDescription* answer_desc) const { |
| 1653 if (!answer_desc->AddTransportInfo(TransportInfo(content_name, | 1664 if (!answer_desc->AddTransportInfo(TransportInfo(content_name, |
| 1654 transport_desc))) { | 1665 transport_desc))) { |
| 1655 LOG(LS_ERROR) | 1666 LOG(LS_ERROR) |
| 1656 << "Failed to AddTransportAnswer, content name=" << content_name; | 1667 << "Failed to AddTransportAnswer, content name=" << content_name; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1831 current_description, desc)) { | 1842 current_description, desc)) { |
| 1832 return false; | 1843 return false; |
| 1833 } | 1844 } |
| 1834 return true; | 1845 return true; |
| 1835 } | 1846 } |
| 1836 | 1847 |
| 1837 bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( | 1848 bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( |
| 1838 const SessionDescription* offer, | 1849 const SessionDescription* offer, |
| 1839 const MediaSessionOptions& options, | 1850 const MediaSessionOptions& options, |
| 1840 const SessionDescription* current_description, | 1851 const SessionDescription* current_description, |
| 1852 const TransportInfo* bundle_transport, |
| 1841 StreamParamsVec* current_streams, | 1853 StreamParamsVec* current_streams, |
| 1842 SessionDescription* answer) const { | 1854 SessionDescription* answer) const { |
| 1843 const ContentInfo* audio_content = GetFirstAudioContent(offer); | 1855 const ContentInfo* audio_content = GetFirstAudioContent(offer); |
| 1844 const AudioContentDescription* offer_audio = | 1856 const AudioContentDescription* offer_audio = |
| 1845 static_cast<const AudioContentDescription*>(audio_content->description); | 1857 static_cast<const AudioContentDescription*>(audio_content->description); |
| 1846 | 1858 |
| 1847 std::unique_ptr<TransportDescription> audio_transport(CreateTransportAnswer( | 1859 std::unique_ptr<TransportDescription> audio_transport( |
| 1848 audio_content->name, offer, | 1860 CreateTransportAnswer(audio_content->name, offer, |
| 1849 GetTransportOptions(options, audio_content->name), current_description)); | 1861 GetTransportOptions(options, audio_content->name), |
| 1862 current_description, bundle_transport != nullptr)); |
| 1850 if (!audio_transport) { | 1863 if (!audio_transport) { |
| 1851 return false; | 1864 return false; |
| 1852 } | 1865 } |
| 1853 | 1866 |
| 1854 // Pick codecs based on the requested communications direction in the offer. | 1867 // Pick codecs based on the requested communications direction in the offer. |
| 1855 const bool wants_send = | 1868 const bool wants_send = |
| 1856 options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_; | 1869 options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_; |
| 1857 auto wants_rtd = RtpTransceiverDirection(wants_send, options.recv_audio); | 1870 auto wants_rtd = RtpTransceiverDirection(wants_send, options.recv_audio); |
| 1858 auto offer_rtd = | 1871 auto offer_rtd = |
| 1859 RtpTransceiverDirection::FromMediaContentDirection( | 1872 RtpTransceiverDirection::FromMediaContentDirection( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1878 sdes_policy, | 1891 sdes_policy, |
| 1879 GetCryptos(GetFirstAudioContentDescription(current_description)), | 1892 GetCryptos(GetFirstAudioContentDescription(current_description)), |
| 1880 audio_rtp_extensions_, | 1893 audio_rtp_extensions_, |
| 1881 current_streams, | 1894 current_streams, |
| 1882 add_legacy_, | 1895 add_legacy_, |
| 1883 bundle_enabled, | 1896 bundle_enabled, |
| 1884 audio_answer.get())) { | 1897 audio_answer.get())) { |
| 1885 return false; // Fails the session setup. | 1898 return false; // Fails the session setup. |
| 1886 } | 1899 } |
| 1887 | 1900 |
| 1901 bool secure = bundle_transport ? bundle_transport->description.secure() |
| 1902 : audio_transport->secure(); |
| 1888 bool rejected = !options.has_audio() || audio_content->rejected || | 1903 bool rejected = !options.has_audio() || audio_content->rejected || |
| 1889 !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO, | 1904 !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO, |
| 1890 audio_answer->protocol(), | 1905 audio_answer->protocol(), secure); |
| 1891 audio_transport->secure()); | |
| 1892 if (!rejected) { | 1906 if (!rejected) { |
| 1893 AddTransportAnswer(audio_content->name, *(audio_transport.get()), answer); | 1907 AddTransportAnswer(audio_content->name, *(audio_transport.get()), answer); |
| 1894 } else { | 1908 } else { |
| 1895 // RFC 3264 | 1909 // RFC 3264 |
| 1896 // The answer MUST contain the same number of m-lines as the offer. | 1910 // The answer MUST contain the same number of m-lines as the offer. |
| 1897 LOG(LS_INFO) << "Audio is not supported in the answer."; | 1911 LOG(LS_INFO) << "Audio is not supported in the answer."; |
| 1898 } | 1912 } |
| 1899 | 1913 |
| 1900 answer->AddContent(audio_content->name, audio_content->type, rejected, | 1914 answer->AddContent(audio_content->name, audio_content->type, rejected, |
| 1901 audio_answer.release()); | 1915 audio_answer.release()); |
| 1902 return true; | 1916 return true; |
| 1903 } | 1917 } |
| 1904 | 1918 |
| 1905 bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( | 1919 bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( |
| 1906 const SessionDescription* offer, | 1920 const SessionDescription* offer, |
| 1907 const MediaSessionOptions& options, | 1921 const MediaSessionOptions& options, |
| 1908 const SessionDescription* current_description, | 1922 const SessionDescription* current_description, |
| 1923 const TransportInfo* bundle_transport, |
| 1909 StreamParamsVec* current_streams, | 1924 StreamParamsVec* current_streams, |
| 1910 SessionDescription* answer) const { | 1925 SessionDescription* answer) const { |
| 1911 const ContentInfo* video_content = GetFirstVideoContent(offer); | 1926 const ContentInfo* video_content = GetFirstVideoContent(offer); |
| 1912 std::unique_ptr<TransportDescription> video_transport(CreateTransportAnswer( | 1927 std::unique_ptr<TransportDescription> video_transport( |
| 1913 video_content->name, offer, | 1928 CreateTransportAnswer(video_content->name, offer, |
| 1914 GetTransportOptions(options, video_content->name), current_description)); | 1929 GetTransportOptions(options, video_content->name), |
| 1930 current_description, bundle_transport != nullptr)); |
| 1915 if (!video_transport) { | 1931 if (!video_transport) { |
| 1916 return false; | 1932 return false; |
| 1917 } | 1933 } |
| 1918 | 1934 |
| 1919 std::unique_ptr<VideoContentDescription> video_answer( | 1935 std::unique_ptr<VideoContentDescription> video_answer( |
| 1920 new VideoContentDescription()); | 1936 new VideoContentDescription()); |
| 1921 // Do not require or create SDES cryptos if DTLS is used. | 1937 // Do not require or create SDES cryptos if DTLS is used. |
| 1922 cricket::SecurePolicy sdes_policy = | 1938 cricket::SecurePolicy sdes_policy = |
| 1923 video_transport->secure() ? cricket::SEC_DISABLED : secure(); | 1939 video_transport->secure() ? cricket::SEC_DISABLED : secure(); |
| 1924 bool bundle_enabled = | 1940 bool bundle_enabled = |
| 1925 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled; | 1941 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled; |
| 1926 if (!CreateMediaContentAnswer( | 1942 if (!CreateMediaContentAnswer( |
| 1927 static_cast<const VideoContentDescription*>( | 1943 static_cast<const VideoContentDescription*>( |
| 1928 video_content->description), | 1944 video_content->description), |
| 1929 options, | 1945 options, |
| 1930 video_codecs_, | 1946 video_codecs_, |
| 1931 sdes_policy, | 1947 sdes_policy, |
| 1932 GetCryptos(GetFirstVideoContentDescription(current_description)), | 1948 GetCryptos(GetFirstVideoContentDescription(current_description)), |
| 1933 video_rtp_extensions_, | 1949 video_rtp_extensions_, |
| 1934 current_streams, | 1950 current_streams, |
| 1935 add_legacy_, | 1951 add_legacy_, |
| 1936 bundle_enabled, | 1952 bundle_enabled, |
| 1937 video_answer.get())) { | 1953 video_answer.get())) { |
| 1938 return false; | 1954 return false; |
| 1939 } | 1955 } |
| 1956 bool secure = bundle_transport ? bundle_transport->description.secure() |
| 1957 : video_transport->secure(); |
| 1940 bool rejected = !options.has_video() || video_content->rejected || | 1958 bool rejected = !options.has_video() || video_content->rejected || |
| 1941 !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO, | 1959 !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO, |
| 1942 video_answer->protocol(), | 1960 video_answer->protocol(), secure); |
| 1943 video_transport->secure()); | |
| 1944 if (!rejected) { | 1961 if (!rejected) { |
| 1945 if (!AddTransportAnswer(video_content->name, *(video_transport.get()), | 1962 if (!AddTransportAnswer(video_content->name, *(video_transport.get()), |
| 1946 answer)) { | 1963 answer)) { |
| 1947 return false; | 1964 return false; |
| 1948 } | 1965 } |
| 1949 video_answer->set_bandwidth(options.video_bandwidth); | 1966 video_answer->set_bandwidth(options.video_bandwidth); |
| 1950 } else { | 1967 } else { |
| 1951 // RFC 3264 | 1968 // RFC 3264 |
| 1952 // The answer MUST contain the same number of m-lines as the offer. | 1969 // The answer MUST contain the same number of m-lines as the offer. |
| 1953 LOG(LS_INFO) << "Video is not supported in the answer."; | 1970 LOG(LS_INFO) << "Video is not supported in the answer."; |
| 1954 } | 1971 } |
| 1955 answer->AddContent(video_content->name, video_content->type, rejected, | 1972 answer->AddContent(video_content->name, video_content->type, rejected, |
| 1956 video_answer.release()); | 1973 video_answer.release()); |
| 1957 return true; | 1974 return true; |
| 1958 } | 1975 } |
| 1959 | 1976 |
| 1960 bool MediaSessionDescriptionFactory::AddDataContentForAnswer( | 1977 bool MediaSessionDescriptionFactory::AddDataContentForAnswer( |
| 1961 const SessionDescription* offer, | 1978 const SessionDescription* offer, |
| 1962 const MediaSessionOptions& options, | 1979 const MediaSessionOptions& options, |
| 1963 const SessionDescription* current_description, | 1980 const SessionDescription* current_description, |
| 1981 const TransportInfo* bundle_transport, |
| 1964 StreamParamsVec* current_streams, | 1982 StreamParamsVec* current_streams, |
| 1965 SessionDescription* answer) const { | 1983 SessionDescription* answer) const { |
| 1966 const ContentInfo* data_content = GetFirstDataContent(offer); | 1984 const ContentInfo* data_content = GetFirstDataContent(offer); |
| 1967 std::unique_ptr<TransportDescription> data_transport(CreateTransportAnswer( | 1985 std::unique_ptr<TransportDescription> data_transport( |
| 1968 data_content->name, offer, | 1986 CreateTransportAnswer(data_content->name, offer, |
| 1969 GetTransportOptions(options, data_content->name), current_description)); | 1987 GetTransportOptions(options, data_content->name), |
| 1988 current_description, bundle_transport != nullptr)); |
| 1970 if (!data_transport) { | 1989 if (!data_transport) { |
| 1971 return false; | 1990 return false; |
| 1972 } | 1991 } |
| 1973 bool is_sctp = (options.data_channel_type == DCT_SCTP); | 1992 bool is_sctp = (options.data_channel_type == DCT_SCTP); |
| 1974 std::vector<DataCodec> data_codecs(data_codecs_); | 1993 std::vector<DataCodec> data_codecs(data_codecs_); |
| 1975 FilterDataCodecs(&data_codecs, is_sctp); | 1994 FilterDataCodecs(&data_codecs, is_sctp); |
| 1976 | 1995 |
| 1977 std::unique_ptr<DataContentDescription> data_answer( | 1996 std::unique_ptr<DataContentDescription> data_answer( |
| 1978 new DataContentDescription()); | 1997 new DataContentDescription()); |
| 1979 // Do not require or create SDES cryptos if DTLS is used. | 1998 // Do not require or create SDES cryptos if DTLS is used. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1995 data_answer.get())) { | 2014 data_answer.get())) { |
| 1996 return false; // Fails the session setup. | 2015 return false; // Fails the session setup. |
| 1997 } | 2016 } |
| 1998 | 2017 |
| 1999 // Respond with sctpmap if the offer uses sctpmap. | 2018 // Respond with sctpmap if the offer uses sctpmap. |
| 2000 const DataContentDescription* offer_data_description = | 2019 const DataContentDescription* offer_data_description = |
| 2001 static_cast<const DataContentDescription*>(data_content->description); | 2020 static_cast<const DataContentDescription*>(data_content->description); |
| 2002 bool offer_uses_sctpmap = offer_data_description->use_sctpmap(); | 2021 bool offer_uses_sctpmap = offer_data_description->use_sctpmap(); |
| 2003 data_answer->set_use_sctpmap(offer_uses_sctpmap); | 2022 data_answer->set_use_sctpmap(offer_uses_sctpmap); |
| 2004 | 2023 |
| 2024 bool secure = bundle_transport ? bundle_transport->description.secure() |
| 2025 : data_transport->secure(); |
| 2026 |
| 2005 bool rejected = !options.has_data() || data_content->rejected || | 2027 bool rejected = !options.has_data() || data_content->rejected || |
| 2006 !IsMediaProtocolSupported(MEDIA_TYPE_DATA, | 2028 !IsMediaProtocolSupported(MEDIA_TYPE_DATA, |
| 2007 data_answer->protocol(), | 2029 data_answer->protocol(), secure); |
| 2008 data_transport->secure()); | |
| 2009 if (!rejected) { | 2030 if (!rejected) { |
| 2010 data_answer->set_bandwidth(options.data_bandwidth); | 2031 data_answer->set_bandwidth(options.data_bandwidth); |
| 2011 if (!AddTransportAnswer(data_content->name, *(data_transport.get()), | 2032 if (!AddTransportAnswer(data_content->name, *(data_transport.get()), |
| 2012 answer)) { | 2033 answer)) { |
| 2013 return false; | 2034 return false; |
| 2014 } | 2035 } |
| 2015 } else { | 2036 } else { |
| 2016 // RFC 3264 | 2037 // RFC 3264 |
| 2017 // The answer MUST contain the same number of m-lines as the offer. | 2038 // The answer MUST contain the same number of m-lines as the offer. |
| 2018 LOG(LS_INFO) << "Data is not supported in the answer."; | 2039 LOG(LS_INFO) << "Data is not supported in the answer."; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2175 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); | 2196 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); |
| 2176 } | 2197 } |
| 2177 | 2198 |
| 2178 DataContentDescription* GetFirstDataContentDescription( | 2199 DataContentDescription* GetFirstDataContentDescription( |
| 2179 SessionDescription* sdesc) { | 2200 SessionDescription* sdesc) { |
| 2180 return static_cast<DataContentDescription*>( | 2201 return static_cast<DataContentDescription*>( |
| 2181 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); | 2202 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); |
| 2182 } | 2203 } |
| 2183 | 2204 |
| 2184 } // namespace cricket | 2205 } // namespace cricket |
| OLD | NEW |