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