blob: f914fc8365e4d5ddefff902f68f7a07bd103a1f6 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:361/*
kjellanderb24317b2016-02-10 15:54:432 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:363 *
kjellanderb24317b2016-02-10 15:54:434 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:369 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "pc/peer_connection.h"
henrike@webrtc.org28e20752013-07-10 00:45:3612
Harald Alvestrand1f7eab62020-10-18 16:51:4713#include <limits.h>
14#include <stddef.h>
Harald Alvestrand0ccfbd22021-04-08 07:25:0415
deadbeefeb459812015-12-16 03:24:4316#include <algorithm>
Harald Alvestrande15fb152020-10-19 13:28:0517#include <memory>
Harald Alvestrande15fb152020-10-19 13:28:0518#include <set>
Harald Alvestrand0d4af122022-01-31 09:36:0519#include <string>
Harald Alvestrand3eaee6b2020-10-19 06:35:5520#include <utility>
henrike@webrtc.org28e20752013-07-10 00:45:3621
Steve Anton64b626b2019-01-29 01:25:2622#include "absl/algorithm/container.h"
Fredrik Solenberg41f3a432018-12-17 20:02:2223#include "absl/strings/match.h"
Harald Alvestrand0d4af122022-01-31 09:36:0524#include "absl/strings/string_view.h"
Steve Anton10542f22019-01-11 17:11:0025#include "api/jsep_ice_candidate.h"
Harald Alvestrand763f5a92020-10-22 10:39:4026#include "api/rtp_parameters.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4727#include "api/rtp_transceiver_direction.h"
Steve Anton10542f22019-01-11 17:11:0028#include "api/uma_metrics.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4729#include "api/video/video_codec_constants.h"
30#include "call/audio_state.h"
31#include "call/packet_receiver.h"
Harald Alvestrand763f5a92020-10-22 10:39:4032#include "media/base/media_channel.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4733#include "media/base/media_config.h"
Harald Alvestrand0d4af122022-01-31 09:36:0534#include "media/base/media_engine.h"
Amit Hilbuchf4770402019-04-08 21:11:5735#include "media/base/rid_description.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4736#include "media/base/stream_params.h"
37#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Harald Alvestrand0ccfbd22021-04-08 07:25:0438#include "p2p/base/basic_async_resolver_factory.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4739#include "p2p/base/connection.h"
40#include "p2p/base/connection_info.h"
41#include "p2p/base/dtls_transport_internal.h"
42#include "p2p/base/p2p_constants.h"
43#include "p2p/base/p2p_transport_channel.h"
44#include "p2p/base/transport_info.h"
Harald Alvestrand9e334b72022-05-04 13:38:3145#include "pc/channel_manager.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4746#include "pc/ice_server_parsing.h"
Harald Alvestrand763f5a92020-10-22 10:39:4047#include "pc/rtp_receiver.h"
Harald Alvestrand0d4af122022-01-31 09:36:0548#include "pc/rtp_receiver_proxy.h"
Harald Alvestrand763f5a92020-10-22 10:39:4049#include "pc/rtp_sender.h"
Harald Alvestrand0d4af122022-01-31 09:36:0550#include "pc/rtp_sender_proxy.h"
Harald Alvestrandc85328f2019-02-28 06:51:0051#include "pc/sctp_transport.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4752#include "pc/simulcast_description.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4753#include "pc/webrtc_session_description_factory.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4754#include "rtc_base/helpers.h"
55#include "rtc_base/ip_address.h"
56#include "rtc_base/location.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3157#include "rtc_base/logging.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4758#include "rtc_base/net_helper.h"
Harald Alvestrand0d4af122022-01-31 09:36:0559#include "rtc_base/network.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4760#include "rtc_base/network_constants.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0861#include "rtc_base/ref_counted_object.h"
Harald Alvestrand1f7eab62020-10-18 16:51:4762#include "rtc_base/socket_address.h"
Steve Anton10542f22019-01-11 17:11:0063#include "rtc_base/string_encode.h"
Tomas Gunnarsson1e40a0c2020-09-28 08:39:3164#include "rtc_base/task_utils/to_queued_task.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3165#include "rtc_base/trace_event.h"
Harald Alvestrand763f5a92020-10-22 10:39:4066#include "rtc_base/unique_id_generator.h"
Qingsi Wang7fc821d2018-07-12 19:54:5367#include "system_wrappers/include/metrics.h"
henrike@webrtc.org28e20752013-07-10 00:45:3668
Steve Anton75737c02017-11-06 18:37:1769using cricket::ContentInfo;
70using cricket::ContentInfos;
71using cricket::MediaContentDescription;
Steve Anton5adfafd2017-12-21 00:34:0072using cricket::MediaProtocolType;
Amit Hilbuchbcd39d42019-01-26 01:13:5673using cricket::RidDescription;
74using cricket::RidDirection;
Amit Hilbuchc63ddb22019-01-02 18:13:5875using cricket::SessionDescription;
Amit Hilbuchbcd39d42019-01-26 01:13:5676using cricket::SimulcastDescription;
77using cricket::SimulcastLayer;
Amit Hilbuchc63ddb22019-01-02 18:13:5878using cricket::SimulcastLayerList;
Amit Hilbuchbcd39d42019-01-26 01:13:5679using cricket::StreamParams;
Steve Anton75737c02017-11-06 18:37:1780using cricket::TransportInfo;
81
82using cricket::LOCAL_PORT_TYPE;
Steve Anton75737c02017-11-06 18:37:1783using cricket::PRFLX_PORT_TYPE;
Jeroen de Borstaf242c82019-04-24 20:13:4884using cricket::RELAY_PORT_TYPE;
85using cricket::STUN_PORT_TYPE;
Steve Anton75737c02017-11-06 18:37:1786
Steve Antonba818672017-11-06 18:21:5787namespace webrtc {
88
Steve Anton75737c02017-11-06 18:37:1789namespace {
henrike@webrtc.org28e20752013-07-10 00:45:3690
Amit Hilbuche2a284d2019-03-05 20:36:3191// UMA metric names.
Amit Hilbuche2a284d2019-03-05 20:36:3192const char kSimulcastNumberOfEncodings[] =
93 "WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings";
Amit Hilbuche2a284d2019-03-05 20:36:3194
Harald Alvestrand19793842018-06-25 10:03:5095static const int REPORT_USAGE_PATTERN_DELAY_MS = 60000;
96
Taylor Brandstettera1c30352016-05-13 15:15:1197uint32_t ConvertIceTransportTypeToCandidateFilter(
98 PeerConnectionInterface::IceTransportsType type) {
99 switch (type) {
100 case PeerConnectionInterface::kNone:
101 return cricket::CF_NONE;
102 case PeerConnectionInterface::kRelay:
103 return cricket::CF_RELAY;
104 case PeerConnectionInterface::kNoHost:
105 return (cricket::CF_ALL & ~cricket::CF_HOST);
106 case PeerConnectionInterface::kAll:
107 return cricket::CF_ALL;
108 default:
Artem Titovd3251962021-11-15 15:57:07109 RTC_DCHECK_NOTREACHED();
Taylor Brandstettera1c30352016-05-13 15:15:11110 }
111 return cricket::CF_NONE;
112}
113
Steve Anton75737c02017-11-06 18:37:17114IceCandidatePairType GetIceCandidatePairCounter(
115 const cricket::Candidate& local,
116 const cricket::Candidate& remote) {
117 const auto& l = local.type();
118 const auto& r = remote.type();
119 const auto& host = LOCAL_PORT_TYPE;
120 const auto& srflx = STUN_PORT_TYPE;
121 const auto& relay = RELAY_PORT_TYPE;
122 const auto& prflx = PRFLX_PORT_TYPE;
123 if (l == host && r == host) {
Jeroen de Borst833979f2018-12-13 16:25:54124 bool local_hostname =
125 !local.address().hostname().empty() && local.address().IsUnresolvedIP();
126 bool remote_hostname = !remote.address().hostname().empty() &&
127 remote.address().IsUnresolvedIP();
Steve Anton75737c02017-11-06 18:37:17128 bool local_private = IPIsPrivate(local.address().ipaddr());
129 bool remote_private = IPIsPrivate(remote.address().ipaddr());
Jeroen de Borst833979f2018-12-13 16:25:54130 if (local_hostname) {
131 if (remote_hostname) {
132 return kIceCandidatePairHostNameHostName;
133 } else if (remote_private) {
134 return kIceCandidatePairHostNameHostPrivate;
135 } else {
136 return kIceCandidatePairHostNameHostPublic;
137 }
138 } else if (local_private) {
139 if (remote_hostname) {
140 return kIceCandidatePairHostPrivateHostName;
141 } else if (remote_private) {
Steve Anton75737c02017-11-06 18:37:17142 return kIceCandidatePairHostPrivateHostPrivate;
143 } else {
144 return kIceCandidatePairHostPrivateHostPublic;
145 }
146 } else {
Jeroen de Borst833979f2018-12-13 16:25:54147 if (remote_hostname) {
148 return kIceCandidatePairHostPublicHostName;
149 } else if (remote_private) {
Steve Anton75737c02017-11-06 18:37:17150 return kIceCandidatePairHostPublicHostPrivate;
151 } else {
152 return kIceCandidatePairHostPublicHostPublic;
153 }
154 }
155 }
156 if (l == host && r == srflx)
157 return kIceCandidatePairHostSrflx;
158 if (l == host && r == relay)
159 return kIceCandidatePairHostRelay;
160 if (l == host && r == prflx)
161 return kIceCandidatePairHostPrflx;
162 if (l == srflx && r == host)
163 return kIceCandidatePairSrflxHost;
164 if (l == srflx && r == srflx)
165 return kIceCandidatePairSrflxSrflx;
166 if (l == srflx && r == relay)
167 return kIceCandidatePairSrflxRelay;
168 if (l == srflx && r == prflx)
169 return kIceCandidatePairSrflxPrflx;
170 if (l == relay && r == host)
171 return kIceCandidatePairRelayHost;
172 if (l == relay && r == srflx)
173 return kIceCandidatePairRelaySrflx;
174 if (l == relay && r == relay)
175 return kIceCandidatePairRelayRelay;
176 if (l == relay && r == prflx)
177 return kIceCandidatePairRelayPrflx;
178 if (l == prflx && r == host)
179 return kIceCandidatePairPrflxHost;
180 if (l == prflx && r == srflx)
181 return kIceCandidatePairPrflxSrflx;
182 if (l == prflx && r == relay)
183 return kIceCandidatePairPrflxRelay;
184 return kIceCandidatePairMax;
185}
186
Danil Chapovalov66cadcc2018-06-19 14:47:43187absl::optional<int> RTCConfigurationToIceConfigOptionalInt(
Qingsi Wang866e08d2018-03-23 00:54:23188 int rtc_configuration_parameter) {
189 if (rtc_configuration_parameter ==
190 webrtc::PeerConnectionInterface::RTCConfiguration::kUndefined) {
Danil Chapovalov66cadcc2018-06-19 14:47:43191 return absl::nullopt;
Qingsi Wang866e08d2018-03-23 00:54:23192 }
193 return rtc_configuration_parameter;
194}
195
Jonas Orelande3096512020-05-27 07:01:05196// Check if the changes of IceTransportsType motives an ice restart.
197bool NeedIceRestart(bool surface_ice_candidates_on_ice_transport_type_changed,
198 PeerConnectionInterface::IceTransportsType current,
199 PeerConnectionInterface::IceTransportsType modified) {
200 if (current == modified) {
201 return false;
202 }
203
204 if (!surface_ice_candidates_on_ice_transport_type_changed) {
205 return true;
206 }
207
208 auto current_filter = ConvertIceTransportTypeToCandidateFilter(current);
209 auto modified_filter = ConvertIceTransportTypeToCandidateFilter(modified);
210
211 // If surface_ice_candidates_on_ice_transport_type_changed is true and we
212 // extend the filter, then no ice restart is needed.
213 return (current_filter & modified_filter) != current_filter;
214}
215
Harald Alvestrand62166932020-10-26 08:30:41216cricket::IceConfig ParseIceConfig(
217 const PeerConnectionInterface::RTCConfiguration& config) {
218 cricket::ContinualGatheringPolicy gathering_policy;
219 switch (config.continual_gathering_policy) {
220 case PeerConnectionInterface::GATHER_ONCE:
221 gathering_policy = cricket::GATHER_ONCE;
222 break;
223 case PeerConnectionInterface::GATHER_CONTINUALLY:
224 gathering_policy = cricket::GATHER_CONTINUALLY;
225 break;
226 default:
Artem Titovd3251962021-11-15 15:57:07227 RTC_DCHECK_NOTREACHED();
Harald Alvestrand62166932020-10-26 08:30:41228 gathering_policy = cricket::GATHER_ONCE;
229 }
230
231 cricket::IceConfig ice_config;
232 ice_config.receiving_timeout = RTCConfigurationToIceConfigOptionalInt(
233 config.ice_connection_receiving_timeout);
234 ice_config.prioritize_most_likely_candidate_pairs =
235 config.prioritize_most_likely_ice_candidate_pairs;
236 ice_config.backup_connection_ping_interval =
237 RTCConfigurationToIceConfigOptionalInt(
238 config.ice_backup_candidate_pair_ping_interval);
239 ice_config.continual_gathering_policy = gathering_policy;
240 ice_config.presume_writable_when_fully_relayed =
241 config.presume_writable_when_fully_relayed;
242 ice_config.surface_ice_candidates_on_ice_transport_type_changed =
243 config.surface_ice_candidates_on_ice_transport_type_changed;
244 ice_config.ice_check_interval_strong_connectivity =
245 config.ice_check_interval_strong_connectivity;
246 ice_config.ice_check_interval_weak_connectivity =
247 config.ice_check_interval_weak_connectivity;
248 ice_config.ice_check_min_interval = config.ice_check_min_interval;
249 ice_config.ice_unwritable_timeout = config.ice_unwritable_timeout;
250 ice_config.ice_unwritable_min_checks = config.ice_unwritable_min_checks;
251 ice_config.ice_inactive_timeout = config.ice_inactive_timeout;
252 ice_config.stun_keepalive_interval = config.stun_candidate_keepalive_interval;
253 ice_config.network_preference = config.network_preference;
Derek Bailey6c127a12021-04-15 19:42:41254 ice_config.stable_writable_connection_ping_interval =
255 config.stable_writable_connection_ping_interval_ms;
Harald Alvestrand62166932020-10-26 08:30:41256 return ice_config;
257}
258
259// Ensures the configuration doesn't have any parameters with invalid values,
260// or values that conflict with other parameters.
261//
262// Returns RTCError::OK() if there are no issues.
263RTCError ValidateConfiguration(
264 const PeerConnectionInterface::RTCConfiguration& config) {
265 return cricket::P2PTransportChannel::ValidateIceConfig(
266 ParseIceConfig(config));
267}
268
269bool HasRtcpMuxEnabled(const cricket::ContentInfo* content) {
270 return content->media_description()->rtcp_mux();
271}
272
Tommic3257d02021-02-10 17:40:08273bool DtlsEnabled(const PeerConnectionInterface::RTCConfiguration& configuration,
274 const PeerConnectionFactoryInterface::Options& options,
275 const PeerConnectionDependencies& dependencies) {
276 if (options.disable_encryption)
277 return false;
278
279 // Enable DTLS by default if we have an identity store or a certificate.
280 bool default_enabled =
281 (dependencies.cert_generator || !configuration.certificates.empty());
282
Harald Alvestrandca327932022-04-04 15:37:31283#if defined(WEBRTC_FUCHSIA)
Harald Alvestrand50b95522021-11-18 10:01:06284 // The `configuration` can override the default value.
285 return configuration.enable_dtls_srtp.value_or(default_enabled);
Harald Alvestrandca327932022-04-04 15:37:31286#else
287 return default_enabled;
288#endif
Tommic3257d02021-02-10 17:40:08289}
290
Steve Anton75737c02017-11-06 18:37:17291} // namespace
292
deadbeef293e9262017-01-11 20:28:30293bool PeerConnectionInterface::RTCConfiguration::operator==(
294 const PeerConnectionInterface::RTCConfiguration& o) const {
295 // This static_assert prevents us from accidentally breaking operator==.
Steve Anton300bf8e2017-07-14 17:13:10296 // Note: Order matters! Fields must be ordered the same as RTCConfiguration.
deadbeef293e9262017-01-11 20:28:30297 struct stuff_being_tested_for_equality {
Magnus Jedvert3beb2072017-07-14 14:23:56298 IceServers servers;
Steve Anton300bf8e2017-07-14 17:13:10299 IceTransportsType type;
deadbeef293e9262017-01-11 20:28:30300 BundlePolicy bundle_policy;
301 RtcpMuxPolicy rtcp_mux_policy;
Steve Anton300bf8e2017-07-14 17:13:10302 std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
303 int ice_candidate_pool_size;
304 bool disable_ipv6;
305 bool disable_ipv6_on_wifi;
deadbeefd21eab3e2017-07-26 23:50:11306 int max_ipv6_networks;
Daniel Lazarenko2870b0a2018-01-25 09:30:22307 bool disable_link_local_networks;
Danil Chapovalov66cadcc2018-06-19 14:47:43308 absl::optional<int> screencast_min_bitrate;
309 absl::optional<bool> combined_audio_video_bwe;
Harald Alvestrandca327932022-04-04 15:37:31310#if defined(WEBRTC_FUCHSIA)
Harald Alvestrand50b95522021-11-18 10:01:06311 absl::optional<bool> enable_dtls_srtp;
Harald Alvestrandca327932022-04-04 15:37:31312#endif
deadbeef293e9262017-01-11 20:28:30313 TcpCandidatePolicy tcp_candidate_policy;
314 CandidateNetworkPolicy candidate_network_policy;
315 int audio_jitter_buffer_max_packets;
316 bool audio_jitter_buffer_fast_accelerate;
Jakob Ivarsson10403ae2018-11-27 14:45:20317 int audio_jitter_buffer_min_delay_ms;
Jakob Ivarsson53eae872019-01-10 14:58:36318 bool audio_jitter_buffer_enable_rtx_handling;
deadbeef293e9262017-01-11 20:28:30319 int ice_connection_receiving_timeout;
320 int ice_backup_candidate_pair_ping_interval;
321 ContinualGatheringPolicy continual_gathering_policy;
deadbeef293e9262017-01-11 20:28:30322 bool prioritize_most_likely_ice_candidate_pairs;
323 struct cricket::MediaConfig media_config;
deadbeef293e9262017-01-11 20:28:30324 bool prune_turn_ports;
Honghai Zhangf8998cf2019-10-14 18:27:50325 PortPrunePolicy turn_port_prune_policy;
deadbeef293e9262017-01-11 20:28:30326 bool presume_writable_when_fully_relayed;
327 bool enable_ice_renomination;
328 bool redetermine_role_on_ice_restart;
Qingsi Wang1fe119f2019-05-31 23:55:33329 bool surface_ice_candidates_on_ice_transport_type_changed;
Danil Chapovalov66cadcc2018-06-19 14:47:43330 absl::optional<int> ice_check_interval_strong_connectivity;
331 absl::optional<int> ice_check_interval_weak_connectivity;
332 absl::optional<int> ice_check_min_interval;
333 absl::optional<int> ice_unwritable_timeout;
334 absl::optional<int> ice_unwritable_min_checks;
Jiawei Ou9d4fd5552018-12-07 07:30:17335 absl::optional<int> ice_inactive_timeout;
Danil Chapovalov66cadcc2018-06-19 14:47:43336 absl::optional<int> stun_candidate_keepalive_interval;
Jonas Orelandbdcee282017-10-10 12:01:40337 webrtc::TurnCustomizer* turn_customizer;
Steve Anton79e79602017-11-20 18:25:56338 SdpSemantics sdp_semantics;
Danil Chapovalov66cadcc2018-06-19 14:47:43339 absl::optional<rtc::AdapterType> network_preference;
Zhi Huangb57e1692018-06-12 18:41:11340 bool active_reset_srtp_params;
Benjamin Wright8c27cca2018-10-25 17:16:44341 absl::optional<CryptoOptions> crypto_options;
Johannes Kron89f874e2018-11-12 09:25:48342 bool offer_extmap_allow_mixed;
Jonas Oreland3c028422019-08-22 14:16:35343 std::string turn_logging_id;
Eldar Rello5ab79e62019-10-09 15:29:44344 bool enable_implicit_rollback;
philipel16cec3b2019-10-25 10:23:02345 absl::optional<bool> allow_codec_switching;
Harald Alvestrand62166932020-10-26 08:30:41346 absl::optional<int> report_usage_pattern_delay_ms;
Derek Bailey6c127a12021-04-15 19:42:41347 absl::optional<int> stable_writable_connection_ping_interval_ms;
Jonas Orelandc8fa1ee2021-08-25 06:58:04348 webrtc::VpnPreference vpn_preference;
Jonas Oreland2ee0e642021-08-25 13:43:02349 std::vector<rtc::NetworkMask> vpn_list;
Niels Möller73d07742021-12-02 12:58:01350 PortAllocatorConfig port_allocator_config;
deadbeef293e9262017-01-11 20:28:30351 };
352 static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this),
353 "Did you add something to RTCConfiguration and forget to "
354 "update operator==?");
355 return type == o.type && servers == o.servers &&
356 bundle_policy == o.bundle_policy &&
357 rtcp_mux_policy == o.rtcp_mux_policy &&
358 tcp_candidate_policy == o.tcp_candidate_policy &&
359 candidate_network_policy == o.candidate_network_policy &&
360 audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets &&
361 audio_jitter_buffer_fast_accelerate ==
362 o.audio_jitter_buffer_fast_accelerate &&
Jakob Ivarsson10403ae2018-11-27 14:45:20363 audio_jitter_buffer_min_delay_ms ==
364 o.audio_jitter_buffer_min_delay_ms &&
Jakob Ivarsson53eae872019-01-10 14:58:36365 audio_jitter_buffer_enable_rtx_handling ==
366 o.audio_jitter_buffer_enable_rtx_handling &&
deadbeef293e9262017-01-11 20:28:30367 ice_connection_receiving_timeout ==
368 o.ice_connection_receiving_timeout &&
369 ice_backup_candidate_pair_ping_interval ==
370 o.ice_backup_candidate_pair_ping_interval &&
371 continual_gathering_policy == o.continual_gathering_policy &&
372 certificates == o.certificates &&
373 prioritize_most_likely_ice_candidate_pairs ==
374 o.prioritize_most_likely_ice_candidate_pairs &&
375 media_config == o.media_config && disable_ipv6 == o.disable_ipv6 &&
zhihuangb09b3f92017-03-07 22:40:51376 disable_ipv6_on_wifi == o.disable_ipv6_on_wifi &&
deadbeefd21eab3e2017-07-26 23:50:11377 max_ipv6_networks == o.max_ipv6_networks &&
Daniel Lazarenko2870b0a2018-01-25 09:30:22378 disable_link_local_networks == o.disable_link_local_networks &&
deadbeef293e9262017-01-11 20:28:30379 screencast_min_bitrate == o.screencast_min_bitrate &&
380 combined_audio_video_bwe == o.combined_audio_video_bwe &&
Harald Alvestrandca327932022-04-04 15:37:31381#if defined(WEBRTC_FUCHSIA)
Harald Alvestrand50b95522021-11-18 10:01:06382 enable_dtls_srtp == o.enable_dtls_srtp &&
Harald Alvestrandca327932022-04-04 15:37:31383#endif
deadbeef293e9262017-01-11 20:28:30384 ice_candidate_pool_size == o.ice_candidate_pool_size &&
385 prune_turn_ports == o.prune_turn_ports &&
Honghai Zhangf8998cf2019-10-14 18:27:50386 turn_port_prune_policy == o.turn_port_prune_policy &&
deadbeef293e9262017-01-11 20:28:30387 presume_writable_when_fully_relayed ==
388 o.presume_writable_when_fully_relayed &&
389 enable_ice_renomination == o.enable_ice_renomination &&
skvlad51072462017-02-02 19:50:14390 redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart &&
Qingsi Wang1fe119f2019-05-31 23:55:33391 surface_ice_candidates_on_ice_transport_type_changed ==
392 o.surface_ice_candidates_on_ice_transport_type_changed &&
Qingsi Wange6826d22018-03-08 22:55:14393 ice_check_interval_strong_connectivity ==
394 o.ice_check_interval_strong_connectivity &&
395 ice_check_interval_weak_connectivity ==
396 o.ice_check_interval_weak_connectivity &&
Steve Anton300bf8e2017-07-14 17:13:10397 ice_check_min_interval == o.ice_check_min_interval &&
Qingsi Wang22e623a2018-03-13 17:53:57398 ice_unwritable_timeout == o.ice_unwritable_timeout &&
399 ice_unwritable_min_checks == o.ice_unwritable_min_checks &&
Jiawei Ou9d4fd5552018-12-07 07:30:17400 ice_inactive_timeout == o.ice_inactive_timeout &&
Qingsi Wangdb53f8e2018-02-20 22:45:49401 stun_candidate_keepalive_interval ==
402 o.stun_candidate_keepalive_interval &&
Steve Anton79e79602017-11-20 18:25:56403 turn_customizer == o.turn_customizer &&
Qingsi Wang9a5c6f82018-02-01 18:38:40404 sdp_semantics == o.sdp_semantics &&
Zhi Huangb57e1692018-06-12 18:41:11405 network_preference == o.network_preference &&
Piotr (Peter) Slatalae0c2e972018-10-08 16:43:21406 active_reset_srtp_params == o.active_reset_srtp_params &&
Johannes Kron89f874e2018-11-12 09:25:48407 crypto_options == o.crypto_options &&
Jonas Oreland3c028422019-08-22 14:16:35408 offer_extmap_allow_mixed == o.offer_extmap_allow_mixed &&
Eldar Rello5ab79e62019-10-09 15:29:44409 turn_logging_id == o.turn_logging_id &&
philipel16cec3b2019-10-25 10:23:02410 enable_implicit_rollback == o.enable_implicit_rollback &&
Harald Alvestrand62166932020-10-26 08:30:41411 allow_codec_switching == o.allow_codec_switching &&
Derek Bailey6c127a12021-04-15 19:42:41412 report_usage_pattern_delay_ms == o.report_usage_pattern_delay_ms &&
413 stable_writable_connection_ping_interval_ms ==
Jonas Orelandc8fa1ee2021-08-25 06:58:04414 o.stable_writable_connection_ping_interval_ms &&
Niels Möller73d07742021-12-02 12:58:01415 vpn_preference == o.vpn_preference && vpn_list == o.vpn_list &&
416 port_allocator_config.min_port == o.port_allocator_config.min_port &&
417 port_allocator_config.max_port == o.port_allocator_config.max_port &&
418 port_allocator_config.flags == o.port_allocator_config.flags;
deadbeef293e9262017-01-11 20:28:30419}
420
421bool PeerConnectionInterface::RTCConfiguration::operator!=(
422 const PeerConnectionInterface::RTCConfiguration& o) const {
423 return !(*this == o);
deadbeef3edec7c2016-12-10 19:44:26424}
425
Harald Alvestranda3dd7722020-11-27 08:05:42426RTCErrorOr<rtc::scoped_refptr<PeerConnection>> PeerConnection::Create(
Harald Alvestrand62166932020-10-26 08:30:41427 rtc::scoped_refptr<ConnectionContext> context,
Harald Alvestrand4da4a872020-11-04 10:34:21428 const PeerConnectionFactoryInterface::Options& options,
Harald Alvestrand62166932020-10-26 08:30:41429 std::unique_ptr<RtcEventLog> event_log,
430 std::unique_ptr<Call> call,
431 const PeerConnectionInterface::RTCConfiguration& configuration,
432 PeerConnectionDependencies dependencies) {
Henrik Boström62995db2022-01-03 08:58:10433 // TODO(https://crbug.com/webrtc/13528): Remove support for kPlanB.
Henrik Boström6d2fe892022-01-21 08:51:07434 if (configuration.sdp_semantics == SdpSemantics::kPlanB_DEPRECATED) {
435 RTC_LOG(LS_WARNING)
436 << "PeerConnection constructed with legacy SDP semantics!";
437 }
Henrik Boström62995db2022-01-03 08:58:10438
Harald Alvestrand62166932020-10-26 08:30:41439 RTCError config_error = cricket::P2PTransportChannel::ValidateIceConfig(
440 ParseIceConfig(configuration));
441 if (!config_error.ok()) {
Harald Alvestranda3dd7722020-11-27 08:05:42442 RTC_LOG(LS_ERROR) << "Invalid ICE configuration: "
443 << config_error.message();
444 return config_error;
Harald Alvestrand62166932020-10-26 08:30:41445 }
446
447 if (!dependencies.allocator) {
448 RTC_LOG(LS_ERROR)
449 << "PeerConnection initialized without a PortAllocator? "
450 "This shouldn't happen if using PeerConnectionFactory.";
Harald Alvestranda3dd7722020-11-27 08:05:42451 return RTCError(
452 RTCErrorType::INVALID_PARAMETER,
453 "Attempt to create a PeerConnection without a PortAllocatorFactory");
Harald Alvestrand62166932020-10-26 08:30:41454 }
455
456 if (!dependencies.observer) {
457 // TODO(deadbeef): Why do we do this?
458 RTC_LOG(LS_ERROR) << "PeerConnection initialized without a "
459 "PeerConnectionObserver";
Harald Alvestranda3dd7722020-11-27 08:05:42460 return RTCError(RTCErrorType::INVALID_PARAMETER,
461 "Attempt to create a PeerConnection without an observer");
Harald Alvestrand62166932020-10-26 08:30:41462 }
463
464 bool is_unified_plan =
465 configuration.sdp_semantics == SdpSemantics::kUnifiedPlan;
Tommic3257d02021-02-10 17:40:08466 bool dtls_enabled = DtlsEnabled(configuration, options, dependencies);
Harald Alvestrand0ccfbd22021-04-08 07:25:04467
468 // Interim code: If an AsyncResolverFactory is given, but not an
469 // AsyncDnsResolverFactory, wrap it in a WrappingAsyncDnsResolverFactory
470 // If neither is given, create a WrappingAsyncDnsResolverFactory wrapping
471 // a BasicAsyncResolver.
472 // TODO(bugs.webrtc.org/12598): Remove code once all callers pass a
473 // AsyncDnsResolverFactory.
474 if (dependencies.async_dns_resolver_factory &&
475 dependencies.async_resolver_factory) {
476 RTC_LOG(LS_ERROR)
477 << "Attempt to set both old and new type of DNS resolver factory";
478 return RTCError(RTCErrorType::INVALID_PARAMETER,
479 "Both old and new type of DNS resolver given");
480 }
481 if (dependencies.async_resolver_factory) {
482 dependencies.async_dns_resolver_factory =
483 std::make_unique<WrappingAsyncDnsResolverFactory>(
484 std::move(dependencies.async_resolver_factory));
485 } else {
486 dependencies.async_dns_resolver_factory =
487 std::make_unique<WrappingAsyncDnsResolverFactory>(
488 std::make_unique<BasicAsyncResolverFactory>());
489 }
490
Harald Alvestrandfd9a8f82020-10-26 14:17:02491 // The PeerConnection constructor consumes some, but not all, dependencies.
Tommi87f70902021-04-27 12:43:08492 auto pc = rtc::make_ref_counted<PeerConnection>(
493 context, options, is_unified_plan, std::move(event_log), std::move(call),
494 dependencies, dtls_enabled);
Harald Alvestranda3dd7722020-11-27 08:05:42495 RTCError init_error = pc->Initialize(configuration, std::move(dependencies));
496 if (!init_error.ok()) {
497 RTC_LOG(LS_ERROR) << "PeerConnection initialization failed";
498 return init_error;
Harald Alvestrand62166932020-10-26 08:30:41499 }
500 return pc;
501}
502
Harald Alvestrand4da4a872020-11-04 10:34:21503PeerConnection::PeerConnection(
504 rtc::scoped_refptr<ConnectionContext> context,
505 const PeerConnectionFactoryInterface::Options& options,
506 bool is_unified_plan,
507 std::unique_ptr<RtcEventLog> event_log,
508 std::unique_ptr<Call> call,
Tommic3257d02021-02-10 17:40:08509 PeerConnectionDependencies& dependencies,
510 bool dtls_enabled)
Harald Alvestranda39689c2020-10-15 08:34:31511 : context_(context),
Jonas Oreland6c7f9842022-04-19 15:24:10512 trials_(std::move(dependencies.trials), &context->field_trials()),
Harald Alvestrand4da4a872020-11-04 10:34:21513 options_(options),
Harald Alvestrandfd9a8f82020-10-26 14:17:02514 observer_(dependencies.observer),
Harald Alvestrand62166932020-10-26 08:30:41515 is_unified_plan_(is_unified_plan),
zhihuang38ede132017-06-15 19:52:32516 event_log_(std::move(event_log)),
Karl Wibergb03ab712019-02-14 10:59:57517 event_log_ptr_(event_log_.get()),
Harald Alvestrand0ccfbd22021-04-08 07:25:04518 async_dns_resolver_factory_(
519 std::move(dependencies.async_dns_resolver_factory)),
Harald Alvestrandfd9a8f82020-10-26 14:17:02520 port_allocator_(std::move(dependencies.allocator)),
521 ice_transport_factory_(std::move(dependencies.ice_transport_factory)),
522 tls_cert_verifier_(std::move(dependencies.tls_cert_verifier)),
Karl Wiberg6cab5c82019-03-26 08:57:01523 call_(std::move(call)),
Henrik Boström79b69802019-07-18 09:16:56524 call_ptr_(call_.get()),
Tomas Gunnarsson97a387d2021-03-29 19:04:29525 // RFC 3264: The numeric value of the session id and version in the
526 // o line MUST be representable with a "64 bit signed integer".
Artem Titov880fa812021-07-30 20:30:23527 // Due to this constraint session id `session_id_` is max limited to
Tomas Gunnarsson97a387d2021-03-29 19:04:29528 // LLONG_MAX.
529 session_id_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
Tommic3257d02021-02-10 17:40:08530 dtls_enabled_(dtls_enabled),
Harald Alvestrand1090e442020-10-05 07:01:09531 data_channel_controller_(this),
Lahiru Ginnaliya Gamathige70f9e242021-01-28 07:32:46532 message_handler_(signaling_thread()),
Tommic3257d02021-02-10 17:40:08533 weak_factory_(this) {
534 worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
535 RTC_DCHECK_RUN_ON(worker_thread());
536 worker_thread_safety_ = PendingTaskSafetyFlag::Create();
537 if (!call_)
538 worker_thread_safety_->SetNotAlive();
539 });
540}
henrike@webrtc.org28e20752013-07-10 00:45:36541
542PeerConnection::~PeerConnection() {
Peter Boström1a9d6152015-12-08 21:15:17543 TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
Steve Anton4171afb2017-11-20 18:20:22544 RTC_DCHECK_RUN_ON(signaling_thread());
545
Harald Alvestrand9cd199d2020-10-27 07:10:43546 if (sdp_handler_) {
547 sdp_handler_->PrepareForShutdown();
548 }
Henrik Boströma3728d32019-10-28 11:09:49549
Steve Anton8af21862017-12-15 19:20:13550 // Need to stop transceivers before destroying the stats collector because
551 // AudioRtpSender has a reference to the StatsCollector it will update when
552 // stopping.
Harald Alvestrande15fb152020-10-19 13:28:05553 if (rtp_manager()) {
554 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
555 transceiver->StopInternal();
556 }
Steve Anton8af21862017-12-15 19:20:13557 }
Steve Anton4171afb2017-11-20 18:20:22558
Taylor Brandstettera1c30352016-05-13 15:15:11559 stats_.reset(nullptr);
hbosb78306a2016-12-19 13:06:57560 if (stats_collector_) {
561 stats_collector_->WaitForPendingRequest();
562 stats_collector_ = nullptr;
563 }
Steve Anton75737c02017-11-06 18:37:17564
Harald Alvestrand9cd199d2020-10-27 07:10:43565 if (sdp_handler_) {
566 // Don't destroy BaseChannels until after stats has been cleaned up so that
567 // the last stats request can still read from the channels.
568 sdp_handler_->DestroyAllChannels();
Steve Anton8af21862017-12-15 19:20:13569
Harald Alvestrand9cd199d2020-10-27 07:10:43570 RTC_LOG(LS_INFO) << "Session: " << session_id() << " is destroyed.";
Steve Anton75737c02017-11-06 18:37:17571
Harald Alvestrand9cd199d2020-10-27 07:10:43572 sdp_handler_->ResetSessionDescFactory();
573 }
Steve Anton75737c02017-11-06 18:37:17574
Tomas Gunnarsson92eebef2021-02-10 12:05:44575 // port_allocator_ and transport_controller_ live on the network thread and
576 // should be destroyed there.
Harald Alvestrandbc32c562022-02-09 12:08:47577 transport_controller_copy_ = nullptr;
Karl Wibergfb3be392019-03-22 13:13:22578 network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
579 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarssond69e0702021-04-07 13:14:43580 TeardownDataChannelTransport_n();
Tomas Gunnarsson92eebef2021-02-10 12:05:44581 transport_controller_.reset();
Karl Wibergfb3be392019-03-22 13:13:22582 port_allocator_.reset();
Tommic3257d02021-02-10 17:40:08583 if (network_thread_safety_)
Tomas Gunnarsson92eebef2021-02-10 12:05:44584 network_thread_safety_->SetNotAlive();
Karl Wibergfb3be392019-03-22 13:13:22585 });
Tomas Gunnarssond69e0702021-04-07 13:14:43586
eladalon248fd4f2017-09-06 12:18:15587 // call_ and event_log_ must be destroyed on the worker thread.
Steve Anton978b8762017-09-29 19:15:02588 worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
Karl Wibergb03ab712019-02-14 10:59:57589 RTC_DCHECK_RUN_ON(worker_thread());
Tommic3257d02021-02-10 17:40:08590 worker_thread_safety_->SetNotAlive();
eladalon248fd4f2017-09-06 12:18:15591 call_.reset();
Qingsi Wang93a84392018-01-31 01:13:09592 // The event log must outlive call (and any other object that uses it).
eladalon248fd4f2017-09-06 12:18:15593 event_log_.reset();
594 });
henrike@webrtc.org28e20752013-07-10 00:45:36595}
596
Harald Alvestranda3dd7722020-11-27 08:05:42597RTCError PeerConnection::Initialize(
buildbot@webrtc.org41451d42014-05-03 05:39:45598 const PeerConnectionInterface::RTCConfiguration& configuration,
Benjamin Wrightcab588882018-05-02 22:12:47599 PeerConnectionDependencies dependencies) {
Karl Wiberg744310f2019-02-14 09:18:56600 RTC_DCHECK_RUN_ON(signaling_thread());
Peter Boström1a9d6152015-12-08 21:15:17601 TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
Steve Anton038834f2017-07-14 22:59:59602
Harald Alvestrandb2a74782018-06-28 11:54:07603 cricket::ServerAddresses stun_servers;
604 std::vector<cricket::RelayServerConfig> turn_servers;
605
606 RTCErrorType parse_error =
607 ParseIceServers(configuration.servers, &stun_servers, &turn_servers);
608 if (parse_error != RTCErrorType::NONE) {
Harald Alvestranda3dd7722020-11-27 08:05:42609 return RTCError(parse_error, "ICE server parse failed");
Harald Alvestrandb2a74782018-06-28 11:54:07610 }
611
Jonas Oreland3c028422019-08-22 14:16:35612 // Add the turn logging id to all turn servers
613 for (cricket::RelayServerConfig& turn_server : turn_servers) {
614 turn_server.turn_logging_id = configuration.turn_logging_id;
615 }
616
Harald Alvestrandfd9a8f82020-10-26 14:17:02617 // Note if STUN or TURN servers were supplied.
Harald Alvestrandb2a74782018-06-28 11:54:07618 if (!stun_servers.empty()) {
619 NoteUsageEvent(UsageEvent::STUN_SERVER_ADDED);
620 }
621 if (!turn_servers.empty()) {
622 NoteUsageEvent(UsageEvent::TURN_SERVER_ADDED);
623 }
henrike@webrtc.org28e20752013-07-10 00:45:36624
Tommic3257d02021-02-10 17:40:08625 // Network thread initialization.
Harald Alvestrandbc32c562022-02-09 12:08:47626 transport_controller_copy_ =
627 network_thread()->Invoke<JsepTransportController*>(RTC_FROM_HERE, [&] {
628 RTC_DCHECK_RUN_ON(network_thread());
629 network_thread_safety_ = PendingTaskSafetyFlag::Create();
630 InitializePortAllocatorResult pa_result = InitializePortAllocator_n(
631 stun_servers, turn_servers, configuration);
632 // Send information about IPv4/IPv6 status.
633 PeerConnectionAddressFamilyCounter address_family =
634 pa_result.enable_ipv6 ? kPeerConnection_IPv6 : kPeerConnection_IPv4;
635 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
636 address_family,
637 kPeerConnectionAddressFamilyCounter_Max);
638 return InitializeTransportController_n(configuration, dependencies);
639 });
Lahiru Ginnaliya Gamathigee99c68d2020-09-30 21:33:45640
Steve Antonba818672017-11-06 18:21:57641 configuration_ = configuration;
642
Harald Alvestrande15fb152020-10-19 13:28:05643 stats_ = std::make_unique<StatsCollector>(this);
644 stats_collector_ = RTCStatsCollector::Create(this);
645
Harald Alvestrand66c40362022-01-28 17:41:30646 sdp_handler_ = SdpOfferAnswerHandler::Create(this, configuration,
Niels Möllerafb246b2022-04-20 12:26:50647 dependencies, context_.get());
Harald Alvestrand9cd199d2020-10-27 07:10:43648
Artem Titovc6c02ef2022-05-09 08:30:09649 rtp_manager_ = std::make_unique<RtpTransmissionManager>(
650 IsUnifiedPlan(), signaling_thread(), worker_thread(), channel_manager(),
651 &usage_pattern_, observer_, stats_.get(), [this]() {
652 RTC_DCHECK_RUN_ON(signaling_thread());
653 sdp_handler_->UpdateNegotiationNeeded();
654 });
Harald Alvestrande15fb152020-10-19 13:28:05655
Artem Titovc6c02ef2022-05-09 08:30:09656 // Add default audio/video transceivers for Plan B SDP.
657 if (!IsUnifiedPlan()) {
658 rtp_manager()->transceivers()->Add(
659 RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
660 signaling_thread(),
661 rtc::make_ref_counted<RtpTransceiver>(cricket::MEDIA_TYPE_AUDIO,
662 channel_manager())));
663 rtp_manager()->transceivers()->Add(
664 RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
665 signaling_thread(),
666 rtc::make_ref_counted<RtpTransceiver>(cricket::MEDIA_TYPE_VIDEO,
667 channel_manager())));
Steve Anton4171afb2017-11-20 18:20:22668 }
Harald Alvestrand763f5a92020-10-22 10:39:40669
Harald Alvestrand62166932020-10-26 08:30:41670 int delay_ms = configuration.report_usage_pattern_delay_ms
671 ? *configuration.report_usage_pattern_delay_ms
672 : REPORT_USAGE_PATTERN_DELAY_MS;
Harald Alvestrand1090e442020-10-05 07:01:09673 message_handler_.RequestUsagePatternReport(
674 [this]() {
675 RTC_DCHECK_RUN_ON(signaling_thread());
676 ReportUsagePattern();
677 },
678 delay_ms);
Jonas Orelanda3aa9bd2019-04-17 05:38:40679
Philipp Hanckef59d9fb2021-10-13 09:34:15680 // Record the number of configured ICE servers for all connections.
681 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.PeerConnection.IceServers.Configured",
682 configuration_.servers.size(), 0, 31, 32);
683
Harald Alvestranda3dd7722020-11-27 08:05:42684 return RTCError::OK();
henrike@webrtc.org28e20752013-07-10 00:45:36685}
686
Harald Alvestrandbc32c562022-02-09 12:08:47687JsepTransportController* PeerConnection::InitializeTransportController_n(
Tommic3257d02021-02-10 17:40:08688 const RTCConfiguration& configuration,
689 const PeerConnectionDependencies& dependencies) {
690 JsepTransportController::Config config;
691 config.redetermine_role_on_ice_restart =
692 configuration.redetermine_role_on_ice_restart;
693 config.ssl_max_version = options_.ssl_max_version;
694 config.disable_encryption = options_.disable_encryption;
695 config.bundle_policy = configuration.bundle_policy;
696 config.rtcp_mux_policy = configuration.rtcp_mux_policy;
697 // TODO(bugs.webrtc.org/9891) - Remove options_.crypto_options then remove
698 // this stub.
699 config.crypto_options = configuration.crypto_options.has_value()
700 ? *configuration.crypto_options
701 : options_.crypto_options;
702 config.transport_observer = this;
703 config.rtcp_handler = InitializeRtcpCallback();
704 config.event_log = event_log_ptr_;
705#if defined(ENABLE_EXTERNAL_AUTH)
706 config.enable_external_auth = true;
707#endif
708 config.active_reset_srtp_params = configuration.active_reset_srtp_params;
709
710 // DTLS has to be enabled to use SCTP.
Florent Castelli516e2842021-04-19 13:29:50711 if (dtls_enabled_) {
Tommic3257d02021-02-10 17:40:08712 config.sctp_factory = context_->sctp_transport_factory();
713 }
714
715 config.ice_transport_factory = ice_transport_factory_.get();
716 config.on_dtls_handshake_error_ =
717 [weak_ptr = weak_factory_.GetWeakPtr()](rtc::SSLHandshakeError s) {
718 if (weak_ptr) {
719 weak_ptr->OnTransportControllerDtlsHandshakeError(s);
720 }
721 };
722
Jonas Oreland6c7f9842022-04-19 15:24:10723 config.field_trials = trials_.get();
Jonas Orelanded99dae2022-03-09 08:28:10724
Tommic3257d02021-02-10 17:40:08725 transport_controller_.reset(
726 new JsepTransportController(network_thread(), port_allocator_.get(),
Harald Alvestrand0ccfbd22021-04-08 07:25:04727 async_dns_resolver_factory_.get(), config));
Tommic3257d02021-02-10 17:40:08728
729 transport_controller_->SubscribeIceConnectionState(
730 [this](cricket::IceConnectionState s) {
731 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson2001dc32021-04-06 09:36:00732 if (s == cricket::kIceConnectionConnected) {
733 ReportTransportStats();
734 }
Tommic3257d02021-02-10 17:40:08735 signaling_thread()->PostTask(
736 ToQueuedTask(signaling_thread_safety_.flag(), [this, s]() {
737 RTC_DCHECK_RUN_ON(signaling_thread());
738 OnTransportControllerConnectionState(s);
739 }));
740 });
741 transport_controller_->SubscribeConnectionState(
742 [this](PeerConnectionInterface::PeerConnectionState s) {
743 RTC_DCHECK_RUN_ON(network_thread());
744 signaling_thread()->PostTask(
745 ToQueuedTask(signaling_thread_safety_.flag(), [this, s]() {
746 RTC_DCHECK_RUN_ON(signaling_thread());
747 SetConnectionState(s);
748 }));
749 });
750 transport_controller_->SubscribeStandardizedIceConnectionState(
751 [this](PeerConnectionInterface::IceConnectionState s) {
752 RTC_DCHECK_RUN_ON(network_thread());
753 signaling_thread()->PostTask(
754 ToQueuedTask(signaling_thread_safety_.flag(), [this, s]() {
755 RTC_DCHECK_RUN_ON(signaling_thread());
756 SetStandardizedIceConnectionState(s);
757 }));
758 });
759 transport_controller_->SubscribeIceGatheringState(
760 [this](cricket::IceGatheringState s) {
761 RTC_DCHECK_RUN_ON(network_thread());
762 signaling_thread()->PostTask(
763 ToQueuedTask(signaling_thread_safety_.flag(), [this, s]() {
764 RTC_DCHECK_RUN_ON(signaling_thread());
765 OnTransportControllerGatheringState(s);
766 }));
767 });
768 transport_controller_->SubscribeIceCandidateGathered(
769 [this](const std::string& transport,
770 const std::vector<cricket::Candidate>& candidates) {
771 RTC_DCHECK_RUN_ON(network_thread());
772 signaling_thread()->PostTask(
773 ToQueuedTask(signaling_thread_safety_.flag(),
774 [this, t = transport, c = candidates]() {
775 RTC_DCHECK_RUN_ON(signaling_thread());
776 OnTransportControllerCandidatesGathered(t, c);
777 }));
778 });
779 transport_controller_->SubscribeIceCandidateError(
780 [this](const cricket::IceCandidateErrorEvent& event) {
781 RTC_DCHECK_RUN_ON(network_thread());
782 signaling_thread()->PostTask(ToQueuedTask(
783 signaling_thread_safety_.flag(), [this, event = event]() {
784 RTC_DCHECK_RUN_ON(signaling_thread());
785 OnTransportControllerCandidateError(event);
786 }));
787 });
788 transport_controller_->SubscribeIceCandidatesRemoved(
789 [this](const std::vector<cricket::Candidate>& c) {
790 RTC_DCHECK_RUN_ON(network_thread());
791 signaling_thread()->PostTask(
792 ToQueuedTask(signaling_thread_safety_.flag(), [this, c = c]() {
793 RTC_DCHECK_RUN_ON(signaling_thread());
794 OnTransportControllerCandidatesRemoved(c);
795 }));
796 });
797 transport_controller_->SubscribeIceCandidatePairChanged(
798 [this](const cricket::CandidatePairChangeEvent& event) {
799 RTC_DCHECK_RUN_ON(network_thread());
800 signaling_thread()->PostTask(ToQueuedTask(
801 signaling_thread_safety_.flag(), [this, event = event]() {
802 RTC_DCHECK_RUN_ON(signaling_thread());
803 OnTransportControllerCandidateChanged(event);
804 }));
805 });
806
807 transport_controller_->SetIceConfig(ParseIceConfig(configuration));
Harald Alvestrandbc32c562022-02-09 12:08:47808 return transport_controller_.get();
Tommic3257d02021-02-10 17:40:08809}
810
Yves Gerey665174f2018-06-19 13:03:05811rtc::scoped_refptr<StreamCollectionInterface> PeerConnection::local_streams() {
Karl Wiberg5966c502019-02-21 22:55:09812 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Antonfc853712018-03-01 21:48:58813 RTC_CHECK(!IsUnifiedPlan()) << "local_streams is not available with Unified "
814 "Plan SdpSemantics. Please use GetSenders "
815 "instead.";
Harald Alvestrand9cd199d2020-10-27 07:10:43816 return sdp_handler_->local_streams();
henrike@webrtc.org28e20752013-07-10 00:45:36817}
818
Yves Gerey665174f2018-06-19 13:03:05819rtc::scoped_refptr<StreamCollectionInterface> PeerConnection::remote_streams() {
Karl Wiberg5966c502019-02-21 22:55:09820 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Antonfc853712018-03-01 21:48:58821 RTC_CHECK(!IsUnifiedPlan()) << "remote_streams is not available with Unified "
822 "Plan SdpSemantics. Please use GetReceivers "
823 "instead.";
Harald Alvestrand9cd199d2020-10-27 07:10:43824 return sdp_handler_->remote_streams();
henrike@webrtc.org28e20752013-07-10 00:45:36825}
826
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29827bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
Karl Wiberg744310f2019-02-14 09:18:56828 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Antonfc853712018-03-01 21:48:58829 RTC_CHECK(!IsUnifiedPlan()) << "AddStream is not available with Unified Plan "
830 "SdpSemantics. Please use AddTrack instead.";
Peter Boström1a9d6152015-12-08 21:15:17831 TRACE_EVENT0("webrtc", "PeerConnection::AddStream");
Harald Alvestrand35ba0c52022-05-05 07:37:41832 if (!ConfiguredForMedia()) {
833 RTC_LOG(LS_ERROR) << "AddStream: Not configured for media";
834 return false;
835 }
Harald Alvestrand9cd199d2020-10-27 07:10:43836 return sdp_handler_->AddStream(local_stream);
henrike@webrtc.org28e20752013-07-10 00:45:36837}
838
839void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
Karl Wiberg744310f2019-02-14 09:18:56840 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand35ba0c52022-05-05 07:37:41841 RTC_DCHECK(ConfiguredForMedia());
Steve Antonfc853712018-03-01 21:48:58842 RTC_CHECK(!IsUnifiedPlan()) << "RemoveStream is not available with Unified "
843 "Plan SdpSemantics. Please use RemoveTrack "
844 "instead.";
Peter Boström1a9d6152015-12-08 21:15:17845 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
Harald Alvestrand9cd199d2020-10-27 07:10:43846 sdp_handler_->RemoveStream(local_stream);
henrike@webrtc.org28e20752013-07-10 00:45:36847}
848
Steve Anton2d6c76a2018-01-06 01:10:52849RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
Steve Antonf9381f02017-12-14 18:23:57850 rtc::scoped_refptr<MediaStreamTrackInterface> track,
Seth Hampson845e8782018-03-02 19:34:10851 const std::vector<std::string>& stream_ids) {
Karl Wiberg744310f2019-02-14 09:18:56852 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Anton2d6c76a2018-01-06 01:10:52853 TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
Harald Alvestrand35ba0c52022-05-05 07:37:41854 if (!ConfiguredForMedia()) {
855 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
856 "Not configured for media");
857 }
Steve Antonf9381f02017-12-14 18:23:57858 if (!track) {
859 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Track is null.");
860 }
861 if (!(track->kind() == MediaStreamTrackInterface::kAudioKind ||
862 track->kind() == MediaStreamTrackInterface::kVideoKind)) {
863 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
864 "Track has invalid kind: " + track->kind());
865 }
Steve Antonf9381f02017-12-14 18:23:57866 if (IsClosed()) {
867 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
868 "PeerConnection is closed.");
deadbeefe1f9d832016-01-14 23:35:42869 }
Niels Möllerafb246b2022-04-20 12:26:50870 if (rtp_manager()->FindSenderForTrack(track.get())) {
Steve Antonf9381f02017-12-14 18:23:57871 LOG_AND_RETURN_ERROR(
872 RTCErrorType::INVALID_PARAMETER,
873 "Sender already exists for track " + track->id() + ".");
deadbeefe1f9d832016-01-14 23:35:42874 }
Harald Alvestrande15fb152020-10-19 13:28:05875 auto sender_or_error = rtp_manager()->AddTrack(track, stream_ids);
Steve Antonf9381f02017-12-14 18:23:57876 if (sender_or_error.ok()) {
Harald Alvestrand9cd199d2020-10-27 07:10:43877 sdp_handler_->UpdateNegotiationNeeded();
Niels Möllerafb246b2022-04-20 12:26:50878 stats_->AddTrack(track.get());
Steve Antonf9381f02017-12-14 18:23:57879 }
880 return sender_or_error;
881}
deadbeefe1f9d832016-01-14 23:35:42882
Harald Alvestrand09a0d012022-01-04 19:42:07883RTCError PeerConnection::RemoveTrackOrError(
Steve Antonf9381f02017-12-14 18:23:57884 rtc::scoped_refptr<RtpSenderInterface> sender) {
Karl Wiberg744310f2019-02-14 09:18:56885 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand35ba0c52022-05-05 07:37:41886 if (!ConfiguredForMedia()) {
887 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
888 "Not configured for media");
889 }
Steve Antonf9381f02017-12-14 18:23:57890 if (!sender) {
891 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Sender is null.");
892 }
deadbeefe1f9d832016-01-14 23:35:42893 if (IsClosed()) {
Steve Antonf9381f02017-12-14 18:23:57894 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
895 "PeerConnection is closed.");
deadbeefe1f9d832016-01-14 23:35:42896 }
Steve Antonf9381f02017-12-14 18:23:57897 if (IsUnifiedPlan()) {
898 auto transceiver = FindTransceiverBySender(sender);
899 if (!transceiver || !sender->track()) {
900 return RTCError::OK();
901 }
902 sender->SetTrack(nullptr);
903 if (transceiver->direction() == RtpTransceiverDirection::kSendRecv) {
Steve Anton52d86772018-02-20 23:48:12904 transceiver->internal()->set_direction(
905 RtpTransceiverDirection::kRecvOnly);
Steve Antonf9381f02017-12-14 18:23:57906 } else if (transceiver->direction() == RtpTransceiverDirection::kSendOnly) {
Steve Anton52d86772018-02-20 23:48:12907 transceiver->internal()->set_direction(
908 RtpTransceiverDirection::kInactive);
Steve Antonf9381f02017-12-14 18:23:57909 }
Steve Anton4171afb2017-11-20 18:20:22910 } else {
Steve Antonf9381f02017-12-14 18:23:57911 bool removed;
912 if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Harald Alvestrande15fb152020-10-19 13:28:05913 removed = rtp_manager()->GetAudioTransceiver()->internal()->RemoveSender(
Niels Möllerafb246b2022-04-20 12:26:50914 sender.get());
Steve Antonf9381f02017-12-14 18:23:57915 } else {
916 RTC_DCHECK_EQ(cricket::MEDIA_TYPE_VIDEO, sender->media_type());
Harald Alvestrande15fb152020-10-19 13:28:05917 removed = rtp_manager()->GetVideoTransceiver()->internal()->RemoveSender(
Niels Möllerafb246b2022-04-20 12:26:50918 sender.get());
Steve Antonf9381f02017-12-14 18:23:57919 }
920 if (!removed) {
921 LOG_AND_RETURN_ERROR(
922 RTCErrorType::INVALID_PARAMETER,
923 "Couldn't find sender " + sender->id() + " to remove.");
924 }
Steve Anton4171afb2017-11-20 18:20:22925 }
Harald Alvestrand9cd199d2020-10-27 07:10:43926 sdp_handler_->UpdateNegotiationNeeded();
Steve Antonf9381f02017-12-14 18:23:57927 return RTCError::OK();
928}
929
930rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
931PeerConnection::FindTransceiverBySender(
932 rtc::scoped_refptr<RtpSenderInterface> sender) {
Harald Alvestrande15fb152020-10-19 13:28:05933 return rtp_manager()->transceivers()->FindBySender(sender);
deadbeefe1f9d832016-01-14 23:35:42934}
935
Steve Anton9158ef62017-11-27 21:01:52936RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
937PeerConnection::AddTransceiver(
938 rtc::scoped_refptr<MediaStreamTrackInterface> track) {
Harald Alvestrand35ba0c52022-05-05 07:37:41939 if (!ConfiguredForMedia()) {
940 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
941 "Not configured for media");
942 }
943
Steve Anton9158ef62017-11-27 21:01:52944 return AddTransceiver(track, RtpTransceiverInit());
945}
946
Tomas Gunnarsson92eebef2021-02-10 12:05:44947RtpTransportInternal* PeerConnection::GetRtpTransport(const std::string& mid) {
Harald Alvestrandbc32c562022-02-09 12:08:47948 // TODO(bugs.webrtc.org/9987): Avoid the thread jump.
949 // This might be done by caching the value on the signaling thread.
Tomas Gunnarsson92eebef2021-02-10 12:05:44950 RTC_DCHECK_RUN_ON(signaling_thread());
951 return network_thread()->Invoke<RtpTransportInternal*>(
952 RTC_FROM_HERE, [this, &mid] {
Harald Alvestrandbc32c562022-02-09 12:08:47953 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson92eebef2021-02-10 12:05:44954 auto rtp_transport = transport_controller_->GetRtpTransport(mid);
955 RTC_DCHECK(rtp_transport);
956 return rtp_transport;
957 });
958}
959
Steve Anton9158ef62017-11-27 21:01:52960RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
961PeerConnection::AddTransceiver(
962 rtc::scoped_refptr<MediaStreamTrackInterface> track,
963 const RtpTransceiverInit& init) {
Karl Wiberg744310f2019-02-14 09:18:56964 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand35ba0c52022-05-05 07:37:41965 if (!ConfiguredForMedia()) {
966 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
967 "Not configured for media");
968 }
Steve Antonfc853712018-03-01 21:48:58969 RTC_CHECK(IsUnifiedPlan())
970 << "AddTransceiver is only available with Unified Plan SdpSemantics";
Steve Anton9158ef62017-11-27 21:01:52971 if (!track) {
972 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "track is null");
973 }
974 cricket::MediaType media_type;
975 if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
976 media_type = cricket::MEDIA_TYPE_AUDIO;
977 } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
978 media_type = cricket::MEDIA_TYPE_VIDEO;
979 } else {
980 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
981 "Track kind is not audio or video");
982 }
983 return AddTransceiver(media_type, track, init);
984}
985
986RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
987PeerConnection::AddTransceiver(cricket::MediaType media_type) {
988 return AddTransceiver(media_type, RtpTransceiverInit());
989}
990
991RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
992PeerConnection::AddTransceiver(cricket::MediaType media_type,
993 const RtpTransceiverInit& init) {
Karl Wiberg744310f2019-02-14 09:18:56994 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand35ba0c52022-05-05 07:37:41995 if (!ConfiguredForMedia()) {
996 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
997 "Not configured for media");
998 }
Steve Antonfc853712018-03-01 21:48:58999 RTC_CHECK(IsUnifiedPlan())
1000 << "AddTransceiver is only available with Unified Plan SdpSemantics";
Steve Anton9158ef62017-11-27 21:01:521001 if (!(media_type == cricket::MEDIA_TYPE_AUDIO ||
1002 media_type == cricket::MEDIA_TYPE_VIDEO)) {
1003 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1004 "media type is not audio or video");
1005 }
1006 return AddTransceiver(media_type, nullptr, init);
1007}
1008
1009RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
1010PeerConnection::AddTransceiver(
1011 cricket::MediaType media_type,
1012 rtc::scoped_refptr<MediaStreamTrackInterface> track,
Steve Anton22da89f2018-01-25 21:58:071013 const RtpTransceiverInit& init,
Guido Urdaneta70c2db12019-04-16 10:24:141014 bool update_negotiation_needed) {
Harald Alvestranda474fbf2020-10-01 16:47:231015 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand35ba0c52022-05-05 07:37:411016 if (!ConfiguredForMedia()) {
1017 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
1018 "Not configured for media");
1019 }
Steve Anton9158ef62017-11-27 21:01:521020 RTC_DCHECK((media_type == cricket::MEDIA_TYPE_AUDIO ||
1021 media_type == cricket::MEDIA_TYPE_VIDEO));
1022 if (track) {
1023 RTC_DCHECK_EQ(media_type,
1024 (track->kind() == MediaStreamTrackInterface::kAudioKind
1025 ? cricket::MEDIA_TYPE_AUDIO
1026 : cricket::MEDIA_TYPE_VIDEO));
1027 }
1028
Amit Hilbuche2a284d2019-03-05 20:36:311029 RTC_HISTOGRAM_COUNTS_LINEAR(kSimulcastNumberOfEncodings,
1030 init.send_encodings.size(), 0, 7, 8);
1031
Amit Hilbuchaa584152019-02-07 01:09:521032 size_t num_rids = absl::c_count_if(init.send_encodings,
1033 [](const RtpEncodingParameters& encoding) {
1034 return !encoding.rid.empty();
1035 });
1036 if (num_rids > 0 && num_rids != init.send_encodings.size()) {
Amit Hilbuchce470aa2019-02-07 01:09:521037 LOG_AND_RETURN_ERROR(
Amit Hilbuchaa584152019-02-07 01:09:521038 RTCErrorType::INVALID_PARAMETER,
1039 "RIDs must be provided for either all or none of the send encodings.");
Emircan Uysaler78323432019-02-08 20:41:391040 }
1041
Amit Hilbuchf4770402019-04-08 21:11:571042 if (num_rids > 0 && absl::c_any_of(init.send_encodings,
1043 [](const RtpEncodingParameters& encoding) {
1044 return !IsLegalRsidName(encoding.rid);
1045 })) {
1046 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1047 "Invalid RID value provided.");
1048 }
1049
Amit Hilbuchaa584152019-02-07 01:09:521050 if (absl::c_any_of(init.send_encodings,
1051 [](const RtpEncodingParameters& encoding) {
1052 return encoding.ssrc.has_value();
1053 })) {
1054 LOG_AND_RETURN_ERROR(
1055 RTCErrorType::UNSUPPORTED_PARAMETER,
1056 "Attempted to set an unimplemented parameter of RtpParameters.");
Florent Castelli892acf02018-10-01 20:47:201057 }
1058
1059 RtpParameters parameters;
1060 parameters.encodings = init.send_encodings;
Amit Hilbuchaa584152019-02-07 01:09:521061
1062 // Encodings are dropped from the tail if too many are provided.
Florent Castellie1b685a2021-04-30 17:11:371063 size_t max_simulcast_streams =
1064 media_type == cricket::MEDIA_TYPE_VIDEO ? kMaxSimulcastStreams : 1u;
1065 if (parameters.encodings.size() > max_simulcast_streams) {
Amit Hilbuchaa584152019-02-07 01:09:521066 parameters.encodings.erase(
Florent Castellie1b685a2021-04-30 17:11:371067 parameters.encodings.begin() + max_simulcast_streams,
Amit Hilbuchaa584152019-02-07 01:09:521068 parameters.encodings.end());
1069 }
1070
1071 // Single RID should be removed.
1072 if (parameters.encodings.size() == 1 &&
1073 !parameters.encodings[0].rid.empty()) {
1074 RTC_LOG(LS_INFO) << "Removing RID: " << parameters.encodings[0].rid << ".";
1075 parameters.encodings[0].rid.clear();
1076 }
1077
1078 // If RIDs were not provided, they are generated for simulcast scenario.
1079 if (parameters.encodings.size() > 1 && num_rids == 0) {
1080 rtc::UniqueStringGenerator rid_generator;
1081 for (RtpEncodingParameters& encoding : parameters.encodings) {
1082 encoding.rid = rid_generator();
1083 }
1084 }
1085
Florent Castelli892acf02018-10-01 20:47:201086 if (UnimplementedRtpParameterHasValue(parameters)) {
1087 LOG_AND_RETURN_ERROR(
1088 RTCErrorType::UNSUPPORTED_PARAMETER,
1089 "Attempted to set an unimplemented parameter of RtpParameters.");
1090 }
Steve Anton9158ef62017-11-27 21:01:521091
Florent Castellic1a0bcb2019-01-29 13:26:481092 auto result = cricket::CheckRtpParametersValues(parameters);
1093 if (!result.ok()) {
1094 LOG_AND_RETURN_ERROR(result.type(), result.message());
1095 }
1096
Steve Anton3d954a62018-04-02 18:27:231097 RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
1098 << " transceiver in response to a call to AddTransceiver.";
Steve Anton07563732018-06-26 18:13:501099 // Set the sender ID equal to the track ID if the track is specified unless
1100 // that sender ID is already in use.
Harald Alvestrande15fb152020-10-19 13:28:051101 std::string sender_id = (track && !rtp_manager()->FindSenderById(track->id())
1102 ? track->id()
1103 : rtc::CreateRandomUuid());
1104 auto sender = rtp_manager()->CreateSender(
1105 media_type, sender_id, track, init.stream_ids, parameters.encodings);
1106 auto receiver =
1107 rtp_manager()->CreateReceiver(media_type, rtc::CreateRandomUuid());
1108 auto transceiver = rtp_manager()->CreateAndAddTransceiver(sender, receiver);
Steve Anton02ee47c2018-01-11 00:26:061109 transceiver->internal()->set_direction(init.direction);
1110
Guido Urdaneta70c2db12019-04-16 10:24:141111 if (update_negotiation_needed) {
Harald Alvestrand9cd199d2020-10-27 07:10:431112 sdp_handler_->UpdateNegotiationNeeded();
Steve Anton22da89f2018-01-25 21:58:071113 }
Steve Antonf9381f02017-12-14 18:23:571114
1115 return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
1116}
1117
Steve Anton52d86772018-02-20 23:48:121118void PeerConnection::OnNegotiationNeeded() {
1119 RTC_DCHECK_RUN_ON(signaling_thread());
1120 RTC_DCHECK(!IsClosed());
Harald Alvestrand9cd199d2020-10-27 07:10:431121 sdp_handler_->UpdateNegotiationNeeded();
Steve Anton52d86772018-02-20 23:48:121122}
1123
deadbeeffac06552015-11-25 19:26:011124rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
deadbeefbd7d8f72015-12-19 00:58:441125 const std::string& kind,
1126 const std::string& stream_id) {
Karl Wiberg5966c502019-02-21 22:55:091127 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand35ba0c52022-05-05 07:37:411128 if (!ConfiguredForMedia()) {
1129 RTC_LOG(LS_ERROR) << "Not configured for media";
1130 return nullptr;
1131 }
Steve Antonfc853712018-03-01 21:48:581132 RTC_CHECK(!IsUnifiedPlan()) << "CreateSender is not available with Unified "
1133 "Plan SdpSemantics. Please use AddTransceiver "
1134 "instead.";
Peter Boström1a9d6152015-12-08 21:15:171135 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
zhihuang29ff8442016-07-27 18:07:251136 if (IsClosed()) {
1137 return nullptr;
1138 }
Steve Anton4171afb2017-11-20 18:20:221139
Seth Hampson5b4f0752018-04-02 23:31:361140 // Internally we need to have one stream with Plan B semantics, so we
1141 // generate a random stream ID if not specified.
Seth Hampson845e8782018-03-02 19:34:101142 std::vector<std::string> stream_ids;
Seth Hampson5b4f0752018-04-02 23:31:361143 if (stream_id.empty()) {
1144 stream_ids.push_back(rtc::CreateRandomUuid());
1145 RTC_LOG(LS_INFO)
1146 << "No stream_id specified for sender. Generated stream ID: "
1147 << stream_ids[0];
1148 } else {
Seth Hampson845e8782018-03-02 19:34:101149 stream_ids.push_back(stream_id);
Steve Anton02ee47c2018-01-11 00:26:061150 }
1151
Steve Anton4171afb2017-11-20 18:20:221152 // TODO(steveanton): Move construction of the RtpSenders to RtpTransceiver.
deadbeefa601f5c2016-06-06 21:27:391153 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
deadbeeffac06552015-11-25 19:26:011154 if (kind == MediaStreamTrackInterface::kAudioKind) {
Amit Hilbuchea7ef2a2019-02-19 23:20:211155 auto audio_sender = AudioRtpSender::Create(
Harald Alvestrande15fb152020-10-19 13:28:051156 worker_thread(), rtc::CreateRandomUuid(), stats_.get(), rtp_manager());
1157 audio_sender->SetMediaChannel(rtp_manager()->voice_media_channel());
deadbeefa601f5c2016-06-06 21:27:391158 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
Steve Anton02ee47c2018-01-11 00:26:061159 signaling_thread(), audio_sender);
Harald Alvestrande15fb152020-10-19 13:28:051160 rtp_manager()->GetAudioTransceiver()->internal()->AddSender(new_sender);
deadbeeffac06552015-11-25 19:26:011161 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
Harald Alvestrande15fb152020-10-19 13:28:051162 auto video_sender = VideoRtpSender::Create(
1163 worker_thread(), rtc::CreateRandomUuid(), rtp_manager());
1164 video_sender->SetMediaChannel(rtp_manager()->video_media_channel());
deadbeefa601f5c2016-06-06 21:27:391165 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
Steve Anton02ee47c2018-01-11 00:26:061166 signaling_thread(), video_sender);
Harald Alvestrande15fb152020-10-19 13:28:051167 rtp_manager()->GetVideoTransceiver()->internal()->AddSender(new_sender);
deadbeeffac06552015-11-25 19:26:011168 } else {
Mirko Bonadei675513b2017-11-09 10:09:251169 RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
Steve Anton4171afb2017-11-20 18:20:221170 return nullptr;
deadbeeffac06552015-11-25 19:26:011171 }
Henrik Andreasssoncc189172019-05-20 09:01:381172 new_sender->internal()->set_stream_ids(stream_ids);
Steve Anton4171afb2017-11-20 18:20:221173
deadbeefe1f9d832016-01-14 23:35:421174 return new_sender;
deadbeeffac06552015-11-25 19:26:011175}
1176
deadbeef70ab1a12015-09-28 23:53:551177std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
1178 const {
Karl Wiberga58e1692019-03-26 12:33:431179 RTC_DCHECK_RUN_ON(signaling_thread());
deadbeefa601f5c2016-06-06 21:27:391180 std::vector<rtc::scoped_refptr<RtpSenderInterface>> ret;
Artem Titovc6c02ef2022-05-09 08:30:091181 for (const auto& sender : rtp_manager()->GetSendersInternal()) {
1182 ret.push_back(sender);
deadbeefa601f5c2016-06-06 21:27:391183 }
1184 return ret;
deadbeef70ab1a12015-09-28 23:53:551185}
1186
1187std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
1188PeerConnection::GetReceivers() const {
Karl Wiberga58e1692019-03-26 12:33:431189 RTC_DCHECK_RUN_ON(signaling_thread());
deadbeefa601f5c2016-06-06 21:27:391190 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> ret;
Artem Titovc6c02ef2022-05-09 08:30:091191 for (const auto& receiver : rtp_manager()->GetReceiversInternal()) {
1192 ret.push_back(receiver);
deadbeefa601f5c2016-06-06 21:27:391193 }
1194 return ret;
deadbeef70ab1a12015-09-28 23:53:551195}
1196
Steve Anton9158ef62017-11-27 21:01:521197std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
1198PeerConnection::GetTransceivers() const {
Karl Wiberg5966c502019-02-21 22:55:091199 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Antonfc853712018-03-01 21:48:581200 RTC_CHECK(IsUnifiedPlan())
1201 << "GetTransceivers is only supported with Unified Plan SdpSemantics.";
Steve Anton9158ef62017-11-27 21:01:521202 std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> all_transceivers;
Artem Titovc6c02ef2022-05-09 08:30:091203 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
1204 all_transceivers.push_back(transceiver);
Steve Anton9158ef62017-11-27 21:01:521205 }
1206 return all_transceivers;
1207}
1208
henrike@webrtc.org28e20752013-07-10 00:45:361209bool PeerConnection::GetStats(StatsObserver* observer,
wu@webrtc.orgb9a088b2014-02-13 23:18:491210 MediaStreamTrackInterface* track,
1211 StatsOutputLevel level) {
Peter Boström1a9d6152015-12-08 21:15:171212 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
Karl Wiberg6cab5c82019-03-26 08:57:011213 RTC_DCHECK_RUN_ON(signaling_thread());
nisse7ce109a2017-01-31 08:57:561214 if (!observer) {
Mirko Bonadei675513b2017-11-09 10:09:251215 RTC_LOG(LS_ERROR) << "GetStats - observer is NULL.";
henrike@webrtc.org28e20752013-07-10 00:45:361216 return false;
1217 }
1218
Tommife041642021-04-07 08:08:281219 RTC_LOG_THREAD_BLOCK_COUNT();
1220
tommi@webrtc.org03505bc2014-07-14 20:15:261221 stats_->UpdateStats(level);
Tommi19015512022-02-02 10:49:351222
1223 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(4);
1224
zhihuange9e94c32016-11-04 18:38:151225 // The StatsCollector is used to tell if a track is valid because it may
1226 // remember tracks that the PeerConnection previously removed.
1227 if (track && !stats_->IsValidTrack(track->id())) {
Mirko Bonadei675513b2017-11-09 10:09:251228 RTC_LOG(LS_WARNING) << "GetStats is called with an invalid track: "
1229 << track->id();
zhihuange9e94c32016-11-04 18:38:151230 return false;
1231 }
Harald Alvestrand1090e442020-10-05 07:01:091232 message_handler_.PostGetStats(observer, stats_.get(), track);
Tommife041642021-04-07 08:08:281233
henrike@webrtc.org28e20752013-07-10 00:45:361234 return true;
1235}
1236
hbos74e1a4f2016-09-16 06:33:011237void PeerConnection::GetStats(RTCStatsCollectorCallback* callback) {
Henrik Boström1df1bf82018-03-20 12:24:201238 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
Karl Wiberg6cab5c82019-03-26 08:57:011239 RTC_DCHECK_RUN_ON(signaling_thread());
hbos74e1a4f2016-09-16 06:33:011240 RTC_DCHECK(stats_collector_);
Henrik Boström1df1bf82018-03-20 12:24:201241 RTC_DCHECK(callback);
Tommife041642021-04-07 08:08:281242 RTC_LOG_THREAD_BLOCK_COUNT();
Niels Möllere7cc8832022-01-04 14:20:031243 stats_collector_->GetStatsReport(
1244 rtc::scoped_refptr<RTCStatsCollectorCallback>(callback));
hbos74e1a4f2016-09-16 06:33:011245}
1246
Henrik Boström1df1bf82018-03-20 12:24:201247void PeerConnection::GetStats(
1248 rtc::scoped_refptr<RtpSenderInterface> selector,
1249 rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1250 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
Karl Wiberg6cab5c82019-03-26 08:57:011251 RTC_DCHECK_RUN_ON(signaling_thread());
Henrik Boström1df1bf82018-03-20 12:24:201252 RTC_DCHECK(callback);
1253 RTC_DCHECK(stats_collector_);
1254 rtc::scoped_refptr<RtpSenderInternal> internal_sender;
1255 if (selector) {
Harald Alvestrande15fb152020-10-19 13:28:051256 for (const auto& proxy_transceiver :
1257 rtp_manager()->transceivers()->List()) {
Henrik Boström1df1bf82018-03-20 12:24:201258 for (const auto& proxy_sender :
1259 proxy_transceiver->internal()->senders()) {
1260 if (proxy_sender == selector) {
1261 internal_sender = proxy_sender->internal();
1262 break;
1263 }
1264 }
1265 if (internal_sender)
1266 break;
1267 }
1268 }
Artem Titov880fa812021-07-30 20:30:231269 // If there is no `internal_sender` then `selector` is either null or does not
Henrik Boström1df1bf82018-03-20 12:24:201270 // belong to the PeerConnection (in Plan B, senders can be removed from the
1271 // PeerConnection). This means that "all the stats objects representing the
1272 // selector" is an empty set. Invoking GetStatsReport() with a null selector
1273 // produces an empty stats report.
1274 stats_collector_->GetStatsReport(internal_sender, callback);
1275}
1276
1277void PeerConnection::GetStats(
1278 rtc::scoped_refptr<RtpReceiverInterface> selector,
1279 rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1280 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
Karl Wiberg6cab5c82019-03-26 08:57:011281 RTC_DCHECK_RUN_ON(signaling_thread());
Henrik Boström1df1bf82018-03-20 12:24:201282 RTC_DCHECK(callback);
1283 RTC_DCHECK(stats_collector_);
1284 rtc::scoped_refptr<RtpReceiverInternal> internal_receiver;
1285 if (selector) {
Harald Alvestrande15fb152020-10-19 13:28:051286 for (const auto& proxy_transceiver :
1287 rtp_manager()->transceivers()->List()) {
Henrik Boström1df1bf82018-03-20 12:24:201288 for (const auto& proxy_receiver :
1289 proxy_transceiver->internal()->receivers()) {
1290 if (proxy_receiver == selector) {
1291 internal_receiver = proxy_receiver->internal();
1292 break;
1293 }
1294 }
1295 if (internal_receiver)
1296 break;
1297 }
1298 }
Artem Titov880fa812021-07-30 20:30:231299 // If there is no `internal_receiver` then `selector` is either null or does
Henrik Boström1df1bf82018-03-20 12:24:201300 // not belong to the PeerConnection (in Plan B, receivers can be removed from
1301 // the PeerConnection). This means that "all the stats objects representing
1302 // the selector" is an empty set. Invoking GetStatsReport() with a null
1303 // selector produces an empty stats report.
1304 stats_collector_->GetStatsReport(internal_receiver, callback);
1305}
1306
henrike@webrtc.org28e20752013-07-10 00:45:361307PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
Karl Wiberg8d2e2282019-02-17 12:00:071308 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431309 return sdp_handler_->signaling_state();
henrike@webrtc.org28e20752013-07-10 00:45:361310}
1311
henrike@webrtc.org28e20752013-07-10 00:45:361312PeerConnectionInterface::IceConnectionState
1313PeerConnection::ice_connection_state() {
Karl Wiberg8d2e2282019-02-17 12:00:071314 RTC_DCHECK_RUN_ON(signaling_thread());
henrike@webrtc.org28e20752013-07-10 00:45:361315 return ice_connection_state_;
1316}
1317
Alex Loiko9289eda2018-11-23 16:18:591318PeerConnectionInterface::IceConnectionState
1319PeerConnection::standardized_ice_connection_state() {
Karl Wiberg8d2e2282019-02-17 12:00:071320 RTC_DCHECK_RUN_ON(signaling_thread());
Alex Loiko9289eda2018-11-23 16:18:591321 return standardized_ice_connection_state_;
1322}
1323
Jonas Olsson635474e2018-10-18 13:58:171324PeerConnectionInterface::PeerConnectionState
1325PeerConnection::peer_connection_state() {
Karl Wiberg8d2e2282019-02-17 12:00:071326 RTC_DCHECK_RUN_ON(signaling_thread());
Jonas Olsson635474e2018-10-18 13:58:171327 return connection_state_;
1328}
1329
henrike@webrtc.org28e20752013-07-10 00:45:361330PeerConnectionInterface::IceGatheringState
1331PeerConnection::ice_gathering_state() {
Karl Wiberg8d2e2282019-02-17 12:00:071332 RTC_DCHECK_RUN_ON(signaling_thread());
henrike@webrtc.org28e20752013-07-10 00:45:361333 return ice_gathering_state_;
1334}
1335
Harald Alvestrand61f74d92020-03-02 10:20:001336absl::optional<bool> PeerConnection::can_trickle_ice_candidates() {
1337 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrandcdcfab02020-09-28 13:02:071338 const SessionDescriptionInterface* description = current_remote_description();
Harald Alvestrand61f74d92020-03-02 10:20:001339 if (!description) {
Harald Alvestrandcdcfab02020-09-28 13:02:071340 description = pending_remote_description();
Harald Alvestrand61f74d92020-03-02 10:20:001341 }
1342 if (!description) {
1343 return absl::nullopt;
1344 }
1345 // TODO(bugs.webrtc.org/7443): Change to retrieve from session-level option.
1346 if (description->description()->transport_infos().size() < 1) {
1347 return absl::nullopt;
1348 }
1349 return description->description()->transport_infos()[0].description.HasOption(
1350 "trickle");
1351}
1352
Harald Alvestranda9af50f2021-05-21 13:33:511353RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>>
1354PeerConnection::CreateDataChannelOrError(const std::string& label,
1355 const DataChannelInit* config) {
Karl Wiberg106d92d2019-02-14 09:17:471356 RTC_DCHECK_RUN_ON(signaling_thread());
Peter Boström1a9d6152015-12-08 21:15:171357 TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
zhihuang9763d562016-08-05 18:14:501358
Harald Alvestrand05e4d082019-12-03 13:04:211359 bool first_datachannel = !data_channel_controller_.HasDataChannels();
jiayl@webrtc.org001fd2d2014-05-29 15:31:111360
kwibergd1fe2812016-04-27 13:47:291361 std::unique_ptr<InternalDataChannelInit> internal_config;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:581362 if (config) {
1363 internal_config.reset(new InternalDataChannelInit(*config));
1364 }
Harald Alvestranda9af50f2021-05-21 13:33:511365 // TODO(bugs.webrtc.org/12796): Return a more specific error.
Taylor Brandstetter3a034e12020-07-09 22:32:341366 rtc::scoped_refptr<DataChannelInterface> channel(
1367 data_channel_controller_.InternalCreateDataChannelWithProxy(
Harald Alvestrand00cf34c2019-12-02 08:56:021368 label, internal_config.get()));
deadbeefab9b2d12015-10-14 18:33:111369 if (!channel.get()) {
Harald Alvestranda9af50f2021-05-21 13:33:511370 return RTCError(RTCErrorType::INTERNAL_ERROR,
1371 "Data channel creation failed");
deadbeefab9b2d12015-10-14 18:33:111372 }
henrike@webrtc.org28e20752013-07-10 00:45:361373
Harald Alvestrand48171ec2021-04-20 15:06:031374 // Trigger the onRenegotiationNeeded event for
jiayl@webrtc.org001fd2d2014-05-29 15:31:111375 // the first SCTP DataChannel.
Harald Alvestrand7af57c62021-04-16 11:12:141376 if (first_datachannel) {
Harald Alvestrand9cd199d2020-10-27 07:10:431377 sdp_handler_->UpdateNegotiationNeeded();
jiayl@webrtc.org001fd2d2014-05-29 15:31:111378 }
Harald Alvestrand8ebba742018-05-31 12:00:341379 NoteUsageEvent(UsageEvent::DATA_ADDED);
Taylor Brandstetter3a034e12020-07-09 22:32:341380 return channel;
henrike@webrtc.org28e20752013-07-10 00:45:361381}
1382
Henrik Boström79b69802019-07-18 09:16:561383void PeerConnection::RestartIce() {
1384 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431385 sdp_handler_->RestartIce();
Henrik Boström79b69802019-07-18 09:16:561386}
1387
henrike@webrtc.org28e20752013-07-10 00:45:361388void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:161389 const RTCOfferAnswerOptions& options) {
Karl Wiberg5966c502019-02-21 22:55:091390 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431391 sdp_handler_->CreateOffer(observer, options);
Henrik Boströma3728d32019-10-28 11:09:491392}
1393
Harald Alvestrandcdcfab02020-09-28 13:02:071394void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
1395 const RTCOfferAnswerOptions& options) {
Henrik Boströma3728d32019-10-28 11:09:491396 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431397 sdp_handler_->CreateAnswer(observer, options);
henrike@webrtc.org28e20752013-07-10 00:45:361398}
1399
henrike@webrtc.org28e20752013-07-10 00:45:361400void PeerConnection::SetLocalDescription(
1401 SetSessionDescriptionObserver* observer,
Steve Anton80dd7b52018-02-17 01:08:421402 SessionDescriptionInterface* desc_ptr) {
Karl Wiberg5966c502019-02-21 22:55:091403 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431404 sdp_handler_->SetLocalDescription(observer, desc_ptr);
Henrik Boström831ae4e2020-07-29 10:04:001405}
1406
1407void PeerConnection::SetLocalDescription(
1408 std::unique_ptr<SessionDescriptionInterface> desc,
1409 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {
1410 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431411 sdp_handler_->SetLocalDescription(std::move(desc), observer);
Henrik Boströma3728d32019-10-28 11:09:491412}
Steve Anton8a006912017-12-04 23:25:561413
Henrik Boström4e196702019-10-30 09:35:501414void PeerConnection::SetLocalDescription(
1415 SetSessionDescriptionObserver* observer) {
1416 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431417 sdp_handler_->SetLocalDescription(observer);
Henrik Boström831ae4e2020-07-29 10:04:001418}
1419
1420void PeerConnection::SetLocalDescription(
1421 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {
1422 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431423 sdp_handler_->SetLocalDescription(observer);
Henrik Boström4e196702019-10-30 09:35:501424}
1425
henrike@webrtc.org28e20752013-07-10 00:45:361426void PeerConnection::SetRemoteDescription(
Henrik Boströma4ecf552017-11-23 14:17:071427 SetSessionDescriptionObserver* observer,
Henrik Boströma3728d32019-10-28 11:09:491428 SessionDescriptionInterface* desc_ptr) {
1429 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431430 sdp_handler_->SetRemoteDescription(observer, desc_ptr);
Henrik Boström31638672017-11-23 16:48:321431}
1432
1433void PeerConnection::SetRemoteDescription(
1434 std::unique_ptr<SessionDescriptionInterface> desc,
1435 rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer) {
Karl Wiberg5966c502019-02-21 22:55:091436 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431437 sdp_handler_->SetRemoteDescription(std::move(desc), observer);
Henrik Boströmafa07dd2018-12-20 10:06:021438}
1439
deadbeef46c73892016-11-17 03:42:041440PeerConnectionInterface::RTCConfiguration PeerConnection::GetConfiguration() {
Karl Wiberg5966c502019-02-21 22:55:091441 RTC_DCHECK_RUN_ON(signaling_thread());
deadbeef46c73892016-11-17 03:42:041442 return configuration_;
1443}
1444
Niels Möller2579f0c2019-08-19 07:58:171445RTCError PeerConnection::SetConfiguration(
1446 const RTCConfiguration& configuration) {
Karl Wiberg5966c502019-02-21 22:55:091447 RTC_DCHECK_RUN_ON(signaling_thread());
Peter Boström1a9d6152015-12-08 21:15:171448 TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
Steve Antonc79268f2018-04-24 16:54:101449 if (IsClosed()) {
Niels Möller2579f0c2019-08-19 07:58:171450 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
1451 "SetConfiguration: PeerConnection is closed.");
Steve Antonc79268f2018-04-24 16:54:101452 }
1453
Qingsi Wanga2d60672018-04-11 23:57:451454 // According to JSEP, after setLocalDescription, changing the candidate pool
1455 // size is not allowed, and changing the set of ICE servers will not result
1456 // in new candidates being gathered.
Steve Anton75737c02017-11-06 18:37:171457 if (local_description() && configuration.ice_candidate_pool_size !=
1458 configuration_.ice_candidate_pool_size) {
Niels Möller2579f0c2019-08-19 07:58:171459 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
1460 "Can't change candidate pool size after calling "
1461 "SetLocalDescription.");
buildbot@webrtc.org41451d42014-05-03 05:39:451462 }
Taylor Brandstettera1c30352016-05-13 15:15:111463
Piotr (Peter) Slatalaaa1e7c22018-10-16 17:04:451464 if (local_description() &&
Benjamin Wright8c27cca2018-10-25 17:16:441465 configuration.crypto_options != configuration_.crypto_options) {
Niels Möller2579f0c2019-08-19 07:58:171466 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
1467 "Can't change crypto_options after calling "
1468 "SetLocalDescription.");
Benjamin Wright8c27cca2018-10-25 17:16:441469 }
1470
deadbeef293e9262017-01-11 20:28:301471 // The simplest (and most future-compatible) way to tell if the config was
1472 // modified in an invalid way is to copy each property we do support
1473 // modifying, then use operator==. There are far more properties we don't
1474 // support modifying than those we do, and more could be added.
1475 RTCConfiguration modified_config = configuration_;
1476 modified_config.servers = configuration.servers;
1477 modified_config.type = configuration.type;
1478 modified_config.ice_candidate_pool_size =
1479 configuration.ice_candidate_pool_size;
1480 modified_config.prune_turn_ports = configuration.prune_turn_ports;
Honghai Zhangf8998cf2019-10-14 18:27:501481 modified_config.turn_port_prune_policy = configuration.turn_port_prune_policy;
Qingsi Wangbca14852019-06-26 21:56:021482 modified_config.surface_ice_candidates_on_ice_transport_type_changed =
1483 configuration.surface_ice_candidates_on_ice_transport_type_changed;
skvladd1f5fda2017-02-04 00:54:051484 modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
Qingsi Wange6826d22018-03-08 22:55:141485 modified_config.ice_check_interval_strong_connectivity =
1486 configuration.ice_check_interval_strong_connectivity;
1487 modified_config.ice_check_interval_weak_connectivity =
1488 configuration.ice_check_interval_weak_connectivity;
Qingsi Wang22e623a2018-03-13 17:53:571489 modified_config.ice_unwritable_timeout = configuration.ice_unwritable_timeout;
1490 modified_config.ice_unwritable_min_checks =
1491 configuration.ice_unwritable_min_checks;
Jiawei Ou9d4fd5552018-12-07 07:30:171492 modified_config.ice_inactive_timeout = configuration.ice_inactive_timeout;
Qingsi Wangdb53f8e2018-02-20 22:45:491493 modified_config.stun_candidate_keepalive_interval =
1494 configuration.stun_candidate_keepalive_interval;
Jonas Orelandbdcee282017-10-10 12:01:401495 modified_config.turn_customizer = configuration.turn_customizer;
Qingsi Wang9a5c6f82018-02-01 18:38:401496 modified_config.network_preference = configuration.network_preference;
Zhi Huangb57e1692018-06-12 18:41:111497 modified_config.active_reset_srtp_params =
1498 configuration.active_reset_srtp_params;
Jonas Oreland3c028422019-08-22 14:16:351499 modified_config.turn_logging_id = configuration.turn_logging_id;
philipel16cec3b2019-10-25 10:23:021500 modified_config.allow_codec_switching = configuration.allow_codec_switching;
Derek Bailey6c127a12021-04-15 19:42:411501 modified_config.stable_writable_connection_ping_interval_ms =
1502 configuration.stable_writable_connection_ping_interval_ms;
deadbeef293e9262017-01-11 20:28:301503 if (configuration != modified_config) {
Niels Möller2579f0c2019-08-19 07:58:171504 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
1505 "Modifying the configuration in an unsupported way.");
deadbeef293e9262017-01-11 20:28:301506 }
1507
Steve Anton038834f2017-07-14 22:59:591508 // Validate the modified configuration.
1509 RTCError validate_error = ValidateConfiguration(modified_config);
1510 if (!validate_error.ok()) {
Niels Möller2579f0c2019-08-19 07:58:171511 return validate_error;
Steve Anton038834f2017-07-14 22:59:591512 }
1513
deadbeef293e9262017-01-11 20:28:301514 // Note that this isn't possible through chromium, since it's an unsigned
1515 // short in WebIDL.
1516 if (configuration.ice_candidate_pool_size < 0 ||
Wez939eb802018-05-03 10:34:171517 configuration.ice_candidate_pool_size > static_cast<int>(UINT16_MAX)) {
Niels Möller2579f0c2019-08-19 07:58:171518 return RTCError(RTCErrorType::INVALID_RANGE);
deadbeef293e9262017-01-11 20:28:301519 }
1520
1521 // Parse ICE servers before hopping to network thread.
1522 cricket::ServerAddresses stun_servers;
1523 std::vector<cricket::RelayServerConfig> turn_servers;
1524 RTCErrorType parse_error =
1525 ParseIceServers(configuration.servers, &stun_servers, &turn_servers);
1526 if (parse_error != RTCErrorType::NONE) {
Philipp Hancke05fadac2021-11-04 08:13:171527 return RTCError(parse_error, "ICE server parse failed");
deadbeef293e9262017-01-11 20:28:301528 }
Jonas Oreland3c028422019-08-22 14:16:351529 // Add the turn logging id to all turn servers
1530 for (cricket::RelayServerConfig& turn_server : turn_servers) {
1531 turn_server.turn_logging_id = configuration.turn_logging_id;
1532 }
1533
Harald Alvestrand8ebba742018-05-31 12:00:341534 // Note if STUN or TURN servers were supplied.
1535 if (!stun_servers.empty()) {
1536 NoteUsageEvent(UsageEvent::STUN_SERVER_ADDED);
1537 }
1538 if (!turn_servers.empty()) {
1539 NoteUsageEvent(UsageEvent::TURN_SERVER_ADDED);
1540 }
deadbeef293e9262017-01-11 20:28:301541
Niels Möller4bab23f2021-01-18 08:24:331542 const bool has_local_description = local_description() != nullptr;
1543
Tomas Gunnarsson20f74562021-02-04 09:22:501544 const bool needs_ice_restart =
1545 modified_config.servers != configuration_.servers ||
1546 NeedIceRestart(
1547 configuration_.surface_ice_candidates_on_ice_transport_type_changed,
1548 configuration_.type, modified_config.type) ||
1549 modified_config.GetTurnPortPrunePolicy() !=
1550 configuration_.GetTurnPortPrunePolicy();
1551 cricket::IceConfig ice_config = ParseIceConfig(modified_config);
1552
1553 // Apply part of the configuration on the network thread. In theory this
1554 // shouldn't fail.
deadbeef293e9262017-01-11 20:28:301555 if (!network_thread()->Invoke<bool>(
Tomas Gunnarsson20f74562021-02-04 09:22:501556 RTC_FROM_HERE,
1557 [this, needs_ice_restart, &ice_config, &stun_servers, &turn_servers,
1558 &modified_config, has_local_description] {
Harald Alvestrandbc32c562022-02-09 12:08:471559 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson20f74562021-02-04 09:22:501560 // As described in JSEP, calling setConfiguration with new ICE
1561 // servers or candidate policy must set a "needs-ice-restart" bit so
1562 // that the next offer triggers an ICE restart which will pick up
1563 // the changes.
1564 if (needs_ice_restart)
1565 transport_controller_->SetNeedsIceRestartFlag();
1566
1567 transport_controller_->SetIceConfig(ice_config);
Niels Möller4bab23f2021-01-18 08:24:331568 return ReconfigurePortAllocator_n(
1569 stun_servers, turn_servers, modified_config.type,
1570 modified_config.ice_candidate_pool_size,
1571 modified_config.GetTurnPortPrunePolicy(),
1572 modified_config.turn_customizer,
1573 modified_config.stun_candidate_keepalive_interval,
1574 has_local_description);
1575 })) {
Niels Möller2579f0c2019-08-19 07:58:171576 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
1577 "Failed to apply configuration to PortAllocator.");
deadbeef293e9262017-01-11 20:28:301578 }
Honghai Zhang4cedf2b2016-08-31 15:18:111579
Zhi Huangb57e1692018-06-12 18:41:111580 if (configuration_.active_reset_srtp_params !=
1581 modified_config.active_reset_srtp_params) {
Harald Alvestrandbc32c562022-02-09 12:08:471582 // TODO(tommi): merge invokes
1583 network_thread()->Invoke<void>(RTC_FROM_HERE, [this, &modified_config] {
1584 RTC_DCHECK_RUN_ON(network_thread());
1585 transport_controller_->SetActiveResetSrtpParams(
1586 modified_config.active_reset_srtp_params);
1587 });
Zhi Huangb57e1692018-06-12 18:41:111588 }
1589
philipel16cec3b2019-10-25 10:23:021590 if (modified_config.allow_codec_switching.has_value()) {
Tomas Gunnarssond41c2a62020-09-21 13:56:421591 std::vector<cricket::VideoMediaChannel*> channels;
Harald Alvestrande15fb152020-10-19 13:28:051592 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
Tomas Gunnarssond41c2a62020-09-21 13:56:421593 if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO)
Taylor Brandstetter6b381c72020-08-24 20:28:471594 continue;
Tomas Gunnarssond41c2a62020-09-21 13:56:421595
Harald Alvestrand2c761b22022-04-30 16:27:401596 auto* video_channel = transceiver->internal()->channel();
Tomas Gunnarssond41c2a62020-09-21 13:56:421597 if (video_channel)
Harald Alvestrand2c761b22022-04-30 16:27:401598 channels.push_back(static_cast<cricket::VideoMediaChannel*>(
1599 video_channel->media_channel()));
philipel01294f02019-11-14 12:03:251600 }
Tomas Gunnarssond41c2a62020-09-21 13:56:421601
1602 worker_thread()->Invoke<void>(
1603 RTC_FROM_HERE,
1604 [channels = std::move(channels),
1605 allow_codec_switching = *modified_config.allow_codec_switching]() {
1606 for (auto* ch : channels)
1607 ch->SetVideoCodecSwitchingEnabled(allow_codec_switching);
1608 });
philipel16cec3b2019-10-25 10:23:021609 }
1610
deadbeef293e9262017-01-11 20:28:301611 configuration_ = modified_config;
Niels Möller2579f0c2019-08-19 07:58:171612 return RTCError::OK();
buildbot@webrtc.org41451d42014-05-03 05:39:451613}
1614
henrike@webrtc.org28e20752013-07-10 00:45:361615bool PeerConnection::AddIceCandidate(
1616 const IceCandidateInterface* ice_candidate) {
Karl Wiberg744310f2019-02-14 09:18:561617 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431618 return sdp_handler_->AddIceCandidate(ice_candidate);
henrike@webrtc.org28e20752013-07-10 00:45:361619}
1620
Henrik Boströmee6f4f62019-11-06 11:36:121621void PeerConnection::AddIceCandidate(
1622 std::unique_ptr<IceCandidateInterface> candidate,
1623 std::function<void(RTCError)> callback) {
1624 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431625 sdp_handler_->AddIceCandidate(std::move(candidate), callback);
Henrik Boströmee6f4f62019-11-06 11:36:121626}
1627
Honghai Zhang7fb69db2016-03-14 18:59:181628bool PeerConnection::RemoveIceCandidates(
1629 const std::vector<cricket::Candidate>& candidates) {
1630 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
Karl Wiberg2cc368f2019-04-02 09:31:561631 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431632 return sdp_handler_->RemoveIceCandidates(candidates);
Honghai Zhang7fb69db2016-03-14 18:59:181633}
1634
Niels Möller0c4f7be2018-05-07 12:01:371635RTCError PeerConnection::SetBitrate(const BitrateSettings& bitrate) {
Steve Anton978b8762017-09-29 19:15:021636 if (!worker_thread()->IsCurrent()) {
1637 return worker_thread()->Invoke<RTCError>(
Yves Gerey665174f2018-06-19 13:03:051638 RTC_FROM_HERE, [&]() { return SetBitrate(bitrate); });
zstein4b979802017-06-02 21:37:371639 }
Karl Wiberg6cab5c82019-03-26 08:57:011640 RTC_DCHECK_RUN_ON(worker_thread());
zstein4b979802017-06-02 21:37:371641
Niels Möller0c4f7be2018-05-07 12:01:371642 const bool has_min = bitrate.min_bitrate_bps.has_value();
1643 const bool has_start = bitrate.start_bitrate_bps.has_value();
1644 const bool has_max = bitrate.max_bitrate_bps.has_value();
zstein4b979802017-06-02 21:37:371645 if (has_min && *bitrate.min_bitrate_bps < 0) {
1646 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1647 "min_bitrate_bps <= 0");
1648 }
Niels Möller0c4f7be2018-05-07 12:01:371649 if (has_start) {
1650 if (has_min && *bitrate.start_bitrate_bps < *bitrate.min_bitrate_bps) {
zstein4b979802017-06-02 21:37:371651 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
Niels Möller0c4f7be2018-05-07 12:01:371652 "start_bitrate_bps < min_bitrate_bps");
1653 } else if (*bitrate.start_bitrate_bps < 0) {
zstein4b979802017-06-02 21:37:371654 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1655 "curent_bitrate_bps < 0");
1656 }
1657 }
1658 if (has_max) {
Yves Gerey665174f2018-06-19 13:03:051659 if (has_start && *bitrate.max_bitrate_bps < *bitrate.start_bitrate_bps) {
zstein4b979802017-06-02 21:37:371660 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
Niels Möller0c4f7be2018-05-07 12:01:371661 "max_bitrate_bps < start_bitrate_bps");
zstein4b979802017-06-02 21:37:371662 } else if (has_min && *bitrate.max_bitrate_bps < *bitrate.min_bitrate_bps) {
1663 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1664 "max_bitrate_bps < min_bitrate_bps");
1665 } else if (*bitrate.max_bitrate_bps < 0) {
1666 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1667 "max_bitrate_bps < 0");
1668 }
1669 }
1670
zstein4b979802017-06-02 21:37:371671 RTC_DCHECK(call_.get());
Piotr (Peter) Slatala7fbfaa42019-03-18 17:31:541672 call_->SetClientBitratePreferences(bitrate);
zstein4b979802017-06-02 21:37:371673
1674 return RTCError::OK();
1675}
1676
henrika5f6bf242017-11-01 10:06:561677void PeerConnection::SetAudioPlayout(bool playout) {
1678 if (!worker_thread()->IsCurrent()) {
1679 worker_thread()->Invoke<void>(
Niels Möller4bab23f2021-01-18 08:24:331680 RTC_FROM_HERE, [this, playout] { SetAudioPlayout(playout); });
henrika5f6bf242017-11-01 10:06:561681 return;
1682 }
Artem Titovc6c02ef2022-05-09 08:30:091683 auto audio_state =
1684 context_->channel_manager()->media_engine()->voice().GetAudioState();
henrika5f6bf242017-11-01 10:06:561685 audio_state->SetPlayout(playout);
1686}
1687
1688void PeerConnection::SetAudioRecording(bool recording) {
1689 if (!worker_thread()->IsCurrent()) {
1690 worker_thread()->Invoke<void>(
Niels Möller4bab23f2021-01-18 08:24:331691 RTC_FROM_HERE, [this, recording] { SetAudioRecording(recording); });
henrika5f6bf242017-11-01 10:06:561692 return;
1693 }
Artem Titovc6c02ef2022-05-09 08:30:091694 auto audio_state =
1695 context_->channel_manager()->media_engine()->voice().GetAudioState();
henrika5f6bf242017-11-01 10:06:561696 audio_state->SetRecording(recording);
1697}
1698
Henrik Boström4c1e7cc2020-06-11 10:26:531699void PeerConnection::AddAdaptationResource(
1700 rtc::scoped_refptr<Resource> resource) {
1701 if (!worker_thread()->IsCurrent()) {
1702 return worker_thread()->Invoke<void>(RTC_FROM_HERE, [this, resource]() {
1703 return AddAdaptationResource(resource);
1704 });
1705 }
1706 RTC_DCHECK_RUN_ON(worker_thread());
1707 if (!call_) {
1708 // The PeerConnection has been closed.
1709 return;
1710 }
1711 call_->AddAdaptationResource(resource);
1712}
1713
Harald Alvestrand35ba0c52022-05-05 07:37:411714bool PeerConnection::ConfiguredForMedia() const {
Artem Titovc6c02ef2022-05-09 08:30:091715 return context_->channel_manager()->media_engine();
Harald Alvestrand35ba0c52022-05-05 07:37:411716}
1717
Bjorn Tereliusde939432017-11-20 16:38:141718bool PeerConnection::StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
1719 int64_t output_period_ms) {
Bjorn Tereliusde939432017-11-20 16:38:141720 return worker_thread()->Invoke<bool>(
Danil Chapovalov116ffe72019-09-05 08:21:111721 RTC_FROM_HERE,
1722 [this, output = std::move(output), output_period_ms]() mutable {
1723 return StartRtcEventLog_w(std::move(output), output_period_ms);
1724 });
ivoc14d5dbe2016-07-04 14:06:551725}
1726
Niels Möllerf00ca1a2019-05-10 09:33:121727bool PeerConnection::StartRtcEventLog(
1728 std::unique_ptr<RtcEventLogOutput> output) {
Niels Möller695cf6a2019-05-13 10:27:231729 int64_t output_period_ms = webrtc::RtcEventLog::kImmediateOutput;
Jonas Oreland6c7f9842022-04-19 15:24:101730 if (trials().IsEnabled("WebRTC-RtcEventLogNewFormat")) {
Niels Möller695cf6a2019-05-13 10:27:231731 output_period_ms = 5000;
1732 }
1733 return StartRtcEventLog(std::move(output), output_period_ms);
Niels Möllerf00ca1a2019-05-10 09:33:121734}
1735
ivoc14d5dbe2016-07-04 14:06:551736void PeerConnection::StopRtcEventLog() {
Niels Möller4bab23f2021-01-18 08:24:331737 worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] { StopRtcEventLog_w(); });
ivoc14d5dbe2016-07-04 14:06:551738}
1739
Harald Alvestrandad88c882018-11-28 15:47:461740rtc::scoped_refptr<DtlsTransportInterface>
1741PeerConnection::LookupDtlsTransportByMid(const std::string& mid) {
Tomas Gunnarsson2aeab5e2021-02-23 20:36:141742 RTC_DCHECK_RUN_ON(network_thread());
Harald Alvestrandad88c882018-11-28 15:47:461743 return transport_controller_->LookupDtlsTransportByMid(mid);
1744}
1745
Harald Alvestrand4a7b3ac2019-01-17 09:39:401746rtc::scoped_refptr<DtlsTransport>
1747PeerConnection::LookupDtlsTransportByMidInternal(const std::string& mid) {
Karl Wiberg2cc368f2019-04-02 09:31:561748 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrandbc32c562022-02-09 12:08:471749 // TODO(bugs.webrtc.org/9987): Avoid the thread jump.
1750 // This might be done by caching the value on the signaling thread.
1751 return network_thread()->Invoke<rtc::scoped_refptr<DtlsTransport>>(
1752 RTC_FROM_HERE, [this, mid]() {
1753 RTC_DCHECK_RUN_ON(network_thread());
1754 return transport_controller_->LookupDtlsTransportByMid(mid);
1755 });
Harald Alvestrand4a7b3ac2019-01-17 09:39:401756}
1757
Harald Alvestrandc85328f2019-02-28 06:51:001758rtc::scoped_refptr<SctpTransportInterface> PeerConnection::GetSctpTransport()
1759 const {
Tomas Gunnarsson92eebef2021-02-10 12:05:441760 RTC_DCHECK_RUN_ON(network_thread());
1761 if (!sctp_mid_n_)
Bjorn A Mellembc3eebc2019-09-23 21:53:541762 return nullptr;
Tomas Gunnarsson92eebef2021-02-10 12:05:441763
1764 return transport_controller_->GetSctpTransport(*sctp_mid_n_);
Harald Alvestrandc85328f2019-02-28 06:51:001765}
1766
henrike@webrtc.org28e20752013-07-10 00:45:361767const SessionDescriptionInterface* PeerConnection::local_description() const {
Karl Wiberg739506e2019-04-03 09:37:281768 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431769 return sdp_handler_->local_description();
henrike@webrtc.org28e20752013-07-10 00:45:361770}
1771
1772const SessionDescriptionInterface* PeerConnection::remote_description() const {
Karl Wiberg739506e2019-04-03 09:37:281773 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431774 return sdp_handler_->remote_description();
henrike@webrtc.org28e20752013-07-10 00:45:361775}
1776
deadbeeffe4a8a42016-12-21 01:56:171777const SessionDescriptionInterface* PeerConnection::current_local_description()
1778 const {
Karl Wiberg739506e2019-04-03 09:37:281779 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431780 return sdp_handler_->current_local_description();
deadbeeffe4a8a42016-12-21 01:56:171781}
1782
1783const SessionDescriptionInterface* PeerConnection::current_remote_description()
1784 const {
Karl Wiberg739506e2019-04-03 09:37:281785 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431786 return sdp_handler_->current_remote_description();
deadbeeffe4a8a42016-12-21 01:56:171787}
1788
1789const SessionDescriptionInterface* PeerConnection::pending_local_description()
1790 const {
Karl Wiberg739506e2019-04-03 09:37:281791 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431792 return sdp_handler_->pending_local_description();
deadbeeffe4a8a42016-12-21 01:56:171793}
1794
1795const SessionDescriptionInterface* PeerConnection::pending_remote_description()
1796 const {
Karl Wiberg739506e2019-04-03 09:37:281797 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:431798 return sdp_handler_->pending_remote_description();
deadbeeffe4a8a42016-12-21 01:56:171799}
1800
henrike@webrtc.org28e20752013-07-10 00:45:361801void PeerConnection::Close() {
Karl Wiberg744310f2019-02-14 09:18:561802 RTC_DCHECK_RUN_ON(signaling_thread());
Peter Boström1a9d6152015-12-08 21:15:171803 TRACE_EVENT0("webrtc", "PeerConnection::Close");
Harald Alvestrandcdcfab02020-09-28 13:02:071804
Tommife041642021-04-07 08:08:281805 RTC_LOG_THREAD_BLOCK_COUNT();
1806
Harald Alvestrandcdcfab02020-09-28 13:02:071807 if (IsClosed()) {
1808 return;
1809 }
henrike@webrtc.org28e20752013-07-10 00:45:361810 // Update stats here so that we have the most recent stats for tracks and
1811 // streams before the channels are closed.
tommi@webrtc.org03505bc2014-07-14 20:15:261812 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:361813
Harald Alvestrandcdcfab02020-09-28 13:02:071814 ice_connection_state_ = PeerConnectionInterface::kIceConnectionClosed;
1815 Observer()->OnIceConnectionChange(ice_connection_state_);
1816 standardized_ice_connection_state_ =
1817 PeerConnectionInterface::IceConnectionState::kIceConnectionClosed;
1818 connection_state_ = PeerConnectionInterface::PeerConnectionState::kClosed;
1819 Observer()->OnConnectionChange(connection_state_);
1820
Harald Alvestrand9cd199d2020-10-27 07:10:431821 sdp_handler_->Close();
Harald Alvestrandcdcfab02020-09-28 13:02:071822
Harald Alvestrand8ebba742018-05-31 12:00:341823 NoteUsageEvent(UsageEvent::CLOSE_CALLED);
Steve Anton3fe1b152017-12-12 18:20:081824
Artem Titovc6c02ef2022-05-09 08:30:091825 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
1826 transceiver->internal()->SetPeerConnectionClosed();
1827 if (!transceiver->stopped())
1828 transceiver->StopInternal();
Steve Anton8af21862017-12-15 19:20:131829 }
Artem Titovc6c02ef2022-05-09 08:30:091830
Steve Anton25cfeb92018-04-26 18:44:001831 // Ensure that all asynchronous stats requests are completed before destroying
1832 // the transport controller below.
1833 if (stats_collector_) {
1834 stats_collector_->WaitForPendingRequest();
1835 }
1836
1837 // Don't destroy BaseChannels until after stats has been cleaned up so that
1838 // the last stats request can still read from the channels.
Harald Alvestrand9cd199d2020-10-27 07:10:431839 sdp_handler_->DestroyAllChannels();
Steve Anton75737c02017-11-06 18:37:171840
Qingsi Wang93a84392018-01-31 01:13:091841 // The event log is used in the transport controller, which must be outlived
1842 // by the former. CreateOffer by the peer connection is implemented
1843 // asynchronously and if the peer connection is closed without resetting the
1844 // WebRTC session description factory, the session description factory would
1845 // call the transport controller.
Harald Alvestrand9cd199d2020-10-27 07:10:431846 sdp_handler_->ResetSessionDescFactory();
Artem Titovc6c02ef2022-05-09 08:30:091847 rtp_manager_->Close();
Qingsi Wang93a84392018-01-31 01:13:091848
Tomas Gunnarsson92eebef2021-02-10 12:05:441849 network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
Tomas Gunnarssond69e0702021-04-07 13:14:431850 // Data channels will already have been unset via the DestroyAllChannels()
1851 // call above, which triggers a call to TeardownDataChannelTransport_n().
1852 // TODO(tommi): ^^ That's not exactly optimal since this is yet another
1853 // blocking hop to the network thread during Close(). Further still, the
1854 // voice/video/data channels will be cleared on the worker thread.
Harald Alvestrandbc32c562022-02-09 12:08:471855 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarsson92eebef2021-02-10 12:05:441856 transport_controller_.reset();
1857 port_allocator_->DiscardCandidatePool();
1858 if (network_thread_safety_) {
1859 network_thread_safety_->SetNotAlive();
Tomas Gunnarsson92eebef2021-02-10 12:05:441860 }
1861 });
nisseeaabdf62017-05-05 09:23:021862
Steve Anton978b8762017-09-29 19:15:021863 worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
Karl Wibergb03ab712019-02-14 10:59:571864 RTC_DCHECK_RUN_ON(worker_thread());
Tommic3257d02021-02-10 17:40:081865 worker_thread_safety_->SetNotAlive();
eladalon248fd4f2017-09-06 12:18:151866 call_.reset();
1867 // The event log must outlive call (and any other object that uses it).
1868 event_log_.reset();
1869 });
Harald Alvestrand8ebba742018-05-31 12:00:341870 ReportUsagePattern();
Harald Alvestrand7a1c7f72018-08-01 08:50:161871 // The .h file says that observer can be discarded after close() returns.
1872 // Make sure this is true.
1873 observer_ = nullptr;
Tomas Gunnarsson2efb8a52021-04-01 14:26:571874
1875 // Signal shutdown to the sdp handler. This invalidates weak pointers for
1876 // internal pending callbacks.
1877 sdp_handler_->PrepareForShutdown();
henrike@webrtc.org28e20752013-07-10 00:45:361878}
1879
Steve Antonba818672017-11-06 18:21:571880void PeerConnection::SetIceConnectionState(IceConnectionState new_state) {
Harald Alvestrandcdcfab02020-09-28 13:02:071881 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Antonba818672017-11-06 18:21:571882 if (ice_connection_state_ == new_state) {
1883 return;
1884 }
1885
deadbeefcbecd352015-09-23 18:50:271886 // After transitioning to "closed", ignore any additional states from
Steve Antonba818672017-11-06 18:21:571887 // TransportController (such as "disconnected").
deadbeefab9b2d12015-10-14 18:33:111888 if (IsClosed()) {
deadbeefcbecd352015-09-23 18:50:271889 return;
1890 }
Steve Antonba818672017-11-06 18:21:571891
Mirko Bonadei675513b2017-11-09 10:09:251892 RTC_LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
1893 << " => " << new_state;
Steve Antonba818672017-11-06 18:21:571894 RTC_DCHECK(ice_connection_state_ !=
1895 PeerConnectionInterface::kIceConnectionClosed);
1896
henrike@webrtc.org28e20752013-07-10 00:45:361897 ice_connection_state_ = new_state;
Harald Alvestrand7a1c7f72018-08-01 08:50:161898 Observer()->OnIceConnectionChange(ice_connection_state_);
henrike@webrtc.org28e20752013-07-10 00:45:361899}
1900
Alex Loiko9289eda2018-11-23 16:18:591901void PeerConnection::SetStandardizedIceConnectionState(
1902 PeerConnectionInterface::IceConnectionState new_state) {
Qingsi Wang36e31472019-05-29 18:37:261903 if (standardized_ice_connection_state_ == new_state) {
Alex Loiko9289eda2018-11-23 16:18:591904 return;
Qingsi Wang36e31472019-05-29 18:37:261905 }
1906
1907 if (IsClosed()) {
Alex Loiko9289eda2018-11-23 16:18:591908 return;
Qingsi Wang36e31472019-05-29 18:37:261909 }
1910
1911 RTC_LOG(LS_INFO) << "Changing standardized IceConnectionState "
1912 << standardized_ice_connection_state_ << " => " << new_state;
1913
Alex Loiko9289eda2018-11-23 16:18:591914 standardized_ice_connection_state_ = new_state;
Jonas Olsson12046902018-12-06 10:25:141915 Observer()->OnStandardizedIceConnectionChange(new_state);
Alex Loiko9289eda2018-11-23 16:18:591916}
1917
Jonas Olsson635474e2018-10-18 13:58:171918void PeerConnection::SetConnectionState(
1919 PeerConnectionInterface::PeerConnectionState new_state) {
Jonas Olsson635474e2018-10-18 13:58:171920 if (connection_state_ == new_state)
1921 return;
1922 if (IsClosed())
1923 return;
1924 connection_state_ = new_state;
1925 Observer()->OnConnectionChange(new_state);
Philipp Hanckebb8f32f2021-02-04 20:50:501926
Philipp Hanckecd0373f2021-02-24 10:04:301927 if (new_state == PeerConnectionState::kConnected && !was_ever_connected_) {
1928 was_ever_connected_ = true;
1929
1930 // The first connection state change to connected happens once per
1931 // connection which makes it a good point to report metrics.
Philipp Hanckebb8f32f2021-02-04 20:50:501932 // Record bundle-policy from configuration. Done here from
1933 // connectionStateChange to limit to actually established connections.
1934 BundlePolicyUsage policy = kBundlePolicyUsageMax;
1935 switch (configuration_.bundle_policy) {
1936 case kBundlePolicyBalanced:
1937 policy = kBundlePolicyUsageBalanced;
1938 break;
1939 case kBundlePolicyMaxBundle:
1940 policy = kBundlePolicyUsageMaxBundle;
1941 break;
1942 case kBundlePolicyMaxCompat:
1943 policy = kBundlePolicyUsageMaxCompat;
1944 break;
1945 }
1946 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.BundlePolicy", policy,
1947 kBundlePolicyUsageMax);
Philipp Hancke89736552021-03-05 11:07:051948
1949 // Record configured ice candidate pool size depending on the
1950 // BUNDLE policy. See
1951 // https://w3c.github.io/webrtc-pc/#dom-rtcconfiguration-icecandidatepoolsize
1952 // The ICE candidate pool size is an optimization and it may be desirable
1953 // to restrict the maximum size of the pre-gathered candidates.
1954 switch (configuration_.bundle_policy) {
1955 case kBundlePolicyBalanced:
1956 RTC_HISTOGRAM_COUNTS_LINEAR(
1957 "WebRTC.PeerConnection.CandidatePoolUsage.Balanced",
1958 configuration_.ice_candidate_pool_size, 0, 255, 256);
1959 break;
1960 case kBundlePolicyMaxBundle:
1961 RTC_HISTOGRAM_COUNTS_LINEAR(
1962 "WebRTC.PeerConnection.CandidatePoolUsage.MaxBundle",
1963 configuration_.ice_candidate_pool_size, 0, 255, 256);
1964 break;
1965 case kBundlePolicyMaxCompat:
1966 RTC_HISTOGRAM_COUNTS_LINEAR(
1967 "WebRTC.PeerConnection.CandidatePoolUsage.MaxCompat",
1968 configuration_.ice_candidate_pool_size, 0, 255, 256);
1969 break;
1970 }
Philipp Hancke1b4807f2021-06-11 09:49:541971
1972 // Record whether there was a local or remote provisional answer.
1973 ProvisionalAnswerUsage pranswer = kProvisionalAnswerNotUsed;
1974 if (local_description()->GetType() == SdpType::kPrAnswer) {
1975 pranswer = kProvisionalAnswerLocal;
1976 } else if (remote_description()->GetType() == SdpType::kPrAnswer) {
1977 pranswer = kProvisionalAnswerRemote;
1978 }
1979 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.ProvisionalAnswer",
1980 pranswer, kProvisionalAnswerMax);
Philipp Hanckef59d9fb2021-10-13 09:34:151981
1982 // Record the number of configured ICE servers for connected connections.
1983 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.PeerConnection.IceServers.Connected",
1984 configuration_.servers.size(), 0, 31, 32);
Philipp Hanckebb8f32f2021-02-04 20:50:501985 }
Jonas Olsson635474e2018-10-18 13:58:171986}
1987
henrike@webrtc.org28e20752013-07-10 00:45:361988void PeerConnection::OnIceGatheringChange(
1989 PeerConnectionInterface::IceGatheringState new_state) {
1990 if (IsClosed()) {
1991 return;
1992 }
1993 ice_gathering_state_ = new_state;
Harald Alvestrand7a1c7f72018-08-01 08:50:161994 Observer()->OnIceGatheringChange(ice_gathering_state_);
henrike@webrtc.org28e20752013-07-10 00:45:361995}
1996
jbauch81bf7b02017-03-25 15:31:121997void PeerConnection::OnIceCandidate(
1998 std::unique_ptr<IceCandidateInterface> candidate) {
zhihuang29ff8442016-07-27 18:07:251999 if (IsClosed()) {
2000 return;
2001 }
Qingsi Wang1ba5dec2019-08-19 18:57:172002 ReportIceCandidateCollected(candidate->candidate());
Harald Alvestrand7a1c7f72018-08-01 08:50:162003 Observer()->OnIceCandidate(candidate.get());
henrike@webrtc.org28e20752013-07-10 00:45:362004}
2005
Eldar Rello0095d372019-12-02 20:22:072006void PeerConnection::OnIceCandidateError(const std::string& address,
2007 int port,
Eldar Relloda13ea22019-06-01 09:23:432008 const std::string& url,
2009 int error_code,
2010 const std::string& error_text) {
2011 if (IsClosed()) {
2012 return;
2013 }
Eldar Rello0095d372019-12-02 20:22:072014 Observer()->OnIceCandidateError(address, port, url, error_code, error_text);
Eldar Relloda13ea22019-06-01 09:23:432015}
2016
Honghai Zhang7fb69db2016-03-14 18:59:182017void PeerConnection::OnIceCandidatesRemoved(
2018 const std::vector<cricket::Candidate>& candidates) {
zhihuang29ff8442016-07-27 18:07:252019 if (IsClosed()) {
2020 return;
2021 }
Harald Alvestrand7a1c7f72018-08-01 08:50:162022 Observer()->OnIceCandidatesRemoved(candidates);
Honghai Zhang7fb69db2016-03-14 18:59:182023}
2024
Alex Drake00c7ecf2019-08-06 17:54:472025void PeerConnection::OnSelectedCandidatePairChanged(
2026 const cricket::CandidatePairChangeEvent& event) {
2027 if (IsClosed()) {
2028 return;
2029 }
Qingsi Wang1ba5dec2019-08-19 18:57:172030
Qingsi Wangcc46b10c2019-09-12 18:19:012031 if (event.selected_candidate_pair.local_candidate().type() ==
2032 LOCAL_PORT_TYPE &&
2033 event.selected_candidate_pair.remote_candidate().type() ==
2034 LOCAL_PORT_TYPE) {
2035 NoteUsageEvent(UsageEvent::DIRECT_CONNECTION_SELECTED);
2036 }
2037
Alex Drake00c7ecf2019-08-06 17:54:472038 Observer()->OnIceSelectedCandidatePairChanged(event);
2039}
2040
Danil Chapovalov66cadcc2018-06-19 14:47:432041absl::optional<std::string> PeerConnection::GetDataMid() const {
Harald Alvestrandcdcfab02020-09-28 13:02:072042 RTC_DCHECK_RUN_ON(signaling_thread());
Florent Castelli516e2842021-04-19 13:29:502043 return sctp_mid_s_;
Steve Antonfa2260d2017-12-29 00:38:232044}
2045
Tomas Gunnarsson92eebef2021-02-10 12:05:442046void PeerConnection::SetSctpDataMid(const std::string& mid) {
2047 RTC_DCHECK_RUN_ON(signaling_thread());
2048 sctp_mid_s_ = mid;
2049}
2050
2051void PeerConnection::ResetSctpDataMid() {
2052 RTC_DCHECK_RUN_ON(signaling_thread());
2053 sctp_mid_s_.reset();
2054 sctp_transport_name_s_.clear();
2055}
2056
Taylor Brandstetter3a034e12020-07-09 22:32:342057void PeerConnection::OnSctpDataChannelClosed(DataChannelInterface* channel) {
Harald Alvestrand00cf34c2019-12-02 08:56:022058 // Since data_channel_controller doesn't do signals, this
2059 // signal is relayed here.
Taylor Brandstetter3a034e12020-07-09 22:32:342060 data_channel_controller_.OnSctpDataChannelClosed(
2061 static_cast<SctpDataChannel*>(channel));
deadbeefab9b2d12015-10-14 18:33:112062}
2063
Karl Wibergfb3be392019-03-22 13:13:222064PeerConnection::InitializePortAllocatorResult
2065PeerConnection::InitializePortAllocator_n(
Harald Alvestrandb2a74782018-06-28 11:54:072066 const cricket::ServerAddresses& stun_servers,
2067 const std::vector<cricket::RelayServerConfig>& turn_servers,
Taylor Brandstettera1c30352016-05-13 15:15:112068 const RTCConfiguration& configuration) {
Karl Wibergfb3be392019-03-22 13:13:222069 RTC_DCHECK_RUN_ON(network_thread());
2070
Taylor Brandstetterf8e65772016-06-28 00:20:152071 port_allocator_->Initialize();
Taylor Brandstettera1c30352016-05-13 15:15:112072 // To handle both internal and externally created port allocator, we will
2073 // enable BUNDLE here.
Karl Wibergfb3be392019-03-22 13:13:222074 int port_allocator_flags = port_allocator_->flags();
2075 port_allocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
2076 cricket::PORTALLOCATOR_ENABLE_IPV6 |
2077 cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
Taylor Brandstettera1c30352016-05-13 15:15:112078 // If the disable-IPv6 flag was specified, we'll not override it
2079 // by experiment.
2080 if (configuration.disable_ipv6) {
Karl Wibergfb3be392019-03-22 13:13:222081 port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
Jonas Oreland6c7f9842022-04-19 15:24:102082 } else if (trials().IsDisabled("WebRTC-IPv6Default")) {
Karl Wibergfb3be392019-03-22 13:13:222083 port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
Taylor Brandstettera1c30352016-05-13 15:15:112084 }
zhihuangb09b3f92017-03-07 22:40:512085 if (configuration.disable_ipv6_on_wifi) {
Karl Wibergfb3be392019-03-22 13:13:222086 port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI);
Mirko Bonadei675513b2017-11-09 10:09:252087 RTC_LOG(LS_INFO) << "IPv6 candidates on Wi-Fi are disabled.";
zhihuangb09b3f92017-03-07 22:40:512088 }
2089
Taylor Brandstettera1c30352016-05-13 15:15:112090 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
Karl Wibergfb3be392019-03-22 13:13:222091 port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
Mirko Bonadei675513b2017-11-09 10:09:252092 RTC_LOG(LS_INFO) << "TCP candidates are disabled.";
Taylor Brandstettera1c30352016-05-13 15:15:112093 }
2094
honghaiz60347052016-06-01 01:29:122095 if (configuration.candidate_network_policy ==
2096 kCandidateNetworkPolicyLowCost) {
Karl Wibergfb3be392019-03-22 13:13:222097 port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
Mirko Bonadei675513b2017-11-09 10:09:252098 RTC_LOG(LS_INFO) << "Do not gather candidates on high-cost networks";
honghaiz60347052016-06-01 01:29:122099 }
2100
Daniel Lazarenko2870b0a2018-01-25 09:30:222101 if (configuration.disable_link_local_networks) {
Karl Wibergfb3be392019-03-22 13:13:222102 port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS;
Daniel Lazarenko2870b0a2018-01-25 09:30:222103 RTC_LOG(LS_INFO) << "Disable candidates on link-local network interfaces.";
2104 }
2105
Karl Wibergfb3be392019-03-22 13:13:222106 port_allocator_->set_flags(port_allocator_flags);
Taylor Brandstettera1c30352016-05-13 15:15:112107 // No step delay is used while allocating ports.
2108 port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
Qingsi Wangc129c352019-04-18 17:41:582109 port_allocator_->SetCandidateFilter(
Taylor Brandstettera1c30352016-05-13 15:15:112110 ConvertIceTransportTypeToCandidateFilter(configuration.type));
deadbeefd21eab3e2017-07-26 23:50:112111 port_allocator_->set_max_ipv6_networks(configuration.max_ipv6_networks);
Taylor Brandstettera1c30352016-05-13 15:15:112112
Harald Alvestrandb2a74782018-06-28 11:54:072113 auto turn_servers_copy = turn_servers;
Benjamin Wright6f80f092018-08-14 00:06:262114 for (auto& turn_server : turn_servers_copy) {
2115 turn_server.tls_cert_verifier = tls_cert_verifier_.get();
Benjamin Wrightd6f86e82018-05-08 20:12:252116 }
Taylor Brandstettera1c30352016-05-13 15:15:112117 // Call this last since it may create pooled allocator sessions using the
2118 // properties set above.
Qingsi Wangdb53f8e2018-02-20 22:45:492119 port_allocator_->SetConfiguration(
Benjamin Wright6f80f092018-08-14 00:06:262120 stun_servers, std::move(turn_servers_copy),
Honghai Zhangf8998cf2019-10-14 18:27:502121 configuration.ice_candidate_pool_size,
2122 configuration.GetTurnPortPrunePolicy(), configuration.turn_customizer,
Qingsi Wangdb53f8e2018-02-20 22:45:492123 configuration.stun_candidate_keepalive_interval);
Karl Wibergfb3be392019-03-22 13:13:222124
2125 InitializePortAllocatorResult res;
2126 res.enable_ipv6 = port_allocator_flags & cricket::PORTALLOCATOR_ENABLE_IPV6;
2127 return res;
Taylor Brandstettera1c30352016-05-13 15:15:112128}
2129
deadbeef91dd5672016-05-18 23:55:302130bool PeerConnection::ReconfigurePortAllocator_n(
deadbeef293e9262017-01-11 20:28:302131 const cricket::ServerAddresses& stun_servers,
2132 const std::vector<cricket::RelayServerConfig>& turn_servers,
2133 IceTransportsType type,
2134 int candidate_pool_size,
Honghai Zhangf8998cf2019-10-14 18:27:502135 PortPrunePolicy turn_port_prune_policy,
Qingsi Wangdb53f8e2018-02-20 22:45:492136 webrtc::TurnCustomizer* turn_customizer,
Karl Wiberg739506e2019-04-03 09:37:282137 absl::optional<int> stun_candidate_keepalive_interval,
2138 bool have_local_description) {
Harald Alvestrandf598e492020-11-04 05:54:102139 RTC_DCHECK_RUN_ON(network_thread());
Qingsi Wangc129c352019-04-18 17:41:582140 port_allocator_->SetCandidateFilter(
deadbeef293e9262017-01-11 20:28:302141 ConvertIceTransportTypeToCandidateFilter(type));
Qingsi Wanga2d60672018-04-11 23:57:452142 // According to JSEP, after setLocalDescription, changing the candidate pool
2143 // size is not allowed, and changing the set of ICE servers will not result
2144 // in new candidates being gathered.
Karl Wiberg739506e2019-04-03 09:37:282145 if (have_local_description) {
Qingsi Wanga2d60672018-04-11 23:57:452146 port_allocator_->FreezeCandidatePool();
2147 }
Benjamin Wright6f80f092018-08-14 00:06:262148 // Add the custom tls turn servers if they exist.
2149 auto turn_servers_copy = turn_servers;
2150 for (auto& turn_server : turn_servers_copy) {
2151 turn_server.tls_cert_verifier = tls_cert_verifier_.get();
2152 }
Taylor Brandstettera1c30352016-05-13 15:15:112153 // Call this last since it may create pooled allocator sessions using the
2154 // candidate filter set above.
deadbeef6de92f92016-12-13 02:49:322155 return port_allocator_->SetConfiguration(
Benjamin Wright6f80f092018-08-14 00:06:262156 stun_servers, std::move(turn_servers_copy), candidate_pool_size,
Honghai Zhangf8998cf2019-10-14 18:27:502157 turn_port_prune_policy, turn_customizer,
2158 stun_candidate_keepalive_interval);
Taylor Brandstettera1c30352016-05-13 15:15:112159}
2160
Elad Alon99c3fe52017-10-13 14:29:402161bool PeerConnection::StartRtcEventLog_w(
Bjorn Tereliusde939432017-11-20 16:38:142162 std::unique_ptr<RtcEventLogOutput> output,
2163 int64_t output_period_ms) {
Karl Wibergb03ab712019-02-14 10:59:572164 RTC_DCHECK_RUN_ON(worker_thread());
zhihuang77985012017-02-07 23:45:162165 if (!event_log_) {
2166 return false;
2167 }
Bjorn Tereliusde939432017-11-20 16:38:142168 return event_log_->StartLogging(std::move(output), output_period_ms);
ivoc14d5dbe2016-07-04 14:06:552169}
2170
2171void PeerConnection::StopRtcEventLog_w() {
Karl Wibergb03ab712019-02-14 10:59:572172 RTC_DCHECK_RUN_ON(worker_thread());
zhihuang77985012017-02-07 23:45:162173 if (event_log_) {
2174 event_log_->StopLogging();
2175 }
ivoc14d5dbe2016-07-04 14:06:552176}
nisseeaabdf62017-05-05 09:23:022177
Steve Anton75737c02017-11-06 18:37:172178bool PeerConnection::GetSctpSslRole(rtc::SSLRole* role) {
Bjorn Mellem175aa2e2018-11-08 19:23:222179 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Anton75737c02017-11-06 18:37:172180 if (!local_description() || !remote_description()) {
Harald Alvestrand977b2652019-12-12 12:40:502181 RTC_LOG(LS_VERBOSE)
Mirko Bonadei675513b2017-11-09 10:09:252182 << "Local and Remote descriptions must be applied to get the "
Jonas Olsson45cc8902018-02-13 09:37:072183 "SSL Role of the SCTP transport.";
Steve Anton75737c02017-11-06 18:37:172184 return false;
2185 }
Harald Alvestrand00cf34c2019-12-02 08:56:022186 if (!data_channel_controller_.data_channel_transport()) {
Mirko Bonadei675513b2017-11-09 10:09:252187 RTC_LOG(LS_INFO) << "Non-rejected SCTP m= section is needed to get the "
Jonas Olsson45cc8902018-02-13 09:37:072188 "SSL Role of the SCTP transport.";
Steve Anton75737c02017-11-06 18:37:172189 return false;
2190 }
2191
Bjorn Mellem175aa2e2018-11-08 19:23:222192 absl::optional<rtc::SSLRole> dtls_role;
Harald Alvestrand7a829a82020-02-12 06:38:212193 if (sctp_mid_s_) {
Harald Alvestrandbc32c562022-02-09 12:08:472194 dtls_role = network_thread()->Invoke<absl::optional<rtc::SSLRole>>(
2195 RTC_FROM_HERE, [this] {
2196 RTC_DCHECK_RUN_ON(network_thread());
2197 return transport_controller_->GetDtlsRole(*sctp_mid_n_);
2198 });
Harald Alvestrand9cd199d2020-10-27 07:10:432199 if (!dtls_role && sdp_handler_->is_caller().has_value()) {
Harald Alvestrand321ec3b2022-02-10 13:42:182200 // This works fine if we are the offerer, but can be a mistake if
Harald Alvestrand06c87a12022-02-11 13:12:162201 // we are the answerer and the remote offer is ACTIVE. In that
Harald Alvestrand321ec3b2022-02-10 13:42:182202 // case, we will guess the role wrong.
2203 // TODO(bugs.webrtc.org/13668): Check if this actually happens.
Harald Alvestrand06c87a12022-02-11 13:12:162204 RTC_LOG(LS_ERROR)
2205 << "Possible risk: DTLS role guesser is active, is_caller is "
2206 << *sdp_handler_->is_caller();
Harald Alvestrand9cd199d2020-10-27 07:10:432207 dtls_role =
2208 *sdp_handler_->is_caller() ? rtc::SSL_SERVER : rtc::SSL_CLIENT;
Bjorn A Mellembc3eebc2019-09-23 21:53:542209 }
Harald Alvestrand321ec3b2022-02-10 13:42:182210 if (dtls_role) {
2211 *role = *dtls_role;
2212 return true;
2213 }
Zhi Huange830e682018-03-30 17:48:352214 }
2215 return false;
Steve Anton75737c02017-11-06 18:37:172216}
2217
2218bool PeerConnection::GetSslRole(const std::string& content_name,
2219 rtc::SSLRole* role) {
Karl Wiberg2cc368f2019-04-02 09:31:562220 RTC_DCHECK_RUN_ON(signaling_thread());
Steve Anton75737c02017-11-06 18:37:172221 if (!local_description() || !remote_description()) {
Mirko Bonadei675513b2017-11-09 10:09:252222 RTC_LOG(LS_INFO)
2223 << "Local and Remote descriptions must be applied to get the "
Jonas Olsson45cc8902018-02-13 09:37:072224 "SSL Role of the session.";
Steve Anton75737c02017-11-06 18:37:172225 return false;
2226 }
2227
Harald Alvestrandbc32c562022-02-09 12:08:472228 auto dtls_role = network_thread()->Invoke<absl::optional<rtc::SSLRole>>(
2229 RTC_FROM_HERE, [this, content_name]() {
2230 RTC_DCHECK_RUN_ON(network_thread());
2231 return transport_controller_->GetDtlsRole(content_name);
2232 });
Zhi Huange830e682018-03-30 17:48:352233 if (dtls_role) {
2234 *role = *dtls_role;
2235 return true;
2236 }
2237 return false;
Steve Anton75737c02017-11-06 18:37:172238}
2239
Steve Anton75737c02017-11-06 18:37:172240bool PeerConnection::GetTransportDescription(
2241 const SessionDescription* description,
2242 const std::string& content_name,
2243 cricket::TransportDescription* tdesc) {
2244 if (!description || !tdesc) {
2245 return false;
2246 }
2247 const TransportInfo* transport_info =
2248 description->GetTransportInfoByName(content_name);
2249 if (!transport_info) {
2250 return false;
2251 }
2252 *tdesc = transport_info->description;
2253 return true;
2254}
2255
Taylor Brandstetter3a034e12020-07-09 22:32:342256std::vector<DataChannelStats> PeerConnection::GetDataChannelStats() const {
Tomas Gunnarsson2e94de52020-06-16 14:54:102257 RTC_DCHECK_RUN_ON(signaling_thread());
2258 return data_channel_controller_.GetDataChannelStats();
2259}
2260
Danil Chapovalov66cadcc2018-06-19 14:47:432261absl::optional<std::string> PeerConnection::sctp_transport_name() const {
Karl Wiberg2cc368f2019-04-02 09:31:562262 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrandbc32c562022-02-09 12:08:472263 if (sctp_mid_s_ && transport_controller_copy_)
Tomas Gunnarsson92eebef2021-02-10 12:05:442264 return sctp_transport_name_s_;
Danil Chapovalov66cadcc2018-06-19 14:47:432265 return absl::optional<std::string>();
Zhi Huange830e682018-03-30 17:48:352266}
2267
Tomas Gunnarssonbfd9ba82021-04-18 09:55:572268absl::optional<std::string> PeerConnection::sctp_mid() const {
2269 RTC_DCHECK_RUN_ON(signaling_thread());
2270 return sctp_mid_s_;
2271}
2272
Qingsi Wang72a43a12018-02-21 00:03:182273cricket::CandidateStatsList PeerConnection::GetPooledCandidateStats() const {
Tomas Gunnarssone1c8a432021-04-08 13:15:282274 RTC_DCHECK_RUN_ON(network_thread());
2275 if (!network_thread_safety_->alive())
2276 return {};
Qingsi Wang72a43a12018-02-21 00:03:182277 cricket::CandidateStatsList candidate_states_list;
Tomas Gunnarssone1c8a432021-04-08 13:15:282278 port_allocator_->GetCandidateStatsFromPooledSessions(&candidate_states_list);
Qingsi Wang72a43a12018-02-21 00:03:182279 return candidate_states_list;
2280}
2281
Steve Anton5dfde182018-02-06 18:34:402282std::map<std::string, cricket::TransportStats>
2283PeerConnection::GetTransportStatsByNames(
2284 const std::set<std::string>& transport_names) {
Markus Handell518669d2021-06-07 11:30:462285 TRACE_EVENT0("webrtc", "PeerConnection::GetTransportStatsByNames");
Karl Wiberg2cc368f2019-04-02 09:31:562286 RTC_DCHECK_RUN_ON(network_thread());
Tomas Gunnarssone1c8a432021-04-08 13:15:282287 if (!network_thread_safety_->alive())
2288 return {};
2289
2290 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
Steve Anton5dfde182018-02-06 18:34:402291 std::map<std::string, cricket::TransportStats> transport_stats_by_name;
2292 for (const std::string& transport_name : transport_names) {
2293 cricket::TransportStats transport_stats;
2294 bool success =
2295 transport_controller_->GetStats(transport_name, &transport_stats);
2296 if (success) {
2297 transport_stats_by_name[transport_name] = std::move(transport_stats);
2298 } else {
2299 RTC_LOG(LS_ERROR) << "Failed to get transport stats for transport_name="
2300 << transport_name;
2301 }
2302 }
2303 return transport_stats_by_name;
Steve Anton75737c02017-11-06 18:37:172304}
2305
2306bool PeerConnection::GetLocalCertificate(
2307 const std::string& transport_name,
2308 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
Tomas Gunnarssone1c8a432021-04-08 13:15:282309 RTC_DCHECK_RUN_ON(network_thread());
2310 if (!network_thread_safety_->alive() || !certificate) {
Zhi Huange830e682018-03-30 17:48:352311 return false;
2312 }
2313 *certificate = transport_controller_->GetLocalCertificate(transport_name);
2314 return *certificate != nullptr;
Steve Anton75737c02017-11-06 18:37:172315}
2316
Taylor Brandstetterc3928662018-02-23 21:04:512317std::unique_ptr<rtc::SSLCertChain> PeerConnection::GetRemoteSSLCertChain(
Steve Anton75737c02017-11-06 18:37:172318 const std::string& transport_name) {
Tomas Gunnarssone1c8a432021-04-08 13:15:282319 RTC_DCHECK_RUN_ON(network_thread());
Taylor Brandstetterc3928662018-02-23 21:04:512320 return transport_controller_->GetRemoteSSLCertChain(transport_name);
Steve Anton75737c02017-11-06 18:37:172321}
2322
Steve Anton75737c02017-11-06 18:37:172323bool PeerConnection::IceRestartPending(const std::string& content_name) const {
Karl Wibergf73f7d62019-04-08 13:36:532324 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:432325 return sdp_handler_->IceRestartPending(content_name);
Steve Anton75737c02017-11-06 18:37:172326}
2327
Steve Anton75737c02017-11-06 18:37:172328bool PeerConnection::NeedsIceRestart(const std::string& content_name) const {
Tommic3257d02021-02-10 17:40:082329 return network_thread()->Invoke<bool>(RTC_FROM_HERE, [this, &content_name] {
2330 RTC_DCHECK_RUN_ON(network_thread());
2331 return transport_controller_->NeedsIceRestart(content_name);
2332 });
Steve Anton75737c02017-11-06 18:37:172333}
2334
Alex Loiko9289eda2018-11-23 16:18:592335void PeerConnection::OnTransportControllerConnectionState(
2336 cricket::IceConnectionState state) {
2337 switch (state) {
2338 case cricket::kIceConnectionConnecting:
2339 // If the current state is Connected or Completed, then there were
2340 // writable channels but now there are not, so the next state must
2341 // be Disconnected.
2342 // kIceConnectionConnecting is currently used as the default,
2343 // un-connected state by the TransportController, so its only use is
2344 // detecting disconnections.
2345 if (ice_connection_state_ ==
2346 PeerConnectionInterface::kIceConnectionConnected ||
2347 ice_connection_state_ ==
2348 PeerConnectionInterface::kIceConnectionCompleted) {
2349 SetIceConnectionState(
2350 PeerConnectionInterface::kIceConnectionDisconnected);
2351 }
2352 break;
2353 case cricket::kIceConnectionFailed:
2354 SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
2355 break;
2356 case cricket::kIceConnectionConnected:
2357 RTC_LOG(LS_INFO) << "Changing to ICE connected state because "
2358 "all transports are writable.";
2359 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
2360 NoteUsageEvent(UsageEvent::ICE_STATE_CONNECTED);
2361 break;
2362 case cricket::kIceConnectionCompleted:
2363 RTC_LOG(LS_INFO) << "Changing to ICE completed state because "
2364 "all transports are complete.";
2365 if (ice_connection_state_ !=
2366 PeerConnectionInterface::kIceConnectionConnected) {
2367 // If jumping directly from "checking" to "connected",
2368 // signal "connected" first.
2369 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
2370 }
2371 SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
Tomas Gunnarsson2001dc32021-04-06 09:36:002372
Alex Loiko9289eda2018-11-23 16:18:592373 NoteUsageEvent(UsageEvent::ICE_STATE_CONNECTED);
Alex Loiko9289eda2018-11-23 16:18:592374 break;
2375 default:
Artem Titovd3251962021-11-15 15:57:072376 RTC_DCHECK_NOTREACHED();
Alex Loiko9289eda2018-11-23 16:18:592377 }
2378}
2379
Steve Anton75737c02017-11-06 18:37:172380void PeerConnection::OnTransportControllerCandidatesGathered(
2381 const std::string& transport_name,
2382 const cricket::Candidates& candidates) {
Tomas Gunnarsson20f74562021-02-04 09:22:502383 // TODO(bugs.webrtc.org/12427): Expect this to come in on the network thread
2384 // (not signaling as it currently does), handle appropriately.
Steve Anton75737c02017-11-06 18:37:172385 int sdp_mline_index;
2386 if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) {
Mirko Bonadei675513b2017-11-09 10:09:252387 RTC_LOG(LS_ERROR)
2388 << "OnTransportControllerCandidatesGathered: content name "
2389 << transport_name << " not found";
Steve Anton75737c02017-11-06 18:37:172390 return;
2391 }
2392
2393 for (cricket::Candidates::const_iterator citer = candidates.begin();
2394 citer != candidates.end(); ++citer) {
2395 // Use transport_name as the candidate media id.
2396 std::unique_ptr<JsepIceCandidate> candidate(
2397 new JsepIceCandidate(transport_name, sdp_mline_index, *citer));
Harald Alvestrand9cd199d2020-10-27 07:10:432398 sdp_handler_->AddLocalIceCandidate(candidate.get());
Steve Anton75737c02017-11-06 18:37:172399 OnIceCandidate(std::move(candidate));
2400 }
2401}
2402
Eldar Relloda13ea22019-06-01 09:23:432403void PeerConnection::OnTransportControllerCandidateError(
2404 const cricket::IceCandidateErrorEvent& event) {
Eldar Rello0095d372019-12-02 20:22:072405 OnIceCandidateError(event.address, event.port, event.url, event.error_code,
Eldar Relloda13ea22019-06-01 09:23:432406 event.error_text);
2407}
2408
Steve Anton75737c02017-11-06 18:37:172409void PeerConnection::OnTransportControllerCandidatesRemoved(
2410 const std::vector<cricket::Candidate>& candidates) {
Steve Anton75737c02017-11-06 18:37:172411 // Sanity check.
2412 for (const cricket::Candidate& candidate : candidates) {
2413 if (candidate.transport_name().empty()) {
Mirko Bonadei675513b2017-11-09 10:09:252414 RTC_LOG(LS_ERROR) << "OnTransportControllerCandidatesRemoved: "
Jonas Olsson45cc8902018-02-13 09:37:072415 "empty content name in candidate "
Mirko Bonadei675513b2017-11-09 10:09:252416 << candidate.ToString();
Steve Anton75737c02017-11-06 18:37:172417 return;
2418 }
2419 }
Harald Alvestrand9cd199d2020-10-27 07:10:432420 sdp_handler_->RemoveLocalIceCandidates(candidates);
Steve Anton75737c02017-11-06 18:37:172421 OnIceCandidatesRemoved(candidates);
2422}
2423
Alex Drake00c7ecf2019-08-06 17:54:472424void PeerConnection::OnTransportControllerCandidateChanged(
2425 const cricket::CandidatePairChangeEvent& event) {
2426 OnSelectedCandidatePairChanged(event);
2427}
2428
Steve Anton75737c02017-11-06 18:37:172429void PeerConnection::OnTransportControllerDtlsHandshakeError(
2430 rtc::SSLHandshakeError error) {
Qingsi Wang7fc821d2018-07-12 19:54:532431 RTC_HISTOGRAM_ENUMERATION(
2432 "WebRTC.PeerConnection.DtlsHandshakeError", static_cast<int>(error),
2433 static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
Steve Anton75737c02017-11-06 18:37:172434}
2435
Steve Anton75737c02017-11-06 18:37:172436// Returns the media index for a local ice candidate given the content name.
2437bool PeerConnection::GetLocalCandidateMediaIndex(
2438 const std::string& content_name,
2439 int* sdp_mline_index) {
2440 if (!local_description() || !sdp_mline_index) {
2441 return false;
2442 }
2443
2444 bool content_found = false;
2445 const ContentInfos& contents = local_description()->description()->contents();
2446 for (size_t index = 0; index < contents.size(); ++index) {
2447 if (contents[index].name == content_name) {
2448 *sdp_mline_index = static_cast<int>(index);
2449 content_found = true;
2450 break;
2451 }
2452 }
2453 return content_found;
2454}
2455
Steve Anton75737c02017-11-06 18:37:172456Call::Stats PeerConnection::GetCallStats() {
2457 if (!worker_thread()->IsCurrent()) {
2458 return worker_thread()->Invoke<Call::Stats>(
Niels Möller4bab23f2021-01-18 08:24:332459 RTC_FROM_HERE, [this] { return GetCallStats(); });
Steve Anton75737c02017-11-06 18:37:172460 }
Karl Wiberg6cab5c82019-03-26 08:57:012461 RTC_DCHECK_RUN_ON(worker_thread());
Henrik Boströme88c95e2020-07-08 09:18:502462 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
Steve Anton75737c02017-11-06 18:37:172463 if (call_) {
2464 return call_->GetStats();
2465 } else {
2466 return Call::Stats();
2467 }
2468}
2469
Bjorn A Mellemb689af42019-08-21 17:44:592470bool PeerConnection::SetupDataChannelTransport_n(const std::string& mid) {
Bjorn A Mellembc3eebc2019-09-23 21:53:542471 DataChannelTransportInterface* transport =
2472 transport_controller_->GetDataChannelTransport(mid);
2473 if (!transport) {
Piotr (Peter) Slatalab1ae10b2019-03-01 19:14:052474 RTC_LOG(LS_ERROR)
Bjorn A Mellemb689af42019-08-21 17:44:592475 << "Data channel transport is not available for data channels, mid="
2476 << mid;
Bjorn Mellem175aa2e2018-11-08 19:23:222477 return false;
2478 }
Bjorn A Mellemb689af42019-08-21 17:44:592479 RTC_LOG(LS_INFO) << "Setting up data channel transport for mid=" << mid;
Bjorn Mellem175aa2e2018-11-08 19:23:222480
Harald Alvestrand00cf34c2019-12-02 08:56:022481 data_channel_controller_.set_data_channel_transport(transport);
2482 data_channel_controller_.SetupDataChannelTransport_n();
Harald Alvestrand7a829a82020-02-12 06:38:212483 sctp_mid_n_ = mid;
Tomas Gunnarssone1c8a432021-04-08 13:15:282484 cricket::DtlsTransportInternal* dtls_transport =
2485 transport_controller_->GetDtlsTransport(mid);
Tomas Gunnarsson92eebef2021-02-10 12:05:442486 if (dtls_transport) {
2487 signaling_thread()->PostTask(
2488 ToQueuedTask(signaling_thread_safety_.flag(),
2489 [this, name = dtls_transport->transport_name()] {
2490 RTC_DCHECK_RUN_ON(signaling_thread());
2491 sctp_transport_name_s_ = std::move(name);
2492 }));
2493 }
Bjorn A Mellembc3eebc2019-09-23 21:53:542494
2495 // Note: setting the data sink and checking initial state must be done last,
2496 // after setting up the data channel. Setting the data sink may trigger
2497 // callbacks to PeerConnection which require the transport to be completely
2498 // set up (eg. OnReadyToSend()).
Harald Alvestrand00cf34c2019-12-02 08:56:022499 transport->SetDataSink(&data_channel_controller_);
Bjorn Mellem175aa2e2018-11-08 19:23:222500 return true;
2501}
2502
Tomas Gunnarssond69e0702021-04-07 13:14:432503void PeerConnection::TeardownDataChannelTransport_n() {
Tomas Gunnarssond69e0702021-04-07 13:14:432504 if (sctp_mid_n_) {
Artem Titov880fa812021-07-30 20:30:232505 // `sctp_mid_` may still be active through an SCTP transport. If not, unset
Tomas Gunnarssond69e0702021-04-07 13:14:432506 // it.
2507 RTC_LOG(LS_INFO) << "Tearing down data channel transport for mid="
2508 << *sctp_mid_n_;
2509 sctp_mid_n_.reset();
2510 }
2511
Harald Alvestrand00cf34c2019-12-02 08:56:022512 data_channel_controller_.TeardownDataChannelTransport_n();
Bjorn Mellem175aa2e2018-11-08 19:23:222513}
2514
Steve Anton75737c02017-11-06 18:37:172515// Returns false if bundle is enabled and rtcp_mux is disabled.
Henrik Boströmf8187e02021-04-26 19:04:262516bool PeerConnection::ValidateBundleSettings(
2517 const SessionDescription* desc,
2518 const std::map<std::string, const cricket::ContentGroup*>&
2519 bundle_groups_by_mid) {
2520 if (bundle_groups_by_mid.empty())
Steve Anton75737c02017-11-06 18:37:172521 return true;
2522
Steve Anton75737c02017-11-06 18:37:172523 const cricket::ContentInfos& contents = desc->contents();
2524 for (cricket::ContentInfos::const_iterator citer = contents.begin();
2525 citer != contents.end(); ++citer) {
2526 const cricket::ContentInfo* content = (&*citer);
2527 RTC_DCHECK(content != NULL);
Henrik Boströmf8187e02021-04-26 19:04:262528 auto it = bundle_groups_by_mid.find(content->name);
2529 if (it != bundle_groups_by_mid.end() && !content->rejected &&
Steve Anton5adfafd2017-12-21 00:34:002530 content->type == MediaProtocolType::kRtp) {
Steve Anton75737c02017-11-06 18:37:172531 if (!HasRtcpMuxEnabled(content))
2532 return false;
2533 }
2534 }
2535 // RTCP-MUX is enabled in all the contents.
2536 return true;
2537}
2538
Steve Anton8e20f172018-03-06 18:55:042539void PeerConnection::ReportSdpFormatReceived(
Philipp Hancke844c7592021-01-18 10:25:312540 const SessionDescriptionInterface& remote_description) {
Steve Anton8e20f172018-03-06 18:55:042541 int num_audio_mlines = 0;
2542 int num_video_mlines = 0;
2543 int num_audio_tracks = 0;
2544 int num_video_tracks = 0;
Philipp Hancke844c7592021-01-18 10:25:312545 for (const ContentInfo& content :
2546 remote_description.description()->contents()) {
Steve Anton8e20f172018-03-06 18:55:042547 cricket::MediaType media_type = content.media_description()->type();
2548 int num_tracks = std::max(
2549 1, static_cast<int>(content.media_description()->streams().size()));
2550 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
2551 num_audio_mlines += 1;
2552 num_audio_tracks += num_tracks;
2553 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
2554 num_video_mlines += 1;
2555 num_video_tracks += num_tracks;
2556 }
2557 }
2558 SdpFormatReceived format = kSdpFormatReceivedNoTracks;
2559 if (num_audio_mlines > 1 || num_video_mlines > 1) {
2560 format = kSdpFormatReceivedComplexUnifiedPlan;
2561 } else if (num_audio_tracks > 1 || num_video_tracks > 1) {
2562 format = kSdpFormatReceivedComplexPlanB;
2563 } else if (num_audio_tracks > 0 || num_video_tracks > 0) {
2564 format = kSdpFormatReceivedSimple;
2565 }
Philipp Hancke844c7592021-01-18 10:25:312566 switch (remote_description.GetType()) {
Philipp Hanckeb8ca2a12020-10-07 10:47:102567 case SdpType::kOffer:
2568 // Historically only offers were counted.
2569 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SdpFormatReceived",
2570 format, kSdpFormatReceivedMax);
2571 break;
2572 case SdpType::kAnswer:
2573 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SdpFormatReceivedAnswer",
2574 format, kSdpFormatReceivedMax);
2575 break;
2576 default:
2577 RTC_LOG(LS_ERROR) << "Can not report SdpFormatReceived for "
Philipp Hancke844c7592021-01-18 10:25:312578 << SdpTypeToString(remote_description.GetType());
Philipp Hanckeb8ca2a12020-10-07 10:47:102579 break;
2580 }
Steve Anton8e20f172018-03-06 18:55:042581}
2582
Philipp Hancke54b925c2021-01-28 08:56:392583void PeerConnection::ReportSdpBundleUsage(
2584 const SessionDescriptionInterface& remote_description) {
2585 RTC_DCHECK_RUN_ON(signaling_thread());
2586
2587 bool using_bundle =
2588 remote_description.description()->HasGroup(cricket::GROUP_TYPE_BUNDLE);
2589 int num_audio_mlines = 0;
2590 int num_video_mlines = 0;
2591 int num_data_mlines = 0;
2592 for (const ContentInfo& content :
2593 remote_description.description()->contents()) {
2594 cricket::MediaType media_type = content.media_description()->type();
2595 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
2596 num_audio_mlines += 1;
2597 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
2598 num_video_mlines += 1;
2599 } else if (media_type == cricket::MEDIA_TYPE_DATA) {
2600 num_data_mlines += 1;
2601 }
2602 }
2603 bool simple = num_audio_mlines <= 1 && num_video_mlines <= 1;
2604 BundleUsage usage = kBundleUsageMax;
2605 if (num_audio_mlines == 0 && num_video_mlines == 0) {
2606 if (num_data_mlines > 0) {
2607 usage = using_bundle ? kBundleUsageBundleDatachannelOnly
2608 : kBundleUsageNoBundleDatachannelOnly;
2609 } else {
2610 usage = kBundleUsageEmpty;
2611 }
Harald Alvestrandfa67aef2021-12-08 14:30:552612 } else if (configuration_.sdp_semantics == SdpSemantics::kPlanB_DEPRECATED) {
Philipp Hancke54b925c2021-01-28 08:56:392613 // In plan-b, simple/complex usage will not show up in the number of
2614 // m-lines or BUNDLE.
2615 usage = using_bundle ? kBundleUsageBundlePlanB : kBundleUsageNoBundlePlanB;
2616 } else {
2617 if (simple) {
2618 usage =
2619 using_bundle ? kBundleUsageBundleSimple : kBundleUsageNoBundleSimple;
2620 } else {
2621 usage = using_bundle ? kBundleUsageBundleComplex
2622 : kBundleUsageNoBundleComplex;
2623 }
2624 }
2625 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.BundleUsage", usage,
2626 kBundleUsageMax);
2627}
2628
Qingsi Wang1ba5dec2019-08-19 18:57:172629void PeerConnection::ReportIceCandidateCollected(
2630 const cricket::Candidate& candidate) {
2631 NoteUsageEvent(UsageEvent::CANDIDATE_COLLECTED);
2632 if (candidate.address().IsPrivateIP()) {
2633 NoteUsageEvent(UsageEvent::PRIVATE_CANDIDATE_COLLECTED);
2634 }
2635 if (candidate.address().IsUnresolvedIP()) {
2636 NoteUsageEvent(UsageEvent::MDNS_CANDIDATE_COLLECTED);
2637 }
2638 if (candidate.address().family() == AF_INET6) {
2639 NoteUsageEvent(UsageEvent::IPV6_CANDIDATE_COLLECTED);
2640 }
2641}
2642
Harald Alvestrand8ebba742018-05-31 12:00:342643void PeerConnection::NoteUsageEvent(UsageEvent event) {
2644 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand44d0dff2020-10-09 05:43:532645 usage_pattern_.NoteUsageEvent(event);
Harald Alvestrand8ebba742018-05-31 12:00:342646}
2647
Tomas Gunnarsson8cb97062021-02-08 17:57:042648// Asynchronously adds remote candidates on the network thread.
2649void PeerConnection::AddRemoteCandidate(const std::string& mid,
2650 const cricket::Candidate& candidate) {
2651 RTC_DCHECK_RUN_ON(signaling_thread());
2652
2653 network_thread()->PostTask(ToQueuedTask(
2654 network_thread_safety_, [this, mid = mid, candidate = candidate] {
2655 RTC_DCHECK_RUN_ON(network_thread());
2656 std::vector<cricket::Candidate> candidates = {candidate};
2657 RTCError error =
2658 transport_controller_->AddRemoteCandidates(mid, candidates);
2659 if (error.ok()) {
2660 signaling_thread()->PostTask(ToQueuedTask(
2661 signaling_thread_safety_.flag(),
2662 [this, candidate = std::move(candidate)] {
2663 ReportRemoteIceCandidateAdded(candidate);
2664 // Candidates successfully submitted for checking.
2665 if (ice_connection_state() ==
2666 PeerConnectionInterface::kIceConnectionNew ||
2667 ice_connection_state() ==
2668 PeerConnectionInterface::kIceConnectionDisconnected) {
2669 // If state is New, then the session has just gotten its first
2670 // remote ICE candidates, so go to Checking. If state is
2671 // Disconnected, the session is re-using old candidates or
2672 // receiving additional ones, so go to Checking. If state is
2673 // Connected, stay Connected.
2674 // TODO(bemasc): If state is Connected, and the new candidates
2675 // are for a newly added transport, then the state actually
2676 // _should_ move to checking. Add a way to distinguish that
2677 // case.
2678 SetIceConnectionState(
2679 PeerConnectionInterface::kIceConnectionChecking);
2680 }
2681 // TODO(bemasc): If state is Completed, go back to Connected.
2682 }));
2683 } else {
2684 RTC_LOG(LS_WARNING) << error.message();
2685 }
2686 }));
2687}
2688
Harald Alvestrand8ebba742018-05-31 12:00:342689void PeerConnection::ReportUsagePattern() const {
Harald Alvestrand44d0dff2020-10-09 05:43:532690 usage_pattern_.ReportUsagePattern(observer_);
Harald Alvestrand8ebba742018-05-31 12:00:342691}
2692
Tomas Gunnarsson8cb97062021-02-08 17:57:042693void PeerConnection::ReportRemoteIceCandidateAdded(
2694 const cricket::Candidate& candidate) {
2695 RTC_DCHECK_RUN_ON(signaling_thread());
2696
2697 NoteUsageEvent(UsageEvent::REMOTE_CANDIDATE_ADDED);
2698
2699 if (candidate.address().IsPrivateIP()) {
2700 NoteUsageEvent(UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED);
2701 }
2702 if (candidate.address().IsUnresolvedIP()) {
2703 NoteUsageEvent(UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED);
2704 }
2705 if (candidate.address().family() == AF_INET6) {
2706 NoteUsageEvent(UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED);
2707 }
2708}
2709
Steve Anton75737c02017-11-06 18:37:172710bool PeerConnection::SrtpRequired() const {
Tomas Gunnarsson3278a712021-03-30 15:23:422711 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand0d018412021-11-04 13:52:312712 return (dtls_enabled_ ||
2713 sdp_handler_->webrtc_session_desc_factory()->SdesPolicy() ==
2714 cricket::SEC_REQUIRED);
Steve Anton75737c02017-11-06 18:37:172715}
2716
2717void PeerConnection::OnTransportControllerGatheringState(
2718 cricket::IceGatheringState state) {
2719 RTC_DCHECK(signaling_thread()->IsCurrent());
2720 if (state == cricket::kIceGatheringGathering) {
2721 OnIceGatheringChange(PeerConnectionInterface::kIceGatheringGathering);
2722 } else if (state == cricket::kIceGatheringComplete) {
2723 OnIceGatheringChange(PeerConnectionInterface::kIceGatheringComplete);
Harald Alvestrandbedb6052020-08-20 12:50:102724 } else if (state == cricket::kIceGatheringNew) {
2725 OnIceGatheringChange(PeerConnectionInterface::kIceGatheringNew);
2726 } else {
2727 RTC_LOG(LS_ERROR) << "Unknown state received: " << state;
Artem Titovd3251962021-11-15 15:57:072728 RTC_DCHECK_NOTREACHED();
Steve Anton75737c02017-11-06 18:37:172729 }
2730}
2731
Tomas Gunnarsson2001dc32021-04-06 09:36:002732// Runs on network_thread().
Steve Anton75737c02017-11-06 18:37:172733void PeerConnection::ReportTransportStats() {
Markus Handell518669d2021-06-07 11:30:462734 TRACE_EVENT0("webrtc", "PeerConnection::ReportTransportStats");
Tommic3257d02021-02-10 17:40:082735 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
Steve Antonc7b964c2018-02-01 22:39:452736 std::map<std::string, std::set<cricket::MediaType>>
2737 media_types_by_transport_name;
Artem Titovc6c02ef2022-05-09 08:30:092738 for (const auto& transceiver : rtp_manager()->transceivers()->UnsafeList()) {
2739 if (transceiver->internal()->channel()) {
2740 std::string transport_name(
2741 transceiver->internal()->channel()->transport_name());
2742 media_types_by_transport_name[transport_name].insert(
2743 transceiver->media_type());
Steve Antonc7b964c2018-02-01 22:39:452744 }
Steve Anton75737c02017-11-06 18:37:172745 }
Tomas Gunnarsson2001dc32021-04-06 09:36:002746
Tomas Gunnarsson2001dc32021-04-06 09:36:002747 if (sctp_mid_n_) {
Tomas Gunnarssone1c8a432021-04-08 13:15:282748 cricket::DtlsTransportInternal* dtls_transport =
2749 transport_controller_->GetDtlsTransport(*sctp_mid_n_);
Tomas Gunnarsson2001dc32021-04-06 09:36:002750 if (dtls_transport) {
2751 media_types_by_transport_name[dtls_transport->transport_name()].insert(
2752 cricket::MEDIA_TYPE_DATA);
2753 }
Steve Anton75737c02017-11-06 18:37:172754 }
Zhi Huange830e682018-03-30 17:48:352755
Tomas Gunnarsson2001dc32021-04-06 09:36:002756 for (const auto& entry : media_types_by_transport_name) {
2757 const std::string& transport_name = entry.first;
2758 const std::set<cricket::MediaType> media_types = entry.second;
2759 cricket::TransportStats stats;
2760 if (transport_controller_->GetStats(transport_name, &stats)) {
2761 ReportBestConnectionState(stats);
2762 ReportNegotiatedCiphers(dtls_enabled_, stats, media_types);
2763 }
2764 }
Steve Anton75737c02017-11-06 18:37:172765}
Tomas Gunnarsson2001dc32021-04-06 09:36:002766
Steve Anton75737c02017-11-06 18:37:172767// Walk through the ConnectionInfos to gather best connection usage
2768// for IPv4 and IPv6.
Tommic3257d02021-02-10 17:40:082769// static (no member state required)
Steve Anton75737c02017-11-06 18:37:172770void PeerConnection::ReportBestConnectionState(
2771 const cricket::TransportStats& stats) {
Steve Antonc7b964c2018-02-01 22:39:452772 for (const cricket::TransportChannelStats& channel_stats :
2773 stats.channel_stats) {
2774 for (const cricket::ConnectionInfo& connection_info :
Jonas Oreland149dc722019-08-28 06:10:272775 channel_stats.ice_transport_stats.connection_infos) {
Steve Antonc7b964c2018-02-01 22:39:452776 if (!connection_info.best_connection) {
Steve Anton75737c02017-11-06 18:37:172777 continue;
2778 }
2779
Steve Antonc7b964c2018-02-01 22:39:452780 const cricket::Candidate& local = connection_info.local_candidate;
2781 const cricket::Candidate& remote = connection_info.remote_candidate;
Steve Anton75737c02017-11-06 18:37:172782
2783 // Increment the counter for IceCandidatePairType.
2784 if (local.protocol() == cricket::TCP_PROTOCOL_NAME ||
2785 (local.type() == RELAY_PORT_TYPE &&
2786 local.relay_protocol() == cricket::TCP_PROTOCOL_NAME)) {
Qingsi Wang7fc821d2018-07-12 19:54:532787 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_TCP",
2788 GetIceCandidatePairCounter(local, remote),
2789 kIceCandidatePairMax);
Steve Anton75737c02017-11-06 18:37:172790 } else if (local.protocol() == cricket::UDP_PROTOCOL_NAME) {
Qingsi Wang7fc821d2018-07-12 19:54:532791 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_UDP",
2792 GetIceCandidatePairCounter(local, remote),
2793 kIceCandidatePairMax);
Steve Anton75737c02017-11-06 18:37:172794 } else {
Karl Wibergc95b9392020-11-07 23:49:372795 RTC_CHECK_NOTREACHED();
Steve Anton75737c02017-11-06 18:37:172796 }
Steve Anton75737c02017-11-06 18:37:172797
2798 // Increment the counter for IP type.
2799 if (local.address().family() == AF_INET) {
Qingsi Wang7fc821d2018-07-12 19:54:532800 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
2801 kBestConnections_IPv4,
2802 kPeerConnectionAddressFamilyCounter_Max);
Steve Anton75737c02017-11-06 18:37:172803 } else if (local.address().family() == AF_INET6) {
Qingsi Wang7fc821d2018-07-12 19:54:532804 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
2805 kBestConnections_IPv6,
2806 kPeerConnectionAddressFamilyCounter_Max);
Steve Anton75737c02017-11-06 18:37:172807 } else {
Qingsi Wang1dac6d82018-12-12 23:28:472808 RTC_CHECK(!local.address().hostname().empty() &&
2809 local.address().IsUnresolvedIP());
Steve Anton75737c02017-11-06 18:37:172810 }
2811
2812 return;
2813 }
2814 }
2815}
2816
Tommic3257d02021-02-10 17:40:082817// static
Steve Anton75737c02017-11-06 18:37:172818void PeerConnection::ReportNegotiatedCiphers(
Tommic3257d02021-02-10 17:40:082819 bool dtls_enabled,
Steve Antonc7b964c2018-02-01 22:39:452820 const cricket::TransportStats& stats,
2821 const std::set<cricket::MediaType>& media_types) {
Tommic3257d02021-02-10 17:40:082822 if (!dtls_enabled || stats.channel_stats.empty()) {
Steve Anton75737c02017-11-06 18:37:172823 return;
2824 }
2825
2826 int srtp_crypto_suite = stats.channel_stats[0].srtp_crypto_suite;
2827 int ssl_cipher_suite = stats.channel_stats[0].ssl_cipher_suite;
Mirko Bonadei7750d802021-07-26 15:27:422828 if (srtp_crypto_suite == rtc::kSrtpInvalidCryptoSuite &&
2829 ssl_cipher_suite == rtc::kTlsNullWithNullNull) {
Steve Anton75737c02017-11-06 18:37:172830 return;
2831 }
2832
Mirko Bonadei7750d802021-07-26 15:27:422833 if (srtp_crypto_suite != rtc::kSrtpInvalidCryptoSuite) {
Qingsi Wang7fc821d2018-07-12 19:54:532834 for (cricket::MediaType media_type : media_types) {
2835 switch (media_type) {
2836 case cricket::MEDIA_TYPE_AUDIO:
2837 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2838 "WebRTC.PeerConnection.SrtpCryptoSuite.Audio", srtp_crypto_suite,
Mirko Bonadei7750d802021-07-26 15:27:422839 rtc::kSrtpCryptoSuiteMaxValue);
Qingsi Wang7fc821d2018-07-12 19:54:532840 break;
2841 case cricket::MEDIA_TYPE_VIDEO:
2842 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2843 "WebRTC.PeerConnection.SrtpCryptoSuite.Video", srtp_crypto_suite,
Mirko Bonadei7750d802021-07-26 15:27:422844 rtc::kSrtpCryptoSuiteMaxValue);
Qingsi Wang7fc821d2018-07-12 19:54:532845 break;
2846 case cricket::MEDIA_TYPE_DATA:
2847 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2848 "WebRTC.PeerConnection.SrtpCryptoSuite.Data", srtp_crypto_suite,
Mirko Bonadei7750d802021-07-26 15:27:422849 rtc::kSrtpCryptoSuiteMaxValue);
Qingsi Wang7fc821d2018-07-12 19:54:532850 break;
2851 default:
Artem Titovd3251962021-11-15 15:57:072852 RTC_DCHECK_NOTREACHED();
Qingsi Wang7fc821d2018-07-12 19:54:532853 continue;
2854 }
Steve Antonc7b964c2018-02-01 22:39:452855 }
Qingsi Wang7fc821d2018-07-12 19:54:532856 }
2857
Mirko Bonadei7750d802021-07-26 15:27:422858 if (ssl_cipher_suite != rtc::kTlsNullWithNullNull) {
Qingsi Wang7fc821d2018-07-12 19:54:532859 for (cricket::MediaType media_type : media_types) {
2860 switch (media_type) {
2861 case cricket::MEDIA_TYPE_AUDIO:
2862 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2863 "WebRTC.PeerConnection.SslCipherSuite.Audio", ssl_cipher_suite,
Mirko Bonadei7750d802021-07-26 15:27:422864 rtc::kSslCipherSuiteMaxValue);
Qingsi Wang7fc821d2018-07-12 19:54:532865 break;
2866 case cricket::MEDIA_TYPE_VIDEO:
2867 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2868 "WebRTC.PeerConnection.SslCipherSuite.Video", ssl_cipher_suite,
Mirko Bonadei7750d802021-07-26 15:27:422869 rtc::kSslCipherSuiteMaxValue);
Qingsi Wang7fc821d2018-07-12 19:54:532870 break;
2871 case cricket::MEDIA_TYPE_DATA:
2872 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2873 "WebRTC.PeerConnection.SslCipherSuite.Data", ssl_cipher_suite,
Mirko Bonadei7750d802021-07-26 15:27:422874 rtc::kSslCipherSuiteMaxValue);
Qingsi Wang7fc821d2018-07-12 19:54:532875 break;
2876 default:
Artem Titovd3251962021-11-15 15:57:072877 RTC_DCHECK_NOTREACHED();
Qingsi Wang7fc821d2018-07-12 19:54:532878 continue;
2879 }
Steve Antonc7b964c2018-02-01 22:39:452880 }
Steve Anton75737c02017-11-06 18:37:172881 }
2882}
2883
Taylor Brandstettercbaa2542018-04-16 23:42:142884bool PeerConnection::OnTransportChanged(
Zhi Huange830e682018-03-30 17:48:352885 const std::string& mid,
Taylor Brandstettercbaa2542018-04-16 23:42:142886 RtpTransportInternal* rtp_transport,
Harald Alvestrandc85328f2019-02-28 06:51:002887 rtc::scoped_refptr<DtlsTransport> dtls_transport,
Bjorn A Mellembc3eebc2019-09-23 21:53:542888 DataChannelTransportInterface* data_channel_transport) {
Karl Wibergac025892019-03-26 12:08:372889 RTC_DCHECK_RUN_ON(network_thread());
Taylor Brandstettercbaa2542018-04-16 23:42:142890 bool ret = true;
Artem Titovc6c02ef2022-05-09 08:30:092891 for (const auto& transceiver : rtp_manager()->transceivers()->UnsafeList()) {
2892 cricket::ChannelInterface* channel = transceiver->internal()->channel();
2893 if (channel && channel->mid() == mid) {
2894 ret = channel->SetRtpTransport(rtp_transport);
Harald Alvestrand19ebabc2022-04-28 13:31:172895 }
Zhi Huange830e682018-03-30 17:48:352896 }
Tomas Gunnarsson92eebef2021-02-10 12:05:442897
Harald Alvestrand7a829a82020-02-12 06:38:212898 if (mid == sctp_mid_n_) {
Harald Alvestrand00cf34c2019-12-02 08:56:022899 data_channel_controller_.OnTransportChanged(data_channel_transport);
Tomas Gunnarsson92eebef2021-02-10 12:05:442900 if (dtls_transport) {
2901 signaling_thread()->PostTask(ToQueuedTask(
2902 signaling_thread_safety_.flag(),
Tomas Gunnarsson94f01942022-01-03 14:59:122903 [this,
2904 name = std::string(dtls_transport->internal()->transport_name())] {
Tomas Gunnarsson92eebef2021-02-10 12:05:442905 RTC_DCHECK_RUN_ON(signaling_thread());
2906 sctp_transport_name_s_ = std::move(name);
2907 }));
2908 }
Bjorn A Mellemb689af42019-08-21 17:44:592909 }
Tomas Gunnarsson92eebef2021-02-10 12:05:442910
Taylor Brandstettercbaa2542018-04-16 23:42:142911 return ret;
Steve Anton75737c02017-11-06 18:37:172912}
2913
Harald Alvestrand7a1c7f72018-08-01 08:50:162914PeerConnectionObserver* PeerConnection::Observer() const {
Harald Alvestrand05e4d082019-12-03 13:04:212915 RTC_DCHECK_RUN_ON(signaling_thread());
2916 RTC_DCHECK(observer_);
Harald Alvestrand7a1c7f72018-08-01 08:50:162917 return observer_;
2918}
2919
Tomas Gunnarsson92eebef2021-02-10 12:05:442920void PeerConnection::StartSctpTransport(int local_port,
2921 int remote_port,
2922 int max_message_size) {
2923 RTC_DCHECK_RUN_ON(signaling_thread());
2924 if (!sctp_mid_s_)
2925 return;
2926
2927 network_thread()->PostTask(ToQueuedTask(
2928 network_thread_safety_,
2929 [this, mid = *sctp_mid_s_, local_port, remote_port, max_message_size] {
2930 rtc::scoped_refptr<SctpTransport> sctp_transport =
Harald Alvestrandbc32c562022-02-09 12:08:472931 transport_controller_n()->GetSctpTransport(mid);
Tomas Gunnarsson92eebef2021-02-10 12:05:442932 if (sctp_transport)
2933 sctp_transport->Start(local_port, remote_port, max_message_size);
2934 }));
2935}
2936
Benjamin Wright8c27cca2018-10-25 17:16:442937CryptoOptions PeerConnection::GetCryptoOptions() {
Harald Alvestrandc06e3742020-10-01 10:23:332938 RTC_DCHECK_RUN_ON(signaling_thread());
Benjamin Wright8c27cca2018-10-25 17:16:442939 // TODO(bugs.webrtc.org/9891) - Remove PeerConnectionFactory::CryptoOptions
2940 // after it has been removed.
2941 return configuration_.crypto_options.has_value()
2942 ? *configuration_.crypto_options
Harald Alvestrand4da4a872020-11-04 10:34:212943 : options_.crypto_options;
Benjamin Wright8c27cca2018-10-25 17:16:442944}
2945
Harald Alvestrand89061872018-01-02 13:08:342946void PeerConnection::ClearStatsCache() {
Karl Wiberg6cab5c82019-03-26 08:57:012947 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand89061872018-01-02 13:08:342948 if (stats_collector_) {
2949 stats_collector_->ClearCachedStatsReport();
2950 }
2951}
2952
Henrik Boströme574a312020-08-25 08:20:112953bool PeerConnection::ShouldFireNegotiationNeededEvent(uint32_t event_id) {
2954 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand9cd199d2020-10-27 07:10:432955 return sdp_handler_->ShouldFireNegotiationNeededEvent(event_id);
Eldar Rello5ab79e62019-10-09 15:29:442956}
2957
Harald Alvestrand1090e442020-10-05 07:01:092958void PeerConnection::RequestUsagePatternReportForTesting() {
Harald Alvestrand00c62ed2021-10-20 08:52:122959 RTC_DCHECK_RUN_ON(signaling_thread());
Harald Alvestrand1090e442020-10-05 07:01:092960 message_handler_.RequestUsagePatternReport(
2961 [this]() {
2962 RTC_DCHECK_RUN_ON(signaling_thread());
2963 ReportUsagePattern();
2964 },
2965 /* delay_ms= */ 0);
2966}
2967
Tomas Gunnarsson1e40a0c2020-09-28 08:39:312968std::function<void(const rtc::CopyOnWriteBuffer& packet,
2969 int64_t packet_time_us)>
2970PeerConnection::InitializeRtcpCallback() {
Tommic3257d02021-02-10 17:40:082971 RTC_DCHECK_RUN_ON(network_thread());
Tommicae1f1d2021-05-31 08:51:092972 return [this](const rtc::CopyOnWriteBuffer& packet, int64_t packet_time_us) {
Tomas Gunnarsson1e40a0c2020-09-28 08:39:312973 RTC_DCHECK_RUN_ON(network_thread());
Tommicae1f1d2021-05-31 08:51:092974 call_ptr_->Receiver()->DeliverPacket(MediaType::ANY, packet,
2975 packet_time_us);
Tomas Gunnarsson1e40a0c2020-09-28 08:39:312976 };
2977}
Harald Alvestrandcdcfab02020-09-28 13:02:072978
henrike@webrtc.org28e20752013-07-10 00:45:362979} // namespace webrtc