2013-07-10 00:45:36 +00:00
|
|
|
/*
|
2016-02-10 07:54:43 -08:00
|
|
|
* Copyright 2012 The WebRTC project authors. All Rights Reserved.
|
2013-07-10 00:45:36 +00:00
|
|
|
*
|
2016-02-10 07:54:43 -08:00
|
|
|
* 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.
|
2013-07-10 00:45:36 +00:00
|
|
|
*/
|
|
|
|
|
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/peer_connection.h"
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-12-15 19:24:43 -08:00
|
|
|
#include <algorithm>
|
2018-05-31 14:00:34 +02:00
|
|
|
#include <limits>
|
2019-09-17 17:06:18 +02:00
|
|
|
#include <memory>
|
2017-12-22 16:02:54 -08:00
|
|
|
#include <queue>
|
2017-11-06 10:37:17 -08:00
|
|
|
#include <set>
|
2015-12-17 03:04:15 -08:00
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2019-01-28 17:25:26 -08:00
|
|
|
#include "absl/algorithm/container.h"
|
2018-12-17 21:02:22 +01:00
|
|
|
#include "absl/strings/match.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "api/jsep_ice_candidate.h"
|
|
|
|
|
#include "api/jsep_session_description.h"
|
|
|
|
|
#include "api/media_stream_proxy.h"
|
|
|
|
|
#include "api/media_stream_track_proxy.h"
|
2019-04-08 14:11:57 -07:00
|
|
|
#include "api/rtc_error.h"
|
2019-08-07 12:24:53 +02:00
|
|
|
#include "api/rtc_event_log/rtc_event_log.h"
|
2019-05-08 13:53:51 +02:00
|
|
|
#include "api/rtc_event_log_output_file.h"
|
2019-04-08 14:11:57 -07:00
|
|
|
#include "api/rtp_parameters.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "api/uma_metrics.h"
|
2019-04-17 07:38:40 +02:00
|
|
|
#include "api/video/builtin_video_bitrate_allocator_factory.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "call/call.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "logging/rtc_event_log/ice_logger.h"
|
2019-04-08 14:11:57 -07:00
|
|
|
#include "media/base/rid_description.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "media/sctp/sctp_transport.h"
|
2019-02-11 10:29:19 +01:00
|
|
|
#include "pc/audio_rtp_receiver.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/audio_track.h"
|
2017-11-06 10:37:17 -08:00
|
|
|
#include "pc/channel.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/channel_manager.h"
|
|
|
|
|
#include "pc/dtmf_sender.h"
|
|
|
|
|
#include "pc/media_stream.h"
|
|
|
|
|
#include "pc/media_stream_observer.h"
|
|
|
|
|
#include "pc/remote_audio_source.h"
|
|
|
|
|
#include "pc/rtp_media_utils.h"
|
|
|
|
|
#include "pc/rtp_receiver.h"
|
|
|
|
|
#include "pc/rtp_sender.h"
|
2019-02-28 07:51:00 +01:00
|
|
|
#include "pc/sctp_transport.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/sctp_utils.h"
|
2020-09-28 13:02:07 +00:00
|
|
|
#include "pc/sdp_offer_answer.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/sdp_utils.h"
|
|
|
|
|
#include "pc/stream_collection.h"
|
2019-02-11 10:29:19 +01:00
|
|
|
#include "pc/video_rtp_receiver.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/video_track.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/bind.h"
|
|
|
|
|
#include "rtc_base/checks.h"
|
|
|
|
|
#include "rtc_base/logging.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/string_encode.h"
|
2018-09-06 13:41:30 +02:00
|
|
|
#include "rtc_base/strings/string_builder.h"
|
2020-09-28 10:39:31 +02:00
|
|
|
#include "rtc_base/task_utils/to_queued_task.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/trace_event.h"
|
|
|
|
|
#include "system_wrappers/include/clock.h"
|
2018-07-12 12:54:53 -07:00
|
|
|
#include "system_wrappers/include/metrics.h"
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
using cricket::ContentInfo;
|
|
|
|
|
using cricket::ContentInfos;
|
|
|
|
|
using cricket::MediaContentDescription;
|
2017-12-20 16:34:00 -08:00
|
|
|
using cricket::MediaProtocolType;
|
2019-01-25 17:13:56 -08:00
|
|
|
using cricket::RidDescription;
|
|
|
|
|
using cricket::RidDirection;
|
2019-01-02 10:13:58 -08:00
|
|
|
using cricket::SessionDescription;
|
2019-01-25 17:13:56 -08:00
|
|
|
using cricket::SimulcastDescription;
|
|
|
|
|
using cricket::SimulcastLayer;
|
2019-01-02 10:13:58 -08:00
|
|
|
using cricket::SimulcastLayerList;
|
2019-01-25 17:13:56 -08:00
|
|
|
using cricket::StreamParams;
|
2017-11-06 10:37:17 -08:00
|
|
|
using cricket::TransportInfo;
|
|
|
|
|
|
|
|
|
|
using cricket::LOCAL_PORT_TYPE;
|
|
|
|
|
using cricket::PRFLX_PORT_TYPE;
|
2019-04-24 13:13:48 -07:00
|
|
|
using cricket::RELAY_PORT_TYPE;
|
|
|
|
|
using cricket::STUN_PORT_TYPE;
|
2017-11-06 10:37:17 -08:00
|
|
|
|
2017-11-06 10:21:57 -08:00
|
|
|
namespace webrtc {
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
namespace {
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2019-03-05 12:36:31 -08:00
|
|
|
// UMA metric names.
|
|
|
|
|
const char kSimulcastNumberOfEncodings[] =
|
|
|
|
|
"WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings";
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
static const char kDefaultAudioSenderId[] = "defaulta0";
|
|
|
|
|
static const char kDefaultVideoSenderId[] = "defaultv0";
|
2015-10-14 11:33:11 -07:00
|
|
|
|
2018-06-25 12:03:50 +02:00
|
|
|
static const int REPORT_USAGE_PATTERN_DELAY_MS = 60000;
|
|
|
|
|
|
2015-10-14 11:33:11 -07:00
|
|
|
|
2016-05-13 08:15:11 -07:00
|
|
|
uint32_t ConvertIceTransportTypeToCandidateFilter(
|
|
|
|
|
PeerConnectionInterface::IceTransportsType type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case PeerConnectionInterface::kNone:
|
|
|
|
|
return cricket::CF_NONE;
|
|
|
|
|
case PeerConnectionInterface::kRelay:
|
|
|
|
|
return cricket::CF_RELAY;
|
|
|
|
|
case PeerConnectionInterface::kNoHost:
|
|
|
|
|
return (cricket::CF_ALL & ~cricket::CF_HOST);
|
|
|
|
|
case PeerConnectionInterface::kAll:
|
|
|
|
|
return cricket::CF_ALL;
|
|
|
|
|
default:
|
2017-01-11 05:56:46 -08:00
|
|
|
RTC_NOTREACHED();
|
2016-05-13 08:15:11 -07:00
|
|
|
}
|
|
|
|
|
return cricket::CF_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
IceCandidatePairType GetIceCandidatePairCounter(
|
|
|
|
|
const cricket::Candidate& local,
|
|
|
|
|
const cricket::Candidate& remote) {
|
|
|
|
|
const auto& l = local.type();
|
|
|
|
|
const auto& r = remote.type();
|
|
|
|
|
const auto& host = LOCAL_PORT_TYPE;
|
|
|
|
|
const auto& srflx = STUN_PORT_TYPE;
|
|
|
|
|
const auto& relay = RELAY_PORT_TYPE;
|
|
|
|
|
const auto& prflx = PRFLX_PORT_TYPE;
|
|
|
|
|
if (l == host && r == host) {
|
2018-12-13 08:25:54 -08:00
|
|
|
bool local_hostname =
|
|
|
|
|
!local.address().hostname().empty() && local.address().IsUnresolvedIP();
|
|
|
|
|
bool remote_hostname = !remote.address().hostname().empty() &&
|
|
|
|
|
remote.address().IsUnresolvedIP();
|
2017-11-06 10:37:17 -08:00
|
|
|
bool local_private = IPIsPrivate(local.address().ipaddr());
|
|
|
|
|
bool remote_private = IPIsPrivate(remote.address().ipaddr());
|
2018-12-13 08:25:54 -08:00
|
|
|
if (local_hostname) {
|
|
|
|
|
if (remote_hostname) {
|
|
|
|
|
return kIceCandidatePairHostNameHostName;
|
|
|
|
|
} else if (remote_private) {
|
|
|
|
|
return kIceCandidatePairHostNameHostPrivate;
|
|
|
|
|
} else {
|
|
|
|
|
return kIceCandidatePairHostNameHostPublic;
|
|
|
|
|
}
|
|
|
|
|
} else if (local_private) {
|
|
|
|
|
if (remote_hostname) {
|
|
|
|
|
return kIceCandidatePairHostPrivateHostName;
|
|
|
|
|
} else if (remote_private) {
|
2017-11-06 10:37:17 -08:00
|
|
|
return kIceCandidatePairHostPrivateHostPrivate;
|
|
|
|
|
} else {
|
|
|
|
|
return kIceCandidatePairHostPrivateHostPublic;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2018-12-13 08:25:54 -08:00
|
|
|
if (remote_hostname) {
|
|
|
|
|
return kIceCandidatePairHostPublicHostName;
|
|
|
|
|
} else if (remote_private) {
|
2017-11-06 10:37:17 -08:00
|
|
|
return kIceCandidatePairHostPublicHostPrivate;
|
|
|
|
|
} else {
|
|
|
|
|
return kIceCandidatePairHostPublicHostPublic;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (l == host && r == srflx)
|
|
|
|
|
return kIceCandidatePairHostSrflx;
|
|
|
|
|
if (l == host && r == relay)
|
|
|
|
|
return kIceCandidatePairHostRelay;
|
|
|
|
|
if (l == host && r == prflx)
|
|
|
|
|
return kIceCandidatePairHostPrflx;
|
|
|
|
|
if (l == srflx && r == host)
|
|
|
|
|
return kIceCandidatePairSrflxHost;
|
|
|
|
|
if (l == srflx && r == srflx)
|
|
|
|
|
return kIceCandidatePairSrflxSrflx;
|
|
|
|
|
if (l == srflx && r == relay)
|
|
|
|
|
return kIceCandidatePairSrflxRelay;
|
|
|
|
|
if (l == srflx && r == prflx)
|
|
|
|
|
return kIceCandidatePairSrflxPrflx;
|
|
|
|
|
if (l == relay && r == host)
|
|
|
|
|
return kIceCandidatePairRelayHost;
|
|
|
|
|
if (l == relay && r == srflx)
|
|
|
|
|
return kIceCandidatePairRelaySrflx;
|
|
|
|
|
if (l == relay && r == relay)
|
|
|
|
|
return kIceCandidatePairRelayRelay;
|
|
|
|
|
if (l == relay && r == prflx)
|
|
|
|
|
return kIceCandidatePairRelayPrflx;
|
|
|
|
|
if (l == prflx && r == host)
|
|
|
|
|
return kIceCandidatePairPrflxHost;
|
|
|
|
|
if (l == prflx && r == srflx)
|
|
|
|
|
return kIceCandidatePairPrflxSrflx;
|
|
|
|
|
if (l == prflx && r == relay)
|
|
|
|
|
return kIceCandidatePairPrflxRelay;
|
|
|
|
|
return kIceCandidatePairMax;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-02 16:31:36 -07:00
|
|
|
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<int> RTCConfigurationToIceConfigOptionalInt(
|
2018-03-22 17:54:23 -07:00
|
|
|
int rtc_configuration_parameter) {
|
|
|
|
|
if (rtc_configuration_parameter ==
|
|
|
|
|
webrtc::PeerConnectionInterface::RTCConfiguration::kUndefined) {
|
2018-06-19 16:47:43 +02:00
|
|
|
return absl::nullopt;
|
2018-03-22 17:54:23 -07:00
|
|
|
}
|
|
|
|
|
return rtc_configuration_parameter;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-27 09:01:05 +02:00
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
} // namespace
|
|
|
|
|
|
2017-01-11 12:28:30 -08:00
|
|
|
bool PeerConnectionInterface::RTCConfiguration::operator==(
|
|
|
|
|
const PeerConnectionInterface::RTCConfiguration& o) const {
|
|
|
|
|
// This static_assert prevents us from accidentally breaking operator==.
|
2017-07-14 10:13:10 -07:00
|
|
|
// Note: Order matters! Fields must be ordered the same as RTCConfiguration.
|
2017-01-11 12:28:30 -08:00
|
|
|
struct stuff_being_tested_for_equality {
|
2017-07-14 14:23:56 +00:00
|
|
|
IceServers servers;
|
2017-07-14 10:13:10 -07:00
|
|
|
IceTransportsType type;
|
2017-01-11 12:28:30 -08:00
|
|
|
BundlePolicy bundle_policy;
|
|
|
|
|
RtcpMuxPolicy rtcp_mux_policy;
|
2017-07-14 10:13:10 -07:00
|
|
|
std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
|
|
|
|
|
int ice_candidate_pool_size;
|
|
|
|
|
bool disable_ipv6;
|
|
|
|
|
bool disable_ipv6_on_wifi;
|
2017-07-26 16:50:11 -07:00
|
|
|
int max_ipv6_networks;
|
2018-01-25 10:30:22 +01:00
|
|
|
bool disable_link_local_networks;
|
2017-07-14 10:13:10 -07:00
|
|
|
bool enable_rtp_data_channel;
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<int> screencast_min_bitrate;
|
|
|
|
|
absl::optional<bool> combined_audio_video_bwe;
|
|
|
|
|
absl::optional<bool> enable_dtls_srtp;
|
2017-01-11 12:28:30 -08:00
|
|
|
TcpCandidatePolicy tcp_candidate_policy;
|
|
|
|
|
CandidateNetworkPolicy candidate_network_policy;
|
|
|
|
|
int audio_jitter_buffer_max_packets;
|
|
|
|
|
bool audio_jitter_buffer_fast_accelerate;
|
2018-11-27 15:45:20 +01:00
|
|
|
int audio_jitter_buffer_min_delay_ms;
|
2019-01-10 15:58:36 +01:00
|
|
|
bool audio_jitter_buffer_enable_rtx_handling;
|
2017-01-11 12:28:30 -08:00
|
|
|
int ice_connection_receiving_timeout;
|
|
|
|
|
int ice_backup_candidate_pair_ping_interval;
|
|
|
|
|
ContinualGatheringPolicy continual_gathering_policy;
|
|
|
|
|
bool prioritize_most_likely_ice_candidate_pairs;
|
|
|
|
|
struct cricket::MediaConfig media_config;
|
|
|
|
|
bool prune_turn_ports;
|
2019-10-14 11:27:50 -07:00
|
|
|
PortPrunePolicy turn_port_prune_policy;
|
2017-01-11 12:28:30 -08:00
|
|
|
bool presume_writable_when_fully_relayed;
|
|
|
|
|
bool enable_ice_renomination;
|
|
|
|
|
bool redetermine_role_on_ice_restart;
|
2019-05-31 16:55:33 -07:00
|
|
|
bool surface_ice_candidates_on_ice_transport_type_changed;
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<int> ice_check_interval_strong_connectivity;
|
|
|
|
|
absl::optional<int> ice_check_interval_weak_connectivity;
|
|
|
|
|
absl::optional<int> ice_check_min_interval;
|
|
|
|
|
absl::optional<int> ice_unwritable_timeout;
|
|
|
|
|
absl::optional<int> ice_unwritable_min_checks;
|
2018-12-06 23:30:17 -08:00
|
|
|
absl::optional<int> ice_inactive_timeout;
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<int> stun_candidate_keepalive_interval;
|
2017-10-10 14:01:40 +02:00
|
|
|
webrtc::TurnCustomizer* turn_customizer;
|
2017-11-20 10:25:56 -08:00
|
|
|
SdpSemantics sdp_semantics;
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<rtc::AdapterType> network_preference;
|
2018-06-12 11:41:11 -07:00
|
|
|
bool active_reset_srtp_params;
|
2018-10-25 10:16:44 -07:00
|
|
|
absl::optional<CryptoOptions> crypto_options;
|
2018-11-12 10:25:48 +01:00
|
|
|
bool offer_extmap_allow_mixed;
|
2019-08-22 16:16:35 +02:00
|
|
|
std::string turn_logging_id;
|
2019-10-09 18:29:44 +03:00
|
|
|
bool enable_implicit_rollback;
|
2019-10-25 12:23:02 +02:00
|
|
|
absl::optional<bool> allow_codec_switching;
|
2017-01-11 12:28:30 -08:00
|
|
|
};
|
|
|
|
|
static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this),
|
|
|
|
|
"Did you add something to RTCConfiguration and forget to "
|
|
|
|
|
"update operator==?");
|
|
|
|
|
return type == o.type && servers == o.servers &&
|
|
|
|
|
bundle_policy == o.bundle_policy &&
|
|
|
|
|
rtcp_mux_policy == o.rtcp_mux_policy &&
|
|
|
|
|
tcp_candidate_policy == o.tcp_candidate_policy &&
|
|
|
|
|
candidate_network_policy == o.candidate_network_policy &&
|
|
|
|
|
audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets &&
|
|
|
|
|
audio_jitter_buffer_fast_accelerate ==
|
|
|
|
|
o.audio_jitter_buffer_fast_accelerate &&
|
2018-11-27 15:45:20 +01:00
|
|
|
audio_jitter_buffer_min_delay_ms ==
|
|
|
|
|
o.audio_jitter_buffer_min_delay_ms &&
|
2019-01-10 15:58:36 +01:00
|
|
|
audio_jitter_buffer_enable_rtx_handling ==
|
|
|
|
|
o.audio_jitter_buffer_enable_rtx_handling &&
|
2017-01-11 12:28:30 -08:00
|
|
|
ice_connection_receiving_timeout ==
|
|
|
|
|
o.ice_connection_receiving_timeout &&
|
|
|
|
|
ice_backup_candidate_pair_ping_interval ==
|
|
|
|
|
o.ice_backup_candidate_pair_ping_interval &&
|
|
|
|
|
continual_gathering_policy == o.continual_gathering_policy &&
|
|
|
|
|
certificates == o.certificates &&
|
|
|
|
|
prioritize_most_likely_ice_candidate_pairs ==
|
|
|
|
|
o.prioritize_most_likely_ice_candidate_pairs &&
|
|
|
|
|
media_config == o.media_config && disable_ipv6 == o.disable_ipv6 &&
|
2017-03-07 14:40:51 -08:00
|
|
|
disable_ipv6_on_wifi == o.disable_ipv6_on_wifi &&
|
2017-07-26 16:50:11 -07:00
|
|
|
max_ipv6_networks == o.max_ipv6_networks &&
|
2018-01-25 10:30:22 +01:00
|
|
|
disable_link_local_networks == o.disable_link_local_networks &&
|
2017-01-11 12:28:30 -08:00
|
|
|
enable_rtp_data_channel == o.enable_rtp_data_channel &&
|
|
|
|
|
screencast_min_bitrate == o.screencast_min_bitrate &&
|
|
|
|
|
combined_audio_video_bwe == o.combined_audio_video_bwe &&
|
|
|
|
|
enable_dtls_srtp == o.enable_dtls_srtp &&
|
|
|
|
|
ice_candidate_pool_size == o.ice_candidate_pool_size &&
|
|
|
|
|
prune_turn_ports == o.prune_turn_ports &&
|
2019-10-14 11:27:50 -07:00
|
|
|
turn_port_prune_policy == o.turn_port_prune_policy &&
|
2017-01-11 12:28:30 -08:00
|
|
|
presume_writable_when_fully_relayed ==
|
|
|
|
|
o.presume_writable_when_fully_relayed &&
|
|
|
|
|
enable_ice_renomination == o.enable_ice_renomination &&
|
2017-02-02 11:50:14 -08:00
|
|
|
redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart &&
|
2019-05-31 16:55:33 -07:00
|
|
|
surface_ice_candidates_on_ice_transport_type_changed ==
|
|
|
|
|
o.surface_ice_candidates_on_ice_transport_type_changed &&
|
2018-03-08 14:55:14 -08:00
|
|
|
ice_check_interval_strong_connectivity ==
|
|
|
|
|
o.ice_check_interval_strong_connectivity &&
|
|
|
|
|
ice_check_interval_weak_connectivity ==
|
|
|
|
|
o.ice_check_interval_weak_connectivity &&
|
2017-07-14 10:13:10 -07:00
|
|
|
ice_check_min_interval == o.ice_check_min_interval &&
|
2018-03-13 10:53:57 -07:00
|
|
|
ice_unwritable_timeout == o.ice_unwritable_timeout &&
|
|
|
|
|
ice_unwritable_min_checks == o.ice_unwritable_min_checks &&
|
2018-12-06 23:30:17 -08:00
|
|
|
ice_inactive_timeout == o.ice_inactive_timeout &&
|
2018-02-20 14:45:49 -08:00
|
|
|
stun_candidate_keepalive_interval ==
|
|
|
|
|
o.stun_candidate_keepalive_interval &&
|
2017-11-20 10:25:56 -08:00
|
|
|
turn_customizer == o.turn_customizer &&
|
2018-02-01 10:38:40 -08:00
|
|
|
sdp_semantics == o.sdp_semantics &&
|
2018-06-12 11:41:11 -07:00
|
|
|
network_preference == o.network_preference &&
|
2018-10-08 09:43:21 -07:00
|
|
|
active_reset_srtp_params == o.active_reset_srtp_params &&
|
2018-11-12 10:25:48 +01:00
|
|
|
crypto_options == o.crypto_options &&
|
2019-08-22 16:16:35 +02:00
|
|
|
offer_extmap_allow_mixed == o.offer_extmap_allow_mixed &&
|
2019-10-09 18:29:44 +03:00
|
|
|
turn_logging_id == o.turn_logging_id &&
|
2019-10-25 12:23:02 +02:00
|
|
|
enable_implicit_rollback == o.enable_implicit_rollback &&
|
2020-06-10 17:53:39 +03:00
|
|
|
allow_codec_switching == o.allow_codec_switching;
|
2017-01-11 12:28:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnectionInterface::RTCConfiguration::operator!=(
|
|
|
|
|
const PeerConnectionInterface::RTCConfiguration& o) const {
|
|
|
|
|
return !(*this == o);
|
2016-12-10 11:44:26 -08:00
|
|
|
}
|
|
|
|
|
|
2017-06-15 12:52:32 -07:00
|
|
|
PeerConnection::PeerConnection(PeerConnectionFactory* factory,
|
|
|
|
|
std::unique_ptr<RtcEventLog> event_log,
|
|
|
|
|
std::unique_ptr<Call> call)
|
2020-09-24 22:39:21 +02:00
|
|
|
: factory_(factory),
|
2017-06-15 12:52:32 -07:00
|
|
|
event_log_(std::move(event_log)),
|
2019-02-14 11:59:57 +01:00
|
|
|
event_log_ptr_(event_log_.get()),
|
2019-03-26 09:57:01 +01:00
|
|
|
call_(std::move(call)),
|
2019-07-18 11:16:56 +02:00
|
|
|
call_ptr_(call_.get()),
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_(this),
|
2020-10-05 07:01:09 +00:00
|
|
|
data_channel_controller_(this),
|
|
|
|
|
message_handler_(signaling_thread()) {}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
PeerConnection::~PeerConnection() {
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
|
2017-11-20 10:20:22 -08:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.PrepareForShutdown();
|
2019-10-28 12:09:49 +01:00
|
|
|
|
2017-12-15 11:20:13 -08:00
|
|
|
// Need to stop transceivers before destroying the stats collector because
|
|
|
|
|
// AudioRtpSender has a reference to the StatsCollector it will update when
|
|
|
|
|
// stopping.
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2020-08-11 09:54:02 +02:00
|
|
|
transceiver->StopInternal();
|
2017-12-15 11:20:13 -08:00
|
|
|
}
|
2017-11-20 10:20:22 -08:00
|
|
|
|
2016-05-13 08:15:11 -07:00
|
|
|
stats_.reset(nullptr);
|
2016-12-19 05:06:57 -08:00
|
|
|
if (stats_collector_) {
|
|
|
|
|
stats_collector_->WaitForPendingRequest();
|
|
|
|
|
stats_collector_ = nullptr;
|
|
|
|
|
}
|
2017-11-06 10:37:17 -08:00
|
|
|
|
2017-12-15 11:20:13 -08:00
|
|
|
// Don't destroy BaseChannels until after stats has been cleaned up so that
|
|
|
|
|
// the last stats request can still read from the channels.
|
2020-10-05 13:08:41 +00:00
|
|
|
sdp_handler_.DestroyAllChannels();
|
2017-12-15 11:20:13 -08:00
|
|
|
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Session: " << session_id() << " is destroyed.";
|
2017-11-06 10:37:17 -08:00
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.ResetSessionDescFactory();
|
2017-11-06 10:37:17 -08:00
|
|
|
transport_controller_.reset();
|
|
|
|
|
|
2016-05-18 16:55:30 -07:00
|
|
|
// port_allocator_ lives on the network thread and should be destroyed there.
|
2019-03-22 14:13:22 +01:00
|
|
|
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
|
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread());
|
|
|
|
|
port_allocator_.reset();
|
|
|
|
|
});
|
2017-09-06 05:18:15 -07:00
|
|
|
// call_ and event_log_ must be destroyed on the worker thread.
|
2017-09-29 12:15:02 -07:00
|
|
|
worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
|
2019-02-14 11:59:57 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2020-09-28 10:39:31 +02:00
|
|
|
call_safety_.reset();
|
2017-09-06 05:18:15 -07:00
|
|
|
call_.reset();
|
2018-01-30 17:13:09 -08:00
|
|
|
// The event log must outlive call (and any other object that uses it).
|
2017-09-06 05:18:15 -07:00
|
|
|
event_log_.reset();
|
|
|
|
|
});
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-11-11 12:55:10 -08:00
|
|
|
bool PeerConnection::Initialize(
|
|
|
|
|
const PeerConnectionInterface::RTCConfiguration& configuration,
|
2018-05-02 15:12:47 -07:00
|
|
|
PeerConnectionDependencies dependencies) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
|
2017-07-14 15:59:59 -07:00
|
|
|
|
|
|
|
|
RTCError config_error = ValidateConfiguration(configuration);
|
|
|
|
|
if (!config_error.ok()) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "Invalid configuration: " << config_error.message();
|
2017-07-14 15:59:59 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-02 15:12:47 -07:00
|
|
|
if (!dependencies.allocator) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR)
|
|
|
|
|
<< "PeerConnection initialized without a PortAllocator? "
|
2018-02-13 10:37:07 +01:00
|
|
|
"This shouldn't happen if using PeerConnectionFactory.";
|
2017-01-11 12:28:30 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2017-10-10 14:01:40 +02:00
|
|
|
|
2018-05-02 15:12:47 -07:00
|
|
|
if (!dependencies.observer) {
|
2017-01-11 12:28:30 -08:00
|
|
|
// TODO(deadbeef): Why do we do this?
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "PeerConnection initialized without a "
|
2018-02-13 10:37:07 +01:00
|
|
|
"PeerConnectionObserver";
|
2015-11-11 12:55:10 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-08 13:12:25 -07:00
|
|
|
|
2018-05-02 15:12:47 -07:00
|
|
|
observer_ = dependencies.observer;
|
2018-08-02 13:20:15 -07:00
|
|
|
async_resolver_factory_ = std::move(dependencies.async_resolver_factory);
|
2018-05-02 15:12:47 -07:00
|
|
|
port_allocator_ = std::move(dependencies.allocator);
|
2020-03-27 18:01:19 -07:00
|
|
|
packet_socket_factory_ = std::move(dependencies.packet_socket_factory);
|
2019-11-15 12:33:05 -08:00
|
|
|
ice_transport_factory_ = std::move(dependencies.ice_transport_factory);
|
2018-05-08 13:12:25 -07:00
|
|
|
tls_cert_verifier_ = std::move(dependencies.tls_cert_verifier);
|
2015-11-11 12:55:10 -08:00
|
|
|
|
2018-06-28 13:54:07 +02:00
|
|
|
cricket::ServerAddresses stun_servers;
|
|
|
|
|
std::vector<cricket::RelayServerConfig> turn_servers;
|
|
|
|
|
|
|
|
|
|
RTCErrorType parse_error =
|
|
|
|
|
ParseIceServers(configuration.servers, &stun_servers, &turn_servers);
|
|
|
|
|
if (parse_error != RTCErrorType::NONE) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 16:16:35 +02:00
|
|
|
// Add the turn logging id to all turn servers
|
|
|
|
|
for (cricket::RelayServerConfig& turn_server : turn_servers) {
|
|
|
|
|
turn_server.turn_logging_id = configuration.turn_logging_id;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-18 16:55:30 -07:00
|
|
|
// The port allocator lives on the network thread and should be initialized
|
2016-05-13 08:15:11 -07:00
|
|
|
// there.
|
2019-03-22 14:13:22 +01:00
|
|
|
const auto pa_result =
|
|
|
|
|
network_thread()->Invoke<InitializePortAllocatorResult>(
|
2018-06-28 13:54:07 +02:00
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
rtc::Bind(&PeerConnection::InitializePortAllocator_n, this,
|
2019-03-22 14:13:22 +01:00
|
|
|
stun_servers, turn_servers, configuration));
|
|
|
|
|
|
2018-06-28 13:54:07 +02:00
|
|
|
// If initialization was successful, note if STUN or TURN servers
|
|
|
|
|
// were supplied.
|
|
|
|
|
if (!stun_servers.empty()) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::STUN_SERVER_ADDED);
|
|
|
|
|
}
|
|
|
|
|
if (!turn_servers.empty()) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::TURN_SERVER_ADDED);
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2018-07-12 12:54:53 -07:00
|
|
|
// Send information about IPv4/IPv6 status.
|
|
|
|
|
PeerConnectionAddressFamilyCounter address_family;
|
2019-03-22 14:13:22 +01:00
|
|
|
if (pa_result.enable_ipv6) {
|
2018-07-12 12:54:53 -07:00
|
|
|
address_family = kPeerConnection_IPv6;
|
|
|
|
|
} else {
|
|
|
|
|
address_family = kPeerConnection_IPv4;
|
|
|
|
|
}
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics", address_family,
|
|
|
|
|
kPeerConnectionAddressFamilyCounter_Max);
|
|
|
|
|
|
2018-03-30 10:48:35 -07:00
|
|
|
const PeerConnectionFactoryInterface::Options& options = factory_->options();
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
// RFC 3264: The numeric value of the session id and version in the
|
|
|
|
|
// o line MUST be representable with a "64 bit signed integer".
|
|
|
|
|
// Due to this constraint session id |session_id_| is max limited to
|
|
|
|
|
// LLONG_MAX.
|
|
|
|
|
session_id_ = rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX);
|
2018-03-30 10:48:35 -07:00
|
|
|
JsepTransportController::Config config;
|
|
|
|
|
config.redetermine_role_on_ice_restart =
|
|
|
|
|
configuration.redetermine_role_on_ice_restart;
|
|
|
|
|
config.ssl_max_version = factory_->options().ssl_max_version;
|
|
|
|
|
config.disable_encryption = options.disable_encryption;
|
|
|
|
|
config.bundle_policy = configuration.bundle_policy;
|
|
|
|
|
config.rtcp_mux_policy = configuration.rtcp_mux_policy;
|
2018-10-25 10:16:44 -07:00
|
|
|
// TODO(bugs.webrtc.org/9891) - Remove options.crypto_options then remove this
|
|
|
|
|
// stub.
|
|
|
|
|
config.crypto_options = configuration.crypto_options.has_value()
|
|
|
|
|
? *configuration.crypto_options
|
|
|
|
|
: options.crypto_options;
|
2018-04-13 16:44:34 -07:00
|
|
|
config.transport_observer = this;
|
2020-09-28 10:39:31 +02:00
|
|
|
config.rtcp_handler = InitializeRtcpCallback();
|
2019-02-14 11:59:57 +01:00
|
|
|
config.event_log = event_log_ptr_;
|
2018-03-30 10:48:35 -07:00
|
|
|
#if defined(ENABLE_EXTERNAL_AUTH)
|
|
|
|
|
config.enable_external_auth = true;
|
|
|
|
|
#endif
|
2018-06-12 11:41:11 -07:00
|
|
|
config.active_reset_srtp_params = configuration.active_reset_srtp_params;
|
2018-10-17 13:15:42 -07:00
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
// Obtain a certificate from RTCConfiguration if any were provided (optional).
|
|
|
|
|
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
|
|
|
|
if (!configuration.certificates.empty()) {
|
|
|
|
|
// TODO(hbos,torbjorng): Decide on certificate-selection strategy instead of
|
|
|
|
|
// just picking the first one. The decision should be made based on the DTLS
|
|
|
|
|
// handshake. The DTLS negotiations need to know about all certificates.
|
|
|
|
|
certificate = configuration.certificates[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.disable_encryption) {
|
|
|
|
|
dtls_enabled_ = false;
|
|
|
|
|
} else {
|
|
|
|
|
// Enable DTLS by default if we have an identity store or a certificate.
|
2018-05-02 15:12:47 -07:00
|
|
|
dtls_enabled_ = (dependencies.cert_generator || certificate);
|
2017-11-06 10:37:17 -08:00
|
|
|
// |configuration| can override the default |dtls_enabled_| value.
|
|
|
|
|
if (configuration.enable_dtls_srtp) {
|
|
|
|
|
dtls_enabled_ = *(configuration.enable_dtls_srtp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-16 16:39:13 +02:00
|
|
|
if (configuration.enable_rtp_data_channel) {
|
2018-11-08 11:23:22 -08:00
|
|
|
// Enable creation of RTP data channels if the kEnableRtpDataChannels is
|
|
|
|
|
// set. It takes precendence over the disable_sctp_data_channels
|
|
|
|
|
// PeerConnectionFactoryInterface::Options.
|
2019-12-03 14:04:21 +01:00
|
|
|
data_channel_controller_.set_data_channel_type(cricket::DCT_RTP);
|
2017-11-06 10:37:17 -08:00
|
|
|
} else {
|
|
|
|
|
// DTLS has to be enabled to use SCTP.
|
|
|
|
|
if (!options.disable_sctp_data_channels && dtls_enabled_) {
|
2019-12-03 14:04:21 +01:00
|
|
|
data_channel_controller_.set_data_channel_type(cricket::DCT_SCTP);
|
2020-08-28 09:15:15 +02:00
|
|
|
config.sctp_factory = factory_->sctp_transport_factory();
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 12:33:05 -08:00
|
|
|
config.ice_transport_factory = ice_transport_factory_.get();
|
|
|
|
|
|
2019-09-23 14:53:54 -07:00
|
|
|
transport_controller_.reset(new JsepTransportController(
|
|
|
|
|
signaling_thread(), network_thread(), port_allocator_.get(),
|
|
|
|
|
async_resolver_factory_.get(), config));
|
2020-10-09 18:07:37 +00:00
|
|
|
transport_controller_->SignalStandardizedIceConnectionState.connect(
|
|
|
|
|
this, &PeerConnection::SetStandardizedIceConnectionState);
|
|
|
|
|
transport_controller_->SignalConnectionState.connect(
|
|
|
|
|
this, &PeerConnection::SetConnectionState);
|
|
|
|
|
transport_controller_->SignalIceGatheringState.connect(
|
|
|
|
|
this, &PeerConnection::OnTransportControllerGatheringState);
|
|
|
|
|
transport_controller_->SignalIceCandidatesGathered.connect(
|
|
|
|
|
this, &PeerConnection::OnTransportControllerCandidatesGathered);
|
|
|
|
|
transport_controller_->SignalIceCandidateError.connect(
|
|
|
|
|
this, &PeerConnection::OnTransportControllerCandidateError);
|
|
|
|
|
transport_controller_->SignalIceCandidatesRemoved.connect(
|
|
|
|
|
this, &PeerConnection::OnTransportControllerCandidatesRemoved);
|
|
|
|
|
transport_controller_->SignalDtlsHandshakeError.connect(
|
|
|
|
|
this, &PeerConnection::OnTransportControllerDtlsHandshakeError);
|
|
|
|
|
transport_controller_->SignalIceCandidatePairChanged.connect(
|
|
|
|
|
this, &PeerConnection::OnTransportControllerCandidateChanged);
|
|
|
|
|
|
2020-09-30 14:33:45 -07:00
|
|
|
transport_controller_->SignalIceConnectionState.AddReceiver(
|
|
|
|
|
[this](cricket::IceConnectionState s) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
OnTransportControllerConnectionState(s);
|
|
|
|
|
});
|
|
|
|
|
|
2019-09-23 14:53:54 -07:00
|
|
|
stats_.reset(new StatsCollector(this));
|
|
|
|
|
stats_collector_ = RTCStatsCollector::Create(this);
|
|
|
|
|
|
|
|
|
|
configuration_ = configuration;
|
|
|
|
|
|
|
|
|
|
transport_controller_->SetIceConfig(ParseIceConfig(configuration));
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
video_options_.screencast_min_bitrate_kbps =
|
|
|
|
|
configuration.screencast_min_bitrate;
|
|
|
|
|
audio_options_.combined_audio_video_bwe =
|
|
|
|
|
configuration.combined_audio_video_bwe;
|
|
|
|
|
|
|
|
|
|
audio_options_.audio_jitter_buffer_max_packets =
|
2017-11-16 10:53:30 +01:00
|
|
|
configuration.audio_jitter_buffer_max_packets;
|
2017-11-06 10:37:17 -08:00
|
|
|
|
|
|
|
|
audio_options_.audio_jitter_buffer_fast_accelerate =
|
2017-11-16 10:53:30 +01:00
|
|
|
configuration.audio_jitter_buffer_fast_accelerate;
|
2017-11-06 10:37:17 -08:00
|
|
|
|
2018-11-27 15:45:20 +01:00
|
|
|
audio_options_.audio_jitter_buffer_min_delay_ms =
|
|
|
|
|
configuration.audio_jitter_buffer_min_delay_ms;
|
|
|
|
|
|
2019-01-10 15:58:36 +01:00
|
|
|
audio_options_.audio_jitter_buffer_enable_rtx_handling =
|
|
|
|
|
configuration.audio_jitter_buffer_enable_rtx_handling;
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
// Whether the certificate generator/certificate is null or not determines
|
|
|
|
|
// what PeerConnectionDescriptionFactory will do, so make sure that we give it
|
|
|
|
|
// the right instructions by clearing the variables if needed.
|
|
|
|
|
if (!dtls_enabled_) {
|
2018-05-02 15:12:47 -07:00
|
|
|
dependencies.cert_generator.reset();
|
2017-11-06 10:37:17 -08:00
|
|
|
certificate = nullptr;
|
|
|
|
|
} else if (certificate) {
|
|
|
|
|
// Favor generated certificate over the certificate generator.
|
2018-05-02 15:12:47 -07:00
|
|
|
dependencies.cert_generator.reset();
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
auto webrtc_session_desc_factory =
|
|
|
|
|
std::make_unique<WebRtcSessionDescriptionFactory>(
|
|
|
|
|
signaling_thread(), channel_manager(), this, session_id(),
|
|
|
|
|
std::move(dependencies.cert_generator), certificate,
|
|
|
|
|
&ssrc_generator_);
|
|
|
|
|
webrtc_session_desc_factory->SignalCertificateReady.connect(
|
2017-11-06 10:37:17 -08:00
|
|
|
this, &PeerConnection::OnCertificateReady);
|
|
|
|
|
|
|
|
|
|
if (options.disable_encryption) {
|
2020-09-28 13:02:07 +00:00
|
|
|
webrtc_session_desc_factory->SetSdesPolicy(cricket::SEC_DISABLED);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
webrtc_session_desc_factory->set_enable_encrypted_rtp_header_extensions(
|
2018-10-25 10:16:44 -07:00
|
|
|
GetCryptoOptions().srtp.enable_encrypted_rtp_header_extensions);
|
2020-09-28 13:02:07 +00:00
|
|
|
webrtc_session_desc_factory->set_is_unified_plan(IsUnifiedPlan());
|
|
|
|
|
sdp_handler_.SetSessionDescFactory(std::move(webrtc_session_desc_factory));
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
// Add default audio/video transceivers for Plan B SDP.
|
|
|
|
|
if (!IsUnifiedPlan()) {
|
2020-09-29 11:54:05 +00:00
|
|
|
transceivers_.Add(RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
|
|
|
|
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)));
|
|
|
|
|
transceivers_.Add(RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
|
|
|
|
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO)));
|
2017-11-20 10:20:22 -08:00
|
|
|
}
|
2018-06-28 12:04:41 +02:00
|
|
|
int delay_ms =
|
|
|
|
|
return_histogram_very_quickly_ ? 0 : REPORT_USAGE_PATTERN_DELAY_MS;
|
2020-10-05 07:01:09 +00:00
|
|
|
|
|
|
|
|
message_handler_.RequestUsagePatternReport(
|
|
|
|
|
[this]() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
ReportUsagePattern();
|
|
|
|
|
},
|
|
|
|
|
delay_ms);
|
2019-04-17 07:38:40 +02:00
|
|
|
|
|
|
|
|
if (dependencies.video_bitrate_allocator_factory) {
|
|
|
|
|
video_bitrate_allocator_factory_ =
|
|
|
|
|
std::move(dependencies.video_bitrate_allocator_factory);
|
|
|
|
|
} else {
|
|
|
|
|
video_bitrate_allocator_factory_ =
|
|
|
|
|
CreateBuiltinVideoBitrateAllocatorFactory();
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 15:59:59 -07:00
|
|
|
RTCError PeerConnection::ValidateConfiguration(
|
|
|
|
|
const RTCConfiguration& config) const {
|
2020-01-27 15:45:02 -08:00
|
|
|
return cricket::P2PTransportChannel::ValidateIceConfig(
|
|
|
|
|
ParseIceConfig(config));
|
2017-07-14 15:59:59 -07:00
|
|
|
}
|
|
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<StreamCollectionInterface> PeerConnection::local_streams() {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(!IsUnifiedPlan()) << "local_streams is not available with Unified "
|
|
|
|
|
"Plan SdpSemantics. Please use GetSenders "
|
|
|
|
|
"instead.";
|
2020-10-09 11:42:17 +00:00
|
|
|
return sdp_handler_.local_streams();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<StreamCollectionInterface> PeerConnection::remote_streams() {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(!IsUnifiedPlan()) << "remote_streams is not available with Unified "
|
|
|
|
|
"Plan SdpSemantics. Please use GetReceivers "
|
|
|
|
|
"instead.";
|
2020-10-09 11:42:17 +00:00
|
|
|
return sdp_handler_.remote_streams();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2014-11-04 11:31:29 +00:00
|
|
|
bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(!IsUnifiedPlan()) << "AddStream is not available with Unified Plan "
|
|
|
|
|
"SdpSemantics. Please use AddTrack instead.";
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::AddStream");
|
2020-10-09 11:42:17 +00:00
|
|
|
return sdp_handler_.AddStream(local_stream);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(!IsUnifiedPlan()) << "RemoveStream is not available with Unified "
|
|
|
|
|
"Plan SdpSemantics. Please use RemoveTrack "
|
|
|
|
|
"instead.";
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
|
2020-10-09 11:42:17 +00:00
|
|
|
sdp_handler_.RemoveStream(local_stream);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2018-01-05 17:10:52 -08:00
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
2017-12-14 10:23:57 -08:00
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
2018-03-02 11:34:10 -08:00
|
|
|
const std::vector<std::string>& stream_ids) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-01-05 17:10:52 -08:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
|
2017-12-14 10:23:57 -08:00
|
|
|
if (!track) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Track is null.");
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
2017-12-14 10:23:57 -08:00
|
|
|
if (!(track->kind() == MediaStreamTrackInterface::kAudioKind ||
|
|
|
|
|
track->kind() == MediaStreamTrackInterface::kVideoKind)) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"Track has invalid kind: " + track->kind());
|
|
|
|
|
}
|
|
|
|
|
if (IsClosed()) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
|
|
|
|
|
"PeerConnection is closed.");
|
|
|
|
|
}
|
|
|
|
|
if (FindSenderForTrack(track)) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(
|
|
|
|
|
RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"Sender already exists for track " + track->id() + ".");
|
|
|
|
|
}
|
|
|
|
|
auto sender_or_error =
|
2018-04-02 16:31:36 -07:00
|
|
|
(IsUnifiedPlan() ? AddTrackUnifiedPlan(track, stream_ids)
|
|
|
|
|
: AddTrackPlanB(track, stream_ids));
|
2017-12-14 10:23:57 -08:00
|
|
|
if (sender_or_error.ok()) {
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2018-01-04 15:48:17 -08:00
|
|
|
stats_->AddTrack(track);
|
2017-12-14 10:23:57 -08:00
|
|
|
}
|
|
|
|
|
return sender_or_error;
|
|
|
|
|
}
|
2016-01-14 15:35:42 -08:00
|
|
|
|
2017-12-14 10:23:57 -08:00
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
|
|
|
|
PeerConnection::AddTrackPlanB(
|
|
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
2018-03-02 11:34:10 -08:00
|
|
|
const std::vector<std::string>& stream_ids) {
|
2018-04-02 16:31:36 -07:00
|
|
|
if (stream_ids.size() > 1u) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
|
|
|
|
|
"AddTrack with more than one stream is not "
|
|
|
|
|
"supported with Plan B semantics.");
|
|
|
|
|
}
|
|
|
|
|
std::vector<std::string> adjusted_stream_ids = stream_ids;
|
|
|
|
|
if (adjusted_stream_ids.empty()) {
|
|
|
|
|
adjusted_stream_ids.push_back(rtc::CreateRandomUuid());
|
|
|
|
|
}
|
2018-01-10 16:26:06 -08:00
|
|
|
cricket::MediaType media_type =
|
|
|
|
|
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
|
|
|
|
? cricket::MEDIA_TYPE_AUDIO
|
|
|
|
|
: cricket::MEDIA_TYPE_VIDEO);
|
2018-06-25 13:03:36 -07:00
|
|
|
auto new_sender =
|
2018-10-01 22:47:20 +02:00
|
|
|
CreateSender(media_type, track->id(), track, adjusted_stream_ids, {});
|
2016-01-14 15:35:42 -08:00
|
|
|
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
2018-11-13 16:26:05 -08:00
|
|
|
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
2017-11-20 10:20:22 -08:00
|
|
|
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
|
|
|
|
const RtpSenderInfo* sender_info =
|
2018-03-27 21:57:18 +00:00
|
|
|
FindSenderInfo(local_audio_sender_infos_,
|
2018-04-02 16:31:36 -07:00
|
|
|
new_sender->internal()->stream_ids()[0], track->id());
|
2017-11-20 10:20:22 -08:00
|
|
|
if (sender_info) {
|
|
|
|
|
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
2017-12-14 10:23:57 -08:00
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
|
2018-11-13 16:26:05 -08:00
|
|
|
new_sender->internal()->SetMediaChannel(video_media_channel());
|
2017-11-20 10:20:22 -08:00
|
|
|
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
|
|
|
|
const RtpSenderInfo* sender_info =
|
2018-03-27 21:57:18 +00:00
|
|
|
FindSenderInfo(local_video_sender_infos_,
|
2018-04-02 16:31:36 -07:00
|
|
|
new_sender->internal()->stream_ids()[0], track->id());
|
2017-11-20 10:20:22 -08:00
|
|
|
if (sender_info) {
|
|
|
|
|
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
|
|
|
|
}
|
2018-01-10 16:26:06 -08:00
|
|
|
return rtc::scoped_refptr<RtpSenderInterface>(new_sender);
|
2017-12-14 10:23:57 -08:00
|
|
|
}
|
2016-01-14 15:35:42 -08:00
|
|
|
|
2017-12-14 10:23:57 -08:00
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
|
|
|
|
PeerConnection::AddTrackUnifiedPlan(
|
|
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
2018-03-02 11:34:10 -08:00
|
|
|
const std::vector<std::string>& stream_ids) {
|
2017-12-14 10:23:57 -08:00
|
|
|
auto transceiver = FindFirstTransceiverForAddedTrack(track);
|
|
|
|
|
if (transceiver) {
|
2018-04-02 11:27:23 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Reusing an existing "
|
|
|
|
|
<< cricket::MediaTypeToString(transceiver->media_type())
|
|
|
|
|
<< " transceiver for AddTrack.";
|
2020-08-11 09:54:02 +02:00
|
|
|
if (transceiver->stopping()) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"The existing transceiver is stopping.");
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-14 10:23:57 -08:00
|
|
|
if (transceiver->direction() == RtpTransceiverDirection::kRecvOnly) {
|
2018-02-20 15:48:12 -08:00
|
|
|
transceiver->internal()->set_direction(
|
|
|
|
|
RtpTransceiverDirection::kSendRecv);
|
2017-12-14 10:23:57 -08:00
|
|
|
} else if (transceiver->direction() == RtpTransceiverDirection::kInactive) {
|
2018-02-20 15:48:12 -08:00
|
|
|
transceiver->internal()->set_direction(
|
|
|
|
|
RtpTransceiverDirection::kSendOnly);
|
2017-12-14 10:23:57 -08:00
|
|
|
}
|
2018-01-10 16:26:06 -08:00
|
|
|
transceiver->sender()->SetTrack(track);
|
2019-05-20 09:01:38 +00:00
|
|
|
transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
|
2019-11-25 18:49:44 +02:00
|
|
|
transceiver->internal()->set_reused_for_addtrack(true);
|
2017-12-14 10:23:57 -08:00
|
|
|
} else {
|
|
|
|
|
cricket::MediaType media_type =
|
|
|
|
|
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
|
|
|
|
? cricket::MEDIA_TYPE_AUDIO
|
|
|
|
|
: cricket::MEDIA_TYPE_VIDEO);
|
2018-04-02 11:27:23 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
|
|
|
|
|
<< " transceiver in response to a call to AddTrack.";
|
2018-06-26 11:13:50 -07:00
|
|
|
std::string sender_id = track->id();
|
|
|
|
|
// Avoid creating a sender with an existing ID by generating a random ID.
|
|
|
|
|
// This can happen if this is the second time AddTrack has created a sender
|
|
|
|
|
// for this track.
|
|
|
|
|
if (FindSenderById(sender_id)) {
|
|
|
|
|
sender_id = rtc::CreateRandomUuid();
|
|
|
|
|
}
|
2018-10-01 22:47:20 +02:00
|
|
|
auto sender = CreateSender(media_type, sender_id, track, stream_ids, {});
|
2018-01-10 16:26:06 -08:00
|
|
|
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
|
|
|
|
|
transceiver = CreateAndAddTransceiver(sender, receiver);
|
2017-12-14 10:23:57 -08:00
|
|
|
transceiver->internal()->set_created_by_addtrack(true);
|
2018-02-20 15:48:12 -08:00
|
|
|
transceiver->internal()->set_direction(RtpTransceiverDirection::kSendRecv);
|
2017-12-14 10:23:57 -08:00
|
|
|
}
|
|
|
|
|
return transceiver->sender();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
|
|
|
|
PeerConnection::FindFirstTransceiverForAddedTrack(
|
|
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
|
|
|
|
RTC_DCHECK(track);
|
2020-09-29 11:54:05 +00:00
|
|
|
for (auto transceiver : transceivers_.List()) {
|
2017-12-14 10:23:57 -08:00
|
|
|
if (!transceiver->sender()->track() &&
|
2018-02-09 11:43:08 -08:00
|
|
|
cricket::MediaTypeToString(transceiver->media_type()) ==
|
2017-12-14 10:23:57 -08:00
|
|
|
track->kind() &&
|
2018-02-20 11:54:42 -08:00
|
|
|
!transceiver->internal()->has_ever_been_used_to_send() &&
|
|
|
|
|
!transceiver->stopped()) {
|
2017-12-14 10:23:57 -08:00
|
|
|
return transceiver;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) {
|
|
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::RemoveTrack");
|
2018-07-23 10:27:33 -07:00
|
|
|
return RemoveTrackNew(sender).ok();
|
2017-12-14 10:23:57 -08:00
|
|
|
}
|
|
|
|
|
|
2018-07-23 10:27:33 -07:00
|
|
|
RTCError PeerConnection::RemoveTrackNew(
|
2017-12-14 10:23:57 -08:00
|
|
|
rtc::scoped_refptr<RtpSenderInterface> sender) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-12-14 10:23:57 -08:00
|
|
|
if (!sender) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Sender is null.");
|
|
|
|
|
}
|
2016-01-14 15:35:42 -08:00
|
|
|
if (IsClosed()) {
|
2017-12-14 10:23:57 -08:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
|
|
|
|
|
"PeerConnection is closed.");
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
2017-12-14 10:23:57 -08:00
|
|
|
if (IsUnifiedPlan()) {
|
|
|
|
|
auto transceiver = FindTransceiverBySender(sender);
|
|
|
|
|
if (!transceiver || !sender->track()) {
|
|
|
|
|
return RTCError::OK();
|
|
|
|
|
}
|
|
|
|
|
sender->SetTrack(nullptr);
|
|
|
|
|
if (transceiver->direction() == RtpTransceiverDirection::kSendRecv) {
|
2018-02-20 15:48:12 -08:00
|
|
|
transceiver->internal()->set_direction(
|
|
|
|
|
RtpTransceiverDirection::kRecvOnly);
|
2017-12-14 10:23:57 -08:00
|
|
|
} else if (transceiver->direction() == RtpTransceiverDirection::kSendOnly) {
|
2018-02-20 15:48:12 -08:00
|
|
|
transceiver->internal()->set_direction(
|
|
|
|
|
RtpTransceiverDirection::kInactive);
|
2017-12-14 10:23:57 -08:00
|
|
|
}
|
2017-11-20 10:20:22 -08:00
|
|
|
} else {
|
2017-12-14 10:23:57 -08:00
|
|
|
bool removed;
|
|
|
|
|
if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
removed = GetAudioTransceiver()->internal()->RemoveSender(sender);
|
|
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_EQ(cricket::MEDIA_TYPE_VIDEO, sender->media_type());
|
|
|
|
|
removed = GetVideoTransceiver()->internal()->RemoveSender(sender);
|
|
|
|
|
}
|
|
|
|
|
if (!removed) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(
|
|
|
|
|
RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"Couldn't find sender " + sender->id() + " to remove.");
|
|
|
|
|
}
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2017-12-14 10:23:57 -08:00
|
|
|
return RTCError::OK();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
|
|
|
|
PeerConnection::FindTransceiverBySender(
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInterface> sender) {
|
2020-09-29 11:54:05 +00:00
|
|
|
return transceivers_.FindBySender(sender);
|
2016-01-14 15:35:42 -08:00
|
|
|
}
|
|
|
|
|
|
2017-11-27 13:01:52 -08:00
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|
|
|
|
PeerConnection::AddTransceiver(
|
|
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
|
|
|
|
return AddTransceiver(track, RtpTransceiverInit());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|
|
|
|
PeerConnection::AddTransceiver(
|
|
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
|
|
|
|
const RtpTransceiverInit& init) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(IsUnifiedPlan())
|
|
|
|
|
<< "AddTransceiver is only available with Unified Plan SdpSemantics";
|
2017-11-27 13:01:52 -08:00
|
|
|
if (!track) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "track is null");
|
|
|
|
|
}
|
|
|
|
|
cricket::MediaType media_type;
|
|
|
|
|
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
|
|
|
|
media_type = cricket::MEDIA_TYPE_AUDIO;
|
|
|
|
|
} else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
|
|
|
|
|
media_type = cricket::MEDIA_TYPE_VIDEO;
|
|
|
|
|
} else {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"Track kind is not audio or video");
|
|
|
|
|
}
|
|
|
|
|
return AddTransceiver(media_type, track, init);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|
|
|
|
PeerConnection::AddTransceiver(cricket::MediaType media_type) {
|
|
|
|
|
return AddTransceiver(media_type, RtpTransceiverInit());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|
|
|
|
PeerConnection::AddTransceiver(cricket::MediaType media_type,
|
|
|
|
|
const RtpTransceiverInit& init) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(IsUnifiedPlan())
|
|
|
|
|
<< "AddTransceiver is only available with Unified Plan SdpSemantics";
|
2017-11-27 13:01:52 -08:00
|
|
|
if (!(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
|
|
|
|
media_type == cricket::MEDIA_TYPE_VIDEO)) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"media type is not audio or video");
|
|
|
|
|
}
|
|
|
|
|
return AddTransceiver(media_type, nullptr, init);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|
|
|
|
PeerConnection::AddTransceiver(
|
|
|
|
|
cricket::MediaType media_type,
|
|
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
2018-01-25 13:58:07 -08:00
|
|
|
const RtpTransceiverInit& init,
|
2019-04-16 12:24:14 +02:00
|
|
|
bool update_negotiation_needed) {
|
2020-10-01 16:47:23 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-27 13:01:52 -08:00
|
|
|
RTC_DCHECK((media_type == cricket::MEDIA_TYPE_AUDIO ||
|
|
|
|
|
media_type == cricket::MEDIA_TYPE_VIDEO));
|
|
|
|
|
if (track) {
|
|
|
|
|
RTC_DCHECK_EQ(media_type,
|
|
|
|
|
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
|
|
|
|
? cricket::MEDIA_TYPE_AUDIO
|
|
|
|
|
: cricket::MEDIA_TYPE_VIDEO));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-05 12:36:31 -08:00
|
|
|
RTC_HISTOGRAM_COUNTS_LINEAR(kSimulcastNumberOfEncodings,
|
|
|
|
|
init.send_encodings.size(), 0, 7, 8);
|
|
|
|
|
|
2019-02-06 17:09:52 -08:00
|
|
|
size_t num_rids = absl::c_count_if(init.send_encodings,
|
|
|
|
|
[](const RtpEncodingParameters& encoding) {
|
|
|
|
|
return !encoding.rid.empty();
|
|
|
|
|
});
|
|
|
|
|
if (num_rids > 0 && num_rids != init.send_encodings.size()) {
|
2019-02-06 17:09:52 -08:00
|
|
|
LOG_AND_RETURN_ERROR(
|
2019-02-06 17:09:52 -08:00
|
|
|
RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"RIDs must be provided for either all or none of the send encodings.");
|
2018-10-01 22:47:20 +02:00
|
|
|
}
|
|
|
|
|
|
2019-04-08 14:11:57 -07:00
|
|
|
if (num_rids > 0 && absl::c_any_of(init.send_encodings,
|
|
|
|
|
[](const RtpEncodingParameters& encoding) {
|
|
|
|
|
return !IsLegalRsidName(encoding.rid);
|
|
|
|
|
})) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"Invalid RID value provided.");
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-06 17:09:52 -08:00
|
|
|
if (absl::c_any_of(init.send_encodings,
|
|
|
|
|
[](const RtpEncodingParameters& encoding) {
|
|
|
|
|
return encoding.ssrc.has_value();
|
|
|
|
|
})) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(
|
|
|
|
|
RTCErrorType::UNSUPPORTED_PARAMETER,
|
|
|
|
|
"Attempted to set an unimplemented parameter of RtpParameters.");
|
2019-02-06 17:09:52 -08:00
|
|
|
}
|
|
|
|
|
|
2019-02-08 20:41:39 +00:00
|
|
|
RtpParameters parameters;
|
|
|
|
|
parameters.encodings = init.send_encodings;
|
2019-02-06 17:09:52 -08:00
|
|
|
|
|
|
|
|
// Encodings are dropped from the tail if too many are provided.
|
|
|
|
|
if (parameters.encodings.size() > kMaxSimulcastStreams) {
|
|
|
|
|
parameters.encodings.erase(
|
|
|
|
|
parameters.encodings.begin() + kMaxSimulcastStreams,
|
|
|
|
|
parameters.encodings.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Single RID should be removed.
|
|
|
|
|
if (parameters.encodings.size() == 1 &&
|
|
|
|
|
!parameters.encodings[0].rid.empty()) {
|
|
|
|
|
RTC_LOG(LS_INFO) << "Removing RID: " << parameters.encodings[0].rid << ".";
|
|
|
|
|
parameters.encodings[0].rid.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If RIDs were not provided, they are generated for simulcast scenario.
|
|
|
|
|
if (parameters.encodings.size() > 1 && num_rids == 0) {
|
|
|
|
|
rtc::UniqueStringGenerator rid_generator;
|
|
|
|
|
for (RtpEncodingParameters& encoding : parameters.encodings) {
|
|
|
|
|
encoding.rid = rid_generator();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-01 22:47:20 +02:00
|
|
|
if (UnimplementedRtpParameterHasValue(parameters)) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(
|
|
|
|
|
RTCErrorType::UNSUPPORTED_PARAMETER,
|
|
|
|
|
"Attempted to set an unimplemented parameter of RtpParameters.");
|
|
|
|
|
}
|
2017-11-27 13:01:52 -08:00
|
|
|
|
2019-01-29 14:26:48 +01:00
|
|
|
auto result = cricket::CheckRtpParametersValues(parameters);
|
|
|
|
|
if (!result.ok()) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(result.type(), result.message());
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-02 11:27:23 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
|
|
|
|
|
<< " transceiver in response to a call to AddTransceiver.";
|
2018-06-26 11:13:50 -07:00
|
|
|
// Set the sender ID equal to the track ID if the track is specified unless
|
|
|
|
|
// that sender ID is already in use.
|
|
|
|
|
std::string sender_id =
|
|
|
|
|
(track && !FindSenderById(track->id()) ? track->id()
|
|
|
|
|
: rtc::CreateRandomUuid());
|
2018-10-01 22:47:20 +02:00
|
|
|
auto sender = CreateSender(media_type, sender_id, track, init.stream_ids,
|
2019-02-06 17:09:52 -08:00
|
|
|
parameters.encodings);
|
2018-01-10 16:26:06 -08:00
|
|
|
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
|
|
|
|
|
auto transceiver = CreateAndAddTransceiver(sender, receiver);
|
|
|
|
|
transceiver->internal()->set_direction(init.direction);
|
|
|
|
|
|
2019-04-16 12:24:14 +02:00
|
|
|
if (update_negotiation_needed) {
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2018-01-25 13:58:07 -08:00
|
|
|
}
|
2017-12-14 10:23:57 -08:00
|
|
|
|
|
|
|
|
return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 16:26:06 -08:00
|
|
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
|
|
|
|
PeerConnection::CreateSender(
|
|
|
|
|
cricket::MediaType media_type,
|
2018-06-25 13:03:36 -07:00
|
|
|
const std::string& id,
|
2018-01-10 16:26:06 -08:00
|
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
2018-10-01 22:47:20 +02:00
|
|
|
const std::vector<std::string>& stream_ids,
|
|
|
|
|
const std::vector<RtpEncodingParameters>& send_encodings) {
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-27 13:01:52 -08:00
|
|
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender;
|
2018-01-10 16:26:06 -08:00
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
RTC_DCHECK(!track ||
|
|
|
|
|
(track->kind() == MediaStreamTrackInterface::kAudioKind));
|
|
|
|
|
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
|
|
|
|
signaling_thread(),
|
2019-05-20 19:31:53 +02:00
|
|
|
AudioRtpSender::Create(worker_thread(), id, stats_.get(), this));
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
2018-01-10 16:26:06 -08:00
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
|
|
|
|
|
RTC_DCHECK(!track ||
|
|
|
|
|
(track->kind() == MediaStreamTrackInterface::kVideoKind));
|
|
|
|
|
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
2019-05-20 19:31:53 +02:00
|
|
|
signaling_thread(), VideoRtpSender::Create(worker_thread(), id, this));
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
2018-01-10 16:26:06 -08:00
|
|
|
}
|
2018-06-25 13:03:36 -07:00
|
|
|
bool set_track_succeeded = sender->SetTrack(track);
|
|
|
|
|
RTC_DCHECK(set_track_succeeded);
|
2019-05-20 09:01:38 +00:00
|
|
|
sender->internal()->set_stream_ids(stream_ids);
|
2018-10-01 22:47:20 +02:00
|
|
|
sender->internal()->set_init_send_encodings(send_encodings);
|
2018-01-10 16:26:06 -08:00
|
|
|
return sender;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
|
|
|
|
PeerConnection::CreateReceiver(cricket::MediaType media_type,
|
|
|
|
|
const std::string& receiver_id) {
|
2017-11-27 13:01:52 -08:00
|
|
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
|
|
|
|
receiver;
|
|
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
2018-07-04 20:51:53 +02:00
|
|
|
signaling_thread(), new AudioRtpReceiver(worker_thread(), receiver_id,
|
|
|
|
|
std::vector<std::string>({})));
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
2017-11-27 13:01:52 -08:00
|
|
|
} else {
|
2018-01-10 16:26:06 -08:00
|
|
|
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
|
2017-11-27 13:01:52 -08:00
|
|
|
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
2018-07-04 20:51:53 +02:00
|
|
|
signaling_thread(), new VideoRtpReceiver(worker_thread(), receiver_id,
|
|
|
|
|
std::vector<std::string>({})));
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
2017-11-27 13:01:52 -08:00
|
|
|
}
|
2018-01-10 16:26:06 -08:00
|
|
|
return receiver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
|
|
|
|
PeerConnection::CreateAndAddTransceiver(
|
|
|
|
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
|
|
|
|
receiver) {
|
2020-09-28 13:02:07 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-06-26 11:13:50 -07:00
|
|
|
// Ensure that the new sender does not have an ID that is already in use by
|
|
|
|
|
// another sender.
|
|
|
|
|
// Allow receiver IDs to conflict since those come from remote SDP (which
|
|
|
|
|
// could be invalid, but should not cause a crash).
|
|
|
|
|
RTC_DCHECK(!FindSenderById(sender->id()));
|
2018-01-10 16:26:06 -08:00
|
|
|
auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
2019-04-23 19:25:51 +02:00
|
|
|
signaling_thread(),
|
2020-03-16 13:40:51 +01:00
|
|
|
new RtpTransceiver(
|
|
|
|
|
sender, receiver, channel_manager(),
|
|
|
|
|
sender->media_type() == cricket::MEDIA_TYPE_AUDIO
|
|
|
|
|
? channel_manager()->GetSupportedAudioRtpHeaderExtensions()
|
|
|
|
|
: channel_manager()->GetSupportedVideoRtpHeaderExtensions()));
|
2020-09-29 11:54:05 +00:00
|
|
|
transceivers_.Add(transceiver);
|
2018-02-20 15:48:12 -08:00
|
|
|
transceiver->internal()->SignalNegotiationNeeded.connect(
|
|
|
|
|
this, &PeerConnection::OnNegotiationNeeded);
|
2017-12-14 10:23:57 -08:00
|
|
|
return transceiver;
|
2017-11-27 13:01:52 -08:00
|
|
|
}
|
|
|
|
|
|
2018-02-20 15:48:12 -08:00
|
|
|
void PeerConnection::OnNegotiationNeeded() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
RTC_DCHECK(!IsClosed());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2018-02-20 15:48:12 -08:00
|
|
|
}
|
|
|
|
|
|
2015-11-25 11:26:01 -08:00
|
|
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
|
2015-12-18 16:58:44 -08:00
|
|
|
const std::string& kind,
|
|
|
|
|
const std::string& stream_id) {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(!IsUnifiedPlan()) << "CreateSender is not available with Unified "
|
|
|
|
|
"Plan SdpSemantics. Please use AddTransceiver "
|
|
|
|
|
"instead.";
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2017-11-20 10:20:22 -08:00
|
|
|
|
2018-04-02 16:31:36 -07:00
|
|
|
// Internally we need to have one stream with Plan B semantics, so we
|
|
|
|
|
// generate a random stream ID if not specified.
|
2018-03-02 11:34:10 -08:00
|
|
|
std::vector<std::string> stream_ids;
|
2018-04-02 16:31:36 -07:00
|
|
|
if (stream_id.empty()) {
|
|
|
|
|
stream_ids.push_back(rtc::CreateRandomUuid());
|
|
|
|
|
RTC_LOG(LS_INFO)
|
|
|
|
|
<< "No stream_id specified for sender. Generated stream ID: "
|
|
|
|
|
<< stream_ids[0];
|
|
|
|
|
} else {
|
2018-03-02 11:34:10 -08:00
|
|
|
stream_ids.push_back(stream_id);
|
2018-01-10 16:26:06 -08:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
// TODO(steveanton): Move construction of the RtpSenders to RtpTransceiver.
|
2016-06-06 14:27:39 -07:00
|
|
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
|
2015-11-25 11:26:01 -08:00
|
|
|
if (kind == MediaStreamTrackInterface::kAudioKind) {
|
2019-02-19 15:20:21 -08:00
|
|
|
auto audio_sender = AudioRtpSender::Create(
|
2019-05-20 19:31:53 +02:00
|
|
|
worker_thread(), rtc::CreateRandomUuid(), stats_.get(), this);
|
2018-11-13 16:26:05 -08:00
|
|
|
audio_sender->SetMediaChannel(voice_media_channel());
|
2016-06-06 14:27:39 -07:00
|
|
|
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
2018-01-10 16:26:06 -08:00
|
|
|
signaling_thread(), audio_sender);
|
2017-11-20 10:20:22 -08:00
|
|
|
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
2015-11-25 11:26:01 -08:00
|
|
|
} else if (kind == MediaStreamTrackInterface::kVideoKind) {
|
2019-02-19 15:20:21 -08:00
|
|
|
auto video_sender =
|
2019-05-20 19:31:53 +02:00
|
|
|
VideoRtpSender::Create(worker_thread(), rtc::CreateRandomUuid(), this);
|
2018-11-13 16:26:05 -08:00
|
|
|
video_sender->SetMediaChannel(video_media_channel());
|
2016-06-06 14:27:39 -07:00
|
|
|
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
2018-01-10 16:26:06 -08:00
|
|
|
signaling_thread(), video_sender);
|
2017-11-20 10:20:22 -08:00
|
|
|
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
2015-11-25 11:26:01 -08:00
|
|
|
} else {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
|
2017-11-20 10:20:22 -08:00
|
|
|
return nullptr;
|
2015-11-25 11:26:01 -08:00
|
|
|
}
|
2019-05-20 09:01:38 +00:00
|
|
|
new_sender->internal()->set_stream_ids(stream_ids);
|
2017-11-20 10:20:22 -08:00
|
|
|
|
2016-01-14 15:35:42 -08:00
|
|
|
return new_sender;
|
2015-11-25 11:26:01 -08:00
|
|
|
}
|
|
|
|
|
|
2015-09-28 16:53:55 -07:00
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
|
|
|
|
|
const {
|
2019-03-26 13:33:43 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2016-06-06 14:27:39 -07:00
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderInterface>> ret;
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& sender : GetSendersInternal()) {
|
2017-11-20 10:20:22 -08:00
|
|
|
ret.push_back(sender);
|
2016-06-06 14:27:39 -07:00
|
|
|
}
|
|
|
|
|
return ret;
|
2015-09-28 16:53:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
|
|
|
|
PeerConnection::GetSendersInternal() const {
|
2020-10-01 10:23:33 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-20 10:20:22 -08:00
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
|
|
|
|
|
all_senders;
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2020-08-11 09:54:02 +02:00
|
|
|
if (IsUnifiedPlan() && transceiver->internal()->stopped())
|
|
|
|
|
continue;
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
auto senders = transceiver->internal()->senders();
|
|
|
|
|
all_senders.insert(all_senders.end(), senders.begin(), senders.end());
|
|
|
|
|
}
|
|
|
|
|
return all_senders;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-28 16:53:55 -07:00
|
|
|
std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
|
|
|
|
|
PeerConnection::GetReceivers() const {
|
2019-03-26 13:33:43 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2016-06-06 14:27:39 -07:00
|
|
|
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> ret;
|
2017-11-20 10:20:22 -08:00
|
|
|
for (const auto& receiver : GetReceiversInternal()) {
|
|
|
|
|
ret.push_back(receiver);
|
2016-06-06 14:27:39 -07:00
|
|
|
}
|
|
|
|
|
return ret;
|
2015-09-28 16:53:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
std::vector<
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
|
|
|
|
PeerConnection::GetReceiversInternal() const {
|
|
|
|
|
std::vector<
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
|
|
|
|
|
all_receivers;
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2020-08-11 09:54:02 +02:00
|
|
|
if (IsUnifiedPlan() && transceiver->internal()->stopped())
|
|
|
|
|
continue;
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
auto receivers = transceiver->internal()->receivers();
|
|
|
|
|
all_receivers.insert(all_receivers.end(), receivers.begin(),
|
|
|
|
|
receivers.end());
|
|
|
|
|
}
|
|
|
|
|
return all_receivers;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-27 13:01:52 -08:00
|
|
|
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
|
|
|
|
|
PeerConnection::GetTransceivers() const {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-01 13:48:58 -08:00
|
|
|
RTC_CHECK(IsUnifiedPlan())
|
|
|
|
|
<< "GetTransceivers is only supported with Unified Plan SdpSemantics.";
|
2017-11-27 13:01:52 -08:00
|
|
|
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> all_transceivers;
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2020-09-22 07:41:50 +00:00
|
|
|
all_transceivers.push_back(transceiver);
|
2017-11-27 13:01:52 -08:00
|
|
|
}
|
|
|
|
|
return all_transceivers;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-13 23:18:49 +00:00
|
|
|
bool PeerConnection::GetStats(StatsObserver* observer,
|
|
|
|
|
MediaStreamTrackInterface* track,
|
|
|
|
|
StatsOutputLevel level) {
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-01-31 00:57:56 -08:00
|
|
|
if (!observer) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "GetStats - observer is NULL.";
|
2013-07-10 00:45:36 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-14 20:15:26 +00:00
|
|
|
stats_->UpdateStats(level);
|
2016-11-04 11:38:15 -07:00
|
|
|
// The StatsCollector is used to tell if a track is valid because it may
|
|
|
|
|
// remember tracks that the PeerConnection previously removed.
|
|
|
|
|
if (track && !stats_->IsValidTrack(track->id())) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING) << "GetStats is called with an invalid track: "
|
|
|
|
|
<< track->id();
|
2016-11-04 11:38:15 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2020-10-05 07:01:09 +00:00
|
|
|
message_handler_.PostGetStats(observer, stats_.get(), track);
|
2013-07-10 00:45:36 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-15 23:33:01 -07:00
|
|
|
void PeerConnection::GetStats(RTCStatsCollectorCallback* callback) {
|
2018-03-20 13:24:20 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2016-09-15 23:33:01 -07:00
|
|
|
RTC_DCHECK(stats_collector_);
|
2018-03-20 13:24:20 +01:00
|
|
|
RTC_DCHECK(callback);
|
2016-09-15 23:33:01 -07:00
|
|
|
stats_collector_->GetStatsReport(callback);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-20 13:24:20 +01:00
|
|
|
void PeerConnection::GetStats(
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInterface> selector,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
|
|
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-20 13:24:20 +01:00
|
|
|
RTC_DCHECK(callback);
|
|
|
|
|
RTC_DCHECK(stats_collector_);
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInternal> internal_sender;
|
|
|
|
|
if (selector) {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& proxy_transceiver : transceivers_.List()) {
|
2018-03-20 13:24:20 +01:00
|
|
|
for (const auto& proxy_sender :
|
|
|
|
|
proxy_transceiver->internal()->senders()) {
|
|
|
|
|
if (proxy_sender == selector) {
|
|
|
|
|
internal_sender = proxy_sender->internal();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (internal_sender)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-16 11:29:55 +01:00
|
|
|
// If there is no |internal_sender| then |selector| is either null or does not
|
2018-03-20 13:24:20 +01:00
|
|
|
// belong to the PeerConnection (in Plan B, senders can be removed from the
|
|
|
|
|
// PeerConnection). This means that "all the stats objects representing the
|
|
|
|
|
// selector" is an empty set. Invoking GetStatsReport() with a null selector
|
|
|
|
|
// produces an empty stats report.
|
|
|
|
|
stats_collector_->GetStatsReport(internal_sender, callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::GetStats(
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInterface> selector,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
|
|
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-03-20 13:24:20 +01:00
|
|
|
RTC_DCHECK(callback);
|
|
|
|
|
RTC_DCHECK(stats_collector_);
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInternal> internal_receiver;
|
|
|
|
|
if (selector) {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& proxy_transceiver : transceivers_.List()) {
|
2018-03-20 13:24:20 +01:00
|
|
|
for (const auto& proxy_receiver :
|
|
|
|
|
proxy_transceiver->internal()->receivers()) {
|
|
|
|
|
if (proxy_receiver == selector) {
|
|
|
|
|
internal_receiver = proxy_receiver->internal();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (internal_receiver)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-11-16 11:29:55 +01:00
|
|
|
// If there is no |internal_receiver| then |selector| is either null or does
|
2018-03-20 13:24:20 +01:00
|
|
|
// not belong to the PeerConnection (in Plan B, receivers can be removed from
|
|
|
|
|
// the PeerConnection). This means that "all the stats objects representing
|
|
|
|
|
// the selector" is an empty set. Invoking GetStatsReport() with a null
|
|
|
|
|
// selector produces an empty stats report.
|
|
|
|
|
stats_collector_->GetStatsReport(internal_receiver, callback);
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
|
2019-02-17 13:00:07 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.signaling_state();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PeerConnectionInterface::IceConnectionState
|
|
|
|
|
PeerConnection::ice_connection_state() {
|
2019-02-17 13:00:07 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2013-07-10 00:45:36 +00:00
|
|
|
return ice_connection_state_;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 16:18:59 +00:00
|
|
|
PeerConnectionInterface::IceConnectionState
|
|
|
|
|
PeerConnection::standardized_ice_connection_state() {
|
2019-02-17 13:00:07 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-11-23 16:18:59 +00:00
|
|
|
return standardized_ice_connection_state_;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-18 15:58:17 +02:00
|
|
|
PeerConnectionInterface::PeerConnectionState
|
|
|
|
|
PeerConnection::peer_connection_state() {
|
2019-02-17 13:00:07 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-10-18 15:58:17 +02:00
|
|
|
return connection_state_;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
PeerConnectionInterface::IceGatheringState
|
|
|
|
|
PeerConnection::ice_gathering_state() {
|
2019-02-17 13:00:07 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2013-07-10 00:45:36 +00:00
|
|
|
return ice_gathering_state_;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 11:20:00 +01:00
|
|
|
absl::optional<bool> PeerConnection::can_trickle_ice_candidates() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
const SessionDescriptionInterface* description = current_remote_description();
|
2020-03-02 11:20:00 +01:00
|
|
|
if (!description) {
|
2020-09-28 13:02:07 +00:00
|
|
|
description = pending_remote_description();
|
2020-03-02 11:20:00 +01:00
|
|
|
}
|
|
|
|
|
if (!description) {
|
|
|
|
|
return absl::nullopt;
|
|
|
|
|
}
|
|
|
|
|
// TODO(bugs.webrtc.org/7443): Change to retrieve from session-level option.
|
|
|
|
|
if (description->description()->transport_infos().size() < 1) {
|
|
|
|
|
return absl::nullopt;
|
|
|
|
|
}
|
|
|
|
|
return description->description()->transport_infos()[0].description.HasOption(
|
|
|
|
|
"trickle");
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_refptr<DataChannelInterface> PeerConnection::CreateDataChannel(
|
2013-07-10 00:45:36 +00:00
|
|
|
const std::string& label,
|
|
|
|
|
const DataChannelInit* config) {
|
2019-02-14 10:17:47 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
|
2016-08-05 11:14:50 -07:00
|
|
|
|
2019-12-03 14:04:21 +01:00
|
|
|
bool first_datachannel = !data_channel_controller_.HasDataChannels();
|
2014-05-29 15:31:11 +00:00
|
|
|
|
2016-04-27 06:47:29 -07:00
|
|
|
std::unique_ptr<InternalDataChannelInit> internal_config;
|
2014-01-14 10:00:58 +00:00
|
|
|
if (config) {
|
|
|
|
|
internal_config.reset(new InternalDataChannelInit(*config));
|
|
|
|
|
}
|
2020-07-09 15:32:34 -07:00
|
|
|
rtc::scoped_refptr<DataChannelInterface> channel(
|
|
|
|
|
data_channel_controller_.InternalCreateDataChannelWithProxy(
|
2019-12-02 09:56:02 +01:00
|
|
|
label, internal_config.get()));
|
2015-10-14 11:33:11 -07:00
|
|
|
if (!channel.get()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2014-05-29 15:31:11 +00:00
|
|
|
// Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or
|
|
|
|
|
// the first SCTP DataChannel.
|
2017-11-06 10:37:17 -08:00
|
|
|
if (data_channel_type() == cricket::DCT_RTP || first_datachannel) {
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2014-05-29 15:31:11 +00:00
|
|
|
}
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::DATA_ADDED);
|
2020-07-09 15:32:34 -07:00
|
|
|
return channel;
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 11:16:56 +02:00
|
|
|
void PeerConnection::RestartIce() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.RestartIce();
|
2019-07-18 11:16:56 +02:00
|
|
|
}
|
|
|
|
|
|
2014-08-04 18:34:16 +00:00
|
|
|
void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
|
|
|
|
|
const RTCOfferAnswerOptions& options) {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.CreateOffer(observer, options);
|
2019-10-28 12:09:49 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
|
|
|
|
|
const RTCOfferAnswerOptions& options) {
|
2019-10-28 12:09:49 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.CreateAnswer(observer, options);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::SetLocalDescription(
|
|
|
|
|
SetSessionDescriptionObserver* observer,
|
2018-02-16 17:08:42 -08:00
|
|
|
SessionDescriptionInterface* desc_ptr) {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.SetLocalDescription(observer, desc_ptr);
|
2020-07-29 12:04:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::SetLocalDescription(
|
|
|
|
|
std::unique_ptr<SessionDescriptionInterface> desc,
|
|
|
|
|
rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.SetLocalDescription(std::move(desc), observer);
|
2019-10-28 12:09:49 +01:00
|
|
|
}
|
|
|
|
|
|
2019-10-30 10:35:50 +01:00
|
|
|
void PeerConnection::SetLocalDescription(
|
|
|
|
|
SetSessionDescriptionObserver* observer) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.SetLocalDescription(observer);
|
2020-07-29 12:04:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::SetLocalDescription(
|
|
|
|
|
rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.SetLocalDescription(observer);
|
2019-10-30 10:35:50 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
void PeerConnection::SetRemoteDescription(
|
|
|
|
|
SetSessionDescriptionObserver* observer,
|
|
|
|
|
SessionDescriptionInterface* desc_ptr) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
sdp_handler_.SetRemoteDescription(observer, desc_ptr);
|
|
|
|
|
}
|
2017-12-04 15:25:56 -08:00
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
void PeerConnection::SetRemoteDescription(
|
|
|
|
|
std::unique_ptr<SessionDescriptionInterface> desc,
|
|
|
|
|
rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
sdp_handler_.SetRemoteDescription(std::move(desc), observer);
|
|
|
|
|
}
|
2018-12-20 11:06:02 +01:00
|
|
|
|
2016-11-16 19:42:04 -08:00
|
|
|
PeerConnectionInterface::RTCConfiguration PeerConnection::GetConfiguration() {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2016-11-16 19:42:04 -08:00
|
|
|
return configuration_;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-19 09:58:17 +02:00
|
|
|
RTCError PeerConnection::SetConfiguration(
|
|
|
|
|
const RTCConfiguration& configuration) {
|
2019-02-21 23:55:09 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
|
2018-04-24 09:54:10 -07:00
|
|
|
if (IsClosed()) {
|
2019-08-19 09:58:17 +02:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
|
|
|
|
|
"SetConfiguration: PeerConnection is closed.");
|
2018-04-24 09:54:10 -07:00
|
|
|
}
|
|
|
|
|
|
2018-04-11 16:57:45 -07:00
|
|
|
// According to JSEP, after setLocalDescription, changing the candidate pool
|
|
|
|
|
// size is not allowed, and changing the set of ICE servers will not result
|
|
|
|
|
// in new candidates being gathered.
|
2017-11-06 10:37:17 -08:00
|
|
|
if (local_description() && configuration.ice_candidate_pool_size !=
|
|
|
|
|
configuration_.ice_candidate_pool_size) {
|
2019-08-19 09:58:17 +02:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
|
|
|
|
|
"Can't change candidate pool size after calling "
|
|
|
|
|
"SetLocalDescription.");
|
2014-05-03 05:39:45 +00:00
|
|
|
}
|
2017-01-11 12:28:30 -08:00
|
|
|
|
2018-10-25 10:16:44 -07:00
|
|
|
if (local_description() &&
|
|
|
|
|
configuration.crypto_options != configuration_.crypto_options) {
|
2019-08-19 09:58:17 +02:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
|
|
|
|
|
"Can't change crypto_options after calling "
|
|
|
|
|
"SetLocalDescription.");
|
2018-10-25 10:16:44 -07:00
|
|
|
}
|
|
|
|
|
|
2017-01-11 12:28:30 -08:00
|
|
|
// 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
|
|
|
|
|
// support modifying than those we do, and more could be added.
|
|
|
|
|
RTCConfiguration modified_config = configuration_;
|
|
|
|
|
modified_config.servers = configuration.servers;
|
|
|
|
|
modified_config.type = configuration.type;
|
|
|
|
|
modified_config.ice_candidate_pool_size =
|
|
|
|
|
configuration.ice_candidate_pool_size;
|
|
|
|
|
modified_config.prune_turn_ports = configuration.prune_turn_ports;
|
2019-10-14 11:27:50 -07:00
|
|
|
modified_config.turn_port_prune_policy = configuration.turn_port_prune_policy;
|
2019-06-26 14:56:02 -07:00
|
|
|
modified_config.surface_ice_candidates_on_ice_transport_type_changed =
|
|
|
|
|
configuration.surface_ice_candidates_on_ice_transport_type_changed;
|
2017-02-03 16:54:05 -08:00
|
|
|
modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
|
2018-03-08 14:55:14 -08:00
|
|
|
modified_config.ice_check_interval_strong_connectivity =
|
|
|
|
|
configuration.ice_check_interval_strong_connectivity;
|
|
|
|
|
modified_config.ice_check_interval_weak_connectivity =
|
|
|
|
|
configuration.ice_check_interval_weak_connectivity;
|
2018-03-13 10:53:57 -07:00
|
|
|
modified_config.ice_unwritable_timeout = configuration.ice_unwritable_timeout;
|
|
|
|
|
modified_config.ice_unwritable_min_checks =
|
|
|
|
|
configuration.ice_unwritable_min_checks;
|
2018-12-06 23:30:17 -08:00
|
|
|
modified_config.ice_inactive_timeout = configuration.ice_inactive_timeout;
|
2018-02-20 14:45:49 -08:00
|
|
|
modified_config.stun_candidate_keepalive_interval =
|
|
|
|
|
configuration.stun_candidate_keepalive_interval;
|
2017-10-10 14:01:40 +02:00
|
|
|
modified_config.turn_customizer = configuration.turn_customizer;
|
2018-02-01 10:38:40 -08:00
|
|
|
modified_config.network_preference = configuration.network_preference;
|
2018-06-12 11:41:11 -07:00
|
|
|
modified_config.active_reset_srtp_params =
|
|
|
|
|
configuration.active_reset_srtp_params;
|
2019-08-22 16:16:35 +02:00
|
|
|
modified_config.turn_logging_id = configuration.turn_logging_id;
|
2019-10-25 12:23:02 +02:00
|
|
|
modified_config.allow_codec_switching = configuration.allow_codec_switching;
|
2017-01-11 12:28:30 -08:00
|
|
|
if (configuration != modified_config) {
|
2019-08-19 09:58:17 +02:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
|
|
|
|
|
"Modifying the configuration in an unsupported way.");
|
2016-12-24 00:47:59 -08:00
|
|
|
}
|
|
|
|
|
|
2017-07-14 15:59:59 -07:00
|
|
|
// Validate the modified configuration.
|
|
|
|
|
RTCError validate_error = ValidateConfiguration(modified_config);
|
|
|
|
|
if (!validate_error.ok()) {
|
2019-08-19 09:58:17 +02:00
|
|
|
return validate_error;
|
2017-07-14 15:59:59 -07:00
|
|
|
}
|
|
|
|
|
|
2017-01-11 12:28:30 -08:00
|
|
|
// Note that this isn't possible through chromium, since it's an unsigned
|
|
|
|
|
// short in WebIDL.
|
|
|
|
|
if (configuration.ice_candidate_pool_size < 0 ||
|
2018-05-03 03:34:17 -07:00
|
|
|
configuration.ice_candidate_pool_size > static_cast<int>(UINT16_MAX)) {
|
2019-08-19 09:58:17 +02:00
|
|
|
return RTCError(RTCErrorType::INVALID_RANGE);
|
2017-01-11 12:28:30 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse ICE servers before hopping to network thread.
|
|
|
|
|
cricket::ServerAddresses stun_servers;
|
|
|
|
|
std::vector<cricket::RelayServerConfig> turn_servers;
|
|
|
|
|
RTCErrorType parse_error =
|
|
|
|
|
ParseIceServers(configuration.servers, &stun_servers, &turn_servers);
|
|
|
|
|
if (parse_error != RTCErrorType::NONE) {
|
2019-08-19 09:58:17 +02:00
|
|
|
return RTCError(parse_error);
|
2017-01-11 12:28:30 -08:00
|
|
|
}
|
2019-08-22 16:16:35 +02:00
|
|
|
// Add the turn logging id to all turn servers
|
|
|
|
|
for (cricket::RelayServerConfig& turn_server : turn_servers) {
|
|
|
|
|
turn_server.turn_logging_id = configuration.turn_logging_id;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 14:00:34 +02:00
|
|
|
// Note if STUN or TURN servers were supplied.
|
|
|
|
|
if (!stun_servers.empty()) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::STUN_SERVER_ADDED);
|
|
|
|
|
}
|
|
|
|
|
if (!turn_servers.empty()) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::TURN_SERVER_ADDED);
|
|
|
|
|
}
|
2017-01-11 12:28:30 -08:00
|
|
|
|
|
|
|
|
// In theory this shouldn't fail.
|
|
|
|
|
if (!network_thread()->Invoke<bool>(
|
|
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
rtc::Bind(&PeerConnection::ReconfigurePortAllocator_n, this,
|
|
|
|
|
stun_servers, turn_servers, modified_config.type,
|
|
|
|
|
modified_config.ice_candidate_pool_size,
|
2019-10-14 11:27:50 -07:00
|
|
|
modified_config.GetTurnPortPrunePolicy(),
|
2018-02-20 14:45:49 -08:00
|
|
|
modified_config.turn_customizer,
|
2019-04-03 11:37:28 +02:00
|
|
|
modified_config.stun_candidate_keepalive_interval,
|
|
|
|
|
static_cast<bool>(local_description())))) {
|
2019-08-19 09:58:17 +02:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
|
|
|
|
|
"Failed to apply configuration to PortAllocator.");
|
2017-01-11 12:28:30 -08:00
|
|
|
}
|
2016-08-31 08:18:11 -07:00
|
|
|
|
2016-12-10 13:15:33 -08:00
|
|
|
// As described in JSEP, calling setConfiguration with new ICE servers or
|
|
|
|
|
// candidate policy must set a "needs-ice-restart" bit so that the next offer
|
|
|
|
|
// triggers an ICE restart which will pick up the changes.
|
2017-01-11 12:28:30 -08:00
|
|
|
if (modified_config.servers != configuration_.servers ||
|
2020-05-27 09:01:05 +02:00
|
|
|
NeedIceRestart(
|
|
|
|
|
configuration_.surface_ice_candidates_on_ice_transport_type_changed,
|
|
|
|
|
configuration_.type, modified_config.type) ||
|
2019-10-14 11:27:50 -07:00
|
|
|
modified_config.GetTurnPortPrunePolicy() !=
|
|
|
|
|
configuration_.GetTurnPortPrunePolicy()) {
|
2017-11-06 14:50:29 -08:00
|
|
|
transport_controller_->SetNeedsIceRestartFlag();
|
2016-12-10 13:15:33 -08:00
|
|
|
}
|
2017-02-03 16:54:05 -08:00
|
|
|
|
2018-02-15 15:10:59 -08:00
|
|
|
transport_controller_->SetIceConfig(ParseIceConfig(modified_config));
|
2019-06-28 14:19:38 -07:00
|
|
|
|
2018-06-12 11:41:11 -07:00
|
|
|
if (configuration_.active_reset_srtp_params !=
|
|
|
|
|
modified_config.active_reset_srtp_params) {
|
|
|
|
|
transport_controller_->SetActiveResetSrtpParams(
|
|
|
|
|
modified_config.active_reset_srtp_params);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 12:23:02 +02:00
|
|
|
if (modified_config.allow_codec_switching.has_value()) {
|
2020-09-21 15:56:42 +02:00
|
|
|
std::vector<cricket::VideoMediaChannel*> channels;
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2020-09-21 15:56:42 +02:00
|
|
|
if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO)
|
2020-08-24 13:28:47 -07:00
|
|
|
continue;
|
2020-09-21 15:56:42 +02:00
|
|
|
|
2020-08-24 13:28:47 -07:00
|
|
|
auto* video_channel = static_cast<cricket::VideoChannel*>(
|
|
|
|
|
transceiver->internal()->channel());
|
2020-09-21 15:56:42 +02:00
|
|
|
if (video_channel)
|
|
|
|
|
channels.push_back(video_channel->media_channel());
|
2019-11-14 13:03:25 +01:00
|
|
|
}
|
2020-09-21 15:56:42 +02:00
|
|
|
|
|
|
|
|
worker_thread()->Invoke<void>(
|
|
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
[channels = std::move(channels),
|
|
|
|
|
allow_codec_switching = *modified_config.allow_codec_switching]() {
|
|
|
|
|
for (auto* ch : channels)
|
|
|
|
|
ch->SetVideoCodecSwitchingEnabled(allow_codec_switching);
|
|
|
|
|
});
|
2019-10-25 12:23:02 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-11 12:28:30 -08:00
|
|
|
configuration_ = modified_config;
|
2019-08-19 09:58:17 +02:00
|
|
|
return RTCError::OK();
|
2014-05-03 05:39:45 +00:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
bool PeerConnection::AddIceCandidate(
|
|
|
|
|
const IceCandidateInterface* ice_candidate) {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.AddIceCandidate(ice_candidate);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-06 12:36:12 +01:00
|
|
|
void PeerConnection::AddIceCandidate(
|
|
|
|
|
std::unique_ptr<IceCandidateInterface> candidate,
|
|
|
|
|
std::function<void(RTCError)> callback) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.AddIceCandidate(std::move(candidate), callback);
|
2019-11-06 12:36:12 +01:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 11:59:18 -07:00
|
|
|
bool PeerConnection::RemoveIceCandidates(
|
|
|
|
|
const std::vector<cricket::Candidate>& candidates) {
|
|
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.RemoveIceCandidates(candidates);
|
2016-03-14 11:59:18 -07:00
|
|
|
}
|
|
|
|
|
|
2018-05-07 14:01:37 +02:00
|
|
|
RTCError PeerConnection::SetBitrate(const BitrateSettings& bitrate) {
|
2017-09-29 12:15:02 -07:00
|
|
|
if (!worker_thread()->IsCurrent()) {
|
|
|
|
|
return worker_thread()->Invoke<RTCError>(
|
2018-05-07 14:01:37 +02:00
|
|
|
RTC_FROM_HERE, [&]() { return SetBitrate(bitrate); });
|
2017-06-02 14:37:37 -07:00
|
|
|
}
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2017-06-02 14:37:37 -07:00
|
|
|
|
2018-05-07 14:01:37 +02:00
|
|
|
const bool has_min = bitrate.min_bitrate_bps.has_value();
|
|
|
|
|
const bool has_start = bitrate.start_bitrate_bps.has_value();
|
|
|
|
|
const bool has_max = bitrate.max_bitrate_bps.has_value();
|
2017-06-02 14:37:37 -07:00
|
|
|
if (has_min && *bitrate.min_bitrate_bps < 0) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"min_bitrate_bps <= 0");
|
|
|
|
|
}
|
2018-05-07 14:01:37 +02:00
|
|
|
if (has_start) {
|
|
|
|
|
if (has_min && *bitrate.start_bitrate_bps < *bitrate.min_bitrate_bps) {
|
2017-06-02 14:37:37 -07:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
2018-05-07 14:01:37 +02:00
|
|
|
"start_bitrate_bps < min_bitrate_bps");
|
|
|
|
|
} else if (*bitrate.start_bitrate_bps < 0) {
|
2017-06-02 14:37:37 -07:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"curent_bitrate_bps < 0");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (has_max) {
|
2018-05-07 14:01:37 +02:00
|
|
|
if (has_start && *bitrate.max_bitrate_bps < *bitrate.start_bitrate_bps) {
|
2017-06-02 14:37:37 -07:00
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
2018-05-07 14:01:37 +02:00
|
|
|
"max_bitrate_bps < start_bitrate_bps");
|
2017-06-02 14:37:37 -07:00
|
|
|
} else if (has_min && *bitrate.max_bitrate_bps < *bitrate.min_bitrate_bps) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"max_bitrate_bps < min_bitrate_bps");
|
|
|
|
|
} else if (*bitrate.max_bitrate_bps < 0) {
|
|
|
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
|
|
|
"max_bitrate_bps < 0");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTC_DCHECK(call_.get());
|
2019-03-18 10:31:54 -07:00
|
|
|
call_->SetClientBitratePreferences(bitrate);
|
2017-06-02 14:37:37 -07:00
|
|
|
|
|
|
|
|
return RTCError::OK();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-01 11:06:56 +01:00
|
|
|
void PeerConnection::SetAudioPlayout(bool playout) {
|
|
|
|
|
if (!worker_thread()->IsCurrent()) {
|
|
|
|
|
worker_thread()->Invoke<void>(
|
|
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
rtc::Bind(&PeerConnection::SetAudioPlayout, this, playout));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto audio_state =
|
2018-11-16 11:29:55 +01:00
|
|
|
factory_->channel_manager()->media_engine()->voice().GetAudioState();
|
2017-11-01 11:06:56 +01:00
|
|
|
audio_state->SetPlayout(playout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::SetAudioRecording(bool recording) {
|
|
|
|
|
if (!worker_thread()->IsCurrent()) {
|
|
|
|
|
worker_thread()->Invoke<void>(
|
|
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
rtc::Bind(&PeerConnection::SetAudioRecording, this, recording));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
auto audio_state =
|
2018-11-16 11:29:55 +01:00
|
|
|
factory_->channel_manager()->media_engine()->voice().GetAudioState();
|
2017-11-01 11:06:56 +01:00
|
|
|
audio_state->SetRecording(recording);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-03 10:03:10 -07:00
|
|
|
std::unique_ptr<rtc::SSLCertificate>
|
|
|
|
|
PeerConnection::GetRemoteAudioSSLCertificate() {
|
2018-02-23 13:04:51 -08:00
|
|
|
std::unique_ptr<rtc::SSLCertChain> chain = GetRemoteAudioSSLCertChain();
|
|
|
|
|
if (!chain || !chain->GetSize()) {
|
2017-10-03 10:03:10 -07:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
2018-10-16 15:23:31 -07:00
|
|
|
return chain->Get(0).Clone();
|
2017-10-03 10:03:10 -07:00
|
|
|
}
|
|
|
|
|
|
2018-01-27 14:16:15 -08:00
|
|
|
std::unique_ptr<rtc::SSLCertChain>
|
|
|
|
|
PeerConnection::GetRemoteAudioSSLCertChain() {
|
2019-03-26 13:33:43 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-02-20 11:35:37 -08:00
|
|
|
auto audio_transceiver = GetFirstAudioTransceiver();
|
|
|
|
|
if (!audio_transceiver || !audio_transceiver->internal()->channel()) {
|
2018-01-27 14:16:15 -08:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return transport_controller_->GetRemoteSSLCertChain(
|
2018-02-20 11:35:37 -08:00
|
|
|
audio_transceiver->internal()->channel()->transport_name());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
|
|
|
|
PeerConnection::GetFirstAudioTransceiver() const {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (auto transceiver : transceivers_.List()) {
|
2018-02-20 11:35:37 -08:00
|
|
|
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
return transceiver;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2018-01-27 14:16:15 -08:00
|
|
|
}
|
|
|
|
|
|
2020-06-11 12:26:53 +02:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-20 17:38:14 +01:00
|
|
|
bool PeerConnection::StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
|
|
|
|
|
int64_t output_period_ms) {
|
|
|
|
|
return worker_thread()->Invoke<bool>(
|
2019-09-05 10:21:11 +02:00
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
[this, output = std::move(output), output_period_ms]() mutable {
|
|
|
|
|
return StartRtcEventLog_w(std::move(output), output_period_ms);
|
|
|
|
|
});
|
2016-07-04 07:06:55 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-10 11:33:12 +02:00
|
|
|
bool PeerConnection::StartRtcEventLog(
|
|
|
|
|
std::unique_ptr<RtcEventLogOutput> output) {
|
2019-05-13 12:27:23 +02:00
|
|
|
int64_t output_period_ms = webrtc::RtcEventLog::kImmediateOutput;
|
2020-09-22 11:36:35 +02:00
|
|
|
if (absl::StartsWith(factory_->trials().Lookup("WebRTC-RtcEventLogNewFormat"),
|
|
|
|
|
"Enabled")) {
|
2019-05-13 12:27:23 +02:00
|
|
|
output_period_ms = 5000;
|
|
|
|
|
}
|
|
|
|
|
return StartRtcEventLog(std::move(output), output_period_ms);
|
2019-05-10 11:33:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-07-04 07:06:55 -07:00
|
|
|
void PeerConnection::StopRtcEventLog() {
|
2017-09-29 12:15:02 -07:00
|
|
|
worker_thread()->Invoke<void>(
|
2016-07-04 07:06:55 -07:00
|
|
|
RTC_FROM_HERE, rtc::Bind(&PeerConnection::StopRtcEventLog_w, this));
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-28 16:47:46 +01:00
|
|
|
rtc::scoped_refptr<DtlsTransportInterface>
|
|
|
|
|
PeerConnection::LookupDtlsTransportByMid(const std::string& mid) {
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-11-28 16:47:46 +01:00
|
|
|
return transport_controller_->LookupDtlsTransportByMid(mid);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-17 10:39:40 +01:00
|
|
|
rtc::scoped_refptr<DtlsTransport>
|
|
|
|
|
PeerConnection::LookupDtlsTransportByMidInternal(const std::string& mid) {
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2019-01-17 10:39:40 +01:00
|
|
|
return transport_controller_->LookupDtlsTransportByMid(mid);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-28 07:51:00 +01:00
|
|
|
rtc::scoped_refptr<SctpTransportInterface> PeerConnection::GetSctpTransport()
|
|
|
|
|
const {
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-02-12 07:38:21 +01:00
|
|
|
if (!sctp_mid_s_) {
|
2019-09-23 14:53:54 -07:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
2020-02-12 07:38:21 +01:00
|
|
|
return transport_controller_->GetSctpTransport(*sctp_mid_s_);
|
2019-02-28 07:51:00 +01:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
const SessionDescriptionInterface* PeerConnection::local_description() const {
|
2019-04-03 11:37:28 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.local_description();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SessionDescriptionInterface* PeerConnection::remote_description() const {
|
2019-04-03 11:37:28 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.remote_description();
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2016-12-20 17:56:17 -08:00
|
|
|
const SessionDescriptionInterface* PeerConnection::current_local_description()
|
|
|
|
|
const {
|
2019-04-03 11:37:28 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.current_local_description();
|
2016-12-20 17:56:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SessionDescriptionInterface* PeerConnection::current_remote_description()
|
|
|
|
|
const {
|
2019-04-03 11:37:28 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.current_remote_description();
|
2016-12-20 17:56:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SessionDescriptionInterface* PeerConnection::pending_local_description()
|
|
|
|
|
const {
|
2019-04-03 11:37:28 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.pending_local_description();
|
2016-12-20 17:56:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SessionDescriptionInterface* PeerConnection::pending_remote_description()
|
|
|
|
|
const {
|
2019-04-03 11:37:28 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.pending_remote_description();
|
2016-12-20 17:56:17 -08:00
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
void PeerConnection::Close() {
|
2019-02-14 10:18:56 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2015-12-08 22:15:17 +01:00
|
|
|
TRACE_EVENT0("webrtc", "PeerConnection::Close");
|
2020-09-28 13:02:07 +00:00
|
|
|
|
|
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
// Update stats here so that we have the most recent stats for tracks and
|
|
|
|
|
// streams before the channels are closed.
|
2014-07-14 20:15:26 +00:00
|
|
|
stats_->UpdateStats(kStatsOutputLevelStandard);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2020-09-28 13:02:07 +00:00
|
|
|
ice_connection_state_ = PeerConnectionInterface::kIceConnectionClosed;
|
|
|
|
|
Observer()->OnIceConnectionChange(ice_connection_state_);
|
|
|
|
|
standardized_ice_connection_state_ =
|
|
|
|
|
PeerConnectionInterface::IceConnectionState::kIceConnectionClosed;
|
|
|
|
|
connection_state_ = PeerConnectionInterface::PeerConnectionState::kClosed;
|
|
|
|
|
Observer()->OnConnectionChange(connection_state_);
|
|
|
|
|
|
|
|
|
|
sdp_handler_.Close();
|
|
|
|
|
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::CLOSE_CALLED);
|
2017-12-12 10:20:08 -08:00
|
|
|
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2020-08-11 09:54:02 +02:00
|
|
|
transceiver->internal()->SetPeerConnectionClosed();
|
|
|
|
|
if (!transceiver->stopped())
|
|
|
|
|
transceiver->StopInternal();
|
2017-12-15 11:20:13 -08:00
|
|
|
}
|
2018-04-26 11:44:00 -07:00
|
|
|
|
|
|
|
|
// Ensure that all asynchronous stats requests are completed before destroying
|
|
|
|
|
// the transport controller below.
|
|
|
|
|
if (stats_collector_) {
|
|
|
|
|
stats_collector_->WaitForPendingRequest();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't destroy BaseChannels until after stats has been cleaned up so that
|
|
|
|
|
// the last stats request can still read from the channels.
|
2020-10-05 13:08:41 +00:00
|
|
|
sdp_handler_.DestroyAllChannels();
|
2017-11-06 10:37:17 -08:00
|
|
|
|
2018-01-30 17:13:09 -08:00
|
|
|
// The event log is used in the transport controller, which must be outlived
|
|
|
|
|
// by the former. CreateOffer by the peer connection is implemented
|
|
|
|
|
// asynchronously and if the peer connection is closed without resetting the
|
|
|
|
|
// WebRTC session description factory, the session description factory would
|
|
|
|
|
// call the transport controller.
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.ResetSessionDescFactory();
|
2018-01-30 17:13:09 -08:00
|
|
|
transport_controller_.reset();
|
|
|
|
|
|
2017-03-10 15:18:00 -08:00
|
|
|
network_thread()->Invoke<void>(
|
|
|
|
|
RTC_FROM_HERE, rtc::Bind(&cricket::PortAllocator::DiscardCandidatePool,
|
|
|
|
|
port_allocator_.get()));
|
2017-05-05 02:23:02 -07:00
|
|
|
|
2017-09-29 12:15:02 -07:00
|
|
|
worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
|
2019-02-14 11:59:57 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2020-09-28 10:39:31 +02:00
|
|
|
call_safety_.reset();
|
2017-09-06 05:18:15 -07:00
|
|
|
call_.reset();
|
|
|
|
|
// The event log must outlive call (and any other object that uses it).
|
|
|
|
|
event_log_.reset();
|
|
|
|
|
});
|
2018-05-31 14:00:34 +02:00
|
|
|
ReportUsagePattern();
|
2018-08-01 10:50:16 +02:00
|
|
|
// The .h file says that observer can be discarded after close() returns.
|
|
|
|
|
// Make sure this is true.
|
|
|
|
|
observer_ = nullptr;
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2018-02-20 11:35:37 -08:00
|
|
|
cricket::VoiceMediaChannel* PeerConnection::voice_media_channel() const {
|
|
|
|
|
RTC_DCHECK(!IsUnifiedPlan());
|
|
|
|
|
auto* voice_channel = static_cast<cricket::VoiceChannel*>(
|
|
|
|
|
GetAudioTransceiver()->internal()->channel());
|
|
|
|
|
if (voice_channel) {
|
|
|
|
|
return voice_channel->media_channel();
|
|
|
|
|
} else {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cricket::VideoMediaChannel* PeerConnection::video_media_channel() const {
|
|
|
|
|
RTC_DCHECK(!IsUnifiedPlan());
|
|
|
|
|
auto* video_channel = static_cast<cricket::VideoChannel*>(
|
|
|
|
|
GetVideoTransceiver()->internal()->channel());
|
|
|
|
|
if (video_channel) {
|
|
|
|
|
return video_channel->media_channel();
|
|
|
|
|
} else {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
void PeerConnection::CreateAudioReceiver(
|
|
|
|
|
MediaStreamInterface* stream,
|
|
|
|
|
const RtpSenderInfo& remote_sender_info) {
|
2017-11-21 13:41:51 +01:00
|
|
|
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
|
|
|
|
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
|
2018-07-04 20:51:53 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
|
|
|
|
|
// the constructor taking stream IDs instead.
|
2018-01-17 17:41:02 -08:00
|
|
|
auto* audio_receiver = new AudioRtpReceiver(
|
|
|
|
|
worker_thread(), remote_sender_info.sender_id, streams);
|
2018-11-13 16:26:05 -08:00
|
|
|
audio_receiver->SetMediaChannel(voice_media_channel());
|
2019-09-11 16:23:05 -07:00
|
|
|
if (remote_sender_info.sender_id == kDefaultAudioSenderId) {
|
|
|
|
|
audio_receiver->SetupUnsignaledMediaChannel();
|
|
|
|
|
} else {
|
|
|
|
|
audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
|
|
|
|
|
}
|
2018-01-17 17:41:02 -08:00
|
|
|
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
|
|
|
|
signaling_thread(), audio_receiver);
|
2017-11-20 10:20:22 -08:00
|
|
|
GetAudioTransceiver()->internal()->AddReceiver(receiver);
|
2019-01-31 21:38:12 +01:00
|
|
|
Observer()->OnAddTrack(receiver, streams);
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
void PeerConnection::CreateVideoReceiver(
|
|
|
|
|
MediaStreamInterface* stream,
|
|
|
|
|
const RtpSenderInfo& remote_sender_info) {
|
2017-11-21 13:41:51 +01:00
|
|
|
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
|
|
|
|
streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
|
2018-07-04 20:51:53 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
|
|
|
|
|
// the constructor taking stream IDs instead.
|
2018-01-17 17:41:02 -08:00
|
|
|
auto* video_receiver = new VideoRtpReceiver(
|
|
|
|
|
worker_thread(), remote_sender_info.sender_id, streams);
|
2018-11-13 16:26:05 -08:00
|
|
|
video_receiver->SetMediaChannel(video_media_channel());
|
2019-09-11 16:23:05 -07:00
|
|
|
if (remote_sender_info.sender_id == kDefaultVideoSenderId) {
|
|
|
|
|
video_receiver->SetupUnsignaledMediaChannel();
|
|
|
|
|
} else {
|
|
|
|
|
video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
|
|
|
|
|
}
|
2018-01-17 17:41:02 -08:00
|
|
|
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
|
|
|
|
signaling_thread(), video_receiver);
|
2017-11-20 10:20:22 -08:00
|
|
|
GetVideoTransceiver()->internal()->AddReceiver(receiver);
|
2019-01-31 21:38:12 +01:00
|
|
|
Observer()->OnAddTrack(receiver, streams);
|
2018-05-31 14:00:34 +02:00
|
|
|
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-09-28 16:53:55 -07:00
|
|
|
// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
|
|
|
|
|
// description.
|
Reland "Added PeerConnectionObserver::OnRemoveTrack."
This reverts commit 6c0c55c31817ecfa32409424495eb68b31828c40.
Reason for revert:
Fixed the flake.
Original change's description:
> Revert "Added PeerConnectionObserver::OnRemoveTrack."
>
> This reverts commit ba97ba7af917d4152f5f3363aba1c1561c6673dc.
>
> Reason for revert: The new tests have caused several test failures on the test bots; the method FakeAudioMediaStreamTrack:GetSignalLevel, which is not supposed to be called is sometimes called anyway.
>
> Original change's description:
> > Added PeerConnectionObserver::OnRemoveTrack.
> >
> > This corresponds to processing the removal of a remote track step of
> > the spec, with processing the addition of a remote track already
> > covered by OnAddTrack.
> > https://w3c.github.io/webrtc-pc/#processing-remote-mediastreamtracks
> >
> > Bug: webrtc:8260, webrtc:8315
> > Change-Id: Ica8be92369733eb3cf1397fb60385d45a9b58700
> > Reviewed-on: https://webrtc-review.googlesource.com/4722
> > Commit-Queue: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#20214}
>
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,hbos@webrtc.org
>
> Change-Id: Id2d9533e27227254769b4280a8ff10a47313e714
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8260, webrtc:8315
> Reviewed-on: https://webrtc-review.googlesource.com/7940
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Alex Loiko <aleloi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#20218}
TBR=steveanton@webrtc.org,deadbeef@webrtc.org,aleloi@webrtc.org,hbos@webrtc.org
Change-Id: Iab7500bebf98535754b102874259de43831fff6b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8260, webrtc:8315
Reviewed-on: https://webrtc-review.googlesource.com/8180
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20227}
2017-10-10 10:05:16 -07:00
|
|
|
rtc::scoped_refptr<RtpReceiverInterface> PeerConnection::RemoveAndStopReceiver(
|
2017-11-20 10:20:22 -08:00
|
|
|
const RtpSenderInfo& remote_sender_info) {
|
|
|
|
|
auto receiver = FindReceiverById(remote_sender_info.sender_id);
|
|
|
|
|
if (!receiver) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "RtpReceiver for track with id "
|
|
|
|
|
<< remote_sender_info.sender_id << " doesn't exist.";
|
Reland "Added PeerConnectionObserver::OnRemoveTrack."
This reverts commit 6c0c55c31817ecfa32409424495eb68b31828c40.
Reason for revert:
Fixed the flake.
Original change's description:
> Revert "Added PeerConnectionObserver::OnRemoveTrack."
>
> This reverts commit ba97ba7af917d4152f5f3363aba1c1561c6673dc.
>
> Reason for revert: The new tests have caused several test failures on the test bots; the method FakeAudioMediaStreamTrack:GetSignalLevel, which is not supposed to be called is sometimes called anyway.
>
> Original change's description:
> > Added PeerConnectionObserver::OnRemoveTrack.
> >
> > This corresponds to processing the removal of a remote track step of
> > the spec, with processing the addition of a remote track already
> > covered by OnAddTrack.
> > https://w3c.github.io/webrtc-pc/#processing-remote-mediastreamtracks
> >
> > Bug: webrtc:8260, webrtc:8315
> > Change-Id: Ica8be92369733eb3cf1397fb60385d45a9b58700
> > Reviewed-on: https://webrtc-review.googlesource.com/4722
> > Commit-Queue: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#20214}
>
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,hbos@webrtc.org
>
> Change-Id: Id2d9533e27227254769b4280a8ff10a47313e714
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8260, webrtc:8315
> Reviewed-on: https://webrtc-review.googlesource.com/7940
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Alex Loiko <aleloi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#20218}
TBR=steveanton@webrtc.org,deadbeef@webrtc.org,aleloi@webrtc.org,hbos@webrtc.org
Change-Id: Iab7500bebf98535754b102874259de43831fff6b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8260, webrtc:8315
Reviewed-on: https://webrtc-review.googlesource.com/8180
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20227}
2017-10-10 10:05:16 -07:00
|
|
|
return nullptr;
|
2015-09-28 16:53:55 -07:00
|
|
|
}
|
2017-11-20 10:20:22 -08:00
|
|
|
if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
GetAudioTransceiver()->internal()->RemoveReceiver(receiver);
|
|
|
|
|
} else {
|
|
|
|
|
GetVideoTransceiver()->internal()->RemoveReceiver(receiver);
|
|
|
|
|
}
|
Reland "Added PeerConnectionObserver::OnRemoveTrack."
This reverts commit 6c0c55c31817ecfa32409424495eb68b31828c40.
Reason for revert:
Fixed the flake.
Original change's description:
> Revert "Added PeerConnectionObserver::OnRemoveTrack."
>
> This reverts commit ba97ba7af917d4152f5f3363aba1c1561c6673dc.
>
> Reason for revert: The new tests have caused several test failures on the test bots; the method FakeAudioMediaStreamTrack:GetSignalLevel, which is not supposed to be called is sometimes called anyway.
>
> Original change's description:
> > Added PeerConnectionObserver::OnRemoveTrack.
> >
> > This corresponds to processing the removal of a remote track step of
> > the spec, with processing the addition of a remote track already
> > covered by OnAddTrack.
> > https://w3c.github.io/webrtc-pc/#processing-remote-mediastreamtracks
> >
> > Bug: webrtc:8260, webrtc:8315
> > Change-Id: Ica8be92369733eb3cf1397fb60385d45a9b58700
> > Reviewed-on: https://webrtc-review.googlesource.com/4722
> > Commit-Queue: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#20214}
>
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,hbos@webrtc.org
>
> Change-Id: Id2d9533e27227254769b4280a8ff10a47313e714
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8260, webrtc:8315
> Reviewed-on: https://webrtc-review.googlesource.com/7940
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Alex Loiko <aleloi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#20218}
TBR=steveanton@webrtc.org,deadbeef@webrtc.org,aleloi@webrtc.org,hbos@webrtc.org
Change-Id: Iab7500bebf98535754b102874259de43831fff6b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8260, webrtc:8315
Reviewed-on: https://webrtc-review.googlesource.com/8180
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20227}
2017-10-10 10:05:16 -07:00
|
|
|
return receiver;
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2017-07-24 17:00:25 -07:00
|
|
|
void PeerConnection::AddAudioTrack(AudioTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2020-10-09 11:42:17 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-07-24 17:00:25 -07:00
|
|
|
RTC_DCHECK(!IsClosed());
|
2018-06-25 13:03:36 -07:00
|
|
|
RTC_DCHECK(track);
|
|
|
|
|
RTC_DCHECK(stream);
|
2017-07-24 17:00:25 -07:00
|
|
|
auto sender = FindSenderForTrack(track);
|
2017-11-20 10:20:22 -08:00
|
|
|
if (sender) {
|
2017-07-24 17:00:25 -07:00
|
|
|
// We already have a sender for this track, so just change the stream_id
|
|
|
|
|
// so that it's correct in the next call to CreateOffer.
|
2019-05-20 09:01:38 +00:00
|
|
|
sender->internal()->set_stream_ids({stream->id()});
|
2017-07-24 17:00:25 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Normal case; we've never seen this track before.
|
2018-06-25 13:03:36 -07:00
|
|
|
auto new_sender = CreateSender(cricket::MEDIA_TYPE_AUDIO, track->id(), track,
|
2018-10-01 22:47:20 +02:00
|
|
|
{stream->id()}, {});
|
2018-11-13 16:26:05 -08:00
|
|
|
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
2017-11-20 10:20:22 -08:00
|
|
|
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
2017-07-24 17:00:25 -07:00
|
|
|
// If the sender has already been configured in SDP, we call SetSsrc,
|
|
|
|
|
// which will connect the sender to the underlying transport. This can
|
|
|
|
|
// occur if a local session description that contains the ID of the sender
|
|
|
|
|
// is set before AddStream is called. It can also occur if the local
|
|
|
|
|
// session description is not changed and RemoveStream is called, and
|
|
|
|
|
// later AddStream is called again with the same stream.
|
2017-11-20 10:20:22 -08:00
|
|
|
const RtpSenderInfo* sender_info =
|
2018-03-27 21:57:18 +00:00
|
|
|
FindSenderInfo(local_audio_sender_infos_, stream->id(), track->id());
|
2017-11-20 10:20:22 -08:00
|
|
|
if (sender_info) {
|
|
|
|
|
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
2017-07-24 17:00:25 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
|
|
|
|
|
// indefinitely, when we have unified plan SDP.
|
|
|
|
|
void PeerConnection::RemoveAudioTrack(AudioTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2020-10-09 11:42:17 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-07-24 17:00:25 -07:00
|
|
|
RTC_DCHECK(!IsClosed());
|
|
|
|
|
auto sender = FindSenderForTrack(track);
|
2017-11-20 10:20:22 -08:00
|
|
|
if (!sender) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
|
|
|
|
|
<< " doesn't exist.";
|
2017-07-24 17:00:25 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2017-11-20 10:20:22 -08:00
|
|
|
GetAudioTransceiver()->internal()->RemoveSender(sender);
|
2017-07-24 17:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::AddVideoTrack(VideoTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2020-10-09 11:42:17 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-07-24 17:00:25 -07:00
|
|
|
RTC_DCHECK(!IsClosed());
|
2018-06-25 13:03:36 -07:00
|
|
|
RTC_DCHECK(track);
|
|
|
|
|
RTC_DCHECK(stream);
|
2017-07-24 17:00:25 -07:00
|
|
|
auto sender = FindSenderForTrack(track);
|
2017-11-20 10:20:22 -08:00
|
|
|
if (sender) {
|
2017-07-24 17:00:25 -07:00
|
|
|
// We already have a sender for this track, so just change the stream_id
|
|
|
|
|
// so that it's correct in the next call to CreateOffer.
|
2019-05-20 09:01:38 +00:00
|
|
|
sender->internal()->set_stream_ids({stream->id()});
|
2017-07-24 17:00:25 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Normal case; we've never seen this track before.
|
2018-06-25 13:03:36 -07:00
|
|
|
auto new_sender = CreateSender(cricket::MEDIA_TYPE_VIDEO, track->id(), track,
|
2018-10-01 22:47:20 +02:00
|
|
|
{stream->id()}, {});
|
2018-11-13 16:26:05 -08:00
|
|
|
new_sender->internal()->SetMediaChannel(video_media_channel());
|
2017-11-20 10:20:22 -08:00
|
|
|
GetVideoTransceiver()->internal()->AddSender(new_sender);
|
|
|
|
|
const RtpSenderInfo* sender_info =
|
2018-03-27 21:57:18 +00:00
|
|
|
FindSenderInfo(local_video_sender_infos_, stream->id(), track->id());
|
2017-11-20 10:20:22 -08:00
|
|
|
if (sender_info) {
|
|
|
|
|
new_sender->internal()->SetSsrc(sender_info->first_ssrc);
|
2017-07-24 17:00:25 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::RemoveVideoTrack(VideoTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2020-10-09 11:42:17 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-07-24 17:00:25 -07:00
|
|
|
RTC_DCHECK(!IsClosed());
|
|
|
|
|
auto sender = FindSenderForTrack(track);
|
2017-11-20 10:20:22 -08:00
|
|
|
if (!sender) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
|
|
|
|
|
<< " doesn't exist.";
|
2017-07-24 17:00:25 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2017-11-20 10:20:22 -08:00
|
|
|
GetVideoTransceiver()->internal()->RemoveSender(sender);
|
2017-07-24 17:00:25 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:21:57 -08:00
|
|
|
void PeerConnection::SetIceConnectionState(IceConnectionState new_state) {
|
2020-09-28 13:02:07 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-06 10:21:57 -08:00
|
|
|
if (ice_connection_state_ == new_state) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-23 11:50:27 -07:00
|
|
|
// After transitioning to "closed", ignore any additional states from
|
2017-11-06 10:21:57 -08:00
|
|
|
// TransportController (such as "disconnected").
|
2015-10-14 11:33:11 -07:00
|
|
|
if (IsClosed()) {
|
2015-09-23 11:50:27 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2017-11-06 10:21:57 -08:00
|
|
|
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
|
|
|
|
|
<< " => " << new_state;
|
2017-11-06 10:21:57 -08:00
|
|
|
RTC_DCHECK(ice_connection_state_ !=
|
|
|
|
|
PeerConnectionInterface::kIceConnectionClosed);
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
ice_connection_state_ = new_state;
|
2018-08-01 10:50:16 +02:00
|
|
|
Observer()->OnIceConnectionChange(ice_connection_state_);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2018-11-23 16:18:59 +00:00
|
|
|
void PeerConnection::SetStandardizedIceConnectionState(
|
|
|
|
|
PeerConnectionInterface::IceConnectionState new_state) {
|
2019-05-29 11:37:26 -07:00
|
|
|
if (standardized_ice_connection_state_ == new_state) {
|
2018-11-23 16:18:59 +00:00
|
|
|
return;
|
2019-05-29 11:37:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IsClosed()) {
|
2018-11-23 16:18:59 +00:00
|
|
|
return;
|
2019-05-29 11:37:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RTC_LOG(LS_INFO) << "Changing standardized IceConnectionState "
|
|
|
|
|
<< standardized_ice_connection_state_ << " => " << new_state;
|
|
|
|
|
|
2018-11-23 16:18:59 +00:00
|
|
|
standardized_ice_connection_state_ = new_state;
|
2018-12-06 11:25:14 +01:00
|
|
|
Observer()->OnStandardizedIceConnectionChange(new_state);
|
2018-11-23 16:18:59 +00:00
|
|
|
}
|
|
|
|
|
|
2018-10-18 15:58:17 +02:00
|
|
|
void PeerConnection::SetConnectionState(
|
|
|
|
|
PeerConnectionInterface::PeerConnectionState new_state) {
|
|
|
|
|
if (connection_state_ == new_state)
|
|
|
|
|
return;
|
|
|
|
|
if (IsClosed())
|
|
|
|
|
return;
|
|
|
|
|
connection_state_ = new_state;
|
|
|
|
|
Observer()->OnConnectionChange(new_state);
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
void PeerConnection::OnIceGatheringChange(
|
|
|
|
|
PeerConnectionInterface::IceGatheringState new_state) {
|
|
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ice_gathering_state_ = new_state;
|
2018-08-01 10:50:16 +02:00
|
|
|
Observer()->OnIceGatheringChange(ice_gathering_state_);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2017-03-25 08:31:12 -07:00
|
|
|
void PeerConnection::OnIceCandidate(
|
|
|
|
|
std::unique_ptr<IceCandidateInterface> candidate) {
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-08-19 11:57:17 -07:00
|
|
|
ReportIceCandidateCollected(candidate->candidate());
|
2018-08-01 10:50:16 +02:00
|
|
|
Observer()->OnIceCandidate(candidate.get());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2019-12-02 22:22:07 +02:00
|
|
|
void PeerConnection::OnIceCandidateError(const std::string& address,
|
|
|
|
|
int port,
|
2019-06-01 12:23:43 +03:00
|
|
|
const std::string& url,
|
|
|
|
|
int error_code,
|
|
|
|
|
const std::string& error_text) {
|
|
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-12-02 22:22:07 +02:00
|
|
|
Observer()->OnIceCandidateError(address, port, url, error_code, error_text);
|
|
|
|
|
// Leftover not to break wpt test during migration to the new API.
|
|
|
|
|
Observer()->OnIceCandidateError(address + ":", url, error_code, error_text);
|
2019-06-01 12:23:43 +03:00
|
|
|
}
|
|
|
|
|
|
2016-03-14 11:59:18 -07:00
|
|
|
void PeerConnection::OnIceCandidatesRemoved(
|
|
|
|
|
const std::vector<cricket::Candidate>& candidates) {
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-08-01 10:50:16 +02:00
|
|
|
Observer()->OnIceCandidatesRemoved(candidates);
|
2016-03-14 11:59:18 -07:00
|
|
|
}
|
|
|
|
|
|
2019-08-06 10:54:47 -07:00
|
|
|
void PeerConnection::OnSelectedCandidatePairChanged(
|
|
|
|
|
const cricket::CandidatePairChangeEvent& event) {
|
|
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-08-19 11:57:17 -07:00
|
|
|
|
2019-09-12 11:19:01 -07:00
|
|
|
if (event.selected_candidate_pair.local_candidate().type() ==
|
|
|
|
|
LOCAL_PORT_TYPE &&
|
|
|
|
|
event.selected_candidate_pair.remote_candidate().type() ==
|
|
|
|
|
LOCAL_PORT_TYPE) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::DIRECT_CONNECTION_SELECTED);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-06 10:54:47 -07:00
|
|
|
Observer()->OnIceSelectedCandidatePairChanged(event);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-15 19:24:43 -08:00
|
|
|
void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-07-24 17:00:25 -07:00
|
|
|
AddAudioTrack(track, stream);
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2015-12-15 19:24:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-07-24 17:00:25 -07:00
|
|
|
RemoveAudioTrack(track, stream);
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2015-12-15 19:24:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-07-24 17:00:25 -07:00
|
|
|
AddVideoTrack(track, stream);
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2015-12-15 19:24:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
|
|
|
|
|
MediaStreamInterface* stream) {
|
2016-07-27 11:07:25 -07:00
|
|
|
if (IsClosed()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-07-24 17:00:25 -07:00
|
|
|
RemoveVideoTrack(track, stream);
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2015-12-15 19:24:43 -08:00
|
|
|
}
|
|
|
|
|
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<std::string> PeerConnection::GetDataMid() const {
|
2020-09-28 13:02:07 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2019-12-03 14:04:21 +01:00
|
|
|
switch (data_channel_type()) {
|
2017-12-28 16:38:23 -08:00
|
|
|
case cricket::DCT_RTP:
|
2019-12-02 09:56:02 +01:00
|
|
|
if (!data_channel_controller_.rtp_data_channel()) {
|
2018-06-19 16:47:43 +02:00
|
|
|
return absl::nullopt;
|
2017-12-28 16:38:23 -08:00
|
|
|
}
|
2019-12-02 09:56:02 +01:00
|
|
|
return data_channel_controller_.rtp_data_channel()->content_name();
|
2017-12-28 16:38:23 -08:00
|
|
|
case cricket::DCT_SCTP:
|
2020-02-12 07:38:21 +01:00
|
|
|
return sctp_mid_s_;
|
2017-12-28 16:38:23 -08:00
|
|
|
default:
|
2018-06-19 16:47:43 +02:00
|
|
|
return absl::nullopt;
|
2017-12-28 16:38:23 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
void PeerConnection::OnRemoteSenderAdded(const RtpSenderInfo& sender_info,
|
2020-10-09 11:42:17 +00:00
|
|
|
MediaStreamInterface* stream,
|
2017-11-20 10:20:22 -08:00
|
|
|
cricket::MediaType media_type) {
|
2020-10-01 16:47:23 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-04-02 11:27:23 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Creating " << cricket::MediaTypeToString(media_type)
|
|
|
|
|
<< " receiver for track_id=" << sender_info.sender_id
|
|
|
|
|
<< " and stream_id=" << sender_info.stream_id;
|
2015-10-14 11:33:11 -07:00
|
|
|
|
|
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
2017-11-20 10:20:22 -08:00
|
|
|
CreateAudioReceiver(stream, sender_info);
|
2015-10-14 11:33:11 -07:00
|
|
|
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
2017-11-20 10:20:22 -08:00
|
|
|
CreateVideoReceiver(stream, sender_info);
|
2015-10-14 11:33:11 -07:00
|
|
|
} else {
|
2017-01-12 02:24:27 -08:00
|
|
|
RTC_NOTREACHED() << "Invalid media type";
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
void PeerConnection::OnRemoteSenderRemoved(const RtpSenderInfo& sender_info,
|
2020-10-09 11:42:17 +00:00
|
|
|
MediaStreamInterface* stream,
|
2017-11-20 10:20:22 -08:00
|
|
|
cricket::MediaType media_type) {
|
2020-10-01 16:47:23 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-04-05 18:12:09 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Removing " << cricket::MediaTypeToString(media_type)
|
|
|
|
|
<< " receiver for track_id=" << sender_info.sender_id
|
|
|
|
|
<< " and stream_id=" << sender_info.stream_id;
|
|
|
|
|
|
Reland "Added PeerConnectionObserver::OnRemoveTrack."
This reverts commit 6c0c55c31817ecfa32409424495eb68b31828c40.
Reason for revert:
Fixed the flake.
Original change's description:
> Revert "Added PeerConnectionObserver::OnRemoveTrack."
>
> This reverts commit ba97ba7af917d4152f5f3363aba1c1561c6673dc.
>
> Reason for revert: The new tests have caused several test failures on the test bots; the method FakeAudioMediaStreamTrack:GetSignalLevel, which is not supposed to be called is sometimes called anyway.
>
> Original change's description:
> > Added PeerConnectionObserver::OnRemoveTrack.
> >
> > This corresponds to processing the removal of a remote track step of
> > the spec, with processing the addition of a remote track already
> > covered by OnAddTrack.
> > https://w3c.github.io/webrtc-pc/#processing-remote-mediastreamtracks
> >
> > Bug: webrtc:8260, webrtc:8315
> > Change-Id: Ica8be92369733eb3cf1397fb60385d45a9b58700
> > Reviewed-on: https://webrtc-review.googlesource.com/4722
> > Commit-Queue: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#20214}
>
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,hbos@webrtc.org
>
> Change-Id: Id2d9533e27227254769b4280a8ff10a47313e714
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8260, webrtc:8315
> Reviewed-on: https://webrtc-review.googlesource.com/7940
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Alex Loiko <aleloi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#20218}
TBR=steveanton@webrtc.org,deadbeef@webrtc.org,aleloi@webrtc.org,hbos@webrtc.org
Change-Id: Iab7500bebf98535754b102874259de43831fff6b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8260, webrtc:8315
Reviewed-on: https://webrtc-review.googlesource.com/8180
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20227}
2017-10-10 10:05:16 -07:00
|
|
|
rtc::scoped_refptr<RtpReceiverInterface> receiver;
|
2015-10-14 11:33:11 -07:00
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
2016-03-24 03:16:19 -07:00
|
|
|
// When the MediaEngine audio channel is destroyed, the RemoteAudioSource
|
|
|
|
|
// will be notified which will end the AudioRtpReceiver::track().
|
2017-11-20 10:20:22 -08:00
|
|
|
receiver = RemoveAndStopReceiver(sender_info);
|
2015-10-14 11:33:11 -07:00
|
|
|
rtc::scoped_refptr<AudioTrackInterface> audio_track =
|
2017-11-20 10:20:22 -08:00
|
|
|
stream->FindAudioTrack(sender_info.sender_id);
|
2015-10-14 11:33:11 -07:00
|
|
|
if (audio_track) {
|
|
|
|
|
stream->RemoveTrack(audio_track);
|
|
|
|
|
}
|
|
|
|
|
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
2016-03-24 03:16:19 -07:00
|
|
|
// Stopping or destroying a VideoRtpReceiver will end the
|
|
|
|
|
// VideoRtpReceiver::track().
|
2017-11-20 10:20:22 -08:00
|
|
|
receiver = RemoveAndStopReceiver(sender_info);
|
2015-10-14 11:33:11 -07:00
|
|
|
rtc::scoped_refptr<VideoTrackInterface> video_track =
|
2017-11-20 10:20:22 -08:00
|
|
|
stream->FindVideoTrack(sender_info.sender_id);
|
2015-10-14 11:33:11 -07:00
|
|
|
if (video_track) {
|
2016-03-24 03:16:19 -07:00
|
|
|
// There's no guarantee the track is still available, e.g. the track may
|
|
|
|
|
// have been removed from the stream by an application.
|
2015-10-14 11:33:11 -07:00
|
|
|
stream->RemoveTrack(video_track);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2017-01-12 05:15:36 -08:00
|
|
|
RTC_NOTREACHED() << "Invalid media type";
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
Reland "Added PeerConnectionObserver::OnRemoveTrack."
This reverts commit 6c0c55c31817ecfa32409424495eb68b31828c40.
Reason for revert:
Fixed the flake.
Original change's description:
> Revert "Added PeerConnectionObserver::OnRemoveTrack."
>
> This reverts commit ba97ba7af917d4152f5f3363aba1c1561c6673dc.
>
> Reason for revert: The new tests have caused several test failures on the test bots; the method FakeAudioMediaStreamTrack:GetSignalLevel, which is not supposed to be called is sometimes called anyway.
>
> Original change's description:
> > Added PeerConnectionObserver::OnRemoveTrack.
> >
> > This corresponds to processing the removal of a remote track step of
> > the spec, with processing the addition of a remote track already
> > covered by OnAddTrack.
> > https://w3c.github.io/webrtc-pc/#processing-remote-mediastreamtracks
> >
> > Bug: webrtc:8260, webrtc:8315
> > Change-Id: Ica8be92369733eb3cf1397fb60385d45a9b58700
> > Reviewed-on: https://webrtc-review.googlesource.com/4722
> > Commit-Queue: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#20214}
>
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,hbos@webrtc.org
>
> Change-Id: Id2d9533e27227254769b4280a8ff10a47313e714
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8260, webrtc:8315
> Reviewed-on: https://webrtc-review.googlesource.com/7940
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Alex Loiko <aleloi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#20218}
TBR=steveanton@webrtc.org,deadbeef@webrtc.org,aleloi@webrtc.org,hbos@webrtc.org
Change-Id: Iab7500bebf98535754b102874259de43831fff6b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8260, webrtc:8315
Reviewed-on: https://webrtc-review.googlesource.com/8180
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20227}
2017-10-10 10:05:16 -07:00
|
|
|
if (receiver) {
|
2018-08-01 10:50:16 +02:00
|
|
|
Observer()->OnRemoveTrack(receiver);
|
Reland "Added PeerConnectionObserver::OnRemoveTrack."
This reverts commit 6c0c55c31817ecfa32409424495eb68b31828c40.
Reason for revert:
Fixed the flake.
Original change's description:
> Revert "Added PeerConnectionObserver::OnRemoveTrack."
>
> This reverts commit ba97ba7af917d4152f5f3363aba1c1561c6673dc.
>
> Reason for revert: The new tests have caused several test failures on the test bots; the method FakeAudioMediaStreamTrack:GetSignalLevel, which is not supposed to be called is sometimes called anyway.
>
> Original change's description:
> > Added PeerConnectionObserver::OnRemoveTrack.
> >
> > This corresponds to processing the removal of a remote track step of
> > the spec, with processing the addition of a remote track already
> > covered by OnAddTrack.
> > https://w3c.github.io/webrtc-pc/#processing-remote-mediastreamtracks
> >
> > Bug: webrtc:8260, webrtc:8315
> > Change-Id: Ica8be92369733eb3cf1397fb60385d45a9b58700
> > Reviewed-on: https://webrtc-review.googlesource.com/4722
> > Commit-Queue: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#20214}
>
> TBR=steveanton@webrtc.org,deadbeef@webrtc.org,hbos@webrtc.org
>
> Change-Id: Id2d9533e27227254769b4280a8ff10a47313e714
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:8260, webrtc:8315
> Reviewed-on: https://webrtc-review.googlesource.com/7940
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Alex Loiko <aleloi@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#20218}
TBR=steveanton@webrtc.org,deadbeef@webrtc.org,aleloi@webrtc.org,hbos@webrtc.org
Change-Id: Iab7500bebf98535754b102874259de43831fff6b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8260, webrtc:8315
Reviewed-on: https://webrtc-review.googlesource.com/8180
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20227}
2017-10-10 10:05:16 -07:00
|
|
|
}
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
void PeerConnection::OnLocalSenderAdded(const RtpSenderInfo& sender_info,
|
|
|
|
|
cricket::MediaType media_type) {
|
2020-10-01 16:47:23 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-04-02 16:31:36 -07:00
|
|
|
RTC_DCHECK(!IsUnifiedPlan());
|
2017-11-20 10:20:22 -08:00
|
|
|
auto sender = FindSenderById(sender_info.sender_id);
|
2015-11-25 11:26:01 -08:00
|
|
|
if (!sender) {
|
2017-11-20 10:20:22 -08:00
|
|
|
RTC_LOG(LS_WARNING) << "An unknown RtpSender with id "
|
|
|
|
|
<< sender_info.sender_id
|
2017-11-09 11:09:25 +01:00
|
|
|
<< " has been configured in the local description.";
|
2015-10-14 11:33:11 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-25 11:26:01 -08:00
|
|
|
if (sender->media_type() != media_type) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
|
2018-02-13 10:37:07 +01:00
|
|
|
" description with an unexpected media type.";
|
2015-11-25 11:26:01 -08:00
|
|
|
return;
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
2015-11-25 11:26:01 -08:00
|
|
|
|
2019-05-20 09:01:38 +00:00
|
|
|
sender->internal()->set_stream_ids({sender_info.stream_id});
|
2017-11-20 10:20:22 -08:00
|
|
|
sender->internal()->SetSsrc(sender_info.first_ssrc);
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
void PeerConnection::OnLocalSenderRemoved(const RtpSenderInfo& sender_info,
|
|
|
|
|
cricket::MediaType media_type) {
|
2020-10-01 16:47:23 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-20 10:20:22 -08:00
|
|
|
auto sender = FindSenderById(sender_info.sender_id);
|
2015-11-25 11:26:01 -08:00
|
|
|
if (!sender) {
|
|
|
|
|
// This is the normal case. I.e., RemoveStream has been called and the
|
2015-10-14 11:33:11 -07:00
|
|
|
// SessionDescriptions has been renegotiated.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-11-25 11:26:01 -08:00
|
|
|
|
|
|
|
|
// A sender has been removed from the SessionDescription but it's still
|
|
|
|
|
// associated with the PeerConnection. This only occurs if the SDP doesn't
|
|
|
|
|
// match with the calls to CreateSender, AddStream and RemoveStream.
|
|
|
|
|
if (sender->media_type() != media_type) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
|
2018-02-13 10:37:07 +01:00
|
|
|
" description with an unexpected media type.";
|
2015-11-25 11:26:01 -08:00
|
|
|
return;
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
2015-11-25 11:26:01 -08:00
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
sender->internal()->SetSsrc(0);
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2020-07-09 15:32:34 -07:00
|
|
|
void PeerConnection::OnSctpDataChannelClosed(DataChannelInterface* channel) {
|
2019-12-02 09:56:02 +01:00
|
|
|
// Since data_channel_controller doesn't do signals, this
|
|
|
|
|
// signal is relayed here.
|
2020-07-09 15:32:34 -07:00
|
|
|
data_channel_controller_.OnSctpDataChannelClosed(
|
|
|
|
|
static_cast<SctpDataChannel*>(channel));
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
|
|
|
|
PeerConnection::GetAudioTransceiver() const {
|
2020-10-01 10:23:33 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-20 10:20:22 -08:00
|
|
|
// This method only works with Plan B SDP, where there is a single
|
|
|
|
|
// audio/video transceiver.
|
|
|
|
|
RTC_DCHECK(!IsUnifiedPlan());
|
2020-09-29 11:54:05 +00:00
|
|
|
for (auto transceiver : transceivers_.List()) {
|
2018-02-09 11:43:08 -08:00
|
|
|
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
2017-11-20 10:20:22 -08:00
|
|
|
return transceiver;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
|
|
|
|
PeerConnection::GetVideoTransceiver() const {
|
2020-10-01 10:23:33 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-20 10:20:22 -08:00
|
|
|
// This method only works with Plan B SDP, where there is a single
|
|
|
|
|
// audio/video transceiver.
|
|
|
|
|
RTC_DCHECK(!IsUnifiedPlan());
|
2020-09-29 11:54:05 +00:00
|
|
|
for (auto transceiver : transceivers_.List()) {
|
2018-02-09 11:43:08 -08:00
|
|
|
if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
|
2017-11-20 10:20:22 -08:00
|
|
|
return transceiver;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
|
|
|
|
PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) const {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2017-11-20 10:20:22 -08:00
|
|
|
for (auto sender : transceiver->internal()->senders()) {
|
|
|
|
|
if (sender->track() == track) {
|
|
|
|
|
return sender;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2015-09-28 16:53:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
|
|
|
|
PeerConnection::FindSenderById(const std::string& sender_id) const {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2017-11-20 10:20:22 -08:00
|
|
|
for (auto sender : transceiver->internal()->senders()) {
|
|
|
|
|
if (sender->id() == sender_id) {
|
|
|
|
|
return sender;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2015-09-28 16:53:55 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
|
|
|
|
PeerConnection::FindReceiverById(const std::string& receiver_id) const {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2017-11-20 10:20:22 -08:00
|
|
|
for (auto receiver : transceiver->internal()->receivers()) {
|
|
|
|
|
if (receiver->id() == receiver_id) {
|
|
|
|
|
return receiver;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<PeerConnection::RtpSenderInfo>*
|
|
|
|
|
PeerConnection::GetRemoteSenderInfos(cricket::MediaType media_type) {
|
2015-10-14 11:33:11 -07:00
|
|
|
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
|
|
|
|
media_type == cricket::MEDIA_TYPE_VIDEO);
|
2017-11-20 10:20:22 -08:00
|
|
|
return (media_type == cricket::MEDIA_TYPE_AUDIO)
|
|
|
|
|
? &remote_audio_sender_infos_
|
|
|
|
|
: &remote_video_sender_infos_;
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
std::vector<PeerConnection::RtpSenderInfo>* PeerConnection::GetLocalSenderInfos(
|
2015-10-14 11:33:11 -07:00
|
|
|
cricket::MediaType media_type) {
|
|
|
|
|
RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
|
|
|
|
media_type == cricket::MEDIA_TYPE_VIDEO);
|
2017-11-20 10:20:22 -08:00
|
|
|
return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_sender_infos_
|
|
|
|
|
: &local_video_sender_infos_;
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-20 10:20:22 -08:00
|
|
|
const PeerConnection::RtpSenderInfo* PeerConnection::FindSenderInfo(
|
|
|
|
|
const std::vector<PeerConnection::RtpSenderInfo>& infos,
|
2018-03-27 21:57:18 +00:00
|
|
|
const std::string& stream_id,
|
2017-11-20 10:20:22 -08:00
|
|
|
const std::string sender_id) const {
|
|
|
|
|
for (const RtpSenderInfo& sender_info : infos) {
|
2018-03-27 21:57:18 +00:00
|
|
|
if (sender_info.stream_id == stream_id &&
|
|
|
|
|
sender_info.sender_id == sender_id) {
|
2017-11-20 10:20:22 -08:00
|
|
|
return &sender_info;
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-09 15:32:34 -07:00
|
|
|
SctpDataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
|
2019-12-03 14:04:21 +01:00
|
|
|
return data_channel_controller_.FindDataChannelBySid(sid);
|
2015-10-14 11:33:11 -07:00
|
|
|
}
|
|
|
|
|
|
2019-03-22 14:13:22 +01:00
|
|
|
PeerConnection::InitializePortAllocatorResult
|
|
|
|
|
PeerConnection::InitializePortAllocator_n(
|
2018-06-28 13:54:07 +02:00
|
|
|
const cricket::ServerAddresses& stun_servers,
|
|
|
|
|
const std::vector<cricket::RelayServerConfig>& turn_servers,
|
2016-05-13 08:15:11 -07:00
|
|
|
const RTCConfiguration& configuration) {
|
2019-03-22 14:13:22 +01:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread());
|
|
|
|
|
|
2016-06-27 17:20:15 -07:00
|
|
|
port_allocator_->Initialize();
|
2016-05-13 08:15:11 -07:00
|
|
|
// To handle both internal and externally created port allocator, we will
|
|
|
|
|
// enable BUNDLE here.
|
2019-03-22 14:13:22 +01:00
|
|
|
int port_allocator_flags = port_allocator_->flags();
|
|
|
|
|
port_allocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
|
|
|
|
|
cricket::PORTALLOCATOR_ENABLE_IPV6 |
|
|
|
|
|
cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
|
2016-05-13 08:15:11 -07:00
|
|
|
// If the disable-IPv6 flag was specified, we'll not override it
|
|
|
|
|
// by experiment.
|
|
|
|
|
if (configuration.disable_ipv6) {
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
|
2020-09-22 11:36:35 +02:00
|
|
|
} else if (absl::StartsWith(factory_->trials().Lookup("WebRTC-IPv6Default"),
|
|
|
|
|
"Disabled")) {
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
|
2016-05-13 08:15:11 -07:00
|
|
|
}
|
2017-03-07 14:40:51 -08:00
|
|
|
if (configuration.disable_ipv6_on_wifi) {
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI);
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "IPv6 candidates on Wi-Fi are disabled.";
|
2017-03-07 14:40:51 -08:00
|
|
|
}
|
|
|
|
|
|
2016-05-13 08:15:11 -07:00
|
|
|
if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "TCP candidates are disabled.";
|
2016-05-13 08:15:11 -07:00
|
|
|
}
|
|
|
|
|
|
2016-05-31 18:29:12 -07:00
|
|
|
if (configuration.candidate_network_policy ==
|
|
|
|
|
kCandidateNetworkPolicyLowCost) {
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Do not gather candidates on high-cost networks";
|
2016-05-31 18:29:12 -07:00
|
|
|
}
|
|
|
|
|
|
2018-01-25 10:30:22 +01:00
|
|
|
if (configuration.disable_link_local_networks) {
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS;
|
2018-01-25 10:30:22 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Disable candidates on link-local network interfaces.";
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-22 14:13:22 +01:00
|
|
|
port_allocator_->set_flags(port_allocator_flags);
|
2016-05-13 08:15:11 -07:00
|
|
|
// No step delay is used while allocating ports.
|
|
|
|
|
port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
|
2019-04-18 10:41:58 -07:00
|
|
|
port_allocator_->SetCandidateFilter(
|
2016-05-13 08:15:11 -07:00
|
|
|
ConvertIceTransportTypeToCandidateFilter(configuration.type));
|
2017-07-26 16:50:11 -07:00
|
|
|
port_allocator_->set_max_ipv6_networks(configuration.max_ipv6_networks);
|
2016-05-13 08:15:11 -07:00
|
|
|
|
2018-06-28 13:54:07 +02:00
|
|
|
auto turn_servers_copy = turn_servers;
|
2018-08-13 17:06:26 -07:00
|
|
|
for (auto& turn_server : turn_servers_copy) {
|
|
|
|
|
turn_server.tls_cert_verifier = tls_cert_verifier_.get();
|
2018-05-08 13:12:25 -07:00
|
|
|
}
|
2016-05-13 08:15:11 -07:00
|
|
|
// Call this last since it may create pooled allocator sessions using the
|
|
|
|
|
// properties set above.
|
2018-02-20 14:45:49 -08:00
|
|
|
port_allocator_->SetConfiguration(
|
2018-08-13 17:06:26 -07:00
|
|
|
stun_servers, std::move(turn_servers_copy),
|
2019-10-14 11:27:50 -07:00
|
|
|
configuration.ice_candidate_pool_size,
|
|
|
|
|
configuration.GetTurnPortPrunePolicy(), configuration.turn_customizer,
|
2018-02-20 14:45:49 -08:00
|
|
|
configuration.stun_candidate_keepalive_interval);
|
2019-03-22 14:13:22 +01:00
|
|
|
|
|
|
|
|
InitializePortAllocatorResult res;
|
|
|
|
|
res.enable_ipv6 = port_allocator_flags & cricket::PORTALLOCATOR_ENABLE_IPV6;
|
|
|
|
|
return res;
|
2016-05-13 08:15:11 -07:00
|
|
|
}
|
|
|
|
|
|
2016-05-18 16:55:30 -07:00
|
|
|
bool PeerConnection::ReconfigurePortAllocator_n(
|
2017-01-11 12:28:30 -08:00
|
|
|
const cricket::ServerAddresses& stun_servers,
|
|
|
|
|
const std::vector<cricket::RelayServerConfig>& turn_servers,
|
|
|
|
|
IceTransportsType type,
|
|
|
|
|
int candidate_pool_size,
|
2019-10-14 11:27:50 -07:00
|
|
|
PortPrunePolicy turn_port_prune_policy,
|
2018-02-20 14:45:49 -08:00
|
|
|
webrtc::TurnCustomizer* turn_customizer,
|
2019-04-03 11:37:28 +02:00
|
|
|
absl::optional<int> stun_candidate_keepalive_interval,
|
|
|
|
|
bool have_local_description) {
|
2019-04-18 10:41:58 -07:00
|
|
|
port_allocator_->SetCandidateFilter(
|
2017-01-11 12:28:30 -08:00
|
|
|
ConvertIceTransportTypeToCandidateFilter(type));
|
2018-04-11 16:57:45 -07:00
|
|
|
// According to JSEP, after setLocalDescription, changing the candidate pool
|
|
|
|
|
// size is not allowed, and changing the set of ICE servers will not result
|
|
|
|
|
// in new candidates being gathered.
|
2019-04-03 11:37:28 +02:00
|
|
|
if (have_local_description) {
|
2018-04-11 16:57:45 -07:00
|
|
|
port_allocator_->FreezeCandidatePool();
|
|
|
|
|
}
|
2018-08-13 17:06:26 -07:00
|
|
|
// Add the custom tls turn servers if they exist.
|
|
|
|
|
auto turn_servers_copy = turn_servers;
|
|
|
|
|
for (auto& turn_server : turn_servers_copy) {
|
|
|
|
|
turn_server.tls_cert_verifier = tls_cert_verifier_.get();
|
|
|
|
|
}
|
2016-05-13 08:15:11 -07:00
|
|
|
// Call this last since it may create pooled allocator sessions using the
|
|
|
|
|
// candidate filter set above.
|
2016-12-12 18:49:32 -08:00
|
|
|
return port_allocator_->SetConfiguration(
|
2018-08-13 17:06:26 -07:00
|
|
|
stun_servers, std::move(turn_servers_copy), candidate_pool_size,
|
2019-10-14 11:27:50 -07:00
|
|
|
turn_port_prune_policy, turn_customizer,
|
|
|
|
|
stun_candidate_keepalive_interval);
|
2016-05-13 08:15:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:21:57 -08:00
|
|
|
cricket::ChannelManager* PeerConnection::channel_manager() const {
|
|
|
|
|
return factory_->channel_manager();
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 16:29:40 +02:00
|
|
|
bool PeerConnection::StartRtcEventLog_w(
|
2017-11-20 17:38:14 +01:00
|
|
|
std::unique_ptr<RtcEventLogOutput> output,
|
|
|
|
|
int64_t output_period_ms) {
|
2019-02-14 11:59:57 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2017-02-07 15:45:16 -08:00
|
|
|
if (!event_log_) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-11-20 17:38:14 +01:00
|
|
|
return event_log_->StartLogging(std::move(output), output_period_ms);
|
2016-07-04 07:06:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::StopRtcEventLog_w() {
|
2019-02-14 11:59:57 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2017-02-07 15:45:16 -08:00
|
|
|
if (event_log_) {
|
|
|
|
|
event_log_->StopLogging();
|
|
|
|
|
}
|
2016-07-04 07:06:55 -07:00
|
|
|
}
|
2017-05-05 02:23:02 -07:00
|
|
|
|
2018-11-13 16:26:05 -08:00
|
|
|
cricket::ChannelInterface* PeerConnection::GetChannel(
|
2017-11-06 10:37:17 -08:00
|
|
|
const std::string& content_name) {
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2018-11-13 16:26:05 -08:00
|
|
|
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
2017-12-22 16:02:54 -08:00
|
|
|
if (channel && channel->content_name() == content_name) {
|
|
|
|
|
return channel;
|
|
|
|
|
}
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
if (rtp_data_channel() &&
|
|
|
|
|
rtp_data_channel()->content_name() == content_name) {
|
|
|
|
|
return rtp_data_channel();
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::GetSctpSslRole(rtc::SSLRole* role) {
|
2018-11-08 11:23:22 -08:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-06 10:37:17 -08:00
|
|
|
if (!local_description() || !remote_description()) {
|
2019-12-12 13:40:50 +01:00
|
|
|
RTC_LOG(LS_VERBOSE)
|
2017-11-09 11:09:25 +01:00
|
|
|
<< "Local and Remote descriptions must be applied to get the "
|
2018-02-13 10:37:07 +01:00
|
|
|
"SSL Role of the SCTP transport.";
|
2017-11-06 10:37:17 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-12-02 09:56:02 +01:00
|
|
|
if (!data_channel_controller_.data_channel_transport()) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO) << "Non-rejected SCTP m= section is needed to get the "
|
2018-02-13 10:37:07 +01:00
|
|
|
"SSL Role of the SCTP transport.";
|
2017-11-06 10:37:17 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-08 11:23:22 -08:00
|
|
|
absl::optional<rtc::SSLRole> dtls_role;
|
2020-02-12 07:38:21 +01:00
|
|
|
if (sctp_mid_s_) {
|
|
|
|
|
dtls_role = transport_controller_->GetDtlsRole(*sctp_mid_s_);
|
2020-09-28 13:02:07 +00:00
|
|
|
if (!dtls_role && sdp_handler_.is_caller().has_value()) {
|
|
|
|
|
dtls_role = *sdp_handler_.is_caller() ? rtc::SSL_SERVER : rtc::SSL_CLIENT;
|
2019-09-23 14:53:54 -07:00
|
|
|
}
|
2018-03-30 10:48:35 -07:00
|
|
|
*role = *dtls_role;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::GetSslRole(const std::string& content_name,
|
|
|
|
|
rtc::SSLRole* role) {
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2017-11-06 10:37:17 -08:00
|
|
|
if (!local_description() || !remote_description()) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_INFO)
|
|
|
|
|
<< "Local and Remote descriptions must be applied to get the "
|
2018-02-13 10:37:07 +01:00
|
|
|
"SSL Role of the session.";
|
2017-11-06 10:37:17 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-30 10:48:35 -07:00
|
|
|
auto dtls_role = transport_controller_->GetDtlsRole(content_name);
|
|
|
|
|
if (dtls_role) {
|
|
|
|
|
*role = *dtls_role;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::GetTransportDescription(
|
|
|
|
|
const SessionDescription* description,
|
|
|
|
|
const std::string& content_name,
|
|
|
|
|
cricket::TransportDescription* tdesc) {
|
|
|
|
|
if (!description || !tdesc) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const TransportInfo* transport_info =
|
|
|
|
|
description->GetTransportInfoByName(content_name);
|
|
|
|
|
if (!transport_info) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
*tdesc = transport_info->description;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cricket::IceConfig PeerConnection::ParseIceConfig(
|
|
|
|
|
const PeerConnectionInterface::RTCConfiguration& config) const {
|
|
|
|
|
cricket::ContinualGatheringPolicy gathering_policy;
|
|
|
|
|
switch (config.continual_gathering_policy) {
|
|
|
|
|
case PeerConnectionInterface::GATHER_ONCE:
|
|
|
|
|
gathering_policy = cricket::GATHER_ONCE;
|
|
|
|
|
break;
|
|
|
|
|
case PeerConnectionInterface::GATHER_CONTINUALLY:
|
|
|
|
|
gathering_policy = cricket::GATHER_CONTINUALLY;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
gathering_policy = cricket::GATHER_ONCE;
|
|
|
|
|
}
|
2018-02-01 10:38:40 -08:00
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
cricket::IceConfig ice_config;
|
2018-03-22 17:54:23 -07:00
|
|
|
ice_config.receiving_timeout = RTCConfigurationToIceConfigOptionalInt(
|
|
|
|
|
config.ice_connection_receiving_timeout);
|
2017-11-06 10:37:17 -08:00
|
|
|
ice_config.prioritize_most_likely_candidate_pairs =
|
|
|
|
|
config.prioritize_most_likely_ice_candidate_pairs;
|
|
|
|
|
ice_config.backup_connection_ping_interval =
|
2018-03-22 17:54:23 -07:00
|
|
|
RTCConfigurationToIceConfigOptionalInt(
|
|
|
|
|
config.ice_backup_candidate_pair_ping_interval);
|
2017-11-06 10:37:17 -08:00
|
|
|
ice_config.continual_gathering_policy = gathering_policy;
|
|
|
|
|
ice_config.presume_writable_when_fully_relayed =
|
|
|
|
|
config.presume_writable_when_fully_relayed;
|
2019-05-31 16:55:33 -07:00
|
|
|
ice_config.surface_ice_candidates_on_ice_transport_type_changed =
|
|
|
|
|
config.surface_ice_candidates_on_ice_transport_type_changed;
|
2018-03-08 14:55:14 -08:00
|
|
|
ice_config.ice_check_interval_strong_connectivity =
|
|
|
|
|
config.ice_check_interval_strong_connectivity;
|
|
|
|
|
ice_config.ice_check_interval_weak_connectivity =
|
|
|
|
|
config.ice_check_interval_weak_connectivity;
|
2017-11-06 10:37:17 -08:00
|
|
|
ice_config.ice_check_min_interval = config.ice_check_min_interval;
|
2018-11-29 23:08:51 -08:00
|
|
|
ice_config.ice_unwritable_timeout = config.ice_unwritable_timeout;
|
|
|
|
|
ice_config.ice_unwritable_min_checks = config.ice_unwritable_min_checks;
|
2018-12-06 23:30:17 -08:00
|
|
|
ice_config.ice_inactive_timeout = config.ice_inactive_timeout;
|
2018-02-20 14:45:49 -08:00
|
|
|
ice_config.stun_keepalive_interval = config.stun_candidate_keepalive_interval;
|
2018-02-01 10:38:40 -08:00
|
|
|
ice_config.network_preference = config.network_preference;
|
2017-11-06 10:37:17 -08:00
|
|
|
return ice_config;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-09 15:32:34 -07:00
|
|
|
std::vector<DataChannelStats> PeerConnection::GetDataChannelStats() const {
|
2020-06-16 16:54:10 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
return data_channel_controller_.GetDataChannelStats();
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<std::string> PeerConnection::sctp_transport_name() const {
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-02-12 07:38:21 +01:00
|
|
|
if (sctp_mid_s_ && transport_controller_) {
|
|
|
|
|
auto dtls_transport = transport_controller_->GetDtlsTransport(*sctp_mid_s_);
|
2018-03-30 10:48:35 -07:00
|
|
|
if (dtls_transport) {
|
|
|
|
|
return dtls_transport->transport_name();
|
|
|
|
|
}
|
2018-06-19 16:47:43 +02:00
|
|
|
return absl::optional<std::string>();
|
2018-03-30 10:48:35 -07:00
|
|
|
}
|
2018-06-19 16:47:43 +02:00
|
|
|
return absl::optional<std::string>();
|
2018-03-30 10:48:35 -07:00
|
|
|
}
|
|
|
|
|
|
2018-02-20 16:03:18 -08:00
|
|
|
cricket::CandidateStatsList PeerConnection::GetPooledCandidateStats() const {
|
|
|
|
|
cricket::CandidateStatsList candidate_states_list;
|
2018-04-11 16:57:45 -07:00
|
|
|
network_thread()->Invoke<void>(
|
|
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
rtc::Bind(&cricket::PortAllocator::GetCandidateStatsFromPooledSessions,
|
|
|
|
|
port_allocator_.get(), &candidate_states_list));
|
2018-02-20 16:03:18 -08:00
|
|
|
return candidate_states_list;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-06 10:34:40 -08:00
|
|
|
std::map<std::string, std::string> PeerConnection::GetTransportNamesByMid()
|
|
|
|
|
const {
|
2019-03-26 13:33:43 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-02-06 10:34:40 -08:00
|
|
|
std::map<std::string, std::string> transport_names_by_mid;
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2018-11-13 16:26:05 -08:00
|
|
|
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
2018-02-06 10:34:40 -08:00
|
|
|
if (channel) {
|
|
|
|
|
transport_names_by_mid[channel->content_name()] =
|
|
|
|
|
channel->transport_name();
|
|
|
|
|
}
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
2019-12-02 09:56:02 +01:00
|
|
|
if (data_channel_controller_.rtp_data_channel()) {
|
|
|
|
|
transport_names_by_mid[data_channel_controller_.rtp_data_channel()
|
|
|
|
|
->content_name()] =
|
|
|
|
|
data_channel_controller_.rtp_data_channel()->transport_name();
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
2019-12-02 09:56:02 +01:00
|
|
|
if (data_channel_controller_.data_channel_transport()) {
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<std::string> transport_name = sctp_transport_name();
|
2018-03-30 10:48:35 -07:00
|
|
|
RTC_DCHECK(transport_name);
|
2020-02-12 07:38:21 +01:00
|
|
|
transport_names_by_mid[*sctp_mid_s_] = *transport_name;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
2018-02-06 10:34:40 -08:00
|
|
|
return transport_names_by_mid;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2018-02-06 10:34:40 -08:00
|
|
|
std::map<std::string, cricket::TransportStats>
|
|
|
|
|
PeerConnection::GetTransportStatsByNames(
|
|
|
|
|
const std::set<std::string>& transport_names) {
|
|
|
|
|
if (!network_thread()->IsCurrent()) {
|
|
|
|
|
return network_thread()
|
|
|
|
|
->Invoke<std::map<std::string, cricket::TransportStats>>(
|
|
|
|
|
RTC_FROM_HERE,
|
|
|
|
|
[&] { return GetTransportStatsByNames(transport_names); });
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
2019-04-02 11:31:56 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread());
|
2018-02-06 10:34:40 -08:00
|
|
|
std::map<std::string, cricket::TransportStats> transport_stats_by_name;
|
|
|
|
|
for (const std::string& transport_name : transport_names) {
|
|
|
|
|
cricket::TransportStats transport_stats;
|
|
|
|
|
bool success =
|
|
|
|
|
transport_controller_->GetStats(transport_name, &transport_stats);
|
|
|
|
|
if (success) {
|
|
|
|
|
transport_stats_by_name[transport_name] = std::move(transport_stats);
|
|
|
|
|
} else {
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Failed to get transport stats for transport_name="
|
|
|
|
|
<< transport_name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return transport_stats_by_name;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::GetLocalCertificate(
|
|
|
|
|
const std::string& transport_name,
|
|
|
|
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
|
2018-03-30 10:48:35 -07:00
|
|
|
if (!certificate) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
*certificate = transport_controller_->GetLocalCertificate(transport_name);
|
|
|
|
|
return *certificate != nullptr;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2018-02-23 13:04:51 -08:00
|
|
|
std::unique_ptr<rtc::SSLCertChain> PeerConnection::GetRemoteSSLCertChain(
|
2017-11-06 10:37:17 -08:00
|
|
|
const std::string& transport_name) {
|
2018-02-23 13:04:51 -08:00
|
|
|
return transport_controller_->GetRemoteSSLCertChain(transport_name);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cricket::DataChannelType PeerConnection::data_channel_type() const {
|
2019-12-03 14:04:21 +01:00
|
|
|
return data_channel_controller_.data_channel_type();
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::IceRestartPending(const std::string& content_name) const {
|
2019-04-08 15:36:53 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.IceRestartPending(content_name);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::NeedsIceRestart(const std::string& content_name) const {
|
|
|
|
|
return transport_controller_->NeedsIceRestart(content_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::OnCertificateReady(
|
|
|
|
|
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
|
|
|
|
|
transport_controller_->SetLocalCertificate(certificate);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 16:18:59 +00:00
|
|
|
void PeerConnection::OnTransportControllerConnectionState(
|
|
|
|
|
cricket::IceConnectionState state) {
|
|
|
|
|
switch (state) {
|
|
|
|
|
case cricket::kIceConnectionConnecting:
|
|
|
|
|
// If the current state is Connected or Completed, then there were
|
|
|
|
|
// writable channels but now there are not, so the next state must
|
|
|
|
|
// be Disconnected.
|
|
|
|
|
// kIceConnectionConnecting is currently used as the default,
|
|
|
|
|
// un-connected state by the TransportController, so its only use is
|
|
|
|
|
// detecting disconnections.
|
|
|
|
|
if (ice_connection_state_ ==
|
|
|
|
|
PeerConnectionInterface::kIceConnectionConnected ||
|
|
|
|
|
ice_connection_state_ ==
|
|
|
|
|
PeerConnectionInterface::kIceConnectionCompleted) {
|
|
|
|
|
SetIceConnectionState(
|
|
|
|
|
PeerConnectionInterface::kIceConnectionDisconnected);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case cricket::kIceConnectionFailed:
|
|
|
|
|
SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
|
|
|
|
|
break;
|
|
|
|
|
case cricket::kIceConnectionConnected:
|
|
|
|
|
RTC_LOG(LS_INFO) << "Changing to ICE connected state because "
|
|
|
|
|
"all transports are writable.";
|
|
|
|
|
SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
|
|
|
|
|
NoteUsageEvent(UsageEvent::ICE_STATE_CONNECTED);
|
|
|
|
|
break;
|
|
|
|
|
case cricket::kIceConnectionCompleted:
|
|
|
|
|
RTC_LOG(LS_INFO) << "Changing to ICE completed state because "
|
|
|
|
|
"all transports are complete.";
|
|
|
|
|
if (ice_connection_state_ !=
|
|
|
|
|
PeerConnectionInterface::kIceConnectionConnected) {
|
|
|
|
|
// If jumping directly from "checking" to "connected",
|
|
|
|
|
// signal "connected" first.
|
|
|
|
|
SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
|
|
|
|
|
}
|
|
|
|
|
SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
|
|
|
|
|
NoteUsageEvent(UsageEvent::ICE_STATE_CONNECTED);
|
|
|
|
|
ReportTransportStats();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
void PeerConnection::OnTransportControllerCandidatesGathered(
|
|
|
|
|
const std::string& transport_name,
|
|
|
|
|
const cricket::Candidates& candidates) {
|
|
|
|
|
int sdp_mline_index;
|
|
|
|
|
if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR)
|
|
|
|
|
<< "OnTransportControllerCandidatesGathered: content name "
|
|
|
|
|
<< transport_name << " not found";
|
2017-11-06 10:37:17 -08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (cricket::Candidates::const_iterator citer = candidates.begin();
|
|
|
|
|
citer != candidates.end(); ++citer) {
|
|
|
|
|
// Use transport_name as the candidate media id.
|
|
|
|
|
std::unique_ptr<JsepIceCandidate> candidate(
|
|
|
|
|
new JsepIceCandidate(transport_name, sdp_mline_index, *citer));
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.AddLocalIceCandidate(candidate.get());
|
2017-11-06 10:37:17 -08:00
|
|
|
OnIceCandidate(std::move(candidate));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-01 12:23:43 +03:00
|
|
|
void PeerConnection::OnTransportControllerCandidateError(
|
|
|
|
|
const cricket::IceCandidateErrorEvent& event) {
|
2019-12-02 22:22:07 +02:00
|
|
|
OnIceCandidateError(event.address, event.port, event.url, event.error_code,
|
2019-06-01 12:23:43 +03:00
|
|
|
event.error_text);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
void PeerConnection::OnTransportControllerCandidatesRemoved(
|
|
|
|
|
const std::vector<cricket::Candidate>& candidates) {
|
|
|
|
|
// Sanity check.
|
|
|
|
|
for (const cricket::Candidate& candidate : candidates) {
|
|
|
|
|
if (candidate.transport_name().empty()) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_ERROR) << "OnTransportControllerCandidatesRemoved: "
|
2018-02-13 10:37:07 +01:00
|
|
|
"empty content name in candidate "
|
2017-11-09 11:09:25 +01:00
|
|
|
<< candidate.ToString();
|
2017-11-06 10:37:17 -08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.RemoveLocalIceCandidates(candidates);
|
2017-11-06 10:37:17 -08:00
|
|
|
OnIceCandidatesRemoved(candidates);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-06 10:54:47 -07:00
|
|
|
void PeerConnection::OnTransportControllerCandidateChanged(
|
|
|
|
|
const cricket::CandidatePairChangeEvent& event) {
|
|
|
|
|
OnSelectedCandidatePairChanged(event);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
void PeerConnection::OnTransportControllerDtlsHandshakeError(
|
|
|
|
|
rtc::SSLHandshakeError error) {
|
2018-07-12 12:54:53 -07:00
|
|
|
RTC_HISTOGRAM_ENUMERATION(
|
|
|
|
|
"WebRTC.PeerConnection.DtlsHandshakeError", static_cast<int>(error),
|
|
|
|
|
static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the media index for a local ice candidate given the content name.
|
|
|
|
|
bool PeerConnection::GetLocalCandidateMediaIndex(
|
|
|
|
|
const std::string& content_name,
|
|
|
|
|
int* sdp_mline_index) {
|
|
|
|
|
if (!local_description() || !sdp_mline_index) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool content_found = false;
|
|
|
|
|
const ContentInfos& contents = local_description()->description()->contents();
|
|
|
|
|
for (size_t index = 0; index < contents.size(); ++index) {
|
|
|
|
|
if (contents[index].name == content_name) {
|
|
|
|
|
*sdp_mline_index = static_cast<int>(index);
|
|
|
|
|
content_found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return content_found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Call::Stats PeerConnection::GetCallStats() {
|
|
|
|
|
if (!worker_thread()->IsCurrent()) {
|
|
|
|
|
return worker_thread()->Invoke<Call::Stats>(
|
|
|
|
|
RTC_FROM_HERE, rtc::Bind(&PeerConnection::GetCallStats, this));
|
|
|
|
|
}
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
2017-11-06 10:37:17 -08:00
|
|
|
if (call_) {
|
|
|
|
|
return call_->GetStats();
|
|
|
|
|
} else {
|
|
|
|
|
return Call::Stats();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
bool PeerConnection::SetupDataChannelTransport_n(const std::string& mid) {
|
2019-09-23 14:53:54 -07:00
|
|
|
DataChannelTransportInterface* transport =
|
|
|
|
|
transport_controller_->GetDataChannelTransport(mid);
|
|
|
|
|
if (!transport) {
|
Add x-mt line to the offer.
We already support decoding of the x-mt line. This change adds the
a=x-mt line to the SDP offer. This is not a backward compatible change
for media transport (because of the changes in pre-shared key handling)
1) if media transport is enabled, and SDES is enabled, generate the
media transport offer.
2) if media transport generated the offer, add that offer to the x-mt
line.
3) in order to create media transport, require an x-mt line (backward incompatible).
The way it works is that
1) PeerConnection, on the offerer, asks jsep transport for the
configuration of the media transport.
2) Tentative media transport is created in JsepTransportController when
that happens.
3) SessionDescription will include configuration from this tentative
media transport.
4) When the LocalDescription is set on the offerer, the tentative media
transport is promoted to the real media transport.
Caveats:
- now we really only support MaxBundle. In the previous implementations,
two media transports were briefly created in some tests, and the second
one was destroyed shortly after instantiation.
- we, for now, enforce SDES. In the future, whether SDES is used will be
refactored out of the peer connection.
In the future (on the callee) we should ignore 'is_media_transport' setting. If
Offer contains x-mt, media transport should be used (if the factory is
present). However, we need to decide how to negotiate media transport
for data channels vs data transport for media (x-mt line at this point
doesn't differentiate the two, so we still need to use app setting).
This change also removes the negotation of pre-shared key from the
a=crypto line. Instead, media transport will have its own, 256bit key.
Such key should be transported in the x-mt line. This makes the code
much simpler, and simplifies the dependency / a=crypto lines parsing.
Also, adds a proper test for the connection re-offer (on both sides: callee and caller).
Before, it was possible that media transport could get recreated, based on the offer.
The tests we had didn't test this scenario, and the loopback media factory didn't allow for such test.
This change adds counts to that loopback media factory, and asserts that only 1 media transport is created, even
when there is a re-offer.
Bug: webrtc:9719
Change-Id: Ibd8739af90e914da40ab412454bba8e1529f5a01
Reviewed-on: https://webrtc-review.googlesource.com/c/125040
Reviewed-by: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Peter Slatala <psla@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26933}
2019-03-01 11:14:05 -08:00
|
|
|
RTC_LOG(LS_ERROR)
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
<< "Data channel transport is not available for data channels, mid="
|
|
|
|
|
<< mid;
|
2018-11-08 11:23:22 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Setting up data channel transport for mid=" << mid;
|
2018-11-08 11:23:22 -08:00
|
|
|
|
2019-12-02 09:56:02 +01:00
|
|
|
data_channel_controller_.set_data_channel_transport(transport);
|
|
|
|
|
data_channel_controller_.SetupDataChannelTransport_n();
|
2020-02-12 07:38:21 +01:00
|
|
|
sctp_mid_n_ = mid;
|
2019-09-23 14:53:54 -07:00
|
|
|
|
|
|
|
|
// Note: setting the data sink and checking initial state must be done last,
|
|
|
|
|
// after setting up the data channel. Setting the data sink may trigger
|
|
|
|
|
// callbacks to PeerConnection which require the transport to be completely
|
|
|
|
|
// set up (eg. OnReadyToSend()).
|
2019-12-02 09:56:02 +01:00
|
|
|
transport->SetDataSink(&data_channel_controller_);
|
2018-11-08 11:23:22 -08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
void PeerConnection::TeardownDataChannelTransport_n() {
|
2020-02-12 07:38:21 +01:00
|
|
|
if (!sctp_mid_n_ && !data_channel_controller_.data_channel_transport()) {
|
2018-11-08 11:23:22 -08:00
|
|
|
return;
|
|
|
|
|
}
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
RTC_LOG(LS_INFO) << "Tearing down data channel transport for mid="
|
2020-02-12 07:38:21 +01:00
|
|
|
<< *sctp_mid_n_;
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
|
|
|
|
|
// |sctp_mid_| may still be active through an SCTP transport. If not, unset
|
|
|
|
|
// it.
|
2020-02-12 07:38:21 +01:00
|
|
|
sctp_mid_n_.reset();
|
2019-12-02 09:56:02 +01:00
|
|
|
data_channel_controller_.TeardownDataChannelTransport_n();
|
2018-11-08 11:23:22 -08:00
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
// Returns false if bundle is enabled and rtcp_mux is disabled.
|
|
|
|
|
bool PeerConnection::ValidateBundleSettings(const SessionDescription* desc) {
|
|
|
|
|
bool bundle_enabled = desc->HasGroup(cricket::GROUP_TYPE_BUNDLE);
|
|
|
|
|
if (!bundle_enabled)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
const cricket::ContentGroup* bundle_group =
|
|
|
|
|
desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
|
|
|
|
|
RTC_DCHECK(bundle_group != NULL);
|
|
|
|
|
|
|
|
|
|
const cricket::ContentInfos& contents = desc->contents();
|
|
|
|
|
for (cricket::ContentInfos::const_iterator citer = contents.begin();
|
|
|
|
|
citer != contents.end(); ++citer) {
|
|
|
|
|
const cricket::ContentInfo* content = (&*citer);
|
|
|
|
|
RTC_DCHECK(content != NULL);
|
|
|
|
|
if (bundle_group->HasContentName(content->name) && !content->rejected &&
|
2017-12-20 16:34:00 -08:00
|
|
|
content->type == MediaProtocolType::kRtp) {
|
2017-11-06 10:37:17 -08:00
|
|
|
if (!HasRtcpMuxEnabled(content))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// RTCP-MUX is enabled in all the contents.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PeerConnection::HasRtcpMuxEnabled(const cricket::ContentInfo* content) {
|
2017-12-21 15:14:30 -08:00
|
|
|
return content->media_description()->rtcp_mux();
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2018-03-06 10:55:04 -08:00
|
|
|
void PeerConnection::ReportSdpFormatReceived(
|
|
|
|
|
const SessionDescriptionInterface& remote_offer) {
|
|
|
|
|
int num_audio_mlines = 0;
|
|
|
|
|
int num_video_mlines = 0;
|
|
|
|
|
int num_audio_tracks = 0;
|
|
|
|
|
int num_video_tracks = 0;
|
|
|
|
|
for (const ContentInfo& content : remote_offer.description()->contents()) {
|
|
|
|
|
cricket::MediaType media_type = content.media_description()->type();
|
|
|
|
|
int num_tracks = std::max(
|
|
|
|
|
1, static_cast<int>(content.media_description()->streams().size()));
|
|
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
num_audio_mlines += 1;
|
|
|
|
|
num_audio_tracks += num_tracks;
|
|
|
|
|
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
|
|
|
|
num_video_mlines += 1;
|
|
|
|
|
num_video_tracks += num_tracks;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SdpFormatReceived format = kSdpFormatReceivedNoTracks;
|
|
|
|
|
if (num_audio_mlines > 1 || num_video_mlines > 1) {
|
|
|
|
|
format = kSdpFormatReceivedComplexUnifiedPlan;
|
|
|
|
|
} else if (num_audio_tracks > 1 || num_video_tracks > 1) {
|
|
|
|
|
format = kSdpFormatReceivedComplexPlanB;
|
|
|
|
|
} else if (num_audio_tracks > 0 || num_video_tracks > 0) {
|
|
|
|
|
format = kSdpFormatReceivedSimple;
|
|
|
|
|
}
|
2020-10-07 12:47:10 +02:00
|
|
|
switch (remote_offer.GetType()) {
|
|
|
|
|
case SdpType::kOffer:
|
|
|
|
|
// Historically only offers were counted.
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SdpFormatReceived",
|
|
|
|
|
format, kSdpFormatReceivedMax);
|
|
|
|
|
break;
|
|
|
|
|
case SdpType::kAnswer:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SdpFormatReceivedAnswer",
|
|
|
|
|
format, kSdpFormatReceivedMax);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Can not report SdpFormatReceived for "
|
|
|
|
|
<< SdpTypeToString(remote_offer.GetType());
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-03-06 10:55:04 -08:00
|
|
|
}
|
|
|
|
|
|
2019-08-19 11:57:17 -07:00
|
|
|
void PeerConnection::ReportIceCandidateCollected(
|
|
|
|
|
const cricket::Candidate& candidate) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::CANDIDATE_COLLECTED);
|
|
|
|
|
if (candidate.address().IsPrivateIP()) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::PRIVATE_CANDIDATE_COLLECTED);
|
|
|
|
|
}
|
|
|
|
|
if (candidate.address().IsUnresolvedIP()) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::MDNS_CANDIDATE_COLLECTED);
|
|
|
|
|
}
|
|
|
|
|
if (candidate.address().family() == AF_INET6) {
|
|
|
|
|
NoteUsageEvent(UsageEvent::IPV6_CANDIDATE_COLLECTED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-31 14:00:34 +02:00
|
|
|
void PeerConnection::NoteUsageEvent(UsageEvent event) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-10-09 05:43:53 +00:00
|
|
|
usage_pattern_.NoteUsageEvent(event);
|
2018-05-31 14:00:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::ReportUsagePattern() const {
|
2020-10-09 05:43:53 +00:00
|
|
|
usage_pattern_.ReportUsagePattern(observer_);
|
2018-05-31 14:00:34 +02:00
|
|
|
}
|
|
|
|
|
|
2017-11-06 10:37:17 -08:00
|
|
|
bool PeerConnection::SrtpRequired() const {
|
2020-06-16 16:39:13 +02:00
|
|
|
return (dtls_enabled_ ||
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.webrtc_session_desc_factory()->SdesPolicy() ==
|
|
|
|
|
cricket::SEC_REQUIRED);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::OnTransportControllerGatheringState(
|
|
|
|
|
cricket::IceGatheringState state) {
|
|
|
|
|
RTC_DCHECK(signaling_thread()->IsCurrent());
|
|
|
|
|
if (state == cricket::kIceGatheringGathering) {
|
|
|
|
|
OnIceGatheringChange(PeerConnectionInterface::kIceGatheringGathering);
|
|
|
|
|
} else if (state == cricket::kIceGatheringComplete) {
|
|
|
|
|
OnIceGatheringChange(PeerConnectionInterface::kIceGatheringComplete);
|
2020-08-20 14:50:10 +02:00
|
|
|
} else if (state == cricket::kIceGatheringNew) {
|
|
|
|
|
OnIceGatheringChange(PeerConnectionInterface::kIceGatheringNew);
|
|
|
|
|
} else {
|
|
|
|
|
RTC_LOG(LS_ERROR) << "Unknown state received: " << state;
|
|
|
|
|
RTC_NOTREACHED();
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::ReportTransportStats() {
|
2018-02-01 14:39:45 -08:00
|
|
|
std::map<std::string, std::set<cricket::MediaType>>
|
|
|
|
|
media_types_by_transport_name;
|
2020-09-29 11:54:05 +00:00
|
|
|
for (const auto& transceiver : transceivers_.List()) {
|
2018-02-01 14:39:45 -08:00
|
|
|
if (transceiver->internal()->channel()) {
|
|
|
|
|
const std::string& transport_name =
|
|
|
|
|
transceiver->internal()->channel()->transport_name();
|
|
|
|
|
media_types_by_transport_name[transport_name].insert(
|
2018-02-09 11:43:08 -08:00
|
|
|
transceiver->media_type());
|
2018-02-01 14:39:45 -08:00
|
|
|
}
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
if (rtp_data_channel()) {
|
2018-02-01 14:39:45 -08:00
|
|
|
media_types_by_transport_name[rtp_data_channel()->transport_name()].insert(
|
|
|
|
|
cricket::MEDIA_TYPE_DATA);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
2018-03-30 10:48:35 -07:00
|
|
|
|
2018-06-19 16:47:43 +02:00
|
|
|
absl::optional<std::string> transport_name = sctp_transport_name();
|
2018-03-30 10:48:35 -07:00
|
|
|
if (transport_name) {
|
|
|
|
|
media_types_by_transport_name[*transport_name].insert(
|
2018-02-01 14:39:45 -08:00
|
|
|
cricket::MEDIA_TYPE_DATA);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
2018-03-30 10:48:35 -07:00
|
|
|
|
2018-02-01 14:39:45 -08:00
|
|
|
for (const auto& entry : media_types_by_transport_name) {
|
|
|
|
|
const std::string& transport_name = entry.first;
|
|
|
|
|
const std::set<cricket::MediaType> media_types = entry.second;
|
2017-11-06 10:37:17 -08:00
|
|
|
cricket::TransportStats stats;
|
2018-02-01 14:39:45 -08:00
|
|
|
if (transport_controller_->GetStats(transport_name, &stats)) {
|
2017-11-06 10:37:17 -08:00
|
|
|
ReportBestConnectionState(stats);
|
2018-02-01 14:39:45 -08:00
|
|
|
ReportNegotiatedCiphers(stats, media_types);
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Walk through the ConnectionInfos to gather best connection usage
|
|
|
|
|
// for IPv4 and IPv6.
|
|
|
|
|
void PeerConnection::ReportBestConnectionState(
|
|
|
|
|
const cricket::TransportStats& stats) {
|
2018-02-01 14:39:45 -08:00
|
|
|
for (const cricket::TransportChannelStats& channel_stats :
|
|
|
|
|
stats.channel_stats) {
|
|
|
|
|
for (const cricket::ConnectionInfo& connection_info :
|
2019-08-28 08:10:27 +02:00
|
|
|
channel_stats.ice_transport_stats.connection_infos) {
|
2018-02-01 14:39:45 -08:00
|
|
|
if (!connection_info.best_connection) {
|
2017-11-06 10:37:17 -08:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-01 14:39:45 -08:00
|
|
|
const cricket::Candidate& local = connection_info.local_candidate;
|
|
|
|
|
const cricket::Candidate& remote = connection_info.remote_candidate;
|
2017-11-06 10:37:17 -08:00
|
|
|
|
|
|
|
|
// Increment the counter for IceCandidatePairType.
|
|
|
|
|
if (local.protocol() == cricket::TCP_PROTOCOL_NAME ||
|
|
|
|
|
(local.type() == RELAY_PORT_TYPE &&
|
|
|
|
|
local.relay_protocol() == cricket::TCP_PROTOCOL_NAME)) {
|
2018-07-12 12:54:53 -07:00
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_TCP",
|
|
|
|
|
GetIceCandidatePairCounter(local, remote),
|
|
|
|
|
kIceCandidatePairMax);
|
2017-11-06 10:37:17 -08:00
|
|
|
} else if (local.protocol() == cricket::UDP_PROTOCOL_NAME) {
|
2018-07-12 12:54:53 -07:00
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_UDP",
|
|
|
|
|
GetIceCandidatePairCounter(local, remote),
|
|
|
|
|
kIceCandidatePairMax);
|
2017-11-06 10:37:17 -08:00
|
|
|
} else {
|
|
|
|
|
RTC_CHECK(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Increment the counter for IP type.
|
|
|
|
|
if (local.address().family() == AF_INET) {
|
2018-07-12 12:54:53 -07:00
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
|
|
|
|
|
kBestConnections_IPv4,
|
|
|
|
|
kPeerConnectionAddressFamilyCounter_Max);
|
2017-11-06 10:37:17 -08:00
|
|
|
} else if (local.address().family() == AF_INET6) {
|
2018-07-12 12:54:53 -07:00
|
|
|
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
|
|
|
|
|
kBestConnections_IPv6,
|
|
|
|
|
kPeerConnectionAddressFamilyCounter_Max);
|
2017-11-06 10:37:17 -08:00
|
|
|
} else {
|
2018-12-12 15:28:47 -08:00
|
|
|
RTC_CHECK(!local.address().hostname().empty() &&
|
|
|
|
|
local.address().IsUnresolvedIP());
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::ReportNegotiatedCiphers(
|
2018-02-01 14:39:45 -08:00
|
|
|
const cricket::TransportStats& stats,
|
|
|
|
|
const std::set<cricket::MediaType>& media_types) {
|
2017-11-06 10:37:17 -08:00
|
|
|
if (!dtls_enabled_ || stats.channel_stats.empty()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int srtp_crypto_suite = stats.channel_stats[0].srtp_crypto_suite;
|
|
|
|
|
int ssl_cipher_suite = stats.channel_stats[0].ssl_cipher_suite;
|
|
|
|
|
if (srtp_crypto_suite == rtc::SRTP_INVALID_CRYPTO_SUITE &&
|
|
|
|
|
ssl_cipher_suite == rtc::TLS_NULL_WITH_NULL_NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-12 12:54:53 -07:00
|
|
|
if (srtp_crypto_suite != rtc::SRTP_INVALID_CRYPTO_SUITE) {
|
|
|
|
|
for (cricket::MediaType media_type : media_types) {
|
|
|
|
|
switch (media_type) {
|
|
|
|
|
case cricket::MEDIA_TYPE_AUDIO:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
|
|
|
|
"WebRTC.PeerConnection.SrtpCryptoSuite.Audio", srtp_crypto_suite,
|
|
|
|
|
rtc::SRTP_CRYPTO_SUITE_MAX_VALUE);
|
|
|
|
|
break;
|
|
|
|
|
case cricket::MEDIA_TYPE_VIDEO:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
|
|
|
|
"WebRTC.PeerConnection.SrtpCryptoSuite.Video", srtp_crypto_suite,
|
|
|
|
|
rtc::SRTP_CRYPTO_SUITE_MAX_VALUE);
|
|
|
|
|
break;
|
|
|
|
|
case cricket::MEDIA_TYPE_DATA:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
|
|
|
|
"WebRTC.PeerConnection.SrtpCryptoSuite.Data", srtp_crypto_suite,
|
|
|
|
|
rtc::SRTP_CRYPTO_SUITE_MAX_VALUE);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-07-11 18:33:52 +00:00
|
|
|
}
|
2018-07-12 12:54:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ssl_cipher_suite != rtc::TLS_NULL_WITH_NULL_NULL) {
|
|
|
|
|
for (cricket::MediaType media_type : media_types) {
|
|
|
|
|
switch (media_type) {
|
|
|
|
|
case cricket::MEDIA_TYPE_AUDIO:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
|
|
|
|
"WebRTC.PeerConnection.SslCipherSuite.Audio", ssl_cipher_suite,
|
|
|
|
|
rtc::SSL_CIPHER_SUITE_MAX_VALUE);
|
|
|
|
|
break;
|
|
|
|
|
case cricket::MEDIA_TYPE_VIDEO:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
|
|
|
|
"WebRTC.PeerConnection.SslCipherSuite.Video", ssl_cipher_suite,
|
|
|
|
|
rtc::SSL_CIPHER_SUITE_MAX_VALUE);
|
|
|
|
|
break;
|
|
|
|
|
case cricket::MEDIA_TYPE_DATA:
|
|
|
|
|
RTC_HISTOGRAM_ENUMERATION_SPARSE(
|
|
|
|
|
"WebRTC.PeerConnection.SslCipherSuite.Data", ssl_cipher_suite,
|
|
|
|
|
rtc::SSL_CIPHER_SUITE_MAX_VALUE);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-02-01 14:39:45 -08:00
|
|
|
}
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnection::OnSentPacket_w(const rtc::SentPacket& sent_packet) {
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
2017-11-06 10:37:17 -08:00
|
|
|
RTC_DCHECK(call_);
|
|
|
|
|
call_->OnSentPacket(sent_packet);
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-16 16:42:14 -07:00
|
|
|
bool PeerConnection::OnTransportChanged(
|
2018-03-30 10:48:35 -07:00
|
|
|
const std::string& mid,
|
2018-04-16 16:42:14 -07:00
|
|
|
RtpTransportInternal* rtp_transport,
|
2019-02-28 07:51:00 +01:00
|
|
|
rtc::scoped_refptr<DtlsTransport> dtls_transport,
|
2019-09-23 14:53:54 -07:00
|
|
|
DataChannelTransportInterface* data_channel_transport) {
|
2019-03-26 13:08:37 +01:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread());
|
2018-04-16 16:42:14 -07:00
|
|
|
bool ret = true;
|
2018-03-30 10:48:35 -07:00
|
|
|
auto base_channel = GetChannel(mid);
|
|
|
|
|
if (base_channel) {
|
2018-04-16 16:42:14 -07:00
|
|
|
ret = base_channel->SetRtpTransport(rtp_transport);
|
2018-03-30 10:48:35 -07:00
|
|
|
}
|
2020-02-12 07:38:21 +01:00
|
|
|
if (mid == sctp_mid_n_) {
|
2019-12-02 09:56:02 +01:00
|
|
|
data_channel_controller_.OnTransportChanged(data_channel_transport);
|
Changes to enable use of DatagramTransport as a data channel transport.
PeerConnection now has a new setting in RTCConfiguration to enable use of
datagram transport for data channels. There is also a corresponding field
trial, which has both a kill-switch and a way to change the default value.
PeerConnection's interaction with MediaTransport for data channels has been
refactored to work with DataChannelTransportInterface instead.
Adds a DataChannelState and OnStateChanged() to the DataChannelSink
callbacks. This allows PeerConnection to listen to the data channel's
state directly, instead of indirectly by monitoring media transport
state. This is necessary to enable use of non-media-transport (eg.
datagram transport) data channel transports.
For now, PeerConnection watches the state through MediaTransport as well.
This will persist until MediaTransport implements the new callback.
Datagram transport use is negotiated. As such, an offer that requests to use
datagram transport for data channels may be rejected by the answerer. If the
offer includes DTLS, the data channels will be negotiated as SCTP/DTLS data
channels with an extra x-opaque parameter for datagram transport. If the
opaque parameter is rejected (by an answerer without datagram support), the
offerer may fall back to SCTP.
If DTLS is not enabled, there is no viable fallback. In this case, the data
channels are negotiated as media transport data channels. If the receiver does
not understand the x-opaque line, it will reject these data channels, and the
offerer's data channels will be closed.
Bug: webrtc:9719
Change-Id: Ic1bf3664c4bcf9d754482df59897f5f72fe68fcc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147702
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28932}
2019-08-21 10:44:59 -07:00
|
|
|
}
|
2018-04-16 16:42:14 -07:00
|
|
|
return ret;
|
2017-11-06 10:37:17 -08:00
|
|
|
}
|
|
|
|
|
|
2019-05-20 19:31:53 +02:00
|
|
|
void PeerConnection::OnSetStreams() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
if (IsUnifiedPlan())
|
2020-09-28 13:02:07 +00:00
|
|
|
sdp_handler_.UpdateNegotiationNeeded();
|
2019-05-20 19:31:53 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-01 10:50:16 +02:00
|
|
|
PeerConnectionObserver* PeerConnection::Observer() const {
|
2019-12-03 14:04:21 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
RTC_DCHECK(observer_);
|
2018-08-01 10:50:16 +02:00
|
|
|
return observer_;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-25 10:16:44 -07:00
|
|
|
CryptoOptions PeerConnection::GetCryptoOptions() {
|
2020-10-01 10:23:33 +00:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-10-25 10:16:44 -07:00
|
|
|
// TODO(bugs.webrtc.org/9891) - Remove PeerConnectionFactory::CryptoOptions
|
|
|
|
|
// after it has been removed.
|
|
|
|
|
return configuration_.crypto_options.has_value()
|
|
|
|
|
? *configuration_.crypto_options
|
|
|
|
|
: factory_->options().crypto_options;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-02 14:08:34 +01:00
|
|
|
void PeerConnection::ClearStatsCache() {
|
2019-03-26 09:57:01 +01:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2018-01-02 14:08:34 +01:00
|
|
|
if (stats_collector_) {
|
|
|
|
|
stats_collector_->ClearCachedStatsReport();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-25 10:20:11 +02:00
|
|
|
bool PeerConnection::ShouldFireNegotiationNeededEvent(uint32_t event_id) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
2020-09-28 13:02:07 +00:00
|
|
|
return sdp_handler_.ShouldFireNegotiationNeededEvent(event_id);
|
2019-10-09 18:29:44 +03:00
|
|
|
}
|
|
|
|
|
|
2020-10-05 07:01:09 +00:00
|
|
|
void PeerConnection::RequestUsagePatternReportForTesting() {
|
|
|
|
|
message_handler_.RequestUsagePatternReport(
|
|
|
|
|
[this]() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
ReportUsagePattern();
|
|
|
|
|
},
|
|
|
|
|
/* delay_ms= */ 0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 10:39:31 +02:00
|
|
|
std::function<void(const rtc::CopyOnWriteBuffer& packet,
|
|
|
|
|
int64_t packet_time_us)>
|
|
|
|
|
PeerConnection::InitializeRtcpCallback() {
|
|
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
|
|
|
|
|
|
|
|
auto flag =
|
|
|
|
|
worker_thread()->Invoke<rtc::scoped_refptr<PendingTaskSafetyFlag>>(
|
|
|
|
|
RTC_FROM_HERE, [this] {
|
|
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
|
|
|
|
if (!call_)
|
|
|
|
|
return rtc::scoped_refptr<PendingTaskSafetyFlag>();
|
|
|
|
|
if (!call_safety_)
|
|
|
|
|
call_safety_.reset(new ScopedTaskSafety());
|
|
|
|
|
return call_safety_->flag();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!flag)
|
|
|
|
|
return [](const rtc::CopyOnWriteBuffer&, int64_t) {};
|
|
|
|
|
|
|
|
|
|
return [this, flag = std::move(flag)](const rtc::CopyOnWriteBuffer& packet,
|
|
|
|
|
int64_t packet_time_us) {
|
|
|
|
|
RTC_DCHECK_RUN_ON(network_thread());
|
|
|
|
|
// TODO(bugs.webrtc.org/11993): We should actually be delivering this call
|
|
|
|
|
// directly to the Call class somehow directly on the network thread and not
|
|
|
|
|
// incur this hop here. The DeliverPacket() method will eventually just have
|
|
|
|
|
// to hop back over to the network thread.
|
|
|
|
|
worker_thread()->PostTask(ToQueuedTask(flag, [this, packet,
|
|
|
|
|
packet_time_us] {
|
|
|
|
|
RTC_DCHECK_RUN_ON(worker_thread());
|
|
|
|
|
call_->Receiver()->DeliverPacket(MediaType::ANY, packet, packet_time_us);
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
}
|
2020-09-28 13:02:07 +00:00
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
} // namespace webrtc
|