diff options
Diffstat (limited to 'chromium/third_party/webrtc/pc')
68 files changed, 2102 insertions, 4074 deletions
diff --git a/chromium/third_party/webrtc/pc/BUILD.gn b/chromium/third_party/webrtc/pc/BUILD.gn index a48a0469d91..3ab816d0616 100644 --- a/chromium/third_party/webrtc/pc/BUILD.gn +++ b/chromium/third_party/webrtc/pc/BUILD.gn @@ -36,8 +36,6 @@ rtc_library("rtc_pc_base") { "composite_data_channel_transport.h", "composite_rtp_transport.cc", "composite_rtp_transport.h", - "datagram_rtp_transport.cc", - "datagram_rtp_transport.h", "dtls_srtp_transport.cc", "dtls_srtp_transport.h", "dtls_transport.cc", @@ -88,6 +86,7 @@ rtc_library("rtc_pc_base") { "../api:function_view", "../api:ice_transport_factory", "../api:libjingle_peerconnection_api", + "../api:priority", "../api:rtc_error", "../api:rtp_headers", "../api:rtp_parameters", @@ -96,7 +95,6 @@ rtc_library("rtc_pc_base") { "../api/crypto:options", "../api/rtc_event_log", "../api/transport:datagram_transport_interface", - "../api/transport/media:media_transport_interface", "../api/video:builtin_video_bitrate_allocator_factory", "../api/video:video_frame", "../api/video:video_rtp_headers", @@ -124,6 +122,8 @@ rtc_library("rtc_pc_base") { "../rtc_base/third_party/sigslot", "../system_wrappers:field_trial", "../system_wrappers:metrics", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/memory", @@ -236,6 +236,7 @@ rtc_library("peerconnection") { "../api:libjingle_peerconnection_api", "../api:media_stream_interface", "../api:network_state_predictor_api", + "../api:priority", "../api:rtc_error", "../api:rtc_event_log_output_file", "../api:rtc_stats_api", @@ -246,7 +247,6 @@ rtc_library("peerconnection") { "../api/task_queue", "../api/transport:datagram_transport_interface", "../api/transport:field_trial_based_config", - "../api/transport/media:media_transport_interface", "../api/units:data_rate", "../api/video:builtin_video_bitrate_allocator_factory", "../api/video:video_frame", @@ -274,6 +274,8 @@ rtc_library("peerconnection") { "../system_wrappers", "../system_wrappers:field_trial", "../system_wrappers:metrics", + ] + absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/types:optional", @@ -329,14 +331,11 @@ if (rtc_include_tests) { ":rtc_pc_base", "../api:array_view", "../api:audio_options_api", - "../api:fake_media_transport", "../api:ice_transport_factory", "../api:libjingle_peerconnection_api", - "../api:loopback_media_transport", "../api:rtc_error", "../api:rtp_headers", "../api:rtp_parameters", - "../api/transport/media:media_transport_interface", "../api/video:builtin_video_bitrate_allocator_factory", "../api/video/test:mock_recordable_encoded_frame", "../call:rtp_interfaces", @@ -404,8 +403,8 @@ if (rtc_include_tests) { "../system_wrappers", "../test:perf_test", "../test:test_support", - "//third_party/abseil-cpp/absl/types:optional", ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] } rtc_library("peerconnection_wrapper") { @@ -497,12 +496,13 @@ if (rtc_include_tests) { "../rtc_base:rtc_base_approved", "../rtc_base:rtc_task_queue", "../rtc_base:task_queue_for_test", + "../rtc_base/synchronization:sequence_checker", "../rtc_base/task_utils:repeating_task", "../rtc_base/third_party/sigslot", "../test:test_support", "../test:video_test_common", - "//third_party/abseil-cpp/absl/types:optional", ] + absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] } rtc_test("peerconnection_unittests") { @@ -515,6 +515,7 @@ if (rtc_include_tests) { "jsep_session_description_unittest.cc", "local_audio_source_unittest.cc", "media_stream_unittest.cc", + "peer_connection_adaptation_integrationtest.cc", "peer_connection_bundle_unittest.cc", "peer_connection_crypto_unittest.cc", "peer_connection_data_channel_unittest.cc", @@ -566,7 +567,6 @@ if (rtc_include_tests) { "../api:function_view", "../api:libjingle_logging_api", "../api:libjingle_peerconnection_api", - "../api:loopback_media_transport", "../api:media_stream_interface", "../api:mock_rtp", "../api:rtc_error", @@ -578,10 +578,10 @@ if (rtc_include_tests) { "../api/rtc_event_log", "../api/rtc_event_log:rtc_event_log_factory", "../api/task_queue:default_task_queue_factory", - "../api/transport/media:media_transport_interface", "../api/transport/rtp:rtp_source", "../api/units:time_delta", "../api/video:builtin_video_bitrate_allocator_factory", + "../call/adaptation:resource_adaptation_test_utilities", "../logging:fake_rtc_event_log", "../media:rtc_media_config", "../media:rtc_media_engine_defaults", @@ -605,6 +605,7 @@ if (rtc_include_tests) { "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/types:optional", ] if (is_android) { deps += [ ":android_black_magic" ] @@ -646,7 +647,6 @@ if (rtc_include_tests) { "../test:audio_codec_mocks", "../test:test_main", "../test:test_support", - "//third_party/abseil-cpp/absl/types:optional", ] if (is_android) { diff --git a/chromium/third_party/webrtc/pc/channel.cc b/chromium/third_party/webrtc/pc/channel.cc index f83f5cdd9a3..e7f62c6aa6d 100644 --- a/chromium/third_party/webrtc/pc/channel.cc +++ b/chromium/third_party/webrtc/pc/channel.cc @@ -16,7 +16,6 @@ #include "absl/algorithm/container.h" #include "absl/memory/memory.h" #include "api/call/audio_sink.h" -#include "api/transport/media/media_transport_config.h" #include "media/base/media_constants.h" #include "media/base/rtp_utils.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" @@ -142,7 +141,7 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread, RTC_DCHECK_RUN_ON(worker_thread_); RTC_DCHECK(ssrc_generator_); demuxer_criteria_.mid = content_name; - RTC_LOG(LS_INFO) << "Created channel for " << content_name; + RTC_LOG(LS_INFO) << "Created channel: " << ToString(); } BaseChannel::~BaseChannel() { @@ -156,12 +155,23 @@ BaseChannel::~BaseChannel() { // the media channel may try to send on the dead transport channel. NULLing // is not an effective strategy since the sends will come on another thread. media_channel_.reset(); - RTC_LOG(LS_INFO) << "Destroyed channel: " << content_name_; + RTC_LOG(LS_INFO) << "Destroyed channel: " << ToString(); +} + +std::string BaseChannel::ToString() const { + rtc::StringBuilder sb; + sb << "{mid: " << content_name_; + if (media_channel_) { + sb << ", media_type: " << MediaTypeToString(media_channel_->media_type()); + } + sb << "}"; + return sb.Release(); } bool BaseChannel::ConnectToRtpTransport() { RTC_DCHECK(rtp_transport_); if (!RegisterRtpDemuxerSink()) { + RTC_LOG(LS_ERROR) << "Failed to set up demuxing for " << ToString(); return false; } rtp_transport_->SignalReadyToSend.connect( @@ -184,24 +194,20 @@ void BaseChannel::DisconnectFromRtpTransport() { rtp_transport_->SignalSentPacket.disconnect(this); } -void BaseChannel::Init_w( - webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config) { +void BaseChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) { RTC_DCHECK_RUN_ON(worker_thread_); - media_transport_config_ = media_transport_config; network_thread_->Invoke<void>( RTC_FROM_HERE, [this, rtp_transport] { SetRtpTransport(rtp_transport); }); // Both RTP and RTCP channels should be set, we can call SetInterface on // the media channel and it can set network options. - media_channel_->SetInterface(this, media_transport_config); + media_channel_->SetInterface(this); } void BaseChannel::Deinit() { RTC_DCHECK(worker_thread_->IsCurrent()); - media_channel_->SetInterface(/*iface=*/nullptr, - webrtc::MediaTransportConfig()); + media_channel_->SetInterface(/*iface=*/nullptr); // Packets arrive on the network thread, processing packets calls virtual // functions, so need to stop this process in Deinit that is called in // derived classes destructor. @@ -237,7 +243,8 @@ bool BaseChannel::SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) { transport_name_ = rtp_transport_->transport_name(); if (!ConnectToRtpTransport()) { - RTC_LOG(LS_ERROR) << "Failed to connect to the new RtpTransport."; + RTC_LOG(LS_ERROR) << "Failed to connect to the new RtpTransport for " + << ToString() << "."; return false; } OnTransportReadyToSend(rtp_transport_->IsReadyToSend()); @@ -349,7 +356,7 @@ void BaseChannel::OnWritableState(bool writable) { void BaseChannel::OnNetworkRouteChanged( absl::optional<rtc::NetworkRoute> network_route) { - RTC_LOG(LS_INFO) << "Network route was changed."; + RTC_LOG(LS_INFO) << "Network route for " << ToString() << " was changed."; RTC_DCHECK(network_thread_->IsCurrent()); rtc::NetworkRoute new_route; @@ -404,7 +411,7 @@ bool BaseChannel::SendPacket(bool rtcp, // Protect ourselves against crazy data. if (!IsValidRtpPacketSize(packet_type, packet->size())) { - RTC_LOG(LS_ERROR) << "Dropping outgoing " << content_name_ << " " + RTC_LOG(LS_ERROR) << "Dropping outgoing " << ToString() << " " << RtpPacketTypeToString(packet_type) << " packet: wrong size=" << packet->size(); return false; @@ -420,16 +427,16 @@ bool BaseChannel::SendPacket(bool rtcp, } // However, there shouldn't be any RTP packets sent before SRTP is set up // (and SetSend(true) is called). - RTC_LOG(LS_ERROR) - << "Can't send outgoing RTP packet when SRTP is inactive" - " and crypto is required"; + RTC_LOG(LS_ERROR) << "Can't send outgoing RTP packet for " << ToString() + << " when SRTP is inactive and crypto is required"; RTC_NOTREACHED(); return false; } std::string packet_type = rtcp ? "RTCP" : "RTP"; RTC_LOG(LS_WARNING) << "Sending an " << packet_type - << " packet without encryption."; + << " packet without encryption for " << ToString() + << "."; } // Bon voyage. @@ -463,7 +470,8 @@ void BaseChannel::OnRtpPacket(const webrtc::RtpPacketReceived& parsed_packet) { // for us to just eat packets here. This is all sidestepped if RTCP mux // is used anyway. RTC_LOG(LS_WARNING) << "Can't process incoming RTP packet when " - "SRTP is inactive and crypto is required"; + "SRTP is inactive and crypto is required " + << ToString(); return; } @@ -504,7 +512,7 @@ void BaseChannel::EnableMedia_w() { if (enabled_) return; - RTC_LOG(LS_INFO) << "Channel enabled"; + RTC_LOG(LS_INFO) << "Channel enabled: " << ToString(); enabled_ = true; UpdateMediaSendRecvState_w(); } @@ -514,7 +522,7 @@ void BaseChannel::DisableMedia_w() { if (!enabled_) return; - RTC_LOG(LS_INFO) << "Channel disabled"; + RTC_LOG(LS_INFO) << "Channel disabled: " << ToString(); enabled_ = false; UpdateMediaSendRecvState_w(); } @@ -534,7 +542,7 @@ void BaseChannel::ChannelWritable_n() { return; } - RTC_LOG(LS_INFO) << "Channel writable (" << content_name_ << ")" + RTC_LOG(LS_INFO) << "Channel writable (" << ToString() << ")" << (was_ever_writable_ ? "" : " for the first time"); was_ever_writable_ = true; @@ -547,7 +555,7 @@ void BaseChannel::ChannelNotWritable_n() { if (!writable_) return; - RTC_LOG(LS_INFO) << "Channel not writable (" << content_name_ << ")"; + RTC_LOG(LS_INFO) << "Channel not writable (" << ToString() << ")"; writable_ = false; UpdateMediaSendRecvState(); } @@ -591,7 +599,8 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams, if (!media_channel()->RemoveSendStream(old_stream.first_ssrc())) { rtc::StringBuilder desc; desc << "Failed to remove send stream with ssrc " - << old_stream.first_ssrc() << "."; + << old_stream.first_ssrc() << " from m-section with mid='" + << content_name() << "'."; SafeSetError(desc.str(), error_desc); ret = false; } @@ -617,7 +626,8 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams, if (new_stream.has_ssrcs() && new_stream.has_rids()) { rtc::StringBuilder desc; desc << "Failed to add send stream: " << new_stream.first_ssrc() - << ". Stream has both SSRCs and RIDs."; + << " into m-section with mid='" << content_name() + << "'. Stream has both SSRCs and RIDs."; SafeSetError(desc.str(), error_desc); ret = false; continue; @@ -632,10 +642,12 @@ bool BaseChannel::UpdateLocalStreams_w(const std::vector<StreamParams>& streams, } if (media_channel()->AddSendStream(new_stream)) { - RTC_LOG(LS_INFO) << "Add send stream ssrc: " << new_stream.ssrcs[0]; + RTC_LOG(LS_INFO) << "Add send stream ssrc: " << new_stream.ssrcs[0] + << " into " << ToString(); } else { rtc::StringBuilder desc; - desc << "Failed to add send stream ssrc: " << new_stream.first_ssrc(); + desc << "Failed to add send stream ssrc: " << new_stream.first_ssrc() + << " into m-section with mid='" << content_name() << "'"; SafeSetError(desc.str(), error_desc); ret = false; } @@ -655,15 +667,18 @@ bool BaseChannel::UpdateRemoteStreams_w( // the unsignaled stream params that are cached. if (!old_stream.has_ssrcs() && !HasStreamWithNoSsrcs(streams)) { ResetUnsignaledRecvStream_w(); - RTC_LOG(LS_INFO) << "Reset unsignaled remote stream."; + RTC_LOG(LS_INFO) << "Reset unsignaled remote stream for " << ToString() + << "."; } else if (old_stream.has_ssrcs() && !GetStreamBySsrc(streams, old_stream.first_ssrc())) { if (RemoveRecvStream_w(old_stream.first_ssrc())) { - RTC_LOG(LS_INFO) << "Remove remote ssrc: " << old_stream.first_ssrc(); + RTC_LOG(LS_INFO) << "Remove remote ssrc: " << old_stream.first_ssrc() + << " from " << ToString() << "."; } else { rtc::StringBuilder desc; desc << "Failed to remove remote stream with ssrc " - << old_stream.first_ssrc() << "."; + << old_stream.first_ssrc() << " from m-section with mid='" + << content_name() << "'."; SafeSetError(desc.str(), error_desc); ret = false; } @@ -681,13 +696,15 @@ bool BaseChannel::UpdateRemoteStreams_w( RTC_LOG(LS_INFO) << "Add remote ssrc: " << (new_stream.has_ssrcs() ? std::to_string(new_stream.first_ssrc()) - : "unsignaled"); + : "unsignaled") + << " to " << ToString(); } else { rtc::StringBuilder desc; desc << "Failed to add remote stream ssrc: " << (new_stream.has_ssrcs() ? std::to_string(new_stream.first_ssrc()) - : "unsignaled"); + : "unsignaled") + << " to " << ToString(); SafeSetError(desc.str(), error_desc); ret = false; } @@ -697,7 +714,9 @@ bool BaseChannel::UpdateRemoteStreams_w( new_stream.ssrcs.end()); } // Re-register the sink to update the receiving ssrcs. - RegisterRtpDemuxerSink(); + if (!RegisterRtpDemuxerSink()) { + RTC_LOG(LS_ERROR) << "Failed to set up demuxing for " << ToString(); + } remote_streams_ = streams; return ret; } @@ -796,10 +815,8 @@ void BaseChannel::UpdateMediaSendRecvState() { [this] { UpdateMediaSendRecvState_w(); }); } -void VoiceChannel::Init_w( - webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config) { - BaseChannel::Init_w(rtp_transport, media_transport_config); +void VoiceChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) { + BaseChannel::Init_w(rtp_transport); } void VoiceChannel::UpdateMediaSendRecvState_w() { @@ -813,7 +830,8 @@ void VoiceChannel::UpdateMediaSendRecvState_w() { bool send = IsReadyToSendMedia_w(); media_channel()->SetSend(send); - RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send; + RTC_LOG(LS_INFO) << "Changing voice state, recv=" << recv << " send=" << send + << " for " << ToString(); } bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, @@ -821,7 +839,7 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, std::string* error_desc) { TRACE_EVENT0("webrtc", "VoiceChannel::SetLocalContent_w"); RTC_DCHECK_RUN_ON(worker_thread()); - RTC_LOG(LS_INFO) << "Setting local voice description"; + RTC_LOG(LS_INFO) << "Setting local voice description for " << ToString(); RTC_DCHECK(content); if (!content) { @@ -841,8 +859,11 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, audio, rtp_header_extensions, webrtc::RtpTransceiverDirectionHasRecv(audio->direction()), &recv_params); if (!media_channel()->SetRecvParameters(recv_params)) { - SafeSetError("Failed to set local audio description recv parameters.", - error_desc); + SafeSetError( + "Failed to set local audio description recv parameters for m-section " + "with mid='" + + content_name() + "'.", + error_desc); return false; } @@ -852,7 +873,7 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, } // Need to re-register the sink to update the handled payload. if (!RegisterRtpDemuxerSink()) { - RTC_LOG(LS_ERROR) << "Failed to set up audio demuxing."; + RTC_LOG(LS_ERROR) << "Failed to set up audio demuxing for " << ToString(); return false; } } @@ -864,7 +885,11 @@ bool VoiceChannel::SetLocalContent_w(const MediaContentDescription* content, // description too (without a remote description, we won't be able // to send them anyway). if (!UpdateLocalStreams_w(audio->streams(), type, error_desc)) { - SafeSetError("Failed to set local audio description streams.", error_desc); + SafeSetError( + "Failed to set local audio description streams for m-section with " + "mid='" + + content_name() + "'.", + error_desc); return false; } @@ -878,7 +903,7 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, std::string* error_desc) { TRACE_EVENT0("webrtc", "VoiceChannel::SetRemoteContent_w"); RTC_DCHECK_RUN_ON(worker_thread()); - RTC_LOG(LS_INFO) << "Setting remote voice description"; + RTC_LOG(LS_INFO) << "Setting remote voice description for " << ToString(); RTC_DCHECK(content); if (!content) { @@ -899,18 +924,22 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, bool parameters_applied = media_channel()->SetSendParameters(send_params); if (!parameters_applied) { - SafeSetError("Failed to set remote audio description send parameters.", - error_desc); + SafeSetError( + "Failed to set remote audio description send parameters for m-section " + "with mid='" + + content_name() + "'.", + error_desc); return false; } last_send_params_ = send_params; if (!webrtc::RtpTransceiverDirectionHasSend(content->direction())) { RTC_DLOG(LS_VERBOSE) << "SetRemoteContent_w: remote side will not send - " - "disable payload type demuxing"; + "disable payload type demuxing for " + << ToString(); ClearHandledPayloadTypes(); if (!RegisterRtpDemuxerSink()) { - RTC_LOG(LS_ERROR) << "Failed to update audio demuxing."; + RTC_LOG(LS_ERROR) << "Failed to update audio demuxing for " << ToString(); return false; } } @@ -920,7 +949,11 @@ bool VoiceChannel::SetRemoteContent_w(const MediaContentDescription* content, // description too (without a local description, we won't be able to // recv them anyway). if (!UpdateRemoteStreams_w(audio->streams(), type, error_desc)) { - SafeSetError("Failed to set remote audio description streams.", error_desc); + SafeSetError( + "Failed to set remote audio description streams for m-section with " + "mid='" + + content_name() + "'.", + error_desc); return false; } @@ -958,11 +991,12 @@ void VideoChannel::UpdateMediaSendRecvState_w() { // and we have had some form of connectivity. bool send = IsReadyToSendMedia_w(); if (!media_channel()->SetSend(send)) { - RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel"; + RTC_LOG(LS_ERROR) << "Failed to SetSend on video channel: " + ToString(); // TODO(gangji): Report error back to server. } - RTC_LOG(LS_INFO) << "Changing video state, send=" << send; + RTC_LOG(LS_INFO) << "Changing video state, send=" << send << " for " + << ToString(); } void VideoChannel::FillBitrateInfo(BandwidthEstimationInfo* bwe_info) { @@ -975,7 +1009,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, std::string* error_desc) { TRACE_EVENT0("webrtc", "VideoChannel::SetLocalContent_w"); RTC_DCHECK_RUN_ON(worker_thread()); - RTC_LOG(LS_INFO) << "Setting local video description"; + RTC_LOG(LS_INFO) << "Setting local video description for " << ToString(); RTC_DCHECK(content); if (!content) { @@ -1007,7 +1041,9 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, needs_send_params_update = true; } else if (recv_codec->packetization != send_codec.packetization) { SafeSetError( - "Failed to set local answer due to invalid codec packetization.", + "Failed to set local answer due to invalid codec packetization " + "specified in m-section with mid='" + + content_name() + "'.", error_desc); return false; } @@ -1016,8 +1052,11 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, } if (!media_channel()->SetRecvParameters(recv_params)) { - SafeSetError("Failed to set local video description recv parameters.", - error_desc); + SafeSetError( + "Failed to set local video description recv parameters for m-section " + "with mid='" + + content_name() + "'.", + error_desc); return false; } @@ -1027,7 +1066,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, } // Need to re-register the sink to update the handled payload. if (!RegisterRtpDemuxerSink()) { - RTC_LOG(LS_ERROR) << "Failed to set up video demuxing."; + RTC_LOG(LS_ERROR) << "Failed to set up video demuxing for " << ToString(); return false; } } @@ -1036,7 +1075,9 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, if (needs_send_params_update) { if (!media_channel()->SetSendParameters(send_params)) { - SafeSetError("Failed to set send parameters.", error_desc); + SafeSetError("Failed to set send parameters for m-section with mid='" + + content_name() + "'.", + error_desc); return false; } last_send_params_ = send_params; @@ -1047,7 +1088,11 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content, // description too (without a remote description, we won't be able // to send them anyway). if (!UpdateLocalStreams_w(video->streams(), type, error_desc)) { - SafeSetError("Failed to set local video description streams.", error_desc); + SafeSetError( + "Failed to set local video description streams for m-section with " + "mid='" + + content_name() + "'.", + error_desc); return false; } @@ -1061,7 +1106,7 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, std::string* error_desc) { TRACE_EVENT0("webrtc", "VideoChannel::SetRemoteContent_w"); RTC_DCHECK_RUN_ON(worker_thread()); - RTC_LOG(LS_INFO) << "Setting remote video description"; + RTC_LOG(LS_INFO) << "Setting remote video description for " << ToString(); RTC_DCHECK(content); if (!content) { @@ -1095,7 +1140,9 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, needs_recv_params_update = true; } else if (send_codec->packetization != recv_codec.packetization) { SafeSetError( - "Failed to set remote answer due to invalid codec packetization.", + "Failed to set remote answer due to invalid codec packetization " + "specifid in m-section with mid='" + + content_name() + "'.", error_desc); return false; } @@ -1104,15 +1151,20 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, } if (!media_channel()->SetSendParameters(send_params)) { - SafeSetError("Failed to set remote video description send parameters.", - error_desc); + SafeSetError( + "Failed to set remote video description send parameters for m-section " + "with mid='" + + content_name() + "'.", + error_desc); return false; } last_send_params_ = send_params; if (needs_recv_params_update) { if (!media_channel()->SetRecvParameters(recv_params)) { - SafeSetError("Failed to set recv parameters.", error_desc); + SafeSetError("Failed to set recv parameters for m-section with mid='" + + content_name() + "'.", + error_desc); return false; } last_recv_params_ = recv_params; @@ -1120,10 +1172,11 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, if (!webrtc::RtpTransceiverDirectionHasSend(content->direction())) { RTC_DLOG(LS_VERBOSE) << "SetRemoteContent_w: remote side will not send - " - "disable payload type demuxing"; + "disable payload type demuxing for " + << ToString(); ClearHandledPayloadTypes(); if (!RegisterRtpDemuxerSink()) { - RTC_LOG(LS_ERROR) << "Failed to update video demuxing."; + RTC_LOG(LS_ERROR) << "Failed to update video demuxing for " << ToString(); return false; } } @@ -1133,7 +1186,11 @@ bool VideoChannel::SetRemoteContent_w(const MediaContentDescription* content, // description too (without a local description, we won't be able to // recv them anyway). if (!UpdateRemoteStreams_w(video->streams(), type, error_desc)) { - SafeSetError("Failed to set remote video description streams.", error_desc); + SafeSetError( + "Failed to set remote video description streams for m-section with " + "mid='" + + content_name() + "'.", + error_desc); return false; } set_remote_content_direction(content->direction()); @@ -1165,10 +1222,8 @@ RtpDataChannel::~RtpDataChannel() { Deinit(); } -void RtpDataChannel::Init_w( - webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config) { - BaseChannel::Init_w(rtp_transport, media_transport_config); +void RtpDataChannel::Init_w(webrtc::RtpTransportInternal* rtp_transport) { + BaseChannel::Init_w(rtp_transport); media_channel()->SignalDataReceived.connect(this, &RtpDataChannel::OnDataReceived); media_channel()->SignalReadyToSend.connect( @@ -1203,7 +1258,7 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, std::string* error_desc) { TRACE_EVENT0("webrtc", "RtpDataChannel::SetLocalContent_w"); RTC_DCHECK_RUN_ON(worker_thread()); - RTC_LOG(LS_INFO) << "Setting local data description"; + RTC_LOG(LS_INFO) << "Setting local data description for " << ToString(); RTC_DCHECK(content); if (!content) { @@ -1224,8 +1279,11 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, data, rtp_header_extensions, webrtc::RtpTransceiverDirectionHasRecv(data->direction()), &recv_params); if (!media_channel()->SetRecvParameters(recv_params)) { - SafeSetError("Failed to set remote data description recv parameters.", - error_desc); + SafeSetError( + "Failed to set remote data description recv parameters for m-section " + "with mid='" + + content_name() + "'.", + error_desc); return false; } for (const DataCodec& codec : data->codecs()) { @@ -1233,7 +1291,7 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, } // Need to re-register the sink to update the handled payload. if (!RegisterRtpDemuxerSink()) { - RTC_LOG(LS_ERROR) << "Failed to set up data demuxing."; + RTC_LOG(LS_ERROR) << "Failed to set up data demuxing for " << ToString(); return false; } @@ -1244,7 +1302,11 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content, // description too (without a remote description, we won't be able // to send them anyway). if (!UpdateLocalStreams_w(data->streams(), type, error_desc)) { - SafeSetError("Failed to set local data description streams.", error_desc); + SafeSetError( + "Failed to set local data description streams for m-section with " + "mid='" + + content_name() + "'.", + error_desc); return false; } @@ -1258,7 +1320,7 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, std::string* error_desc) { TRACE_EVENT0("webrtc", "RtpDataChannel::SetRemoteContent_w"); RTC_DCHECK_RUN_ON(worker_thread()); - RTC_LOG(LS_INFO) << "Setting remote data description"; + RTC_LOG(LS_INFO) << "Setting remote data description for " << ToString(); RTC_DCHECK(content); if (!content) { @@ -1280,14 +1342,17 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, RtpHeaderExtensions rtp_header_extensions = GetFilteredRtpHeaderExtensions(data->rtp_header_extensions()); - RTC_LOG(LS_INFO) << "Setting remote data description"; + RTC_LOG(LS_INFO) << "Setting remote data description for " << ToString(); DataSendParameters send_params = last_send_params_; RtpSendParametersFromMediaDescription<DataCodec>( data, rtp_header_extensions, webrtc::RtpTransceiverDirectionHasRecv(data->direction()), &send_params); if (!media_channel()->SetSendParameters(send_params)) { - SafeSetError("Failed to set remote data description send parameters.", - error_desc); + SafeSetError( + "Failed to set remote data description send parameters for m-section " + "with mid='" + + content_name() + "'.", + error_desc); return false; } last_send_params_ = send_params; @@ -1297,7 +1362,11 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content, // description too (without a local description, we won't be able to // recv them anyway). if (!UpdateRemoteStreams_w(data->streams(), type, error_desc)) { - SafeSetError("Failed to set remote data description streams.", error_desc); + SafeSetError( + "Failed to set remote data description streams for m-section with " + "mid='" + + content_name() + "'.", + error_desc); return false; } @@ -1311,20 +1380,21 @@ void RtpDataChannel::UpdateMediaSendRecvState_w() { // content. We receive data on the default channel and multiplexed streams. bool recv = IsReadyToReceiveMedia_w(); if (!media_channel()->SetReceive(recv)) { - RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel"; + RTC_LOG(LS_ERROR) << "Failed to SetReceive on data channel: " << ToString(); } // Send outgoing data if we're the active call, we have the remote content, // and we have had some form of connectivity. bool send = IsReadyToSendMedia_w(); if (!media_channel()->SetSend(send)) { - RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel"; + RTC_LOG(LS_ERROR) << "Failed to SetSend on data channel: " << ToString(); } // Trigger SignalReadyToSendData asynchronously. OnDataChannelReadyToSend(send); - RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send; + RTC_LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send + << " for " << ToString(); } void RtpDataChannel::OnMessage(rtc::Message* pmsg) { diff --git a/chromium/third_party/webrtc/pc/channel.h b/chromium/third_party/webrtc/pc/channel.h index 238a8e20fee..406058ed4f2 100644 --- a/chromium/third_party/webrtc/pc/channel.h +++ b/chromium/third_party/webrtc/pc/channel.h @@ -22,7 +22,6 @@ #include "api/function_view.h" #include "api/jsep.h" #include "api/rtp_receiver_interface.h" -#include "api/transport/media/media_transport_config.h" #include "api/video/video_sink_interface.h" #include "api/video/video_source_interface.h" #include "call/rtp_packet_sink_interface.h" @@ -46,7 +45,6 @@ namespace webrtc { class AudioSinkInterface; -class MediaTransportInterface; } // namespace webrtc namespace cricket { @@ -72,7 +70,7 @@ struct CryptoParams; // NetworkInterface. class BaseChannel : public ChannelInterface, - public rtc::MessageHandler, + public rtc::MessageHandlerAutoCleanup, public sigslot::has_slots<>, public MediaChannel::NetworkInterface, public webrtc::RtpPacketSinkInterface { @@ -92,9 +90,7 @@ class BaseChannel : public ChannelInterface, webrtc::CryptoOptions crypto_options, rtc::UniqueRandomIdGenerator* ssrc_generator); virtual ~BaseChannel(); - virtual void Init_w( - webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config); + virtual void Init_w(webrtc::RtpTransportInternal* rtp_transport); // Deinit may be called multiple times and is simply ignored if it's already // done. @@ -275,6 +271,9 @@ class BaseChannel : public ChannelInterface, bool RegisterRtpDemuxerSink(); + // Return description of media channel to facilitate logging + std::string ToString() const; + bool has_received_packet_ = false; private: @@ -296,9 +295,6 @@ class BaseChannel : public ChannelInterface, webrtc::RtpTransportInternal* rtp_transport_ = nullptr; - // Optional media transport configuration (experimental). - webrtc::MediaTransportConfig media_transport_config_; - std::vector<std::pair<rtc::Socket::Option, int> > socket_options_; std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_; bool writable_ = false; @@ -350,9 +346,7 @@ class VoiceChannel : public BaseChannel { cricket::MediaType media_type() const override { return cricket::MEDIA_TYPE_AUDIO; } - void Init_w( - webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config) override; + void Init_w(webrtc::RtpTransportInternal* rtp_transport) override; private: // overrides from BaseChannel @@ -432,9 +426,7 @@ class RtpDataChannel : public BaseChannel { DtlsTransportInternal* rtcp_dtls_transport, rtc::PacketTransportInternal* rtp_packet_transport, rtc::PacketTransportInternal* rtcp_packet_transport); - void Init_w( - webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config) override; + void Init_w(webrtc::RtpTransportInternal* rtp_transport) override; virtual bool SendData(const SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, diff --git a/chromium/third_party/webrtc/pc/channel_manager.cc b/chromium/third_party/webrtc/pc/channel_manager.cc index f5f3dd4a7bb..84d74678b5b 100644 --- a/chromium/third_party/webrtc/pc/channel_manager.cc +++ b/chromium/third_party/webrtc/pc/channel_manager.cc @@ -187,7 +187,6 @@ VoiceChannel* ChannelManager::CreateVoiceChannel( webrtc::Call* call, const cricket::MediaConfig& media_config, webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config, rtc::Thread* signaling_thread, const std::string& content_name, bool srtp_required, @@ -197,9 +196,8 @@ VoiceChannel* ChannelManager::CreateVoiceChannel( if (!worker_thread_->IsCurrent()) { return worker_thread_->Invoke<VoiceChannel*>(RTC_FROM_HERE, [&] { return CreateVoiceChannel(call, media_config, rtp_transport, - media_transport_config, signaling_thread, - content_name, srtp_required, crypto_options, - ssrc_generator, options); + signaling_thread, content_name, srtp_required, + crypto_options, ssrc_generator, options); }); } @@ -221,7 +219,7 @@ VoiceChannel* ChannelManager::CreateVoiceChannel( absl::WrapUnique(media_channel), content_name, srtp_required, crypto_options, ssrc_generator); - voice_channel->Init_w(rtp_transport, media_transport_config); + voice_channel->Init_w(rtp_transport); VoiceChannel* voice_channel_ptr = voice_channel.get(); voice_channels_.push_back(std::move(voice_channel)); @@ -257,7 +255,6 @@ VideoChannel* ChannelManager::CreateVideoChannel( webrtc::Call* call, const cricket::MediaConfig& media_config, webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config, rtc::Thread* signaling_thread, const std::string& content_name, bool srtp_required, @@ -267,10 +264,10 @@ VideoChannel* ChannelManager::CreateVideoChannel( webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) { if (!worker_thread_->IsCurrent()) { return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] { - return CreateVideoChannel( - call, media_config, rtp_transport, media_transport_config, - signaling_thread, content_name, srtp_required, crypto_options, - ssrc_generator, options, video_bitrate_allocator_factory); + return CreateVideoChannel(call, media_config, rtp_transport, + signaling_thread, content_name, srtp_required, + crypto_options, ssrc_generator, options, + video_bitrate_allocator_factory); }); } @@ -293,7 +290,7 @@ VideoChannel* ChannelManager::CreateVideoChannel( absl::WrapUnique(media_channel), content_name, srtp_required, crypto_options, ssrc_generator); - video_channel->Init_w(rtp_transport, media_transport_config); + video_channel->Init_w(rtp_transport); VideoChannel* video_channel_ptr = video_channel.get(); video_channels_.push_back(std::move(video_channel)); @@ -355,7 +352,7 @@ RtpDataChannel* ChannelManager::CreateRtpDataChannel( crypto_options, ssrc_generator); // Media Transports are not supported with Rtp Data Channel. - data_channel->Init_w(rtp_transport, webrtc::MediaTransportConfig()); + data_channel->Init_w(rtp_transport); RtpDataChannel* data_channel_ptr = data_channel.get(); data_channels_.push_back(std::move(data_channel)); diff --git a/chromium/third_party/webrtc/pc/channel_manager.h b/chromium/third_party/webrtc/pc/channel_manager.h index 415e476a90a..8d5fc0aa5b9 100644 --- a/chromium/third_party/webrtc/pc/channel_manager.h +++ b/chromium/third_party/webrtc/pc/channel_manager.h @@ -19,7 +19,6 @@ #include "api/audio_options.h" #include "api/crypto/crypto_options.h" -#include "api/transport/media/media_transport_config.h" #include "call/call.h" #include "media/base/codec.h" #include "media/base/media_channel.h" @@ -101,7 +100,6 @@ class ChannelManager final { webrtc::Call* call, const cricket::MediaConfig& media_config, webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config, rtc::Thread* signaling_thread, const std::string& content_name, bool srtp_required, @@ -118,7 +116,6 @@ class ChannelManager final { webrtc::Call* call, const cricket::MediaConfig& media_config, webrtc::RtpTransportInternal* rtp_transport, - const webrtc::MediaTransportConfig& media_transport_config, rtc::Thread* signaling_thread, const std::string& content_name, bool srtp_required, diff --git a/chromium/third_party/webrtc/pc/channel_manager_unittest.cc b/chromium/third_party/webrtc/pc/channel_manager_unittest.cc index 6f3128ebde1..610d7979ab4 100644 --- a/chromium/third_party/webrtc/pc/channel_manager_unittest.cc +++ b/chromium/third_party/webrtc/pc/channel_manager_unittest.cc @@ -13,7 +13,6 @@ #include <memory> #include "api/rtc_error.h" -#include "api/transport/media/media_transport_config.h" #include "api/video/builtin_video_bitrate_allocator_factory.h" #include "media/base/fake_media_engine.h" #include "media/base/test_utils.h" @@ -73,20 +72,17 @@ class ChannelManagerTest : public ::testing::Test { return dtls_srtp_transport; } - void TestCreateDestroyChannels( - webrtc::RtpTransportInternal* rtp_transport, - webrtc::MediaTransportConfig media_transport_config) { + void TestCreateDestroyChannels(webrtc::RtpTransportInternal* rtp_transport) { cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel( &fake_call_, cricket::MediaConfig(), rtp_transport, - media_transport_config, rtc::Thread::Current(), cricket::CN_AUDIO, - kDefaultSrtpRequired, webrtc::CryptoOptions(), &ssrc_generator_, - AudioOptions()); + rtc::Thread::Current(), cricket::CN_AUDIO, kDefaultSrtpRequired, + webrtc::CryptoOptions(), &ssrc_generator_, AudioOptions()); EXPECT_TRUE(voice_channel != nullptr); cricket::VideoChannel* video_channel = cm_->CreateVideoChannel( &fake_call_, cricket::MediaConfig(), rtp_transport, - media_transport_config, rtc::Thread::Current(), cricket::CN_VIDEO, - kDefaultSrtpRequired, webrtc::CryptoOptions(), &ssrc_generator_, - VideoOptions(), video_bitrate_allocator_factory_.get()); + rtc::Thread::Current(), cricket::CN_VIDEO, kDefaultSrtpRequired, + webrtc::CryptoOptions(), &ssrc_generator_, VideoOptions(), + video_bitrate_allocator_factory_.get()); EXPECT_TRUE(video_channel != nullptr); cricket::RtpDataChannel* rtp_data_channel = cm_->CreateRtpDataChannel( cricket::MediaConfig(), rtp_transport, rtc::Thread::Current(), @@ -183,8 +179,7 @@ TEST_F(ChannelManagerTest, SetVideoRtxEnabled) { TEST_F(ChannelManagerTest, CreateDestroyChannels) { EXPECT_TRUE(cm_->Init()); auto rtp_transport = CreateDtlsSrtpTransport(); - TestCreateDestroyChannels(rtp_transport.get(), - webrtc::MediaTransportConfig()); + TestCreateDestroyChannels(rtp_transport.get()); } TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) { @@ -194,8 +189,7 @@ TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) { EXPECT_TRUE(cm_->set_network_thread(network_.get())); EXPECT_TRUE(cm_->Init()); auto rtp_transport = CreateDtlsSrtpTransport(); - TestCreateDestroyChannels(rtp_transport.get(), - webrtc::MediaTransportConfig()); + TestCreateDestroyChannels(rtp_transport.get()); } } // namespace cricket diff --git a/chromium/third_party/webrtc/pc/channel_unittest.cc b/chromium/third_party/webrtc/pc/channel_unittest.cc index a3fe3f68de4..479340c5202 100644 --- a/chromium/third_party/webrtc/pc/channel_unittest.cc +++ b/chromium/third_party/webrtc/pc/channel_unittest.cc @@ -17,7 +17,6 @@ #include "api/array_view.h" #include "api/audio_options.h" #include "api/rtp_parameters.h" -#include "api/transport/media/media_transport_config.h" #include "media/base/codec.h" #include "media/base/fake_media_engine.h" #include "media/base/fake_rtp.h" @@ -1431,7 +1430,7 @@ std::unique_ptr<cricket::VoiceChannel> ChannelTest<VoiceTraits>::CreateChannel( worker_thread, network_thread, signaling_thread, std::move(ch), cricket::CN_AUDIO, (flags & DTLS) != 0, webrtc::CryptoOptions(), &ssrc_generator_); - channel->Init_w(rtp_transport, webrtc::MediaTransportConfig()); + channel->Init_w(rtp_transport); return channel; } @@ -1514,7 +1513,7 @@ std::unique_ptr<cricket::VideoChannel> ChannelTest<VideoTraits>::CreateChannel( worker_thread, network_thread, signaling_thread, std::move(ch), cricket::CN_VIDEO, (flags & DTLS) != 0, webrtc::CryptoOptions(), &ssrc_generator_); - channel->Init_w(rtp_transport, webrtc::MediaTransportConfig()); + channel->Init_w(rtp_transport); return channel; } @@ -2301,7 +2300,7 @@ std::unique_ptr<cricket::RtpDataChannel> ChannelTest<DataTraits>::CreateChannel( worker_thread, network_thread, signaling_thread, std::move(ch), cricket::CN_DATA, (flags & DTLS) != 0, webrtc::CryptoOptions(), &ssrc_generator_); - channel->Init_w(rtp_transport, webrtc::MediaTransportConfig()); + channel->Init_w(rtp_transport); return channel; } diff --git a/chromium/third_party/webrtc/pc/data_channel.cc b/chromium/third_party/webrtc/pc/data_channel.cc index 4f871b4d504..ca6b6145cb1 100644 --- a/chromium/third_party/webrtc/pc/data_channel.cc +++ b/chromium/third_party/webrtc/pc/data_channel.cc @@ -14,6 +14,7 @@ #include <string> #include <utility> +#include "api/proxy.h" #include "media/sctp/sctp_transport_internal.h" #include "pc/sctp_utils.h" #include "rtc_base/checks.h" @@ -137,26 +138,75 @@ rtc::scoped_refptr<DataChannel> DataChannel::Create( DataChannelProviderInterface* provider, cricket::DataChannelType dct, const std::string& label, - const InternalDataChannelInit& config) { + const InternalDataChannelInit& config, + rtc::Thread* signaling_thread, + rtc::Thread* network_thread) { rtc::scoped_refptr<DataChannel> channel( - new rtc::RefCountedObject<DataChannel>(provider, dct, label)); - if (!channel->Init(config)) { - return NULL; + new rtc::RefCountedObject<DataChannel>(config, provider, dct, label, + signaling_thread, network_thread)); + if (!channel->Init()) { + return nullptr; } return channel; } +// Define proxy for DataChannelInterface. +BEGIN_SIGNALING_PROXY_MAP(DataChannel) +PROXY_SIGNALING_THREAD_DESTRUCTOR() +PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*) +PROXY_METHOD0(void, UnregisterObserver) +BYPASS_PROXY_CONSTMETHOD0(std::string, label) +BYPASS_PROXY_CONSTMETHOD0(bool, reliable) +BYPASS_PROXY_CONSTMETHOD0(bool, ordered) +BYPASS_PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime) +BYPASS_PROXY_CONSTMETHOD0(uint16_t, maxRetransmits) +BYPASS_PROXY_CONSTMETHOD0(absl::optional<int>, maxRetransmitsOpt) +BYPASS_PROXY_CONSTMETHOD0(absl::optional<int>, maxPacketLifeTime) +BYPASS_PROXY_CONSTMETHOD0(std::string, protocol) +BYPASS_PROXY_CONSTMETHOD0(bool, negotiated) +// Can't bypass the proxy since the id may change. +PROXY_CONSTMETHOD0(int, id) +BYPASS_PROXY_CONSTMETHOD0(Priority, priority) +PROXY_CONSTMETHOD0(DataState, state) +PROXY_CONSTMETHOD0(RTCError, error) +PROXY_CONSTMETHOD0(uint32_t, messages_sent) +PROXY_CONSTMETHOD0(uint64_t, bytes_sent) +PROXY_CONSTMETHOD0(uint32_t, messages_received) +PROXY_CONSTMETHOD0(uint64_t, bytes_received) +PROXY_CONSTMETHOD0(uint64_t, buffered_amount) +PROXY_METHOD0(void, Close) +// TODO(bugs.webrtc.org/11547): Change to run on the network thread. +PROXY_METHOD1(bool, Send, const DataBuffer&) +END_PROXY_MAP() + +// static +rtc::scoped_refptr<DataChannelInterface> DataChannel::CreateProxy( + rtc::scoped_refptr<DataChannel> channel) { + // TODO(bugs.webrtc.org/11547): incorporate the network thread in the proxy. + // Also, consider allowing the proxy object to own the reference (std::move). + // As is, the proxy has a raw pointer and no reference to the channel object + // and trusting that the lifetime management aligns with the + // sctp_data_channels_ array in DataChannelController. + return DataChannelProxy::Create(channel->signaling_thread_, channel.get()); +} + bool DataChannel::IsSctpLike(cricket::DataChannelType type) { return type == cricket::DCT_SCTP || type == cricket::DCT_MEDIA_TRANSPORT || type == cricket::DCT_DATA_CHANNEL_TRANSPORT || type == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP; } -DataChannel::DataChannel(DataChannelProviderInterface* provider, +DataChannel::DataChannel(const InternalDataChannelInit& config, + DataChannelProviderInterface* provider, cricket::DataChannelType dct, - const std::string& label) - : internal_id_(GenerateUniqueId()), + const std::string& label, + rtc::Thread* signaling_thread, + rtc::Thread* network_thread) + : signaling_thread_(signaling_thread), + network_thread_(network_thread), + internal_id_(GenerateUniqueId()), label_(label), + config_(config), observer_(nullptr), state_(kConnecting), messages_sent_(0), @@ -172,31 +222,33 @@ DataChannel::DataChannel(DataChannelProviderInterface* provider, receive_ssrc_set_(false), writable_(false), send_ssrc_(0), - receive_ssrc_(0) {} + receive_ssrc_(0) { + RTC_DCHECK_RUN_ON(signaling_thread_); +} -bool DataChannel::Init(const InternalDataChannelInit& config) { +bool DataChannel::Init() { + RTC_DCHECK_RUN_ON(signaling_thread_); if (data_channel_type_ == cricket::DCT_RTP) { - if (config.reliable || config.id != -1 || config.maxRetransmits || - config.maxRetransmitTime) { + if (config_.reliable || config_.id != -1 || config_.maxRetransmits || + config_.maxRetransmitTime) { RTC_LOG(LS_ERROR) << "Failed to initialize the RTP data channel due to " "invalid DataChannelInit."; return false; } handshake_state_ = kHandshakeReady; } else if (IsSctpLike(data_channel_type_)) { - if (config.id < -1 || - (config.maxRetransmits && *config.maxRetransmits < 0) || - (config.maxRetransmitTime && *config.maxRetransmitTime < 0)) { + if (config_.id < -1 || + (config_.maxRetransmits && *config_.maxRetransmits < 0) || + (config_.maxRetransmitTime && *config_.maxRetransmitTime < 0)) { RTC_LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to " "invalid DataChannelInit."; return false; } - if (config.maxRetransmits && config.maxRetransmitTime) { + if (config_.maxRetransmits && config_.maxRetransmitTime) { RTC_LOG(LS_ERROR) << "maxRetransmits and maxRetransmitTime should not be both set."; return false; } - config_ = config; switch (config_.open_handshake_role) { case webrtc::InternalDataChannelInit::kNone: // pre-negotiated @@ -228,18 +280,23 @@ bool DataChannel::Init(const InternalDataChannelInit& config) { return true; } -DataChannel::~DataChannel() {} +DataChannel::~DataChannel() { + RTC_DCHECK_RUN_ON(signaling_thread_); +} void DataChannel::RegisterObserver(DataChannelObserver* observer) { + RTC_DCHECK_RUN_ON(signaling_thread_); observer_ = observer; DeliverQueuedReceivedData(); } void DataChannel::UnregisterObserver() { - observer_ = NULL; + RTC_DCHECK_RUN_ON(signaling_thread_); + observer_ = nullptr; } bool DataChannel::reliable() const { + // May be called on any thread. if (data_channel_type_ == cricket::DCT_RTP) { return false; } else { @@ -248,10 +305,12 @@ bool DataChannel::reliable() const { } uint64_t DataChannel::buffered_amount() const { + RTC_DCHECK_RUN_ON(signaling_thread_); return buffered_amount_; } void DataChannel::Close() { + RTC_DCHECK_RUN_ON(signaling_thread_); if (state_ == kClosed) return; send_ssrc_ = 0; @@ -261,12 +320,42 @@ void DataChannel::Close() { UpdateState(); } +DataChannel::DataState DataChannel::state() const { + RTC_DCHECK_RUN_ON(signaling_thread_); + return state_; +} + RTCError DataChannel::error() const { + RTC_DCHECK_RUN_ON(signaling_thread_); return error_; } +uint32_t DataChannel::messages_sent() const { + RTC_DCHECK_RUN_ON(signaling_thread_); + return messages_sent_; +} + +uint64_t DataChannel::bytes_sent() const { + RTC_DCHECK_RUN_ON(signaling_thread_); + return bytes_sent_; +} + +uint32_t DataChannel::messages_received() const { + RTC_DCHECK_RUN_ON(signaling_thread_); + return messages_received_; +} + +uint64_t DataChannel::bytes_received() const { + RTC_DCHECK_RUN_ON(signaling_thread_); + return bytes_received_; +} + bool DataChannel::Send(const DataBuffer& buffer) { - buffered_amount_ += buffer.size(); + RTC_DCHECK_RUN_ON(signaling_thread_); + // TODO(bugs.webrtc.org/11547): Expect this method to be called on the network + // thread. Bring buffer management etc to the network thread and keep the + // operational state management on the signaling thread. + if (state_ != kOpen) { return false; } @@ -278,6 +367,8 @@ bool DataChannel::Send(const DataBuffer& buffer) { return true; } + buffered_amount_ += buffer.size(); + // If the queue is non-empty, we're waiting for SignalReadyToSend, // so just add to the end of the queue and keep waiting. if (!queued_send_data_.Empty()) { @@ -305,6 +396,7 @@ bool DataChannel::Send(const DataBuffer& buffer) { } void DataChannel::SetReceiveSsrc(uint32_t receive_ssrc) { + RTC_DCHECK_RUN_ON(signaling_thread_); RTC_DCHECK(data_channel_type_ == cricket::DCT_RTP); if (receive_ssrc_set_) { @@ -323,11 +415,12 @@ void DataChannel::SetSctpSid(int sid) { return; } - config_.id = sid; + const_cast<InternalDataChannelInit&>(config_).id = sid; provider_->AddSctpDataStream(sid); } void DataChannel::OnClosingProcedureStartedRemotely(int sid) { + RTC_DCHECK_RUN_ON(signaling_thread_); if (IsSctpLike(data_channel_type_) && sid == config_.id && state_ != kClosing && state_ != kClosed) { // Don't bother sending queued data since the side that initiated the @@ -344,6 +437,7 @@ void DataChannel::OnClosingProcedureStartedRemotely(int sid) { } void DataChannel::OnClosingProcedureComplete(int sid) { + RTC_DCHECK_RUN_ON(signaling_thread_); if (IsSctpLike(data_channel_type_) && sid == config_.id) { // If the closing procedure is complete, we should have finished sending // all pending data and transitioned to kClosing already. @@ -355,6 +449,7 @@ void DataChannel::OnClosingProcedureComplete(int sid) { } void DataChannel::OnTransportChannelCreated() { + RTC_DCHECK_RUN_ON(signaling_thread_); RTC_DCHECK(IsSctpLike(data_channel_type_)); if (!connected_to_provider_) { connected_to_provider_ = provider_->ConnectDataChannel(this); @@ -370,10 +465,18 @@ void DataChannel::OnTransportChannelClosed() { // The SctpTransport is unusable (for example, because the SCTP m= section // was rejected, or because the DTLS transport closed), so we need to close // abruptly. - // Note: this needs to differentiate between normal close and error close. - // https://w3c.github.io/webrtc-pc/#announcing-a-data-channel-as-closed - CloseAbruptlyWithError( - RTCError(RTCErrorType::NETWORK_ERROR, "Transport channel closed")); + RTCError error = RTCError(RTCErrorType::OPERATION_ERROR_WITH_DATA, + "Transport channel closed"); + error.set_error_detail(RTCErrorDetailType::SCTP_FAILURE); + CloseAbruptlyWithError(std::move(error)); +} + +DataChannel::Stats DataChannel::GetStats() const { + RTC_DCHECK_RUN_ON(signaling_thread_); + Stats stats{internal_id_, id(), label(), + protocol(), state(), messages_sent(), + messages_received(), bytes_sent(), bytes_received()}; + return stats; } // The remote peer request that this channel shall be closed. @@ -384,6 +487,7 @@ void DataChannel::RemotePeerRequestClose() { } void DataChannel::SetSendSsrc(uint32_t send_ssrc) { + RTC_DCHECK_RUN_ON(signaling_thread_); RTC_DCHECK(data_channel_type_ == cricket::DCT_RTP); if (send_ssrc_set_) { return; @@ -395,6 +499,7 @@ void DataChannel::SetSendSsrc(uint32_t send_ssrc) { void DataChannel::OnDataReceived(const cricket::ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& payload) { + RTC_DCHECK_RUN_ON(signaling_thread_); if (data_channel_type_ == cricket::DCT_RTP && params.ssrc != receive_ssrc_) { return; } @@ -461,6 +566,8 @@ void DataChannel::OnDataReceived(const cricket::ReceiveDataParams& params, } void DataChannel::OnChannelReady(bool writable) { + RTC_DCHECK_RUN_ON(signaling_thread_); + writable_ = writable; if (!writable) { return; @@ -472,6 +579,8 @@ void DataChannel::OnChannelReady(bool writable) { } void DataChannel::CloseAbruptlyWithError(RTCError error) { + RTC_DCHECK_RUN_ON(signaling_thread_); + if (state_ == kClosed) { return; } @@ -500,6 +609,7 @@ void DataChannel::CloseAbruptlyWithDataChannelFailure( } void DataChannel::UpdateState() { + RTC_DCHECK_RUN_ON(signaling_thread_); // UpdateState determines what to do from a few state variables. Include // all conditions required for each state transition here for // clarity. OnChannelReady(true) will send any queued data and then invoke @@ -567,6 +677,7 @@ void DataChannel::UpdateState() { } void DataChannel::SetState(DataState state) { + RTC_DCHECK_RUN_ON(signaling_thread_); if (state_ == state) { return; } @@ -583,6 +694,7 @@ void DataChannel::SetState(DataState state) { } void DataChannel::DisconnectFromProvider() { + RTC_DCHECK_RUN_ON(signaling_thread_); if (!connected_to_provider_) return; @@ -591,6 +703,7 @@ void DataChannel::DisconnectFromProvider() { } void DataChannel::DeliverQueuedReceivedData() { + RTC_DCHECK_RUN_ON(signaling_thread_); if (!observer_) { return; } @@ -604,6 +717,7 @@ void DataChannel::DeliverQueuedReceivedData() { } void DataChannel::SendQueuedDataMessages() { + RTC_DCHECK_RUN_ON(signaling_thread_); if (queued_send_data_.Empty()) { return; } @@ -622,6 +736,7 @@ void DataChannel::SendQueuedDataMessages() { bool DataChannel::SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked) { + RTC_DCHECK_RUN_ON(signaling_thread_); cricket::SendDataParams send_params; if (IsSctpLike(data_channel_type_)) { @@ -680,6 +795,7 @@ bool DataChannel::SendDataMessage(const DataBuffer& buffer, } bool DataChannel::QueueSendDataMessage(const DataBuffer& buffer) { + RTC_DCHECK_RUN_ON(signaling_thread_); size_t start_buffered_amount = queued_send_data_.byte_count(); if (start_buffered_amount + buffer.size() > kMaxQueuedSendDataBytes) { RTC_LOG(LS_ERROR) << "Can't buffer any more data for the data channel."; @@ -690,6 +806,7 @@ bool DataChannel::QueueSendDataMessage(const DataBuffer& buffer) { } void DataChannel::SendQueuedControlMessages() { + RTC_DCHECK_RUN_ON(signaling_thread_); PacketQueue control_packets; control_packets.Swap(&queued_control_data_); @@ -700,10 +817,12 @@ void DataChannel::SendQueuedControlMessages() { } void DataChannel::QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer) { + RTC_DCHECK_RUN_ON(signaling_thread_); queued_control_data_.PushBack(std::make_unique<DataBuffer>(buffer, true)); } bool DataChannel::SendControlMessage(const rtc::CopyOnWriteBuffer& buffer) { + RTC_DCHECK_RUN_ON(signaling_thread_); bool is_open_message = handshake_state_ == kHandshakeShouldSendOpen; RTC_DCHECK(IsSctpLike(data_channel_type_)); diff --git a/chromium/third_party/webrtc/pc/data_channel.h b/chromium/third_party/webrtc/pc/data_channel.h index c1de7c7a7ae..09b6692f02d 100644 --- a/chromium/third_party/webrtc/pc/data_channel.h +++ b/chromium/third_party/webrtc/pc/data_channel.h @@ -17,8 +17,9 @@ #include <string> #include "api/data_channel_interface.h" -#include "api/proxy.h" +#include "api/priority.h" #include "api/scoped_refptr.h" +#include "api/transport/data_channel_transport_interface.h" #include "media/base/media_channel.h" #include "pc/channel.h" #include "rtc_base/async_invoker.h" @@ -53,6 +54,8 @@ class DataChannelProviderInterface { virtual ~DataChannelProviderInterface() {} }; +// TODO(tommi): Change to not inherit from DataChannelInit but to have it as +// a const member. Block access to the 'id' member since it cannot be const. struct InternalDataChannelInit : public DataChannelInit { enum OpenHandshakeRole { kOpener, kAcker, kNone }; // The default role is kOpener because the default |negotiated| is false. @@ -83,7 +86,7 @@ class SctpSidAllocator { std::set<int> used_sids_; }; -// DataChannel is a an implementation of the DataChannelInterface based on +// DataChannel is an implementation of the DataChannelInterface based on // libjingle's data engine. It provides an implementation of unreliable or // reliabledata channels. Currently this class is specifically designed to use // both RtpDataChannel and SctpTransport. @@ -110,48 +113,72 @@ class SctpSidAllocator { // callback and transition to kClosed. class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { public: + struct Stats { + int internal_id; + int id; + std::string label; + std::string protocol; + DataState state; + uint32_t messages_sent; + uint32_t messages_received; + uint64_t bytes_sent; + uint64_t bytes_received; + }; + static rtc::scoped_refptr<DataChannel> Create( DataChannelProviderInterface* provider, cricket::DataChannelType dct, const std::string& label, - const InternalDataChannelInit& config); + const InternalDataChannelInit& config, + rtc::Thread* signaling_thread, + rtc::Thread* network_thread); + + // Instantiates an API proxy for a DataChannel instance that will be handed + // out to external callers. + static rtc::scoped_refptr<DataChannelInterface> CreateProxy( + rtc::scoped_refptr<DataChannel> channel); static bool IsSctpLike(cricket::DataChannelType type); - virtual void RegisterObserver(DataChannelObserver* observer); - virtual void UnregisterObserver(); + void RegisterObserver(DataChannelObserver* observer) override; + void UnregisterObserver() override; - virtual std::string label() const { return label_; } - virtual bool reliable() const; - virtual bool ordered() const { return config_.ordered; } + std::string label() const override { return label_; } + bool reliable() const override; + bool ordered() const override { return config_.ordered; } // Backwards compatible accessors - virtual uint16_t maxRetransmitTime() const { + uint16_t maxRetransmitTime() const override { return config_.maxRetransmitTime ? *config_.maxRetransmitTime : static_cast<uint16_t>(-1); } - virtual uint16_t maxRetransmits() const { + uint16_t maxRetransmits() const override { return config_.maxRetransmits ? *config_.maxRetransmits : static_cast<uint16_t>(-1); } - virtual absl::optional<int> maxPacketLifeTime() const { + absl::optional<int> maxPacketLifeTime() const override { return config_.maxRetransmitTime; } - virtual absl::optional<int> maxRetransmitsOpt() const { + absl::optional<int> maxRetransmitsOpt() const override { return config_.maxRetransmits; } - virtual std::string protocol() const { return config_.protocol; } - virtual bool negotiated() const { return config_.negotiated; } - virtual int id() const { return config_.id; } + std::string protocol() const override { return config_.protocol; } + bool negotiated() const override { return config_.negotiated; } + int id() const override { return config_.id; } + Priority priority() const override { + return config_.priority ? *config_.priority : Priority::kLow; + } + virtual int internal_id() const { return internal_id_; } - virtual uint64_t buffered_amount() const; - virtual void Close(); - virtual DataState state() const { return state_; } - virtual RTCError error() const; - virtual uint32_t messages_sent() const { return messages_sent_; } - virtual uint64_t bytes_sent() const { return bytes_sent_; } - virtual uint32_t messages_received() const { return messages_received_; } - virtual uint64_t bytes_received() const { return bytes_received_; } - virtual bool Send(const DataBuffer& buffer); + + uint64_t buffered_amount() const override; + void Close() override; + DataState state() const override; + RTCError error() const override; + uint32_t messages_sent() const override; + uint64_t bytes_sent() const override; + uint32_t messages_received() const override; + uint64_t bytes_received() const override; + bool Send(const DataBuffer& buffer) override; // Close immediately, ignoring any queued data or closing procedure. // This is called for RTP data channels when SDP indicates a channel should @@ -195,6 +222,8 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { // to kClosed. void OnTransportChannelClosed(); + Stats GetStats() const; + /******************************************* * The following methods are for RTP only. * *******************************************/ @@ -225,10 +254,13 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { static void ResetInternalIdAllocatorForTesting(int new_value); protected: - DataChannel(DataChannelProviderInterface* client, + DataChannel(const InternalDataChannelInit& config, + DataChannelProviderInterface* client, cricket::DataChannelType dct, - const std::string& label); - virtual ~DataChannel(); + const std::string& label, + rtc::Thread* signaling_thread, + rtc::Thread* network_thread); + ~DataChannel() override; private: // A packet queue which tracks the total queued bytes. Queued packets are @@ -262,7 +294,7 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { kHandshakeReady }; - bool Init(const InternalDataChannelInit& config); + bool Init(); void UpdateState(); void SetState(DataState state); void DisconnectFromProvider(); @@ -277,64 +309,40 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> { void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer); bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer); + rtc::Thread* const signaling_thread_; + rtc::Thread* const network_thread_; const int internal_id_; - std::string label_; - InternalDataChannelInit config_; - DataChannelObserver* observer_; - DataState state_; - RTCError error_; - uint32_t messages_sent_; - uint64_t bytes_sent_; - uint32_t messages_received_; - uint64_t bytes_received_; + const std::string label_; + const InternalDataChannelInit config_; + DataChannelObserver* observer_ RTC_GUARDED_BY(signaling_thread_); + DataState state_ RTC_GUARDED_BY(signaling_thread_); + RTCError error_ RTC_GUARDED_BY(signaling_thread_); + uint32_t messages_sent_ RTC_GUARDED_BY(signaling_thread_); + uint64_t bytes_sent_ RTC_GUARDED_BY(signaling_thread_); + uint32_t messages_received_ RTC_GUARDED_BY(signaling_thread_); + uint64_t bytes_received_ RTC_GUARDED_BY(signaling_thread_); // Number of bytes of data that have been queued using Send(). Increased // before each transport send and decreased after each successful send. - uint64_t buffered_amount_; - cricket::DataChannelType data_channel_type_; - DataChannelProviderInterface* provider_; - HandshakeState handshake_state_; - bool connected_to_provider_; - bool send_ssrc_set_; - bool receive_ssrc_set_; - bool writable_; + uint64_t buffered_amount_ RTC_GUARDED_BY(signaling_thread_); + const cricket::DataChannelType data_channel_type_; + DataChannelProviderInterface* const provider_; + HandshakeState handshake_state_ RTC_GUARDED_BY(signaling_thread_); + bool connected_to_provider_ RTC_GUARDED_BY(signaling_thread_); + bool send_ssrc_set_ RTC_GUARDED_BY(signaling_thread_); + bool receive_ssrc_set_ RTC_GUARDED_BY(signaling_thread_); + bool writable_ RTC_GUARDED_BY(signaling_thread_); // Did we already start the graceful SCTP closing procedure? - bool started_closing_procedure_ = false; - uint32_t send_ssrc_; - uint32_t receive_ssrc_; + bool started_closing_procedure_ RTC_GUARDED_BY(signaling_thread_) = false; + uint32_t send_ssrc_ RTC_GUARDED_BY(signaling_thread_); + uint32_t receive_ssrc_ RTC_GUARDED_BY(signaling_thread_); // Control messages that always have to get sent out before any queued // data. - PacketQueue queued_control_data_; - PacketQueue queued_received_data_; - PacketQueue queued_send_data_; - rtc::AsyncInvoker invoker_; + PacketQueue queued_control_data_ RTC_GUARDED_BY(signaling_thread_); + PacketQueue queued_received_data_ RTC_GUARDED_BY(signaling_thread_); + PacketQueue queued_send_data_ RTC_GUARDED_BY(signaling_thread_); + rtc::AsyncInvoker invoker_ RTC_GUARDED_BY(signaling_thread_); }; -// Define proxy for DataChannelInterface. -BEGIN_SIGNALING_PROXY_MAP(DataChannel) -PROXY_SIGNALING_THREAD_DESTRUCTOR() -PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*) -PROXY_METHOD0(void, UnregisterObserver) -PROXY_CONSTMETHOD0(std::string, label) -PROXY_CONSTMETHOD0(bool, reliable) -PROXY_CONSTMETHOD0(bool, ordered) -PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime) -PROXY_CONSTMETHOD0(uint16_t, maxRetransmits) -PROXY_CONSTMETHOD0(absl::optional<int>, maxRetransmitsOpt) -PROXY_CONSTMETHOD0(absl::optional<int>, maxPacketLifeTime) -PROXY_CONSTMETHOD0(std::string, protocol) -PROXY_CONSTMETHOD0(bool, negotiated) -PROXY_CONSTMETHOD0(int, id) -PROXY_CONSTMETHOD0(DataState, state) -PROXY_CONSTMETHOD0(RTCError, error) -PROXY_CONSTMETHOD0(uint32_t, messages_sent) -PROXY_CONSTMETHOD0(uint64_t, bytes_sent) -PROXY_CONSTMETHOD0(uint32_t, messages_received) -PROXY_CONSTMETHOD0(uint64_t, bytes_received) -PROXY_CONSTMETHOD0(uint64_t, buffered_amount) -PROXY_METHOD0(void, Close) -PROXY_METHOD1(bool, Send, const DataBuffer&) -END_PROXY_MAP() - } // namespace webrtc #endif // PC_DATA_CHANNEL_H_ diff --git a/chromium/third_party/webrtc/pc/data_channel_controller.cc b/chromium/third_party/webrtc/pc/data_channel_controller.cc index e9ea742c44f..710ca8e5317 100644 --- a/chromium/third_party/webrtc/pc/data_channel_controller.cc +++ b/chromium/third_party/webrtc/pc/data_channel_controller.cc @@ -25,37 +25,10 @@ bool DataChannelController::HasDataChannels() const { bool DataChannelController::SendData(const cricket::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, cricket::SendDataResult* result) { - // RTC_DCHECK_RUN_ON(signaling_thread()); - if (data_channel_transport()) { - SendDataParams send_params; - send_params.type = ToWebrtcDataMessageType(params.type); - send_params.ordered = params.ordered; - if (params.max_rtx_count >= 0) { - send_params.max_rtx_count = params.max_rtx_count; - } else if (params.max_rtx_ms >= 0) { - send_params.max_rtx_ms = params.max_rtx_ms; - } - - RTCError error = network_thread()->Invoke<RTCError>( - RTC_FROM_HERE, [this, params, send_params, payload] { - return data_channel_transport()->SendData(params.sid, send_params, - payload); - }); - - if (error.ok()) { - *result = cricket::SendDataResult::SDR_SUCCESS; - return true; - } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) { - // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked. - // TODO(mellem): Stop using RTCError here and get rid of the mapping. - *result = cricket::SendDataResult::SDR_BLOCK; - return false; - } - *result = cricket::SendDataResult::SDR_ERROR; - return false; - } else if (rtp_data_channel()) { + if (data_channel_transport()) + return DataChannelSendData(params, payload, result); + if (rtp_data_channel()) return rtp_data_channel()->SendData(params, payload, result); - } RTC_LOG(LS_ERROR) << "SendData called before transport is ready"; return false; } @@ -146,6 +119,14 @@ void DataChannelController::OnDataReceived( data_channel_transport_invoker_->AsyncInvoke<void>( RTC_FROM_HERE, signaling_thread(), [this, params, buffer] { RTC_DCHECK_RUN_ON(signaling_thread()); + // TODO(bugs.webrtc.org/11547): The data being received should be + // delivered on the network thread. The way HandleOpenMessage_s works + // right now is that it's called for all types of buffers and operates + // as a selector function. Change this so that it's only called for + // buffers that it should be able to handle. Once we do that, we can + // deliver all other buffers on the network thread (change + // SignalDataChannelTransportReceivedData_s to + // SignalDataChannelTransportReceivedData_n). if (!HandleOpenMessage_s(params, buffer)) { SignalDataChannelTransportReceivedData_s(params, buffer); } @@ -193,6 +174,11 @@ void DataChannelController::OnTransportClosed() { void DataChannelController::SetupDataChannelTransport_n() { RTC_DCHECK_RUN_ON(network_thread()); data_channel_transport_invoker_ = std::make_unique<rtc::AsyncInvoker>(); + + // There's a new data channel transport. This needs to be signaled to the + // |sctp_data_channels_| so that they can reopen and reconnect. This is + // necessary when bundling is applied. + NotifyDataChannelsOfTransportCreated(); } void DataChannelController::TeardownDataChannelTransport_n() { @@ -219,17 +205,21 @@ void DataChannelController::OnTransportChanged( // There's a new data channel transport. This needs to be signaled to the // |sctp_data_channels_| so that they can reopen and reconnect. This is // necessary when bundling is applied. - data_channel_transport_invoker_->AsyncInvoke<void>( - RTC_FROM_HERE, signaling_thread(), [this] { - RTC_DCHECK_RUN_ON(signaling_thread()); - for (const auto& channel : sctp_data_channels_) { - channel->OnTransportChannelCreated(); - } - }); + NotifyDataChannelsOfTransportCreated(); } } } +std::vector<DataChannel::Stats> DataChannelController::GetDataChannelStats() + const { + RTC_DCHECK_RUN_ON(signaling_thread()); + std::vector<DataChannel::Stats> stats; + stats.reserve(sctp_data_channels_.size()); + for (const auto& channel : sctp_data_channels_) + stats.push_back(channel->GetStats()); + return stats; +} + bool DataChannelController::HandleOpenMessage_s( const cricket::ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) { @@ -262,7 +252,7 @@ void DataChannelController::OnDataChannelOpenMessage( } rtc::scoped_refptr<DataChannelInterface> proxy_channel = - DataChannelProxy::Create(signaling_thread(), channel); + DataChannel::CreateProxy(std::move(channel)); pc_->Observer()->OnDataChannel(std::move(proxy_channel)); pc_->NoteDataAddedEvent(); } @@ -299,7 +289,8 @@ DataChannelController::InternalCreateDataChannel( } rtc::scoped_refptr<DataChannel> channel( - DataChannel::Create(this, data_channel_type(), label, new_config)); + DataChannel::Create(this, data_channel_type(), label, new_config, + signaling_thread(), network_thread())); if (!channel) { sid_allocator_.ReleaseSid(new_config.id); return nullptr; @@ -424,9 +415,10 @@ void DataChannelController::UpdateLocalRtpDataChannels( void DataChannelController::UpdateRemoteRtpDataChannels( const cricket::StreamParamsVec& streams) { + RTC_DCHECK_RUN_ON(signaling_thread()); + std::vector<std::string> existing_channels; - RTC_DCHECK_RUN_ON(signaling_thread()); // Find new and active data channels. for (const cricket::StreamParams& params : streams) { // The data channel label is either the mslabel or the SSRC if the mslabel @@ -447,6 +439,38 @@ void DataChannelController::UpdateRemoteRtpDataChannels( UpdateClosingRtpDataChannels(existing_channels, false); } +cricket::DataChannelType DataChannelController::data_channel_type() const { + // TODO(bugs.webrtc.org/9987): Should be restricted to the signaling thread. + // RTC_DCHECK_RUN_ON(signaling_thread()); + return data_channel_type_; +} + +void DataChannelController::set_data_channel_type( + cricket::DataChannelType type) { + RTC_DCHECK_RUN_ON(signaling_thread()); + data_channel_type_ = type; +} + +DataChannelTransportInterface* DataChannelController::data_channel_transport() + const { + // TODO(bugs.webrtc.org/11547): Only allow this accessor to be called on the + // network thread. + // RTC_DCHECK_RUN_ON(network_thread()); + return data_channel_transport_; +} + +void DataChannelController::set_data_channel_transport( + DataChannelTransportInterface* transport) { + RTC_DCHECK_RUN_ON(network_thread()); + data_channel_transport_ = transport; +} + +const std::map<std::string, rtc::scoped_refptr<DataChannel>>* +DataChannelController::rtp_data_channels() const { + RTC_DCHECK_RUN_ON(signaling_thread()); + return &rtp_data_channels_; +} + void DataChannelController::UpdateClosingRtpDataChannels( const std::vector<std::string>& active_channels, bool is_local_update) { @@ -484,10 +508,59 @@ void DataChannelController::CreateRemoteRtpDataChannel(const std::string& label, } channel->SetReceiveSsrc(remote_ssrc); rtc::scoped_refptr<DataChannelInterface> proxy_channel = - DataChannelProxy::Create(signaling_thread(), channel); + DataChannel::CreateProxy(std::move(channel)); pc_->Observer()->OnDataChannel(std::move(proxy_channel)); } +bool DataChannelController::DataChannelSendData( + const cricket::SendDataParams& params, + const rtc::CopyOnWriteBuffer& payload, + cricket::SendDataResult* result) { + // TODO(bugs.webrtc.org/11547): Expect method to be called on the network + // thread instead. Remove the Invoke() below and move assocated state to + // the network thread. + RTC_DCHECK_RUN_ON(signaling_thread()); + RTC_DCHECK(data_channel_transport()); + + SendDataParams send_params; + send_params.type = ToWebrtcDataMessageType(params.type); + send_params.ordered = params.ordered; + if (params.max_rtx_count >= 0) { + send_params.max_rtx_count = params.max_rtx_count; + } else if (params.max_rtx_ms >= 0) { + send_params.max_rtx_ms = params.max_rtx_ms; + } + + RTCError error = network_thread()->Invoke<RTCError>( + RTC_FROM_HERE, [this, params, send_params, payload] { + return data_channel_transport()->SendData(params.sid, send_params, + payload); + }); + + if (error.ok()) { + *result = cricket::SendDataResult::SDR_SUCCESS; + return true; + } else if (error.type() == RTCErrorType::RESOURCE_EXHAUSTED) { + // SCTP transport uses RESOURCE_EXHAUSTED when it's blocked. + // TODO(mellem): Stop using RTCError here and get rid of the mapping. + *result = cricket::SendDataResult::SDR_BLOCK; + return false; + } + *result = cricket::SendDataResult::SDR_ERROR; + return false; +} + +void DataChannelController::NotifyDataChannelsOfTransportCreated() { + RTC_DCHECK_RUN_ON(network_thread()); + data_channel_transport_invoker_->AsyncInvoke<void>( + RTC_FROM_HERE, signaling_thread(), [this] { + RTC_DCHECK_RUN_ON(signaling_thread()); + for (const auto& channel : sctp_data_channels_) { + channel->OnTransportChannelCreated(); + } + }); +} + rtc::Thread* DataChannelController::network_thread() const { return pc_->network_thread(); } diff --git a/chromium/third_party/webrtc/pc/data_channel_controller.h b/chromium/third_party/webrtc/pc/data_channel_controller.h index 60bcbb32a87..c3e64aba953 100644 --- a/chromium/third_party/webrtc/pc/data_channel_controller.h +++ b/chromium/third_party/webrtc/pc/data_channel_controller.h @@ -64,6 +64,9 @@ class DataChannelController : public DataChannelProviderInterface, void OnTransportChanged( DataChannelTransportInterface* data_channel_transport); + // Called from PeerConnection::GetDataChannelStats on the signaling thread. + std::vector<DataChannel::Stats> GetDataChannelStats() const; + // Creates channel and adds it to the collection of DataChannels that will // be offered in a SessionDescription. rtc::scoped_refptr<DataChannel> InternalCreateDataChannel( @@ -89,34 +92,18 @@ class DataChannelController : public DataChannelProviderInterface, void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams); // Accessors - cricket::DataChannelType data_channel_type() const { - return data_channel_type_; - } - void set_data_channel_type(cricket::DataChannelType type) { - data_channel_type_ = type; - } + cricket::DataChannelType data_channel_type() const; + void set_data_channel_type(cricket::DataChannelType type); cricket::RtpDataChannel* rtp_data_channel() const { return rtp_data_channel_; } void set_rtp_data_channel(cricket::RtpDataChannel* channel) { rtp_data_channel_ = channel; } - DataChannelTransportInterface* data_channel_transport() const { - return data_channel_transport_; - } - void set_data_channel_transport(DataChannelTransportInterface* transport) { - data_channel_transport_ = transport; - } + DataChannelTransportInterface* data_channel_transport() const; + void set_data_channel_transport(DataChannelTransportInterface* transport); const std::map<std::string, rtc::scoped_refptr<DataChannel>>* - rtp_data_channels() const { - RTC_DCHECK_RUN_ON(signaling_thread()); - return &rtp_data_channels_; - } - const std::vector<rtc::scoped_refptr<DataChannel>>* sctp_data_channels() - const { - RTC_DCHECK_RUN_ON(signaling_thread()); - return &sctp_data_channels_; - } + rtp_data_channels() const; sigslot::signal1<DataChannel*>& SignalDataChannelCreated() { RTC_DCHECK_RUN_ON(signaling_thread()); @@ -146,6 +133,15 @@ class DataChannelController : public DataChannelProviderInterface, const std::vector<std::string>& active_channels, bool is_local_update) RTC_RUN_ON(signaling_thread()); + // Called from SendData when data_channel_transport() is true. + bool DataChannelSendData(const cricket::SendDataParams& params, + const rtc::CopyOnWriteBuffer& payload, + cricket::SendDataResult* result); + + // Called when all data channels need to be notified of a transport channel + // (calls OnTransportChannelCreated on the signaling thread). + void NotifyDataChannelsOfTransportCreated(); + rtc::Thread* network_thread() const; rtc::Thread* signaling_thread() const; @@ -189,6 +185,8 @@ class DataChannelController : public DataChannelProviderInterface, // Signals from |data_channel_transport_|. These are invoked on the // signaling thread. + // TODO(bugs.webrtc.org/11547): These '_s' signals likely all belong on the + // network thread. sigslot::signal1<bool> SignalDataChannelTransportWritable_s RTC_GUARDED_BY(signaling_thread()); sigslot::signal2<const cricket::ReceiveDataParams&, diff --git a/chromium/third_party/webrtc/pc/data_channel_unittest.cc b/chromium/third_party/webrtc/pc/data_channel_unittest.cc index 6bb8f7e5c70..11dfcc4aeed 100644 --- a/chromium/third_party/webrtc/pc/data_channel_unittest.cc +++ b/chromium/third_party/webrtc/pc/data_channel_unittest.cc @@ -64,6 +64,7 @@ class FakeDataChannelObserver : public webrtc::DataChannelObserver { // TODO(deadbeef): The fact that these tests use a fake provider makes them not // too valuable. Should rewrite using the // peerconnection_datachannel_unittest.cc infrastructure. +// TODO(bugs.webrtc.org/11547): Incorporate a dedicated network thread. class SctpDataChannelTest : public ::testing::Test { protected: SctpDataChannelTest() @@ -71,7 +72,9 @@ class SctpDataChannelTest : public ::testing::Test { webrtc_data_channel_(DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test", - init_)) {} + init_, + rtc::Thread::Current(), + rtc::Thread::Current())) {} void SetChannelReady() { provider_->set_transport_available(true); @@ -111,7 +114,8 @@ class StateSignalsListener : public sigslot::has_slots<> { TEST_F(SctpDataChannelTest, ConnectedToTransportOnCreated) { provider_->set_transport_available(true); rtc::scoped_refptr<DataChannel> dc = - DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init_); + DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init_, + rtc::Thread::Current(), rtc::Thread::Current()); EXPECT_TRUE(provider_->IsConnected(dc.get())); // The sid is not set yet, so it should not have added the streams. @@ -305,7 +309,8 @@ TEST_F(SctpDataChannelTest, LateCreatedChannelTransitionToOpen) { webrtc::InternalDataChannelInit init; init.id = 1; rtc::scoped_refptr<DataChannel> dc = - DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init); + DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init, + rtc::Thread::Current(), rtc::Thread::Current()); EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, dc->state()); EXPECT_TRUE_WAIT(webrtc::DataChannelInterface::kOpen == dc->state(), 1000); } @@ -318,7 +323,8 @@ TEST_F(SctpDataChannelTest, SendUnorderedAfterReceivesOpenAck) { init.id = 1; init.ordered = false; rtc::scoped_refptr<DataChannel> dc = - DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init); + DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init, + rtc::Thread::Current(), rtc::Thread::Current()); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000); @@ -348,7 +354,8 @@ TEST_F(SctpDataChannelTest, SendUnorderedAfterReceiveData) { init.id = 1; init.ordered = false; rtc::scoped_refptr<DataChannel> dc = - DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init); + DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", init, + rtc::Thread::Current(), rtc::Thread::Current()); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000); @@ -449,7 +456,8 @@ TEST_F(SctpDataChannelTest, NoMsgSentIfNegotiatedAndNotFromOpenMsg) { SetChannelReady(); rtc::scoped_refptr<DataChannel> dc = - DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", config); + DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", config, + rtc::Thread::Current(), rtc::Thread::Current()); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000); EXPECT_EQ(0U, provider_->last_send_data_params().ssrc); @@ -512,7 +520,8 @@ TEST_F(SctpDataChannelTest, OpenAckSentIfCreatedFromOpenMessage) { SetChannelReady(); rtc::scoped_refptr<DataChannel> dc = - DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", config); + DataChannel::Create(provider_.get(), cricket::DCT_SCTP, "test1", config, + rtc::Thread::Current(), rtc::Thread::Current()); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000); @@ -630,9 +639,9 @@ TEST_F(SctpDataChannelTest, TransportDestroyedWhileDataBuffered) { EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, webrtc_data_channel_->state(), kDefaultTimeout); EXPECT_FALSE(webrtc_data_channel_->error().ok()); - EXPECT_EQ(webrtc::RTCErrorType::NETWORK_ERROR, + EXPECT_EQ(webrtc::RTCErrorType::OPERATION_ERROR_WITH_DATA, webrtc_data_channel_->error().type()); - EXPECT_EQ(webrtc::RTCErrorDetailType::NONE, + EXPECT_EQ(webrtc::RTCErrorDetailType::SCTP_FAILURE, webrtc_data_channel_->error().error_detail()); } diff --git a/chromium/third_party/webrtc/pc/datagram_rtp_transport.cc b/chromium/third_party/webrtc/pc/datagram_rtp_transport.cc deleted file mode 100644 index ad1e6dc995b..00000000000 --- a/chromium/third_party/webrtc/pc/datagram_rtp_transport.cc +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright 2018 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "pc/datagram_rtp_transport.h" - -#include <algorithm> -#include <memory> -#include <utility> - -#include "absl/memory/memory.h" -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" -#include "api/array_view.h" -#include "api/rtc_error.h" -#include "media/base/rtp_utils.h" -#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" -#include "modules/rtp_rtcp/source/rtp_packet.h" -#include "modules/rtp_rtcp/source/rtp_packet_received.h" -#include "p2p/base/dtls_transport_internal.h" -#include "p2p/base/packet_transport_internal.h" -#include "rtc_base/buffer.h" -#include "rtc_base/checks.h" -#include "rtc_base/dscp.h" -#include "rtc_base/logging.h" -#include "rtc_base/rtc_certificate.h" -#include "rtc_base/ssl_stream_adapter.h" -#include "rtc_base/stream.h" -#include "rtc_base/thread.h" -#include "system_wrappers/include/field_trial.h" - -namespace webrtc { - -namespace { - -// Field trials. -// Disable datagram to RTCP feedback translation and enable RTCP feedback loop -// on top of datagram feedback loop. Note that two -// feedback loops add unneccesary overhead, so it's preferable to use feedback -// loop provided by datagram transport and convert datagram ACKs to RTCP ACKs, -// but enabling RTCP feedback loop may be useful in tests and experiments. -const char kDisableDatagramToRtcpFeebackTranslationFieldTrial[] = - "WebRTC-kDisableDatagramToRtcpFeebackTranslation"; - -} // namespace - -// Maximum packet size of RTCP feedback packet for allocation. We re-create RTCP -// feedback packets when we get ACK notifications from datagram transport. Our -// rtcp feedback packets contain only 1 ACK, so they are much smaller than 1250. -constexpr size_t kMaxRtcpFeedbackPacketSize = 1250; - -DatagramRtpTransport::DatagramRtpTransport( - const std::vector<RtpExtension>& rtp_header_extensions, - cricket::IceTransportInternal* ice_transport, - DatagramTransportInterface* datagram_transport) - : ice_transport_(ice_transport), - datagram_transport_(datagram_transport), - disable_datagram_to_rtcp_feeback_translation_(field_trial::IsEnabled( - kDisableDatagramToRtcpFeebackTranslationFieldTrial)) { - // Save extension map for parsing RTP packets (we only need transport - // sequence numbers). - const RtpExtension* transport_sequence_number_extension = - RtpExtension::FindHeaderExtensionByUri(rtp_header_extensions, - TransportSequenceNumber::kUri); - - if (transport_sequence_number_extension != nullptr) { - rtp_header_extension_map_.Register<TransportSequenceNumber>( - transport_sequence_number_extension->id); - } else { - RTC_LOG(LS_ERROR) << "Transport sequence numbers are not supported in " - "datagram transport connection"; - } - - RTC_DCHECK(ice_transport_); - RTC_DCHECK(datagram_transport_); - - ice_transport_->SignalNetworkRouteChanged.connect( - this, &DatagramRtpTransport::OnNetworkRouteChanged); - // Subscribe to DatagramTransport to read incoming packets. - datagram_transport_->SetDatagramSink(this); - datagram_transport_->SetTransportStateCallback(this); -} - -DatagramRtpTransport::~DatagramRtpTransport() { - // Unsubscribe from DatagramTransport sinks. - datagram_transport_->SetDatagramSink(nullptr); - datagram_transport_->SetTransportStateCallback(nullptr); -} - -bool DatagramRtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet, - const rtc::PacketOptions& options, - int flags) { - RTC_DCHECK_RUN_ON(&thread_checker_); - - // Assign and increment datagram_id. - const DatagramId datagram_id = current_datagram_id_++; - - // Send as is (without extracting transport sequence number) for - // RTP packets if we are not doing datagram => RTCP feedback translation. - if (disable_datagram_to_rtcp_feeback_translation_) { - // Even if we are not extracting transport sequence number we need to - // propagate "Sent" notification for both RTP and RTCP packets. For this - // reason we need save options.packet_id in packet map. - sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id); - - return SendDatagram(*packet, datagram_id); - } - - // Parse RTP packet. - RtpPacket rtp_packet(&rtp_header_extension_map_); - // TODO(mellem): Verify that this doesn't mangle something (it shouldn't). - if (!rtp_packet.Parse(*packet)) { - RTC_NOTREACHED() << "Failed to parse outgoing RtpPacket, len=" - << packet->size() - << ", options.packet_id=" << options.packet_id; - return -1; - } - - // Try to get transport sequence number. - uint16_t transport_senquence_number; - if (!rtp_packet.GetExtension<TransportSequenceNumber>( - &transport_senquence_number)) { - // Save packet info without transport sequence number. - sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id); - - RTC_LOG(LS_VERBOSE) - << "Sending rtp packet without transport sequence number, packet=" - << rtp_packet.ToString(); - - return SendDatagram(*packet, datagram_id); - } - - // Save packet info with sequence number and ssrc so we could reconstruct - // RTCP feedback packet when we receive datagram ACK. - sent_rtp_packet_map_[datagram_id] = SentPacketInfo( - options.packet_id, rtp_packet.Ssrc(), transport_senquence_number); - - // Since datagram transport provides feedback and timestamps, we do not need - // to send transport sequence number, so we remove it from RTP packet. Later - // when we get Ack for sent datagram, we will re-create RTCP feedback packet. - if (!rtp_packet.RemoveExtension(TransportSequenceNumber::kId)) { - RTC_NOTREACHED() << "Failed to remove transport sequence number, packet=" - << rtp_packet.ToString(); - return -1; - } - - RTC_LOG(LS_VERBOSE) << "Removed transport_senquence_number=" - << transport_senquence_number - << " from packet=" << rtp_packet.ToString() - << ", saved bytes=" << packet->size() - rtp_packet.size(); - - return SendDatagram( - rtc::ArrayView<const uint8_t>(rtp_packet.data(), rtp_packet.size()), - datagram_id); -} - -bool DatagramRtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet, - const rtc::PacketOptions& options, - int flags) { - RTC_DCHECK_RUN_ON(&thread_checker_); - - // Assign and increment datagram_id. - const DatagramId datagram_id = current_datagram_id_++; - - // Even if we are not extracting transport sequence number we need to - // propagate "Sent" notification for both RTP and RTCP packets. For this - // reason we need save options.packet_id in packet map. - sent_rtp_packet_map_[datagram_id] = SentPacketInfo(options.packet_id); - return SendDatagram(*packet, datagram_id); -} - -bool DatagramRtpTransport::SendDatagram(rtc::ArrayView<const uint8_t> data, - DatagramId datagram_id) { - return datagram_transport_->SendDatagram(data, datagram_id).ok(); -} - -void DatagramRtpTransport::OnDatagramReceived( - rtc::ArrayView<const uint8_t> data) { - RTC_DCHECK_RUN_ON(&thread_checker_); - - rtc::ArrayView<const char> cdata(reinterpret_cast<const char*>(data.data()), - data.size()); - if (cricket::InferRtpPacketType(cdata) == cricket::RtpPacketType::kRtcp) { - rtc::CopyOnWriteBuffer buffer(data.data(), data.size()); - SignalRtcpPacketReceived(&buffer, /*packet_time_us=*/-1); - return; - } - - // TODO(sukhanov): I am not filling out time, but on my video quality - // test in WebRTC the time was not set either and higher layers of the stack - // overwrite -1 with current current rtc time. Leaveing comment for now to - // make sure it works as expected. - RtpPacketReceived parsed_packet(&rtp_header_extension_map_); - if (!parsed_packet.Parse(data)) { - RTC_LOG(LS_ERROR) << "Failed to parse incoming RTP packet"; - return; - } - if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) { - RTC_LOG(LS_WARNING) << "Failed to demux RTP packet: " - << RtpDemuxer::DescribePacket(parsed_packet); - } -} - -void DatagramRtpTransport::OnDatagramSent(DatagramId datagram_id) { - RTC_DCHECK_RUN_ON(&thread_checker_); - - // Find packet_id and propagate OnPacketSent notification. - const auto& it = sent_rtp_packet_map_.find(datagram_id); - if (it == sent_rtp_packet_map_.end()) { - RTC_NOTREACHED() << "Did not find sent packet info for sent datagram_id=" - << datagram_id; - return; - } - - // Also see how DatagramRtpTransport::OnSentPacket handles OnSentPacket - // notification from ICE in bypass mode. - rtc::SentPacket sent_packet(/*packet_id=*/it->second.packet_id, - rtc::TimeMillis()); - - SignalSentPacket(sent_packet); -} - -bool DatagramRtpTransport::GetAndRemoveSentPacketInfo( - DatagramId datagram_id, - SentPacketInfo* sent_packet_info) { - RTC_CHECK(sent_packet_info != nullptr); - - const auto& it = sent_rtp_packet_map_.find(datagram_id); - if (it == sent_rtp_packet_map_.end()) { - return false; - } - - *sent_packet_info = it->second; - sent_rtp_packet_map_.erase(it); - return true; -} - -void DatagramRtpTransport::OnDatagramAcked(const DatagramAck& ack) { - RTC_DCHECK_RUN_ON(&thread_checker_); - - SentPacketInfo sent_packet_info; - if (!GetAndRemoveSentPacketInfo(ack.datagram_id, &sent_packet_info)) { - // TODO(sukhanov): If OnDatagramAck() can come after OnDatagramLost(), - // datagram_id is already deleted and we may need to relax the CHECK below. - // It's probably OK to ignore such datagrams, because it's been a few RTTs - // anyway since they were sent. - RTC_NOTREACHED() << "Did not find sent packet info for datagram_id=" - << ack.datagram_id; - return; - } - - RTC_LOG(LS_VERBOSE) << "Datagram acked, ack.datagram_id=" << ack.datagram_id - << ", sent_packet_info.packet_id=" - << sent_packet_info.packet_id - << ", sent_packet_info.transport_sequence_number=" - << sent_packet_info.transport_sequence_number.value_or(-1) - << ", sent_packet_info.ssrc=" - << sent_packet_info.ssrc.value_or(-1) - << ", receive_timestamp_ms=" - << ack.receive_timestamp.ms(); - - // If transport sequence number was not present in RTP packet, we do not need - // to propagate RTCP feedback. - if (!sent_packet_info.transport_sequence_number) { - return; - } - - // TODO(sukhanov): We noticed that datagram transport implementations can - // return zero timestamps in the middle of the call. This is workaround to - // avoid propagating zero timestamps, but we need to understand why we have - // them in the first place. - int64_t receive_timestamp_us = ack.receive_timestamp.us(); - - if (receive_timestamp_us == 0) { - receive_timestamp_us = previous_nonzero_timestamp_us_; - } else { - previous_nonzero_timestamp_us_ = receive_timestamp_us; - } - - // Ssrc must be provided in packet info if transport sequence number is set, - // which is guaranteed by SentPacketInfo constructor. - RTC_CHECK(sent_packet_info.ssrc); - - // Recreate RTCP feedback packet. - rtcp::TransportFeedback feedback_packet; - feedback_packet.SetMediaSsrc(*sent_packet_info.ssrc); - - const uint16_t transport_sequence_number = - sent_packet_info.transport_sequence_number.value(); - - feedback_packet.SetBase(transport_sequence_number, receive_timestamp_us); - feedback_packet.AddReceivedPacket(transport_sequence_number, - receive_timestamp_us); - - rtc::CopyOnWriteBuffer buffer(kMaxRtcpFeedbackPacketSize); - size_t index = 0; - if (!feedback_packet.Create(buffer.data(), &index, buffer.capacity(), - nullptr)) { - RTC_NOTREACHED() << "Failed to create RTCP feedback packet"; - return; - } - - RTC_CHECK_GT(index, 0); - RTC_CHECK_LE(index, kMaxRtcpFeedbackPacketSize); - - // Propagage created RTCP packet as normal incoming packet. - buffer.SetSize(index); - SignalRtcpPacketReceived(&buffer, /*packet_time_us=*/-1); -} - -void DatagramRtpTransport::OnDatagramLost(DatagramId datagram_id) { - RTC_DCHECK_RUN_ON(&thread_checker_); - - RTC_LOG(LS_INFO) << "Datagram lost, datagram_id=" << datagram_id; - - SentPacketInfo sent_packet_info; - if (!GetAndRemoveSentPacketInfo(datagram_id, &sent_packet_info)) { - RTC_NOTREACHED() << "Did not find sent packet info for lost datagram_id=" - << datagram_id; - } -} - -void DatagramRtpTransport::OnStateChanged(MediaTransportState state) { - state_ = state; - SignalWritableState(state_ == MediaTransportState::kWritable); - if (state_ == MediaTransportState::kWritable) { - SignalReadyToSend(true); - } -} - -const std::string& DatagramRtpTransport::transport_name() const { - return ice_transport_->transport_name(); -} - -int DatagramRtpTransport::SetRtpOption(rtc::Socket::Option opt, int value) { - return ice_transport_->SetOption(opt, value); -} - -int DatagramRtpTransport::SetRtcpOption(rtc::Socket::Option opt, int value) { - return -1; -} - -bool DatagramRtpTransport::IsReadyToSend() const { - return state_ == MediaTransportState::kWritable; -} - -bool DatagramRtpTransport::IsWritable(bool /*rtcp*/) const { - return state_ == MediaTransportState::kWritable; -} - -void DatagramRtpTransport::UpdateRtpHeaderExtensionMap( - const cricket::RtpHeaderExtensions& header_extensions) { - rtp_header_extension_map_ = RtpHeaderExtensionMap(header_extensions); -} - -bool DatagramRtpTransport::RegisterRtpDemuxerSink( - const RtpDemuxerCriteria& criteria, - RtpPacketSinkInterface* sink) { - rtp_demuxer_.RemoveSink(sink); - return rtp_demuxer_.AddSink(criteria, sink); -} - -bool DatagramRtpTransport::UnregisterRtpDemuxerSink( - RtpPacketSinkInterface* sink) { - return rtp_demuxer_.RemoveSink(sink); -} - -void DatagramRtpTransport::OnNetworkRouteChanged( - absl::optional<rtc::NetworkRoute> network_route) { - RTC_DCHECK_RUN_ON(&thread_checker_); - SignalNetworkRouteChanged(network_route); -} - -} // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/datagram_rtp_transport.h b/chromium/third_party/webrtc/pc/datagram_rtp_transport.h deleted file mode 100644 index f9684c69c03..00000000000 --- a/chromium/third_party/webrtc/pc/datagram_rtp_transport.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2019 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef PC_DATAGRAM_RTP_TRANSPORT_H_ -#define PC_DATAGRAM_RTP_TRANSPORT_H_ - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "api/crypto/crypto_options.h" -#include "api/transport/datagram_transport_interface.h" -#include "api/transport/media/media_transport_interface.h" -#include "modules/rtp_rtcp/include/rtp_header_extension_map.h" -#include "modules/rtp_rtcp/source/rtp_header_extensions.h" -#include "p2p/base/ice_transport_internal.h" -#include "p2p/base/packet_transport_internal.h" -#include "pc/rtp_transport_internal.h" -#include "rtc_base/buffer.h" -#include "rtc_base/buffer_queue.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/ssl_stream_adapter.h" -#include "rtc_base/stream.h" -#include "rtc_base/strings/string_builder.h" -#include "rtc_base/thread_checker.h" - -namespace webrtc { - -constexpr int kDatagramDtlsAdaptorComponent = -1; - -// RTP transport which uses the DatagramTransportInterface to send and receive -// packets. -class DatagramRtpTransport : public RtpTransportInternal, - public webrtc::DatagramSinkInterface, - public webrtc::MediaTransportStateCallback { - public: - DatagramRtpTransport( - const std::vector<webrtc::RtpExtension>& rtp_header_extensions, - cricket::IceTransportInternal* ice_transport, - DatagramTransportInterface* datagram_transport); - - ~DatagramRtpTransport() override; - - // ===================================================== - // Overrides for webrtc::DatagramTransportSinkInterface - // and MediaTransportStateCallback - // ===================================================== - void OnDatagramReceived(rtc::ArrayView<const uint8_t> data) override; - - void OnDatagramSent(webrtc::DatagramId datagram_id) override; - - void OnDatagramAcked(const webrtc::DatagramAck& ack) override; - - void OnDatagramLost(webrtc::DatagramId datagram_id) override; - - void OnStateChanged(webrtc::MediaTransportState state) override; - - // ===================================================== - // RtpTransportInternal overrides - // ===================================================== - bool SendRtpPacket(rtc::CopyOnWriteBuffer* packet, - const rtc::PacketOptions& options, - int flags) override; - - bool SendRtcpPacket(rtc::CopyOnWriteBuffer* packet, - const rtc::PacketOptions& options, - int flags) override; - - const std::string& transport_name() const override; - - // Datagram transport always muxes RTCP. - bool rtcp_mux_enabled() const override { return true; } - void SetRtcpMuxEnabled(bool enable) override {} - - int SetRtpOption(rtc::Socket::Option opt, int value) override; - int SetRtcpOption(rtc::Socket::Option opt, int value) override; - - bool IsReadyToSend() const override; - - bool IsWritable(bool rtcp) const override; - - bool IsSrtpActive() const override { return false; } - - void UpdateRtpHeaderExtensionMap( - const cricket::RtpHeaderExtensions& header_extensions) override; - - bool RegisterRtpDemuxerSink(const RtpDemuxerCriteria& criteria, - RtpPacketSinkInterface* sink) override; - - bool UnregisterRtpDemuxerSink(RtpPacketSinkInterface* sink) override; - - private: - // RTP/RTCP packet info stored for each sent packet. - struct SentPacketInfo { - // RTP packet info with ssrc and transport sequence number. - SentPacketInfo(int64_t packet_id, - uint32_t ssrc, - uint16_t transport_sequence_number) - : ssrc(ssrc), - transport_sequence_number(transport_sequence_number), - packet_id(packet_id) {} - - // Packet info without SSRC and transport sequence number used for RTCP - // packets, RTP packets when transport sequence number is not provided or - // when feedback translation is disabled. - explicit SentPacketInfo(int64_t packet_id) : packet_id(packet_id) {} - - SentPacketInfo() = default; - - absl::optional<uint32_t> ssrc; - - // Transport sequence number (if it was provided in outgoing RTP packet). - // It is used to re-create RTCP feedback packets from datagram ACKs. - absl::optional<uint16_t> transport_sequence_number; - - // Packet id from rtc::PacketOptions. It is required to propagage sent - // notification up the stack (SignalSentPacket). - int64_t packet_id = 0; - }; - - // Finds SentPacketInfo for given |datagram_id| and removes map entry. - // Returns false if entry was not found. - bool GetAndRemoveSentPacketInfo(webrtc::DatagramId datagram_id, - SentPacketInfo* sent_packet_info); - - // Sends datagram to datagram_transport. - bool SendDatagram(rtc::ArrayView<const uint8_t> data, - webrtc::DatagramId datagram_id); - - // Propagates network route changes from ICE. - void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route); - - rtc::ThreadChecker thread_checker_; - cricket::IceTransportInternal* ice_transport_; - webrtc::DatagramTransportInterface* datagram_transport_; - - RtpDemuxer rtp_demuxer_; - - MediaTransportState state_ = MediaTransportState::kPending; - - // Extension map for parsing transport sequence numbers. - webrtc::RtpHeaderExtensionMap rtp_header_extension_map_; - - // Keeps information about sent RTP packet until they are Acked or Lost. - std::map<webrtc::DatagramId, SentPacketInfo> sent_rtp_packet_map_; - - // Current datagram_id, incremented after each sent RTP packets. - // Datagram id is passed to datagram transport when we send datagram and we - // get it back in notifications about Sent, Acked and Lost datagrams. - int64_t current_datagram_id_ = 0; - - // TODO(sukhanov): Previous nonzero timestamp is required for workaround for - // zero timestamps received, which sometimes are received from datagram - // transport. Investigate if we can eliminate zero timestamps. - int64_t previous_nonzero_timestamp_us_ = 0; - - // Disable datagram to RTCP feedback translation and enable RTCP feedback - // loop (note that having both RTCP and datagram feedback loops is - // inefficient, but can be useful in tests and experiments). - const bool disable_datagram_to_rtcp_feeback_translation_; -}; - -} // namespace webrtc - -#endif // PC_DATAGRAM_RTP_TRANSPORT_H_ diff --git a/chromium/third_party/webrtc/pc/jsep_transport.cc b/chromium/third_party/webrtc/pc/jsep_transport.cc index 5bf74f1e87a..6864dfc45db 100644 --- a/chromium/third_party/webrtc/pc/jsep_transport.cc +++ b/chromium/third_party/webrtc/pc/jsep_transport.cc @@ -38,16 +38,12 @@ JsepTransportDescription::JsepTransportDescription( const std::vector<CryptoParams>& cryptos, const std::vector<int>& encrypted_header_extension_ids, int rtp_abs_sendtime_extn_id, - const TransportDescription& transport_desc, - absl::optional<std::string> media_alt_protocol, - absl::optional<std::string> data_alt_protocol) + const TransportDescription& transport_desc) : rtcp_mux_enabled(rtcp_mux_enabled), cryptos(cryptos), encrypted_header_extension_ids(encrypted_header_extension_ids), rtp_abs_sendtime_extn_id(rtp_abs_sendtime_extn_id), - transport_desc(transport_desc), - media_alt_protocol(media_alt_protocol), - data_alt_protocol(data_alt_protocol) {} + transport_desc(transport_desc) {} JsepTransportDescription::JsepTransportDescription( const JsepTransportDescription& from) @@ -55,9 +51,7 @@ JsepTransportDescription::JsepTransportDescription( cryptos(from.cryptos), encrypted_header_extension_ids(from.encrypted_header_extension_ids), rtp_abs_sendtime_extn_id(from.rtp_abs_sendtime_extn_id), - transport_desc(from.transport_desc), - media_alt_protocol(from.media_alt_protocol), - data_alt_protocol(from.data_alt_protocol) {} + transport_desc(from.transport_desc) {} JsepTransportDescription::~JsepTransportDescription() = default; @@ -71,8 +65,6 @@ JsepTransportDescription& JsepTransportDescription::operator=( encrypted_header_extension_ids = from.encrypted_header_extension_ids; rtp_abs_sendtime_extn_id = from.rtp_abs_sendtime_extn_id; transport_desc = from.transport_desc; - media_alt_protocol = from.media_alt_protocol; - data_alt_protocol = from.data_alt_protocol; return *this; } @@ -88,9 +80,7 @@ JsepTransport::JsepTransport( std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport, std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport, std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport, - std::unique_ptr<SctpTransportInternal> sctp_transport, - std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport, - webrtc::DataChannelTransportInterface* data_channel_transport) + std::unique_ptr<SctpTransportInternal> sctp_transport) : network_thread_(rtc::Thread::Current()), mid_(mid), local_certificate_(local_certificate), @@ -115,10 +105,7 @@ JsepTransport::JsepTransport( sctp_transport_(sctp_transport ? new rtc::RefCountedObject<webrtc::SctpTransport>( std::move(sctp_transport)) - : nullptr), - datagram_transport_(std::move(datagram_transport)), - datagram_rtp_transport_(std::move(datagram_rtp_transport)), - data_channel_transport_(data_channel_transport) { + : nullptr) { RTC_DCHECK(ice_transport_); RTC_DCHECK(rtp_dtls_transport_); // |rtcp_ice_transport_| must be present iff |rtcp_dtls_transport_| is @@ -383,18 +370,6 @@ absl::optional<rtc::SSLRole> JsepTransport::GetDtlsRole() const { return absl::optional<rtc::SSLRole>(dtls_role); } -absl::optional<OpaqueTransportParameters> -JsepTransport::GetTransportParameters() const { - rtc::CritScope scope(&accessor_lock_); - if (!datagram_transport()) { - return absl::nullopt; - } - - OpaqueTransportParameters params; - params.parameters = datagram_transport()->GetTransportParameters(); - return params; -} - bool JsepTransport::GetStats(TransportStats* stats) { RTC_DCHECK_RUN_ON(network_thread_); rtc::CritScope scope(&accessor_lock_); @@ -462,7 +437,6 @@ webrtc::RTCError JsepTransport::SetNegotiatedDtlsParameters( DtlsTransportInternal* dtls_transport, absl::optional<rtc::SSLRole> dtls_role, rtc::SSLFingerprint* remote_fingerprint) { - RTC_DCHECK_RUN_ON(network_thread_); RTC_DCHECK(dtls_transport); // Set SSL role. Role must be set before fingerprint is applied, which // initiates DTLS setup. @@ -535,7 +509,7 @@ void JsepTransport::ActivateRtcpMux() { RTC_DCHECK(dtls_srtp_transport_); RTC_DCHECK(!unencrypted_rtp_transport_); RTC_DCHECK(!sdes_transport_); - dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport(), + dtls_srtp_transport_->SetDtlsTransports(rtp_dtls_transport_locked(), /*rtcp_dtls_transport=*/nullptr); } rtcp_dtls_transport_ = nullptr; // Destroy this reference. @@ -549,7 +523,6 @@ bool JsepTransport::SetSdes(const std::vector<CryptoParams>& cryptos, webrtc::SdpType type, ContentSource source) { RTC_DCHECK_RUN_ON(network_thread_); - rtc::CritScope scope(&accessor_lock_); bool ret = false; ret = sdes_negotiator_.Process(cryptos, type, source); if (!ret) { @@ -734,7 +707,6 @@ webrtc::RTCError JsepTransport::NegotiateDtlsRole( bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport, TransportStats* stats) { RTC_DCHECK_RUN_ON(network_thread_); - rtc::CritScope scope(&accessor_lock_); RTC_DCHECK(dtls_transport); TransportChannelStats substats; if (rtcp_dtls_transport_) { @@ -756,106 +728,10 @@ bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport, return true; } +// TODO(nisse): Delete. void JsepTransport::NegotiateDatagramTransport(SdpType type) { RTC_DCHECK(type == SdpType::kAnswer || type == SdpType::kPrAnswer); - rtc::CritScope lock(&accessor_lock_); - if (!datagram_transport_) { - return; // No need to negotiate the use of datagram transport. - } - - bool compatible_datagram_transport = false; - if (datagram_transport_ && - local_description_->transport_desc.opaque_parameters && - remote_description_->transport_desc.opaque_parameters) { - // If both descriptions have datagram transport parameters, and the remote - // parameters are accepted by the datagram transport, then use the datagram - // transport. Otherwise, fall back to RTP. - compatible_datagram_transport = - datagram_transport_ - ->SetRemoteTransportParameters(remote_description_->transport_desc - .opaque_parameters->parameters) - .ok(); - } - - bool use_datagram_transport_for_media = - compatible_datagram_transport && - remote_description_->media_alt_protocol == - remote_description_->transport_desc.opaque_parameters->protocol && - remote_description_->media_alt_protocol == - local_description_->media_alt_protocol; - - bool use_datagram_transport_for_data = - compatible_datagram_transport && - remote_description_->data_alt_protocol == - remote_description_->transport_desc.opaque_parameters->protocol && - remote_description_->data_alt_protocol == - local_description_->data_alt_protocol; - - RTC_LOG(LS_INFO) - << "Negotiating datagram transport, use_datagram_transport_for_media=" - << use_datagram_transport_for_media - << ", use_datagram_transport_for_data=" << use_datagram_transport_for_data - << " answer type=" << (type == SdpType::kAnswer ? "answer" : "pr_answer"); - - // A provisional or full or answer lets the peer start sending on one of the - // transports. - if (composite_rtp_transport_) { - composite_rtp_transport_->SetSendTransport( - use_datagram_transport_for_media ? datagram_rtp_transport_.get() - : default_rtp_transport()); - } - if (composite_data_channel_transport_) { - composite_data_channel_transport_->SetSendTransport( - use_datagram_transport_for_data ? data_channel_transport_ - : sctp_data_channel_transport_.get()); - } - - if (type != SdpType::kAnswer) { - return; - } - - if (composite_rtp_transport_) { - if (use_datagram_transport_for_media) { - // Negotiated use of datagram transport for RTP, so remove the - // non-datagram RTP transport. - composite_rtp_transport_->RemoveTransport(default_rtp_transport()); - if (unencrypted_rtp_transport_) { - unencrypted_rtp_transport_ = nullptr; - } else if (sdes_transport_) { - sdes_transport_ = nullptr; - } else { - dtls_srtp_transport_ = nullptr; - } - } else { - composite_rtp_transport_->RemoveTransport(datagram_rtp_transport_.get()); - datagram_rtp_transport_ = nullptr; - } - } - - if (composite_data_channel_transport_) { - if (use_datagram_transport_for_data) { - // Negotiated use of datagram transport for data channels, so remove the - // non-datagram data channel transport. - composite_data_channel_transport_->RemoveTransport( - sctp_data_channel_transport_.get()); - sctp_data_channel_transport_ = nullptr; - sctp_transport_ = nullptr; - } else { - composite_data_channel_transport_->RemoveTransport( - data_channel_transport_); - data_channel_transport_ = nullptr; - } - } else if (data_channel_transport_ && !use_datagram_transport_for_data) { - // The datagram transport has been rejected without a fallback. We still - // need to inform the application and delete it. - SignalDataChannelTransportNegotiated(this, nullptr); - data_channel_transport_ = nullptr; - } - - if (!use_datagram_transport_for_media && !use_datagram_transport_for_data) { - // Datagram transport is not being used for anything, so clean it up. - datagram_transport_ = nullptr; - } + return; // No need to negotiate the use of datagram transport. } } // namespace cricket diff --git a/chromium/third_party/webrtc/pc/jsep_transport.h b/chromium/third_party/webrtc/pc/jsep_transport.h index 6d88deff076..27c30a5202c 100644 --- a/chromium/third_party/webrtc/pc/jsep_transport.h +++ b/chromium/third_party/webrtc/pc/jsep_transport.h @@ -20,7 +20,6 @@ #include "api/candidate.h" #include "api/ice_transport_interface.h" #include "api/jsep.h" -#include "api/transport/datagram_transport_interface.h" #include "media/sctp/sctp_transport_internal.h" #include "p2p/base/dtls_transport.h" #include "p2p/base/p2p_constants.h" @@ -54,9 +53,7 @@ struct JsepTransportDescription { const std::vector<CryptoParams>& cryptos, const std::vector<int>& encrypted_header_extension_ids, int rtp_abs_sendtime_extn_id, - const TransportDescription& transport_description, - absl::optional<std::string> media_alt_protocol, - absl::optional<std::string> data_alt_protocol); + const TransportDescription& transport_description); JsepTransportDescription(const JsepTransportDescription& from); ~JsepTransportDescription(); @@ -69,14 +66,6 @@ struct JsepTransportDescription { // TODO(zhihuang): Add the ICE and DTLS related variables and methods from // TransportDescription and remove this extra layer of abstraction. TransportDescription transport_desc; - - // Alt-protocols that apply to this JsepTransport. Presence indicates a - // request to use an alternative protocol for media and/or data. The - // alt-protocol is handled by a datagram transport. If one or both of these - // values are present, JsepTransport will attempt to negotiate use of the - // datagram transport for media and/or data. - absl::optional<std::string> media_alt_protocol; - absl::optional<std::string> data_alt_protocol; }; // Helper class used by JsepTransportController that processes @@ -103,9 +92,7 @@ class JsepTransport : public sigslot::has_slots<> { std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport, std::unique_ptr<DtlsTransportInternal> rtp_dtls_transport, std::unique_ptr<DtlsTransportInternal> rtcp_dtls_transport, - std::unique_ptr<SctpTransportInternal> sctp_transport, - std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport, - webrtc::DataChannelTransportInterface* data_channel_transport); + std::unique_ptr<SctpTransportInternal> sctp_transport); ~JsepTransport() override; @@ -128,14 +115,15 @@ class JsepTransport : public sigslot::has_slots<> { webrtc::RTCError SetLocalJsepTransportDescription( const JsepTransportDescription& jsep_description, - webrtc::SdpType type); + webrtc::SdpType type) RTC_LOCKS_EXCLUDED(accessor_lock_); // Set the remote TransportDescription to be used by DTLS and ICE channels // that are part of this Transport. webrtc::RTCError SetRemoteJsepTransportDescription( const JsepTransportDescription& jsep_description, - webrtc::SdpType type); - webrtc::RTCError AddRemoteCandidates(const Candidates& candidates); + webrtc::SdpType type) RTC_LOCKS_EXCLUDED(accessor_lock_); + webrtc::RTCError AddRemoteCandidates(const Candidates& candidates) + RTC_LOCKS_EXCLUDED(accessor_lock_); // Set the "needs-ice-restart" flag as described in JSEP. After the flag is // set, offers should generate new ufrags/passwords until an ICE restart @@ -143,23 +131,22 @@ class JsepTransport : public sigslot::has_slots<> { // // This and the below method can be called safely from any thread as long as // SetXTransportDescription is not in progress. - void SetNeedsIceRestartFlag(); + void SetNeedsIceRestartFlag() RTC_LOCKS_EXCLUDED(accessor_lock_); // Returns true if the ICE restart flag above was set, and no ICE restart has // occurred yet for this transport (by applying a local description with // changed ufrag/password). - bool needs_ice_restart() const { + bool needs_ice_restart() const RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); return needs_ice_restart_; } // Returns role if negotiated, or empty absl::optional if it hasn't been // negotiated yet. - absl::optional<rtc::SSLRole> GetDtlsRole() const; - - absl::optional<OpaqueTransportParameters> GetTransportParameters() const; + absl::optional<rtc::SSLRole> GetDtlsRole() const + RTC_LOCKS_EXCLUDED(accessor_lock_); // TODO(deadbeef): Make this const. See comment in transportcontroller.h. - bool GetStats(TransportStats* stats); + bool GetStats(TransportStats* stats) RTC_LOCKS_EXCLUDED(accessor_lock_); const JsepTransportDescription* local_description() const { RTC_DCHECK_RUN_ON(network_thread_); @@ -171,7 +158,8 @@ class JsepTransport : public sigslot::has_slots<> { return remote_description_.get(); } - webrtc::RtpTransportInternal* rtp_transport() const { + webrtc::RtpTransportInternal* rtp_transport() const + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); if (composite_rtp_transport_) { return composite_rtp_transport_.get(); @@ -182,7 +170,8 @@ class JsepTransport : public sigslot::has_slots<> { } } - const DtlsTransportInternal* rtp_dtls_transport() const { + const DtlsTransportInternal* rtp_dtls_transport() const + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); if (rtp_dtls_transport_) { return rtp_dtls_transport_->internal(); @@ -191,16 +180,14 @@ class JsepTransport : public sigslot::has_slots<> { } } - DtlsTransportInternal* rtp_dtls_transport() { + DtlsTransportInternal* rtp_dtls_transport() + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); - if (rtp_dtls_transport_) { - return rtp_dtls_transport_->internal(); - } else { - return nullptr; - } + return rtp_dtls_transport_locked(); } - const DtlsTransportInternal* rtcp_dtls_transport() const { + const DtlsTransportInternal* rtcp_dtls_transport() const + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); if (rtcp_dtls_transport_) { return rtcp_dtls_transport_->internal(); @@ -209,7 +196,8 @@ class JsepTransport : public sigslot::has_slots<> { } } - DtlsTransportInternal* rtcp_dtls_transport() { + DtlsTransportInternal* rtcp_dtls_transport() + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); if (rtcp_dtls_transport_) { return rtcp_dtls_transport_->internal(); @@ -218,17 +206,20 @@ class JsepTransport : public sigslot::has_slots<> { } } - rtc::scoped_refptr<webrtc::DtlsTransport> RtpDtlsTransport() { + rtc::scoped_refptr<webrtc::DtlsTransport> RtpDtlsTransport() + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); return rtp_dtls_transport_; } - rtc::scoped_refptr<webrtc::SctpTransport> SctpTransport() const { + rtc::scoped_refptr<webrtc::SctpTransport> SctpTransport() const + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); return sctp_transport_; } - webrtc::DataChannelTransportInterface* data_channel_transport() const { + webrtc::DataChannelTransportInterface* data_channel_transport() const + RTC_LOCKS_EXCLUDED(accessor_lock_) { rtc::CritScope scope(&accessor_lock_); if (composite_data_channel_transport_) { return composite_data_channel_transport_.get(); @@ -238,12 +229,6 @@ class JsepTransport : public sigslot::has_slots<> { return data_channel_transport_; } - // Returns datagram transport, if available. - webrtc::DatagramTransportInterface* datagram_transport() const { - rtc::CritScope scope(&accessor_lock_); - return datagram_transport_.get(); - } - // This is signaled when RTCP-mux becomes active and // |rtcp_dtls_transport_| is destroyed. The JsepTransportController will // handle the signal and update the aggregate transport states. @@ -271,6 +256,15 @@ class JsepTransport : public sigslot::has_slots<> { void SetActiveResetSrtpParams(bool active_reset_srtp_params); private: + DtlsTransportInternal* rtp_dtls_transport_locked() + RTC_EXCLUSIVE_LOCKS_REQUIRED(accessor_lock_) { + if (rtp_dtls_transport_) { + return rtp_dtls_transport_->internal(); + } else { + return nullptr; + } + } + bool SetRtcpMux(bool enable, webrtc::SdpType type, ContentSource source); void ActivateRtcpMux(); @@ -278,7 +272,8 @@ class JsepTransport : public sigslot::has_slots<> { bool SetSdes(const std::vector<CryptoParams>& cryptos, const std::vector<int>& encrypted_extension_ids, webrtc::SdpType type, - ContentSource source); + ContentSource source) + RTC_EXCLUSIVE_LOCKS_REQUIRED(accessor_lock_); // Negotiates and sets the DTLS parameters based on the current local and // remote transport description, such as the DTLS role to use, and whether @@ -295,26 +290,28 @@ class JsepTransport : public sigslot::has_slots<> { webrtc::SdpType local_description_type, ConnectionRole local_connection_role, ConnectionRole remote_connection_role, - absl::optional<rtc::SSLRole>* negotiated_dtls_role); + absl::optional<rtc::SSLRole>* negotiated_dtls_role) + RTC_LOCKS_EXCLUDED(accessor_lock_); // Pushes down the ICE parameters from the remote description. void SetRemoteIceParameters(const IceParameters& ice_parameters, IceTransportInternal* ice); // Pushes down the DTLS parameters obtained via negotiation. - webrtc::RTCError SetNegotiatedDtlsParameters( + static webrtc::RTCError SetNegotiatedDtlsParameters( DtlsTransportInternal* dtls_transport, absl::optional<rtc::SSLRole> dtls_role, rtc::SSLFingerprint* remote_fingerprint); bool GetTransportStats(DtlsTransportInternal* dtls_transport, - TransportStats* stats); + TransportStats* stats) + RTC_EXCLUSIVE_LOCKS_REQUIRED(accessor_lock_); // Deactivates, signals removal, and deletes |composite_rtp_transport_| if the // current state of negotiation is sufficient to determine which rtp_transport // and data channel transport to use. void NegotiateDatagramTransport(webrtc::SdpType type) - RTC_RUN_ON(network_thread_); + RTC_RUN_ON(network_thread_) RTC_LOCKS_EXCLUDED(accessor_lock_); // Returns the default (non-datagram) rtp transport, if any. webrtc::RtpTransportInternal* default_rtp_transport() const @@ -387,10 +384,6 @@ class JsepTransport : public sigslot::has_slots<> { absl::optional<std::vector<int>> recv_extension_ids_ RTC_GUARDED_BY(network_thread_); - // Optional datagram transport (experimental). - std::unique_ptr<webrtc::DatagramTransportInterface> datagram_transport_ - RTC_GUARDED_BY(accessor_lock_); - std::unique_ptr<webrtc::RtpTransportInternal> datagram_rtp_transport_ RTC_GUARDED_BY(accessor_lock_); diff --git a/chromium/third_party/webrtc/pc/jsep_transport_controller.cc b/chromium/third_party/webrtc/pc/jsep_transport_controller.cc index a7e1b876fe0..dbe7435c020 100644 --- a/chromium/third_party/webrtc/pc/jsep_transport_controller.cc +++ b/chromium/third_party/webrtc/pc/jsep_transport_controller.cc @@ -15,11 +15,8 @@ #include "absl/algorithm/container.h" #include "api/ice_transport_factory.h" -#include "api/transport/datagram_transport_interface.h" -#include "api/transport/media/media_transport_interface.h" #include "p2p/base/ice_transport_internal.h" #include "p2p/base/port.h" -#include "pc/datagram_rtp_transport.h" #include "pc/srtp_filter.h" #include "rtc_base/bind.h" #include "rtc_base/checks.h" @@ -140,26 +137,6 @@ RtpTransportInternal* JsepTransportController::GetRtpTransport( return jsep_transport->rtp_transport(); } -MediaTransportConfig JsepTransportController::GetMediaTransportConfig( - const std::string& mid) const { - auto jsep_transport = GetJsepTransportForMid(mid); - if (!jsep_transport) { - return MediaTransportConfig(); - } - - DatagramTransportInterface* datagram_transport = nullptr; - if (config_.use_datagram_transport) { - datagram_transport = jsep_transport->datagram_transport(); - } - - if (datagram_transport) { - return MediaTransportConfig( - /*rtp_max_packet_size=*/datagram_transport->GetLargestDatagramSize()); - } else { - return MediaTransportConfig(); - } -} - DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport( const std::string& mid) const { auto jsep_transport = GetJsepTransportForMid(mid); @@ -425,17 +402,6 @@ void JsepTransportController::SetActiveResetSrtpParams( } } -void JsepTransportController::SetMediaTransportSettings( - bool use_datagram_transport, - bool use_datagram_transport_for_data_channels, - bool use_datagram_transport_for_data_channels_receive_only) { - config_.use_datagram_transport = use_datagram_transport; - config_.use_datagram_transport_for_data_channels = - use_datagram_transport_for_data_channels; - config_.use_datagram_transport_for_data_channels_receive_only = - use_datagram_transport_for_data_channels_receive_only; -} - void JsepTransportController::RollbackTransports() { if (!network_thread_->IsCurrent()) { network_thread_->Invoke<void>(RTC_FROM_HERE, [=] { RollbackTransports(); }); @@ -468,16 +434,12 @@ JsepTransportController::CreateIceTransport(const std::string& transport_name, std::unique_ptr<cricket::DtlsTransportInternal> JsepTransportController::CreateDtlsTransport( const cricket::ContentInfo& content_info, - cricket::IceTransportInternal* ice, - DatagramTransportInterface* datagram_transport) { + cricket::IceTransportInternal* ice) { RTC_DCHECK(network_thread_->IsCurrent()); std::unique_ptr<cricket::DtlsTransportInternal> dtls; - if (datagram_transport) { - RTC_DCHECK(config_.use_datagram_transport || - config_.use_datagram_transport_for_data_channels); - } else if (config_.dtls_transport_factory) { + if (config_.dtls_transport_factory) { dtls = config_.dtls_transport_factory->CreateDtlsTransport( ice, config_.crypto_options); } else { @@ -614,16 +576,9 @@ RTCError JsepTransportController::ApplyDescription_n( } std::vector<int> merged_encrypted_extension_ids; - absl::optional<std::string> bundle_media_alt_protocol; - absl::optional<std::string> bundle_data_alt_protocol; if (bundle_group_) { merged_encrypted_extension_ids = MergeEncryptedHeaderExtensionIdsForBundle(description); - error = GetAltProtocolsForBundle(description, &bundle_media_alt_protocol, - &bundle_data_alt_protocol); - if (!error.ok()) { - return error; - } } for (const cricket::ContentInfo& content_info : description->contents()) { @@ -642,8 +597,6 @@ RTCError JsepTransportController::ApplyDescription_n( description->transport_infos().size()); for (size_t i = 0; i < description->contents().size(); ++i) { const cricket::ContentInfo& content_info = description->contents()[i]; - const cricket::MediaContentDescription* media_description = - content_info.media_description(); const cricket::TransportInfo& transport_info = description->transport_infos()[i]; if (content_info.rejected) { @@ -654,7 +607,8 @@ RTCError JsepTransportController::ApplyDescription_n( if (IsBundled(content_info.name) && content_info.name != *bundled_mid()) { if (!HandleBundledContent(content_info)) { return RTCError(RTCErrorType::INVALID_PARAMETER, - "Failed to process the bundled m= section."); + "Failed to process the bundled m= section with mid='" + + content_info.name + "'."); } continue; } @@ -665,23 +619,10 @@ RTCError JsepTransportController::ApplyDescription_n( } std::vector<int> extension_ids; - absl::optional<std::string> media_alt_protocol; - absl::optional<std::string> data_alt_protocol; if (bundled_mid() && content_info.name == *bundled_mid()) { extension_ids = merged_encrypted_extension_ids; - media_alt_protocol = bundle_media_alt_protocol; - data_alt_protocol = bundle_data_alt_protocol; } else { extension_ids = GetEncryptedHeaderExtensionIds(content_info); - switch (media_description->type()) { - case cricket::MEDIA_TYPE_AUDIO: - case cricket::MEDIA_TYPE_VIDEO: - media_alt_protocol = media_description->alt_protocol(); - break; - case cricket::MEDIA_TYPE_DATA: - data_alt_protocol = media_description->alt_protocol(); - break; - } } int rtp_abs_sendtime_extn_id = @@ -695,8 +636,7 @@ RTCError JsepTransportController::ApplyDescription_n( cricket::JsepTransportDescription jsep_description = CreateJsepTransportDescription(content_info, transport_info, - extension_ids, rtp_abs_sendtime_extn_id, - media_alt_protocol, data_alt_protocol); + extension_ids, rtp_abs_sendtime_extn_id); if (local) { error = transport->SetLocalJsepTransportDescription(jsep_description, type); @@ -706,9 +646,10 @@ RTCError JsepTransportController::ApplyDescription_n( } if (!error.ok()) { - LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, - "Failed to apply the description for " + - content_info.name + ": " + error.message()); + LOG_AND_RETURN_ERROR( + RTCErrorType::INVALID_PARAMETER, + "Failed to apply the description for m= section with mid='" + + content_info.name + "': " + error.message()); } } if (type == SdpType::kAnswer) { @@ -727,11 +668,11 @@ RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup( // The BUNDLE group containing a MID that no m= section has is invalid. if (new_bundle_group) { - for (const auto& content_name : new_bundle_group->content_names()) { + for (const std::string& content_name : new_bundle_group->content_names()) { if (!description->GetContentByName(content_name)) { return RTCError(RTCErrorType::INVALID_PARAMETER, - "The BUNDLE group contains MID:" + content_name + - " matching no m= section."); + "The BUNDLE group contains MID='" + content_name + + "' matching no m= section."); } } } @@ -743,18 +684,21 @@ RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup( if (new_bundle_group) { // The BUNDLE group in answer should be a subset of offered group. - for (const auto& content_name : new_bundle_group->content_names()) { + for (const std::string& content_name : + new_bundle_group->content_names()) { if (!offered_bundle_group || !offered_bundle_group->HasContentName(content_name)) { return RTCError(RTCErrorType::INVALID_PARAMETER, - "The BUNDLE group in answer contains a MID that was " - "not in the offered group."); + "The BUNDLE group in answer contains a MID='" + + content_name + + "' that was " + "not in the offered group."); } } } if (bundle_group_) { - for (const auto& content_name : bundle_group_->content_names()) { + for (const std::string& content_name : bundle_group_->content_names()) { // An answer that removes m= sections from pre-negotiated BUNDLE group // without rejecting it, is invalid. if (!new_bundle_group || @@ -762,8 +706,9 @@ RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup( auto* content_info = description->GetContentByName(content_name); if (!content_info || !content_info->rejected) { return RTCError(RTCErrorType::INVALID_PARAMETER, - "Answer cannot remove m= section " + content_name + - " from already-established BUNDLE group."); + "Answer cannot remove m= section with mid='" + + content_name + + "' from already-established BUNDLE group."); } } } @@ -798,9 +743,9 @@ RTCError JsepTransportController::ValidateAndMaybeUpdateBundleGroup( for (const auto& content_name : bundle_group_->content_names()) { auto other_content = description->GetContentByName(content_name); if (!other_content->rejected) { - return RTCError( - RTCErrorType::INVALID_PARAMETER, - "The m= section:" + content_name + " should be rejected."); + return RTCError(RTCErrorType::INVALID_PARAMETER, + "The m= section with mid='" + content_name + + "' should be rejected."); } } } @@ -815,8 +760,8 @@ RTCError JsepTransportController::ValidateContent( content_info.type == cricket::MediaProtocolType::kRtp && !content_info.media_description()->rtcp_mux()) { return RTCError(RTCErrorType::INVALID_PARAMETER, - "The m= section:" + content_info.name + - " is invalid. RTCP-MUX is not " + "The m= section with mid='" + content_info.name + + "' is invalid. RTCP-MUX is not " "enabled when it is required."); } return RTCError::OK(); @@ -892,9 +837,7 @@ JsepTransportController::CreateJsepTransportDescription( const cricket::ContentInfo& content_info, const cricket::TransportInfo& transport_info, const std::vector<int>& encrypted_extension_ids, - int rtp_abs_sendtime_extn_id, - absl::optional<std::string> media_alt_protocol, - absl::optional<std::string> data_alt_protocol) { + int rtp_abs_sendtime_extn_id) { const cricket::MediaContentDescription* content_desc = content_info.media_description(); RTC_DCHECK(content_desc); @@ -904,8 +847,7 @@ JsepTransportController::CreateJsepTransportDescription( return cricket::JsepTransportDescription( rtcp_mux_enabled, content_desc->cryptos(), encrypted_extension_ids, - rtp_abs_sendtime_extn_id, transport_info.description, media_alt_protocol, - data_alt_protocol); + rtp_abs_sendtime_extn_id, transport_info.description); } bool JsepTransportController::ShouldUpdateBundleGroup( @@ -971,55 +913,6 @@ JsepTransportController::MergeEncryptedHeaderExtensionIdsForBundle( return merged_ids; } -RTCError JsepTransportController::GetAltProtocolsForBundle( - const cricket::SessionDescription* description, - absl::optional<std::string>* media_alt_protocol, - absl::optional<std::string>* data_alt_protocol) { - RTC_DCHECK(description); - RTC_DCHECK(bundle_group_); - RTC_DCHECK(media_alt_protocol); - RTC_DCHECK(data_alt_protocol); - - bool found_media = false; - bool found_data = false; - for (const cricket::ContentInfo& content : description->contents()) { - if (bundle_group_->HasContentName(content.name)) { - const cricket::MediaContentDescription* media_description = - content.media_description(); - switch (media_description->type()) { - case cricket::MEDIA_TYPE_AUDIO: - case cricket::MEDIA_TYPE_VIDEO: - if (found_media && - *media_alt_protocol != media_description->alt_protocol()) { - return RTCError(RTCErrorType::INVALID_PARAMETER, - "The BUNDLE group contains conflicting " - "alt-protocols for media ('" + - media_alt_protocol->value_or("") + "' and '" + - media_description->alt_protocol().value_or("") + - "')"); - } - found_media = true; - *media_alt_protocol = media_description->alt_protocol(); - break; - case cricket::MEDIA_TYPE_DATA: - if (found_data && - *data_alt_protocol != media_description->alt_protocol()) { - return RTCError(RTCErrorType::INVALID_PARAMETER, - "The BUNDLE group contains conflicting " - "alt-protocols for data ('" + - data_alt_protocol->value_or("") + "' and '" + - media_description->alt_protocol().value_or("") + - "')"); - } - found_data = true; - *data_alt_protocol = media_description->alt_protocol(); - break; - } - } - } - return RTCError::OK(); -} - int JsepTransportController::GetRtpAbsSendTimeHeaderExtensionId( const cricket::ContentInfo& content_info) { if (!config_.enable_external_auth) { @@ -1060,83 +953,6 @@ cricket::JsepTransport* JsepTransportController::GetJsepTransportByName( return (it == jsep_transports_by_name_.end()) ? nullptr : it->second.get(); } -// TODO(sukhanov): Refactor to avoid code duplication for Media and Datagram -// transports setup. -std::unique_ptr<webrtc::DatagramTransportInterface> -JsepTransportController::MaybeCreateDatagramTransport( - const cricket::ContentInfo& content_info, - const cricket::SessionDescription& description, - bool local) { - if (config_.media_transport_factory == nullptr) { - return nullptr; - } - - if (!(config_.use_datagram_transport || - config_.use_datagram_transport_for_data_channels)) { - return nullptr; - } - - // Caller (offerer) datagram transport. - if (offer_datagram_transport_) { - RTC_DCHECK(local); - RTC_LOG(LS_INFO) << "Offered datagram transport has now been activated."; - return std::move(offer_datagram_transport_); - } - - const cricket::TransportDescription* transport_description = - description.GetTransportDescriptionByName(content_info.mid()); - RTC_DCHECK(transport_description) - << "Missing transport description for mid=" << content_info.mid(); - - if (!transport_description->opaque_parameters) { - RTC_LOG(LS_INFO) - << "No opaque transport parameters, not creating datagram transport"; - return nullptr; - } - - if (transport_description->opaque_parameters->protocol != - config_.media_transport_factory->GetTransportName()) { - RTC_LOG(LS_INFO) << "Opaque transport parameters for protocol=" - << transport_description->opaque_parameters->protocol - << ", which does not match supported protocol=" - << config_.media_transport_factory->GetTransportName(); - return nullptr; - } - - RTC_DCHECK(!local); - // When bundle is enabled, two JsepTransports are created, and then - // the second transport is destroyed (right away). - // For datagram transport, we don't want to create the second - // datagram transport in the first place. - RTC_LOG(LS_INFO) << "Returning new, client datagram transport."; - - MediaTransportSettings settings; - settings.is_caller = local; - settings.remote_transport_parameters = - transport_description->opaque_parameters->parameters; - settings.event_log = config_.event_log; - - auto datagram_transport_result = - config_.media_transport_factory->CreateDatagramTransport(network_thread_, - settings); - - if (!datagram_transport_result.ok()) { - // Datagram transport negotiation will fail and we'll fall back to RTP. - return nullptr; - } - - if (!datagram_transport_result.value() - ->SetRemoteTransportParameters( - transport_description->opaque_parameters->parameters) - .ok()) { - // Datagram transport negotiation failed (parameters are incompatible). - // Fall back to RTP. - return nullptr; - } - - return datagram_transport_result.MoveValue(); -} - RTCError JsepTransportController::MaybeCreateJsepTransport( bool local, const cricket::ContentInfo& content_info, @@ -1158,14 +974,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport( CreateIceTransport(content_info.name, /*rtcp=*/false); RTC_DCHECK(ice); - std::unique_ptr<DatagramTransportInterface> datagram_transport = - MaybeCreateDatagramTransport(content_info, description, local); - if (datagram_transport) { - datagram_transport->Connect(ice->internal()); - } - std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport = - CreateDtlsTransport(content_info, ice->internal(), nullptr); + CreateDtlsTransport(content_info, ice->internal()); std::unique_ptr<cricket::DtlsTransportInternal> rtcp_dtls_transport; std::unique_ptr<RtpTransport> unencrypted_rtp_transport; @@ -1177,29 +987,9 @@ RTCError JsepTransportController::MaybeCreateJsepTransport( if (config_.rtcp_mux_policy != PeerConnectionInterface::kRtcpMuxPolicyRequire && content_info.type == cricket::MediaProtocolType::kRtp) { - RTC_DCHECK(datagram_transport == nullptr); rtcp_ice = CreateIceTransport(content_info.name, /*rtcp=*/true); rtcp_dtls_transport = - CreateDtlsTransport(content_info, rtcp_ice->internal(), - /*datagram_transport=*/nullptr); - } - - // Only create a datagram RTP transport if the datagram transport should be - // used for RTP. - if (datagram_transport && config_.use_datagram_transport) { - // TODO(sukhanov): We use unencrypted RTP transport over DatagramTransport, - // because MediaTransport encrypts. In the future we may want to - // implement our own version of RtpTransport over MediaTransport, because - // it will give us more control over things like: - // - Fusing - // - Rtp header compression - // - Handling Rtcp feedback. - RTC_LOG(LS_INFO) << "Creating UnencryptedRtpTransport, because datagram " - "transport is used."; - RTC_DCHECK(!rtcp_dtls_transport); - datagram_rtp_transport = std::make_unique<DatagramRtpTransport>( - content_info.media_description()->rtp_header_extensions(), - ice->internal(), datagram_transport.get()); + CreateDtlsTransport(content_info, rtcp_ice->internal()); } if (config_.disable_encryption) { @@ -1223,19 +1013,13 @@ RTCError JsepTransportController::MaybeCreateJsepTransport( config_.sctp_factory->CreateSctpTransport(rtp_dtls_transport.get()); } - DataChannelTransportInterface* data_channel_transport = nullptr; - if (config_.use_datagram_transport_for_data_channels) { - data_channel_transport = datagram_transport.get(); - } - std::unique_ptr<cricket::JsepTransport> jsep_transport = std::make_unique<cricket::JsepTransport>( content_info.name, certificate_, std::move(ice), std::move(rtcp_ice), std::move(unencrypted_rtp_transport), std::move(sdes_transport), std::move(dtls_srtp_transport), std::move(datagram_rtp_transport), std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport), - std::move(sctp_transport), std::move(datagram_transport), - data_channel_transport); + std::move(sctp_transport)); jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect( this, &JsepTransportController::OnRtcpPacketReceived_n); @@ -1637,54 +1421,4 @@ void JsepTransportController::OnDtlsHandshakeError( SignalDtlsHandshakeError(error); } -absl::optional<cricket::OpaqueTransportParameters> -JsepTransportController::GetTransportParameters(const std::string& mid) { - if (!(config_.use_datagram_transport || - config_.use_datagram_transport_for_data_channels)) { - return absl::nullopt; - } - - cricket::JsepTransport* transport = GetJsepTransportForMid(mid); - if (transport) { - absl::optional<cricket::OpaqueTransportParameters> params = - transport->GetTransportParameters(); - if (params) { - params->protocol = config_.media_transport_factory->GetTransportName(); - } - return params; - } - - RTC_DCHECK(!local_desc_ && !remote_desc_) - << "JsepTransport should exist for every mid once any description is set"; - - if (config_.use_datagram_transport_for_data_channels_receive_only) { - return absl::nullopt; - } - - // Need to generate a transport for the offer. - if (!offer_datagram_transport_) { - webrtc::MediaTransportSettings settings; - settings.is_caller = true; - settings.pre_shared_key = rtc::CreateRandomString(32); - settings.event_log = config_.event_log; - auto datagram_transport_or_error = - config_.media_transport_factory->CreateDatagramTransport( - network_thread_, settings); - - if (datagram_transport_or_error.ok()) { - offer_datagram_transport_ = - std::move(datagram_transport_or_error.value()); - } else { - RTC_LOG(LS_INFO) << "Unable to create datagram transport, error=" - << datagram_transport_or_error.error().message(); - } - } - - // We have prepared a transport for the offer, and can now use its parameters. - cricket::OpaqueTransportParameters params; - params.parameters = offer_datagram_transport_->GetTransportParameters(); - params.protocol = config_.media_transport_factory->GetTransportName(); - return params; -} - } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/jsep_transport_controller.h b/chromium/third_party/webrtc/pc/jsep_transport_controller.h index c966e744c68..250501fd055 100644 --- a/chromium/third_party/webrtc/pc/jsep_transport_controller.h +++ b/chromium/third_party/webrtc/pc/jsep_transport_controller.h @@ -22,7 +22,6 @@ #include "api/ice_transport_factory.h" #include "api/peer_connection_interface.h" #include "api/rtc_event_log/rtc_event_log.h" -#include "api/transport/media/media_transport_config.h" #include "media/sctp/sctp_transport_internal.h" #include "p2p/base/dtls_transport.h" #include "p2p/base/dtls_transport_factory.h" @@ -103,31 +102,6 @@ class JsepTransportController : public sigslot::has_slots<> { // Factory for SCTP transports. cricket::SctpTransportInternalFactory* sctp_factory = nullptr; - - // Whether an RtpMediaTransport should be created as default, when no - // MediaTransportFactory is provided. - bool use_rtp_media_transport = false; - - // Use encrypted datagram transport to send packets. - bool use_datagram_transport = false; - - // Use datagram transport's implementation of data channels instead of SCTP. - bool use_datagram_transport_for_data_channels = false; - - // Whether |use_datagram_transport_for_data_channels| applies to outgoing - // calls. If true, |use_datagram_transport_for_data_channels| applies only - // to incoming calls. - bool use_datagram_transport_for_data_channels_receive_only = false; - - // Optional media transport factory (experimental). If provided it will be - // used to create datagram_transport (as long as either - // |use_datagram_transport| or - // |use_datagram_transport_for_data_channels| is set to true). However, - // whether it will be used to send / receive audio and video frames instead - // of RTP is determined by |use_datagram_transport|. Note that currently - // datagram_transport co-exists with RTP / RTCP transports and may use the - // same underlying ICE transport. - MediaTransportFactory* media_transport_factory = nullptr; }; // The ICE related events are signaled on the |signaling_thread|. @@ -161,8 +135,6 @@ class JsepTransportController : public sigslot::has_slots<> { rtc::scoped_refptr<SctpTransport> GetSctpTransport( const std::string& mid) const; - MediaTransportConfig GetMediaTransportConfig(const std::string& mid) const; - DataChannelTransportInterface* GetDataChannelTransport( const std::string& mid) const; @@ -215,26 +187,10 @@ class JsepTransportController : public sigslot::has_slots<> { void SetActiveResetSrtpParams(bool active_reset_srtp_params); - // Allows to overwrite the settings from config. You may set or reset the - // media transport configuration on the jsep transport controller, as long as - // you did not call 'GetMediaTransport' or 'MaybeCreateJsepTransport'. Once - // Jsep transport is created, you can't change this setting. - void SetMediaTransportSettings( - bool use_datagram_transport, - bool use_datagram_transport_for_data_channels, - bool use_datagram_transport_for_data_channels_receive_only); - // For now the rollback only removes mid to transport mappings // and deletes unused transports, but doesn't consider anything more complex. void RollbackTransports(); - // Gets the transport parameters for the transport identified by |mid|. - // If |mid| is bundled, returns the parameters for the bundled transport. - // If the transport for |mid| has not been created yet, it may be allocated in - // order to generate transport parameters. - absl::optional<cricket::OpaqueTransportParameters> GetTransportParameters( - const std::string& mid); - // All of these signals are fired on the signaling thread. // If any transport failed => failed, @@ -290,9 +246,7 @@ class JsepTransportController : public sigslot::has_slots<> { const cricket::ContentInfo& content_info, const cricket::TransportInfo& transport_info, const std::vector<int>& encrypted_extension_ids, - int rtp_abs_sendtime_extn_id, - absl::optional<std::string> media_alt_protocol, - absl::optional<std::string> data_alt_protocol); + int rtp_abs_sendtime_extn_id); absl::optional<std::string> bundled_mid() const { absl::optional<std::string> bundled_mid; @@ -314,12 +268,6 @@ class JsepTransportController : public sigslot::has_slots<> { std::vector<int> GetEncryptedHeaderExtensionIds( const cricket::ContentInfo& content_info); - // Extracts the alt-protocol settings that apply to the bundle group. - RTCError GetAltProtocolsForBundle( - const cricket::SessionDescription* description, - absl::optional<std::string>* media_alt_protocol, - absl::optional<std::string>* data_alt_protocol); - int GetRtpAbsSendTimeHeaderExtensionId( const cricket::ContentInfo& content_info); @@ -347,16 +295,6 @@ class JsepTransportController : public sigslot::has_slots<> { const cricket::ContentInfo& content_info, const cricket::SessionDescription& description); - // Creates datagram transport if config wants to use it, and a=x-mt line is - // present for the current media transport. Returned - // DatagramTransportInterface is not connected, and must be connected to ICE. - // You must call |GenerateOrGetLastMediaTransportOffer| on the caller before - // calling MaybeCreateDatagramTransport. - std::unique_ptr<webrtc::DatagramTransportInterface> - MaybeCreateDatagramTransport(const cricket::ContentInfo& content_info, - const cricket::SessionDescription& description, - bool local); - void MaybeDestroyJsepTransport(const std::string& mid); void DestroyAllJsepTransports_n(); @@ -370,8 +308,7 @@ class JsepTransportController : public sigslot::has_slots<> { std::unique_ptr<cricket::DtlsTransportInternal> CreateDtlsTransport( const cricket::ContentInfo& content_info, - cricket::IceTransportInternal* ice, - DatagramTransportInterface* datagram_transport); + cricket::IceTransportInternal* ice); rtc::scoped_refptr<webrtc::IceTransportInterface> CreateIceTransport( const std::string& transport_name, bool rtcp); @@ -446,17 +383,6 @@ class JsepTransportController : public sigslot::has_slots<> { Config config_; - // Early on in the call we don't know if datagram transport is going to be - // used, but we need to get the server-supported parameters to add to an SDP. - // This server datagram transport will be promoted to the used datagram - // transport after the local description is set, and the ownership will be - // transferred to the actual JsepTransport. This "offer" datagram transport is - // not created if it's done on the party that provides answer. This offer - // datagram transport is only created once at the beginning of the connection, - // and never again. - std::unique_ptr<DatagramTransportInterface> offer_datagram_transport_ = - nullptr; - const cricket::SessionDescription* local_desc_ = nullptr; const cricket::SessionDescription* remote_desc_ = nullptr; absl::optional<bool> initial_offerer_; diff --git a/chromium/third_party/webrtc/pc/jsep_transport_controller_unittest.cc b/chromium/third_party/webrtc/pc/jsep_transport_controller_unittest.cc index 3fc6f8b7e55..7bdba23c2d8 100644 --- a/chromium/third_party/webrtc/pc/jsep_transport_controller_unittest.cc +++ b/chromium/third_party/webrtc/pc/jsep_transport_controller_unittest.cc @@ -13,9 +13,6 @@ #include <map> #include <memory> -#include "api/test/fake_media_transport.h" -#include "api/test/loopback_media_transport.h" -#include "api/transport/media/media_transport_interface.h" #include "p2p/base/dtls_transport_factory.h" #include "p2p/base/fake_dtls_transport.h" #include "p2p/base/fake_ice_transport.h" @@ -44,20 +41,6 @@ static const char kDataMid1[] = "data1"; namespace webrtc { -namespace { - -// Media transport factory requires crypto settings to be present in order to -// create media transport. -void AddCryptoSettings(cricket::SessionDescription* description) { - for (auto& content : description->contents()) { - content.media_description()->AddCrypto(cricket::CryptoParams( - /*t=*/0, std::string(rtc::CS_AES_CM_128_HMAC_SHA1_80), - "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2", "")); - } -} - -} // namespace - class FakeIceTransportFactory : public webrtc::IceTransportFactory { public: ~FakeIceTransportFactory() override = default; @@ -440,96 +423,6 @@ TEST_F(JsepTransportControllerTest, GetDtlsTransportWithRtcpMux) { EXPECT_EQ(nullptr, transport_controller_->GetRtcpDtlsTransport(kVideoMid1)); } -TEST_F(JsepTransportControllerTest, - DtlsIsStillCreatedIfDatagramTransportIsOnlyUsedForDataChannels) { - FakeMediaTransportFactory fake_media_transport_factory("transport_params"); - JsepTransportController::Config config; - - config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - config.media_transport_factory = &fake_media_transport_factory; - config.use_datagram_transport_for_data_channels = true; - CreateJsepTransportController(config); - - auto description = CreateSessionDescriptionWithBundledData(); - AddCryptoSettings(description.get()); - - absl::optional<cricket::OpaqueTransportParameters> params = - transport_controller_->GetTransportParameters(kAudioMid1); - for (auto& info : description->transport_infos()) { - info.description.opaque_parameters = params; - } - for (cricket::ContentInfo& content_info : description->contents()) { - if (content_info.media_description()->type() == cricket::MEDIA_TYPE_DATA) { - content_info.media_description()->set_alt_protocol(params->protocol); - } - } - - EXPECT_TRUE(transport_controller_ - ->SetLocalDescription(SdpType::kOffer, description.get()) - .ok()); - EXPECT_TRUE(transport_controller_ - ->SetRemoteDescription(SdpType::kAnswer, description.get()) - .ok()); - - FakeDatagramTransport* datagram_transport = - static_cast<FakeDatagramTransport*>( - transport_controller_->GetDataChannelTransport(kAudioMid1)); - - ASSERT_NE(nullptr, datagram_transport); - - EXPECT_EQ(cricket::ICE_CANDIDATE_COMPONENT_RTP, - transport_controller_->GetDtlsTransport(kAudioMid1)->component()) - << "Datagram transport for media was not enabled, and so DTLS transport " - "should be created."; - - // Datagram transport is not used for media, so no max packet size is - // specified. - EXPECT_EQ(transport_controller_->GetMediaTransportConfig(kAudioMid1) - .rtp_max_packet_size, - absl::nullopt); - - // Since datagram transport is not used for RTP, setting it to writable should - // not make the RTP transport writable. - datagram_transport->set_state(MediaTransportState::kWritable); - EXPECT_FALSE(transport_controller_->GetRtpTransport(kAudioMid1) - ->IsWritable(/*rtcp=*/false)); -} - -// An offer that bundles different alt-protocols should be rejected. -TEST_F(JsepTransportControllerTest, CannotBundleDifferentAltProtocols) { - FakeMediaTransportFactory fake_media_transport_factory("transport_params"); - JsepTransportController::Config config; - config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - config.media_transport_factory = &fake_media_transport_factory; - config.use_datagram_transport = true; - config.use_datagram_transport_for_data_channels = true; - CreateJsepTransportController(config); - - auto description = CreateSessionDescriptionWithBundledData(); - AddCryptoSettings(description.get()); - - absl::optional<cricket::OpaqueTransportParameters> params = - transport_controller_->GetTransportParameters(kAudioMid1); - for (auto& info : description->transport_infos()) { - info.description.opaque_parameters = params; - } - - // Append a different alt-protocol to each of the sections. - for (cricket::ContentInfo& content_info : description->contents()) { - content_info.media_description()->set_alt_protocol(params->protocol + "-" + - content_info.name); - } - - EXPECT_FALSE(transport_controller_ - ->SetLocalDescription(SdpType::kOffer, description.get()) - .ok()); - EXPECT_FALSE(transport_controller_ - ->SetRemoteDescription(SdpType::kAnswer, description.get()) - .ok()); -} - TEST_F(JsepTransportControllerTest, SetIceConfig) { CreateJsepTransportController(JsepTransportController::Config()); auto description = CreateSessionDescriptionWithoutBundle(); @@ -1650,423 +1543,4 @@ TEST_F(JsepTransportControllerTest, ChangeTaggedMediaSectionMaxBundle) { .ok()); } -constexpr char kFakeTransportParameters[] = "fake-params"; - -// Test fixture that provides common setup and helpers for tests related to the -// datagram transport. -class JsepTransportControllerDatagramTest - : public JsepTransportControllerTest, - public testing::WithParamInterface<bool> { - public: - JsepTransportControllerDatagramTest() - : JsepTransportControllerTest(), - fake_media_transport_factory_(kFakeTransportParameters) { - JsepTransportController::Config config; - config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - config.media_transport_factory = &fake_media_transport_factory_; - config.use_datagram_transport = true; - CreateJsepTransportController(config); - } - - // Whether the JsepTransportController under test acts as the offerer or - // answerer in this test. - bool IsOfferer() { return GetParam(); } - - // Sets a description as local or remote based on type and current - // perspective. - RTCError SetDescription(SdpType type, - const cricket::SessionDescription* description) { - if (IsOfferer() == (type == SdpType::kOffer)) { - return transport_controller_->SetLocalDescription(type, description); - } else { - return transport_controller_->SetRemoteDescription(type, description); - } - } - - // Creates a session description with the settings necessary for datagram - // transport (bundle + crypto) and the given |transport_params|. - std::unique_ptr<cricket::SessionDescription> - CreateSessionDescriptionForDatagramTransport( - absl::optional<cricket::OpaqueTransportParameters> transport_params) { - auto description = CreateSessionDescriptionWithBundleGroup(); - AddCryptoSettings(description.get()); - - for (auto& info : description->transport_infos()) { - info.description.opaque_parameters = transport_params; - } - if (transport_params) { - for (auto& content_info : description->contents()) { - content_info.media_description()->set_alt_protocol( - transport_params->protocol); - } - } - return description; - } - - // Creates transport parameters with |protocol| and |parameters| - // matching what |fake_media_transport_factory_| provides. - cricket::OpaqueTransportParameters CreateTransportParameters() { - cricket::OpaqueTransportParameters params; - params.protocol = fake_media_transport_factory_.GetTransportName(); - params.parameters = "fake-params"; - return params; - } - - protected: - FakeMediaTransportFactory fake_media_transport_factory_; -}; - -TEST_P(JsepTransportControllerDatagramTest, InitDatagramTransport) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - // Getting transport parameters is allowed before setting a description. - // This is necessary so that the offerer can include these params. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - // Setting a description activates the datagram transport without changing - // transport parameters. - auto description = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, description.get()).ok()); - - // After setting an offer with transport parameters, those parameters are - // reflected by the controller. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -TEST_P(JsepTransportControllerDatagramTest, - OfferMissingDatagramTransportParams) { - if (IsOfferer()) { - // This test doesn't make sense from the offerer's perspective, as the offer - // must contain datagram transport params if the offerer supports it. - return; - } - - auto description = - CreateSessionDescriptionForDatagramTransport(absl::nullopt); - EXPECT_TRUE(SetDescription(SdpType::kOffer, description.get()).ok()); - - // The offer didn't contain any datagram transport parameters, so the answer - // won't either. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); -} - -TEST_P(JsepTransportControllerDatagramTest, OfferHasWrongTransportName) { - if (IsOfferer()) { - // This test doesn't make sense from the offerer's perspective, as the - // offerer cannot offer itself the wrong transport. - return; - } - - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - fake_params.protocol = "wrong-name"; - - auto description = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, description.get()).ok()); - - // The offerer and answerer support different datagram transports, so the - // answerer rejects the offered parameters. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); -} - -TEST_P(JsepTransportControllerDatagramTest, IncompatibleAnswer) { - // Transport will claim that no parameters are compatible, even if they match - // exactly. - fake_media_transport_factory_.set_transport_parameters_comparison( - [](absl::string_view, absl::string_view) { return false; }); - - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - auto answer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - // The offerer and answerer have incompatible parameters, so the answerer - // rejects the offered parameters. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); -} - -TEST_P(JsepTransportControllerDatagramTest, CompatibleAnswer) { - // Transport will claim that no parameters are compatible, even if they are - // completely different. - fake_media_transport_factory_.set_transport_parameters_comparison( - [](absl::string_view, absl::string_view) { return true; }); - - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - cricket::OpaqueTransportParameters answer_params; - answer_params.protocol = fake_params.protocol; - answer_params.parameters = "something different from offer"; - auto answer = CreateSessionDescriptionForDatagramTransport(answer_params); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - // The offerer and answerer have compatible parameters, so the answerer - // accepts the offered parameters. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -TEST_P(JsepTransportControllerDatagramTest, AnswerRejectsDatagram) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto answer = CreateSessionDescriptionForDatagramTransport(absl::nullopt); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - // The answer rejected datagram transport, so its parameters are empty. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); -} - -TEST_P(JsepTransportControllerDatagramTest, AnswerAcceptsDatagram) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto answer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - // The answer accepted datagram transport, so it is present. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -TEST_P(JsepTransportControllerDatagramTest, PrAnswerRejectsDatagram) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto answer = CreateSessionDescriptionForDatagramTransport(absl::nullopt); - EXPECT_TRUE(SetDescription(SdpType::kPrAnswer, answer.get()).ok()); - - // The answer rejected datagram transport, but it's provisional, so the - // transport is kept around for now. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -TEST_P(JsepTransportControllerDatagramTest, PrAnswerAcceptsDatagram) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto answer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kPrAnswer, answer.get()).ok()); - - // The answer provisionally accepted datagram transport, so it's kept. - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -TEST_P(JsepTransportControllerDatagramTest, RenegotiationCannotAddDatagram) { - auto offer = CreateSessionDescriptionForDatagramTransport(absl::nullopt); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); - - auto answer = CreateSessionDescriptionForDatagramTransport(absl::nullopt); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); - - // Attempting to add a datagram transport on a re-offer does not cause an - // error, but also does not add a datagram transport. - auto reoffer = - CreateSessionDescriptionForDatagramTransport(CreateTransportParameters()); - EXPECT_TRUE(SetDescription(SdpType::kOffer, reoffer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - absl::nullopt); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - absl::nullopt); -} - -TEST_P(JsepTransportControllerDatagramTest, RenegotiationCannotRemoveDatagram) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto answer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - // Attempting to remove a datagram transport on a re-offer does not cause an - // error, but also does not remove the datagram transport. - auto reoffer = CreateSessionDescriptionForDatagramTransport(absl::nullopt); - EXPECT_TRUE(SetDescription(SdpType::kOffer, reoffer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -TEST_P(JsepTransportControllerDatagramTest, - RenegotiationKeepsDatagramTransport) { - cricket::OpaqueTransportParameters fake_params = CreateTransportParameters(); - if (IsOfferer()) { - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - } - - auto offer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, offer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto answer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, answer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - // Attempting to remove a datagram transport on a re-offer does not cause an - // error, but also does not remove the datagram transport. - auto reoffer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kOffer, reoffer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); - - auto reanswer = CreateSessionDescriptionForDatagramTransport(fake_params); - EXPECT_TRUE(SetDescription(SdpType::kAnswer, reanswer.get()).ok()); - - EXPECT_EQ(transport_controller_->GetTransportParameters(kAudioMid1), - fake_params); - EXPECT_EQ(transport_controller_->GetTransportParameters(kVideoMid1), - fake_params); -} - -INSTANTIATE_TEST_SUITE_P( - JsepTransportControllerDatagramTests, - JsepTransportControllerDatagramTest, - testing::Values(true, false), - // The parameter value is the local perspective (offerer or answerer). - [](const testing::TestParamInfo<bool>& info) { - return info.param ? "Offerer" : "Answerer"; - }); - } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/jsep_transport_unittest.cc b/chromium/third_party/webrtc/pc/jsep_transport_unittest.cc index a4b1d5593e3..d8f2fff621b 100644 --- a/chromium/third_party/webrtc/pc/jsep_transport_unittest.cc +++ b/chromium/third_party/webrtc/pc/jsep_transport_unittest.cc @@ -120,9 +120,7 @@ class JsepTransport2Test : public ::testing::Test, public sigslot::has_slots<> { std::move(sdes_transport), std::move(dtls_srtp_transport), /*datagram_rtp_transport=*/nullptr, std::move(rtp_dtls_transport), std::move(rtcp_dtls_transport), - /*sctp_transport=*/nullptr, - /*datagram_transport=*/nullptr, - /*data_channel_transport=*/nullptr); + /*sctp_transport=*/nullptr); signal_rtcp_mux_active_received_ = false; jsep_transport->SignalRtcpMuxActive.connect( diff --git a/chromium/third_party/webrtc/pc/media_session.cc b/chromium/third_party/webrtc/pc/media_session.cc index 51885b4fc42..c03b1bebaaa 100644 --- a/chromium/third_party/webrtc/pc/media_session.cc +++ b/chromium/third_party/webrtc/pc/media_session.cc @@ -55,6 +55,57 @@ void GetSupportedSdesCryptoSuiteNames( } } +webrtc::RtpExtension RtpExtensionFromCapability( + const webrtc::RtpHeaderExtensionCapability& capability) { + return webrtc::RtpExtension(capability.uri, + capability.preferred_id.value_or(1)); +} + +cricket::RtpHeaderExtensions RtpHeaderExtensionsFromCapabilities( + const std::vector<webrtc::RtpHeaderExtensionCapability>& capabilities) { + cricket::RtpHeaderExtensions exts; + for (const auto& capability : capabilities) { + exts.push_back(RtpExtensionFromCapability(capability)); + } + return exts; +} + +std::vector<webrtc::RtpHeaderExtensionCapability> +UnstoppedRtpHeaderExtensionCapabilities( + std::vector<webrtc::RtpHeaderExtensionCapability> capabilities) { + capabilities.erase( + std::remove_if( + capabilities.begin(), capabilities.end(), + [](const webrtc::RtpHeaderExtensionCapability& capability) { + return capability.direction == RtpTransceiverDirection::kStopped; + }), + capabilities.end()); + return capabilities; +} + +bool IsCapabilityPresent(const webrtc::RtpHeaderExtensionCapability& capability, + const cricket::RtpHeaderExtensions& extensions) { + return std::find_if(extensions.begin(), extensions.end(), + [&capability](const webrtc::RtpExtension& extension) { + return capability.uri == extension.uri; + }) != extensions.end(); +} + +cricket::RtpHeaderExtensions UnstoppedOrPresentRtpHeaderExtensions( + const std::vector<webrtc::RtpHeaderExtensionCapability>& capabilities, + const cricket::RtpHeaderExtensions& unencrypted, + const cricket::RtpHeaderExtensions& encrypted) { + cricket::RtpHeaderExtensions extensions; + for (const auto& capability : capabilities) { + if (capability.direction != RtpTransceiverDirection::kStopped || + IsCapabilityPresent(capability, unencrypted) || + IsCapabilityPresent(capability, encrypted)) { + extensions.push_back(RtpExtensionFromCapability(capability)); + } + } + return extensions; +} + } // namespace namespace cricket { @@ -268,19 +319,6 @@ static StreamParamsVec GetCurrentStreamParams( return stream_params; } -// Filters the data codecs for the data channel type. -void FilterDataCodecs(std::vector<DataCodec>* codecs, bool sctp) { - // Filter RTP codec for SCTP and vice versa. - const char* codec_name = - sctp ? kGoogleRtpDataCodecName : kGoogleSctpDataCodecName; - codecs->erase(std::remove_if(codecs->begin(), codecs->end(), - [&codec_name](const DataCodec& codec) { - return absl::EqualsIgnoreCase(codec.name, - codec_name); - }), - codecs->end()); -} - static StreamParams CreateStreamParamsForNewSenderWithSsrcs( const SenderOptions& sender, const std::string& rtcp_cname, @@ -452,15 +490,12 @@ static bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group, selected_transport_info->description.ice_pwd; ConnectionRole selected_connection_role = selected_transport_info->description.connection_role; - const absl::optional<OpaqueTransportParameters>& selected_opaque_parameters = - selected_transport_info->description.opaque_parameters; for (TransportInfo& transport_info : sdesc->transport_infos()) { if (bundle_group.HasContentName(transport_info.content_name) && transport_info.content_name != selected_content_name) { transport_info.description.ice_ufrag = selected_ufrag; transport_info.description.ice_pwd = selected_pwd; transport_info.description.connection_role = selected_connection_role; - transport_info.description.opaque_parameters = selected_opaque_parameters; } } return true; @@ -646,7 +681,21 @@ static bool CreateContentOffer( if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { offer->set_rtcp_reduced_size(true); } - offer->set_rtp_header_extensions(rtp_extensions); + + // Build the vector of header extensions with directions for this + // media_description's options. + RtpHeaderExtensions extensions; + for (auto extension_with_id : rtp_extensions) { + for (const auto& extension : media_description_options.header_extensions) { + if (extension_with_id.uri == extension.uri) { + // TODO(crbug.com/1051821): Configure the extension direction from + // the information in the media_description_options extension + // capability. + extensions.push_back(extension_with_id); + } + } + } + offer->set_rtp_header_extensions(extensions); AddSimulcastToMediaDescription(media_description_options, offer); @@ -661,8 +710,6 @@ static bool CreateContentOffer( } } - offer->set_alt_protocol(media_description_options.alt_protocol); - if (secure_policy == SEC_REQUIRED && offer->cryptos().empty()) { return false; } @@ -1178,7 +1225,7 @@ static bool CreateMediaContentAnswer( const MediaSessionOptions& session_options, const SecurePolicy& sdes_policy, const CryptoParamsVec* current_cryptos, - const RtpHeaderExtensions& local_rtp_extenstions, + const RtpHeaderExtensions& local_rtp_extensions, UniqueRandomIdGenerator* ssrc_generator, bool enable_encrypted_rtp_header_extensions, StreamParamsVec* current_streams, @@ -1187,7 +1234,7 @@ static bool CreateMediaContentAnswer( answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum()); RtpHeaderExtensions negotiated_rtp_extensions; NegotiateRtpHeaderExtensions( - local_rtp_extenstions, offer->rtp_header_extensions(), + local_rtp_extensions, offer->rtp_header_extensions(), enable_encrypted_rtp_header_extensions, &negotiated_rtp_extensions); answer->set_rtp_header_extensions(negotiated_rtp_extensions); @@ -1218,9 +1265,6 @@ static bool CreateMediaContentAnswer( answer->set_direction(NegotiateRtpTransceiverDirection( offer->direction(), media_description_options.direction)); - if (offer->alt_protocol() == media_description_options.alt_protocol) { - answer->set_alt_protocol(media_description_options.alt_protocol); - } return true; } @@ -1365,12 +1409,8 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( : MediaSessionDescriptionFactory(transport_desc_factory, ssrc_generator) { channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_); channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_); - audio_rtp_extensions_ = - channel_manager->GetDefaultEnabledAudioRtpHeaderExtensions(); channel_manager->GetSupportedVideoSendCodecs(&video_send_codecs_); channel_manager->GetSupportedVideoReceiveCodecs(&video_recv_codecs_); - video_rtp_extensions_ = - channel_manager->GetDefaultEnabledVideoRtpHeaderExtensions(); channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_); ComputeAudioCodecsIntersectionAndUnion(); ComputeVideoCodecsIntersectionAndUnion(); @@ -1433,22 +1473,11 @@ static void RemoveUnifiedPlanExtensions(RtpHeaderExtensions* extensions) { } RtpHeaderExtensions -MediaSessionDescriptionFactory::audio_rtp_header_extensions() const { - RtpHeaderExtensions extensions = audio_rtp_extensions_; +MediaSessionDescriptionFactory::filtered_rtp_header_extensions( + RtpHeaderExtensions extensions) const { if (!is_unified_plan_) { RemoveUnifiedPlanExtensions(&extensions); } - - return extensions; -} - -RtpHeaderExtensions -MediaSessionDescriptionFactory::video_rtp_header_extensions() const { - RtpHeaderExtensions extensions = video_rtp_extensions_; - if (!is_unified_plan_) { - RemoveUnifiedPlanExtensions(&extensions); - } - return extensions; } @@ -1483,14 +1512,10 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer( // If application doesn't want CN codecs in offer. StripCNCodecs(&offer_audio_codecs); } - FilterDataCodecs(&offer_rtp_data_codecs, - session_options.data_channel_type == DCT_SCTP); - - RtpHeaderExtensions audio_rtp_extensions; - RtpHeaderExtensions video_rtp_extensions; - GetRtpHdrExtsToOffer(current_active_contents, - session_options.offer_extmap_allow_mixed, - &audio_rtp_extensions, &video_rtp_extensions); + AudioVideoRtpHeaderExtensions extensions_with_ids = + GetOfferedRtpHeaderExtensionsWithIds( + current_active_contents, session_options.offer_extmap_allow_mixed, + session_options.media_description_options); auto offer = std::make_unique<SessionDescription>(); @@ -1510,18 +1535,20 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer( } switch (media_description_options.type) { case MEDIA_TYPE_AUDIO: - if (!AddAudioContentForOffer( - media_description_options, session_options, current_content, - current_description, audio_rtp_extensions, offer_audio_codecs, - ¤t_streams, offer.get(), &ice_credentials)) { + if (!AddAudioContentForOffer(media_description_options, session_options, + current_content, current_description, + extensions_with_ids.audio, + offer_audio_codecs, ¤t_streams, + offer.get(), &ice_credentials)) { return nullptr; } break; case MEDIA_TYPE_VIDEO: - if (!AddVideoContentForOffer( - media_description_options, session_options, current_content, - current_description, video_rtp_extensions, offer_video_codecs, - ¤t_streams, offer.get(), &ice_credentials)) { + if (!AddVideoContentForOffer(media_description_options, session_options, + current_content, current_description, + extensions_with_ids.video, + offer_video_codecs, ¤t_streams, + offer.get(), &ice_credentials)) { return nullptr; } break; @@ -1628,8 +1655,6 @@ MediaSessionDescriptionFactory::CreateAnswer( // If application doesn't want CN codecs in answer. StripCNCodecs(&answer_audio_codecs); } - FilterDataCodecs(&answer_rtp_data_codecs, - session_options.data_channel_type == DCT_SCTP); auto answer = std::make_unique<SessionDescription>(); @@ -1658,13 +1683,16 @@ MediaSessionDescriptionFactory::CreateAnswer( msection_index < current_description->contents().size()) { current_content = ¤t_description->contents()[msection_index]; } + RtpHeaderExtensions header_extensions = RtpHeaderExtensionsFromCapabilities( + UnstoppedRtpHeaderExtensionCapabilities( + media_description_options.header_extensions)); switch (media_description_options.type) { case MEDIA_TYPE_AUDIO: if (!AddAudioContentForAnswer( media_description_options, session_options, offer_content, offer, current_content, current_description, - bundle_transport.get(), answer_audio_codecs, ¤t_streams, - answer.get(), &ice_credentials)) { + bundle_transport.get(), answer_audio_codecs, header_extensions, + ¤t_streams, answer.get(), &ice_credentials)) { return nullptr; } break; @@ -1672,8 +1700,8 @@ MediaSessionDescriptionFactory::CreateAnswer( if (!AddVideoContentForAnswer( media_description_options, session_options, offer_content, offer, current_content, current_description, - bundle_transport.get(), answer_video_codecs, ¤t_streams, - answer.get(), &ice_credentials)) { + bundle_transport.get(), answer_video_codecs, header_extensions, + ¤t_streams, answer.get(), &ice_credentials)) { return nullptr; } break; @@ -1966,11 +1994,12 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer( &used_pltypes); } -void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( +MediaSessionDescriptionFactory::AudioVideoRtpHeaderExtensions +MediaSessionDescriptionFactory::GetOfferedRtpHeaderExtensionsWithIds( const std::vector<const ContentInfo*>& current_active_contents, bool extmap_allow_mixed, - RtpHeaderExtensions* offer_audio_extensions, - RtpHeaderExtensions* offer_video_extensions) const { + const std::vector<MediaDescriptionOptions>& media_description_options) + const { // All header extensions allocated from the same range to avoid potential // issues when using BUNDLE. @@ -1984,6 +2013,7 @@ void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( RtpHeaderExtensions all_regular_extensions; RtpHeaderExtensions all_encrypted_extensions; + AudioVideoRtpHeaderExtensions offered_extensions; // First - get all extensions from the current description if the media type // is used. // Add them to |used_ids| so the local ids are not reused if a new media @@ -1992,36 +2022,45 @@ void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) { const AudioContentDescription* audio = content->media_description()->as_audio(); - MergeRtpHdrExts(audio->rtp_header_extensions(), offer_audio_extensions, + MergeRtpHdrExts(audio->rtp_header_extensions(), &offered_extensions.audio, &all_regular_extensions, &all_encrypted_extensions, &used_ids); } else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) { const VideoContentDescription* video = content->media_description()->as_video(); - MergeRtpHdrExts(video->rtp_header_extensions(), offer_video_extensions, + MergeRtpHdrExts(video->rtp_header_extensions(), &offered_extensions.video, &all_regular_extensions, &all_encrypted_extensions, &used_ids); } } - // Add our default RTP header extensions that are not in the current - // description. - MergeRtpHdrExts(audio_rtp_header_extensions(), offer_audio_extensions, - &all_regular_extensions, &all_encrypted_extensions, - &used_ids); - MergeRtpHdrExts(video_rtp_header_extensions(), offer_video_extensions, - &all_regular_extensions, &all_encrypted_extensions, - &used_ids); + // Add all encountered header extensions in the media description options that + // are not in the current description. + for (const auto& entry : media_description_options) { + RtpHeaderExtensions filtered_extensions = + filtered_rtp_header_extensions(UnstoppedOrPresentRtpHeaderExtensions( + entry.header_extensions, all_regular_extensions, + all_encrypted_extensions)); + if (entry.type == MEDIA_TYPE_AUDIO) + MergeRtpHdrExts(filtered_extensions, &offered_extensions.audio, + &all_regular_extensions, &all_encrypted_extensions, + &used_ids); + else if (entry.type == MEDIA_TYPE_VIDEO) + MergeRtpHdrExts(filtered_extensions, &offered_extensions.video, + &all_regular_extensions, &all_encrypted_extensions, + &used_ids); + } // TODO(jbauch): Support adding encrypted header extensions to existing // sessions. if (enable_encrypted_rtp_header_extensions_ && current_active_contents.empty()) { - AddEncryptedVersionsOfHdrExts(offer_audio_extensions, + AddEncryptedVersionsOfHdrExts(&offered_extensions.audio, &all_encrypted_extensions, &used_ids); - AddEncryptedVersionsOfHdrExts(offer_video_extensions, + AddEncryptedVersionsOfHdrExts(&offered_extensions.video, &all_encrypted_extensions, &used_ids); } + return offered_extensions; } bool MediaSessionDescriptionFactory::AddTransportOffer( @@ -2396,6 +2435,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( const SessionDescription* current_description, const TransportInfo* bundle_transport, const AudioCodecs& audio_codecs, + const RtpHeaderExtensions& default_audio_rtp_header_extensions, StreamParamsVec* current_streams, SessionDescription* answer, IceCredentialsIterator* ice_credentials) const { @@ -2468,9 +2508,9 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( if (!CreateMediaContentAnswer( offer_audio_description, media_description_options, session_options, sdes_policy, GetCryptos(current_content), - audio_rtp_header_extensions(), ssrc_generator_, - enable_encrypted_rtp_header_extensions_, current_streams, - bundle_enabled, audio_answer.get())) { + filtered_rtp_header_extensions(default_audio_rtp_header_extensions), + ssrc_generator_, enable_encrypted_rtp_header_extensions_, + current_streams, bundle_enabled, audio_answer.get())) { return false; // Fails the session setup. } @@ -2506,6 +2546,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( const SessionDescription* current_description, const TransportInfo* bundle_transport, const VideoCodecs& video_codecs, + const RtpHeaderExtensions& default_video_rtp_header_extensions, StreamParamsVec* current_streams, SessionDescription* answer, IceCredentialsIterator* ice_credentials) const { @@ -2586,9 +2627,9 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( if (!CreateMediaContentAnswer( offer_video_description, media_description_options, session_options, sdes_policy, GetCryptos(current_content), - video_rtp_header_extensions(), ssrc_generator_, - enable_encrypted_rtp_header_extensions_, current_streams, - bundle_enabled, video_answer.get())) { + filtered_rtp_header_extensions(default_video_rtp_header_extensions), + ssrc_generator_, enable_encrypted_rtp_header_extensions_, + current_streams, bundle_enabled, video_answer.get())) { return false; // Failed the sessin setup. } bool secure = bundle_transport ? bundle_transport->description.secure() diff --git a/chromium/third_party/webrtc/pc/media_session.h b/chromium/third_party/webrtc/pc/media_session.h index ef83834318f..f305a6214ca 100644 --- a/chromium/third_party/webrtc/pc/media_session.h +++ b/chromium/third_party/webrtc/pc/media_session.h @@ -78,7 +78,7 @@ struct MediaDescriptionOptions { // stream information goes in the local descriptions. std::vector<SenderOptions> sender_options; std::vector<webrtc::RtpCodecCapability> codec_preferences; - absl::optional<std::string> alt_protocol; + std::vector<webrtc::RtpHeaderExtensionCapability> header_extensions; private: // Doesn't DCHECK on |type|. @@ -147,19 +147,13 @@ class MediaSessionDescriptionFactory { const AudioCodecs& audio_recv_codecs() const; void set_audio_codecs(const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs); - void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) { - audio_rtp_extensions_ = extensions; - } - RtpHeaderExtensions audio_rtp_header_extensions() const; const VideoCodecs& video_sendrecv_codecs() const; const VideoCodecs& video_send_codecs() const; const VideoCodecs& video_recv_codecs() const; void set_video_codecs(const VideoCodecs& send_codecs, const VideoCodecs& recv_codecs); - void set_video_rtp_header_extensions(const RtpHeaderExtensions& extensions) { - video_rtp_extensions_ = extensions; - } - RtpHeaderExtensions video_rtp_header_extensions() const; + RtpHeaderExtensions filtered_rtp_header_extensions( + RtpHeaderExtensions extensions) const; const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; } void set_rtp_data_codecs(const RtpDataCodecs& codecs) { rtp_data_codecs_ = codecs; @@ -184,6 +178,11 @@ class MediaSessionDescriptionFactory { const SessionDescription* current_description) const; private: + struct AudioVideoRtpHeaderExtensions { + RtpHeaderExtensions audio; + RtpHeaderExtensions video; + }; + const AudioCodecs& GetAudioCodecsForOffer( const webrtc::RtpTransceiverDirection& direction) const; const AudioCodecs& GetAudioCodecsForAnswer( @@ -205,11 +204,11 @@ class MediaSessionDescriptionFactory { AudioCodecs* audio_codecs, VideoCodecs* video_codecs, RtpDataCodecs* rtp_data_codecs) const; - void GetRtpHdrExtsToOffer( + AudioVideoRtpHeaderExtensions GetOfferedRtpHeaderExtensionsWithIds( const std::vector<const ContentInfo*>& current_active_contents, bool extmap_allow_mixed, - RtpHeaderExtensions* audio_extensions, - RtpHeaderExtensions* video_extensions) const; + const std::vector<MediaDescriptionOptions>& media_description_options) + const; bool AddTransportOffer(const std::string& content_name, const TransportOptions& transport_options, const SessionDescription* current_desc, @@ -293,6 +292,7 @@ class MediaSessionDescriptionFactory { const SessionDescription* current_description, const TransportInfo* bundle_transport, const AudioCodecs& audio_codecs, + const RtpHeaderExtensions& default_audio_rtp_header_extensions, StreamParamsVec* current_streams, SessionDescription* answer, IceCredentialsIterator* ice_credentials) const; @@ -306,6 +306,7 @@ class MediaSessionDescriptionFactory { const SessionDescription* current_description, const TransportInfo* bundle_transport, const VideoCodecs& video_codecs, + const RtpHeaderExtensions& default_video_rtp_header_extensions, StreamParamsVec* current_streams, SessionDescription* answer, IceCredentialsIterator* ice_credentials) const; @@ -334,14 +335,12 @@ class MediaSessionDescriptionFactory { AudioCodecs audio_sendrecv_codecs_; // Union of send and recv. AudioCodecs all_audio_codecs_; - RtpHeaderExtensions audio_rtp_extensions_; VideoCodecs video_send_codecs_; VideoCodecs video_recv_codecs_; // Intersection of send and recv. VideoCodecs video_sendrecv_codecs_; // Union of send and recv. VideoCodecs all_video_codecs_; - RtpHeaderExtensions video_rtp_extensions_; RtpDataCodecs rtp_data_codecs_; // This object is not owned by the channel so it must outlive it. rtc::UniqueRandomIdGenerator* const ssrc_generator_; diff --git a/chromium/third_party/webrtc/pc/media_session_unittest.cc b/chromium/third_party/webrtc/pc/media_session_unittest.cc index ba4db0a674b..ac949fb6301 100644 --- a/chromium/third_party/webrtc/pc/media_session_unittest.cc +++ b/chromium/third_party/webrtc/pc/media_session_unittest.cc @@ -541,9 +541,6 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test { EXPECT_EQ( media_desc_options_it->transport_options.enable_ice_renomination, GetIceRenomination(ti_audio)); - EXPECT_EQ(media_desc_options_it->transport_options.opaque_parameters, - ti_audio->description.opaque_parameters); - } else { EXPECT_TRUE(ti_audio == NULL); } @@ -556,8 +553,6 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test { EXPECT_EQ(ti_audio->description.ice_ufrag, ti_video->description.ice_ufrag); EXPECT_EQ(ti_audio->description.ice_pwd, ti_video->description.ice_pwd); - EXPECT_EQ(ti_audio->description.opaque_parameters, - ti_video->description.opaque_parameters); } else { if (has_current_desc) { EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag); @@ -568,8 +563,6 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test { EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH), ti_video->description.ice_pwd.size()); } - EXPECT_EQ(media_desc_options_it->transport_options.opaque_parameters, - ti_video->description.opaque_parameters); } EXPECT_EQ( media_desc_options_it->transport_options.enable_ice_renomination, @@ -754,13 +747,10 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test { const cricket::RtpHeaderExtensions& expectedAnswer) { MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); - f1_.set_audio_rtp_header_extensions(offered); - f1_.set_video_rtp_header_extensions(offered); - f2_.set_audio_rtp_header_extensions(local); - f2_.set_video_rtp_header_extensions(local); - + SetAudioVideoRtpHeaderExtensions(offered, offered, &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); ASSERT_TRUE(offer.get() != NULL); + SetAudioVideoRtpHeaderExtensions(local, local, &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); @@ -772,6 +762,38 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test { GetFirstVideoContentDescription(answer.get())->rtp_header_extensions()); } + std::vector<webrtc::RtpHeaderExtensionCapability> + HeaderExtensionCapabilitiesFromRtpExtensions( + cricket::RtpHeaderExtensions extensions) { + std::vector<webrtc::RtpHeaderExtensionCapability> capabilities; + for (const auto& extension : extensions) { + webrtc::RtpHeaderExtensionCapability capability( + extension.uri, extension.id, + webrtc::RtpTransceiverDirection::kSendRecv); + capabilities.push_back(capability); + } + return capabilities; + } + + void SetAudioVideoRtpHeaderExtensions(cricket::RtpHeaderExtensions audio_exts, + cricket::RtpHeaderExtensions video_exts, + MediaSessionOptions* opts) { + auto audio_caps = HeaderExtensionCapabilitiesFromRtpExtensions(audio_exts); + auto video_caps = HeaderExtensionCapabilitiesFromRtpExtensions(video_exts); + for (auto& entry : opts->media_description_options) { + switch (entry.type) { + case MEDIA_TYPE_AUDIO: + entry.header_extensions = audio_caps; + break; + case MEDIA_TYPE_VIDEO: + entry.header_extensions = video_caps; + break; + default: + break; + } + } + } + protected: UniqueRandomIdGenerator ssrc_generator1; UniqueRandomIdGenerator ssrc_generator2; @@ -1659,13 +1681,13 @@ TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) { TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) { MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); - f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1)); - f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1)); - f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2)); - f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2)); + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), + MAKE_VECTOR(kVideoRtpExtension1), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); ASSERT_TRUE(offer.get() != NULL); + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2), + MAKE_VECTOR(kVideoRtpExtension2), &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); @@ -1714,21 +1736,21 @@ TEST_F(MediaSessionDescriptionFactoryTest, MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); - const auto offered = MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00); - f1_.set_audio_rtp_header_extensions(offered); - f1_.set_video_rtp_header_extensions(offered); - const auto local = MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01); - f2_.set_audio_rtp_header_extensions(local); - f2_.set_video_rtp_header_extensions(local); + SetAudioVideoRtpHeaderExtensions( + MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), + MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); + SetAudioVideoRtpHeaderExtensions( + MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), + MAKE_VECTOR(kRtpExtensionTransportSequenceNumber01), &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(), - ElementsAreArray(offered)); + ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); EXPECT_THAT( GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(), - ElementsAreArray(offered)); + ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); } TEST_F(MediaSessionDescriptionFactoryTest, @@ -1736,21 +1758,18 @@ TEST_F(MediaSessionDescriptionFactoryTest, MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); - const auto offered = MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00); - f1_.set_audio_rtp_header_extensions(offered); - f1_.set_video_rtp_header_extensions(offered); - const auto local = MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00); - f2_.set_audio_rtp_header_extensions(local); - f2_.set_video_rtp_header_extensions(local); + SetAudioVideoRtpHeaderExtensions( + MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), + MAKE_VECTOR(kRtpExtensionGenericFrameDescriptorUri00), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( GetFirstAudioContentDescription(answer.get())->rtp_header_extensions(), - ElementsAreArray(offered)); + ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); EXPECT_THAT( GetFirstVideoContentDescription(answer.get())->rtp_header_extensions(), - ElementsAreArray(offered)); + ElementsAreArray(kRtpExtensionGenericFrameDescriptorUri00)); } TEST_F(MediaSessionDescriptionFactoryTest, @@ -1759,10 +1778,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7); - RtpExtension local_tsn(RtpExtension::kTransportSequenceNumberUri, 5); - f1_.set_video_rtp_header_extensions({offer_dd}); - f2_.set_video_rtp_header_extensions({local_tsn}); + SetAudioVideoRtpHeaderExtensions({}, {offer_dd}, &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); + RtpExtension local_tsn(RtpExtension::kTransportSequenceNumberUri, 5); + SetAudioVideoRtpHeaderExtensions({}, {local_tsn}, &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( @@ -1777,9 +1796,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtension offer_dd(RtpExtension::kDependencyDescriptorUri, 7); RtpExtension local_dd(RtpExtension::kDependencyDescriptorUri, 5); - f1_.set_video_rtp_header_extensions({offer_dd}); - f2_.set_video_rtp_header_extensions({local_dd}); + SetAudioVideoRtpHeaderExtensions({}, {offer_dd}, &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); + SetAudioVideoRtpHeaderExtensions({}, {local_dd}, &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( @@ -1796,12 +1815,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)}; const cricket::RtpHeaderExtensions local_extensions = { RtpExtension(RtpExtension::kTransportSequenceNumberUri, 5)}; - f1_.set_video_rtp_header_extensions(offered_extensions); - f1_.set_audio_rtp_header_extensions(offered_extensions); - f2_.set_video_rtp_header_extensions(local_extensions); - f2_.set_audio_rtp_header_extensions(local_extensions); - + SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions, + &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); + SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( @@ -1821,12 +1838,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 7)}; const cricket::RtpHeaderExtensions local_extensions = { RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)}; - f1_.set_video_rtp_header_extensions(offered_extensions); - f1_.set_audio_rtp_header_extensions(offered_extensions); - f2_.set_video_rtp_header_extensions(local_extensions); - f2_.set_audio_rtp_header_extensions(local_extensions); - + SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions, + &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); + SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( @@ -1846,12 +1861,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtension(RtpExtension::kTransportSequenceNumberUri, 7)}; const cricket::RtpHeaderExtensions local_extensions = { RtpExtension(RtpExtension::kAbsoluteCaptureTimeUri, 5)}; - f1_.set_video_rtp_header_extensions(offered_extensions); - f1_.set_audio_rtp_header_extensions(offered_extensions); - f2_.set_video_rtp_header_extensions(local_extensions); - f2_.set_audio_rtp_header_extensions(local_extensions); - + SetAudioVideoRtpHeaderExtensions(offered_extensions, offered_extensions, + &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, nullptr); + SetAudioVideoRtpHeaderExtensions(local_extensions, local_extensions, &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, nullptr); EXPECT_THAT( @@ -1863,6 +1876,203 @@ TEST_F(MediaSessionDescriptionFactoryTest, } TEST_F(MediaSessionDescriptionFactoryTest, + OffersUnstoppedExtensionsWithAudioVideoExtensionStopped) { + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 1, + RtpTransceiverDirection::kStopped), + webrtc::RtpHeaderExtensionCapability("uri2", 3, + RtpTransceiverDirection::kSendOnly)}; + AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 1, + RtpTransceiverDirection::kStopped), + webrtc::RtpHeaderExtensionCapability("uri3", 7, + RtpTransceiverDirection::kSendOnly)}; + auto offer = f1_.CreateOffer(opts, nullptr); + EXPECT_THAT( + offer->contents(), + ElementsAre( + Property(&ContentInfo::media_description, + Pointee(Property( + &MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri2"))))), + Property(&ContentInfo::media_description, + Pointee(Property( + &MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri3"))))))); +} + +TEST_F(MediaSessionDescriptionFactoryTest, + OffersUnstoppedExtensionsWithAudioExtensionStopped) { + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 1, + RtpTransceiverDirection::kSendOnly), + webrtc::RtpHeaderExtensionCapability("uri2", 3, + RtpTransceiverDirection::kStopped)}; + AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri42", 42, + RtpTransceiverDirection::kSendRecv), + webrtc::RtpHeaderExtensionCapability("uri3", 7, + RtpTransceiverDirection::kSendOnly)}; + auto offer = f1_.CreateOffer(opts, nullptr); + EXPECT_THAT( + offer->contents(), + ElementsAre( + Property(&ContentInfo::media_description, + Pointee(Property( + &MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri1"))))), + Property( + &ContentInfo::media_description, + Pointee(Property( + &MediaContentDescription::rtp_header_extensions, + UnorderedElementsAre(Field(&RtpExtension::uri, "uri3"), + Field(&RtpExtension::uri, "uri42"))))))); +} + +TEST_F(MediaSessionDescriptionFactoryTest, + OffersUnstoppedExtensionsWithVideoExtensionStopped) { + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 5, + RtpTransceiverDirection::kSendOnly), + webrtc::RtpHeaderExtensionCapability("uri2", 7, + RtpTransceiverDirection::kSendRecv)}; + AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video1", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri42", 42, + RtpTransceiverDirection::kSendRecv), + webrtc::RtpHeaderExtensionCapability("uri3", 7, + RtpTransceiverDirection::kStopped)}; + auto offer = f1_.CreateOffer(opts, nullptr); + EXPECT_THAT( + offer->contents(), + ElementsAre( + Property( + &ContentInfo::media_description, + Pointee(Property( + &MediaContentDescription::rtp_header_extensions, + UnorderedElementsAre(Field(&RtpExtension::uri, "uri1"), + Field(&RtpExtension::uri, "uri2"))))), + Property(&ContentInfo::media_description, + Pointee(Property( + &MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri42"))))))); +} + +TEST_F(MediaSessionDescriptionFactoryTest, AnswersUnstoppedExtensions) { + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 4, + RtpTransceiverDirection::kStopped), + webrtc::RtpHeaderExtensionCapability("uri2", 3, + RtpTransceiverDirection::kSendOnly), + webrtc::RtpHeaderExtensionCapability("uri3", 2, + RtpTransceiverDirection::kRecvOnly), + webrtc::RtpHeaderExtensionCapability("uri4", 1, + RtpTransceiverDirection::kSendRecv)}; + auto offer = f1_.CreateOffer(opts, nullptr); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 4, + RtpTransceiverDirection::kSendOnly), + webrtc::RtpHeaderExtensionCapability("uri2", 3, + RtpTransceiverDirection::kRecvOnly), + webrtc::RtpHeaderExtensionCapability("uri3", 2, + RtpTransceiverDirection::kStopped), + webrtc::RtpHeaderExtensionCapability("uri4", 1, + RtpTransceiverDirection::kSendRecv)}; + auto answer = f2_.CreateAnswer(offer.get(), opts, nullptr); + EXPECT_THAT( + answer->contents(), + ElementsAre(Property( + &ContentInfo::media_description, + Pointee(Property(&MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri2"), + Field(&RtpExtension::uri, "uri4"))))))); +} + +TEST_F(MediaSessionDescriptionFactoryTest, + AppendsUnstoppedExtensionsToCurrentDescription) { + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_AUDIO, "audio", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 1, + RtpTransceiverDirection::kSendRecv)}; + auto offer = f1_.CreateOffer(opts, nullptr); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 2, + RtpTransceiverDirection::kSendRecv), + webrtc::RtpHeaderExtensionCapability("uri2", 3, + RtpTransceiverDirection::kRecvOnly), + webrtc::RtpHeaderExtensionCapability("uri3", 5, + RtpTransceiverDirection::kStopped), + webrtc::RtpHeaderExtensionCapability("uri4", 6, + RtpTransceiverDirection::kSendRecv)}; + auto offer2 = f1_.CreateOffer(opts, offer.get()); + EXPECT_THAT( + offer2->contents(), + ElementsAre(Property( + &ContentInfo::media_description, + Pointee(Property(&MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri1"), + Field(&RtpExtension::uri, "uri2"), + Field(&RtpExtension::uri, "uri4"))))))); +} + +TEST_F(MediaSessionDescriptionFactoryTest, + AppendsStoppedExtensionIfKnownAndPresentInTheOffer) { + MediaSessionOptions opts; + AddMediaDescriptionOptions(MEDIA_TYPE_VIDEO, "video", + RtpTransceiverDirection::kSendRecv, kActive, + &opts); + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 1, + RtpTransceiverDirection::kSendRecv), + webrtc::RtpHeaderExtensionCapability("uri2", 1, + RtpTransceiverDirection::kSendRecv)}; + auto offer = f1_.CreateOffer(opts, nullptr); + + // Now add "uri2" as stopped to the options verify that the offer contains + // uri2 since it's already present since before. + opts.media_description_options.back().header_extensions = { + webrtc::RtpHeaderExtensionCapability("uri1", 1, + RtpTransceiverDirection::kSendRecv), + webrtc::RtpHeaderExtensionCapability("uri2", 2, + RtpTransceiverDirection::kStopped)}; + auto offer2 = f1_.CreateOffer(opts, offer.get()); + EXPECT_THAT( + offer2->contents(), + ElementsAre(Property( + &ContentInfo::media_description, + Pointee(Property(&MediaContentDescription::rtp_header_extensions, + ElementsAre(Field(&RtpExtension::uri, "uri1"), + Field(&RtpExtension::uri, "uri2"))))))); +} + +TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithEncryptedRtpExtensionsBoth) { MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); @@ -1870,13 +2080,12 @@ TEST_F(MediaSessionDescriptionFactoryTest, f1_.set_enable_encrypted_rtp_header_extensions(true); f2_.set_enable_encrypted_rtp_header_extensions(true); - f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1)); - f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1)); - f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2)); - f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2)); - + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), + MAKE_VECTOR(kVideoRtpExtension1), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); ASSERT_TRUE(offer.get() != NULL); + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2), + MAKE_VECTOR(kVideoRtpExtension2), &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); @@ -1901,13 +2110,12 @@ TEST_F(MediaSessionDescriptionFactoryTest, f1_.set_enable_encrypted_rtp_header_extensions(true); - f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1)); - f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1)); - f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2)); - f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2)); - + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), + MAKE_VECTOR(kVideoRtpExtension1), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); ASSERT_TRUE(offer.get() != NULL); + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2), + MAKE_VECTOR(kVideoRtpExtension2), &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); @@ -1932,13 +2140,12 @@ TEST_F(MediaSessionDescriptionFactoryTest, f2_.set_enable_encrypted_rtp_header_extensions(true); - f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1)); - f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1)); - f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2)); - f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2)); - + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), + MAKE_VECTOR(kVideoRtpExtension1), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); ASSERT_TRUE(offer.get() != NULL); + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2), + MAKE_VECTOR(kVideoRtpExtension2), &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); @@ -3340,12 +3547,11 @@ TEST_F(MediaSessionDescriptionFactoryTest, MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); - f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1)); - f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1)); - f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2)); - f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2)); - + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension1), + MAKE_VECTOR(kVideoRtpExtension1), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension2), + MAKE_VECTOR(kVideoRtpExtension2), &opts); std::unique_ptr<SessionDescription> answer = f2_.CreateAnswer(offer.get(), opts, NULL); @@ -3396,9 +3602,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) { MediaSessionOptions opts; AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &opts); - f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3)); - f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3)); - + SetAudioVideoRtpHeaderExtensions(MAKE_VECTOR(kAudioRtpExtension3), + MAKE_VECTOR(kVideoRtpExtension3), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); // Since the audio extensions used ID 3 for "both_audio_and_video", so should @@ -3435,11 +3640,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) { f1_.set_enable_encrypted_rtp_header_extensions(true); f2_.set_enable_encrypted_rtp_header_extensions(true); - f1_.set_audio_rtp_header_extensions( - MAKE_VECTOR(kAudioRtpExtension3ForEncryption)); - f1_.set_video_rtp_header_extensions( - MAKE_VECTOR(kVideoRtpExtension3ForEncryption)); - + SetAudioVideoRtpHeaderExtensions( + MAKE_VECTOR(kAudioRtpExtension3ForEncryption), + MAKE_VECTOR(kVideoRtpExtension3ForEncryption), &opts); std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL); // The extensions that are shared between audio and video should use the same @@ -3631,164 +3834,6 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfo(false, options, true); } -TEST_F(MediaSessionDescriptionFactoryTest, - TestTransportInfoOfferBundlesTransportOptions) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - - cricket::OpaqueTransportParameters audio_params; - audio_params.protocol = "audio-transport"; - audio_params.parameters = "audio-params"; - FindFirstMediaDescriptionByMid("audio", &options) - ->transport_options.opaque_parameters = audio_params; - - cricket::OpaqueTransportParameters video_params; - video_params.protocol = "video-transport"; - video_params.parameters = "video-params"; - FindFirstMediaDescriptionByMid("video", &options) - ->transport_options.opaque_parameters = video_params; - - TestTransportInfo(/*offer=*/true, options, /*has_current_desc=*/false); -} - -TEST_F(MediaSessionDescriptionFactoryTest, - TestTransportInfoAnswerBundlesTransportOptions) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - - cricket::OpaqueTransportParameters audio_params; - audio_params.protocol = "audio-transport"; - audio_params.parameters = "audio-params"; - FindFirstMediaDescriptionByMid("audio", &options) - ->transport_options.opaque_parameters = audio_params; - - cricket::OpaqueTransportParameters video_params; - video_params.protocol = "video-transport"; - video_params.parameters = "video-params"; - FindFirstMediaDescriptionByMid("video", &options) - ->transport_options.opaque_parameters = video_params; - - TestTransportInfo(/*offer=*/false, options, /*has_current_desc=*/false); -} - -TEST_F(MediaSessionDescriptionFactoryTest, AltProtocolAddedToOffer) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - AddDataSection(cricket::DCT_RTP, RtpTransceiverDirection::kRecvOnly, - &options); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = "foo"; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = "bar"; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = "baz"; - - std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, nullptr); - - EXPECT_EQ(offer->GetContentDescriptionByName("audio")->alt_protocol(), "foo"); - EXPECT_EQ(offer->GetContentDescriptionByName("video")->alt_protocol(), "bar"); - EXPECT_EQ(offer->GetContentDescriptionByName("data")->alt_protocol(), "baz"); -} - -TEST_F(MediaSessionDescriptionFactoryTest, AltProtocolAddedToAnswer) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kRecvOnly, - &options); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = "foo"; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = "bar"; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = "baz"; - - std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, nullptr); - std::unique_ptr<SessionDescription> answer = - f1_.CreateAnswer(offer.get(), options, nullptr); - - EXPECT_EQ(answer->GetContentDescriptionByName("audio")->alt_protocol(), - "foo"); - EXPECT_EQ(answer->GetContentDescriptionByName("video")->alt_protocol(), - "bar"); - EXPECT_EQ(answer->GetContentDescriptionByName("data")->alt_protocol(), "baz"); -} - -TEST_F(MediaSessionDescriptionFactoryTest, AltProtocolNotInOffer) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kRecvOnly, - &options); - - std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, nullptr); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = "foo"; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = "bar"; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = "baz"; - - std::unique_ptr<SessionDescription> answer = - f1_.CreateAnswer(offer.get(), options, nullptr); - - EXPECT_EQ(answer->GetContentDescriptionByName("audio")->alt_protocol(), - absl::nullopt); - EXPECT_EQ(answer->GetContentDescriptionByName("video")->alt_protocol(), - absl::nullopt); - EXPECT_EQ(answer->GetContentDescriptionByName("data")->alt_protocol(), - absl::nullopt); -} - -TEST_F(MediaSessionDescriptionFactoryTest, AltProtocolDifferentInOffer) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kRecvOnly, - &options); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = "not-foo"; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = "not-bar"; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = "not-baz"; - - std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, nullptr); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = "foo"; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = "bar"; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = "baz"; - - std::unique_ptr<SessionDescription> answer = - f1_.CreateAnswer(offer.get(), options, nullptr); - - EXPECT_EQ(answer->GetContentDescriptionByName("audio")->alt_protocol(), - absl::nullopt); - EXPECT_EQ(answer->GetContentDescriptionByName("video")->alt_protocol(), - absl::nullopt); - EXPECT_EQ(answer->GetContentDescriptionByName("data")->alt_protocol(), - absl::nullopt); -} - -TEST_F(MediaSessionDescriptionFactoryTest, AltProtocolNotInAnswer) { - MediaSessionOptions options; - AddAudioVideoSections(RtpTransceiverDirection::kRecvOnly, &options); - AddDataSection(cricket::DCT_SCTP, RtpTransceiverDirection::kRecvOnly, - &options); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = "foo"; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = "bar"; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = "baz"; - - std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(options, nullptr); - - FindFirstMediaDescriptionByMid("audio", &options)->alt_protocol = - absl::nullopt; - FindFirstMediaDescriptionByMid("video", &options)->alt_protocol = - absl::nullopt; - FindFirstMediaDescriptionByMid("data", &options)->alt_protocol = - absl::nullopt; - - std::unique_ptr<SessionDescription> answer = - f1_.CreateAnswer(offer.get(), options, nullptr); - - EXPECT_EQ(answer->GetContentDescriptionByName("audio")->alt_protocol(), - absl::nullopt); - EXPECT_EQ(answer->GetContentDescriptionByName("video")->alt_protocol(), - absl::nullopt); - EXPECT_EQ(answer->GetContentDescriptionByName("data")->alt_protocol(), - absl::nullopt); -} - // Create an offer with bundle enabled and verify the crypto parameters are // the common set of the available cryptos. TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) { @@ -4599,7 +4644,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) { // properly. send_codecs[1].channels = 0; - // Alther iLBC receive codec to be lowercase, to test that case conversions + // Alter iLBC receive codec to be lowercase, to test that case conversions // are handled properly. recv_codecs[2].name = "ilbc"; diff --git a/chromium/third_party/webrtc/pc/media_stream_unittest.cc b/chromium/third_party/webrtc/pc/media_stream_unittest.cc index b70171dfcba..55226992e09 100644 --- a/chromium/third_party/webrtc/pc/media_stream_unittest.cc +++ b/chromium/third_party/webrtc/pc/media_stream_unittest.cc @@ -46,7 +46,7 @@ class MockObserver : public ObserverInterface { } } - MOCK_METHOD0(OnChanged, void()); + MOCK_METHOD(void, OnChanged, (), (override)); private: NotifierInterface* notifier_; diff --git a/chromium/third_party/webrtc/pc/peer_connection.cc b/chromium/third_party/webrtc/pc/peer_connection.cc index 05e7b95591e..1bf937359f3 100644 --- a/chromium/third_party/webrtc/pc/peer_connection.cc +++ b/chromium/third_party/webrtc/pc/peer_connection.cc @@ -107,13 +107,6 @@ const char kDtlsSrtpSetupFailureRtcp[] = namespace { -// Field trials. -// Controls datagram transport support. -const char kDatagramTransportFieldTrial[] = "WebRTC-DatagramTransport"; -// Controls datagram transport data channel support. -const char kDatagramTransportDataChannelFieldTrial[] = - "WebRTC-DatagramTransportDataChannels"; - // UMA metric names. const char kSimulcastVersionApplyLocalDescription[] = "WebRTC.PeerConnection.Simulcast.ApplyLocalDescription"; @@ -690,6 +683,26 @@ class CreateSessionDescriptionObserverOperationWrapper std::function<void()> operation_complete_callback_; }; +// Check if the changes of IceTransportsType motives an ice restart. +bool NeedIceRestart(bool surface_ice_candidates_on_ice_transport_type_changed, + PeerConnectionInterface::IceTransportsType current, + PeerConnectionInterface::IceTransportsType modified) { + if (current == modified) { + return false; + } + + if (!surface_ice_candidates_on_ice_transport_type_changed) { + return true; + } + + auto current_filter = ConvertIceTransportTypeToCandidateFilter(current); + auto modified_filter = ConvertIceTransportTypeToCandidateFilter(modified); + + // If surface_ice_candidates_on_ice_transport_type_changed is true and we + // extend the filter, then no ice restart is needed. + return (current_filter & modified_filter) != current_filter; +} + } // namespace // Used by parameterless SetLocalDescription() to create an offer or answer. @@ -896,11 +909,6 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( SdpSemantics sdp_semantics; absl::optional<rtc::AdapterType> network_preference; bool active_reset_srtp_params; - bool use_media_transport; - bool use_media_transport_for_data_channels; - absl::optional<bool> use_datagram_transport; - absl::optional<bool> use_datagram_transport_for_data_channels; - absl::optional<bool> use_datagram_transport_for_data_channels_receive_only; absl::optional<CryptoOptions> crypto_options; bool offer_extmap_allow_mixed; std::string turn_logging_id; @@ -961,20 +969,11 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( sdp_semantics == o.sdp_semantics && network_preference == o.network_preference && active_reset_srtp_params == o.active_reset_srtp_params && - use_media_transport == o.use_media_transport && - use_media_transport_for_data_channels == - o.use_media_transport_for_data_channels && - use_datagram_transport == o.use_datagram_transport && - use_datagram_transport_for_data_channels == - o.use_datagram_transport_for_data_channels && - use_datagram_transport_for_data_channels_receive_only == - o.use_datagram_transport_for_data_channels_receive_only && crypto_options == o.crypto_options && offer_extmap_allow_mixed == o.offer_extmap_allow_mixed && turn_logging_id == o.turn_logging_id && enable_implicit_rollback == o.enable_implicit_rollback && - allow_codec_switching == o.allow_codec_switching && - enable_simulcast_stats == o.enable_simulcast_stats; + allow_codec_switching == o.allow_codec_switching; } bool PeerConnectionInterface::RTCConfiguration::operator!=( @@ -1034,14 +1033,11 @@ void ExtractSharedMediaSessionOptions( PeerConnection::PeerConnection(PeerConnectionFactory* factory, std::unique_ptr<RtcEventLog> event_log, std::unique_ptr<Call> call) - : factory_(factory), + : MessageHandler(false), + factory_(factory), event_log_(std::move(event_log)), event_log_ptr_(event_log_.get()), operations_chain_(rtc::OperationsChain::Create()), - datagram_transport_config_( - field_trial::FindFullName(kDatagramTransportFieldTrial)), - datagram_transport_data_channel_config_( - field_trial::FindFullName(kDatagramTransportDataChannelFieldTrial)), rtcp_cname_(GenerateRtcpCname()), local_streams_(StreamCollection::Create()), remote_streams_(StreamCollection::Create()), @@ -1246,33 +1242,6 @@ bool PeerConnection::Initialize( #endif config.active_reset_srtp_params = configuration.active_reset_srtp_params; - use_datagram_transport_ = datagram_transport_config_.enabled && - configuration.use_datagram_transport.value_or( - datagram_transport_config_.default_value); - use_datagram_transport_for_data_channels_ = - datagram_transport_data_channel_config_.enabled && - configuration.use_datagram_transport_for_data_channels.value_or( - datagram_transport_data_channel_config_.default_value); - use_datagram_transport_for_data_channels_receive_only_ = - configuration.use_datagram_transport_for_data_channels_receive_only - .value_or(datagram_transport_data_channel_config_.receive_only); - if (use_datagram_transport_ || use_datagram_transport_for_data_channels_) { - if (!factory_->media_transport_factory()) { - RTC_DCHECK(false) - << "PeerConnecton is initialized with use_datagram_transport = true " - "or use_datagram_transport_for_data_channels = true " - "but media transport factory is not set in PeerConnectionFactory"; - return false; - } - - config.use_datagram_transport = use_datagram_transport_; - config.use_datagram_transport_for_data_channels = - use_datagram_transport_for_data_channels_; - config.use_datagram_transport_for_data_channels_receive_only = - use_datagram_transport_for_data_channels_receive_only_; - config.media_transport_factory = factory_->media_transport_factory(); - } - // Obtain a certificate from RTCConfiguration if any were provided (optional). rtc::scoped_refptr<rtc::RTCCertificate> certificate; if (!configuration.certificates.empty()) { @@ -1295,24 +1264,7 @@ bool PeerConnection::Initialize( sctp_factory_ = factory_->CreateSctpTransportInternalFactory(); - if (use_datagram_transport_for_data_channels_) { - if (configuration.enable_rtp_data_channel) { - RTC_LOG(LS_ERROR) << "enable_rtp_data_channel and " - "use_datagram_transport_for_data_channels are " - "incompatible and cannot both be set to true"; - return false; - } - if (configuration.enable_dtls_srtp && !*configuration.enable_dtls_srtp) { - RTC_LOG(LS_INFO) << "Using data channel transport with no fallback"; - data_channel_controller_.set_data_channel_type( - cricket::DCT_DATA_CHANNEL_TRANSPORT); - } else { - RTC_LOG(LS_INFO) << "Using data channel transport with fallback to SCTP"; - data_channel_controller_.set_data_channel_type( - cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP); - config.sctp_factory = sctp_factory_.get(); - } - } else if (configuration.enable_rtp_data_channel) { + if (configuration.enable_rtp_data_channel) { // Enable creation of RTP data channels if the kEnableRtpDataChannels is // set. It takes precendence over the disable_sctp_data_channels // PeerConnectionFactoryInterface::Options. @@ -2179,7 +2131,7 @@ rtc::scoped_refptr<DataChannelInterface> PeerConnection::CreateDataChannel( if (config) { internal_config.reset(new InternalDataChannelInit(*config)); } - rtc::scoped_refptr<DataChannelInterface> channel( + rtc::scoped_refptr<DataChannel> channel( data_channel_controller_.InternalCreateDataChannel( label, internal_config.get())); if (!channel.get()) { @@ -2192,7 +2144,7 @@ rtc::scoped_refptr<DataChannelInterface> PeerConnection::CreateDataChannel( UpdateNegotiationNeeded(); } NoteUsageEvent(UsageEvent::DATA_ADDED); - return DataChannelProxy::Create(signaling_thread(), channel.get()); + return DataChannel::CreateProxy(std::move(channel)); } void PeerConnection::RestartIce() { @@ -3937,66 +3889,6 @@ RTCError PeerConnection::SetConfiguration( "SetLocalDescription."); } - if (local_description() && configuration.use_datagram_transport != - configuration_.use_datagram_transport) { - LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION, - "Can't change use_datagram_transport " - "after calling SetLocalDescription."); - } - - if (remote_description() && configuration.use_datagram_transport != - configuration_.use_datagram_transport) { - LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION, - "Can't change use_datagram_transport " - "after calling SetRemoteDescription."); - } - - if (local_description() && - configuration.use_datagram_transport_for_data_channels != - configuration_.use_datagram_transport_for_data_channels) { - LOG_AND_RETURN_ERROR( - RTCErrorType::INVALID_MODIFICATION, - "Can't change use_datagram_transport_for_data_channels " - "after calling SetLocalDescription."); - } - - if (remote_description() && - configuration.use_datagram_transport_for_data_channels != - configuration_.use_datagram_transport_for_data_channels) { - LOG_AND_RETURN_ERROR( - RTCErrorType::INVALID_MODIFICATION, - "Can't change use_datagram_transport_for_data_channels " - "after calling SetRemoteDescription."); - } - - if (local_description() && - configuration.use_datagram_transport_for_data_channels_receive_only != - configuration_ - .use_datagram_transport_for_data_channels_receive_only) { - LOG_AND_RETURN_ERROR( - RTCErrorType::INVALID_MODIFICATION, - "Can't change use_datagram_transport_for_data_channels_receive_only " - "after calling SetLocalDescription."); - } - - if (remote_description() && - configuration.use_datagram_transport_for_data_channels_receive_only != - configuration_ - .use_datagram_transport_for_data_channels_receive_only) { - LOG_AND_RETURN_ERROR( - RTCErrorType::INVALID_MODIFICATION, - "Can't change use_datagram_transport_for_data_channels_receive_only " - "after calling SetRemoteDescription."); - } - - if ((configuration.use_datagram_transport && - *configuration.use_datagram_transport) || - (configuration.use_datagram_transport_for_data_channels && - *configuration.use_datagram_transport_for_data_channels)) { - RTC_CHECK(configuration.bundle_policy == kBundlePolicyMaxBundle) - << "Media transport requires MaxBundle policy."; - } - // The simplest (and most future-compatible) way to tell if the config was // modified in an invalid way is to copy each property we do support // modifying, then use operator==. There are far more properties we don't @@ -4025,11 +3917,6 @@ RTCError PeerConnection::SetConfiguration( modified_config.network_preference = configuration.network_preference; modified_config.active_reset_srtp_params = configuration.active_reset_srtp_params; - modified_config.use_datagram_transport = configuration.use_datagram_transport; - modified_config.use_datagram_transport_for_data_channels = - configuration.use_datagram_transport_for_data_channels; - modified_config.use_datagram_transport_for_data_channels_receive_only = - configuration.use_datagram_transport_for_data_channels_receive_only; modified_config.turn_logging_id = configuration.turn_logging_id; modified_config.allow_codec_switching = configuration.allow_codec_switching; if (configuration != modified_config) { @@ -4089,7 +3976,9 @@ RTCError PeerConnection::SetConfiguration( // candidate policy must set a "needs-ice-restart" bit so that the next offer // triggers an ICE restart which will pick up the changes. if (modified_config.servers != configuration_.servers || - modified_config.type != configuration_.type || + NeedIceRestart( + configuration_.surface_ice_candidates_on_ice_transport_type_changed, + configuration_.type, modified_config.type) || modified_config.GetTurnPortPrunePolicy() != configuration_.GetTurnPortPrunePolicy()) { transport_controller_->SetNeedsIceRestartFlag(); @@ -4097,20 +3986,6 @@ RTCError PeerConnection::SetConfiguration( transport_controller_->SetIceConfig(ParseIceConfig(modified_config)); - use_datagram_transport_ = datagram_transport_config_.enabled && - modified_config.use_datagram_transport.value_or( - datagram_transport_config_.default_value); - use_datagram_transport_for_data_channels_ = - datagram_transport_data_channel_config_.enabled && - modified_config.use_datagram_transport_for_data_channels.value_or( - datagram_transport_data_channel_config_.default_value); - use_datagram_transport_for_data_channels_receive_only_ = - modified_config.use_datagram_transport_for_data_channels_receive_only - .value_or(datagram_transport_data_channel_config_.receive_only); - transport_controller_->SetMediaTransportSettings( - use_datagram_transport_, use_datagram_transport_for_data_channels_, - use_datagram_transport_for_data_channels_receive_only_); - if (configuration_.active_reset_srtp_params != modified_config.active_reset_srtp_params) { transport_controller_->SetActiveResetSrtpParams( @@ -4348,6 +4223,21 @@ PeerConnection::GetFirstAudioTransceiver() const { return nullptr; } +void PeerConnection::AddAdaptationResource( + rtc::scoped_refptr<Resource> resource) { + if (!worker_thread()->IsCurrent()) { + return worker_thread()->Invoke<void>(RTC_FROM_HERE, [this, resource]() { + return AddAdaptationResource(resource); + }); + } + RTC_DCHECK_RUN_ON(worker_thread()); + if (!call_) { + // The PeerConnection has been closed. + return; + } + call_->AddAdaptationResource(resource); +} + bool PeerConnection::StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output, int64_t output_period_ms) { return worker_thread()->Invoke<bool>( @@ -4910,25 +4800,6 @@ void PeerConnection::GetOptionsForOffer( session_options->offer_extmap_allow_mixed = configuration_.offer_extmap_allow_mixed; - // If datagram transport is in use, add opaque transport parameters. - if (use_datagram_transport_ || use_datagram_transport_for_data_channels_) { - for (auto& options : session_options->media_description_options) { - absl::optional<cricket::OpaqueTransportParameters> params = - transport_controller_->GetTransportParameters(options.mid); - if (!params) { - continue; - } - options.transport_options.opaque_parameters = params; - if ((use_datagram_transport_ && - (options.type == cricket::MEDIA_TYPE_AUDIO || - options.type == cricket::MEDIA_TYPE_VIDEO)) || - (use_datagram_transport_for_data_channels_ && - options.type == cricket::MEDIA_TYPE_DATA)) { - options.alt_protocol = params->protocol; - } - } - } - // Allow fallback for using obsolete SCTP syntax. // Note that the default in |session_options| is true, while // the default in |options| is false. @@ -4984,21 +4855,21 @@ void PeerConnection::GetOptionsForPlanBOffer( // Add audio/video/data m= sections to the end if needed. if (!audio_index && offer_new_audio_description) { - session_options->media_description_options.push_back( - cricket::MediaDescriptionOptions( - cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, - RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), - false)); - + cricket::MediaDescriptionOptions options( + cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, + RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), false); + options.header_extensions = + channel_manager()->GetSupportedAudioRtpHeaderExtensions(); + session_options->media_description_options.push_back(options); audio_index = session_options->media_description_options.size() - 1; } if (!video_index && offer_new_video_description) { - session_options->media_description_options.push_back( - cricket::MediaDescriptionOptions( - cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, - RtpTransceiverDirectionFromSendRecv(send_video, recv_video), - false)); - + cricket::MediaDescriptionOptions options( + cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, + RtpTransceiverDirectionFromSendRecv(send_video, recv_video), false); + options.header_extensions = + channel_manager()->GetSupportedVideoRtpHeaderExtensions(); + session_options->media_description_options.push_back(options); video_index = session_options->media_description_options.size() - 1; } if (!data_index && offer_new_data_description) { @@ -5030,6 +4901,8 @@ GetMediaDescriptionOptionsForTransceiver( transceiver->stopped()); media_description_options.codec_preferences = transceiver->codec_preferences(); + media_description_options.header_extensions = + transceiver->HeaderExtensionsToOffer(); // This behavior is specified in JSEP. The gist is that: // 1. The MSID is included if the RtpTransceiver's direction is sendonly or // sendrecv. @@ -5234,25 +5107,6 @@ void PeerConnection::GetOptionsForAnswer( RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::GetPooledIceCredentials, port_allocator_.get())); - - // If datagram transport is in use, add opaque transport parameters. - if (use_datagram_transport_ || use_datagram_transport_for_data_channels_) { - for (auto& options : session_options->media_description_options) { - absl::optional<cricket::OpaqueTransportParameters> params = - transport_controller_->GetTransportParameters(options.mid); - if (!params) { - continue; - } - options.transport_options.opaque_parameters = params; - if ((use_datagram_transport_ && - (options.type == cricket::MEDIA_TYPE_AUDIO || - options.type == cricket::MEDIA_TYPE_VIDEO)) || - (use_datagram_transport_for_data_channels_ && - options.type == cricket::MEDIA_TYPE_DATA)) { - options.alt_protocol = params->protocol; - } - } - } } void PeerConnection::GetOptionsForPlanBAnswer( @@ -5361,6 +5215,8 @@ void PeerConnection::GenerateMediaDescriptionOptions( stopped)); *audio_index = session_options->media_description_options.size() - 1; } + session_options->media_description_options.back().header_extensions = + channel_manager()->GetSupportedAudioRtpHeaderExtensions(); } else if (IsVideoContent(&content)) { // If we already have an video m= section, reject this extra one. if (*video_index) { @@ -5376,6 +5232,8 @@ void PeerConnection::GenerateMediaDescriptionOptions( stopped)); *video_index = session_options->media_description_options.size() - 1; } + session_options->media_description_options.back().header_extensions = + channel_manager()->GetSupportedVideoRtpHeaderExtensions(); } else { RTC_DCHECK(IsDataContent(&content)); // If we already have an data m= section, reject this extra one. @@ -6188,6 +6046,11 @@ cricket::IceConfig PeerConnection::ParseIceConfig( return ice_config; } +std::vector<DataChannel::Stats> PeerConnection::GetDataChannelStats() const { + RTC_DCHECK_RUN_ON(signaling_thread()); + return data_channel_controller_.GetDataChannelStats(); +} + absl::optional<std::string> PeerConnection::sctp_transport_name() const { RTC_DCHECK_RUN_ON(signaling_thread()); if (sctp_mid_s_ && transport_controller_) { @@ -6612,13 +6475,11 @@ RTCError PeerConnection::CreateChannels(const SessionDescription& desc) { cricket::VoiceChannel* PeerConnection::CreateVoiceChannel( const std::string& mid) { RtpTransportInternal* rtp_transport = GetRtpTransport(mid); - MediaTransportConfig media_transport_config = - transport_controller_->GetMediaTransportConfig(mid); cricket::VoiceChannel* voice_channel = channel_manager()->CreateVoiceChannel( - call_ptr_, configuration_.media_config, rtp_transport, - media_transport_config, signaling_thread(), mid, SrtpRequired(), - GetCryptoOptions(), &ssrc_generator_, audio_options_); + call_ptr_, configuration_.media_config, rtp_transport, signaling_thread(), + mid, SrtpRequired(), GetCryptoOptions(), &ssrc_generator_, + audio_options_); if (!voice_channel) { return nullptr; } @@ -6635,13 +6496,10 @@ cricket::VoiceChannel* PeerConnection::CreateVoiceChannel( cricket::VideoChannel* PeerConnection::CreateVideoChannel( const std::string& mid) { RtpTransportInternal* rtp_transport = GetRtpTransport(mid); - MediaTransportConfig media_transport_config = - transport_controller_->GetMediaTransportConfig(mid); cricket::VideoChannel* video_channel = channel_manager()->CreateVideoChannel( - call_ptr_, configuration_.media_config, rtp_transport, - media_transport_config, signaling_thread(), mid, SrtpRequired(), - GetCryptoOptions(), &ssrc_generator_, video_options_, + call_ptr_, configuration_.media_config, rtp_transport, signaling_thread(), + mid, SrtpRequired(), GetCryptoOptions(), &ssrc_generator_, video_options_, video_bitrate_allocator_factory_.get()); if (!video_channel) { return nullptr; @@ -6668,16 +6526,12 @@ bool PeerConnection::CreateDataChannel(const std::string& mid) { } else { return false; } - - // All non-RTP data channels must initialize |sctp_data_channels_|. - for (const auto& channel : - *data_channel_controller_.sctp_data_channels()) { - channel->OnTransportChannelCreated(); - } return true; case cricket::DCT_RTP: default: RtpTransportInternal* rtp_transport = GetRtpTransport(mid); + // TODO(bugs.webrtc.org/9987): set_rtp_data_channel() should be called on + // the network thread like set_data_channel_transport is. data_channel_controller_.set_rtp_data_channel( channel_manager()->CreateRtpDataChannel( configuration_.media_config, rtp_transport, signaling_thread(), @@ -7090,8 +6944,7 @@ bool PeerConnection::ReadyToUseRemoteCandidate( } bool PeerConnection::SrtpRequired() const { - return !use_datagram_transport_ && - (dtls_enabled_ || + return (dtls_enabled_ || webrtc_session_desc_factory_->SdesPolicy() == cricket::SEC_REQUIRED); } diff --git a/chromium/third_party/webrtc/pc/peer_connection.h b/chromium/third_party/webrtc/pc/peer_connection.h index f3102572fbe..a91dc9c0423 100644 --- a/chromium/third_party/webrtc/pc/peer_connection.h +++ b/chromium/third_party/webrtc/pc/peer_connection.h @@ -237,6 +237,8 @@ class PeerConnection : public PeerConnectionInternal, rtc::scoped_refptr<SctpTransportInterface> GetSctpTransport() const override; + void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) override; + bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output, int64_t output_period_ms) override; bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) override; @@ -278,11 +280,7 @@ class PeerConnection : public PeerConnectionInternal, return data_channel_controller_.rtp_data_channel(); } - std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels() - const override { - RTC_DCHECK_RUN_ON(signaling_thread()); - return *data_channel_controller_.sctp_data_channels(); - } + std::vector<DataChannel::Stats> GetDataChannelStats() const override; absl::optional<std::string> sctp_transport_name() const override; @@ -360,57 +358,6 @@ class PeerConnection : public PeerConnectionInternal, uint32_t first_ssrc; }; - // Field-trial based configuration for datagram transport. - struct DatagramTransportConfig { - explicit DatagramTransportConfig(const std::string& field_trial) - : enabled("enabled", true), default_value("default_value", false) { - ParseFieldTrial({&enabled, &default_value}, field_trial); - } - - // Whether datagram transport support is enabled at all. Defaults to true, - // allowing datagram transport to be used if (a) the application provides a - // factory for it and (b) the configuration specifies its use. This flag - // provides a kill-switch to force-disable datagram transport across all - // applications, without code changes. - FieldTrialFlag enabled; - - // Whether the datagram transport is enabled or disabled by default. - // Defaults to false, meaning that applications must configure use of - // datagram transport through RTCConfiguration. If set to true, - // applications will use the datagram transport by default (but may still - // explicitly configure themselves not to use it through RTCConfiguration). - FieldTrialFlag default_value; - }; - - // Field-trial based configuration for datagram transport data channels. - struct DatagramTransportDataChannelConfig { - explicit DatagramTransportDataChannelConfig(const std::string& field_trial) - : enabled("enabled", true), - default_value("default_value", false), - receive_only("receive_only", false) { - ParseFieldTrial({&enabled, &default_value, &receive_only}, field_trial); - } - - // Whether datagram transport data channel support is enabled at all. - // Defaults to true, allowing datagram transport to be used if (a) the - // application provides a factory for it and (b) the configuration specifies - // its use. This flag provides a kill-switch to force-disable datagram - // transport across all applications, without code changes. - FieldTrialFlag enabled; - - // Whether the datagram transport data channels are enabled or disabled by - // default. Defaults to false, meaning that applications must configure use - // of datagram transport through RTCConfiguration. If set to true, - // applications will use the datagram transport by default (but may still - // explicitly configure themselves not to use it through RTCConfiguration). - FieldTrialFlag default_value; - - // Whether the datagram transport is enabled in receive-only mode. If true, - // and if the datagram transport is enabled, it will only be used when - // receiving incoming calls, not when placing outgoing calls. - FieldTrialFlag receive_only; - }; - // Captures partial state to be used for rollback. Applicable only in // Unified Plan. class TransceiverStableState { @@ -1214,25 +1161,6 @@ class PeerConnection : public PeerConnectionInternal, PeerConnectionInterface::RTCConfiguration configuration_ RTC_GUARDED_BY(signaling_thread()); - // Field-trial based configuration for datagram transport. - const DatagramTransportConfig datagram_transport_config_; - - // Field-trial based configuration for datagram transport data channels. - const DatagramTransportDataChannelConfig - datagram_transport_data_channel_config_; - - // Final, resolved value for whether datagram transport is in use. - bool use_datagram_transport_ RTC_GUARDED_BY(signaling_thread()) = false; - - // Equivalent of |use_datagram_transport_|, but for its use with data - // channels. - bool use_datagram_transport_for_data_channels_ - RTC_GUARDED_BY(signaling_thread()) = false; - - // Resolved value of whether to use data channels only for incoming calls. - bool use_datagram_transport_for_data_channels_receive_only_ - RTC_GUARDED_BY(signaling_thread()) = false; - // TODO(zstein): |async_resolver_factory_| can currently be nullptr if it // is not injected. It should be required once chromium supplies it. std::unique_ptr<AsyncResolverFactory> async_resolver_factory_ diff --git a/chromium/third_party/webrtc/pc/peer_connection_adaptation_integrationtest.cc b/chromium/third_party/webrtc/pc/peer_connection_adaptation_integrationtest.cc new file mode 100644 index 00000000000..71d054eb909 --- /dev/null +++ b/chromium/third_party/webrtc/pc/peer_connection_adaptation_integrationtest.cc @@ -0,0 +1,161 @@ +/* + * Copyright 2020 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <memory> + +#include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "api/rtp_parameters.h" +#include "api/scoped_refptr.h" +#include "call/adaptation/test/fake_resource.h" +#include "pc/test/fake_periodic_video_source.h" +#include "pc/test/fake_periodic_video_track_source.h" +#include "pc/test/peer_connection_test_wrapper.h" +#include "rtc_base/checks.h" +#include "rtc_base/gunit.h" +#include "rtc_base/ref_counted_object.h" +#include "rtc_base/thread.h" +#include "rtc_base/virtual_socket_server.h" +#include "test/gtest.h" + +namespace webrtc { + +const int64_t kDefaultTimeoutMs = 5000; + +struct TrackWithPeriodicSource { + rtc::scoped_refptr<VideoTrackInterface> track; + rtc::scoped_refptr<FakePeriodicVideoTrackSource> periodic_track_source; +}; + +// Performs an O/A exchange and waits until the signaling state is stable again. +void Negotiate(rtc::scoped_refptr<PeerConnectionTestWrapper> caller, + rtc::scoped_refptr<PeerConnectionTestWrapper> callee) { + // Wire up callbacks and listeners such that a full O/A is performed in + // response to CreateOffer(). + PeerConnectionTestWrapper::Connect(caller.get(), callee.get()); + caller->CreateOffer(PeerConnectionInterface::RTCOfferAnswerOptions()); + caller->WaitForNegotiation(); +} + +TrackWithPeriodicSource CreateTrackWithPeriodicSource( + rtc::scoped_refptr<PeerConnectionFactoryInterface> factory) { + FakePeriodicVideoSource::Config periodic_track_source_config; + periodic_track_source_config.frame_interval_ms = 100; + periodic_track_source_config.timestamp_offset_ms = rtc::TimeMillis(); + rtc::scoped_refptr<FakePeriodicVideoTrackSource> periodic_track_source = + new rtc::RefCountedObject<FakePeriodicVideoTrackSource>( + periodic_track_source_config, /* remote */ false); + TrackWithPeriodicSource track_with_source; + track_with_source.track = + factory->CreateVideoTrack("PeriodicTrack", periodic_track_source); + track_with_source.periodic_track_source = periodic_track_source; + return track_with_source; +} + +// Triggers overuse and obtains VideoSinkWants. Adaptation processing happens in +// parallel and this function makes no guarantee that the returnd VideoSinkWants +// have yet to reflect the overuse signal. Used together with EXPECT_TRUE_WAIT +// to "spam overuse until a change is observed". +rtc::VideoSinkWants TriggerOveruseAndGetSinkWants( + rtc::scoped_refptr<FakeResource> fake_resource, + const FakePeriodicVideoSource& source) { + fake_resource->SetUsageState(ResourceUsageState::kOveruse); + return source.wants(); +} + +class PeerConnectionAdaptationIntegrationTest : public ::testing::Test { + public: + PeerConnectionAdaptationIntegrationTest() + : virtual_socket_server_(), + network_thread_(new rtc::Thread(&virtual_socket_server_)), + worker_thread_(rtc::Thread::Create()) { + RTC_CHECK(network_thread_->Start()); + RTC_CHECK(worker_thread_->Start()); + } + + rtc::scoped_refptr<PeerConnectionTestWrapper> CreatePcWrapper( + const char* name) { + rtc::scoped_refptr<PeerConnectionTestWrapper> pc_wrapper = + new rtc::RefCountedObject<PeerConnectionTestWrapper>( + name, network_thread_.get(), worker_thread_.get()); + PeerConnectionInterface::RTCConfiguration config; + config.sdp_semantics = SdpSemantics::kUnifiedPlan; + EXPECT_TRUE(pc_wrapper->CreatePc(config, CreateBuiltinAudioEncoderFactory(), + CreateBuiltinAudioDecoderFactory())); + return pc_wrapper; + } + + protected: + rtc::VirtualSocketServer virtual_socket_server_; + std::unique_ptr<rtc::Thread> network_thread_; + std::unique_ptr<rtc::Thread> worker_thread_; +}; + +TEST_F(PeerConnectionAdaptationIntegrationTest, + ResouceInjectedAfterNegotiationCausesReductionInResolution) { + auto caller_wrapper = CreatePcWrapper("caller"); + auto caller = caller_wrapper->pc(); + auto callee_wrapper = CreatePcWrapper("callee"); + + // Adding a track and negotiating ensures that a VideoSendStream exists. + TrackWithPeriodicSource track_with_source = + CreateTrackWithPeriodicSource(caller_wrapper->pc_factory()); + auto sender = caller->AddTrack(track_with_source.track, {}).value(); + Negotiate(caller_wrapper, callee_wrapper); + // Prefer degrading resolution. + auto parameters = sender->GetParameters(); + parameters.degradation_preference = DegradationPreference::MAINTAIN_FRAMERATE; + sender->SetParameters(parameters); + + const auto& source = + track_with_source.periodic_track_source->fake_periodic_source(); + int pixel_count_before_overuse = source.wants().max_pixel_count; + + // Inject a fake resource and spam kOveruse until resolution becomes limited. + auto fake_resource = FakeResource::Create("FakeResource"); + caller->AddAdaptationResource(fake_resource); + EXPECT_TRUE_WAIT( + TriggerOveruseAndGetSinkWants(fake_resource, source).max_pixel_count < + pixel_count_before_overuse, + kDefaultTimeoutMs); +} + +TEST_F(PeerConnectionAdaptationIntegrationTest, + ResouceInjectedBeforeNegotiationCausesReductionInResolution) { + auto caller_wrapper = CreatePcWrapper("caller"); + auto caller = caller_wrapper->pc(); + auto callee_wrapper = CreatePcWrapper("callee"); + + // Inject a fake resource before adding any tracks or negotiating. + auto fake_resource = FakeResource::Create("FakeResource"); + caller->AddAdaptationResource(fake_resource); + + // Adding a track and negotiating ensures that a VideoSendStream exists. + TrackWithPeriodicSource track_with_source = + CreateTrackWithPeriodicSource(caller_wrapper->pc_factory()); + auto sender = caller->AddTrack(track_with_source.track, {}).value(); + Negotiate(caller_wrapper, callee_wrapper); + // Prefer degrading resolution. + auto parameters = sender->GetParameters(); + parameters.degradation_preference = DegradationPreference::MAINTAIN_FRAMERATE; + sender->SetParameters(parameters); + + const auto& source = + track_with_source.periodic_track_source->fake_periodic_source(); + int pixel_count_before_overuse = source.wants().max_pixel_count; + + // Spam kOveruse until resolution becomes limited. + EXPECT_TRUE_WAIT( + TriggerOveruseAndGetSinkWants(fake_resource, source).max_pixel_count < + pixel_count_before_overuse, + kDefaultTimeoutMs); +} + +} // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/peer_connection_factory.cc b/chromium/third_party/webrtc/pc/peer_connection_factory.cc index 9a758bea2d0..2ff8dee4d00 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_factory.cc +++ b/chromium/third_party/webrtc/pc/peer_connection_factory.cc @@ -23,7 +23,6 @@ #include "api/peer_connection_proxy.h" #include "api/rtc_event_log/rtc_event_log.h" #include "api/transport/field_trial_based_config.h" -#include "api/transport/media/media_transport_interface.h" #include "api/turn_customizer.h" #include "api/units/data_rate.h" #include "api/video_track_source_proxy.h" @@ -82,7 +81,6 @@ PeerConnectionFactory::PeerConnectionFactory( std::move(dependencies.network_state_predictor_factory)), injected_network_controller_factory_( std::move(dependencies.network_controller_factory)), - media_transport_factory_(std::move(dependencies.media_transport_factory)), neteq_factory_(std::move(dependencies.neteq_factory)), trials_(dependencies.trials ? std::move(dependencies.trials) : std::make_unique<FieldTrialBasedConfig>()) { diff --git a/chromium/third_party/webrtc/pc/peer_connection_factory.h b/chromium/third_party/webrtc/pc/peer_connection_factory.h index 962b08c7c99..58859a0296a 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_factory.h +++ b/chromium/third_party/webrtc/pc/peer_connection_factory.h @@ -18,7 +18,6 @@ #include "api/media_stream_interface.h" #include "api/peer_connection_interface.h" #include "api/scoped_refptr.h" -#include "api/transport/media/media_transport_interface.h" #include "media/sctp/sctp_transport_internal.h" #include "pc/channel_manager.h" #include "rtc_base/rtc_certificate_generator.h" @@ -87,10 +86,6 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { const Options& options() const { return options_; } - MediaTransportFactory* media_transport_factory() { - return media_transport_factory_.get(); - } - protected: // This structure allows simple management of all new dependencies being added // to the PeerConnectionFactory. @@ -128,7 +123,6 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { network_state_predictor_factory_; std::unique_ptr<NetworkControllerFactoryInterface> injected_network_controller_factory_; - std::unique_ptr<MediaTransportFactory> media_transport_factory_; std::unique_ptr<NetEqFactory> neteq_factory_; const std::unique_ptr<WebRtcKeyValueConfig> trials_; }; diff --git a/chromium/third_party/webrtc/pc/peer_connection_header_extension_unittest.cc b/chromium/third_party/webrtc/pc/peer_connection_header_extension_unittest.cc index 3f44d4f877d..62fda592127 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_header_extension_unittest.cc +++ b/chromium/third_party/webrtc/pc/peer_connection_header_extension_unittest.cc @@ -33,16 +33,31 @@ class PeerConnectionHeaderExtensionTest : public ::testing::TestWithParam< std::tuple<cricket::MediaType, SdpSemantics>> { protected: + PeerConnectionHeaderExtensionTest() + : extensions_( + {RtpHeaderExtensionCapability("uri1", + 1, + RtpTransceiverDirection::kStopped), + RtpHeaderExtensionCapability("uri2", + 2, + RtpTransceiverDirection::kSendOnly), + RtpHeaderExtensionCapability("uri3", + 3, + RtpTransceiverDirection::kRecvOnly), + RtpHeaderExtensionCapability( + "uri4", + 4, + RtpTransceiverDirection::kSendRecv)}) {} + std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection( cricket::MediaType media_type, - absl::optional<SdpSemantics> semantics, - std::vector<RtpHeaderExtensionCapability> extensions) { + absl::optional<SdpSemantics> semantics) { auto voice = std::make_unique<cricket::FakeVoiceEngine>(); auto video = std::make_unique<cricket::FakeVideoEngine>(); if (media_type == cricket::MediaType::MEDIA_TYPE_AUDIO) - voice->SetRtpHeaderExtensions(extensions); + voice->SetRtpHeaderExtensions(extensions_); else - video->SetRtpHeaderExtensions(extensions); + video->SetRtpHeaderExtensions(extensions_); auto media_engine = std::make_unique<cricket::CompositeMediaEngine>( std::move(voice), std::move(video)); PeerConnectionFactoryDependencies factory_dependencies; @@ -71,6 +86,8 @@ class PeerConnectionHeaderExtensionTest return std::make_unique<PeerConnectionWrapper>(pc_factory, pc, std::move(observer)); } + + std::vector<RtpHeaderExtensionCapability> extensions_; }; TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) { @@ -79,19 +96,10 @@ TEST_P(PeerConnectionHeaderExtensionTest, TransceiverOffersHeaderExtensions) { std::tie(media_type, semantics) = GetParam(); if (semantics != SdpSemantics::kUnifiedPlan) return; - std::vector<RtpHeaderExtensionCapability> extensions( - {RtpHeaderExtensionCapability("uri1", 1, - RtpTransceiverDirection::kStopped), - RtpHeaderExtensionCapability("uri2", 2, - RtpTransceiverDirection::kSendOnly), - RtpHeaderExtensionCapability("uri3", 3, - RtpTransceiverDirection::kRecvOnly), - RtpHeaderExtensionCapability("uri4", 4, - RtpTransceiverDirection::kSendRecv)}); std::unique_ptr<PeerConnectionWrapper> wrapper = - CreatePeerConnection(media_type, semantics, extensions); + CreatePeerConnection(media_type, semantics); auto transceiver = wrapper->AddTransceiver(media_type); - EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions); + EXPECT_EQ(transceiver->HeaderExtensionsToOffer(), extensions_); } TEST_P(PeerConnectionHeaderExtensionTest, @@ -99,20 +107,14 @@ TEST_P(PeerConnectionHeaderExtensionTest, cricket::MediaType media_type; SdpSemantics semantics; std::tie(media_type, semantics) = GetParam(); - std::unique_ptr<PeerConnectionWrapper> wrapper = CreatePeerConnection( - media_type, semantics, - std::vector<RtpHeaderExtensionCapability>( - {RtpHeaderExtensionCapability("uri1", 1, - RtpTransceiverDirection::kSendRecv), - RtpHeaderExtensionCapability("uri2", 2, - RtpTransceiverDirection::kStopped), - RtpHeaderExtensionCapability("uri3", 3, - RtpTransceiverDirection::kRecvOnly)})); + std::unique_ptr<PeerConnectionWrapper> wrapper = + CreatePeerConnection(media_type, semantics); EXPECT_THAT(wrapper->pc_factory() ->GetRtpSenderCapabilities(media_type) .header_extensions, - ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri1"), - Field(&RtpHeaderExtensionCapability::uri, "uri3"))); + ElementsAre(Field(&RtpHeaderExtensionCapability::uri, "uri2"), + Field(&RtpHeaderExtensionCapability::uri, "uri3"), + Field(&RtpHeaderExtensionCapability::uri, "uri4"))); EXPECT_EQ(wrapper->pc_factory() ->GetRtpReceiverCapabilities(media_type) .header_extensions, @@ -121,6 +123,49 @@ TEST_P(PeerConnectionHeaderExtensionTest, .header_extensions); } +TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedDefaultExtensions) { + cricket::MediaType media_type; + SdpSemantics semantics; + std::tie(media_type, semantics) = GetParam(); + if (semantics != SdpSemantics::kUnifiedPlan) + return; + std::unique_ptr<PeerConnectionWrapper> wrapper = + CreatePeerConnection(media_type, semantics); + auto transceiver = wrapper->AddTransceiver(media_type); + auto session_description = wrapper->CreateOffer(); + EXPECT_THAT(session_description->description() + ->contents()[0] + .media_description() + ->rtp_header_extensions(), + ElementsAre(Field(&RtpExtension::uri, "uri2"), + Field(&RtpExtension::uri, "uri3"), + Field(&RtpExtension::uri, "uri4"))); +} + +TEST_P(PeerConnectionHeaderExtensionTest, OffersUnstoppedModifiedExtensions) { + cricket::MediaType media_type; + SdpSemantics semantics; + std::tie(media_type, semantics) = GetParam(); + if (semantics != SdpSemantics::kUnifiedPlan) + return; + std::unique_ptr<PeerConnectionWrapper> wrapper = + CreatePeerConnection(media_type, semantics); + auto transceiver = wrapper->AddTransceiver(media_type); + auto modified_extensions = transceiver->HeaderExtensionsToOffer(); + modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv; + modified_extensions[3].direction = RtpTransceiverDirection::kStopped; + EXPECT_TRUE( + transceiver->SetOfferedRtpHeaderExtensions(modified_extensions).ok()); + auto session_description = wrapper->CreateOffer(); + EXPECT_THAT(session_description->description() + ->contents()[0] + .media_description() + ->rtp_header_extensions(), + ElementsAre(Field(&RtpExtension::uri, "uri1"), + Field(&RtpExtension::uri, "uri2"), + Field(&RtpExtension::uri, "uri3"))); +} + INSTANTIATE_TEST_SUITE_P( , PeerConnectionHeaderExtensionTest, diff --git a/chromium/third_party/webrtc/pc/peer_connection_integrationtest.cc b/chromium/third_party/webrtc/pc/peer_connection_integrationtest.cc index f3b4f283606..afb5f2ba752 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_integrationtest.cc +++ b/chromium/third_party/webrtc/pc/peer_connection_integrationtest.cc @@ -28,7 +28,6 @@ #include "api/rtc_event_log/rtc_event_log_factory.h" #include "api/rtp_receiver_interface.h" #include "api/task_queue/default_task_queue_factory.h" -#include "api/test/loopback_media_transport.h" #include "api/uma_metrics.h" #include "api/video_codecs/sdp_video_format.h" #include "call/call.h" @@ -215,7 +214,6 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver, dependencies.cert_generator = std::move(cert_generator); if (!client->Init(nullptr, nullptr, std::move(dependencies), network_thread, worker_thread, nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false)) { delete client; @@ -611,7 +609,6 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver, rtc::Thread* network_thread, rtc::Thread* worker_thread, std::unique_ptr<webrtc::FakeRtcEventLogFactory> event_log_factory, - std::unique_ptr<webrtc::MediaTransportFactory> media_transport_factory, bool reset_encoder_factory, bool reset_decoder_factory) { // There's an error in this test code if Init ends up being called twice. @@ -666,10 +663,6 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver, std::make_unique<webrtc::RtcEventLogFactory>( pc_factory_dependencies.task_queue_factory.get()); } - if (media_transport_factory) { - pc_factory_dependencies.media_transport_factory = - std::move(media_transport_factory); - } peer_connection_factory_ = webrtc::CreateModularPeerConnectionFactory( std::move(pc_factory_dependencies)); @@ -1082,8 +1075,8 @@ class PeerConnectionWrapper : public webrtc::PeerConnectionObserver, class MockRtcEventLogOutput : public webrtc::RtcEventLogOutput { public: virtual ~MockRtcEventLogOutput() = default; - MOCK_CONST_METHOD0(IsActive, bool()); - MOCK_METHOD1(Write, bool(const std::string&)); + MOCK_METHOD(bool, IsActive, (), (const, override)); + MOCK_METHOD(bool, Write, (const std::string&), (override)); }; // This helper object is used for both specifying how many audio/video frames @@ -1216,7 +1209,7 @@ class MockIceTransportFactory : public IceTransportFactory { return new rtc::RefCountedObject<MockIceTransport>(transport_name, component); } - MOCK_METHOD0(RecordIceTransportCreated, void()); + MOCK_METHOD(void, RecordIceTransportCreated, ()); }; // Tests two PeerConnections connecting to each other end-to-end, using a @@ -1230,8 +1223,7 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { ss_(new rtc::VirtualSocketServer()), fss_(new rtc::FirewallSocketServer(ss_.get())), network_thread_(new rtc::Thread(fss_.get())), - worker_thread_(rtc::Thread::Create()), - loopback_media_transports_(network_thread_.get()) { + worker_thread_(rtc::Thread::Create()) { network_thread_->SetName("PCNetworkThread", this); worker_thread_->SetName("PCWorkerThread", this); RTC_CHECK(network_thread_->Start()); @@ -1288,7 +1280,6 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { const RTCConfiguration* config, webrtc::PeerConnectionDependencies dependencies, std::unique_ptr<webrtc::FakeRtcEventLogFactory> event_log_factory, - std::unique_ptr<webrtc::MediaTransportFactory> media_transport_factory, bool reset_encoder_factory, bool reset_decoder_factory) { RTCConfiguration modified_config; @@ -1305,8 +1296,7 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { if (!client->Init(options, &modified_config, std::move(dependencies), network_thread_.get(), worker_thread_.get(), - std::move(event_log_factory), - std::move(media_transport_factory), reset_encoder_factory, + std::move(event_log_factory), reset_encoder_factory, reset_decoder_factory)) { return nullptr; } @@ -1321,11 +1311,11 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { webrtc::PeerConnectionDependencies dependencies) { std::unique_ptr<webrtc::FakeRtcEventLogFactory> event_log_factory( new webrtc::FakeRtcEventLogFactory(rtc::Thread::Current())); - return CreatePeerConnectionWrapper( - debug_name, options, config, std::move(dependencies), - std::move(event_log_factory), - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); + return CreatePeerConnectionWrapper(debug_name, options, config, + std::move(dependencies), + std::move(event_log_factory), + /*reset_encoder_factory=*/false, + /*reset_decoder_factory=*/false); } bool CreatePeerConnectionWrappers() { @@ -1346,13 +1336,13 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { sdp_semantics_ = caller_semantics; caller_ = CreatePeerConnectionWrapper( "Caller", nullptr, nullptr, webrtc::PeerConnectionDependencies(nullptr), - nullptr, /*media_transport_factory=*/nullptr, + nullptr, /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false); sdp_semantics_ = callee_semantics; callee_ = CreatePeerConnectionWrapper( "Callee", nullptr, nullptr, webrtc::PeerConnectionDependencies(nullptr), - nullptr, /*media_transport_factory=*/nullptr, + nullptr, /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false); sdp_semantics_ = original_semantics; @@ -1365,30 +1355,12 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { caller_ = CreatePeerConnectionWrapper( "Caller", nullptr, &caller_config, webrtc::PeerConnectionDependencies(nullptr), nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); - callee_ = CreatePeerConnectionWrapper( - "Callee", nullptr, &callee_config, - webrtc::PeerConnectionDependencies(nullptr), nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); - return caller_ && callee_; - } - - bool CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - const PeerConnectionInterface::RTCConfiguration& caller_config, - const PeerConnectionInterface::RTCConfiguration& callee_config, - std::unique_ptr<webrtc::MediaTransportFactory> caller_factory, - std::unique_ptr<webrtc::MediaTransportFactory> callee_factory) { - caller_ = CreatePeerConnectionWrapper( - "Caller", nullptr, &caller_config, - webrtc::PeerConnectionDependencies(nullptr), nullptr, - std::move(caller_factory), /*reset_encoder_factory=*/false, + /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false); callee_ = CreatePeerConnectionWrapper( "Callee", nullptr, &callee_config, webrtc::PeerConnectionDependencies(nullptr), nullptr, - std::move(callee_factory), /*reset_encoder_factory=*/false, + /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false); return caller_ && callee_; } @@ -1398,16 +1370,16 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { webrtc::PeerConnectionDependencies caller_dependencies, const PeerConnectionInterface::RTCConfiguration& callee_config, webrtc::PeerConnectionDependencies callee_dependencies) { - caller_ = CreatePeerConnectionWrapper( - "Caller", nullptr, &caller_config, std::move(caller_dependencies), - nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); - callee_ = CreatePeerConnectionWrapper( - "Callee", nullptr, &callee_config, std::move(callee_dependencies), - nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); + caller_ = + CreatePeerConnectionWrapper("Caller", nullptr, &caller_config, + std::move(caller_dependencies), nullptr, + /*reset_encoder_factory=*/false, + /*reset_decoder_factory=*/false); + callee_ = + CreatePeerConnectionWrapper("Callee", nullptr, &callee_config, + std::move(callee_dependencies), nullptr, + /*reset_encoder_factory=*/false, + /*reset_decoder_factory=*/false); return caller_ && callee_; } @@ -1417,12 +1389,12 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { caller_ = CreatePeerConnectionWrapper( "Caller", &caller_options, nullptr, webrtc::PeerConnectionDependencies(nullptr), nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, + /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false); callee_ = CreatePeerConnectionWrapper( "Callee", &callee_options, nullptr, webrtc::PeerConnectionDependencies(nullptr), nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, + /*reset_encoder_factory=*/false, /*reset_decoder_factory=*/false); return caller_ && callee_; } @@ -1446,21 +1418,21 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { webrtc::PeerConnectionDependencies dependencies(nullptr); dependencies.cert_generator = std::move(cert_generator); - return CreatePeerConnectionWrapper( - "New Peer", nullptr, nullptr, std::move(dependencies), nullptr, - /*media_transport_factory=*/nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); + return CreatePeerConnectionWrapper("New Peer", nullptr, nullptr, + std::move(dependencies), nullptr, + /*reset_encoder_factory=*/false, + /*reset_decoder_factory=*/false); } bool CreateOneDirectionalPeerConnectionWrappers(bool caller_to_callee) { caller_ = CreatePeerConnectionWrapper( "Caller", nullptr, nullptr, webrtc::PeerConnectionDependencies(nullptr), - nullptr, /*media_transport_factory=*/nullptr, + nullptr, /*reset_encoder_factory=*/!caller_to_callee, /*reset_decoder_factory=*/caller_to_callee); callee_ = CreatePeerConnectionWrapper( "Callee", nullptr, nullptr, webrtc::PeerConnectionDependencies(nullptr), - nullptr, /*media_transport_factory=*/nullptr, + nullptr, /*reset_encoder_factory=*/caller_to_callee, /*reset_decoder_factory=*/!caller_to_callee); return caller_ && callee_; @@ -1551,10 +1523,6 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { rtc::VirtualSocketServer* virtual_socket_server() { return ss_.get(); } - webrtc::MediaTransportPair* loopback_media_transports() { - return &loopback_media_transports_; - } - PeerConnectionWrapper* caller() { return caller_.get(); } // Set the |caller_| to the |wrapper| passed in and return the @@ -1752,7 +1720,6 @@ class PeerConnectionIntegrationBaseTest : public ::testing::Test { // on the network thread. std::vector<std::unique_ptr<cricket::TestTurnServer>> turn_servers_; std::vector<std::unique_ptr<cricket::TestTurnCustomizer>> turn_customizers_; - webrtc::MediaTransportPair loopback_media_transports_; std::unique_ptr<PeerConnectionWrapper> caller_; std::unique_ptr<PeerConnectionWrapper> callee_; }; @@ -3875,877 +3842,8 @@ TEST_P(PeerConnectionIntegrationTest, kDefaultTimeout); } -// Tests that the datagram transport to SCTP fallback works correctly when -// datagram transport negotiation fails. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelFallbackToSctp) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - - // Configure one endpoint to use datagram transport for data channels while - // the other does not. - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, RTCConfiguration(), - loopback_media_transports()->first_factory(), nullptr)); - ConnectFakeSignaling(); - - // The caller offers a data channel using either datagram transport or SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Negotiation should fallback to SCTP, allowing the data channel to be - // established. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Ensure that failure of the datagram negotiation doesn't impede media flow. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -// Tests that the data channel transport works correctly when datagram transport -// negotiation succeeds and does not fall back to SCTP. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelDoesNotFallbackToSctp) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - - // Configure one endpoint to use datagram transport for data channels while - // the other does not. - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // The caller offers a data channel using either datagram transport or SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Negotiation should succeed, allowing the data channel to be established. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Ensure that failure of the datagram negotiation doesn't impede media flow. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -// Tests that the datagram transport to SCTP fallback works correctly when -// datagram transports do not advertise compatible transport parameters. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportIncompatibleParametersFallsBackToSctp) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - - // By default, only equal parameters are compatible. - loopback_media_transports()->SetFirstDatagramTransportParameters("foo"); - loopback_media_transports()->SetSecondDatagramTransportParameters("bar"); - - // Configure one endpoint to use datagram transport for data channels while - // the other does not. - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // The caller offers a data channel using either datagram transport or SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Negotiation should fallback to SCTP, allowing the data channel to be - // established. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use SCTP for data channels. - EXPECT_NE(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_NE(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Ensure that failure of the datagram negotiation doesn't impede media flow. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -// Tests that the datagram transport to SCTP fallback works correctly when -// only the answerer believes datagram transport parameters are incompatible. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportIncompatibleParametersOnAnswererFallsBackToSctp) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - - // By default, only equal parameters are compatible. - loopback_media_transports()->SetFirstDatagramTransportParameters("foo"); - loopback_media_transports()->SetSecondDatagramTransportParameters("bar"); - - // Set the offerer to accept different parameters, while the answerer rejects - // them. - loopback_media_transports()->SetFirstDatagramTransportParametersComparison( - [](absl::string_view a, absl::string_view b) { return true; }); - loopback_media_transports()->SetSecondDatagramTransportParametersComparison( - [](absl::string_view a, absl::string_view b) { return false; }); - - // Configure one endpoint to use datagram transport for data channels while - // the other does not. - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // The caller offers a data channel using either datagram transport or SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Negotiation should fallback to SCTP, allowing the data channel to be - // established. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use SCTP for data channels. - EXPECT_NE(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_NE(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Ensure that failure of the datagram negotiation doesn't impede media flow. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -// Tests that the data channel transport works correctly when datagram -// transports provide different, but compatible, transport parameters. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportCompatibleParametersDoNotFallbackToSctp) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - - // By default, only equal parameters are compatible. - loopback_media_transports()->SetFirstDatagramTransportParameters("foo"); - loopback_media_transports()->SetSecondDatagramTransportParameters("bar"); - - // Change the comparison used to treat these transport parameters are - // compatible (on both sides). - loopback_media_transports()->SetFirstDatagramTransportParametersComparison( - [](absl::string_view a, absl::string_view b) { return true; }); - loopback_media_transports()->SetSecondDatagramTransportParametersComparison( - [](absl::string_view a, absl::string_view b) { return true; }); - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // The caller offers a data channel using either datagram transport or SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Negotiation should succeed, allowing the data channel to be established. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use datagram transport for data channels. - EXPECT_EQ(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_EQ(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Ensure that failure of the datagram negotiation doesn't impede media flow. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelWithMediaOnCaller) { - // Configure the caller to attempt use of datagram transport for media and - // data channels. - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport_for_data_channels = true; - offerer_config.use_datagram_transport = true; - - // Configure the callee to only use datagram transport for data channels. - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - answerer_config.use_datagram_transport_for_data_channels = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Offer both media and data. - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use datagram transport for data channels. - EXPECT_EQ(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_EQ(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Media flow should not be impacted. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportMediaWithDataChannelOnCaller) { - // Configure the caller to attempt use of datagram transport for media and - // data channels. - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport_for_data_channels = true; - offerer_config.use_datagram_transport = true; - - // Configure the callee to only use datagram transport for media. - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - answerer_config.use_datagram_transport = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Offer both media and data. - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use SCTP for data channels. - EXPECT_NE(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_NE(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Media flow should not be impacted. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelWithMediaOnCallee) { - // Configure the caller to attempt use of datagram transport for data - // channels. - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport_for_data_channels = true; - - // Configure the callee to use datagram transport for data channels and media. - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - answerer_config.use_datagram_transport_for_data_channels = true; - answerer_config.use_datagram_transport = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Offer both media and data. - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use datagram transport for data channels. - EXPECT_EQ(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_EQ(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Media flow should not be impacted. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportMediaWithDataChannelOnCallee) { - // Configure the caller to attempt use of datagram transport for media. - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport = true; - - // Configure the callee to only use datagram transport for media and data - // channels. - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - answerer_config.use_datagram_transport = true; - answerer_config.use_datagram_transport_for_data_channels = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Offer both media and data. - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use SCTP for data channels. - EXPECT_NE(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_NE(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Media flow should not be impacted. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -TEST_P(PeerConnectionIntegrationTest, DatagramTransportDataChannelAndMedia) { - // Configure the caller to use datagram transport for data channels and media. - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport_for_data_channels = true; - offerer_config.use_datagram_transport = true; - - // Configure the callee to use datagram transport for data channels and media. - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - answerer_config.use_datagram_transport_for_data_channels = true; - answerer_config.use_datagram_transport = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Offer both media and data. - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Both endpoints should agree to use datagram transport for data channels. - EXPECT_EQ(nullptr, caller()->pc()->GetSctpTransport()); - EXPECT_EQ(nullptr, callee()->pc()->GetSctpTransport()); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); - - // Media flow should not be impacted. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - -// Tests that data channels use SCTP instead of datagram transport if datagram -// transport is configured in receive-only mode on the caller. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelReceiveOnlyOnCallerUsesSctp) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - rtc_config.use_datagram_transport_for_data_channels_receive_only = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // The caller should offer a data channel using SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // SCTP transports should be present, since they are in use. - EXPECT_NE(caller()->pc()->GetSctpTransport(), nullptr); - EXPECT_NE(callee()->pc()->GetSctpTransport(), nullptr); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); -} - #endif // HAVE_SCTP -// Tests that a callee configured for receive-only use of datagram transport -// data channels accepts them on incoming calls. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelReceiveOnlyOnCallee) { - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport_for_data_channels = true; - - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - answerer_config.use_datagram_transport_for_data_channels = true; - answerer_config.use_datagram_transport_for_data_channels_receive_only = true; - - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // SCTP transports should not be present, since datagram transport is used. - EXPECT_EQ(caller()->pc()->GetSctpTransport(), nullptr); - EXPECT_EQ(callee()->pc()->GetSctpTransport(), nullptr); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); -} - -// This test sets up a call between two parties with a datagram transport data -// channel. -TEST_P(PeerConnectionIntegrationTest, DatagramTransportDataChannelEndToEnd) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - rtc_config.enable_dtls_srtp = false; - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Expect that data channel created on caller side will show up for callee as - // well. - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Caller data channel should already exist (it created one). Callee data - // channel may not exist yet, since negotiation happens in-band, not in SDP. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); -} - -// Tests that 'zero-rtt' data channel transports (which are ready-to-send as -// soon as they're created) work correctly. -TEST_P(PeerConnectionIntegrationTest, DatagramTransportDataChannelZeroRtt) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - rtc_config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxBundle; - rtc_config.use_datagram_transport_for_data_channels = true; - rtc_config.enable_dtls_srtp = false; // SDES is required for media transport. - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Ensure that the callee's media transport is ready-to-send immediately. - // Note that only the callee can become writable in zero RTTs. The caller - // must wait for the callee's answer. - loopback_media_transports()->SetSecondStateAfterConnect( - webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Expect that data channel created on caller side will show up for callee as - // well. - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - loopback_media_transports()->SetFirstState( - webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Caller data channel should already exist (it created one). Callee data - // channel may not exist yet, since negotiation happens in-band, not in SDP. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Ensure data can be sent in both directions. - std::string data = "hello world"; - caller()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), - kDefaultTimeout); - callee()->data_channel()->Send(DataBuffer(data)); - EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), - kDefaultTimeout); -} - -// Ensures that when the callee closes a datagram transport data channel, the -// closing procedure results in the data channel being closed for the caller -// as well. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelCalleeCloses) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.use_datagram_transport_for_data_channels = true; - rtc_config.enable_dtls_srtp = false; - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Create a data channel on the caller and signal it to the callee. - caller()->CreateDataChannel(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Data channels exist and open on both ends of the connection. - ASSERT_NE(nullptr, caller()->data_channel()); - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); - ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - - // Close the data channel on the callee side, and wait for it to reach the - // "closed" state on both sides. - callee()->data_channel()->Close(); - EXPECT_TRUE_WAIT(!caller()->data_observer()->IsOpen(), kDefaultTimeout); - EXPECT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout); -} - -// Tests that datagram transport data channels can do in-band negotiation. -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelConfigSentToOtherSide) { - PeerConnectionInterface::RTCConfiguration rtc_config; - rtc_config.use_datagram_transport_for_data_channels = true; - rtc_config.enable_dtls_srtp = false; - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - rtc_config, rtc_config, loopback_media_transports()->first_factory(), - loopback_media_transports()->second_factory())); - ConnectFakeSignaling(); - - // Create a data channel with a non-default configuration and signal it to the - // callee. - webrtc::DataChannelInit init; - init.id = 53; - init.maxRetransmits = 52; - caller()->CreateDataChannel("data-channel", &init); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Ensure that the data channel transport is ready. - loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable); - loopback_media_transports()->FlushAsyncInvokes(); - - // Ensure that the data channel exists on the callee with the correct - // configuration. - ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); - ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); - // Since "negotiate" is false, the "id" parameter is ignored. - EXPECT_NE(init.id, callee()->data_channel()->id()); - EXPECT_EQ("data-channel", callee()->data_channel()->label()); - EXPECT_EQ(init.maxRetransmits, callee()->data_channel()->maxRetransmits()); - EXPECT_FALSE(callee()->data_channel()->negotiated()); -} - -TEST_P(PeerConnectionIntegrationTest, - DatagramTransportDataChannelRejectedWithNoFallback) { - PeerConnectionInterface::RTCConfiguration offerer_config; - offerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - offerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - offerer_config.use_datagram_transport_for_data_channels = true; - // Disabling DTLS precludes a fallback to SCTP. - offerer_config.enable_dtls_srtp = false; - - PeerConnectionInterface::RTCConfiguration answerer_config; - answerer_config.rtcp_mux_policy = - PeerConnectionInterface::kRtcpMuxPolicyRequire; - answerer_config.bundle_policy = - PeerConnectionInterface::kBundlePolicyMaxBundle; - // Both endpoints must disable DTLS or SetRemoteDescription will fail. - answerer_config.enable_dtls_srtp = false; - - // Configure one endpoint to use datagram transport for data channels while - // the other does not. - ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory( - offerer_config, answerer_config, - loopback_media_transports()->first_factory(), nullptr)); - ConnectFakeSignaling(); - - // The caller offers a data channel using either datagram transport or SCTP. - caller()->CreateDataChannel(); - caller()->AddAudioVideoTracks(); - callee()->AddAudioVideoTracks(); - caller()->CreateAndSetAndSignalOffer(); - ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); - - // Caller data channel should already exist (it created one). Callee data - // channel should not exist, since negotiation happens in-band, not in SDP. - EXPECT_NE(nullptr, caller()->data_channel()); - EXPECT_EQ(nullptr, callee()->data_channel()); - - // The caller's data channel should close when the datagram transport is - // rejected. - EXPECT_FALSE(caller()->data_observer()->IsOpen()); - - // Media flow should not be impacted by the failed data channel. - MediaExpectations media_expectations; - media_expectations.ExpectBidirectionalAudioAndVideo(); - ASSERT_TRUE(ExpectNewFrames(media_expectations)); -} - // Test that the ICE connection and gathering states eventually reach // "complete". TEST_P(PeerConnectionIntegrationTest, IceStatesReachCompletion) { @@ -5702,10 +4800,10 @@ TEST_P(PeerConnectionIntegrationTest, IceTransportFactoryUsedForConnections) { auto ice_transport_factory = std::make_unique<MockIceTransportFactory>(); EXPECT_CALL(*ice_transport_factory, RecordIceTransportCreated()).Times(1); dependencies.ice_transport_factory = std::move(ice_transport_factory); - auto wrapper = CreatePeerConnectionWrapper( - "Caller", nullptr, &default_config, std::move(dependencies), nullptr, - nullptr, /*reset_encoder_factory=*/false, - /*reset_decoder_factory=*/false); + auto wrapper = CreatePeerConnectionWrapper("Caller", nullptr, &default_config, + std::move(dependencies), nullptr, + /*reset_encoder_factory=*/false, + /*reset_decoder_factory=*/false); ASSERT_TRUE(wrapper); wrapper->CreateDataChannel(); rtc::scoped_refptr<MockSetSessionDescriptionObserver> observer( @@ -6134,6 +5232,23 @@ TEST_P(PeerConnectionIntegrationTest, RegatherAfterChangingIceTransportType) { callee()->pc()->SetConfiguration(callee_config); EXPECT_EQ_WAIT(cricket::LOCAL_PORT_TYPE, callee()->last_candidate_gathered().type(), kDefaultTimeout); + + // Create an offer and verify that it does not contain an ICE restart (i.e new + // ice credentials). + std::string caller_ufrag_pre_offer = caller() + ->pc() + ->local_description() + ->description() + ->transport_infos()[0] + .description.ice_ufrag; + caller()->CreateAndSetAndSignalOffer(); + std::string caller_ufrag_post_offer = caller() + ->pc() + ->local_description() + ->description() + ->transport_infos()[0] + .description.ice_ufrag; + EXPECT_EQ(caller_ufrag_pre_offer, caller_ufrag_post_offer); } TEST_P(PeerConnectionIntegrationTest, OnIceCandidateError) { @@ -6173,6 +5288,35 @@ TEST_P(PeerConnectionIntegrationTest, OnIceCandidateError) { EXPECT_NE(caller()->error_event().address, ""); } +TEST_P(PeerConnectionIntegrationTest, OnIceCandidateErrorWithEmptyAddress) { + webrtc::PeerConnectionInterface::IceServer ice_server; + ice_server.urls.push_back("turn:127.0.0.1:3478?transport=tcp"); + ice_server.username = "test"; + ice_server.password = "test"; + + PeerConnectionInterface::RTCConfiguration caller_config; + caller_config.servers.push_back(ice_server); + caller_config.type = webrtc::PeerConnectionInterface::kRelay; + caller_config.continual_gathering_policy = PeerConnection::GATHER_CONTINUALLY; + + PeerConnectionInterface::RTCConfiguration callee_config; + callee_config.servers.push_back(ice_server); + callee_config.type = webrtc::PeerConnectionInterface::kRelay; + callee_config.continual_gathering_policy = PeerConnection::GATHER_CONTINUALLY; + + ASSERT_TRUE( + CreatePeerConnectionWrappersWithConfig(caller_config, callee_config)); + + // Do normal offer/answer and wait for ICE to complete. + ConnectFakeSignaling(); + caller()->AddAudioVideoTracks(); + callee()->AddAudioVideoTracks(); + caller()->CreateAndSetAndSignalOffer(); + ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); + EXPECT_EQ_WAIT(701, caller()->error_event().error_code, kDefaultTimeout); + EXPECT_EQ(caller()->error_event().address, ""); +} + TEST_F(PeerConnectionIntegrationTestUnifiedPlan, AudioKeepsFlowingAfterImplicitRollback) { PeerConnectionInterface::RTCConfiguration config; diff --git a/chromium/third_party/webrtc/pc/peer_connection_interface_unittest.cc b/chromium/third_party/webrtc/pc/peer_connection_interface_unittest.cc index 2a369705975..9251511747f 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_interface_unittest.cc +++ b/chromium/third_party/webrtc/pc/peer_connection_interface_unittest.cc @@ -627,7 +627,7 @@ class MockTrackObserver : public ObserverInterface { } } - MOCK_METHOD0(OnChanged, void()); + MOCK_METHOD(void, OnChanged, (), (override)); private: NotifierInterface* notifier_; @@ -1421,15 +1421,11 @@ TEST_P(PeerConnectionInterfaceTest, GetConfigurationAfterSetConfiguration) { PeerConnectionInterface::RTCConfiguration config = pc_->GetConfiguration(); config.type = PeerConnectionInterface::kRelay; - config.use_datagram_transport = true; - config.use_datagram_transport_for_data_channels = true; EXPECT_TRUE(pc_->SetConfiguration(config).ok()); PeerConnectionInterface::RTCConfiguration returned_config = pc_->GetConfiguration(); EXPECT_EQ(PeerConnectionInterface::kRelay, returned_config.type); - EXPECT_TRUE(returned_config.use_datagram_transport); - EXPECT_TRUE(returned_config.use_datagram_transport_for_data_channels); } TEST_P(PeerConnectionInterfaceTest, SetConfigurationFailsAfterClose) { diff --git a/chromium/third_party/webrtc/pc/peer_connection_internal.h b/chromium/third_party/webrtc/pc/peer_connection_internal.h index 52ffe85c2c2..66d585b592d 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_internal.h +++ b/chromium/third_party/webrtc/pc/peer_connection_internal.h @@ -46,8 +46,11 @@ class PeerConnectionInternal : public PeerConnectionInterface { // Only valid when using deprecated RTP data channels. virtual cricket::RtpDataChannel* rtp_data_channel() const = 0; - virtual std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels() - const = 0; + // Call on the network thread to fetch stats for all the data channels. + // TODO(tommi): Make pure virtual after downstream updates. + virtual std::vector<DataChannel::Stats> GetDataChannelStats() const { + return {}; + } virtual absl::optional<std::string> sctp_transport_name() const = 0; diff --git a/chromium/third_party/webrtc/pc/peer_connection_media_unittest.cc b/chromium/third_party/webrtc/pc/peer_connection_media_unittest.cc index c9ffd776d9d..3c117c3ecd8 100644 --- a/chromium/third_party/webrtc/pc/peer_connection_media_unittest.cc +++ b/chromium/third_party/webrtc/pc/peer_connection_media_unittest.cc @@ -825,8 +825,10 @@ TEST_P(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) { } void AddComfortNoiseCodecsToSend(cricket::FakeMediaEngine* media_engine) { - const cricket::AudioCodec kComfortNoiseCodec8k(102, "CN", 8000, 0, 1); - const cricket::AudioCodec kComfortNoiseCodec16k(103, "CN", 16000, 0, 1); + const cricket::AudioCodec kComfortNoiseCodec8k(102, cricket::kCnCodecName, + 8000, 0, 1); + const cricket::AudioCodec kComfortNoiseCodec16k(103, cricket::kCnCodecName, + 16000, 0, 1); auto codecs = media_engine->voice().send_codecs(); codecs.push_back(kComfortNoiseCodec8k); @@ -837,7 +839,7 @@ void AddComfortNoiseCodecsToSend(cricket::FakeMediaEngine* media_engine) { bool HasAnyComfortNoiseCodecs(const cricket::SessionDescription* desc) { const auto* audio_desc = cricket::GetFirstAudioContentDescription(desc); for (const auto& codec : audio_desc->codecs()) { - if (codec.name == "CN") { + if (codec.name == cricket::kCnCodecName) { return true; } } @@ -1118,10 +1120,11 @@ TEST_P(PeerConnectionMediaTest, MediaEngineErrorPropagatedToClients) { std::string error; ASSERT_FALSE(caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(), &error)); - EXPECT_EQ( - "Failed to set remote answer sdp: Failed to set remote video description " - "send parameters.", - error); + EXPECT_EQ(std::string("Failed to set remote answer sdp: Failed to set remote " + "video description " + "send parameters for m-section with mid='") + + (IsUnifiedPlan() ? "1" : "video") + "'.", + error); } // Tests that if the underlying video encoder fails once then subsequent diff --git a/chromium/third_party/webrtc/pc/proxy_unittest.cc b/chromium/third_party/webrtc/pc/proxy_unittest.cc index a00b47ff6b6..500828a03ee 100644 --- a/chromium/third_party/webrtc/pc/proxy_unittest.cc +++ b/chromium/third_party/webrtc/pc/proxy_unittest.cc @@ -46,16 +46,16 @@ class Fake : public FakeInterface { return new rtc::RefCountedObject<Fake>(); } // Used to verify destructor is called on the correct thread. - MOCK_METHOD0(Destroy, void()); + MOCK_METHOD(void, Destroy, ()); - MOCK_METHOD0(VoidMethod0, void()); - MOCK_METHOD0(Method0, std::string()); - MOCK_CONST_METHOD0(ConstMethod0, std::string()); + MOCK_METHOD(void, VoidMethod0, (), (override)); + MOCK_METHOD(std::string, Method0, (), (override)); + MOCK_METHOD(std::string, ConstMethod0, (), (const, override)); - MOCK_METHOD1(Method1, std::string(std::string)); - MOCK_CONST_METHOD1(ConstMethod1, std::string(std::string)); + MOCK_METHOD(std::string, Method1, (std::string), (override)); + MOCK_METHOD(std::string, ConstMethod1, (std::string), (const, override)); - MOCK_METHOD2(Method2, std::string(std::string, std::string)); + MOCK_METHOD(std::string, Method2, (std::string, std::string), (override)); protected: Fake() {} @@ -266,7 +266,7 @@ class FooInterface { class Foo : public FooInterface { public: Foo() {} - MOCK_METHOD0(Bar, void()); + MOCK_METHOD(void, Bar, (), (override)); }; BEGIN_OWNED_PROXY_MAP(Foo) diff --git a/chromium/third_party/webrtc/pc/remote_audio_source.cc b/chromium/third_party/webrtc/pc/remote_audio_source.cc index da00402e414..ce6a2d42c6f 100644 --- a/chromium/third_party/webrtc/pc/remote_audio_source.cc +++ b/chromium/third_party/webrtc/pc/remote_audio_source.cc @@ -49,7 +49,8 @@ class RemoteAudioSource::AudioDataProxy : public AudioSinkInterface { }; RemoteAudioSource::RemoteAudioSource(rtc::Thread* worker_thread) - : main_thread_(rtc::Thread::Current()), + : MessageHandler(false), + main_thread_(rtc::Thread::Current()), worker_thread_(worker_thread), state_(MediaSourceInterface::kLive) { RTC_DCHECK(main_thread_); diff --git a/chromium/third_party/webrtc/pc/rtc_stats_collector.cc b/chromium/third_party/webrtc/pc/rtc_stats_collector.cc index 0e2f170ff0e..f66be30dd3d 100644 --- a/chromium/third_party/webrtc/pc/rtc_stats_collector.cc +++ b/chromium/third_party/webrtc/pc/rtc_stats_collector.cc @@ -397,7 +397,6 @@ void SetOutboundRTPStreamStatsFromVoiceSenderInfo( void SetOutboundRTPStreamStatsFromVideoSenderInfo( const std::string& mid, const cricket::VideoSenderInfo& video_sender_info, - bool enable_simulcast_stats, RTCOutboundRTPStreamStats* outbound_video) { SetOutboundRTPStreamStatsFromMediaSenderInfo(video_sender_info, outbound_video); @@ -422,21 +421,19 @@ void SetOutboundRTPStreamStatsFromVideoSenderInfo( rtc::kNumMillisecsPerSec; outbound_video->total_encoded_bytes_target = video_sender_info.total_encoded_bytes_target; - if (enable_simulcast_stats) { - if (video_sender_info.send_frame_width > 0) { - outbound_video->frame_width = - static_cast<uint32_t>(video_sender_info.send_frame_width); - } - if (video_sender_info.send_frame_height > 0) { - outbound_video->frame_height = - static_cast<uint32_t>(video_sender_info.send_frame_height); - } - if (video_sender_info.framerate_sent > 0) { - outbound_video->frames_per_second = video_sender_info.framerate_sent; - } - outbound_video->frames_sent = video_sender_info.frames_sent; - outbound_video->huge_frames_sent = video_sender_info.huge_frames_sent; + if (video_sender_info.send_frame_width > 0) { + outbound_video->frame_width = + static_cast<uint32_t>(video_sender_info.send_frame_width); + } + if (video_sender_info.send_frame_height > 0) { + outbound_video->frame_height = + static_cast<uint32_t>(video_sender_info.send_frame_height); } + if (video_sender_info.framerate_sent > 0) { + outbound_video->frames_per_second = video_sender_info.framerate_sent; + } + outbound_video->frames_sent = video_sender_info.frames_sent; + outbound_video->huge_frames_sent = video_sender_info.huge_frames_sent; outbound_video->total_packet_send_delay = static_cast<double>(video_sender_info.total_packet_send_delay_ms) / rtc::kNumMillisecsPerSec; @@ -987,7 +984,6 @@ RTCStatsCollector::RTCStatsCollector(PeerConnectionInternal* pc, RTC_DCHECK_GE(cache_lifetime_us_, 0); pc_->SignalDataChannelCreated().connect( this, &RTCStatsCollector::OnDataChannelCreated); - enable_simulcast_stats_ = pc_->GetConfiguration().enable_simulcast_stats; } RTCStatsCollector::~RTCStatsCollector() { @@ -1279,22 +1275,21 @@ void RTCStatsCollector::ProduceCodecStats_n( void RTCStatsCollector::ProduceDataChannelStats_s( int64_t timestamp_us, RTCStatsReport* report) const { - RTC_DCHECK(signaling_thread_->IsCurrent()); - for (const rtc::scoped_refptr<DataChannel>& data_channel : - pc_->sctp_data_channels()) { + RTC_DCHECK_RUN_ON(signaling_thread_); + std::vector<DataChannel::Stats> data_stats = pc_->GetDataChannelStats(); + for (const auto& stats : data_stats) { std::unique_ptr<RTCDataChannelStats> data_channel_stats( new RTCDataChannelStats( - "RTCDataChannel_" + rtc::ToString(data_channel->internal_id()), + "RTCDataChannel_" + rtc::ToString(stats.internal_id), timestamp_us)); - data_channel_stats->label = data_channel->label(); - data_channel_stats->protocol = data_channel->protocol(); - data_channel_stats->datachannelid = data_channel->id(); - data_channel_stats->state = - DataStateToRTCDataChannelState(data_channel->state()); - data_channel_stats->messages_sent = data_channel->messages_sent(); - data_channel_stats->bytes_sent = data_channel->bytes_sent(); - data_channel_stats->messages_received = data_channel->messages_received(); - data_channel_stats->bytes_received = data_channel->bytes_received(); + data_channel_stats->label = std::move(stats.label); + data_channel_stats->protocol = std::move(stats.protocol); + data_channel_stats->data_channel_identifier = stats.id; + data_channel_stats->state = DataStateToRTCDataChannelState(stats.state); + data_channel_stats->messages_sent = stats.messages_sent; + data_channel_stats->bytes_sent = stats.bytes_sent; + data_channel_stats->messages_received = stats.messages_received; + data_channel_stats->bytes_received = stats.bytes_received; report->AddStats(std::move(data_channel_stats)); } } @@ -1663,16 +1658,14 @@ void RTCStatsCollector::ProduceVideoRTPStreamStats_n( // Outbound std::map<std::string, RTCOutboundRTPStreamStats*> video_outbound_rtps; for (const cricket::VideoSenderInfo& video_sender_info : - enable_simulcast_stats_ - ? track_media_info_map.video_media_info()->senders - : track_media_info_map.video_media_info()->aggregated_senders) { + track_media_info_map.video_media_info()->senders) { if (!video_sender_info.connected()) continue; auto outbound_video = std::make_unique<RTCOutboundRTPStreamStats>( RTCOutboundRTPStreamStatsIDFromSSRC(false, video_sender_info.ssrc()), timestamp_us); - SetOutboundRTPStreamStatsFromVideoSenderInfo( - mid, video_sender_info, enable_simulcast_stats_, outbound_video.get()); + SetOutboundRTPStreamStatsFromVideoSenderInfo(mid, video_sender_info, + outbound_video.get()); rtc::scoped_refptr<VideoTrackInterface> video_track = track_media_info_map.GetVideoTrack(video_sender_info); if (video_track) { diff --git a/chromium/third_party/webrtc/pc/rtc_stats_collector.h b/chromium/third_party/webrtc/pc/rtc_stats_collector.h index 7c85a35fe04..cd5ec21041a 100644 --- a/chromium/third_party/webrtc/pc/rtc_stats_collector.h +++ b/chromium/third_party/webrtc/pc/rtc_stats_collector.h @@ -288,7 +288,6 @@ class RTCStatsCollector : public virtual rtc::RefCountInterface, std::set<uintptr_t> opened_data_channels; }; InternalRecord internal_record_; - bool enable_simulcast_stats_ = false; }; const char* CandidateTypeToRTCIceCandidateTypeForTesting( diff --git a/chromium/third_party/webrtc/pc/rtc_stats_collector_unittest.cc b/chromium/third_party/webrtc/pc/rtc_stats_collector_unittest.cc index db00dd7d91d..013965c4861 100644 --- a/chromium/third_party/webrtc/pc/rtc_stats_collector_unittest.cc +++ b/chromium/third_party/webrtc/pc/rtc_stats_collector_unittest.cc @@ -993,7 +993,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) { RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0); expected_data_channel0.label = "MockDataChannel0"; expected_data_channel0.protocol = "udp"; - expected_data_channel0.datachannelid = 0; + expected_data_channel0.data_channel_identifier = 0; expected_data_channel0.state = "connecting"; expected_data_channel0.messages_sent = 1; expected_data_channel0.bytes_sent = 2; @@ -1005,7 +1005,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) { RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0); expected_data_channel1.label = "MockDataChannel1"; expected_data_channel1.protocol = "tcp"; - expected_data_channel1.datachannelid = 1; + expected_data_channel1.data_channel_identifier = 1; expected_data_channel1.state = "open"; expected_data_channel1.messages_sent = 5; expected_data_channel1.bytes_sent = 6; @@ -1018,7 +1018,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) { RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0); expected_data_channel2.label = "MockDataChannel2"; expected_data_channel2.protocol = "udp"; - expected_data_channel2.datachannelid = 2; + expected_data_channel2.data_channel_identifier = 2; expected_data_channel2.state = "closing"; expected_data_channel2.messages_sent = 9; expected_data_channel2.bytes_sent = 10; @@ -1031,7 +1031,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) { RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0); expected_data_channel3.label = "MockDataChannel3"; expected_data_channel3.protocol = "tcp"; - expected_data_channel3.datachannelid = 3; + expected_data_channel3.data_channel_identifier = 3; expected_data_channel3.state = "closed"; expected_data_channel3.messages_sent = 13; expected_data_channel3.bytes_sent = 14; @@ -1398,11 +1398,14 @@ TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) { report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>()); } + // TODO(bugs.webrtc.org/11547): Supply a separate network thread. rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create( - nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit()); + nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit(), + rtc::Thread::Current(), rtc::Thread::Current()); pc_->SignalDataChannelCreated()(dummy_channel_a.get()); rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create( - nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit()); + nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit(), + rtc::Thread::Current(), rtc::Thread::Current()); pc_->SignalDataChannelCreated()(dummy_channel_b.get()); dummy_channel_a->SignalOpened(dummy_channel_a.get()); @@ -2075,13 +2078,11 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { expected_video.total_packet_send_delay = 10.0; expected_video.quality_limitation_reason = "bandwidth"; expected_video.quality_limitation_resolution_changes = 56u; - if (pc_->GetConfiguration().enable_simulcast_stats) { - expected_video.frame_width = 200u; - expected_video.frame_height = 100u; - expected_video.frames_per_second = 10.0; - expected_video.frames_sent = 5; - expected_video.huge_frames_sent = 2; - } + expected_video.frame_width = 200u; + expected_video.frame_height = 100u; + expected_video.frames_per_second = 10.0; + expected_video.frames_sent = 5; + expected_video.huge_frames_sent = 2; // |expected_video.content_type| should be undefined. // |expected_video.qp_sum| should be undefined. // |expected_video.encoder_implementation| should be undefined. diff --git a/chromium/third_party/webrtc/pc/rtc_stats_integrationtest.cc b/chromium/third_party/webrtc/pc/rtc_stats_integrationtest.cc index d6d5c6f819c..a0fd2d02535 100644 --- a/chromium/third_party/webrtc/pc/rtc_stats_integrationtest.cc +++ b/chromium/third_party/webrtc/pc/rtc_stats_integrationtest.cc @@ -352,8 +352,7 @@ class RTCStatsReportVerifier { explicit RTCStatsReportVerifier(const RTCStatsReport* report) : report_(report) {} - void VerifyReport(std::vector<const char*> allowed_missing_stats, - bool enable_simulcast_stats) { + void VerifyReport(std::vector<const char*> allowed_missing_stats) { std::set<const char*> missing_stats = StatsTypes(); bool verify_successful = true; std::vector<const RTCTransportStats*> transport_stats = @@ -396,7 +395,7 @@ class RTCStatsReportVerifier { stats.cast_to<RTCInboundRTPStreamStats>()); } else if (stats.type() == RTCOutboundRTPStreamStats::kType) { verify_successful &= VerifyRTCOutboundRTPStreamStats( - stats.cast_to<RTCOutboundRTPStreamStats>(), enable_simulcast_stats); + stats.cast_to<RTCOutboundRTPStreamStats>()); } else if (stats.type() == RTCRemoteInboundRtpStreamStats::kType) { verify_successful &= VerifyRTCRemoteInboundRtpStreamStats( stats.cast_to<RTCRemoteInboundRtpStreamStats>()); @@ -461,7 +460,7 @@ class RTCStatsReportVerifier { RTCStatsVerifier verifier(report_, &data_channel); verifier.TestMemberIsDefined(data_channel.label); verifier.TestMemberIsDefined(data_channel.protocol); - verifier.TestMemberIsDefined(data_channel.datachannelid); + verifier.TestMemberIsDefined(data_channel.data_channel_identifier); verifier.TestMemberIsDefined(data_channel.state); verifier.TestMemberIsNonNegative<uint32_t>(data_channel.messages_sent); verifier.TestMemberIsNonNegative<uint64_t>(data_channel.bytes_sent); @@ -866,8 +865,7 @@ class RTCStatsReportVerifier { } bool VerifyRTCOutboundRTPStreamStats( - const RTCOutboundRTPStreamStats& outbound_stream, - bool enable_simulcast_stats) { + const RTCOutboundRTPStreamStats& outbound_stream) { RTCStatsVerifier verifier(report_, &outbound_stream); VerifyRTCRTPStreamStats(outbound_stream, &verifier); if (outbound_stream.media_type.is_defined() && @@ -912,24 +910,23 @@ class RTCStatsReportVerifier { // this to be present. verifier.MarkMemberTested(outbound_stream.content_type, true); verifier.TestMemberIsDefined(outbound_stream.encoder_implementation); - if (enable_simulcast_stats) { + // Unless an implementation-specific amount of time has passed and at + // least one frame has been encoded, undefined is reported. Because it + // is hard to tell what is the case here, we treat FPS as optional. + // TODO(hbos): Update the tests to run until all implemented metrics + // should be populated. + if (outbound_stream.frames_per_second.is_defined()) { verifier.TestMemberIsNonNegative<double>( outbound_stream.frames_per_second); - verifier.TestMemberIsNonNegative<uint32_t>( - outbound_stream.frame_height); - verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.frame_width); - verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.frames_sent); - verifier.TestMemberIsNonNegative<uint32_t>( - outbound_stream.huge_frames_sent); - verifier.MarkMemberTested(outbound_stream.rid, true); } else { verifier.TestMemberIsUndefined(outbound_stream.frames_per_second); - verifier.TestMemberIsUndefined(outbound_stream.frame_height); - verifier.TestMemberIsUndefined(outbound_stream.frame_width); - verifier.TestMemberIsUndefined(outbound_stream.frames_sent); - verifier.TestMemberIsUndefined(outbound_stream.huge_frames_sent); - verifier.TestMemberIsUndefined(outbound_stream.rid); } + verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.frame_height); + verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.frame_width); + verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.frames_sent); + verifier.TestMemberIsNonNegative<uint32_t>( + outbound_stream.huge_frames_sent); + verifier.MarkMemberTested(outbound_stream.rid, true); } else { verifier.TestMemberIsUndefined(outbound_stream.frames_encoded); verifier.TestMemberIsUndefined(outbound_stream.key_frames_encoded); @@ -1044,9 +1041,7 @@ TEST_F(RTCStatsIntegrationTest, GetStatsFromCaller) { StartCall(); rtc::scoped_refptr<const RTCStatsReport> report = GetStatsFromCaller(); - RTCStatsReportVerifier(report.get()) - .VerifyReport({}, - caller_->pc()->GetConfiguration().enable_simulcast_stats); + RTCStatsReportVerifier(report.get()).VerifyReport({}); #if RTC_TRACE_EVENTS_ENABLED EXPECT_EQ(report->ToJson(), RTCStatsReportTraceListener::last_trace()); @@ -1057,9 +1052,7 @@ TEST_F(RTCStatsIntegrationTest, GetStatsFromCallee) { StartCall(); rtc::scoped_refptr<const RTCStatsReport> report = GetStatsFromCallee(); - RTCStatsReportVerifier(report.get()) - .VerifyReport({}, - caller_->pc()->GetConfiguration().enable_simulcast_stats); + RTCStatsReportVerifier(report.get()).VerifyReport({}); #if RTC_TRACE_EVENTS_ENABLED EXPECT_EQ(report->ToJson(), RTCStatsReportTraceListener::last_trace()); @@ -1083,9 +1076,7 @@ TEST_F(RTCStatsIntegrationTest, GetStatsWithSenderSelector) { RTCMediaStreamStats::kType, RTCDataChannelStats::kType, }; - RTCStatsReportVerifier(report.get()) - .VerifyReport(allowed_missing_stats, - caller_->pc()->GetConfiguration().enable_simulcast_stats); + RTCStatsReportVerifier(report.get()).VerifyReport(allowed_missing_stats); EXPECT_TRUE(report->size()); } @@ -1104,9 +1095,7 @@ TEST_F(RTCStatsIntegrationTest, GetStatsWithReceiverSelector) { RTCMediaStreamStats::kType, RTCDataChannelStats::kType, }; - RTCStatsReportVerifier(report.get()) - .VerifyReport(allowed_missing_stats, - caller_->pc()->GetConfiguration().enable_simulcast_stats); + RTCStatsReportVerifier(report.get()).VerifyReport(allowed_missing_stats); EXPECT_TRUE(report->size()); } diff --git a/chromium/third_party/webrtc/pc/rtp_sender_receiver_unittest.cc b/chromium/third_party/webrtc/pc/rtp_sender_receiver_unittest.cc index 9736f183b55..364e87a89f3 100644 --- a/chromium/third_party/webrtc/pc/rtp_sender_receiver_unittest.cc +++ b/chromium/third_party/webrtc/pc/rtp_sender_receiver_unittest.cc @@ -88,7 +88,7 @@ static const int kDefaultTimeout = 10000; // 10 seconds. class MockSetStreamsObserver : public webrtc::RtpSenderBase::SetStreamsObserver { public: - MOCK_METHOD0(OnSetStreams, void()); + MOCK_METHOD(void, OnSetStreams, (), (override)); }; } // namespace @@ -123,14 +123,13 @@ class RtpSenderReceiverTest voice_channel_ = channel_manager_.CreateVoiceChannel( &fake_call_, cricket::MediaConfig(), rtp_transport_.get(), - MediaTransportConfig(), rtc::Thread::Current(), cricket::CN_AUDIO, - srtp_required, webrtc::CryptoOptions(), &ssrc_generator_, - cricket::AudioOptions()); + rtc::Thread::Current(), cricket::CN_AUDIO, srtp_required, + webrtc::CryptoOptions(), &ssrc_generator_, cricket::AudioOptions()); video_channel_ = channel_manager_.CreateVideoChannel( &fake_call_, cricket::MediaConfig(), rtp_transport_.get(), - MediaTransportConfig(), rtc::Thread::Current(), cricket::CN_VIDEO, - srtp_required, webrtc::CryptoOptions(), &ssrc_generator_, - cricket::VideoOptions(), video_bitrate_allocator_factory_.get()); + rtc::Thread::Current(), cricket::CN_VIDEO, srtp_required, + webrtc::CryptoOptions(), &ssrc_generator_, cricket::VideoOptions(), + video_bitrate_allocator_factory_.get()); voice_channel_->Enable(true); video_channel_->Enable(true); voice_media_channel_ = media_engine_->GetVoiceChannel(0); diff --git a/chromium/third_party/webrtc/pc/rtp_transceiver.cc b/chromium/third_party/webrtc/pc/rtp_transceiver.cc index d6e5ff46a12..b4e500bbc8d 100644 --- a/chromium/third_party/webrtc/pc/rtp_transceiver.cc +++ b/chromium/third_party/webrtc/pc/rtp_transceiver.cc @@ -114,7 +114,7 @@ RtpTransceiver::RtpTransceiver( : unified_plan_(true), media_type_(sender->media_type()), channel_manager_(channel_manager), - HeaderExtensionsToOffer_(std::move(header_extensions_offered)) { + header_extensions_to_offer_(std::move(header_extensions_offered)) { RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO || media_type_ == cricket::MEDIA_TYPE_VIDEO); RTC_DCHECK_EQ(sender->media_type(), receiver->media_type()); @@ -356,7 +356,51 @@ RTCError RtpTransceiver::SetCodecPreferences( std::vector<RtpHeaderExtensionCapability> RtpTransceiver::HeaderExtensionsToOffer() const { - return HeaderExtensionsToOffer_; + return header_extensions_to_offer_; +} + +RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions( + rtc::ArrayView<const RtpHeaderExtensionCapability> + header_extensions_to_offer) { + for (const auto& entry : header_extensions_to_offer) { + // Handle unsupported requests for mandatory extensions as per + // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface. + // Note: + // - We do not handle setOfferedRtpHeaderExtensions algorithm step 2.1, + // this has to be checked on a higher level. We naturally error out + // in the handling of Step 2.2 if an unset URI is encountered. + + // Step 2.2. + // Handle unknown extensions. + auto it = std::find_if( + header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(), + [&entry](const auto& offered) { return entry.uri == offered.uri; }); + if (it == header_extensions_to_offer_.end()) { + return RTCError(RTCErrorType::INVALID_PARAMETER, + "Attempted to modify an unoffered extension."); + } + + // Step 2.4-2.5. + // - Use of the transceiver interface indicates unified plan is in effect, + // hence the MID extension needs to be enabled. + // - Also handle the mandatory video orientation extensions. + if ((entry.uri == RtpExtension::kMidUri || + entry.uri == RtpExtension::kVideoRotationUri) && + entry.direction != RtpTransceiverDirection::kSendRecv) { + return RTCError(RTCErrorType::INVALID_MODIFICATION, + "Attempted to stop a mandatory extension."); + } + } + + // Apply mutation after error checking. + for (const auto& entry : header_extensions_to_offer) { + auto it = std::find_if( + header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(), + [&entry](const auto& offered) { return entry.uri == offered.uri; }); + it->direction = entry.direction; + } + + return RTCError::OK(); } } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/rtp_transceiver.h b/chromium/third_party/webrtc/pc/rtp_transceiver.h index 0668447b9f1..be46ccfd5c1 100644 --- a/chromium/third_party/webrtc/pc/rtp_transceiver.h +++ b/chromium/third_party/webrtc/pc/rtp_transceiver.h @@ -195,6 +195,9 @@ class RtpTransceiver final } std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer() const override; + RTCError SetOfferedRtpHeaderExtensions( + rtc::ArrayView<const RtpHeaderExtensionCapability> + header_extensions_to_offer) override; private: void OnFirstPacketReceived(cricket::ChannelInterface* channel); @@ -220,7 +223,7 @@ class RtpTransceiver final cricket::ChannelInterface* channel_ = nullptr; cricket::ChannelManager* channel_manager_ = nullptr; std::vector<RtpCodecCapability> codec_preferences_; - std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer_; + std::vector<RtpHeaderExtensionCapability> header_extensions_to_offer_; }; BEGIN_SIGNALING_PROXY_MAP(RtpTransceiver) @@ -241,6 +244,9 @@ PROXY_METHOD1(webrtc::RTCError, PROXY_CONSTMETHOD0(std::vector<RtpCodecCapability>, codec_preferences) PROXY_CONSTMETHOD0(std::vector<RtpHeaderExtensionCapability>, HeaderExtensionsToOffer) +PROXY_METHOD1(webrtc::RTCError, + SetOfferedRtpHeaderExtensions, + rtc::ArrayView<const RtpHeaderExtensionCapability>) END_PROXY_MAP() } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/rtp_transceiver_unittest.cc b/chromium/third_party/webrtc/pc/rtp_transceiver_unittest.cc index 5e345739f17..e3f05c4dd92 100644 --- a/chromium/third_party/webrtc/pc/rtp_transceiver_unittest.cc +++ b/chromium/third_party/webrtc/pc/rtp_transceiver_unittest.cc @@ -25,6 +25,7 @@ using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Field; using ::testing::Not; +using ::testing::Property; using ::testing::Return; using ::testing::ReturnRef; @@ -78,27 +79,95 @@ TEST(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) { EXPECT_EQ(nullptr, transceiver.channel()); } -TEST(RtpTransceiverTest, - InitsWithChannelManagerRtpHeaderExtensionCapabilities) { - cricket::ChannelManager channel_manager( - std::make_unique<cricket::FakeMediaEngine>(), - std::make_unique<cricket::FakeDataEngine>(), rtc::Thread::Current(), - rtc::Thread::Current()); - std::vector<RtpHeaderExtensionCapability> extensions({ - RtpHeaderExtensionCapability("uri1", 1, - RtpTransceiverDirection::kSendRecv), - RtpHeaderExtensionCapability("uri2", 2, - RtpTransceiverDirection::kRecvOnly), - }); - RtpTransceiver transceiver( - RtpSenderProxyWithInternal<RtpSenderInternal>::Create( - rtc::Thread::Current(), - new rtc::RefCountedObject<MockRtpSenderInternal>()), - RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( - rtc::Thread::Current(), - new rtc::RefCountedObject<MockRtpReceiverInternal>()), - &channel_manager, extensions); - EXPECT_EQ(transceiver.HeaderExtensionsToOffer(), extensions); +class RtpTransceiverTestForHeaderExtensions : public ::testing::Test { + public: + RtpTransceiverTestForHeaderExtensions() + : channel_manager_(std::make_unique<cricket::FakeMediaEngine>(), + std::make_unique<cricket::FakeDataEngine>(), + rtc::Thread::Current(), + rtc::Thread::Current()), + extensions_( + {RtpHeaderExtensionCapability("uri1", + 1, + RtpTransceiverDirection::kSendOnly), + RtpHeaderExtensionCapability("uri2", + 2, + RtpTransceiverDirection::kRecvOnly), + RtpHeaderExtensionCapability(RtpExtension::kMidUri, + 3, + RtpTransceiverDirection::kSendRecv), + RtpHeaderExtensionCapability(RtpExtension::kVideoRotationUri, + 4, + RtpTransceiverDirection::kSendRecv)}), + transceiver_(RtpSenderProxyWithInternal<RtpSenderInternal>::Create( + rtc::Thread::Current(), + new rtc::RefCountedObject<MockRtpSenderInternal>()), + RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create( + rtc::Thread::Current(), + new rtc::RefCountedObject<MockRtpReceiverInternal>()), + &channel_manager_, + extensions_) {} + + cricket::ChannelManager channel_manager_; + std::vector<RtpHeaderExtensionCapability> extensions_; + RtpTransceiver transceiver_; +}; + +TEST_F(RtpTransceiverTestForHeaderExtensions, OffersChannelManagerList) { + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_); +} + +TEST_F(RtpTransceiverTestForHeaderExtensions, ModifiesDirection) { + auto modified_extensions = extensions_; + modified_extensions[0].direction = RtpTransceiverDirection::kSendOnly; + EXPECT_TRUE( + transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok()); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions); + modified_extensions[0].direction = RtpTransceiverDirection::kRecvOnly; + EXPECT_TRUE( + transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok()); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions); + modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv; + EXPECT_TRUE( + transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok()); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions); + modified_extensions[0].direction = RtpTransceiverDirection::kInactive; + EXPECT_TRUE( + transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok()); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions); +} + +TEST_F(RtpTransceiverTestForHeaderExtensions, AcceptsStoppedExtension) { + auto modified_extensions = extensions_; + modified_extensions[0].direction = RtpTransceiverDirection::kStopped; + EXPECT_TRUE( + transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions).ok()); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), modified_extensions); +} + +TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsUnsupportedExtension) { + std::vector<RtpHeaderExtensionCapability> modified_extensions( + {RtpHeaderExtensionCapability("uri3", 1, + RtpTransceiverDirection::kSendRecv)}); + EXPECT_THAT(transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions), + Property(&RTCError::type, RTCErrorType::INVALID_PARAMETER)); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_); +} + +TEST_F(RtpTransceiverTestForHeaderExtensions, + RejectsStoppedMandatoryExtensions) { + std::vector<RtpHeaderExtensionCapability> modified_extensions = extensions_; + // Attempting to stop the mandatory MID extension. + modified_extensions[2].direction = RtpTransceiverDirection::kStopped; + EXPECT_THAT(transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions), + Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION)); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_); + modified_extensions = extensions_; + // Attempting to stop the mandatory video orientation extension. + modified_extensions[3].direction = RtpTransceiverDirection::kStopped; + EXPECT_THAT(transceiver_.SetOfferedRtpHeaderExtensions(modified_extensions), + Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION)); + EXPECT_EQ(transceiver_.HeaderExtensionsToOffer(), extensions_); } } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/sctp_utils.cc b/chromium/third_party/webrtc/pc/sctp_utils.cc index 9cdff0e4da6..1882a1525f7 100644 --- a/chromium/third_party/webrtc/pc/sctp_utils.cc +++ b/chromium/third_party/webrtc/pc/sctp_utils.cc @@ -13,6 +13,7 @@ #include <stddef.h> #include <stdint.h> +#include "api/priority.h" #include "rtc_base/byte_buffer.h" #include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/logging.h" @@ -34,6 +35,15 @@ enum DataChannelOpenMessageChannelType { DCOMCT_UNORDERED_PARTIAL_TIME = 0x82, }; +// Values of priority in the DC open protocol message. +// These are compared against an integer, so are enum, not enum class. +enum DataChannelPriority { + DCO_PRIORITY_VERY_LOW = 128, + DCO_PRIORITY_LOW = 256, + DCO_PRIORITY_MEDIUM = 512, + DCO_PRIORITY_HIGH = 1024, +}; + bool IsOpenMessage(const rtc::CopyOnWriteBuffer& payload) { // Format defined at // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04 @@ -76,6 +86,18 @@ bool ParseDataChannelOpenMessage(const rtc::CopyOnWriteBuffer& payload, << "Could not read OPEN message reliabilility prioirty."; return false; } + // Parse priority as defined in + // https://w3c.github.io/webrtc-priority/#rtcdatachannel-processing-steps + if (priority <= DCO_PRIORITY_VERY_LOW) { + config->priority = Priority::kVeryLow; + } else if (priority <= DCO_PRIORITY_LOW) { + config->priority = Priority::kLow; + } else if (priority <= DCO_PRIORITY_MEDIUM) { + config->priority = Priority::kMedium; + } else { + config->priority = Priority::kHigh; + } + uint32_t reliability_param; if (!buffer.ReadUInt32(&reliability_param)) { RTC_LOG(LS_WARNING) << "Could not read OPEN message reliabilility param."; @@ -146,6 +168,24 @@ bool WriteDataChannelOpenMessage(const std::string& label, uint8_t channel_type = 0; uint32_t reliability_param = 0; uint16_t priority = 0; + // Set priority according to + // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-12#section-6.4 + if (config.priority) { + switch (*config.priority) { + case Priority::kVeryLow: + priority = DCO_PRIORITY_VERY_LOW; + break; + case Priority::kLow: + priority = DCO_PRIORITY_LOW; + break; + case Priority::kMedium: + priority = DCO_PRIORITY_MEDIUM; + break; + case Priority::kHigh: + priority = DCO_PRIORITY_HIGH; + break; + } + } if (config.ordered) { if (config.maxRetransmits) { channel_type = DCOMCT_ORDERED_PARTIAL_RTXS; diff --git a/chromium/third_party/webrtc/pc/sctp_utils_unittest.cc b/chromium/third_party/webrtc/pc/sctp_utils_unittest.cc index 70c627714da..690a9dc5239 100644 --- a/chromium/third_party/webrtc/pc/sctp_utils_unittest.cc +++ b/chromium/third_party/webrtc/pc/sctp_utils_unittest.cc @@ -45,6 +45,13 @@ class SctpUtilsTest : public ::testing::Test { } ASSERT_TRUE(buffer.ReadUInt16(&priority)); + if (config.priority) { + // Exact values are checked by round-trip conversion, but + // all values defined are greater than zero. + EXPECT_GT(priority, 0); + } else { + EXPECT_EQ(priority, 0); + } ASSERT_TRUE(buffer.ReadUInt32(&reliability)); if (config.maxRetransmits || config.maxRetransmitTime) { @@ -136,6 +143,27 @@ TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) { EXPECT_FALSE(output_config.maxRetransmitTime); } +TEST_F(SctpUtilsTest, WriteParseOpenMessageWithPriority) { + webrtc::DataChannelInit config; + std::string label = "abc"; + config.protocol = "y"; + config.priority = webrtc::Priority::kVeryLow; + + rtc::CopyOnWriteBuffer packet; + ASSERT_TRUE(webrtc::WriteDataChannelOpenMessage(label, config, &packet)); + + VerifyOpenMessageFormat(packet, label, config); + + std::string output_label; + webrtc::DataChannelInit output_config; + ASSERT_TRUE(webrtc::ParseDataChannelOpenMessage(packet, &output_label, + &output_config)); + + EXPECT_EQ(label, output_label); + ASSERT_TRUE(output_config.priority); + EXPECT_EQ(*config.priority, *output_config.priority); +} + TEST_F(SctpUtilsTest, WriteParseAckMessage) { rtc::CopyOnWriteBuffer packet; webrtc::WriteDataChannelOpenAckMessage(&packet); diff --git a/chromium/third_party/webrtc/pc/session_description.h b/chromium/third_party/webrtc/pc/session_description.h index bfd19b8c7ad..27142e1c726 100644 --- a/chromium/third_party/webrtc/pc/session_description.h +++ b/chromium/third_party/webrtc/pc/session_description.h @@ -253,13 +253,6 @@ class MediaContentDescription { receive_rids_ = rids; } - virtual const absl::optional<std::string>& alt_protocol() const { - return alt_protocol_; - } - virtual void set_alt_protocol(const absl::optional<std::string>& protocol) { - alt_protocol_ = protocol; - } - protected: bool rtcp_mux_ = false; bool rtcp_reduced_size_ = false; @@ -282,8 +275,6 @@ class MediaContentDescription { SimulcastDescription simulcast_; std::vector<RidDescription> receive_rids_; - absl::optional<std::string> alt_protocol_; - private: // Copy function that returns a raw pointer. Caller will assert ownership. // Should only be called by the Clone() function. Must be implemented diff --git a/chromium/third_party/webrtc/pc/stats_collector.cc b/chromium/third_party/webrtc/pc/stats_collector.cc index 0509c6dc19c..317e4443d41 100644 --- a/chromium/third_party/webrtc/pc/stats_collector.cc +++ b/chromium/third_party/webrtc/pc/stats_collector.cc @@ -1146,19 +1146,20 @@ void StatsCollector::ExtractDataInfo() { rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; - for (const auto& dc : pc_->sctp_data_channels()) { + std::vector<DataChannel::Stats> data_stats = pc_->GetDataChannelStats(); + for (const auto& stats : data_stats) { StatsReport::Id id(StatsReport::NewTypedIntId( - StatsReport::kStatsReportTypeDataChannel, dc->id())); + StatsReport::kStatsReportTypeDataChannel, stats.id)); StatsReport* report = reports_.ReplaceOrAddNew(id); report->set_timestamp(stats_gathering_started_); - report->AddString(StatsReport::kStatsValueNameLabel, dc->label()); + report->AddString(StatsReport::kStatsValueNameLabel, stats.label); // Filter out the initial id (-1). - if (dc->id() >= 0) { - report->AddInt(StatsReport::kStatsValueNameDataChannelId, dc->id()); + if (stats.id >= 0) { + report->AddInt(StatsReport::kStatsValueNameDataChannelId, stats.id); } - report->AddString(StatsReport::kStatsValueNameProtocol, dc->protocol()); + report->AddString(StatsReport::kStatsValueNameProtocol, stats.protocol); report->AddString(StatsReport::kStatsValueNameState, - DataChannelInterface::DataStateString(dc->state())); + DataChannelInterface::DataStateString(stats.state)); } } diff --git a/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.cc b/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.cc index db0886ddad4..1a7efd4ad12 100644 --- a/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.cc +++ b/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.cc @@ -47,7 +47,9 @@ FakeAudioCaptureModule::FakeAudioCaptureModule() current_mic_level_(kMaxVolume), started_(false), next_frame_time_(0), - frames_received_(0) {} + frames_received_(0) { + process_thread_checker_.Detach(); +} FakeAudioCaptureModule::~FakeAudioCaptureModule() { if (process_thread_) { @@ -77,7 +79,7 @@ int32_t FakeAudioCaptureModule::ActiveAudioLayer( int32_t FakeAudioCaptureModule::RegisterAudioCallback( webrtc::AudioTransport* audio_callback) { - rtc::CritScope cs(&crit_callback_); + rtc::CritScope cs(&crit_); audio_callback_ = audio_callback; return 0; } @@ -448,29 +450,34 @@ void FakeAudioCaptureModule::UpdateProcessing(bool start) { if (process_thread_) { process_thread_->Stop(); process_thread_.reset(nullptr); + process_thread_checker_.Detach(); } + rtc::CritScope lock(&crit_); started_ = false; } } void FakeAudioCaptureModule::StartProcessP() { - RTC_CHECK(process_thread_->IsCurrent()); - if (started_) { - // Already started. - return; + RTC_DCHECK_RUN_ON(&process_thread_checker_); + { + rtc::CritScope lock(&crit_); + if (started_) { + // Already started. + return; + } } ProcessFrameP(); } void FakeAudioCaptureModule::ProcessFrameP() { - RTC_CHECK(process_thread_->IsCurrent()); - if (!started_) { - next_frame_time_ = rtc::TimeMillis(); - started_ = true; - } - + RTC_DCHECK_RUN_ON(&process_thread_checker_); { rtc::CritScope cs(&crit_); + if (!started_) { + next_frame_time_ = rtc::TimeMillis(); + started_ = true; + } + // Receive and send frames every kTimePerFrameMs. if (playing_) { ReceiveFrameP(); @@ -488,24 +495,22 @@ void FakeAudioCaptureModule::ProcessFrameP() { } void FakeAudioCaptureModule::ReceiveFrameP() { - RTC_CHECK(process_thread_->IsCurrent()); - { - rtc::CritScope cs(&crit_callback_); - if (!audio_callback_) { - return; - } - ResetRecBuffer(); - size_t nSamplesOut = 0; - int64_t elapsed_time_ms = 0; - int64_t ntp_time_ms = 0; - if (audio_callback_->NeedMorePlayData( - kNumberSamples, kNumberBytesPerSample, kNumberOfChannels, - kSamplesPerSecond, rec_buffer_, nSamplesOut, &elapsed_time_ms, - &ntp_time_ms) != 0) { - RTC_NOTREACHED(); - } - RTC_CHECK(nSamplesOut == kNumberSamples); + RTC_DCHECK_RUN_ON(&process_thread_checker_); + if (!audio_callback_) { + return; + } + ResetRecBuffer(); + size_t nSamplesOut = 0; + int64_t elapsed_time_ms = 0; + int64_t ntp_time_ms = 0; + if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample, + kNumberOfChannels, kSamplesPerSecond, + rec_buffer_, nSamplesOut, + &elapsed_time_ms, &ntp_time_ms) != 0) { + RTC_NOTREACHED(); } + RTC_CHECK(nSamplesOut == kNumberSamples); + // The SetBuffer() function ensures that after decoding, the audio buffer // should contain samples of similar magnitude (there is likely to be some // distortion due to the audio pipeline). If one sample is detected to @@ -513,25 +518,22 @@ void FakeAudioCaptureModule::ReceiveFrameP() { // has been received from the remote side (i.e. faked frames are not being // pulled). if (CheckRecBuffer(kHighSampleValue)) { - rtc::CritScope cs(&crit_); ++frames_received_; } } void FakeAudioCaptureModule::SendFrameP() { - RTC_CHECK(process_thread_->IsCurrent()); - rtc::CritScope cs(&crit_callback_); + RTC_DCHECK_RUN_ON(&process_thread_checker_); if (!audio_callback_) { return; } bool key_pressed = false; - uint32_t current_mic_level = 0; - MicrophoneVolume(¤t_mic_level); + uint32_t current_mic_level = current_mic_level_; if (audio_callback_->RecordedDataIsAvailable( send_buffer_, kNumberSamples, kNumberBytesPerSample, kNumberOfChannels, kSamplesPerSecond, kTotalDelayMs, kClockDriftMs, current_mic_level, key_pressed, current_mic_level) != 0) { RTC_NOTREACHED(); } - SetMicrophoneVolume(current_mic_level); + current_mic_level_ = current_mic_level; } diff --git a/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.h b/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.h index 0af38102908..2a5d54c84e4 100644 --- a/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.h +++ b/chromium/third_party/webrtc/pc/test/fake_audio_capture_module.h @@ -26,13 +26,14 @@ #include "modules/audio_device/include/audio_device.h" #include "rtc_base/critical_section.h" #include "rtc_base/message_handler.h" +#include "rtc_base/synchronization/sequence_checker.h" namespace rtc { class Thread; } // namespace rtc class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, - public rtc::MessageHandler { + public rtc::MessageHandlerAutoCleanup { public: typedef uint16_t Sample; @@ -47,13 +48,13 @@ class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, // Returns the number of frames that have been successfully pulled by the // instance. Note that correctly detecting success can only be done if the // pulled frame was generated/pushed from a FakeAudioCaptureModule. - int frames_received() const; + int frames_received() const RTC_LOCKS_EXCLUDED(crit_); int32_t ActiveAudioLayer(AudioLayer* audio_layer) const override; // Note: Calling this method from a callback may result in deadlock. - int32_t RegisterAudioCallback( - webrtc::AudioTransport* audio_callback) override; + int32_t RegisterAudioCallback(webrtc::AudioTransport* audio_callback) override + RTC_LOCKS_EXCLUDED(crit_); int32_t Init() override; int32_t Terminate() override; @@ -80,12 +81,12 @@ class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, int32_t InitRecording() override; bool RecordingIsInitialized() const override; - int32_t StartPlayout() override; - int32_t StopPlayout() override; - bool Playing() const override; - int32_t StartRecording() override; - int32_t StopRecording() override; - bool Recording() const override; + int32_t StartPlayout() RTC_LOCKS_EXCLUDED(crit_) override; + int32_t StopPlayout() RTC_LOCKS_EXCLUDED(crit_) override; + bool Playing() const RTC_LOCKS_EXCLUDED(crit_) override; + int32_t StartRecording() RTC_LOCKS_EXCLUDED(crit_) override; + int32_t StopRecording() RTC_LOCKS_EXCLUDED(crit_) override; + bool Recording() const RTC_LOCKS_EXCLUDED(crit_) override; int32_t InitSpeaker() override; bool SpeakerIsInitialized() const override; @@ -99,8 +100,10 @@ class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, int32_t MinSpeakerVolume(uint32_t* min_volume) const override; int32_t MicrophoneVolumeIsAvailable(bool* available) override; - int32_t SetMicrophoneVolume(uint32_t volume) override; - int32_t MicrophoneVolume(uint32_t* volume) const override; + int32_t SetMicrophoneVolume(uint32_t volume) + RTC_LOCKS_EXCLUDED(crit_) override; + int32_t MicrophoneVolume(uint32_t* volume) const + RTC_LOCKS_EXCLUDED(crit_) override; int32_t MaxMicrophoneVolume(uint32_t* max_volume) const override; int32_t MinMicrophoneVolume(uint32_t* min_volume) const override; @@ -170,26 +173,28 @@ class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, // Returns true/false depending on if recording or playback has been // enabled/started. - bool ShouldStartProcessing(); + bool ShouldStartProcessing() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); // Starts or stops the pushing and pulling of audio frames. - void UpdateProcessing(bool start); + void UpdateProcessing(bool start) RTC_LOCKS_EXCLUDED(crit_); // Starts the periodic calling of ProcessFrame() in a thread safe way. void StartProcessP(); // Periodcally called function that ensures that frames are pulled and pushed // periodically if enabled/started. - void ProcessFrameP(); + void ProcessFrameP() RTC_LOCKS_EXCLUDED(crit_); // Pulls frames from the registered webrtc::AudioTransport. - void ReceiveFrameP(); + void ReceiveFrameP() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); // Pushes frames to the registered webrtc::AudioTransport. - void SendFrameP(); + void SendFrameP() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); // Callback for playout and recording. - webrtc::AudioTransport* audio_callback_; + webrtc::AudioTransport* audio_callback_ RTC_GUARDED_BY(crit_); - bool recording_; // True when audio is being pushed from the instance. - bool playing_; // True when audio is being pulled by the instance. + bool recording_ RTC_GUARDED_BY( + crit_); // True when audio is being pushed from the instance. + bool playing_ RTC_GUARDED_BY( + crit_); // True when audio is being pulled by the instance. bool play_is_initialized_; // True when the instance is ready to pull audio. bool rec_is_initialized_; // True when the instance is ready to push audio. @@ -197,13 +202,13 @@ class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, // Input to and output from RecordedDataIsAvailable(..) makes it possible to // modify the current mic level. The implementation does not care about the // mic level so it just feeds back what it receives. - uint32_t current_mic_level_; + uint32_t current_mic_level_ RTC_GUARDED_BY(crit_); // next_frame_time_ is updated in a non-drifting manner to indicate the next // wall clock time the next frame should be generated and received. started_ // ensures that next_frame_time_ can be initialized properly on first call. - bool started_; - int64_t next_frame_time_; + bool started_ RTC_GUARDED_BY(crit_); + int64_t next_frame_time_ RTC_GUARDED_BY(process_thread_checker_); std::unique_ptr<rtc::Thread> process_thread_; @@ -220,9 +225,7 @@ class FakeAudioCaptureModule : public webrtc::AudioDeviceModule, // Protects variables that are accessed from process_thread_ and // the main thread. rtc::CriticalSection crit_; - // Protects |audio_callback_| that is accessed from process_thread_ and - // the main thread. - rtc::CriticalSection crit_callback_; + webrtc::SequenceChecker process_thread_checker_; }; #endif // PC_TEST_FAKE_AUDIO_CAPTURE_MODULE_H_ diff --git a/chromium/third_party/webrtc/pc/test/fake_peer_connection_base.h b/chromium/third_party/webrtc/pc/test/fake_peer_connection_base.h index f4b27f03e18..e1663e6d9f8 100644 --- a/chromium/third_party/webrtc/pc/test/fake_peer_connection_base.h +++ b/chromium/third_party/webrtc/pc/test/fake_peer_connection_base.h @@ -254,11 +254,6 @@ class FakePeerConnectionBase : public PeerConnectionInternal { cricket::RtpDataChannel* rtp_data_channel() const override { return nullptr; } - std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels() - const override { - return {}; - } - absl::optional<std::string> sctp_transport_name() const override { return absl::nullopt; } diff --git a/chromium/third_party/webrtc/pc/test/fake_peer_connection_for_stats.h b/chromium/third_party/webrtc/pc/test/fake_peer_connection_for_stats.h index c6391583f57..175a1ede153 100644 --- a/chromium/third_party/webrtc/pc/test/fake_peer_connection_for_stats.h +++ b/chromium/third_party/webrtc/pc/test/fake_peer_connection_for_stats.h @@ -174,8 +174,10 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { void AddSctpDataChannel(const std::string& label, const InternalDataChannelInit& init) { - AddSctpDataChannel(DataChannel::Create(&data_channel_provider_, - cricket::DCT_SCTP, label, init)); + // TODO(bugs.webrtc.org/11547): Supply a separate network thread. + AddSctpDataChannel(DataChannel::Create( + &data_channel_provider_, cricket::DCT_SCTP, label, init, + rtc::Thread::Current(), rtc::Thread::Current())); } void AddSctpDataChannel(rtc::scoped_refptr<DataChannel> data_channel) { @@ -257,9 +259,12 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { return transceivers_; } - std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels() - const override { - return sctp_data_channels_; + std::vector<DataChannel::Stats> GetDataChannelStats() const override { + RTC_DCHECK_RUN_ON(signaling_thread()); + std::vector<DataChannel::Stats> stats; + for (const auto& channel : sctp_data_channels_) + stats.push_back(channel->GetStats()); + return stats; } cricket::CandidateStatsList GetPooledCandidateStats() const override { diff --git a/chromium/third_party/webrtc/pc/test/fake_periodic_video_source.h b/chromium/third_party/webrtc/pc/test/fake_periodic_video_source.h index 1684ca4adbb..b1cff4e5edc 100644 --- a/chromium/third_party/webrtc/pc/test/fake_periodic_video_source.h +++ b/chromium/third_party/webrtc/pc/test/fake_periodic_video_source.h @@ -16,6 +16,7 @@ #include "api/video/video_source_interface.h" #include "media/base/fake_frame_source.h" #include "media/base/video_broadcaster.h" +#include "rtc_base/critical_section.h" #include "rtc_base/task_queue_for_test.h" #include "rtc_base/task_utils/repeating_task.h" @@ -59,6 +60,11 @@ class FakePeriodicVideoSource final }); } + rtc::VideoSinkWants wants() const { + rtc::CritScope cs(&crit_); + return wants_; + } + void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override { RTC_DCHECK(thread_checker_.IsCurrent()); broadcaster_.RemoveSink(sink); @@ -67,6 +73,10 @@ class FakePeriodicVideoSource final void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink, const rtc::VideoSinkWants& wants) override { RTC_DCHECK(thread_checker_.IsCurrent()); + { + rtc::CritScope cs(&crit_); + wants_ = wants; + } broadcaster_.AddOrUpdateSink(sink, wants); } @@ -80,6 +90,8 @@ class FakePeriodicVideoSource final rtc::VideoBroadcaster broadcaster_; cricket::FakeFrameSource frame_source_; + rtc::CriticalSection crit_; + rtc::VideoSinkWants wants_ RTC_GUARDED_BY(&crit_); std::unique_ptr<TaskQueueForTest> task_queue_; }; diff --git a/chromium/third_party/webrtc/pc/test/fake_periodic_video_track_source.h b/chromium/third_party/webrtc/pc/test/fake_periodic_video_track_source.h index cc406d6d3fc..98a456f2328 100644 --- a/chromium/third_party/webrtc/pc/test/fake_periodic_video_track_source.h +++ b/chromium/third_party/webrtc/pc/test/fake_periodic_video_track_source.h @@ -29,6 +29,10 @@ class FakePeriodicVideoTrackSource : public VideoTrackSource { ~FakePeriodicVideoTrackSource() = default; + const FakePeriodicVideoSource& fake_periodic_source() const { + return source_; + } + protected: rtc::VideoSourceInterface<VideoFrame>* source() override { return &source_; } diff --git a/chromium/third_party/webrtc/pc/test/fake_rtc_certificate_generator.h b/chromium/third_party/webrtc/pc/test/fake_rtc_certificate_generator.h index 9c43ba97262..b726a4c0ba8 100644 --- a/chromium/third_party/webrtc/pc/test/fake_rtc_certificate_generator.h +++ b/chromium/third_party/webrtc/pc/test/fake_rtc_certificate_generator.h @@ -118,7 +118,7 @@ static const rtc::RTCCertificatePEM kEcdsaPems[] = { class FakeRTCCertificateGenerator : public rtc::RTCCertificateGeneratorInterface, - public rtc::MessageHandler { + public rtc::MessageHandlerAutoCleanup { public: typedef rtc::TypedMessageData< rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback> > diff --git a/chromium/third_party/webrtc/pc/test/mock_channel_interface.h b/chromium/third_party/webrtc/pc/test/mock_channel_interface.h index 255bd2fceec..2df3baee47e 100644 --- a/chromium/third_party/webrtc/pc/test/mock_channel_interface.h +++ b/chromium/third_party/webrtc/pc/test/mock_channel_interface.h @@ -24,25 +24,40 @@ namespace cricket { // implementation of BaseChannel. class MockChannelInterface : public cricket::ChannelInterface { public: - MOCK_CONST_METHOD0(media_type, cricket::MediaType()); - MOCK_CONST_METHOD0(media_channel, MediaChannel*()); - MOCK_CONST_METHOD0(transport_name, const std::string&()); - MOCK_CONST_METHOD0(content_name, const std::string&()); - MOCK_CONST_METHOD0(enabled, bool()); - MOCK_METHOD1(Enable, bool(bool)); - MOCK_METHOD0(SignalFirstPacketReceived, - sigslot::signal1<ChannelInterface*>&()); - MOCK_METHOD3(SetLocalContent, - bool(const cricket::MediaContentDescription*, - webrtc::SdpType, - std::string*)); - MOCK_METHOD3(SetRemoteContent, - bool(const cricket::MediaContentDescription*, - webrtc::SdpType, - std::string*)); - MOCK_CONST_METHOD0(local_streams, const std::vector<StreamParams>&()); - MOCK_CONST_METHOD0(remote_streams, const std::vector<StreamParams>&()); - MOCK_METHOD1(SetRtpTransport, bool(webrtc::RtpTransportInternal*)); + MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); + MOCK_METHOD(MediaChannel*, media_channel, (), (const, override)); + MOCK_METHOD(const std::string&, transport_name, (), (const, override)); + MOCK_METHOD(const std::string&, content_name, (), (const, override)); + MOCK_METHOD(bool, enabled, (), (const, override)); + MOCK_METHOD(bool, Enable, (bool), (override)); + MOCK_METHOD(sigslot::signal1<ChannelInterface*>&, + SignalFirstPacketReceived, + (), + (override)); + MOCK_METHOD(bool, + SetLocalContent, + (const cricket::MediaContentDescription*, + webrtc::SdpType, + std::string*), + (override)); + MOCK_METHOD(bool, + SetRemoteContent, + (const cricket::MediaContentDescription*, + webrtc::SdpType, + std::string*), + (override)); + MOCK_METHOD(const std::vector<StreamParams>&, + local_streams, + (), + (const, override)); + MOCK_METHOD(const std::vector<StreamParams>&, + remote_streams, + (), + (const, override)); + MOCK_METHOD(bool, + SetRtpTransport, + (webrtc::RtpTransportInternal*), + (override)); }; } // namespace cricket diff --git a/chromium/third_party/webrtc/pc/test/mock_data_channel.h b/chromium/third_party/webrtc/pc/test/mock_data_channel.h index 3385ec2f75c..bc5f94da5f7 100644 --- a/chromium/third_party/webrtc/pc/test/mock_data_channel.h +++ b/chromium/third_party/webrtc/pc/test/mock_data_channel.h @@ -22,15 +22,24 @@ class MockDataChannel : public rtc::RefCountedObject<DataChannel> { public: MockDataChannel(int id, DataState state) : MockDataChannel(id, "MockDataChannel", state, "udp", 0, 0, 0, 0) {} - MockDataChannel(int id, - const std::string& label, - DataState state, - const std::string& protocol, - uint32_t messages_sent, - uint64_t bytes_sent, - uint32_t messages_received, - uint64_t bytes_received) - : rtc::RefCountedObject<DataChannel>(nullptr, cricket::DCT_NONE, label) { + MockDataChannel( + int id, + const std::string& label, + DataState state, + const std::string& protocol, + uint32_t messages_sent, + uint64_t bytes_sent, + uint32_t messages_received, + uint64_t bytes_received, + const InternalDataChannelInit& config = InternalDataChannelInit(), + rtc::Thread* signaling_thread = rtc::Thread::Current(), + rtc::Thread* network_thread = rtc::Thread::Current()) + : rtc::RefCountedObject<DataChannel>(config, + nullptr, + cricket::DCT_NONE, + label, + signaling_thread, + network_thread) { EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id)); EXPECT_CALL(*this, state()).WillRepeatedly(::testing::Return(state)); EXPECT_CALL(*this, protocol()).WillRepeatedly(::testing::Return(protocol)); @@ -43,13 +52,13 @@ class MockDataChannel : public rtc::RefCountedObject<DataChannel> { EXPECT_CALL(*this, bytes_received()) .WillRepeatedly(::testing::Return(bytes_received)); } - MOCK_CONST_METHOD0(id, int()); - MOCK_CONST_METHOD0(state, DataState()); - MOCK_CONST_METHOD0(protocol, std::string()); - MOCK_CONST_METHOD0(messages_sent, uint32_t()); - MOCK_CONST_METHOD0(bytes_sent, uint64_t()); - MOCK_CONST_METHOD0(messages_received, uint32_t()); - MOCK_CONST_METHOD0(bytes_received, uint64_t()); + MOCK_METHOD(int, id, (), (const, override)); + MOCK_METHOD(DataState, state, (), (const, override)); + MOCK_METHOD(std::string, protocol, (), (const, override)); + MOCK_METHOD(uint32_t, messages_sent, (), (const, override)); + MOCK_METHOD(uint64_t, bytes_sent, (), (const, override)); + MOCK_METHOD(uint32_t, messages_received, (), (const, override)); + MOCK_METHOD(uint64_t, bytes_received, (), (const, override)); }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/test/mock_delayable.h b/chromium/third_party/webrtc/pc/test/mock_delayable.h index 548f9f8c0a8..bef07c1970f 100644 --- a/chromium/third_party/webrtc/pc/test/mock_delayable.h +++ b/chromium/third_party/webrtc/pc/test/mock_delayable.h @@ -21,9 +21,14 @@ namespace webrtc { class MockDelayable : public cricket::Delayable { public: - MOCK_METHOD2(SetBaseMinimumPlayoutDelayMs, bool(uint32_t ssrc, int delay_ms)); - MOCK_CONST_METHOD1(GetBaseMinimumPlayoutDelayMs, - absl::optional<int>(uint32_t ssrc)); + MOCK_METHOD(bool, + SetBaseMinimumPlayoutDelayMs, + (uint32_t ssrc, int delay_ms), + (override)); + MOCK_METHOD(absl::optional<int>, + GetBaseMinimumPlayoutDelayMs, + (uint32_t ssrc), + (const, override)); }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/test/mock_rtp_receiver_internal.h b/chromium/third_party/webrtc/pc/test/mock_rtp_receiver_internal.h index ffe78b52304..779dcdcf086 100644 --- a/chromium/third_party/webrtc/pc/test/mock_rtp_receiver_internal.h +++ b/chromium/third_party/webrtc/pc/test/mock_rtp_receiver_internal.h @@ -24,37 +24,54 @@ namespace webrtc { class MockRtpReceiverInternal : public RtpReceiverInternal { public: // RtpReceiverInterface methods. - MOCK_METHOD1(SetTrack, void(MediaStreamTrackInterface*)); - MOCK_CONST_METHOD0(track, rtc::scoped_refptr<MediaStreamTrackInterface>()); - MOCK_CONST_METHOD0(dtls_transport, - rtc::scoped_refptr<DtlsTransportInterface>()); - MOCK_CONST_METHOD0(stream_ids, std::vector<std::string>()); - MOCK_CONST_METHOD0(streams, - std::vector<rtc::scoped_refptr<MediaStreamInterface>>()); - MOCK_CONST_METHOD0(media_type, cricket::MediaType()); - MOCK_CONST_METHOD0(id, std::string()); - MOCK_CONST_METHOD0(GetParameters, RtpParameters()); - MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*)); - MOCK_METHOD1(SetJitterBufferMinimumDelay, void(absl::optional<double>)); - MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>()); - MOCK_METHOD1(SetFrameDecryptor, - void(rtc::scoped_refptr<FrameDecryptorInterface>)); - MOCK_CONST_METHOD0(GetFrameDecryptor, - rtc::scoped_refptr<FrameDecryptorInterface>()); + MOCK_METHOD(rtc::scoped_refptr<MediaStreamTrackInterface>, + track, + (), + (const, override)); + MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>, + dtls_transport, + (), + (const, override)); + MOCK_METHOD(std::vector<std::string>, stream_ids, (), (const, override)); + MOCK_METHOD(std::vector<rtc::scoped_refptr<MediaStreamInterface>>, + streams, + (), + (const, override)); + MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); + MOCK_METHOD(std::string, id, (), (const, override)); + MOCK_METHOD(RtpParameters, GetParameters, (), (const, override)); + MOCK_METHOD(void, SetObserver, (RtpReceiverObserverInterface*), (override)); + MOCK_METHOD(void, + SetJitterBufferMinimumDelay, + (absl::optional<double>), + (override)); + MOCK_METHOD(std::vector<RtpSource>, GetSources, (), (const, override)); + MOCK_METHOD(void, + SetFrameDecryptor, + (rtc::scoped_refptr<FrameDecryptorInterface>), + (override)); + MOCK_METHOD(rtc::scoped_refptr<FrameDecryptorInterface>, + GetFrameDecryptor, + (), + (const, override)); // RtpReceiverInternal methods. - MOCK_METHOD0(Stop, void()); - MOCK_METHOD1(SetMediaChannel, void(cricket::MediaChannel*)); - MOCK_METHOD1(SetupMediaChannel, void(uint32_t)); - MOCK_METHOD0(SetupUnsignaledMediaChannel, void()); - MOCK_CONST_METHOD0(ssrc, uint32_t()); - MOCK_METHOD0(NotifyFirstPacketReceived, void()); - MOCK_METHOD1(set_stream_ids, void(std::vector<std::string>)); - MOCK_METHOD1(set_transport, void(rtc::scoped_refptr<DtlsTransportInterface>)); - MOCK_METHOD1( - SetStreams, - void(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&)); - MOCK_CONST_METHOD0(AttachmentId, int()); + MOCK_METHOD(void, Stop, (), (override)); + MOCK_METHOD(void, SetMediaChannel, (cricket::MediaChannel*), (override)); + MOCK_METHOD(void, SetupMediaChannel, (uint32_t), (override)); + MOCK_METHOD(void, SetupUnsignaledMediaChannel, (), (override)); + MOCK_METHOD(uint32_t, ssrc, (), (const, override)); + MOCK_METHOD(void, NotifyFirstPacketReceived, (), (override)); + MOCK_METHOD(void, set_stream_ids, (std::vector<std::string>), (override)); + MOCK_METHOD(void, + set_transport, + (rtc::scoped_refptr<DtlsTransportInterface>), + (override)); + MOCK_METHOD(void, + SetStreams, + (const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&), + (override)); + MOCK_METHOD(int, AttachmentId, (), (const, override)); }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/test/mock_rtp_sender_internal.h b/chromium/third_party/webrtc/pc/test/mock_rtp_sender_internal.h index 2cf0173bd1c..1a31c5dac69 100644 --- a/chromium/third_party/webrtc/pc/test/mock_rtp_sender_internal.h +++ b/chromium/third_party/webrtc/pc/test/mock_rtp_sender_internal.h @@ -23,37 +23,65 @@ namespace webrtc { class MockRtpSenderInternal : public RtpSenderInternal { public: // RtpSenderInterface methods. - MOCK_METHOD1(SetTrack, bool(MediaStreamTrackInterface*)); - MOCK_CONST_METHOD0(track, rtc::scoped_refptr<MediaStreamTrackInterface>()); - MOCK_CONST_METHOD0(ssrc, uint32_t()); - MOCK_CONST_METHOD0(dtls_transport, - rtc::scoped_refptr<DtlsTransportInterface>()); - MOCK_CONST_METHOD0(media_type, cricket::MediaType()); - MOCK_CONST_METHOD0(id, std::string()); - MOCK_CONST_METHOD0(stream_ids, std::vector<std::string>()); - MOCK_CONST_METHOD0(init_send_encodings, std::vector<RtpEncodingParameters>()); - MOCK_METHOD1(set_transport, void(rtc::scoped_refptr<DtlsTransportInterface>)); - MOCK_CONST_METHOD0(GetParameters, RtpParameters()); - MOCK_CONST_METHOD0(GetParametersInternal, RtpParameters()); - MOCK_METHOD1(SetParameters, RTCError(const RtpParameters&)); - MOCK_METHOD1(SetParametersInternal, RTCError(const RtpParameters&)); - MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr<DtmfSenderInterface>()); - MOCK_METHOD1(SetFrameEncryptor, - void(rtc::scoped_refptr<FrameEncryptorInterface>)); - MOCK_CONST_METHOD0(GetFrameEncryptor, - rtc::scoped_refptr<FrameEncryptorInterface>()); + MOCK_METHOD(bool, SetTrack, (MediaStreamTrackInterface*), (override)); + MOCK_METHOD(rtc::scoped_refptr<MediaStreamTrackInterface>, + track, + (), + (const, override)); + MOCK_METHOD(uint32_t, ssrc, (), (const, override)); + MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>, + dtls_transport, + (), + (const, override)); + MOCK_METHOD(cricket::MediaType, media_type, (), (const, override)); + MOCK_METHOD(std::string, id, (), (const, override)); + MOCK_METHOD(std::vector<std::string>, stream_ids, (), (const, override)); + MOCK_METHOD(std::vector<RtpEncodingParameters>, + init_send_encodings, + (), + (const, override)); + MOCK_METHOD(void, + set_transport, + (rtc::scoped_refptr<DtlsTransportInterface>), + (override)); + MOCK_METHOD(RtpParameters, GetParameters, (), (const, override)); + MOCK_METHOD(RtpParameters, GetParametersInternal, (), (const, override)); + MOCK_METHOD(RTCError, SetParameters, (const RtpParameters&), (override)); + MOCK_METHOD(RTCError, + SetParametersInternal, + (const RtpParameters&), + (override)); + MOCK_METHOD(rtc::scoped_refptr<DtmfSenderInterface>, + GetDtmfSender, + (), + (const, override)); + MOCK_METHOD(void, + SetFrameEncryptor, + (rtc::scoped_refptr<FrameEncryptorInterface>), + (override)); + MOCK_METHOD(rtc::scoped_refptr<FrameEncryptorInterface>, + GetFrameEncryptor, + (), + (const, override)); // RtpSenderInternal methods. - MOCK_METHOD1(SetMediaChannel, void(cricket::MediaChannel*)); - MOCK_METHOD1(SetSsrc, void(uint32_t)); - MOCK_METHOD1(set_stream_ids, void(const std::vector<std::string>&)); - MOCK_METHOD1(SetStreams, void(const std::vector<std::string>&)); - MOCK_METHOD1(set_init_send_encodings, - void(const std::vector<RtpEncodingParameters>&)); - MOCK_METHOD0(Stop, void()); - MOCK_CONST_METHOD0(AttachmentId, int()); - MOCK_METHOD1(DisableEncodingLayers, - RTCError(const std::vector<std::string>&)); + MOCK_METHOD(void, SetMediaChannel, (cricket::MediaChannel*), (override)); + MOCK_METHOD(void, SetSsrc, (uint32_t), (override)); + MOCK_METHOD(void, + set_stream_ids, + (const std::vector<std::string>&), + (override)); + MOCK_METHOD(void, SetStreams, (const std::vector<std::string>&), (override)); + MOCK_METHOD(void, + set_init_send_encodings, + (const std::vector<RtpEncodingParameters>&), + (override)); + MOCK_METHOD(void, Stop, (), (override)); + MOCK_METHOD(int, AttachmentId, (), (const, override)); + MOCK_METHOD(RTCError, + DisableEncodingLayers, + (const std::vector<std::string>&), + (override)); }; } // namespace webrtc diff --git a/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.cc b/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.cc index 4f0d72e6675..946f459f3b7 100644 --- a/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.cc +++ b/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.cc @@ -80,7 +80,8 @@ PeerConnectionTestWrapper::PeerConnectionTestWrapper( rtc::Thread* worker_thread) : name_(name), network_thread_(network_thread), - worker_thread_(worker_thread) { + worker_thread_(worker_thread), + pending_negotiation_(false) { pc_thread_checker_.Detach(); } @@ -135,6 +136,17 @@ PeerConnectionTestWrapper::CreateDataChannel( return peer_connection_->CreateDataChannel(label, &init); } +void PeerConnectionTestWrapper::WaitForNegotiation() { + EXPECT_TRUE_WAIT(!pending_negotiation_, kMaxWait); +} + +void PeerConnectionTestWrapper::OnSignalingChange( + webrtc::PeerConnectionInterface::SignalingState new_state) { + if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable) { + pending_negotiation_ = false; + } +} + void PeerConnectionTestWrapper::OnAddTrack( rtc::scoped_refptr<RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) { @@ -182,6 +194,7 @@ void PeerConnectionTestWrapper::OnSuccess(SessionDescriptionInterface* desc) { void PeerConnectionTestWrapper::CreateOffer( const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options) { RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": CreateOffer."; + pending_negotiation_ = true; peer_connection_->CreateOffer(this, options); } @@ -189,6 +202,7 @@ void PeerConnectionTestWrapper::CreateAnswer( const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options) { RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": CreateAnswer."; + pending_negotiation_ = true; peer_connection_->CreateAnswer(this, options); } diff --git a/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.h b/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.h index 2dc88e93095..92599b78ab9 100644 --- a/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.h +++ b/chromium/third_party/webrtc/pc/test/peer_connection_test_wrapper.h @@ -49,15 +49,21 @@ class PeerConnectionTestWrapper rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory, rtc::scoped_refptr<webrtc::AudioDecoderFactory> audio_decoder_factory); + rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory() + const { + return peer_connection_factory_; + } webrtc::PeerConnectionInterface* pc() { return peer_connection_.get(); } rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel( const std::string& label, const webrtc::DataChannelInit& init); + void WaitForNegotiation(); + // Implements PeerConnectionObserver. void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) override {} + webrtc::PeerConnectionInterface::SignalingState new_state) override; void OnAddTrack( rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& @@ -121,6 +127,7 @@ class PeerConnectionTestWrapper rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_; std::unique_ptr<webrtc::FakeVideoTrackRenderer> renderer_; int num_get_user_media_calls_ = 0; + bool pending_negotiation_; }; #endif // PC_TEST_PEER_CONNECTION_TEST_WRAPPER_H_ diff --git a/chromium/third_party/webrtc/pc/track_media_info_map_unittest.cc b/chromium/third_party/webrtc/pc/track_media_info_map_unittest.cc index c487ab8f816..0cb1e0e2777 100644 --- a/chromium/third_party/webrtc/pc/track_media_info_map_unittest.cc +++ b/chromium/third_party/webrtc/pc/track_media_info_map_unittest.cc @@ -83,19 +83,21 @@ rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockRtpReceiver( class TrackMediaInfoMapTest : public ::testing::Test { public: - TrackMediaInfoMapTest() + TrackMediaInfoMapTest() : TrackMediaInfoMapTest(true) {} + + explicit TrackMediaInfoMapTest(bool use_current_thread) : voice_media_info_(new cricket::VoiceMediaInfo()), video_media_info_(new cricket::VideoMediaInfo()), local_audio_track_(AudioTrack::Create("LocalAudioTrack", nullptr)), remote_audio_track_(AudioTrack::Create("RemoteAudioTrack", nullptr)), - local_video_track_( - VideoTrack::Create("LocalVideoTrack", - FakeVideoTrackSource::Create(false), - rtc::Thread::Current())), - remote_video_track_( - VideoTrack::Create("RemoteVideoTrack", - FakeVideoTrackSource::Create(false), - rtc::Thread::Current())) {} + local_video_track_(VideoTrack::Create( + "LocalVideoTrack", + FakeVideoTrackSource::Create(false), + use_current_thread ? rtc::Thread::Current() : nullptr)), + remote_video_track_(VideoTrack::Create( + "RemoteVideoTrack", + FakeVideoTrackSource::Create(false), + use_current_thread ? rtc::Thread::Current() : nullptr)) {} ~TrackMediaInfoMapTest() { // If we have a map the ownership has been passed to the map, only delete if @@ -417,7 +419,10 @@ TEST_F(TrackMediaInfoMapTest, GetAttachmentIdByTrack) { // base/test/gtest_util.h. #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) -class TrackMediaInfoMapDeathTest : public TrackMediaInfoMapTest {}; +class TrackMediaInfoMapDeathTest : public TrackMediaInfoMapTest { + public: + TrackMediaInfoMapDeathTest() : TrackMediaInfoMapTest(false) {} +}; TEST_F(TrackMediaInfoMapDeathTest, MultipleOneSsrcReceiversPerTrack) { AddRtpReceiverWithSsrcs({1}, remote_audio_track_); diff --git a/chromium/third_party/webrtc/pc/video_rtp_receiver_unittest.cc b/chromium/third_party/webrtc/pc/video_rtp_receiver_unittest.cc index c4b7b8205d0..b3eb6e6e355 100644 --- a/chromium/third_party/webrtc/pc/video_rtp_receiver_unittest.cc +++ b/chromium/third_party/webrtc/pc/video_rtp_receiver_unittest.cc @@ -32,16 +32,20 @@ class VideoRtpReceiverTest : public testing::Test { MockVideoMediaChannel(cricket::FakeVideoEngine* engine, const cricket::VideoOptions& options) : FakeVideoMediaChannel(engine, options) {} - MOCK_METHOD2(SetRecordableEncodedFrameCallback, - void(uint32_t, - std::function<void(const RecordableEncodedFrame&)>)); - MOCK_METHOD1(ClearRecordableEncodedFrameCallback, void(uint32_t)); - MOCK_METHOD1(GenerateKeyFrame, void(uint32_t)); + MOCK_METHOD(void, + SetRecordableEncodedFrameCallback, + (uint32_t, std::function<void(const RecordableEncodedFrame&)>), + (override)); + MOCK_METHOD(void, + ClearRecordableEncodedFrameCallback, + (uint32_t), + (override)); + MOCK_METHOD(void, GenerateKeyFrame, (uint32_t), (override)); }; class MockVideoSink : public rtc::VideoSinkInterface<RecordableEncodedFrame> { public: - MOCK_METHOD1(OnFrame, void(const RecordableEncodedFrame&)); + MOCK_METHOD(void, OnFrame, (const RecordableEncodedFrame&), (override)); }; VideoRtpReceiverTest() diff --git a/chromium/third_party/webrtc/pc/video_rtp_track_source_unittest.cc b/chromium/third_party/webrtc/pc/video_rtp_track_source_unittest.cc index ed26db36549..ea1b4cacf87 100644 --- a/chromium/third_party/webrtc/pc/video_rtp_track_source_unittest.cc +++ b/chromium/third_party/webrtc/pc/video_rtp_track_source_unittest.cc @@ -19,13 +19,13 @@ namespace { class MockCallback : public VideoRtpTrackSource::Callback { public: - MOCK_METHOD0(OnGenerateKeyFrame, void()); - MOCK_METHOD1(OnEncodedSinkEnabled, void(bool)); + MOCK_METHOD(void, OnGenerateKeyFrame, (), (override)); + MOCK_METHOD(void, OnEncodedSinkEnabled, (bool), (override)); }; class MockSink : public rtc::VideoSinkInterface<RecordableEncodedFrame> { public: - MOCK_METHOD1(OnFrame, void(const RecordableEncodedFrame&)); + MOCK_METHOD(void, OnFrame, (const RecordableEncodedFrame&), (override)); }; rtc::scoped_refptr<VideoRtpTrackSource> MakeSource( diff --git a/chromium/third_party/webrtc/pc/webrtc_sdp.cc b/chromium/third_party/webrtc/pc/webrtc_sdp.cc index f77327faf1e..90a00c1479f 100644 --- a/chromium/third_party/webrtc/pc/webrtc_sdp.cc +++ b/chromium/third_party/webrtc/pc/webrtc_sdp.cc @@ -229,12 +229,6 @@ static const char kApplicationSpecificMaximum[] = "AS"; static const char kDefaultSctpmapProtocol[] = "webrtc-datachannel"; -// This is a non-standardized setting for plugin transports. -static const char kOpaqueTransportParametersLine[] = "x-opaque"; - -// This is a non-standardized setting for plugin transports. -static const char kAltProtocolLine[] = "x-alt-protocol"; - // RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload // types. const int kWildcardPayloadType = -1; @@ -523,25 +517,6 @@ static void InitAttrLine(const std::string& attribute, rtc::StringBuilder* os) { InitLine(kLineTypeAttributes, attribute, os); } -// Adds an x-otp SDP attribute line based on opaque transport parameters. -static void AddOpaqueTransportLine( - const cricket::OpaqueTransportParameters params, - std::string* message) { - rtc::StringBuilder os; - InitAttrLine(kOpaqueTransportParametersLine, &os); - os << kSdpDelimiterColon << params.protocol << kSdpDelimiterColon - << rtc::Base64::Encode(params.parameters); - AddLine(os.str(), message); -} - -static void AddAltProtocolLine(const std::string& protocol, - std::string* message) { - rtc::StringBuilder os; - InitAttrLine(kAltProtocolLine, &os); - os << kSdpDelimiterColon << protocol; - AddLine(os.str(), message); -} - // Writes a SDP attribute line based on |attribute| and |value| to |message|. static void AddAttributeLine(const std::string& attribute, int value, @@ -1532,15 +1507,6 @@ void BuildMediaDescription(const ContentInfo* content_info, AddLine(os.str(), message); } } - - if (transport_info->description.opaque_parameters) { - AddOpaqueTransportLine(*transport_info->description.opaque_parameters, - message); - } - } - - if (media_desc->alt_protocol()) { - AddAltProtocolLine(*media_desc->alt_protocol(), message); } // RFC 3388 @@ -2105,32 +2071,6 @@ bool ParseConnectionData(const std::string& line, return true; } -bool ParseOpaqueTransportLine(const std::string& line, - std::string* protocol, - std::string* transport_parameters, - SdpParseError* error) { - std::string value; - if (!GetValue(line, kOpaqueTransportParametersLine, &value, error)) { - return false; - } - std::string tmp_parameters; - if (!rtc::tokenize_first(value, kSdpDelimiterColonChar, protocol, - &tmp_parameters)) { - return ParseFailedGetValue(line, kOpaqueTransportParametersLine, error); - } - if (!rtc::Base64::Decode(tmp_parameters, rtc::Base64::DO_STRICT, - transport_parameters, nullptr)) { - return ParseFailedGetValue(line, kOpaqueTransportParametersLine, error); - } - return true; -} - -bool ParseAltProtocolLine(const std::string& line, - std::string* protocol, - SdpParseError* error) { - return GetValue(line, kAltProtocolLine, protocol, error); -} - bool ParseSessionDescription(const std::string& message, size_t* pos, std::string* session_id, @@ -3137,19 +3077,6 @@ bool ParseContent(const std::string& message, if (!ParseIceOptions(line, &transport->transport_options, error)) { return false; } - } else if (HasAttribute(line, kOpaqueTransportParametersLine)) { - transport->opaque_parameters = cricket::OpaqueTransportParameters(); - if (!ParseOpaqueTransportLine( - line, &transport->opaque_parameters->protocol, - &transport->opaque_parameters->parameters, error)) { - return false; - } - } else if (HasAttribute(line, kAltProtocolLine)) { - std::string alt_protocol; - if (!ParseAltProtocolLine(line, &alt_protocol, error)) { - return false; - } - media_desc->set_alt_protocol(alt_protocol); } else if (HasAttribute(line, kAttributeFmtp)) { if (!ParseFmtpAttributes(line, media_type, media_desc, error)) { return false; diff --git a/chromium/third_party/webrtc/pc/webrtc_sdp_unittest.cc b/chromium/third_party/webrtc/pc/webrtc_sdp_unittest.cc index a2ad4b8bdc6..4279de67eea 100644 --- a/chromium/third_party/webrtc/pc/webrtc_sdp_unittest.cc +++ b/chromium/third_party/webrtc/pc/webrtc_sdp_unittest.cc @@ -1528,8 +1528,6 @@ class WebRtcSdpTest : public ::testing::Test { CompareSimulcastDescription( c1.media_description()->simulcast_description(), c2.media_description()->simulcast_description()); - EXPECT_EQ(c1.media_description()->alt_protocol(), - c2.media_description()->alt_protocol()); } // group @@ -1584,8 +1582,6 @@ class WebRtcSdpTest : public ::testing::Test { } EXPECT_EQ(transport1.description.transport_options, transport2.description.transport_options); - EXPECT_EQ(transport1.description.opaque_parameters, - transport2.description.opaque_parameters); } // global attributes @@ -1679,23 +1675,6 @@ class WebRtcSdpTest : public ::testing::Test { desc_.AddTransportInfo(transport_info); } - void AddOpaqueTransportParameters(const std::string& content_name, - cricket::OpaqueTransportParameters params) { - ASSERT_TRUE(desc_.GetTransportInfoByName(content_name) != NULL); - cricket::TransportInfo info = *(desc_.GetTransportInfoByName(content_name)); - desc_.RemoveTransportInfoByName(content_name); - info.description.opaque_parameters = params; - desc_.AddTransportInfo(info); - } - - void AddAltProtocol(const std::string& content_name, - const std::string& alt_protocol) { - ASSERT_TRUE(desc_.GetTransportInfoByName(content_name) != NULL); - cricket::MediaContentDescription* description = - desc_.GetContentDescriptionByName(content_name); - description->set_alt_protocol(alt_protocol); - } - void AddFingerprint() { desc_.RemoveTransportInfoByName(kAudioContentName); desc_.RemoveTransportInfoByName(kVideoContentName); @@ -2236,41 +2215,6 @@ TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithIceOptions) { EXPECT_EQ(sdp_with_ice_options, message); } -TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithOpaqueTransportParams) { - cricket::OpaqueTransportParameters params; - params.protocol = "foo"; - params.parameters = "test64"; - AddOpaqueTransportParameters(kAudioContentName, params); - AddOpaqueTransportParameters(kVideoContentName, params); - - ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), - jdesc_.session_version())); - std::string message = webrtc::SdpSerialize(jdesc_); - - std::string sdp_with_transport_parameters = kSdpFullString; - InjectAfter(kAttributeIcePwdVoice, "a=x-opaque:foo:dGVzdDY0\r\n", - &sdp_with_transport_parameters); - InjectAfter(kAttributeIcePwdVideo, "a=x-opaque:foo:dGVzdDY0\r\n", - &sdp_with_transport_parameters); - EXPECT_EQ(message, sdp_with_transport_parameters); -} - -TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithAltProtocol) { - AddAltProtocol(kAudioContentName, "foo"); - AddAltProtocol(kVideoContentName, "bar"); - - ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), - jdesc_.session_version())); - std::string message = webrtc::SdpSerialize(jdesc_); - - std::string sdp_with_alt_protocol = kSdpFullString; - InjectAfter(kAttributeIcePwdVoice, "a=x-alt-protocol:foo\r\n", - &sdp_with_alt_protocol); - InjectAfter(kAttributeIcePwdVideo, "a=x-alt-protocol:bar\r\n", - &sdp_with_alt_protocol); - EXPECT_EQ(message, sdp_with_alt_protocol); -} - TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithRecvOnlyContent) { EXPECT_TRUE(TestSerializeDirection(RtpTransceiverDirection::kRecvOnly)); } @@ -2445,8 +2389,6 @@ TEST_F(WebRtcSdpTest, SerializeHostnameCandidate) { EXPECT_EQ(std::string(kRawHostnameCandidate), message); } -// TODO(mallinath) : Enable this test once WebRTCSdp capable of parsing -// RFC 6544. TEST_F(WebRtcSdpTest, SerializeTcpCandidates) { Candidate candidate(ICE_CANDIDATE_COMPONENT_RTP, "tcp", rtc::SocketAddress("192.168.1.5", 9), kCandidatePriority, @@ -2685,48 +2627,6 @@ TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithIceOptions) { EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_ice_options)); } -TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithOpaqueTransportParams) { - std::string sdp_with_transport_parameters = kSdpFullString; - InjectAfter(kAttributeIcePwdVoice, "a=x-opaque:foo:dGVzdDY0\r\n", - &sdp_with_transport_parameters); - InjectAfter(kAttributeIcePwdVideo, "a=x-opaque:foo:dGVzdDY0\r\n", - &sdp_with_transport_parameters); - - JsepSessionDescription jdesc_with_transport_parameters(kDummyType); - EXPECT_TRUE(SdpDeserialize(sdp_with_transport_parameters, - &jdesc_with_transport_parameters)); - - cricket::OpaqueTransportParameters params; - params.protocol = "foo"; - params.parameters = "test64"; - - AddOpaqueTransportParameters(kAudioContentName, params); - AddOpaqueTransportParameters(kVideoContentName, params); - - ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), - jdesc_.session_version())); - EXPECT_TRUE( - CompareSessionDescription(jdesc_, jdesc_with_transport_parameters)); -} - -TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithAltProtocol) { - std::string sdp_with_alt_protocol = kSdpFullString; - InjectAfter(kAttributeIcePwdVoice, "a=x-alt-protocol:foo\r\n", - &sdp_with_alt_protocol); - InjectAfter(kAttributeIcePwdVideo, "a=x-alt-protocol:bar\r\n", - &sdp_with_alt_protocol); - - JsepSessionDescription jdesc_with_alt_protocol(kDummyType); - EXPECT_TRUE(SdpDeserialize(sdp_with_alt_protocol, &jdesc_with_alt_protocol)); - - AddAltProtocol(kAudioContentName, "foo"); - AddAltProtocol(kVideoContentName, "bar"); - - ASSERT_TRUE(jdesc_.Initialize(desc_.Clone(), jdesc_.session_id(), - jdesc_.session_version())); - EXPECT_TRUE(CompareSessionDescription(jdesc_, jdesc_with_alt_protocol)); -} - TEST_F(WebRtcSdpTest, DeserializeSessionDescriptionWithUfragPwd) { // Remove the original ice-ufrag and ice-pwd JsepSessionDescription jdesc_with_ufrag_pwd(kDummyType); diff --git a/chromium/third_party/webrtc/pc/webrtc_session_description_factory.cc b/chromium/third_party/webrtc/pc/webrtc_session_description_factory.cc index aaef7fdeb67..d95174ec445 100644 --- a/chromium/third_party/webrtc/pc/webrtc_session_description_factory.cc +++ b/chromium/third_party/webrtc/pc/webrtc_session_description_factory.cc @@ -130,7 +130,8 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, const rtc::scoped_refptr<rtc::RTCCertificate>& certificate, UniqueRandomIdGenerator* ssrc_generator) - : signaling_thread_(signaling_thread), + : MessageHandler(false), + signaling_thread_(signaling_thread), session_desc_factory_(channel_manager, &transport_desc_factory_, ssrc_generator), |