1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
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.
9 */
10
11 #include "pc/peer_connection.h"
12
13 #include <limits.h>
14 #include <stddef.h>
15
16 #include <algorithm>
17 #include <memory>
18 #include <set>
19 #include <string>
20 #include <utility>
21
22 #include "absl/algorithm/container.h"
23 #include "absl/strings/match.h"
24 #include "absl/strings/string_view.h"
25 #include "api/jsep_ice_candidate.h"
26 #include "api/rtp_parameters.h"
27 #include "api/rtp_transceiver_direction.h"
28 #include "api/uma_metrics.h"
29 #include "api/video/video_codec_constants.h"
30 #include "call/audio_state.h"
31 #include "call/packet_receiver.h"
32 #include "media/base/media_channel.h"
33 #include "media/base/media_config.h"
34 #include "media/base/media_engine.h"
35 #include "media/base/rid_description.h"
36 #include "media/base/stream_params.h"
37 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
38 #include "p2p/base/basic_async_resolver_factory.h"
39 #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"
45 #include "pc/ice_server_parsing.h"
46 #include "pc/rtp_receiver.h"
47 #include "pc/rtp_receiver_proxy.h"
48 #include "pc/rtp_sender.h"
49 #include "pc/rtp_sender_proxy.h"
50 #include "pc/sctp_transport.h"
51 #include "pc/simulcast_description.h"
52 #include "pc/webrtc_session_description_factory.h"
53 #include "rtc_base/helpers.h"
54 #include "rtc_base/ip_address.h"
55 #include "rtc_base/logging.h"
56 #include "rtc_base/net_helper.h"
57 #include "rtc_base/network.h"
58 #include "rtc_base/network_constants.h"
59 #include "rtc_base/socket_address.h"
60 #include "rtc_base/string_encode.h"
61 #include "rtc_base/trace_event.h"
62 #include "rtc_base/unique_id_generator.h"
63 #include "system_wrappers/include/metrics.h"
64
65 using cricket::ContentInfo;
66 using cricket::ContentInfos;
67 using cricket::MediaContentDescription;
68 using cricket::MediaProtocolType;
69 using cricket::RidDescription;
70 using cricket::RidDirection;
71 using cricket::SessionDescription;
72 using cricket::SimulcastDescription;
73 using cricket::SimulcastLayer;
74 using cricket::SimulcastLayerList;
75 using cricket::StreamParams;
76 using cricket::TransportInfo;
77
78 using cricket::LOCAL_PORT_TYPE;
79 using cricket::PRFLX_PORT_TYPE;
80 using cricket::RELAY_PORT_TYPE;
81 using cricket::STUN_PORT_TYPE;
82
83 namespace webrtc {
84
85 namespace {
86
87 // UMA metric names.
88 const char kSimulcastNumberOfEncodings[] =
89 "WebRTC.PeerConnection.Simulcast.NumberOfSendEncodings";
90
91 static const int REPORT_USAGE_PATTERN_DELAY_MS = 60000;
92
ConvertIceTransportTypeToCandidateFilter(PeerConnectionInterface::IceTransportsType type)93 uint32_t ConvertIceTransportTypeToCandidateFilter(
94 PeerConnectionInterface::IceTransportsType type) {
95 switch (type) {
96 case PeerConnectionInterface::kNone:
97 return cricket::CF_NONE;
98 case PeerConnectionInterface::kRelay:
99 return cricket::CF_RELAY;
100 case PeerConnectionInterface::kNoHost:
101 return (cricket::CF_ALL & ~cricket::CF_HOST);
102 case PeerConnectionInterface::kAll:
103 return cricket::CF_ALL;
104 default:
105 RTC_DCHECK_NOTREACHED();
106 }
107 return cricket::CF_NONE;
108 }
109
GetIceCandidatePairCounter(const cricket::Candidate & local,const cricket::Candidate & remote)110 IceCandidatePairType GetIceCandidatePairCounter(
111 const cricket::Candidate& local,
112 const cricket::Candidate& remote) {
113 const auto& l = local.type();
114 const auto& r = remote.type();
115 const auto& host = LOCAL_PORT_TYPE;
116 const auto& srflx = STUN_PORT_TYPE;
117 const auto& relay = RELAY_PORT_TYPE;
118 const auto& prflx = PRFLX_PORT_TYPE;
119 if (l == host && r == host) {
120 bool local_hostname =
121 !local.address().hostname().empty() && local.address().IsUnresolvedIP();
122 bool remote_hostname = !remote.address().hostname().empty() &&
123 remote.address().IsUnresolvedIP();
124 bool local_private = IPIsPrivate(local.address().ipaddr());
125 bool remote_private = IPIsPrivate(remote.address().ipaddr());
126 if (local_hostname) {
127 if (remote_hostname) {
128 return kIceCandidatePairHostNameHostName;
129 } else if (remote_private) {
130 return kIceCandidatePairHostNameHostPrivate;
131 } else {
132 return kIceCandidatePairHostNameHostPublic;
133 }
134 } else if (local_private) {
135 if (remote_hostname) {
136 return kIceCandidatePairHostPrivateHostName;
137 } else if (remote_private) {
138 return kIceCandidatePairHostPrivateHostPrivate;
139 } else {
140 return kIceCandidatePairHostPrivateHostPublic;
141 }
142 } else {
143 if (remote_hostname) {
144 return kIceCandidatePairHostPublicHostName;
145 } else if (remote_private) {
146 return kIceCandidatePairHostPublicHostPrivate;
147 } else {
148 return kIceCandidatePairHostPublicHostPublic;
149 }
150 }
151 }
152 if (l == host && r == srflx)
153 return kIceCandidatePairHostSrflx;
154 if (l == host && r == relay)
155 return kIceCandidatePairHostRelay;
156 if (l == host && r == prflx)
157 return kIceCandidatePairHostPrflx;
158 if (l == srflx && r == host)
159 return kIceCandidatePairSrflxHost;
160 if (l == srflx && r == srflx)
161 return kIceCandidatePairSrflxSrflx;
162 if (l == srflx && r == relay)
163 return kIceCandidatePairSrflxRelay;
164 if (l == srflx && r == prflx)
165 return kIceCandidatePairSrflxPrflx;
166 if (l == relay && r == host)
167 return kIceCandidatePairRelayHost;
168 if (l == relay && r == srflx)
169 return kIceCandidatePairRelaySrflx;
170 if (l == relay && r == relay)
171 return kIceCandidatePairRelayRelay;
172 if (l == relay && r == prflx)
173 return kIceCandidatePairRelayPrflx;
174 if (l == prflx && r == host)
175 return kIceCandidatePairPrflxHost;
176 if (l == prflx && r == srflx)
177 return kIceCandidatePairPrflxSrflx;
178 if (l == prflx && r == relay)
179 return kIceCandidatePairPrflxRelay;
180 return kIceCandidatePairMax;
181 }
182
RTCConfigurationToIceConfigOptionalInt(int rtc_configuration_parameter)183 absl::optional<int> RTCConfigurationToIceConfigOptionalInt(
184 int rtc_configuration_parameter) {
185 if (rtc_configuration_parameter ==
186 webrtc::PeerConnectionInterface::RTCConfiguration::kUndefined) {
187 return absl::nullopt;
188 }
189 return rtc_configuration_parameter;
190 }
191
192 // Check if the changes of IceTransportsType motives an ice restart.
NeedIceRestart(bool surface_ice_candidates_on_ice_transport_type_changed,PeerConnectionInterface::IceTransportsType current,PeerConnectionInterface::IceTransportsType modified)193 bool NeedIceRestart(bool surface_ice_candidates_on_ice_transport_type_changed,
194 PeerConnectionInterface::IceTransportsType current,
195 PeerConnectionInterface::IceTransportsType modified) {
196 if (current == modified) {
197 return false;
198 }
199
200 if (!surface_ice_candidates_on_ice_transport_type_changed) {
201 return true;
202 }
203
204 auto current_filter = ConvertIceTransportTypeToCandidateFilter(current);
205 auto modified_filter = ConvertIceTransportTypeToCandidateFilter(modified);
206
207 // If surface_ice_candidates_on_ice_transport_type_changed is true and we
208 // extend the filter, then no ice restart is needed.
209 return (current_filter & modified_filter) != current_filter;
210 }
211
ParseIceConfig(const PeerConnectionInterface::RTCConfiguration & config)212 cricket::IceConfig ParseIceConfig(
213 const PeerConnectionInterface::RTCConfiguration& config) {
214 cricket::ContinualGatheringPolicy gathering_policy;
215 switch (config.continual_gathering_policy) {
216 case PeerConnectionInterface::GATHER_ONCE:
217 gathering_policy = cricket::GATHER_ONCE;
218 break;
219 case PeerConnectionInterface::GATHER_CONTINUALLY:
220 gathering_policy = cricket::GATHER_CONTINUALLY;
221 break;
222 default:
223 RTC_DCHECK_NOTREACHED();
224 gathering_policy = cricket::GATHER_ONCE;
225 }
226
227 cricket::IceConfig ice_config;
228 ice_config.receiving_timeout = RTCConfigurationToIceConfigOptionalInt(
229 config.ice_connection_receiving_timeout);
230 ice_config.prioritize_most_likely_candidate_pairs =
231 config.prioritize_most_likely_ice_candidate_pairs;
232 ice_config.backup_connection_ping_interval =
233 RTCConfigurationToIceConfigOptionalInt(
234 config.ice_backup_candidate_pair_ping_interval);
235 ice_config.continual_gathering_policy = gathering_policy;
236 ice_config.presume_writable_when_fully_relayed =
237 config.presume_writable_when_fully_relayed;
238 ice_config.surface_ice_candidates_on_ice_transport_type_changed =
239 config.surface_ice_candidates_on_ice_transport_type_changed;
240 ice_config.ice_check_interval_strong_connectivity =
241 config.ice_check_interval_strong_connectivity;
242 ice_config.ice_check_interval_weak_connectivity =
243 config.ice_check_interval_weak_connectivity;
244 ice_config.ice_check_min_interval = config.ice_check_min_interval;
245 ice_config.ice_unwritable_timeout = config.ice_unwritable_timeout;
246 ice_config.ice_unwritable_min_checks = config.ice_unwritable_min_checks;
247 ice_config.ice_inactive_timeout = config.ice_inactive_timeout;
248 ice_config.stun_keepalive_interval = config.stun_candidate_keepalive_interval;
249 ice_config.network_preference = config.network_preference;
250 ice_config.stable_writable_connection_ping_interval =
251 config.stable_writable_connection_ping_interval_ms;
252 return ice_config;
253 }
254
255 // Ensures the configuration doesn't have any parameters with invalid values,
256 // or values that conflict with other parameters.
257 //
258 // Returns RTCError::OK() if there are no issues.
ValidateConfiguration(const PeerConnectionInterface::RTCConfiguration & config)259 RTCError ValidateConfiguration(
260 const PeerConnectionInterface::RTCConfiguration& config) {
261 return cricket::P2PTransportChannel::ValidateIceConfig(
262 ParseIceConfig(config));
263 }
264
HasRtcpMuxEnabled(const cricket::ContentInfo * content)265 bool HasRtcpMuxEnabled(const cricket::ContentInfo* content) {
266 return content->media_description()->rtcp_mux();
267 }
268
DtlsEnabled(const PeerConnectionInterface::RTCConfiguration & configuration,const PeerConnectionFactoryInterface::Options & options,const PeerConnectionDependencies & dependencies)269 bool DtlsEnabled(const PeerConnectionInterface::RTCConfiguration& configuration,
270 const PeerConnectionFactoryInterface::Options& options,
271 const PeerConnectionDependencies& dependencies) {
272 if (options.disable_encryption)
273 return false;
274
275 // Enable DTLS by default if we have an identity store or a certificate.
276 bool default_enabled =
277 (dependencies.cert_generator || !configuration.certificates.empty());
278
279 #if defined(WEBRTC_FUCHSIA)
280 // The `configuration` can override the default value.
281 return configuration.enable_dtls_srtp.value_or(default_enabled);
282 #else
283 return default_enabled;
284 #endif
285 }
286
287 } // namespace
288
operator ==(const PeerConnectionInterface::RTCConfiguration & o) const289 bool PeerConnectionInterface::RTCConfiguration::operator==(
290 const PeerConnectionInterface::RTCConfiguration& o) const {
291 // This static_assert prevents us from accidentally breaking operator==.
292 // Note: Order matters! Fields must be ordered the same as RTCConfiguration.
293 struct stuff_being_tested_for_equality {
294 IceServers servers;
295 IceTransportsType type;
296 BundlePolicy bundle_policy;
297 RtcpMuxPolicy rtcp_mux_policy;
298 std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
299 int ice_candidate_pool_size;
300 bool disable_ipv6_on_wifi;
301 int max_ipv6_networks;
302 bool disable_link_local_networks;
303 absl::optional<int> screencast_min_bitrate;
304 absl::optional<bool> combined_audio_video_bwe;
305 #if defined(WEBRTC_FUCHSIA)
306 absl::optional<bool> enable_dtls_srtp;
307 #endif
308 TcpCandidatePolicy tcp_candidate_policy;
309 CandidateNetworkPolicy candidate_network_policy;
310 int audio_jitter_buffer_max_packets;
311 bool audio_jitter_buffer_fast_accelerate;
312 int audio_jitter_buffer_min_delay_ms;
313 int ice_connection_receiving_timeout;
314 int ice_backup_candidate_pair_ping_interval;
315 ContinualGatheringPolicy continual_gathering_policy;
316 bool prioritize_most_likely_ice_candidate_pairs;
317 struct cricket::MediaConfig media_config;
318 bool prune_turn_ports;
319 PortPrunePolicy turn_port_prune_policy;
320 bool presume_writable_when_fully_relayed;
321 bool enable_ice_renomination;
322 bool redetermine_role_on_ice_restart;
323 bool surface_ice_candidates_on_ice_transport_type_changed;
324 absl::optional<int> ice_check_interval_strong_connectivity;
325 absl::optional<int> ice_check_interval_weak_connectivity;
326 absl::optional<int> ice_check_min_interval;
327 absl::optional<int> ice_unwritable_timeout;
328 absl::optional<int> ice_unwritable_min_checks;
329 absl::optional<int> ice_inactive_timeout;
330 absl::optional<int> stun_candidate_keepalive_interval;
331 webrtc::TurnCustomizer* turn_customizer;
332 SdpSemantics sdp_semantics;
333 absl::optional<rtc::AdapterType> network_preference;
334 bool active_reset_srtp_params;
335 absl::optional<CryptoOptions> crypto_options;
336 bool offer_extmap_allow_mixed;
337 std::string turn_logging_id;
338 bool enable_implicit_rollback;
339 absl::optional<bool> allow_codec_switching;
340 absl::optional<int> report_usage_pattern_delay_ms;
341 absl::optional<int> stable_writable_connection_ping_interval_ms;
342 webrtc::VpnPreference vpn_preference;
343 std::vector<rtc::NetworkMask> vpn_list;
344 PortAllocatorConfig port_allocator_config;
345 absl::optional<TimeDelta> pacer_burst_interval;
346 };
347 static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this),
348 "Did you add something to RTCConfiguration and forget to "
349 "update operator==?");
350 return type == o.type && servers == o.servers &&
351 bundle_policy == o.bundle_policy &&
352 rtcp_mux_policy == o.rtcp_mux_policy &&
353 tcp_candidate_policy == o.tcp_candidate_policy &&
354 candidate_network_policy == o.candidate_network_policy &&
355 audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets &&
356 audio_jitter_buffer_fast_accelerate ==
357 o.audio_jitter_buffer_fast_accelerate &&
358 audio_jitter_buffer_min_delay_ms ==
359 o.audio_jitter_buffer_min_delay_ms &&
360 ice_connection_receiving_timeout ==
361 o.ice_connection_receiving_timeout &&
362 ice_backup_candidate_pair_ping_interval ==
363 o.ice_backup_candidate_pair_ping_interval &&
364 continual_gathering_policy == o.continual_gathering_policy &&
365 certificates == o.certificates &&
366 prioritize_most_likely_ice_candidate_pairs ==
367 o.prioritize_most_likely_ice_candidate_pairs &&
368 media_config == o.media_config &&
369 disable_ipv6_on_wifi == o.disable_ipv6_on_wifi &&
370 max_ipv6_networks == o.max_ipv6_networks &&
371 disable_link_local_networks == o.disable_link_local_networks &&
372 screencast_min_bitrate == o.screencast_min_bitrate &&
373 combined_audio_video_bwe == o.combined_audio_video_bwe &&
374 #if defined(WEBRTC_FUCHSIA)
375 enable_dtls_srtp == o.enable_dtls_srtp &&
376 #endif
377 ice_candidate_pool_size == o.ice_candidate_pool_size &&
378 prune_turn_ports == o.prune_turn_ports &&
379 turn_port_prune_policy == o.turn_port_prune_policy &&
380 presume_writable_when_fully_relayed ==
381 o.presume_writable_when_fully_relayed &&
382 enable_ice_renomination == o.enable_ice_renomination &&
383 redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart &&
384 surface_ice_candidates_on_ice_transport_type_changed ==
385 o.surface_ice_candidates_on_ice_transport_type_changed &&
386 ice_check_interval_strong_connectivity ==
387 o.ice_check_interval_strong_connectivity &&
388 ice_check_interval_weak_connectivity ==
389 o.ice_check_interval_weak_connectivity &&
390 ice_check_min_interval == o.ice_check_min_interval &&
391 ice_unwritable_timeout == o.ice_unwritable_timeout &&
392 ice_unwritable_min_checks == o.ice_unwritable_min_checks &&
393 ice_inactive_timeout == o.ice_inactive_timeout &&
394 stun_candidate_keepalive_interval ==
395 o.stun_candidate_keepalive_interval &&
396 turn_customizer == o.turn_customizer &&
397 sdp_semantics == o.sdp_semantics &&
398 network_preference == o.network_preference &&
399 active_reset_srtp_params == o.active_reset_srtp_params &&
400 crypto_options == o.crypto_options &&
401 offer_extmap_allow_mixed == o.offer_extmap_allow_mixed &&
402 turn_logging_id == o.turn_logging_id &&
403 enable_implicit_rollback == o.enable_implicit_rollback &&
404 allow_codec_switching == o.allow_codec_switching &&
405 report_usage_pattern_delay_ms == o.report_usage_pattern_delay_ms &&
406 stable_writable_connection_ping_interval_ms ==
407 o.stable_writable_connection_ping_interval_ms &&
408 vpn_preference == o.vpn_preference && vpn_list == o.vpn_list &&
409 port_allocator_config.min_port == o.port_allocator_config.min_port &&
410 port_allocator_config.max_port == o.port_allocator_config.max_port &&
411 port_allocator_config.flags == o.port_allocator_config.flags &&
412 pacer_burst_interval == o.pacer_burst_interval;
413 }
414
operator !=(const PeerConnectionInterface::RTCConfiguration & o) const415 bool PeerConnectionInterface::RTCConfiguration::operator!=(
416 const PeerConnectionInterface::RTCConfiguration& o) const {
417 return !(*this == o);
418 }
419
Create(rtc::scoped_refptr<ConnectionContext> context,const PeerConnectionFactoryInterface::Options & options,std::unique_ptr<RtcEventLog> event_log,std::unique_ptr<Call> call,const PeerConnectionInterface::RTCConfiguration & configuration,PeerConnectionDependencies dependencies)420 RTCErrorOr<rtc::scoped_refptr<PeerConnection>> PeerConnection::Create(
421 rtc::scoped_refptr<ConnectionContext> context,
422 const PeerConnectionFactoryInterface::Options& options,
423 std::unique_ptr<RtcEventLog> event_log,
424 std::unique_ptr<Call> call,
425 const PeerConnectionInterface::RTCConfiguration& configuration,
426 PeerConnectionDependencies dependencies) {
427 // TODO(https://crbug.com/webrtc/13528): Remove support for kPlanB.
428 if (configuration.sdp_semantics == SdpSemantics::kPlanB_DEPRECATED) {
429 RTC_LOG(LS_WARNING)
430 << "PeerConnection constructed with legacy SDP semantics!";
431 }
432
433 RTCError config_error = cricket::P2PTransportChannel::ValidateIceConfig(
434 ParseIceConfig(configuration));
435 if (!config_error.ok()) {
436 RTC_LOG(LS_ERROR) << "Invalid ICE configuration: "
437 << config_error.message();
438 return config_error;
439 }
440
441 if (!dependencies.allocator) {
442 RTC_LOG(LS_ERROR)
443 << "PeerConnection initialized without a PortAllocator? "
444 "This shouldn't happen if using PeerConnectionFactory.";
445 return RTCError(
446 RTCErrorType::INVALID_PARAMETER,
447 "Attempt to create a PeerConnection without a PortAllocatorFactory");
448 }
449
450 if (!dependencies.observer) {
451 // TODO(deadbeef): Why do we do this?
452 RTC_LOG(LS_ERROR) << "PeerConnection initialized without a "
453 "PeerConnectionObserver";
454 return RTCError(RTCErrorType::INVALID_PARAMETER,
455 "Attempt to create a PeerConnection without an observer");
456 }
457
458 bool is_unified_plan =
459 configuration.sdp_semantics == SdpSemantics::kUnifiedPlan;
460 bool dtls_enabled = DtlsEnabled(configuration, options, dependencies);
461
462 // Interim code: If an AsyncResolverFactory is given, but not an
463 // AsyncDnsResolverFactory, wrap it in a WrappingAsyncDnsResolverFactory
464 // If neither is given, create a WrappingAsyncDnsResolverFactory wrapping
465 // a BasicAsyncResolver.
466 // TODO(bugs.webrtc.org/12598): Remove code once all callers pass a
467 // AsyncDnsResolverFactory.
468 if (dependencies.async_dns_resolver_factory &&
469 dependencies.async_resolver_factory) {
470 RTC_LOG(LS_ERROR)
471 << "Attempt to set both old and new type of DNS resolver factory";
472 return RTCError(RTCErrorType::INVALID_PARAMETER,
473 "Both old and new type of DNS resolver given");
474 }
475 if (dependencies.async_resolver_factory) {
476 dependencies.async_dns_resolver_factory =
477 std::make_unique<WrappingAsyncDnsResolverFactory>(
478 std::move(dependencies.async_resolver_factory));
479 } else {
480 dependencies.async_dns_resolver_factory =
481 std::make_unique<WrappingAsyncDnsResolverFactory>(
482 std::make_unique<BasicAsyncResolverFactory>());
483 }
484
485 // The PeerConnection constructor consumes some, but not all, dependencies.
486 auto pc = rtc::make_ref_counted<PeerConnection>(
487 context, options, is_unified_plan, std::move(event_log), std::move(call),
488 dependencies, dtls_enabled);
489 RTCError init_error = pc->Initialize(configuration, std::move(dependencies));
490 if (!init_error.ok()) {
491 RTC_LOG(LS_ERROR) << "PeerConnection initialization failed";
492 return init_error;
493 }
494 return pc;
495 }
496
PeerConnection(rtc::scoped_refptr<ConnectionContext> context,const PeerConnectionFactoryInterface::Options & options,bool is_unified_plan,std::unique_ptr<RtcEventLog> event_log,std::unique_ptr<Call> call,PeerConnectionDependencies & dependencies,bool dtls_enabled)497 PeerConnection::PeerConnection(
498 rtc::scoped_refptr<ConnectionContext> context,
499 const PeerConnectionFactoryInterface::Options& options,
500 bool is_unified_plan,
501 std::unique_ptr<RtcEventLog> event_log,
502 std::unique_ptr<Call> call,
503 PeerConnectionDependencies& dependencies,
504 bool dtls_enabled)
505 : context_(context),
506 trials_(std::move(dependencies.trials), &context->field_trials()),
507 options_(options),
508 observer_(dependencies.observer),
509 is_unified_plan_(is_unified_plan),
510 event_log_(std::move(event_log)),
511 event_log_ptr_(event_log_.get()),
512 async_dns_resolver_factory_(
513 std::move(dependencies.async_dns_resolver_factory)),
514 port_allocator_(std::move(dependencies.allocator)),
515 ice_transport_factory_(std::move(dependencies.ice_transport_factory)),
516 tls_cert_verifier_(std::move(dependencies.tls_cert_verifier)),
517 call_(std::move(call)),
518 call_ptr_(call_.get()),
519 // RFC 3264: The numeric value of the session id and version in the
520 // o line MUST be representable with a "64 bit signed integer".
521 // Due to this constraint session id `session_id_` is max limited to
522 // LLONG_MAX.
523 session_id_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
524 dtls_enabled_(dtls_enabled),
525 data_channel_controller_(this),
526 message_handler_(signaling_thread()),
527 weak_factory_(this) {
528 worker_thread()->BlockingCall([this] {
529 RTC_DCHECK_RUN_ON(worker_thread());
530 worker_thread_safety_ = PendingTaskSafetyFlag::Create();
531 if (!call_)
532 worker_thread_safety_->SetNotAlive();
533 });
534 }
535
~PeerConnection()536 PeerConnection::~PeerConnection() {
537 TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
538 RTC_DCHECK_RUN_ON(signaling_thread());
539
540 if (sdp_handler_) {
541 sdp_handler_->PrepareForShutdown();
542 }
543
544 // Need to stop transceivers before destroying the stats collector because
545 // AudioRtpSender has a reference to the LegacyStatsCollector it will update
546 // when stopping.
547 if (rtp_manager()) {
548 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
549 transceiver->StopInternal();
550 }
551 }
552
553 legacy_stats_.reset(nullptr);
554 if (stats_collector_) {
555 stats_collector_->WaitForPendingRequest();
556 stats_collector_ = nullptr;
557 }
558
559 if (sdp_handler_) {
560 // Don't destroy BaseChannels until after stats has been cleaned up so that
561 // the last stats request can still read from the channels.
562 sdp_handler_->DestroyAllChannels();
563
564 RTC_LOG(LS_INFO) << "Session: " << session_id() << " is destroyed.";
565
566 sdp_handler_->ResetSessionDescFactory();
567 }
568
569 // port_allocator_ and transport_controller_ live on the network thread and
570 // should be destroyed there.
571 transport_controller_copy_ = nullptr;
572 network_thread()->BlockingCall([this] {
573 RTC_DCHECK_RUN_ON(network_thread());
574 TeardownDataChannelTransport_n();
575 transport_controller_.reset();
576 port_allocator_.reset();
577 if (network_thread_safety_)
578 network_thread_safety_->SetNotAlive();
579 });
580
581 // call_ and event_log_ must be destroyed on the worker thread.
582 worker_thread()->BlockingCall([this] {
583 RTC_DCHECK_RUN_ON(worker_thread());
584 worker_thread_safety_->SetNotAlive();
585 call_.reset();
586 // The event log must outlive call (and any other object that uses it).
587 event_log_.reset();
588 });
589 }
590
Initialize(const PeerConnectionInterface::RTCConfiguration & configuration,PeerConnectionDependencies dependencies)591 RTCError PeerConnection::Initialize(
592 const PeerConnectionInterface::RTCConfiguration& configuration,
593 PeerConnectionDependencies dependencies) {
594 RTC_DCHECK_RUN_ON(signaling_thread());
595 TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
596
597 cricket::ServerAddresses stun_servers;
598 std::vector<cricket::RelayServerConfig> turn_servers;
599
600 RTCError parse_error = ParseIceServersOrError(configuration.servers,
601 &stun_servers, &turn_servers);
602 if (!parse_error.ok()) {
603 return parse_error;
604 }
605
606 // Restrict number of TURN servers.
607 if (!trials().IsDisabled("WebRTC-LimitTurnServers") &&
608 turn_servers.size() > cricket::kMaxTurnServers) {
609 RTC_LOG(LS_WARNING) << "Number of configured TURN servers is "
610 << turn_servers.size()
611 << " which exceeds the maximum allowed number of "
612 << cricket::kMaxTurnServers;
613 turn_servers.resize(cricket::kMaxTurnServers);
614 }
615
616 // Add the turn logging id to all turn servers
617 for (cricket::RelayServerConfig& turn_server : turn_servers) {
618 turn_server.turn_logging_id = configuration.turn_logging_id;
619 }
620
621 // Note if STUN or TURN servers were supplied.
622 if (!stun_servers.empty()) {
623 NoteUsageEvent(UsageEvent::STUN_SERVER_ADDED);
624 }
625 if (!turn_servers.empty()) {
626 NoteUsageEvent(UsageEvent::TURN_SERVER_ADDED);
627 }
628
629 // Network thread initialization.
630 transport_controller_copy_ =
631 network_thread()->BlockingCall([&] {
632 RTC_DCHECK_RUN_ON(network_thread());
633 network_thread_safety_ = PendingTaskSafetyFlag::Create();
634 InitializePortAllocatorResult pa_result = InitializePortAllocator_n(
635 stun_servers, turn_servers, configuration);
636 // Send information about IPv4/IPv6 status.
637 PeerConnectionAddressFamilyCounter address_family =
638 pa_result.enable_ipv6 ? kPeerConnection_IPv6 : kPeerConnection_IPv4;
639 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
640 address_family,
641 kPeerConnectionAddressFamilyCounter_Max);
642 return InitializeTransportController_n(configuration, dependencies);
643 });
644
645 configuration_ = configuration;
646
647 legacy_stats_ = std::make_unique<LegacyStatsCollector>(this);
648 stats_collector_ = RTCStatsCollector::Create(this);
649
650 sdp_handler_ = SdpOfferAnswerHandler::Create(this, configuration,
651 dependencies, context_.get());
652
653 rtp_manager_ = std::make_unique<RtpTransmissionManager>(
654 IsUnifiedPlan(), context_.get(), &usage_pattern_, observer_,
655 legacy_stats_.get(), [this]() {
656 RTC_DCHECK_RUN_ON(signaling_thread());
657 sdp_handler_->UpdateNegotiationNeeded();
658 });
659
660 // Add default audio/video transceivers for Plan B SDP.
661 if (!IsUnifiedPlan()) {
662 rtp_manager()->transceivers()->Add(
663 RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
664 signaling_thread(), rtc::make_ref_counted<RtpTransceiver>(
665 cricket::MEDIA_TYPE_AUDIO, context())));
666 rtp_manager()->transceivers()->Add(
667 RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
668 signaling_thread(), rtc::make_ref_counted<RtpTransceiver>(
669 cricket::MEDIA_TYPE_VIDEO, context())));
670 }
671
672 int delay_ms = configuration.report_usage_pattern_delay_ms
673 ? *configuration.report_usage_pattern_delay_ms
674 : REPORT_USAGE_PATTERN_DELAY_MS;
675 message_handler_.RequestUsagePatternReport(
676 [this]() {
677 RTC_DCHECK_RUN_ON(signaling_thread());
678 ReportUsagePattern();
679 },
680 delay_ms);
681
682 return RTCError::OK();
683 }
684
InitializeTransportController_n(const RTCConfiguration & configuration,const PeerConnectionDependencies & dependencies)685 JsepTransportController* PeerConnection::InitializeTransportController_n(
686 const RTCConfiguration& configuration,
687 const PeerConnectionDependencies& dependencies) {
688 JsepTransportController::Config config;
689 config.redetermine_role_on_ice_restart =
690 configuration.redetermine_role_on_ice_restart;
691 config.ssl_max_version = options_.ssl_max_version;
692 config.disable_encryption = options_.disable_encryption;
693 config.bundle_policy = configuration.bundle_policy;
694 config.rtcp_mux_policy = configuration.rtcp_mux_policy;
695 // TODO(bugs.webrtc.org/9891) - Remove options_.crypto_options then remove
696 // this stub.
697 config.crypto_options = configuration.crypto_options.has_value()
698 ? *configuration.crypto_options
699 : options_.crypto_options;
700 config.transport_observer = this;
701 config.rtcp_handler = InitializeRtcpCallback();
702 config.event_log = event_log_ptr_;
703 #if defined(ENABLE_EXTERNAL_AUTH)
704 config.enable_external_auth = true;
705 #endif
706 config.active_reset_srtp_params = configuration.active_reset_srtp_params;
707
708 // DTLS has to be enabled to use SCTP.
709 if (dtls_enabled_) {
710 config.sctp_factory = context_->sctp_transport_factory();
711 }
712
713 config.ice_transport_factory = ice_transport_factory_.get();
714 config.on_dtls_handshake_error_ =
715 [weak_ptr = weak_factory_.GetWeakPtr()](rtc::SSLHandshakeError s) {
716 if (weak_ptr) {
717 weak_ptr->OnTransportControllerDtlsHandshakeError(s);
718 }
719 };
720
721 config.field_trials = trials_.get();
722
723 transport_controller_.reset(
724 new JsepTransportController(network_thread(), port_allocator_.get(),
725 async_dns_resolver_factory_.get(), config));
726
727 transport_controller_->SubscribeIceConnectionState(
728 [this](cricket::IceConnectionState s) {
729 RTC_DCHECK_RUN_ON(network_thread());
730 if (s == cricket::kIceConnectionConnected) {
731 ReportTransportStats();
732 }
733 signaling_thread()->PostTask(
734 SafeTask(signaling_thread_safety_.flag(), [this, s]() {
735 RTC_DCHECK_RUN_ON(signaling_thread());
736 OnTransportControllerConnectionState(s);
737 }));
738 });
739 transport_controller_->SubscribeConnectionState(
740 [this](PeerConnectionInterface::PeerConnectionState s) {
741 RTC_DCHECK_RUN_ON(network_thread());
742 signaling_thread()->PostTask(
743 SafeTask(signaling_thread_safety_.flag(), [this, s]() {
744 RTC_DCHECK_RUN_ON(signaling_thread());
745 SetConnectionState(s);
746 }));
747 });
748 transport_controller_->SubscribeStandardizedIceConnectionState(
749 [this](PeerConnectionInterface::IceConnectionState s) {
750 RTC_DCHECK_RUN_ON(network_thread());
751 signaling_thread()->PostTask(
752 SafeTask(signaling_thread_safety_.flag(), [this, s]() {
753 RTC_DCHECK_RUN_ON(signaling_thread());
754 SetStandardizedIceConnectionState(s);
755 }));
756 });
757 transport_controller_->SubscribeIceGatheringState(
758 [this](cricket::IceGatheringState s) {
759 RTC_DCHECK_RUN_ON(network_thread());
760 signaling_thread()->PostTask(
761 SafeTask(signaling_thread_safety_.flag(), [this, s]() {
762 RTC_DCHECK_RUN_ON(signaling_thread());
763 OnTransportControllerGatheringState(s);
764 }));
765 });
766 transport_controller_->SubscribeIceCandidateGathered(
767 [this](const std::string& transport,
768 const std::vector<cricket::Candidate>& candidates) {
769 RTC_DCHECK_RUN_ON(network_thread());
770 signaling_thread()->PostTask(
771 SafeTask(signaling_thread_safety_.flag(),
772 [this, t = transport, c = candidates]() {
773 RTC_DCHECK_RUN_ON(signaling_thread());
774 OnTransportControllerCandidatesGathered(t, c);
775 }));
776 });
777 transport_controller_->SubscribeIceCandidateError(
778 [this](const cricket::IceCandidateErrorEvent& event) {
779 RTC_DCHECK_RUN_ON(network_thread());
780 signaling_thread()->PostTask(
781 SafeTask(signaling_thread_safety_.flag(), [this, event = event]() {
782 RTC_DCHECK_RUN_ON(signaling_thread());
783 OnTransportControllerCandidateError(event);
784 }));
785 });
786 transport_controller_->SubscribeIceCandidatesRemoved(
787 [this](const std::vector<cricket::Candidate>& c) {
788 RTC_DCHECK_RUN_ON(network_thread());
789 signaling_thread()->PostTask(
790 SafeTask(signaling_thread_safety_.flag(), [this, c = c]() {
791 RTC_DCHECK_RUN_ON(signaling_thread());
792 OnTransportControllerCandidatesRemoved(c);
793 }));
794 });
795 transport_controller_->SubscribeIceCandidatePairChanged(
796 [this](const cricket::CandidatePairChangeEvent& event) {
797 RTC_DCHECK_RUN_ON(network_thread());
798 signaling_thread()->PostTask(
799 SafeTask(signaling_thread_safety_.flag(), [this, event = event]() {
800 RTC_DCHECK_RUN_ON(signaling_thread());
801 OnTransportControllerCandidateChanged(event);
802 }));
803 });
804
805 transport_controller_->SetIceConfig(ParseIceConfig(configuration));
806 return transport_controller_.get();
807 }
808
local_streams()809 rtc::scoped_refptr<StreamCollectionInterface> PeerConnection::local_streams() {
810 RTC_DCHECK_RUN_ON(signaling_thread());
811 RTC_CHECK(!IsUnifiedPlan()) << "local_streams is not available with Unified "
812 "Plan SdpSemantics. Please use GetSenders "
813 "instead.";
814 return sdp_handler_->local_streams();
815 }
816
remote_streams()817 rtc::scoped_refptr<StreamCollectionInterface> PeerConnection::remote_streams() {
818 RTC_DCHECK_RUN_ON(signaling_thread());
819 RTC_CHECK(!IsUnifiedPlan()) << "remote_streams is not available with Unified "
820 "Plan SdpSemantics. Please use GetReceivers "
821 "instead.";
822 return sdp_handler_->remote_streams();
823 }
824
AddStream(MediaStreamInterface * local_stream)825 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
826 RTC_DCHECK_RUN_ON(signaling_thread());
827 RTC_CHECK(!IsUnifiedPlan()) << "AddStream is not available with Unified Plan "
828 "SdpSemantics. Please use AddTrack instead.";
829 TRACE_EVENT0("webrtc", "PeerConnection::AddStream");
830 if (!ConfiguredForMedia()) {
831 RTC_LOG(LS_ERROR) << "AddStream: Not configured for media";
832 return false;
833 }
834 return sdp_handler_->AddStream(local_stream);
835 }
836
RemoveStream(MediaStreamInterface * local_stream)837 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
838 RTC_DCHECK_RUN_ON(signaling_thread());
839 RTC_DCHECK(ConfiguredForMedia());
840 RTC_CHECK(!IsUnifiedPlan()) << "RemoveStream is not available with Unified "
841 "Plan SdpSemantics. Please use RemoveTrack "
842 "instead.";
843 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
844 sdp_handler_->RemoveStream(local_stream);
845 }
846
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids)847 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
848 rtc::scoped_refptr<MediaStreamTrackInterface> track,
849 const std::vector<std::string>& stream_ids) {
850 return AddTrack(std::move(track), stream_ids, nullptr);
851 }
852
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids,const std::vector<RtpEncodingParameters> & init_send_encodings)853 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
854 rtc::scoped_refptr<MediaStreamTrackInterface> track,
855 const std::vector<std::string>& stream_ids,
856 const std::vector<RtpEncodingParameters>& init_send_encodings) {
857 return AddTrack(std::move(track), stream_ids, &init_send_encodings);
858 }
859
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids,const std::vector<RtpEncodingParameters> * init_send_encodings)860 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
861 rtc::scoped_refptr<MediaStreamTrackInterface> track,
862 const std::vector<std::string>& stream_ids,
863 const std::vector<RtpEncodingParameters>* init_send_encodings) {
864 RTC_DCHECK_RUN_ON(signaling_thread());
865 TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
866 if (!ConfiguredForMedia()) {
867 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
868 "Not configured for media");
869 }
870 if (!track) {
871 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Track is null.");
872 }
873 if (!(track->kind() == MediaStreamTrackInterface::kAudioKind ||
874 track->kind() == MediaStreamTrackInterface::kVideoKind)) {
875 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
876 "Track has invalid kind: " + track->kind());
877 }
878 if (IsClosed()) {
879 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
880 "PeerConnection is closed.");
881 }
882 if (rtp_manager()->FindSenderForTrack(track.get())) {
883 LOG_AND_RETURN_ERROR(
884 RTCErrorType::INVALID_PARAMETER,
885 "Sender already exists for track " + track->id() + ".");
886 }
887 auto sender_or_error =
888 rtp_manager()->AddTrack(track, stream_ids, init_send_encodings);
889 if (sender_or_error.ok()) {
890 sdp_handler_->UpdateNegotiationNeeded();
891 legacy_stats_->AddTrack(track.get());
892 }
893 return sender_or_error;
894 }
895
RemoveTrackOrError(rtc::scoped_refptr<RtpSenderInterface> sender)896 RTCError PeerConnection::RemoveTrackOrError(
897 rtc::scoped_refptr<RtpSenderInterface> sender) {
898 RTC_DCHECK_RUN_ON(signaling_thread());
899 if (!ConfiguredForMedia()) {
900 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
901 "Not configured for media");
902 }
903 if (!sender) {
904 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "Sender is null.");
905 }
906 if (IsClosed()) {
907 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
908 "PeerConnection is closed.");
909 }
910 if (IsUnifiedPlan()) {
911 auto transceiver = FindTransceiverBySender(sender);
912 if (!transceiver || !sender->track()) {
913 return RTCError::OK();
914 }
915 sender->SetTrack(nullptr);
916 if (transceiver->direction() == RtpTransceiverDirection::kSendRecv) {
917 transceiver->internal()->set_direction(
918 RtpTransceiverDirection::kRecvOnly);
919 } else if (transceiver->direction() == RtpTransceiverDirection::kSendOnly) {
920 transceiver->internal()->set_direction(
921 RtpTransceiverDirection::kInactive);
922 }
923 } else {
924 bool removed;
925 if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
926 removed = rtp_manager()->GetAudioTransceiver()->internal()->RemoveSender(
927 sender.get());
928 } else {
929 RTC_DCHECK_EQ(cricket::MEDIA_TYPE_VIDEO, sender->media_type());
930 removed = rtp_manager()->GetVideoTransceiver()->internal()->RemoveSender(
931 sender.get());
932 }
933 if (!removed) {
934 LOG_AND_RETURN_ERROR(
935 RTCErrorType::INVALID_PARAMETER,
936 "Couldn't find sender " + sender->id() + " to remove.");
937 }
938 }
939 sdp_handler_->UpdateNegotiationNeeded();
940 return RTCError::OK();
941 }
942
943 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
FindTransceiverBySender(rtc::scoped_refptr<RtpSenderInterface> sender)944 PeerConnection::FindTransceiverBySender(
945 rtc::scoped_refptr<RtpSenderInterface> sender) {
946 return rtp_manager()->transceivers()->FindBySender(sender);
947 }
948
949 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track)950 PeerConnection::AddTransceiver(
951 rtc::scoped_refptr<MediaStreamTrackInterface> track) {
952 if (!ConfiguredForMedia()) {
953 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
954 "Not configured for media");
955 }
956
957 return AddTransceiver(track, RtpTransceiverInit());
958 }
959
GetRtpTransport(const std::string & mid)960 RtpTransportInternal* PeerConnection::GetRtpTransport(const std::string& mid) {
961 // TODO(bugs.webrtc.org/9987): Avoid the thread jump.
962 // This might be done by caching the value on the signaling thread.
963 RTC_DCHECK_RUN_ON(signaling_thread());
964 return network_thread()->BlockingCall([this, &mid] {
965 RTC_DCHECK_RUN_ON(network_thread());
966 auto rtp_transport = transport_controller_->GetRtpTransport(mid);
967 RTC_DCHECK(rtp_transport);
968 return rtp_transport;
969 });
970 }
971
972 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,const RtpTransceiverInit & init)973 PeerConnection::AddTransceiver(
974 rtc::scoped_refptr<MediaStreamTrackInterface> track,
975 const RtpTransceiverInit& init) {
976 RTC_DCHECK_RUN_ON(signaling_thread());
977 if (!ConfiguredForMedia()) {
978 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
979 "Not configured for media");
980 }
981 RTC_CHECK(IsUnifiedPlan())
982 << "AddTransceiver is only available with Unified Plan SdpSemantics";
983 if (!track) {
984 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "track is null");
985 }
986 cricket::MediaType media_type;
987 if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
988 media_type = cricket::MEDIA_TYPE_AUDIO;
989 } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
990 media_type = cricket::MEDIA_TYPE_VIDEO;
991 } else {
992 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
993 "Track kind is not audio or video");
994 }
995 return AddTransceiver(media_type, track, init);
996 }
997
998 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
AddTransceiver(cricket::MediaType media_type)999 PeerConnection::AddTransceiver(cricket::MediaType media_type) {
1000 return AddTransceiver(media_type, RtpTransceiverInit());
1001 }
1002
1003 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
AddTransceiver(cricket::MediaType media_type,const RtpTransceiverInit & init)1004 PeerConnection::AddTransceiver(cricket::MediaType media_type,
1005 const RtpTransceiverInit& init) {
1006 RTC_DCHECK_RUN_ON(signaling_thread());
1007 if (!ConfiguredForMedia()) {
1008 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
1009 "Not configured for media");
1010 }
1011 RTC_CHECK(IsUnifiedPlan())
1012 << "AddTransceiver is only available with Unified Plan SdpSemantics";
1013 if (!(media_type == cricket::MEDIA_TYPE_AUDIO ||
1014 media_type == cricket::MEDIA_TYPE_VIDEO)) {
1015 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1016 "media type is not audio or video");
1017 }
1018 return AddTransceiver(media_type, nullptr, init);
1019 }
1020
1021 RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
AddTransceiver(cricket::MediaType media_type,rtc::scoped_refptr<MediaStreamTrackInterface> track,const RtpTransceiverInit & init,bool update_negotiation_needed)1022 PeerConnection::AddTransceiver(
1023 cricket::MediaType media_type,
1024 rtc::scoped_refptr<MediaStreamTrackInterface> track,
1025 const RtpTransceiverInit& init,
1026 bool update_negotiation_needed) {
1027 RTC_DCHECK_RUN_ON(signaling_thread());
1028 if (!ConfiguredForMedia()) {
1029 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
1030 "Not configured for media");
1031 }
1032 RTC_DCHECK((media_type == cricket::MEDIA_TYPE_AUDIO ||
1033 media_type == cricket::MEDIA_TYPE_VIDEO));
1034 if (track) {
1035 RTC_DCHECK_EQ(media_type,
1036 (track->kind() == MediaStreamTrackInterface::kAudioKind
1037 ? cricket::MEDIA_TYPE_AUDIO
1038 : cricket::MEDIA_TYPE_VIDEO));
1039 }
1040
1041 RTC_HISTOGRAM_COUNTS_LINEAR(kSimulcastNumberOfEncodings,
1042 init.send_encodings.size(), 0, 7, 8);
1043
1044 size_t num_rids = absl::c_count_if(init.send_encodings,
1045 [](const RtpEncodingParameters& encoding) {
1046 return !encoding.rid.empty();
1047 });
1048 if (num_rids > 0 && num_rids != init.send_encodings.size()) {
1049 LOG_AND_RETURN_ERROR(
1050 RTCErrorType::INVALID_PARAMETER,
1051 "RIDs must be provided for either all or none of the send encodings.");
1052 }
1053
1054 if (num_rids > 0 && absl::c_any_of(init.send_encodings,
1055 [](const RtpEncodingParameters& encoding) {
1056 return !IsLegalRsidName(encoding.rid);
1057 })) {
1058 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1059 "Invalid RID value provided.");
1060 }
1061
1062 if (absl::c_any_of(init.send_encodings,
1063 [](const RtpEncodingParameters& encoding) {
1064 return encoding.ssrc.has_value();
1065 })) {
1066 LOG_AND_RETURN_ERROR(
1067 RTCErrorType::UNSUPPORTED_PARAMETER,
1068 "Attempted to set an unimplemented parameter of RtpParameters.");
1069 }
1070
1071 RtpParameters parameters;
1072 parameters.encodings = init.send_encodings;
1073
1074 // Encodings are dropped from the tail if too many are provided.
1075 size_t max_simulcast_streams =
1076 media_type == cricket::MEDIA_TYPE_VIDEO ? kMaxSimulcastStreams : 1u;
1077 if (parameters.encodings.size() > max_simulcast_streams) {
1078 parameters.encodings.erase(
1079 parameters.encodings.begin() + max_simulcast_streams,
1080 parameters.encodings.end());
1081 }
1082
1083 // Single RID should be removed.
1084 if (parameters.encodings.size() == 1 &&
1085 !parameters.encodings[0].rid.empty()) {
1086 RTC_LOG(LS_INFO) << "Removing RID: " << parameters.encodings[0].rid << ".";
1087 parameters.encodings[0].rid.clear();
1088 }
1089
1090 // If RIDs were not provided, they are generated for simulcast scenario.
1091 if (parameters.encodings.size() > 1 && num_rids == 0) {
1092 rtc::UniqueStringGenerator rid_generator;
1093 for (RtpEncodingParameters& encoding : parameters.encodings) {
1094 encoding.rid = rid_generator();
1095 }
1096 }
1097
1098 if (UnimplementedRtpParameterHasValue(parameters)) {
1099 LOG_AND_RETURN_ERROR(
1100 RTCErrorType::UNSUPPORTED_PARAMETER,
1101 "Attempted to set an unimplemented parameter of RtpParameters.");
1102 }
1103
1104 std::vector<cricket::VideoCodec> codecs;
1105 if (media_type == cricket::MEDIA_TYPE_VIDEO) {
1106 // Gather the current codec capabilities to allow checking scalabilityMode
1107 // against supported values.
1108 codecs = context_->media_engine()->video().send_codecs(false);
1109 }
1110
1111 auto result = cricket::CheckRtpParametersValues(parameters, codecs);
1112 if (!result.ok()) {
1113 LOG_AND_RETURN_ERROR(result.type(), result.message());
1114 }
1115
1116 RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
1117 << " transceiver in response to a call to AddTransceiver.";
1118 // Set the sender ID equal to the track ID if the track is specified unless
1119 // that sender ID is already in use.
1120 std::string sender_id = (track && !rtp_manager()->FindSenderById(track->id())
1121 ? track->id()
1122 : rtc::CreateRandomUuid());
1123 auto sender = rtp_manager()->CreateSender(
1124 media_type, sender_id, track, init.stream_ids, parameters.encodings);
1125 auto receiver =
1126 rtp_manager()->CreateReceiver(media_type, rtc::CreateRandomUuid());
1127 auto transceiver = rtp_manager()->CreateAndAddTransceiver(sender, receiver);
1128 transceiver->internal()->set_direction(init.direction);
1129
1130 if (update_negotiation_needed) {
1131 sdp_handler_->UpdateNegotiationNeeded();
1132 }
1133
1134 return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
1135 }
1136
OnNegotiationNeeded()1137 void PeerConnection::OnNegotiationNeeded() {
1138 RTC_DCHECK_RUN_ON(signaling_thread());
1139 RTC_DCHECK(!IsClosed());
1140 sdp_handler_->UpdateNegotiationNeeded();
1141 }
1142
CreateSender(const std::string & kind,const std::string & stream_id)1143 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
1144 const std::string& kind,
1145 const std::string& stream_id) {
1146 RTC_DCHECK_RUN_ON(signaling_thread());
1147 if (!ConfiguredForMedia()) {
1148 RTC_LOG(LS_ERROR) << "Not configured for media";
1149 return nullptr;
1150 }
1151 RTC_CHECK(!IsUnifiedPlan()) << "CreateSender is not available with Unified "
1152 "Plan SdpSemantics. Please use AddTransceiver "
1153 "instead.";
1154 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
1155 if (IsClosed()) {
1156 return nullptr;
1157 }
1158
1159 // Internally we need to have one stream with Plan B semantics, so we
1160 // generate a random stream ID if not specified.
1161 std::vector<std::string> stream_ids;
1162 if (stream_id.empty()) {
1163 stream_ids.push_back(rtc::CreateRandomUuid());
1164 RTC_LOG(LS_INFO)
1165 << "No stream_id specified for sender. Generated stream ID: "
1166 << stream_ids[0];
1167 } else {
1168 stream_ids.push_back(stream_id);
1169 }
1170
1171 // TODO(steveanton): Move construction of the RtpSenders to RtpTransceiver.
1172 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
1173 if (kind == MediaStreamTrackInterface::kAudioKind) {
1174 auto audio_sender =
1175 AudioRtpSender::Create(worker_thread(), rtc::CreateRandomUuid(),
1176 legacy_stats_.get(), rtp_manager());
1177 audio_sender->SetMediaChannel(rtp_manager()->voice_media_channel());
1178 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
1179 signaling_thread(), audio_sender);
1180 rtp_manager()->GetAudioTransceiver()->internal()->AddSender(new_sender);
1181 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
1182 auto video_sender = VideoRtpSender::Create(
1183 worker_thread(), rtc::CreateRandomUuid(), rtp_manager());
1184 video_sender->SetMediaChannel(rtp_manager()->video_media_channel());
1185 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
1186 signaling_thread(), video_sender);
1187 rtp_manager()->GetVideoTransceiver()->internal()->AddSender(new_sender);
1188 } else {
1189 RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
1190 return nullptr;
1191 }
1192 new_sender->internal()->set_stream_ids(stream_ids);
1193
1194 return new_sender;
1195 }
1196
GetSenders() const1197 std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
1198 const {
1199 RTC_DCHECK_RUN_ON(signaling_thread());
1200 std::vector<rtc::scoped_refptr<RtpSenderInterface>> ret;
1201 if (ConfiguredForMedia()) {
1202 for (const auto& sender : rtp_manager()->GetSendersInternal()) {
1203 ret.push_back(sender);
1204 }
1205 }
1206 return ret;
1207 }
1208
1209 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
GetReceivers() const1210 PeerConnection::GetReceivers() const {
1211 RTC_DCHECK_RUN_ON(signaling_thread());
1212 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> ret;
1213 if (ConfiguredForMedia()) {
1214 for (const auto& receiver : rtp_manager()->GetReceiversInternal()) {
1215 ret.push_back(receiver);
1216 }
1217 }
1218 return ret;
1219 }
1220
1221 std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
GetTransceivers() const1222 PeerConnection::GetTransceivers() const {
1223 RTC_DCHECK_RUN_ON(signaling_thread());
1224 RTC_CHECK(IsUnifiedPlan())
1225 << "GetTransceivers is only supported with Unified Plan SdpSemantics.";
1226 std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> all_transceivers;
1227 if (ConfiguredForMedia()) {
1228 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
1229 all_transceivers.push_back(transceiver);
1230 }
1231 }
1232 return all_transceivers;
1233 }
1234
GetStats(StatsObserver * observer,MediaStreamTrackInterface * track,StatsOutputLevel level)1235 bool PeerConnection::GetStats(StatsObserver* observer,
1236 MediaStreamTrackInterface* track,
1237 StatsOutputLevel level) {
1238 TRACE_EVENT0("webrtc", "PeerConnection::GetStats (legacy)");
1239 RTC_DCHECK_RUN_ON(signaling_thread());
1240 if (!observer) {
1241 RTC_LOG(LS_ERROR) << "Legacy GetStats - observer is NULL.";
1242 return false;
1243 }
1244
1245 RTC_LOG_THREAD_BLOCK_COUNT();
1246
1247 legacy_stats_->UpdateStats(level);
1248
1249 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(4);
1250
1251 // The LegacyStatsCollector is used to tell if a track is valid because it may
1252 // remember tracks that the PeerConnection previously removed.
1253 if (track && !legacy_stats_->IsValidTrack(track->id())) {
1254 RTC_LOG(LS_WARNING) << "Legacy GetStats is called with an invalid track: "
1255 << track->id();
1256 return false;
1257 }
1258 message_handler_.PostGetStats(observer, legacy_stats_.get(), track);
1259
1260 return true;
1261 }
1262
GetStats(RTCStatsCollectorCallback * callback)1263 void PeerConnection::GetStats(RTCStatsCollectorCallback* callback) {
1264 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
1265 RTC_DCHECK_RUN_ON(signaling_thread());
1266 RTC_DCHECK(stats_collector_);
1267 RTC_DCHECK(callback);
1268 RTC_LOG_THREAD_BLOCK_COUNT();
1269 stats_collector_->GetStatsReport(
1270 rtc::scoped_refptr<RTCStatsCollectorCallback>(callback));
1271 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
1272 }
1273
GetStats(rtc::scoped_refptr<RtpSenderInterface> selector,rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1274 void PeerConnection::GetStats(
1275 rtc::scoped_refptr<RtpSenderInterface> selector,
1276 rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1277 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
1278 RTC_DCHECK_RUN_ON(signaling_thread());
1279 RTC_DCHECK(callback);
1280 RTC_DCHECK(stats_collector_);
1281 RTC_LOG_THREAD_BLOCK_COUNT();
1282 rtc::scoped_refptr<RtpSenderInternal> internal_sender;
1283 if (selector) {
1284 for (const auto& proxy_transceiver :
1285 rtp_manager()->transceivers()->List()) {
1286 for (const auto& proxy_sender :
1287 proxy_transceiver->internal()->senders()) {
1288 if (proxy_sender == selector) {
1289 internal_sender = proxy_sender->internal();
1290 break;
1291 }
1292 }
1293 if (internal_sender)
1294 break;
1295 }
1296 }
1297 // If there is no `internal_sender` then `selector` is either null or does not
1298 // belong to the PeerConnection (in Plan B, senders can be removed from the
1299 // PeerConnection). This means that "all the stats objects representing the
1300 // selector" is an empty set. Invoking GetStatsReport() with a null selector
1301 // produces an empty stats report.
1302 stats_collector_->GetStatsReport(internal_sender, callback);
1303 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
1304 }
1305
GetStats(rtc::scoped_refptr<RtpReceiverInterface> selector,rtc::scoped_refptr<RTCStatsCollectorCallback> callback)1306 void PeerConnection::GetStats(
1307 rtc::scoped_refptr<RtpReceiverInterface> selector,
1308 rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
1309 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
1310 RTC_DCHECK_RUN_ON(signaling_thread());
1311 RTC_DCHECK(callback);
1312 RTC_DCHECK(stats_collector_);
1313 RTC_LOG_THREAD_BLOCK_COUNT();
1314 rtc::scoped_refptr<RtpReceiverInternal> internal_receiver;
1315 if (selector) {
1316 for (const auto& proxy_transceiver :
1317 rtp_manager()->transceivers()->List()) {
1318 for (const auto& proxy_receiver :
1319 proxy_transceiver->internal()->receivers()) {
1320 if (proxy_receiver == selector) {
1321 internal_receiver = proxy_receiver->internal();
1322 break;
1323 }
1324 }
1325 if (internal_receiver)
1326 break;
1327 }
1328 }
1329 // If there is no `internal_receiver` then `selector` is either null or does
1330 // not belong to the PeerConnection (in Plan B, receivers can be removed from
1331 // the PeerConnection). This means that "all the stats objects representing
1332 // the selector" is an empty set. Invoking GetStatsReport() with a null
1333 // selector produces an empty stats report.
1334 stats_collector_->GetStatsReport(internal_receiver, callback);
1335 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
1336 }
1337
signaling_state()1338 PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
1339 RTC_DCHECK_RUN_ON(signaling_thread());
1340 return sdp_handler_->signaling_state();
1341 }
1342
1343 PeerConnectionInterface::IceConnectionState
ice_connection_state()1344 PeerConnection::ice_connection_state() {
1345 RTC_DCHECK_RUN_ON(signaling_thread());
1346 return ice_connection_state_;
1347 }
1348
1349 PeerConnectionInterface::IceConnectionState
standardized_ice_connection_state()1350 PeerConnection::standardized_ice_connection_state() {
1351 RTC_DCHECK_RUN_ON(signaling_thread());
1352 return standardized_ice_connection_state_;
1353 }
1354
1355 PeerConnectionInterface::PeerConnectionState
peer_connection_state()1356 PeerConnection::peer_connection_state() {
1357 RTC_DCHECK_RUN_ON(signaling_thread());
1358 return connection_state_;
1359 }
1360
1361 PeerConnectionInterface::IceGatheringState
ice_gathering_state()1362 PeerConnection::ice_gathering_state() {
1363 RTC_DCHECK_RUN_ON(signaling_thread());
1364 return ice_gathering_state_;
1365 }
1366
can_trickle_ice_candidates()1367 absl::optional<bool> PeerConnection::can_trickle_ice_candidates() {
1368 RTC_DCHECK_RUN_ON(signaling_thread());
1369 const SessionDescriptionInterface* description = current_remote_description();
1370 if (!description) {
1371 description = pending_remote_description();
1372 }
1373 if (!description) {
1374 return absl::nullopt;
1375 }
1376 // TODO(bugs.webrtc.org/7443): Change to retrieve from session-level option.
1377 if (description->description()->transport_infos().size() < 1) {
1378 return absl::nullopt;
1379 }
1380 return description->description()->transport_infos()[0].description.HasOption(
1381 "trickle");
1382 }
1383
1384 RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>>
CreateDataChannelOrError(const std::string & label,const DataChannelInit * config)1385 PeerConnection::CreateDataChannelOrError(const std::string& label,
1386 const DataChannelInit* config) {
1387 RTC_DCHECK_RUN_ON(signaling_thread());
1388 TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
1389
1390 bool first_datachannel = !data_channel_controller_.HasDataChannels();
1391
1392 std::unique_ptr<InternalDataChannelInit> internal_config;
1393 if (config) {
1394 internal_config.reset(new InternalDataChannelInit(*config));
1395 }
1396 // TODO(bugs.webrtc.org/12796): Return a more specific error.
1397 rtc::scoped_refptr<DataChannelInterface> channel(
1398 data_channel_controller_.InternalCreateDataChannelWithProxy(
1399 label, internal_config.get()));
1400 if (!channel.get()) {
1401 return RTCError(RTCErrorType::INTERNAL_ERROR,
1402 "Data channel creation failed");
1403 }
1404
1405 // Trigger the onRenegotiationNeeded event for
1406 // the first SCTP DataChannel.
1407 if (first_datachannel) {
1408 sdp_handler_->UpdateNegotiationNeeded();
1409 }
1410 NoteUsageEvent(UsageEvent::DATA_ADDED);
1411 return channel;
1412 }
1413
RestartIce()1414 void PeerConnection::RestartIce() {
1415 RTC_DCHECK_RUN_ON(signaling_thread());
1416 sdp_handler_->RestartIce();
1417 }
1418
CreateOffer(CreateSessionDescriptionObserver * observer,const RTCOfferAnswerOptions & options)1419 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
1420 const RTCOfferAnswerOptions& options) {
1421 RTC_DCHECK_RUN_ON(signaling_thread());
1422 sdp_handler_->CreateOffer(observer, options);
1423 }
1424
CreateAnswer(CreateSessionDescriptionObserver * observer,const RTCOfferAnswerOptions & options)1425 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
1426 const RTCOfferAnswerOptions& options) {
1427 RTC_DCHECK_RUN_ON(signaling_thread());
1428 sdp_handler_->CreateAnswer(observer, options);
1429 }
1430
SetLocalDescription(SetSessionDescriptionObserver * observer,SessionDescriptionInterface * desc_ptr)1431 void PeerConnection::SetLocalDescription(
1432 SetSessionDescriptionObserver* observer,
1433 SessionDescriptionInterface* desc_ptr) {
1434 RTC_DCHECK_RUN_ON(signaling_thread());
1435 sdp_handler_->SetLocalDescription(observer, desc_ptr);
1436 }
1437
SetLocalDescription(std::unique_ptr<SessionDescriptionInterface> desc,rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer)1438 void PeerConnection::SetLocalDescription(
1439 std::unique_ptr<SessionDescriptionInterface> desc,
1440 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {
1441 RTC_DCHECK_RUN_ON(signaling_thread());
1442 sdp_handler_->SetLocalDescription(std::move(desc), observer);
1443 }
1444
SetLocalDescription(SetSessionDescriptionObserver * observer)1445 void PeerConnection::SetLocalDescription(
1446 SetSessionDescriptionObserver* observer) {
1447 RTC_DCHECK_RUN_ON(signaling_thread());
1448 sdp_handler_->SetLocalDescription(observer);
1449 }
1450
SetLocalDescription(rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer)1451 void PeerConnection::SetLocalDescription(
1452 rtc::scoped_refptr<SetLocalDescriptionObserverInterface> observer) {
1453 RTC_DCHECK_RUN_ON(signaling_thread());
1454 sdp_handler_->SetLocalDescription(observer);
1455 }
1456
SetRemoteDescription(SetSessionDescriptionObserver * observer,SessionDescriptionInterface * desc_ptr)1457 void PeerConnection::SetRemoteDescription(
1458 SetSessionDescriptionObserver* observer,
1459 SessionDescriptionInterface* desc_ptr) {
1460 RTC_DCHECK_RUN_ON(signaling_thread());
1461 sdp_handler_->SetRemoteDescription(observer, desc_ptr);
1462 }
1463
SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer)1464 void PeerConnection::SetRemoteDescription(
1465 std::unique_ptr<SessionDescriptionInterface> desc,
1466 rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer) {
1467 RTC_DCHECK_RUN_ON(signaling_thread());
1468 sdp_handler_->SetRemoteDescription(std::move(desc), observer);
1469 }
1470
GetConfiguration()1471 PeerConnectionInterface::RTCConfiguration PeerConnection::GetConfiguration() {
1472 RTC_DCHECK_RUN_ON(signaling_thread());
1473 return configuration_;
1474 }
1475
SetConfiguration(const RTCConfiguration & configuration)1476 RTCError PeerConnection::SetConfiguration(
1477 const RTCConfiguration& configuration) {
1478 RTC_DCHECK_RUN_ON(signaling_thread());
1479 TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
1480 if (IsClosed()) {
1481 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
1482 "SetConfiguration: PeerConnection is closed.");
1483 }
1484
1485 // According to JSEP, after setLocalDescription, changing the candidate pool
1486 // size is not allowed, and changing the set of ICE servers will not result
1487 // in new candidates being gathered.
1488 if (local_description() && configuration.ice_candidate_pool_size !=
1489 configuration_.ice_candidate_pool_size) {
1490 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
1491 "Can't change candidate pool size after calling "
1492 "SetLocalDescription.");
1493 }
1494
1495 if (local_description() &&
1496 configuration.crypto_options != configuration_.crypto_options) {
1497 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
1498 "Can't change crypto_options after calling "
1499 "SetLocalDescription.");
1500 }
1501
1502 // The simplest (and most future-compatible) way to tell if the config was
1503 // modified in an invalid way is to copy each property we do support
1504 // modifying, then use operator==. There are far more properties we don't
1505 // support modifying than those we do, and more could be added.
1506 RTCConfiguration modified_config = configuration_;
1507 modified_config.servers = configuration.servers;
1508 modified_config.type = configuration.type;
1509 modified_config.ice_candidate_pool_size =
1510 configuration.ice_candidate_pool_size;
1511 modified_config.prune_turn_ports = configuration.prune_turn_ports;
1512 modified_config.turn_port_prune_policy = configuration.turn_port_prune_policy;
1513 modified_config.surface_ice_candidates_on_ice_transport_type_changed =
1514 configuration.surface_ice_candidates_on_ice_transport_type_changed;
1515 modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
1516 modified_config.ice_check_interval_strong_connectivity =
1517 configuration.ice_check_interval_strong_connectivity;
1518 modified_config.ice_check_interval_weak_connectivity =
1519 configuration.ice_check_interval_weak_connectivity;
1520 modified_config.ice_unwritable_timeout = configuration.ice_unwritable_timeout;
1521 modified_config.ice_unwritable_min_checks =
1522 configuration.ice_unwritable_min_checks;
1523 modified_config.ice_inactive_timeout = configuration.ice_inactive_timeout;
1524 modified_config.stun_candidate_keepalive_interval =
1525 configuration.stun_candidate_keepalive_interval;
1526 modified_config.turn_customizer = configuration.turn_customizer;
1527 modified_config.network_preference = configuration.network_preference;
1528 modified_config.active_reset_srtp_params =
1529 configuration.active_reset_srtp_params;
1530 modified_config.turn_logging_id = configuration.turn_logging_id;
1531 modified_config.allow_codec_switching = configuration.allow_codec_switching;
1532 modified_config.stable_writable_connection_ping_interval_ms =
1533 configuration.stable_writable_connection_ping_interval_ms;
1534 if (configuration != modified_config) {
1535 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
1536 "Modifying the configuration in an unsupported way.");
1537 }
1538
1539 // Validate the modified configuration.
1540 RTCError validate_error = ValidateConfiguration(modified_config);
1541 if (!validate_error.ok()) {
1542 return validate_error;
1543 }
1544
1545 // Note that this isn't possible through chromium, since it's an unsigned
1546 // short in WebIDL.
1547 if (configuration.ice_candidate_pool_size < 0 ||
1548 configuration.ice_candidate_pool_size > static_cast<int>(UINT16_MAX)) {
1549 return RTCError(RTCErrorType::INVALID_RANGE);
1550 }
1551
1552 // Parse ICE servers before hopping to network thread.
1553 cricket::ServerAddresses stun_servers;
1554 std::vector<cricket::RelayServerConfig> turn_servers;
1555 RTCError parse_error = ParseIceServersOrError(configuration.servers,
1556 &stun_servers, &turn_servers);
1557 if (!parse_error.ok()) {
1558 return parse_error;
1559 }
1560
1561 // Restrict number of TURN servers.
1562 if (!trials().IsDisabled("WebRTC-LimitTurnServers") &&
1563 turn_servers.size() > cricket::kMaxTurnServers) {
1564 RTC_LOG(LS_WARNING) << "Number of configured TURN servers is "
1565 << turn_servers.size()
1566 << " which exceeds the maximum allowed number of "
1567 << cricket::kMaxTurnServers;
1568 turn_servers.resize(cricket::kMaxTurnServers);
1569 }
1570
1571 // Add the turn logging id to all turn servers
1572 for (cricket::RelayServerConfig& turn_server : turn_servers) {
1573 turn_server.turn_logging_id = configuration.turn_logging_id;
1574 }
1575
1576 // Note if STUN or TURN servers were supplied.
1577 if (!stun_servers.empty()) {
1578 NoteUsageEvent(UsageEvent::STUN_SERVER_ADDED);
1579 }
1580 if (!turn_servers.empty()) {
1581 NoteUsageEvent(UsageEvent::TURN_SERVER_ADDED);
1582 }
1583
1584 const bool has_local_description = local_description() != nullptr;
1585
1586 const bool needs_ice_restart =
1587 modified_config.servers != configuration_.servers ||
1588 NeedIceRestart(
1589 configuration_.surface_ice_candidates_on_ice_transport_type_changed,
1590 configuration_.type, modified_config.type) ||
1591 modified_config.GetTurnPortPrunePolicy() !=
1592 configuration_.GetTurnPortPrunePolicy();
1593 cricket::IceConfig ice_config = ParseIceConfig(modified_config);
1594
1595 // Apply part of the configuration on the network thread. In theory this
1596 // shouldn't fail.
1597 if (!network_thread()->BlockingCall(
1598 [this, needs_ice_restart, &ice_config, &stun_servers, &turn_servers,
1599 &modified_config, has_local_description] {
1600 RTC_DCHECK_RUN_ON(network_thread());
1601 // As described in JSEP, calling setConfiguration with new ICE
1602 // servers or candidate policy must set a "needs-ice-restart" bit so
1603 // that the next offer triggers an ICE restart which will pick up
1604 // the changes.
1605 if (needs_ice_restart)
1606 transport_controller_->SetNeedsIceRestartFlag();
1607
1608 transport_controller_->SetIceConfig(ice_config);
1609 return ReconfigurePortAllocator_n(
1610 stun_servers, turn_servers, modified_config.type,
1611 modified_config.ice_candidate_pool_size,
1612 modified_config.GetTurnPortPrunePolicy(),
1613 modified_config.turn_customizer,
1614 modified_config.stun_candidate_keepalive_interval,
1615 has_local_description);
1616 })) {
1617 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
1618 "Failed to apply configuration to PortAllocator.");
1619 }
1620
1621 if (configuration_.active_reset_srtp_params !=
1622 modified_config.active_reset_srtp_params) {
1623 // TODO(tommi): merge BlockingCalls
1624 network_thread()->BlockingCall([this, &modified_config] {
1625 RTC_DCHECK_RUN_ON(network_thread());
1626 transport_controller_->SetActiveResetSrtpParams(
1627 modified_config.active_reset_srtp_params);
1628 });
1629 }
1630
1631 if (modified_config.allow_codec_switching.has_value()) {
1632 std::vector<cricket::VideoMediaChannel*> channels;
1633 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
1634 if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO)
1635 continue;
1636
1637 auto* video_channel = transceiver->internal()->channel();
1638 if (video_channel)
1639 channels.push_back(static_cast<cricket::VideoMediaChannel*>(
1640 video_channel->media_channel()));
1641 }
1642
1643 worker_thread()->BlockingCall(
1644 [channels = std::move(channels),
1645 allow_codec_switching = *modified_config.allow_codec_switching]() {
1646 for (auto* ch : channels)
1647 ch->SetVideoCodecSwitchingEnabled(allow_codec_switching);
1648 });
1649 }
1650
1651 configuration_ = modified_config;
1652 return RTCError::OK();
1653 }
1654
AddIceCandidate(const IceCandidateInterface * ice_candidate)1655 bool PeerConnection::AddIceCandidate(
1656 const IceCandidateInterface* ice_candidate) {
1657 RTC_DCHECK_RUN_ON(signaling_thread());
1658 ClearStatsCache();
1659 return sdp_handler_->AddIceCandidate(ice_candidate);
1660 }
1661
AddIceCandidate(std::unique_ptr<IceCandidateInterface> candidate,std::function<void (RTCError)> callback)1662 void PeerConnection::AddIceCandidate(
1663 std::unique_ptr<IceCandidateInterface> candidate,
1664 std::function<void(RTCError)> callback) {
1665 RTC_DCHECK_RUN_ON(signaling_thread());
1666 sdp_handler_->AddIceCandidate(std::move(candidate),
1667 [this, callback](webrtc::RTCError result) {
1668 ClearStatsCache();
1669 callback(result);
1670 });
1671 }
1672
RemoveIceCandidates(const std::vector<cricket::Candidate> & candidates)1673 bool PeerConnection::RemoveIceCandidates(
1674 const std::vector<cricket::Candidate>& candidates) {
1675 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
1676 RTC_DCHECK_RUN_ON(signaling_thread());
1677 return sdp_handler_->RemoveIceCandidates(candidates);
1678 }
1679
SetBitrate(const BitrateSettings & bitrate)1680 RTCError PeerConnection::SetBitrate(const BitrateSettings& bitrate) {
1681 if (!worker_thread()->IsCurrent()) {
1682 return worker_thread()->BlockingCall([&]() { return SetBitrate(bitrate); });
1683 }
1684 RTC_DCHECK_RUN_ON(worker_thread());
1685
1686 const bool has_min = bitrate.min_bitrate_bps.has_value();
1687 const bool has_start = bitrate.start_bitrate_bps.has_value();
1688 const bool has_max = bitrate.max_bitrate_bps.has_value();
1689 if (has_min && *bitrate.min_bitrate_bps < 0) {
1690 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1691 "min_bitrate_bps <= 0");
1692 }
1693 if (has_start) {
1694 if (has_min && *bitrate.start_bitrate_bps < *bitrate.min_bitrate_bps) {
1695 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1696 "start_bitrate_bps < min_bitrate_bps");
1697 } else if (*bitrate.start_bitrate_bps < 0) {
1698 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1699 "curent_bitrate_bps < 0");
1700 }
1701 }
1702 if (has_max) {
1703 if (has_start && *bitrate.max_bitrate_bps < *bitrate.start_bitrate_bps) {
1704 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1705 "max_bitrate_bps < start_bitrate_bps");
1706 } else if (has_min && *bitrate.max_bitrate_bps < *bitrate.min_bitrate_bps) {
1707 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1708 "max_bitrate_bps < min_bitrate_bps");
1709 } else if (*bitrate.max_bitrate_bps < 0) {
1710 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
1711 "max_bitrate_bps < 0");
1712 }
1713 }
1714
1715 RTC_DCHECK(call_.get());
1716 call_->SetClientBitratePreferences(bitrate);
1717
1718 return RTCError::OK();
1719 }
1720
SetAudioPlayout(bool playout)1721 void PeerConnection::SetAudioPlayout(bool playout) {
1722 if (!worker_thread()->IsCurrent()) {
1723 worker_thread()->BlockingCall(
1724 [this, playout] { SetAudioPlayout(playout); });
1725 return;
1726 }
1727 auto audio_state = context_->media_engine()->voice().GetAudioState();
1728 audio_state->SetPlayout(playout);
1729 }
1730
SetAudioRecording(bool recording)1731 void PeerConnection::SetAudioRecording(bool recording) {
1732 if (!worker_thread()->IsCurrent()) {
1733 worker_thread()->BlockingCall(
1734 [this, recording] { SetAudioRecording(recording); });
1735 return;
1736 }
1737 auto audio_state = context_->media_engine()->voice().GetAudioState();
1738 audio_state->SetRecording(recording);
1739 }
1740
AddAdaptationResource(rtc::scoped_refptr<Resource> resource)1741 void PeerConnection::AddAdaptationResource(
1742 rtc::scoped_refptr<Resource> resource) {
1743 if (!worker_thread()->IsCurrent()) {
1744 return worker_thread()->BlockingCall(
1745 [this, resource]() { return AddAdaptationResource(resource); });
1746 }
1747 RTC_DCHECK_RUN_ON(worker_thread());
1748 if (!call_) {
1749 // The PeerConnection has been closed.
1750 return;
1751 }
1752 call_->AddAdaptationResource(resource);
1753 }
1754
ConfiguredForMedia() const1755 bool PeerConnection::ConfiguredForMedia() const {
1756 return context_->media_engine();
1757 }
1758
StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,int64_t output_period_ms)1759 bool PeerConnection::StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
1760 int64_t output_period_ms) {
1761 return worker_thread()->BlockingCall(
1762 [this, output = std::move(output), output_period_ms]() mutable {
1763 return StartRtcEventLog_w(std::move(output), output_period_ms);
1764 });
1765 }
1766
StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output)1767 bool PeerConnection::StartRtcEventLog(
1768 std::unique_ptr<RtcEventLogOutput> output) {
1769 int64_t output_period_ms = webrtc::RtcEventLog::kImmediateOutput;
1770 if (trials().IsEnabled("WebRTC-RtcEventLogNewFormat")) {
1771 output_period_ms = 5000;
1772 }
1773 return StartRtcEventLog(std::move(output), output_period_ms);
1774 }
1775
StopRtcEventLog()1776 void PeerConnection::StopRtcEventLog() {
1777 worker_thread()->BlockingCall([this] { StopRtcEventLog_w(); });
1778 }
1779
1780 rtc::scoped_refptr<DtlsTransportInterface>
LookupDtlsTransportByMid(const std::string & mid)1781 PeerConnection::LookupDtlsTransportByMid(const std::string& mid) {
1782 RTC_DCHECK_RUN_ON(network_thread());
1783 return transport_controller_->LookupDtlsTransportByMid(mid);
1784 }
1785
1786 rtc::scoped_refptr<DtlsTransport>
LookupDtlsTransportByMidInternal(const std::string & mid)1787 PeerConnection::LookupDtlsTransportByMidInternal(const std::string& mid) {
1788 RTC_DCHECK_RUN_ON(signaling_thread());
1789 // TODO(bugs.webrtc.org/9987): Avoid the thread jump.
1790 // This might be done by caching the value on the signaling thread.
1791 return network_thread()->BlockingCall([this, mid]() {
1792 RTC_DCHECK_RUN_ON(network_thread());
1793 return transport_controller_->LookupDtlsTransportByMid(mid);
1794 });
1795 }
1796
GetSctpTransport() const1797 rtc::scoped_refptr<SctpTransportInterface> PeerConnection::GetSctpTransport()
1798 const {
1799 RTC_DCHECK_RUN_ON(network_thread());
1800 if (!sctp_mid_n_)
1801 return nullptr;
1802
1803 return transport_controller_->GetSctpTransport(*sctp_mid_n_);
1804 }
1805
local_description() const1806 const SessionDescriptionInterface* PeerConnection::local_description() const {
1807 RTC_DCHECK_RUN_ON(signaling_thread());
1808 return sdp_handler_->local_description();
1809 }
1810
remote_description() const1811 const SessionDescriptionInterface* PeerConnection::remote_description() const {
1812 RTC_DCHECK_RUN_ON(signaling_thread());
1813 return sdp_handler_->remote_description();
1814 }
1815
current_local_description() const1816 const SessionDescriptionInterface* PeerConnection::current_local_description()
1817 const {
1818 RTC_DCHECK_RUN_ON(signaling_thread());
1819 return sdp_handler_->current_local_description();
1820 }
1821
current_remote_description() const1822 const SessionDescriptionInterface* PeerConnection::current_remote_description()
1823 const {
1824 RTC_DCHECK_RUN_ON(signaling_thread());
1825 return sdp_handler_->current_remote_description();
1826 }
1827
pending_local_description() const1828 const SessionDescriptionInterface* PeerConnection::pending_local_description()
1829 const {
1830 RTC_DCHECK_RUN_ON(signaling_thread());
1831 return sdp_handler_->pending_local_description();
1832 }
1833
pending_remote_description() const1834 const SessionDescriptionInterface* PeerConnection::pending_remote_description()
1835 const {
1836 RTC_DCHECK_RUN_ON(signaling_thread());
1837 return sdp_handler_->pending_remote_description();
1838 }
1839
Close()1840 void PeerConnection::Close() {
1841 RTC_DCHECK_RUN_ON(signaling_thread());
1842 TRACE_EVENT0("webrtc", "PeerConnection::Close");
1843
1844 RTC_LOG_THREAD_BLOCK_COUNT();
1845
1846 if (IsClosed()) {
1847 return;
1848 }
1849 // Update stats here so that we have the most recent stats for tracks and
1850 // streams before the channels are closed.
1851 legacy_stats_->UpdateStats(kStatsOutputLevelStandard);
1852
1853 ice_connection_state_ = PeerConnectionInterface::kIceConnectionClosed;
1854 Observer()->OnIceConnectionChange(ice_connection_state_);
1855 standardized_ice_connection_state_ =
1856 PeerConnectionInterface::IceConnectionState::kIceConnectionClosed;
1857 connection_state_ = PeerConnectionInterface::PeerConnectionState::kClosed;
1858 Observer()->OnConnectionChange(connection_state_);
1859
1860 sdp_handler_->Close();
1861
1862 NoteUsageEvent(UsageEvent::CLOSE_CALLED);
1863
1864 if (ConfiguredForMedia()) {
1865 for (const auto& transceiver : rtp_manager()->transceivers()->List()) {
1866 transceiver->internal()->SetPeerConnectionClosed();
1867 if (!transceiver->stopped())
1868 transceiver->StopInternal();
1869 }
1870 }
1871 // Ensure that all asynchronous stats requests are completed before destroying
1872 // the transport controller below.
1873 if (stats_collector_) {
1874 stats_collector_->WaitForPendingRequest();
1875 }
1876
1877 // Don't destroy BaseChannels until after stats has been cleaned up so that
1878 // the last stats request can still read from the channels.
1879 sdp_handler_->DestroyAllChannels();
1880
1881 // The event log is used in the transport controller, which must be outlived
1882 // by the former. CreateOffer by the peer connection is implemented
1883 // asynchronously and if the peer connection is closed without resetting the
1884 // WebRTC session description factory, the session description factory would
1885 // call the transport controller.
1886 sdp_handler_->ResetSessionDescFactory();
1887 if (ConfiguredForMedia()) {
1888 rtp_manager_->Close();
1889 }
1890
1891 network_thread()->BlockingCall([this] {
1892 // Data channels will already have been unset via the DestroyAllChannels()
1893 // call above, which triggers a call to TeardownDataChannelTransport_n().
1894 // TODO(tommi): ^^ That's not exactly optimal since this is yet another
1895 // blocking hop to the network thread during Close(). Further still, the
1896 // voice/video/data channels will be cleared on the worker thread.
1897 RTC_DCHECK_RUN_ON(network_thread());
1898 transport_controller_.reset();
1899 port_allocator_->DiscardCandidatePool();
1900 if (network_thread_safety_) {
1901 network_thread_safety_->SetNotAlive();
1902 }
1903 });
1904
1905 worker_thread()->BlockingCall([this] {
1906 RTC_DCHECK_RUN_ON(worker_thread());
1907 worker_thread_safety_->SetNotAlive();
1908 call_.reset();
1909 // The event log must outlive call (and any other object that uses it).
1910 event_log_.reset();
1911 });
1912 ReportUsagePattern();
1913 // The .h file says that observer can be discarded after close() returns.
1914 // Make sure this is true.
1915 observer_ = nullptr;
1916
1917 // Signal shutdown to the sdp handler. This invalidates weak pointers for
1918 // internal pending callbacks.
1919 sdp_handler_->PrepareForShutdown();
1920 }
1921
SetIceConnectionState(IceConnectionState new_state)1922 void PeerConnection::SetIceConnectionState(IceConnectionState new_state) {
1923 RTC_DCHECK_RUN_ON(signaling_thread());
1924 if (ice_connection_state_ == new_state) {
1925 return;
1926 }
1927
1928 // After transitioning to "closed", ignore any additional states from
1929 // TransportController (such as "disconnected").
1930 if (IsClosed()) {
1931 return;
1932 }
1933
1934 RTC_LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
1935 << " => " << new_state;
1936 RTC_DCHECK(ice_connection_state_ !=
1937 PeerConnectionInterface::kIceConnectionClosed);
1938
1939 ice_connection_state_ = new_state;
1940 Observer()->OnIceConnectionChange(ice_connection_state_);
1941 }
1942
SetStandardizedIceConnectionState(PeerConnectionInterface::IceConnectionState new_state)1943 void PeerConnection::SetStandardizedIceConnectionState(
1944 PeerConnectionInterface::IceConnectionState new_state) {
1945 if (standardized_ice_connection_state_ == new_state) {
1946 return;
1947 }
1948
1949 if (IsClosed()) {
1950 return;
1951 }
1952
1953 RTC_LOG(LS_INFO) << "Changing standardized IceConnectionState "
1954 << standardized_ice_connection_state_ << " => " << new_state;
1955
1956 standardized_ice_connection_state_ = new_state;
1957 Observer()->OnStandardizedIceConnectionChange(new_state);
1958 }
1959
SetConnectionState(PeerConnectionInterface::PeerConnectionState new_state)1960 void PeerConnection::SetConnectionState(
1961 PeerConnectionInterface::PeerConnectionState new_state) {
1962 if (connection_state_ == new_state)
1963 return;
1964 if (IsClosed())
1965 return;
1966 connection_state_ = new_state;
1967 Observer()->OnConnectionChange(new_state);
1968
1969 // The first connection state change to connected happens once per
1970 // connection which makes it a good point to report metrics.
1971 if (new_state == PeerConnectionState::kConnected && !was_ever_connected_) {
1972 was_ever_connected_ = true;
1973 ReportFirstConnectUsageMetrics();
1974 }
1975 }
1976
ReportFirstConnectUsageMetrics()1977 void PeerConnection::ReportFirstConnectUsageMetrics() {
1978 // Record bundle-policy from configuration. Done here from
1979 // connectionStateChange to limit to actually established connections.
1980 BundlePolicyUsage policy = kBundlePolicyUsageMax;
1981 switch (configuration_.bundle_policy) {
1982 case kBundlePolicyBalanced:
1983 policy = kBundlePolicyUsageBalanced;
1984 break;
1985 case kBundlePolicyMaxBundle:
1986 policy = kBundlePolicyUsageMaxBundle;
1987 break;
1988 case kBundlePolicyMaxCompat:
1989 policy = kBundlePolicyUsageMaxCompat;
1990 break;
1991 }
1992 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.BundlePolicy", policy,
1993 kBundlePolicyUsageMax);
1994
1995 // Record whether there was a local or remote provisional answer.
1996 ProvisionalAnswerUsage pranswer = kProvisionalAnswerNotUsed;
1997 if (local_description()->GetType() == SdpType::kPrAnswer) {
1998 pranswer = kProvisionalAnswerLocal;
1999 } else if (remote_description()->GetType() == SdpType::kPrAnswer) {
2000 pranswer = kProvisionalAnswerRemote;
2001 }
2002 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.ProvisionalAnswer", pranswer,
2003 kProvisionalAnswerMax);
2004
2005 // Record the number of valid / invalid ice-ufrag. We do allow certain
2006 // non-spec ice-char for backward-compat reasons. At this point we know
2007 // that the ufrag/pwd consists of a valid ice-char or one of the four
2008 // not allowed characters since we have passed the IsIceChar check done
2009 // by the p2p transport description on setRemoteDescription calls.
2010 auto transport_infos = remote_description()->description()->transport_infos();
2011 if (transport_infos.size() > 0) {
2012 auto ice_parameters = transport_infos[0].description.GetIceParameters();
2013 auto is_invalid_char = [](char c) {
2014 return c == '-' || c == '=' || c == '#' || c == '_';
2015 };
2016 bool isUsingInvalidIceCharInUfrag =
2017 absl::c_any_of(ice_parameters.ufrag, is_invalid_char);
2018 bool isUsingInvalidIceCharInPwd =
2019 absl::c_any_of(ice_parameters.pwd, is_invalid_char);
2020 RTC_HISTOGRAM_BOOLEAN(
2021 "WebRTC.PeerConnection.ValidIceChars",
2022 !(isUsingInvalidIceCharInUfrag || isUsingInvalidIceCharInPwd));
2023 }
2024 }
2025
OnIceGatheringChange(PeerConnectionInterface::IceGatheringState new_state)2026 void PeerConnection::OnIceGatheringChange(
2027 PeerConnectionInterface::IceGatheringState new_state) {
2028 if (IsClosed()) {
2029 return;
2030 }
2031 ice_gathering_state_ = new_state;
2032 Observer()->OnIceGatheringChange(ice_gathering_state_);
2033 }
2034
OnIceCandidate(std::unique_ptr<IceCandidateInterface> candidate)2035 void PeerConnection::OnIceCandidate(
2036 std::unique_ptr<IceCandidateInterface> candidate) {
2037 if (IsClosed()) {
2038 return;
2039 }
2040 ReportIceCandidateCollected(candidate->candidate());
2041 ClearStatsCache();
2042 Observer()->OnIceCandidate(candidate.get());
2043 }
2044
OnIceCandidateError(const std::string & address,int port,const std::string & url,int error_code,const std::string & error_text)2045 void PeerConnection::OnIceCandidateError(const std::string& address,
2046 int port,
2047 const std::string& url,
2048 int error_code,
2049 const std::string& error_text) {
2050 if (IsClosed()) {
2051 return;
2052 }
2053 Observer()->OnIceCandidateError(address, port, url, error_code, error_text);
2054 }
2055
OnIceCandidatesRemoved(const std::vector<cricket::Candidate> & candidates)2056 void PeerConnection::OnIceCandidatesRemoved(
2057 const std::vector<cricket::Candidate>& candidates) {
2058 if (IsClosed()) {
2059 return;
2060 }
2061 Observer()->OnIceCandidatesRemoved(candidates);
2062 }
2063
OnSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent & event)2064 void PeerConnection::OnSelectedCandidatePairChanged(
2065 const cricket::CandidatePairChangeEvent& event) {
2066 if (IsClosed()) {
2067 return;
2068 }
2069
2070 if (event.selected_candidate_pair.local_candidate().type() ==
2071 LOCAL_PORT_TYPE &&
2072 event.selected_candidate_pair.remote_candidate().type() ==
2073 LOCAL_PORT_TYPE) {
2074 NoteUsageEvent(UsageEvent::DIRECT_CONNECTION_SELECTED);
2075 }
2076
2077 Observer()->OnIceSelectedCandidatePairChanged(event);
2078 }
2079
GetDataMid() const2080 absl::optional<std::string> PeerConnection::GetDataMid() const {
2081 RTC_DCHECK_RUN_ON(signaling_thread());
2082 return sctp_mid_s_;
2083 }
2084
SetSctpDataMid(const std::string & mid)2085 void PeerConnection::SetSctpDataMid(const std::string& mid) {
2086 RTC_DCHECK_RUN_ON(signaling_thread());
2087 sctp_mid_s_ = mid;
2088 }
2089
ResetSctpDataMid()2090 void PeerConnection::ResetSctpDataMid() {
2091 RTC_DCHECK_RUN_ON(signaling_thread());
2092 sctp_mid_s_.reset();
2093 sctp_transport_name_s_.clear();
2094 }
2095
OnSctpDataChannelClosed(DataChannelInterface * channel)2096 void PeerConnection::OnSctpDataChannelClosed(DataChannelInterface* channel) {
2097 // Since data_channel_controller doesn't do signals, this
2098 // signal is relayed here.
2099 data_channel_controller_.OnSctpDataChannelClosed(
2100 static_cast<SctpDataChannel*>(channel));
2101 }
2102
2103 PeerConnection::InitializePortAllocatorResult
InitializePortAllocator_n(const cricket::ServerAddresses & stun_servers,const std::vector<cricket::RelayServerConfig> & turn_servers,const RTCConfiguration & configuration)2104 PeerConnection::InitializePortAllocator_n(
2105 const cricket::ServerAddresses& stun_servers,
2106 const std::vector<cricket::RelayServerConfig>& turn_servers,
2107 const RTCConfiguration& configuration) {
2108 RTC_DCHECK_RUN_ON(network_thread());
2109
2110 port_allocator_->Initialize();
2111 // To handle both internal and externally created port allocator, we will
2112 // enable BUNDLE here.
2113 int port_allocator_flags = port_allocator_->flags();
2114 port_allocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
2115 cricket::PORTALLOCATOR_ENABLE_IPV6 |
2116 cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
2117 if (trials().IsDisabled("WebRTC-IPv6Default")) {
2118 port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
2119 }
2120 if (configuration.disable_ipv6_on_wifi) {
2121 port_allocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI);
2122 RTC_LOG(LS_INFO) << "IPv6 candidates on Wi-Fi are disabled.";
2123 }
2124
2125 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
2126 port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
2127 RTC_LOG(LS_INFO) << "TCP candidates are disabled.";
2128 }
2129
2130 if (configuration.candidate_network_policy ==
2131 kCandidateNetworkPolicyLowCost) {
2132 port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
2133 RTC_LOG(LS_INFO) << "Do not gather candidates on high-cost networks";
2134 }
2135
2136 if (configuration.disable_link_local_networks) {
2137 port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_LINK_LOCAL_NETWORKS;
2138 RTC_LOG(LS_INFO) << "Disable candidates on link-local network interfaces.";
2139 }
2140
2141 port_allocator_->set_flags(port_allocator_flags);
2142 // No step delay is used while allocating ports.
2143 port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
2144 port_allocator_->SetCandidateFilter(
2145 ConvertIceTransportTypeToCandidateFilter(configuration.type));
2146 port_allocator_->set_max_ipv6_networks(configuration.max_ipv6_networks);
2147
2148 auto turn_servers_copy = turn_servers;
2149 for (auto& turn_server : turn_servers_copy) {
2150 turn_server.tls_cert_verifier = tls_cert_verifier_.get();
2151 }
2152 // Call this last since it may create pooled allocator sessions using the
2153 // properties set above.
2154 port_allocator_->SetConfiguration(
2155 stun_servers, std::move(turn_servers_copy),
2156 configuration.ice_candidate_pool_size,
2157 configuration.GetTurnPortPrunePolicy(), configuration.turn_customizer,
2158 configuration.stun_candidate_keepalive_interval);
2159
2160 InitializePortAllocatorResult res;
2161 res.enable_ipv6 = port_allocator_flags & cricket::PORTALLOCATOR_ENABLE_IPV6;
2162 return res;
2163 }
2164
ReconfigurePortAllocator_n(const cricket::ServerAddresses & stun_servers,const std::vector<cricket::RelayServerConfig> & turn_servers,IceTransportsType type,int candidate_pool_size,PortPrunePolicy turn_port_prune_policy,webrtc::TurnCustomizer * turn_customizer,absl::optional<int> stun_candidate_keepalive_interval,bool have_local_description)2165 bool PeerConnection::ReconfigurePortAllocator_n(
2166 const cricket::ServerAddresses& stun_servers,
2167 const std::vector<cricket::RelayServerConfig>& turn_servers,
2168 IceTransportsType type,
2169 int candidate_pool_size,
2170 PortPrunePolicy turn_port_prune_policy,
2171 webrtc::TurnCustomizer* turn_customizer,
2172 absl::optional<int> stun_candidate_keepalive_interval,
2173 bool have_local_description) {
2174 RTC_DCHECK_RUN_ON(network_thread());
2175 port_allocator_->SetCandidateFilter(
2176 ConvertIceTransportTypeToCandidateFilter(type));
2177 // According to JSEP, after setLocalDescription, changing the candidate pool
2178 // size is not allowed, and changing the set of ICE servers will not result
2179 // in new candidates being gathered.
2180 if (have_local_description) {
2181 port_allocator_->FreezeCandidatePool();
2182 }
2183 // Add the custom tls turn servers if they exist.
2184 auto turn_servers_copy = turn_servers;
2185 for (auto& turn_server : turn_servers_copy) {
2186 turn_server.tls_cert_verifier = tls_cert_verifier_.get();
2187 }
2188 // Call this last since it may create pooled allocator sessions using the
2189 // candidate filter set above.
2190 return port_allocator_->SetConfiguration(
2191 stun_servers, std::move(turn_servers_copy), candidate_pool_size,
2192 turn_port_prune_policy, turn_customizer,
2193 stun_candidate_keepalive_interval);
2194 }
2195
StartRtcEventLog_w(std::unique_ptr<RtcEventLogOutput> output,int64_t output_period_ms)2196 bool PeerConnection::StartRtcEventLog_w(
2197 std::unique_ptr<RtcEventLogOutput> output,
2198 int64_t output_period_ms) {
2199 RTC_DCHECK_RUN_ON(worker_thread());
2200 if (!event_log_) {
2201 return false;
2202 }
2203 return event_log_->StartLogging(std::move(output), output_period_ms);
2204 }
2205
StopRtcEventLog_w()2206 void PeerConnection::StopRtcEventLog_w() {
2207 RTC_DCHECK_RUN_ON(worker_thread());
2208 if (event_log_) {
2209 event_log_->StopLogging();
2210 }
2211 }
2212
GetSctpSslRole(rtc::SSLRole * role)2213 bool PeerConnection::GetSctpSslRole(rtc::SSLRole* role) {
2214 RTC_DCHECK_RUN_ON(signaling_thread());
2215 if (!local_description() || !remote_description()) {
2216 RTC_LOG(LS_VERBOSE)
2217 << "Local and Remote descriptions must be applied to get the "
2218 "SSL Role of the SCTP transport.";
2219 return false;
2220 }
2221 if (!data_channel_controller_.data_channel_transport()) {
2222 RTC_LOG(LS_INFO) << "Non-rejected SCTP m= section is needed to get the "
2223 "SSL Role of the SCTP transport.";
2224 return false;
2225 }
2226
2227 absl::optional<rtc::SSLRole> dtls_role;
2228 if (sctp_mid_s_) {
2229 dtls_role = network_thread()->BlockingCall([this] {
2230 RTC_DCHECK_RUN_ON(network_thread());
2231 return transport_controller_->GetDtlsRole(*sctp_mid_n_);
2232 });
2233 if (!dtls_role && sdp_handler_->is_caller().has_value()) {
2234 // This works fine if we are the offerer, but can be a mistake if
2235 // we are the answerer and the remote offer is ACTIVE. In that
2236 // case, we will guess the role wrong.
2237 // TODO(bugs.webrtc.org/13668): Check if this actually happens.
2238 RTC_LOG(LS_ERROR)
2239 << "Possible risk: DTLS role guesser is active, is_caller is "
2240 << *sdp_handler_->is_caller();
2241 dtls_role =
2242 *sdp_handler_->is_caller() ? rtc::SSL_SERVER : rtc::SSL_CLIENT;
2243 }
2244 if (dtls_role) {
2245 *role = *dtls_role;
2246 return true;
2247 }
2248 }
2249 return false;
2250 }
2251
GetSslRole(const std::string & content_name,rtc::SSLRole * role)2252 bool PeerConnection::GetSslRole(const std::string& content_name,
2253 rtc::SSLRole* role) {
2254 RTC_DCHECK_RUN_ON(signaling_thread());
2255 if (!local_description() || !remote_description()) {
2256 RTC_LOG(LS_INFO)
2257 << "Local and Remote descriptions must be applied to get the "
2258 "SSL Role of the session.";
2259 return false;
2260 }
2261
2262 auto dtls_role = network_thread()->BlockingCall([this, content_name]() {
2263 RTC_DCHECK_RUN_ON(network_thread());
2264 return transport_controller_->GetDtlsRole(content_name);
2265 });
2266 if (dtls_role) {
2267 *role = *dtls_role;
2268 return true;
2269 }
2270 return false;
2271 }
2272
GetTransportDescription(const SessionDescription * description,const std::string & content_name,cricket::TransportDescription * tdesc)2273 bool PeerConnection::GetTransportDescription(
2274 const SessionDescription* description,
2275 const std::string& content_name,
2276 cricket::TransportDescription* tdesc) {
2277 if (!description || !tdesc) {
2278 return false;
2279 }
2280 const TransportInfo* transport_info =
2281 description->GetTransportInfoByName(content_name);
2282 if (!transport_info) {
2283 return false;
2284 }
2285 *tdesc = transport_info->description;
2286 return true;
2287 }
2288
GetDataChannelStats() const2289 std::vector<DataChannelStats> PeerConnection::GetDataChannelStats() const {
2290 RTC_DCHECK_RUN_ON(signaling_thread());
2291 return data_channel_controller_.GetDataChannelStats();
2292 }
2293
sctp_transport_name() const2294 absl::optional<std::string> PeerConnection::sctp_transport_name() const {
2295 RTC_DCHECK_RUN_ON(signaling_thread());
2296 if (sctp_mid_s_ && transport_controller_copy_)
2297 return sctp_transport_name_s_;
2298 return absl::optional<std::string>();
2299 }
2300
sctp_mid() const2301 absl::optional<std::string> PeerConnection::sctp_mid() const {
2302 RTC_DCHECK_RUN_ON(signaling_thread());
2303 return sctp_mid_s_;
2304 }
2305
GetPooledCandidateStats() const2306 cricket::CandidateStatsList PeerConnection::GetPooledCandidateStats() const {
2307 RTC_DCHECK_RUN_ON(network_thread());
2308 if (!network_thread_safety_->alive())
2309 return {};
2310 cricket::CandidateStatsList candidate_stats_list;
2311 port_allocator_->GetCandidateStatsFromPooledSessions(&candidate_stats_list);
2312 return candidate_stats_list;
2313 }
2314
2315 std::map<std::string, cricket::TransportStats>
GetTransportStatsByNames(const std::set<std::string> & transport_names)2316 PeerConnection::GetTransportStatsByNames(
2317 const std::set<std::string>& transport_names) {
2318 TRACE_EVENT0("webrtc", "PeerConnection::GetTransportStatsByNames");
2319 RTC_DCHECK_RUN_ON(network_thread());
2320 if (!network_thread_safety_->alive())
2321 return {};
2322
2323 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2324 std::map<std::string, cricket::TransportStats> transport_stats_by_name;
2325 for (const std::string& transport_name : transport_names) {
2326 cricket::TransportStats transport_stats;
2327 bool success =
2328 transport_controller_->GetStats(transport_name, &transport_stats);
2329 if (success) {
2330 transport_stats_by_name[transport_name] = std::move(transport_stats);
2331 } else {
2332 RTC_LOG(LS_ERROR) << "Failed to get transport stats for transport_name="
2333 << transport_name;
2334 }
2335 }
2336 return transport_stats_by_name;
2337 }
2338
GetLocalCertificate(const std::string & transport_name,rtc::scoped_refptr<rtc::RTCCertificate> * certificate)2339 bool PeerConnection::GetLocalCertificate(
2340 const std::string& transport_name,
2341 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
2342 RTC_DCHECK_RUN_ON(network_thread());
2343 if (!network_thread_safety_->alive() || !certificate) {
2344 return false;
2345 }
2346 *certificate = transport_controller_->GetLocalCertificate(transport_name);
2347 return *certificate != nullptr;
2348 }
2349
GetRemoteSSLCertChain(const std::string & transport_name)2350 std::unique_ptr<rtc::SSLCertChain> PeerConnection::GetRemoteSSLCertChain(
2351 const std::string& transport_name) {
2352 RTC_DCHECK_RUN_ON(network_thread());
2353 return transport_controller_->GetRemoteSSLCertChain(transport_name);
2354 }
2355
IceRestartPending(const std::string & content_name) const2356 bool PeerConnection::IceRestartPending(const std::string& content_name) const {
2357 RTC_DCHECK_RUN_ON(signaling_thread());
2358 return sdp_handler_->IceRestartPending(content_name);
2359 }
2360
NeedsIceRestart(const std::string & content_name) const2361 bool PeerConnection::NeedsIceRestart(const std::string& content_name) const {
2362 return network_thread()->BlockingCall([this, &content_name] {
2363 RTC_DCHECK_RUN_ON(network_thread());
2364 return transport_controller_->NeedsIceRestart(content_name);
2365 });
2366 }
2367
OnTransportControllerConnectionState(cricket::IceConnectionState state)2368 void PeerConnection::OnTransportControllerConnectionState(
2369 cricket::IceConnectionState state) {
2370 switch (state) {
2371 case cricket::kIceConnectionConnecting:
2372 // If the current state is Connected or Completed, then there were
2373 // writable channels but now there are not, so the next state must
2374 // be Disconnected.
2375 // kIceConnectionConnecting is currently used as the default,
2376 // un-connected state by the TransportController, so its only use is
2377 // detecting disconnections.
2378 if (ice_connection_state_ ==
2379 PeerConnectionInterface::kIceConnectionConnected ||
2380 ice_connection_state_ ==
2381 PeerConnectionInterface::kIceConnectionCompleted) {
2382 SetIceConnectionState(
2383 PeerConnectionInterface::kIceConnectionDisconnected);
2384 }
2385 break;
2386 case cricket::kIceConnectionFailed:
2387 SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
2388 break;
2389 case cricket::kIceConnectionConnected:
2390 RTC_LOG(LS_INFO) << "Changing to ICE connected state because "
2391 "all transports are writable.";
2392 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
2393 NoteUsageEvent(UsageEvent::ICE_STATE_CONNECTED);
2394 break;
2395 case cricket::kIceConnectionCompleted:
2396 RTC_LOG(LS_INFO) << "Changing to ICE completed state because "
2397 "all transports are complete.";
2398 if (ice_connection_state_ !=
2399 PeerConnectionInterface::kIceConnectionConnected) {
2400 // If jumping directly from "checking" to "connected",
2401 // signal "connected" first.
2402 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
2403 }
2404 SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
2405
2406 NoteUsageEvent(UsageEvent::ICE_STATE_CONNECTED);
2407 break;
2408 default:
2409 RTC_DCHECK_NOTREACHED();
2410 }
2411 }
2412
OnTransportControllerCandidatesGathered(const std::string & transport_name,const cricket::Candidates & candidates)2413 void PeerConnection::OnTransportControllerCandidatesGathered(
2414 const std::string& transport_name,
2415 const cricket::Candidates& candidates) {
2416 // TODO(bugs.webrtc.org/12427): Expect this to come in on the network thread
2417 // (not signaling as it currently does), handle appropriately.
2418 int sdp_mline_index;
2419 if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) {
2420 RTC_LOG(LS_ERROR)
2421 << "OnTransportControllerCandidatesGathered: content name "
2422 << transport_name << " not found";
2423 return;
2424 }
2425
2426 for (cricket::Candidates::const_iterator citer = candidates.begin();
2427 citer != candidates.end(); ++citer) {
2428 // Use transport_name as the candidate media id.
2429 std::unique_ptr<JsepIceCandidate> candidate(
2430 new JsepIceCandidate(transport_name, sdp_mline_index, *citer));
2431 sdp_handler_->AddLocalIceCandidate(candidate.get());
2432 OnIceCandidate(std::move(candidate));
2433 }
2434 }
2435
OnTransportControllerCandidateError(const cricket::IceCandidateErrorEvent & event)2436 void PeerConnection::OnTransportControllerCandidateError(
2437 const cricket::IceCandidateErrorEvent& event) {
2438 OnIceCandidateError(event.address, event.port, event.url, event.error_code,
2439 event.error_text);
2440 }
2441
OnTransportControllerCandidatesRemoved(const std::vector<cricket::Candidate> & candidates)2442 void PeerConnection::OnTransportControllerCandidatesRemoved(
2443 const std::vector<cricket::Candidate>& candidates) {
2444 // Sanity check.
2445 for (const cricket::Candidate& candidate : candidates) {
2446 if (candidate.transport_name().empty()) {
2447 RTC_LOG(LS_ERROR) << "OnTransportControllerCandidatesRemoved: "
2448 "empty content name in candidate "
2449 << candidate.ToString();
2450 return;
2451 }
2452 }
2453 sdp_handler_->RemoveLocalIceCandidates(candidates);
2454 OnIceCandidatesRemoved(candidates);
2455 }
2456
OnTransportControllerCandidateChanged(const cricket::CandidatePairChangeEvent & event)2457 void PeerConnection::OnTransportControllerCandidateChanged(
2458 const cricket::CandidatePairChangeEvent& event) {
2459 OnSelectedCandidatePairChanged(event);
2460 }
2461
OnTransportControllerDtlsHandshakeError(rtc::SSLHandshakeError error)2462 void PeerConnection::OnTransportControllerDtlsHandshakeError(
2463 rtc::SSLHandshakeError error) {
2464 RTC_HISTOGRAM_ENUMERATION(
2465 "WebRTC.PeerConnection.DtlsHandshakeError", static_cast<int>(error),
2466 static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
2467 }
2468
2469 // Returns the media index for a local ice candidate given the content name.
GetLocalCandidateMediaIndex(const std::string & content_name,int * sdp_mline_index)2470 bool PeerConnection::GetLocalCandidateMediaIndex(
2471 const std::string& content_name,
2472 int* sdp_mline_index) {
2473 if (!local_description() || !sdp_mline_index) {
2474 return false;
2475 }
2476
2477 bool content_found = false;
2478 const ContentInfos& contents = local_description()->description()->contents();
2479 for (size_t index = 0; index < contents.size(); ++index) {
2480 if (contents[index].name == content_name) {
2481 *sdp_mline_index = static_cast<int>(index);
2482 content_found = true;
2483 break;
2484 }
2485 }
2486 return content_found;
2487 }
2488
GetCallStats()2489 Call::Stats PeerConnection::GetCallStats() {
2490 if (!worker_thread()->IsCurrent()) {
2491 return worker_thread()->BlockingCall([this] { return GetCallStats(); });
2492 }
2493 RTC_DCHECK_RUN_ON(worker_thread());
2494 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2495 if (call_) {
2496 return call_->GetStats();
2497 } else {
2498 return Call::Stats();
2499 }
2500 }
2501
SetupDataChannelTransport_n(const std::string & mid)2502 bool PeerConnection::SetupDataChannelTransport_n(const std::string& mid) {
2503 DataChannelTransportInterface* transport =
2504 transport_controller_->GetDataChannelTransport(mid);
2505 if (!transport) {
2506 RTC_LOG(LS_ERROR)
2507 << "Data channel transport is not available for data channels, mid="
2508 << mid;
2509 return false;
2510 }
2511 RTC_LOG(LS_INFO) << "Setting up data channel transport for mid=" << mid;
2512
2513 data_channel_controller_.set_data_channel_transport(transport);
2514 data_channel_controller_.SetupDataChannelTransport_n();
2515 sctp_mid_n_ = mid;
2516 cricket::DtlsTransportInternal* dtls_transport =
2517 transport_controller_->GetDtlsTransport(mid);
2518 if (dtls_transport) {
2519 signaling_thread()->PostTask(
2520 SafeTask(signaling_thread_safety_.flag(),
2521 [this, name = dtls_transport->transport_name()] {
2522 RTC_DCHECK_RUN_ON(signaling_thread());
2523 sctp_transport_name_s_ = std::move(name);
2524 }));
2525 }
2526
2527 // Note: setting the data sink and checking initial state must be done last,
2528 // after setting up the data channel. Setting the data sink may trigger
2529 // callbacks to PeerConnection which require the transport to be completely
2530 // set up (eg. OnReadyToSend()).
2531 transport->SetDataSink(&data_channel_controller_);
2532 return true;
2533 }
2534
TeardownDataChannelTransport_n()2535 void PeerConnection::TeardownDataChannelTransport_n() {
2536 if (sctp_mid_n_) {
2537 // `sctp_mid_` may still be active through an SCTP transport. If not, unset
2538 // it.
2539 RTC_LOG(LS_INFO) << "Tearing down data channel transport for mid="
2540 << *sctp_mid_n_;
2541 sctp_mid_n_.reset();
2542 }
2543
2544 data_channel_controller_.TeardownDataChannelTransport_n();
2545 }
2546
2547 // Returns false if bundle is enabled and rtcp_mux is disabled.
ValidateBundleSettings(const SessionDescription * desc,const std::map<std::string,const cricket::ContentGroup * > & bundle_groups_by_mid)2548 bool PeerConnection::ValidateBundleSettings(
2549 const SessionDescription* desc,
2550 const std::map<std::string, const cricket::ContentGroup*>&
2551 bundle_groups_by_mid) {
2552 if (bundle_groups_by_mid.empty())
2553 return true;
2554
2555 const cricket::ContentInfos& contents = desc->contents();
2556 for (cricket::ContentInfos::const_iterator citer = contents.begin();
2557 citer != contents.end(); ++citer) {
2558 const cricket::ContentInfo* content = (&*citer);
2559 RTC_DCHECK(content != NULL);
2560 auto it = bundle_groups_by_mid.find(content->name);
2561 if (it != bundle_groups_by_mid.end() && !content->rejected &&
2562 content->type == MediaProtocolType::kRtp) {
2563 if (!HasRtcpMuxEnabled(content))
2564 return false;
2565 }
2566 }
2567 // RTCP-MUX is enabled in all the contents.
2568 return true;
2569 }
2570
ReportSdpBundleUsage(const SessionDescriptionInterface & remote_description)2571 void PeerConnection::ReportSdpBundleUsage(
2572 const SessionDescriptionInterface& remote_description) {
2573 RTC_DCHECK_RUN_ON(signaling_thread());
2574
2575 bool using_bundle =
2576 remote_description.description()->HasGroup(cricket::GROUP_TYPE_BUNDLE);
2577 int num_audio_mlines = 0;
2578 int num_video_mlines = 0;
2579 int num_data_mlines = 0;
2580 for (const ContentInfo& content :
2581 remote_description.description()->contents()) {
2582 cricket::MediaType media_type = content.media_description()->type();
2583 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
2584 num_audio_mlines += 1;
2585 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
2586 num_video_mlines += 1;
2587 } else if (media_type == cricket::MEDIA_TYPE_DATA) {
2588 num_data_mlines += 1;
2589 }
2590 }
2591 bool simple = num_audio_mlines <= 1 && num_video_mlines <= 1;
2592 BundleUsage usage = kBundleUsageMax;
2593 if (num_audio_mlines == 0 && num_video_mlines == 0) {
2594 if (num_data_mlines > 0) {
2595 usage = using_bundle ? kBundleUsageBundleDatachannelOnly
2596 : kBundleUsageNoBundleDatachannelOnly;
2597 } else {
2598 usage = kBundleUsageEmpty;
2599 }
2600 } else if (configuration_.sdp_semantics == SdpSemantics::kPlanB_DEPRECATED) {
2601 // In plan-b, simple/complex usage will not show up in the number of
2602 // m-lines or BUNDLE.
2603 usage = using_bundle ? kBundleUsageBundlePlanB : kBundleUsageNoBundlePlanB;
2604 } else {
2605 if (simple) {
2606 usage =
2607 using_bundle ? kBundleUsageBundleSimple : kBundleUsageNoBundleSimple;
2608 } else {
2609 usage = using_bundle ? kBundleUsageBundleComplex
2610 : kBundleUsageNoBundleComplex;
2611 }
2612 }
2613 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.BundleUsage", usage,
2614 kBundleUsageMax);
2615 }
2616
ReportIceCandidateCollected(const cricket::Candidate & candidate)2617 void PeerConnection::ReportIceCandidateCollected(
2618 const cricket::Candidate& candidate) {
2619 NoteUsageEvent(UsageEvent::CANDIDATE_COLLECTED);
2620 if (candidate.address().IsPrivateIP()) {
2621 NoteUsageEvent(UsageEvent::PRIVATE_CANDIDATE_COLLECTED);
2622 }
2623 if (candidate.address().IsUnresolvedIP()) {
2624 NoteUsageEvent(UsageEvent::MDNS_CANDIDATE_COLLECTED);
2625 }
2626 if (candidate.address().family() == AF_INET6) {
2627 NoteUsageEvent(UsageEvent::IPV6_CANDIDATE_COLLECTED);
2628 }
2629 }
2630
NoteUsageEvent(UsageEvent event)2631 void PeerConnection::NoteUsageEvent(UsageEvent event) {
2632 RTC_DCHECK_RUN_ON(signaling_thread());
2633 usage_pattern_.NoteUsageEvent(event);
2634 }
2635
2636 // Asynchronously adds remote candidates on the network thread.
AddRemoteCandidate(const std::string & mid,const cricket::Candidate & candidate)2637 void PeerConnection::AddRemoteCandidate(const std::string& mid,
2638 const cricket::Candidate& candidate) {
2639 RTC_DCHECK_RUN_ON(signaling_thread());
2640
2641 if (candidate.network_type() != rtc::ADAPTER_TYPE_UNKNOWN) {
2642 RTC_DLOG(LS_WARNING) << "Using candidate with adapter type set - this "
2643 "should only happen in test";
2644 }
2645
2646 // Clear fields that do not make sense as remote candidates.
2647 cricket::Candidate new_candidate(candidate);
2648 new_candidate.set_network_type(rtc::ADAPTER_TYPE_UNKNOWN);
2649 new_candidate.set_relay_protocol("");
2650 new_candidate.set_underlying_type_for_vpn(rtc::ADAPTER_TYPE_UNKNOWN);
2651
2652 network_thread()->PostTask(SafeTask(
2653 network_thread_safety_, [this, mid = mid, candidate = new_candidate] {
2654 RTC_DCHECK_RUN_ON(network_thread());
2655 std::vector<cricket::Candidate> candidates = {candidate};
2656 RTCError error =
2657 transport_controller_->AddRemoteCandidates(mid, candidates);
2658 if (error.ok()) {
2659 signaling_thread()->PostTask(SafeTask(
2660 signaling_thread_safety_.flag(),
2661 [this, candidate = std::move(candidate)] {
2662 ReportRemoteIceCandidateAdded(candidate);
2663 // Candidates successfully submitted for checking.
2664 if (ice_connection_state() ==
2665 PeerConnectionInterface::kIceConnectionNew ||
2666 ice_connection_state() ==
2667 PeerConnectionInterface::kIceConnectionDisconnected) {
2668 // If state is New, then the session has just gotten its first
2669 // remote ICE candidates, so go to Checking. If state is
2670 // Disconnected, the session is re-using old candidates or
2671 // receiving additional ones, so go to Checking. If state is
2672 // Connected, stay Connected.
2673 // TODO(bemasc): If state is Connected, and the new candidates
2674 // are for a newly added transport, then the state actually
2675 // _should_ move to checking. Add a way to distinguish that
2676 // case.
2677 SetIceConnectionState(
2678 PeerConnectionInterface::kIceConnectionChecking);
2679 }
2680 // TODO(bemasc): If state is Completed, go back to Connected.
2681 }));
2682 } else {
2683 RTC_LOG(LS_WARNING) << error.message();
2684 }
2685 }));
2686 }
2687
ReportUsagePattern() const2688 void PeerConnection::ReportUsagePattern() const {
2689 usage_pattern_.ReportUsagePattern(observer_);
2690 }
2691
ReportRemoteIceCandidateAdded(const cricket::Candidate & candidate)2692 void PeerConnection::ReportRemoteIceCandidateAdded(
2693 const cricket::Candidate& candidate) {
2694 RTC_DCHECK_RUN_ON(signaling_thread());
2695
2696 NoteUsageEvent(UsageEvent::REMOTE_CANDIDATE_ADDED);
2697
2698 if (candidate.address().IsPrivateIP()) {
2699 NoteUsageEvent(UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED);
2700 }
2701 if (candidate.address().IsUnresolvedIP()) {
2702 NoteUsageEvent(UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED);
2703 }
2704 if (candidate.address().family() == AF_INET6) {
2705 NoteUsageEvent(UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED);
2706 }
2707 }
2708
SrtpRequired() const2709 bool PeerConnection::SrtpRequired() const {
2710 RTC_DCHECK_RUN_ON(signaling_thread());
2711 return (dtls_enabled_ ||
2712 sdp_handler_->webrtc_session_desc_factory()->SdesPolicy() ==
2713 cricket::SEC_REQUIRED);
2714 }
2715
OnTransportControllerGatheringState(cricket::IceGatheringState state)2716 void PeerConnection::OnTransportControllerGatheringState(
2717 cricket::IceGatheringState state) {
2718 RTC_DCHECK(signaling_thread()->IsCurrent());
2719 if (state == cricket::kIceGatheringGathering) {
2720 OnIceGatheringChange(PeerConnectionInterface::kIceGatheringGathering);
2721 } else if (state == cricket::kIceGatheringComplete) {
2722 OnIceGatheringChange(PeerConnectionInterface::kIceGatheringComplete);
2723 } else if (state == cricket::kIceGatheringNew) {
2724 OnIceGatheringChange(PeerConnectionInterface::kIceGatheringNew);
2725 } else {
2726 RTC_LOG(LS_ERROR) << "Unknown state received: " << state;
2727 RTC_DCHECK_NOTREACHED();
2728 }
2729 }
2730
2731 // Runs on network_thread().
ReportTransportStats()2732 void PeerConnection::ReportTransportStats() {
2733 TRACE_EVENT0("webrtc", "PeerConnection::ReportTransportStats");
2734 rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
2735 std::map<std::string, std::set<cricket::MediaType>>
2736 media_types_by_transport_name;
2737 if (ConfiguredForMedia()) {
2738 for (const auto& transceiver :
2739 rtp_manager()->transceivers()->UnsafeList()) {
2740 if (transceiver->internal()->channel()) {
2741 std::string transport_name(
2742 transceiver->internal()->channel()->transport_name());
2743 media_types_by_transport_name[transport_name].insert(
2744 transceiver->media_type());
2745 }
2746 }
2747 }
2748
2749 if (sctp_mid_n_) {
2750 cricket::DtlsTransportInternal* dtls_transport =
2751 transport_controller_->GetDtlsTransport(*sctp_mid_n_);
2752 if (dtls_transport) {
2753 media_types_by_transport_name[dtls_transport->transport_name()].insert(
2754 cricket::MEDIA_TYPE_DATA);
2755 }
2756 }
2757
2758 for (const auto& entry : media_types_by_transport_name) {
2759 const std::string& transport_name = entry.first;
2760 const std::set<cricket::MediaType> media_types = entry.second;
2761 cricket::TransportStats stats;
2762 if (transport_controller_->GetStats(transport_name, &stats)) {
2763 ReportBestConnectionState(stats);
2764 ReportNegotiatedCiphers(dtls_enabled_, stats, media_types);
2765 }
2766 }
2767 }
2768
2769 // Walk through the ConnectionInfos to gather best connection usage
2770 // for IPv4 and IPv6.
2771 // static (no member state required)
ReportBestConnectionState(const cricket::TransportStats & stats)2772 void PeerConnection::ReportBestConnectionState(
2773 const cricket::TransportStats& stats) {
2774 for (const cricket::TransportChannelStats& channel_stats :
2775 stats.channel_stats) {
2776 for (const cricket::ConnectionInfo& connection_info :
2777 channel_stats.ice_transport_stats.connection_infos) {
2778 if (!connection_info.best_connection) {
2779 continue;
2780 }
2781
2782 const cricket::Candidate& local = connection_info.local_candidate;
2783 const cricket::Candidate& remote = connection_info.remote_candidate;
2784
2785 // Increment the counter for IceCandidatePairType.
2786 if (local.protocol() == cricket::TCP_PROTOCOL_NAME ||
2787 (local.type() == RELAY_PORT_TYPE &&
2788 local.relay_protocol() == cricket::TCP_PROTOCOL_NAME)) {
2789 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_TCP",
2790 GetIceCandidatePairCounter(local, remote),
2791 kIceCandidatePairMax);
2792 } else if (local.protocol() == cricket::UDP_PROTOCOL_NAME) {
2793 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_UDP",
2794 GetIceCandidatePairCounter(local, remote),
2795 kIceCandidatePairMax);
2796 } else {
2797 RTC_CHECK_NOTREACHED();
2798 }
2799
2800 // Increment the counter for IP type.
2801 if (local.address().family() == AF_INET) {
2802 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
2803 kBestConnections_IPv4,
2804 kPeerConnectionAddressFamilyCounter_Max);
2805 } else if (local.address().family() == AF_INET6) {
2806 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
2807 kBestConnections_IPv6,
2808 kPeerConnectionAddressFamilyCounter_Max);
2809 } else {
2810 RTC_CHECK(!local.address().hostname().empty() &&
2811 local.address().IsUnresolvedIP());
2812 }
2813
2814 return;
2815 }
2816 }
2817 }
2818
2819 // static
ReportNegotiatedCiphers(bool dtls_enabled,const cricket::TransportStats & stats,const std::set<cricket::MediaType> & media_types)2820 void PeerConnection::ReportNegotiatedCiphers(
2821 bool dtls_enabled,
2822 const cricket::TransportStats& stats,
2823 const std::set<cricket::MediaType>& media_types) {
2824 if (!dtls_enabled || stats.channel_stats.empty()) {
2825 return;
2826 }
2827
2828 int srtp_crypto_suite = stats.channel_stats[0].srtp_crypto_suite;
2829 int ssl_cipher_suite = stats.channel_stats[0].ssl_cipher_suite;
2830 if (srtp_crypto_suite == rtc::kSrtpInvalidCryptoSuite &&
2831 ssl_cipher_suite == rtc::kTlsNullWithNullNull) {
2832 return;
2833 }
2834
2835 if (srtp_crypto_suite != rtc::kSrtpInvalidCryptoSuite) {
2836 for (cricket::MediaType media_type : media_types) {
2837 switch (media_type) {
2838 case cricket::MEDIA_TYPE_AUDIO:
2839 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2840 "WebRTC.PeerConnection.SrtpCryptoSuite.Audio", srtp_crypto_suite,
2841 rtc::kSrtpCryptoSuiteMaxValue);
2842 break;
2843 case cricket::MEDIA_TYPE_VIDEO:
2844 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2845 "WebRTC.PeerConnection.SrtpCryptoSuite.Video", srtp_crypto_suite,
2846 rtc::kSrtpCryptoSuiteMaxValue);
2847 break;
2848 case cricket::MEDIA_TYPE_DATA:
2849 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2850 "WebRTC.PeerConnection.SrtpCryptoSuite.Data", srtp_crypto_suite,
2851 rtc::kSrtpCryptoSuiteMaxValue);
2852 break;
2853 default:
2854 RTC_DCHECK_NOTREACHED();
2855 continue;
2856 }
2857 }
2858 }
2859
2860 if (ssl_cipher_suite != rtc::kTlsNullWithNullNull) {
2861 for (cricket::MediaType media_type : media_types) {
2862 switch (media_type) {
2863 case cricket::MEDIA_TYPE_AUDIO:
2864 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2865 "WebRTC.PeerConnection.SslCipherSuite.Audio", ssl_cipher_suite,
2866 rtc::kSslCipherSuiteMaxValue);
2867 break;
2868 case cricket::MEDIA_TYPE_VIDEO:
2869 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2870 "WebRTC.PeerConnection.SslCipherSuite.Video", ssl_cipher_suite,
2871 rtc::kSslCipherSuiteMaxValue);
2872 break;
2873 case cricket::MEDIA_TYPE_DATA:
2874 RTC_HISTOGRAM_ENUMERATION_SPARSE(
2875 "WebRTC.PeerConnection.SslCipherSuite.Data", ssl_cipher_suite,
2876 rtc::kSslCipherSuiteMaxValue);
2877 break;
2878 default:
2879 RTC_DCHECK_NOTREACHED();
2880 continue;
2881 }
2882 }
2883 }
2884 }
2885
OnTransportChanged(const std::string & mid,RtpTransportInternal * rtp_transport,rtc::scoped_refptr<DtlsTransport> dtls_transport,DataChannelTransportInterface * data_channel_transport)2886 bool PeerConnection::OnTransportChanged(
2887 const std::string& mid,
2888 RtpTransportInternal* rtp_transport,
2889 rtc::scoped_refptr<DtlsTransport> dtls_transport,
2890 DataChannelTransportInterface* data_channel_transport) {
2891 RTC_DCHECK_RUN_ON(network_thread());
2892 bool ret = true;
2893 if (ConfiguredForMedia()) {
2894 for (const auto& transceiver :
2895 rtp_manager()->transceivers()->UnsafeList()) {
2896 cricket::ChannelInterface* channel = transceiver->internal()->channel();
2897 if (channel && channel->mid() == mid) {
2898 ret = channel->SetRtpTransport(rtp_transport);
2899 }
2900 }
2901 }
2902
2903 if (mid == sctp_mid_n_) {
2904 data_channel_controller_.OnTransportChanged(data_channel_transport);
2905 if (dtls_transport) {
2906 signaling_thread()->PostTask(SafeTask(
2907 signaling_thread_safety_.flag(),
2908 [this,
2909 name = std::string(dtls_transport->internal()->transport_name())] {
2910 RTC_DCHECK_RUN_ON(signaling_thread());
2911 sctp_transport_name_s_ = std::move(name);
2912 }));
2913 }
2914 }
2915
2916 return ret;
2917 }
2918
Observer() const2919 PeerConnectionObserver* PeerConnection::Observer() const {
2920 RTC_DCHECK_RUN_ON(signaling_thread());
2921 RTC_DCHECK(observer_);
2922 return observer_;
2923 }
2924
StartSctpTransport(int local_port,int remote_port,int max_message_size)2925 void PeerConnection::StartSctpTransport(int local_port,
2926 int remote_port,
2927 int max_message_size) {
2928 RTC_DCHECK_RUN_ON(signaling_thread());
2929 if (!sctp_mid_s_)
2930 return;
2931
2932 network_thread()->PostTask(SafeTask(
2933 network_thread_safety_,
2934 [this, mid = *sctp_mid_s_, local_port, remote_port, max_message_size] {
2935 rtc::scoped_refptr<SctpTransport> sctp_transport =
2936 transport_controller_n()->GetSctpTransport(mid);
2937 if (sctp_transport)
2938 sctp_transport->Start(local_port, remote_port, max_message_size);
2939 }));
2940 }
2941
GetCryptoOptions()2942 CryptoOptions PeerConnection::GetCryptoOptions() {
2943 RTC_DCHECK_RUN_ON(signaling_thread());
2944 // TODO(bugs.webrtc.org/9891) - Remove PeerConnectionFactory::CryptoOptions
2945 // after it has been removed.
2946 return configuration_.crypto_options.has_value()
2947 ? *configuration_.crypto_options
2948 : options_.crypto_options;
2949 }
2950
ClearStatsCache()2951 void PeerConnection::ClearStatsCache() {
2952 RTC_DCHECK_RUN_ON(signaling_thread());
2953 if (legacy_stats_) {
2954 legacy_stats_->InvalidateCache();
2955 }
2956 if (stats_collector_) {
2957 stats_collector_->ClearCachedStatsReport();
2958 }
2959 }
2960
ShouldFireNegotiationNeededEvent(uint32_t event_id)2961 bool PeerConnection::ShouldFireNegotiationNeededEvent(uint32_t event_id) {
2962 RTC_DCHECK_RUN_ON(signaling_thread());
2963 return sdp_handler_->ShouldFireNegotiationNeededEvent(event_id);
2964 }
2965
RequestUsagePatternReportForTesting()2966 void PeerConnection::RequestUsagePatternReportForTesting() {
2967 RTC_DCHECK_RUN_ON(signaling_thread());
2968 message_handler_.RequestUsagePatternReport(
2969 [this]() {
2970 RTC_DCHECK_RUN_ON(signaling_thread());
2971 ReportUsagePattern();
2972 },
2973 /* delay_ms= */ 0);
2974 }
2975
2976 std::function<void(const rtc::CopyOnWriteBuffer& packet,
2977 int64_t packet_time_us)>
InitializeRtcpCallback()2978 PeerConnection::InitializeRtcpCallback() {
2979 RTC_DCHECK_RUN_ON(network_thread());
2980 return [this](const rtc::CopyOnWriteBuffer& packet, int64_t packet_time_us) {
2981 RTC_DCHECK_RUN_ON(network_thread());
2982 call_ptr_->Receiver()->DeliverPacket(MediaType::ANY, packet,
2983 packet_time_us);
2984 };
2985 }
2986
2987 } // namespace webrtc
2988