blob: 65203fdc731f1ef8e861e3971800d811fa2c61cc [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
ossu7bb87ee2017-01-23 04:56:25 -080011#include "webrtc/pc/peerconnection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
deadbeefeb459812015-12-15 19:24:43 -080013#include <algorithm>
kwiberg0eb15ed2015-12-17 03:04:15 -080014#include <utility>
15#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000016
Henrik Kjellander15583c12016-02-10 10:53:12 +010017#include "webrtc/api/jsepicecandidate.h"
18#include "webrtc/api/jsepsessiondescription.h"
19#include "webrtc/api/mediaconstraintsinterface.h"
Henrik Kjellander15583c12016-02-10 10:53:12 +010020#include "webrtc/api/mediastreamproxy.h"
21#include "webrtc/api/mediastreamtrackproxy.h"
ivoc14d5dbe2016-07-04 07:06:55 -070022#include "webrtc/base/bind.h"
nissec80e7412017-01-11 05:56:46 -080023#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000024#include "webrtc/base/logging.h"
25#include "webrtc/base/stringencode.h"
deadbeefab9b2d12015-10-14 11:33:11 -070026#include "webrtc/base/stringutils.h"
Peter Boström1a9d6152015-12-08 22:15:17 +010027#include "webrtc/base/trace_event.h"
ossuf515ab82016-12-07 04:52:58 -080028#include "webrtc/call/call.h"
skvlad11a9cbf2016-10-07 11:53:05 -070029#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
deadbeef953c2ce2017-01-09 14:53:41 -080030#include "webrtc/media/sctp/sctptransport.h"
ossu7bb87ee2017-01-23 04:56:25 -080031#include "webrtc/pc/audiotrack.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010032#include "webrtc/pc/channelmanager.h"
ossu7bb87ee2017-01-23 04:56:25 -080033#include "webrtc/pc/dtmfsender.h"
34#include "webrtc/pc/mediastream.h"
35#include "webrtc/pc/mediastreamobserver.h"
36#include "webrtc/pc/remoteaudiosource.h"
37#include "webrtc/pc/rtpreceiver.h"
38#include "webrtc/pc/rtpsender.h"
39#include "webrtc/pc/streamcollection.h"
40#include "webrtc/pc/videocapturertracksource.h"
41#include "webrtc/pc/videotrack.h"
42#include "webrtc/system_wrappers/include/clock.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010043#include "webrtc/system_wrappers/include/field_trial.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044
45namespace {
46
deadbeefab9b2d12015-10-14 11:33:11 -070047using webrtc::DataChannel;
48using webrtc::MediaConstraintsInterface;
49using webrtc::MediaStreamInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050using webrtc::PeerConnectionInterface;
deadbeef293e9262017-01-11 12:28:30 -080051using webrtc::RTCError;
52using webrtc::RTCErrorType;
deadbeefa601f5c2016-06-06 14:27:39 -070053using webrtc::RtpSenderInternal;
deadbeeffac06552015-11-25 11:26:01 -080054using webrtc::RtpSenderInterface;
deadbeefa601f5c2016-06-06 14:27:39 -070055using webrtc::RtpSenderProxy;
56using webrtc::RtpSenderProxyWithInternal;
deadbeefab9b2d12015-10-14 11:33:11 -070057using webrtc::StreamCollection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058
deadbeefab9b2d12015-10-14 11:33:11 -070059static const char kDefaultStreamLabel[] = "default";
60static const char kDefaultAudioTrackLabel[] = "defaulta0";
61static const char kDefaultVideoTrackLabel[] = "defaultv0";
62
zhihuang8f65cdf2016-05-06 18:40:30 -070063// The length of RTCP CNAMEs.
64static const int kRtcpCnameLength = 16;
65
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066enum {
wu@webrtc.org91053e72013-08-10 07:18:04 +000067 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 MSG_SET_SESSIONDESCRIPTION_FAILED,
deadbeefab9b2d12015-10-14 11:33:11 -070069 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070 MSG_GETSTATS,
deadbeefbd292462015-12-14 18:15:29 -080071 MSG_FREE_DATACHANNELS,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072};
73
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000074struct SetSessionDescriptionMsg : public rtc::MessageData {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075 explicit SetSessionDescriptionMsg(
76 webrtc::SetSessionDescriptionObserver* observer)
77 : observer(observer) {
78 }
79
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000080 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081 std::string error;
82};
83
deadbeefab9b2d12015-10-14 11:33:11 -070084struct CreateSessionDescriptionMsg : public rtc::MessageData {
85 explicit CreateSessionDescriptionMsg(
86 webrtc::CreateSessionDescriptionObserver* observer)
87 : observer(observer) {}
88
89 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
90 std::string error;
91};
92
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000093struct GetStatsMsg : public rtc::MessageData {
tommi@webrtc.org5b06b062014-08-15 08:38:30 +000094 GetStatsMsg(webrtc::StatsObserver* observer,
95 webrtc::MediaStreamTrackInterface* track)
96 : observer(observer), track(track) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000098 rtc::scoped_refptr<webrtc::StatsObserver> observer;
tommi@webrtc.org5b06b062014-08-15 08:38:30 +000099 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100};
101
deadbeefab9b2d12015-10-14 11:33:11 -0700102// Check if we can send |new_stream| on a PeerConnection.
103bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
104 webrtc::MediaStreamInterface* new_stream) {
105 if (!new_stream || !current_streams) {
106 return false;
107 }
108 if (current_streams->find(new_stream->label()) != nullptr) {
109 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label()
110 << " is already added.";
111 return false;
112 }
113 return true;
114}
115
116bool MediaContentDirectionHasSend(cricket::MediaContentDirection dir) {
117 return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV;
118}
119
deadbeef5e97fb52015-10-15 12:49:08 -0700120// If the direction is "recvonly" or "inactive", treat the description
121// as containing no streams.
122// See: https://code.google.com/p/webrtc/issues/detail?id=5054
123std::vector<cricket::StreamParams> GetActiveStreams(
124 const cricket::MediaContentDescription* desc) {
125 return MediaContentDirectionHasSend(desc->direction())
126 ? desc->streams()
127 : std::vector<cricket::StreamParams>();
128}
129
deadbeefab9b2d12015-10-14 11:33:11 -0700130bool IsValidOfferToReceiveMedia(int value) {
131 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
132 return (value >= Options::kUndefined) &&
133 (value <= Options::kMaxOfferToReceiveMedia);
134}
135
136// Add the stream and RTP data channel info to |session_options|.
deadbeeffac06552015-11-25 11:26:01 -0800137void AddSendStreams(
138 cricket::MediaSessionOptions* session_options,
deadbeefa601f5c2016-06-06 14:27:39 -0700139 const std::vector<rtc::scoped_refptr<
140 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders,
deadbeeffac06552015-11-25 11:26:01 -0800141 const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
142 rtp_data_channels) {
deadbeefab9b2d12015-10-14 11:33:11 -0700143 session_options->streams.clear();
deadbeeffac06552015-11-25 11:26:01 -0800144 for (const auto& sender : senders) {
145 session_options->AddSendStream(sender->media_type(), sender->id(),
deadbeefa601f5c2016-06-06 14:27:39 -0700146 sender->internal()->stream_id());
deadbeefab9b2d12015-10-14 11:33:11 -0700147 }
148
149 // Check for data channels.
150 for (const auto& kv : rtp_data_channels) {
151 const DataChannel* channel = kv.second;
152 if (channel->state() == DataChannel::kConnecting ||
153 channel->state() == DataChannel::kOpen) {
154 // |streamid| and |sync_label| are both set to the DataChannel label
155 // here so they can be signaled the same way as MediaStreams and Tracks.
156 // For MediaStreams, the sync_label is the MediaStream label and the
157 // track label is the same as |streamid|.
158 const std::string& streamid = channel->label();
159 const std::string& sync_label = channel->label();
160 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid,
161 sync_label);
162 }
163 }
164}
165
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700166uint32_t ConvertIceTransportTypeToCandidateFilter(
167 PeerConnectionInterface::IceTransportsType type) {
168 switch (type) {
169 case PeerConnectionInterface::kNone:
170 return cricket::CF_NONE;
171 case PeerConnectionInterface::kRelay:
172 return cricket::CF_RELAY;
173 case PeerConnectionInterface::kNoHost:
174 return (cricket::CF_ALL & ~cricket::CF_HOST);
175 case PeerConnectionInterface::kAll:
176 return cricket::CF_ALL;
177 default:
nissec80e7412017-01-11 05:56:46 -0800178 RTC_NOTREACHED();
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700179 }
180 return cricket::CF_NONE;
181}
182
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700183// Helper method to set a voice/video channel on all applicable senders
184// and receivers when one is created/destroyed by WebRtcSession.
185//
186// Used by On(Voice|Video)Channel(Created|Destroyed)
187template <class SENDER,
188 class RECEIVER,
189 class CHANNEL,
190 class SENDERS,
191 class RECEIVERS>
192void SetChannelOnSendersAndReceivers(CHANNEL* channel,
193 SENDERS& senders,
194 RECEIVERS& receivers,
195 cricket::MediaType media_type) {
196 for (auto& sender : senders) {
197 if (sender->media_type() == media_type) {
198 static_cast<SENDER*>(sender->internal())->SetChannel(channel);
199 }
200 }
201 for (auto& receiver : receivers) {
202 if (receiver->media_type() == media_type) {
203 if (!channel) {
204 receiver->internal()->Stop();
205 }
206 static_cast<RECEIVER*>(receiver->internal())->SetChannel(channel);
207 }
208 }
209}
210
deadbeef293e9262017-01-11 12:28:30 -0800211// Helper to set an error and return from a method.
212bool SafeSetError(webrtc::RTCErrorType type, webrtc::RTCError* error) {
213 if (error) {
214 error->set_type(type);
215 }
216 return type == webrtc::RTCErrorType::NONE;
217}
218
deadbeef0a6c4ca2015-10-06 11:38:28 -0700219} // namespace
220
221namespace webrtc {
222
deadbeef293e9262017-01-11 12:28:30 -0800223bool PeerConnectionInterface::RTCConfiguration::operator==(
224 const PeerConnectionInterface::RTCConfiguration& o) const {
225 // This static_assert prevents us from accidentally breaking operator==.
226 struct stuff_being_tested_for_equality {
227 IceTransportsType type;
228 IceServers servers;
229 BundlePolicy bundle_policy;
230 RtcpMuxPolicy rtcp_mux_policy;
231 TcpCandidatePolicy tcp_candidate_policy;
232 CandidateNetworkPolicy candidate_network_policy;
233 int audio_jitter_buffer_max_packets;
234 bool audio_jitter_buffer_fast_accelerate;
235 int ice_connection_receiving_timeout;
236 int ice_backup_candidate_pair_ping_interval;
237 ContinualGatheringPolicy continual_gathering_policy;
238 std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
239 bool prioritize_most_likely_ice_candidate_pairs;
240 struct cricket::MediaConfig media_config;
241 bool disable_ipv6;
zhihuangb09b3f92017-03-07 14:40:51 -0800242 bool disable_ipv6_on_wifi;
deadbeef293e9262017-01-11 12:28:30 -0800243 bool enable_rtp_data_channel;
244 bool enable_quic;
245 rtc::Optional<int> screencast_min_bitrate;
246 rtc::Optional<bool> combined_audio_video_bwe;
247 rtc::Optional<bool> enable_dtls_srtp;
248 int ice_candidate_pool_size;
249 bool prune_turn_ports;
250 bool presume_writable_when_fully_relayed;
251 bool enable_ice_renomination;
252 bool redetermine_role_on_ice_restart;
skvlad51072462017-02-02 11:50:14 -0800253 rtc::Optional<int> ice_check_min_interval;
deadbeef293e9262017-01-11 12:28:30 -0800254 };
255 static_assert(sizeof(stuff_being_tested_for_equality) == sizeof(*this),
256 "Did you add something to RTCConfiguration and forget to "
257 "update operator==?");
258 return type == o.type && servers == o.servers &&
259 bundle_policy == o.bundle_policy &&
260 rtcp_mux_policy == o.rtcp_mux_policy &&
261 tcp_candidate_policy == o.tcp_candidate_policy &&
262 candidate_network_policy == o.candidate_network_policy &&
263 audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets &&
264 audio_jitter_buffer_fast_accelerate ==
265 o.audio_jitter_buffer_fast_accelerate &&
266 ice_connection_receiving_timeout ==
267 o.ice_connection_receiving_timeout &&
268 ice_backup_candidate_pair_ping_interval ==
269 o.ice_backup_candidate_pair_ping_interval &&
270 continual_gathering_policy == o.continual_gathering_policy &&
271 certificates == o.certificates &&
272 prioritize_most_likely_ice_candidate_pairs ==
273 o.prioritize_most_likely_ice_candidate_pairs &&
274 media_config == o.media_config && disable_ipv6 == o.disable_ipv6 &&
zhihuangb09b3f92017-03-07 14:40:51 -0800275 disable_ipv6_on_wifi == o.disable_ipv6_on_wifi &&
deadbeef293e9262017-01-11 12:28:30 -0800276 enable_rtp_data_channel == o.enable_rtp_data_channel &&
277 enable_quic == o.enable_quic &&
278 screencast_min_bitrate == o.screencast_min_bitrate &&
279 combined_audio_video_bwe == o.combined_audio_video_bwe &&
280 enable_dtls_srtp == o.enable_dtls_srtp &&
281 ice_candidate_pool_size == o.ice_candidate_pool_size &&
282 prune_turn_ports == o.prune_turn_ports &&
283 presume_writable_when_fully_relayed ==
284 o.presume_writable_when_fully_relayed &&
285 enable_ice_renomination == o.enable_ice_renomination &&
skvlad51072462017-02-02 11:50:14 -0800286 redetermine_role_on_ice_restart == o.redetermine_role_on_ice_restart &&
287 ice_check_min_interval == o.ice_check_min_interval;
deadbeef293e9262017-01-11 12:28:30 -0800288}
289
290bool PeerConnectionInterface::RTCConfiguration::operator!=(
291 const PeerConnectionInterface::RTCConfiguration& o) const {
292 return !(*this == o);
deadbeef3edec7c2016-12-10 11:44:26 -0800293}
294
zhihuang8f65cdf2016-05-06 18:40:30 -0700295// Generate a RTCP CNAME when a PeerConnection is created.
296std::string GenerateRtcpCname() {
297 std::string cname;
298 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) {
299 LOG(LS_ERROR) << "Failed to generate CNAME.";
nisseeb4ca4e2017-01-12 02:24:27 -0800300 RTC_NOTREACHED();
zhihuang8f65cdf2016-05-06 18:40:30 -0700301 }
302 return cname;
303}
304
htaa2a49d92016-03-04 02:51:39 -0800305bool ExtractMediaSessionOptions(
deadbeefab9b2d12015-10-14 11:33:11 -0700306 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
htaaac2dea2016-03-10 13:35:55 -0800307 bool is_offer,
deadbeefab9b2d12015-10-14 11:33:11 -0700308 cricket::MediaSessionOptions* session_options) {
309 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
310 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) ||
311 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) {
312 return false;
313 }
314
htaaac2dea2016-03-10 13:35:55 -0800315 // If constraints don't prevent us, we always accept video.
deadbeefc80741f2015-10-22 13:14:45 -0700316 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
deadbeefab9b2d12015-10-14 11:33:11 -0700317 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0);
htaaac2dea2016-03-10 13:35:55 -0800318 } else {
319 session_options->recv_audio = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700320 }
htaaac2dea2016-03-10 13:35:55 -0800321 // For offers, we only offer video if we have it or it's forced by options.
322 // For answers, we will always accept video (if offered).
deadbeefc80741f2015-10-22 13:14:45 -0700323 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
deadbeefab9b2d12015-10-14 11:33:11 -0700324 session_options->recv_video = (rtc_options.offer_to_receive_video > 0);
htaaac2dea2016-03-10 13:35:55 -0800325 } else if (is_offer) {
326 session_options->recv_video = false;
327 } else {
328 session_options->recv_video = true;
deadbeefab9b2d12015-10-14 11:33:11 -0700329 }
330
331 session_options->vad_enabled = rtc_options.voice_activity_detection;
deadbeefc80741f2015-10-22 13:14:45 -0700332 session_options->bundle_enabled = rtc_options.use_rtp_mux;
deadbeef0ed85b22016-02-23 17:24:52 -0800333 for (auto& kv : session_options->transport_options) {
334 kv.second.ice_restart = rtc_options.ice_restart;
335 }
deadbeefab9b2d12015-10-14 11:33:11 -0700336
337 return true;
338}
339
340bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
341 cricket::MediaSessionOptions* session_options) {
342 bool value = false;
343 size_t mandatory_constraints_satisfied = 0;
344
345 // kOfferToReceiveAudio defaults to true according to spec.
346 if (!FindConstraint(constraints,
347 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
348 &mandatory_constraints_satisfied) ||
349 value) {
350 session_options->recv_audio = true;
351 }
352
353 // kOfferToReceiveVideo defaults to false according to spec. But
354 // if it is an answer and video is offered, we should still accept video
355 // per default.
356 value = false;
357 if (!FindConstraint(constraints,
358 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
359 &mandatory_constraints_satisfied) ||
360 value) {
361 session_options->recv_video = true;
362 }
363
364 if (FindConstraint(constraints,
365 MediaConstraintsInterface::kVoiceActivityDetection, &value,
366 &mandatory_constraints_satisfied)) {
367 session_options->vad_enabled = value;
368 }
369
370 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
371 &mandatory_constraints_satisfied)) {
372 session_options->bundle_enabled = value;
373 } else {
374 // kUseRtpMux defaults to true according to spec.
375 session_options->bundle_enabled = true;
376 }
deadbeefab9b2d12015-10-14 11:33:11 -0700377
deadbeef0ed85b22016-02-23 17:24:52 -0800378 bool ice_restart = false;
deadbeefab9b2d12015-10-14 11:33:11 -0700379 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
380 &value, &mandatory_constraints_satisfied)) {
deadbeefab9b2d12015-10-14 11:33:11 -0700381 // kIceRestart defaults to false according to spec.
deadbeef0ed85b22016-02-23 17:24:52 -0800382 ice_restart = true;
383 }
384 for (auto& kv : session_options->transport_options) {
385 kv.second.ice_restart = ice_restart;
deadbeefab9b2d12015-10-14 11:33:11 -0700386 }
387
388 if (!constraints) {
389 return true;
390 }
391 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
392}
393
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000394PeerConnection::PeerConnection(PeerConnectionFactory* factory)
395 : factory_(factory),
396 observer_(NULL),
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +0000397 uma_observer_(NULL),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000398 signaling_state_(kStable),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000399 ice_connection_state_(kIceConnectionNew),
deadbeefab9b2d12015-10-14 11:33:11 -0700400 ice_gathering_state_(kIceGatheringNew),
nisse30612762016-12-20 05:03:58 -0800401 event_log_(RtcEventLog::Create()),
zhihuang8f65cdf2016-05-06 18:40:30 -0700402 rtcp_cname_(GenerateRtcpCname()),
deadbeefab9b2d12015-10-14 11:33:11 -0700403 local_streams_(StreamCollection::Create()),
404 remote_streams_(StreamCollection::Create()) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000405
406PeerConnection::~PeerConnection() {
Peter Boström1a9d6152015-12-08 22:15:17 +0100407 TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection");
deadbeef0a6c4ca2015-10-06 11:38:28 -0700408 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeef70ab1a12015-09-28 16:53:55 -0700409 // Need to detach RTP senders/receivers from WebRtcSession,
410 // since it's about to be destroyed.
411 for (const auto& sender : senders_) {
deadbeefa601f5c2016-06-06 14:27:39 -0700412 sender->internal()->Stop();
deadbeef70ab1a12015-09-28 16:53:55 -0700413 }
414 for (const auto& receiver : receivers_) {
deadbeefa601f5c2016-06-06 14:27:39 -0700415 receiver->internal()->Stop();
deadbeef70ab1a12015-09-28 16:53:55 -0700416 }
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700417 // Destroy stats_ because it depends on session_.
418 stats_.reset(nullptr);
hbosb78306a2016-12-19 05:06:57 -0800419 if (stats_collector_) {
420 stats_collector_->WaitForPendingRequest();
421 stats_collector_ = nullptr;
422 }
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700423 // Now destroy session_ before destroying other members,
424 // because its destruction fires signals (such as VoiceChannelDestroyed)
425 // which will trigger some final actions in PeerConnection...
426 session_.reset(nullptr);
deadbeef91dd5672016-05-18 16:55:30 -0700427 // port_allocator_ lives on the network thread and should be destroyed there.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700428 network_thread()->Invoke<void>(RTC_FROM_HERE,
nisseeaabdf62017-05-05 02:23:02 -0700429 [this] { port_allocator_.reset(); });
430 // call_ must be destroyed on the worker thread.
431 factory_->worker_thread()->Invoke<void>(RTC_FROM_HERE,
432 [this] { call_.reset(); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433}
434
435bool PeerConnection::Initialize(
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000436 const PeerConnectionInterface::RTCConfiguration& configuration,
kwibergd1fe2812016-04-27 06:47:29 -0700437 std::unique_ptr<cricket::PortAllocator> allocator,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200438 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
deadbeef653b8e02015-11-11 12:55:10 -0800439 PeerConnectionObserver* observer) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100440 TRACE_EVENT0("webrtc", "PeerConnection::Initialize");
deadbeef293e9262017-01-11 12:28:30 -0800441 if (!allocator) {
442 LOG(LS_ERROR) << "PeerConnection initialized without a PortAllocator? "
443 << "This shouldn't happen if using PeerConnectionFactory.";
444 return false;
445 }
deadbeef653b8e02015-11-11 12:55:10 -0800446 if (!observer) {
deadbeef293e9262017-01-11 12:28:30 -0800447 // TODO(deadbeef): Why do we do this?
448 LOG(LS_ERROR) << "PeerConnection initialized without a "
449 << "PeerConnectionObserver";
deadbeef653b8e02015-11-11 12:55:10 -0800450 return false;
451 }
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000452 observer_ = observer;
kwiberg0eb15ed2015-12-17 03:04:15 -0800453 port_allocator_ = std::move(allocator);
deadbeef653b8e02015-11-11 12:55:10 -0800454
deadbeef91dd5672016-05-18 16:55:30 -0700455 // The port allocator lives on the network thread and should be initialized
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700456 // there.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700457 if (!network_thread()->Invoke<bool>(
458 RTC_FROM_HERE, rtc::Bind(&PeerConnection::InitializePortAllocator_n,
459 this, configuration))) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000460 return false;
461 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000462
nisseeaabdf62017-05-05 02:23:02 -0700463 // Call must be constructed on the worker thread.
464 factory_->worker_thread()->Invoke<void>(
465 RTC_FROM_HERE, rtc::Bind(&PeerConnection::CreateCall_w,
466 this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467
zhihuang29ff8442016-07-27 11:07:25 -0700468 session_.reset(new WebRtcSession(
nisseeaabdf62017-05-05 02:23:02 -0700469 call_.get(), factory_->channel_manager(), configuration.media_config,
470 event_log_.get(),
471 factory_->network_thread(),
zhihuang29ff8442016-07-27 11:07:25 -0700472 factory_->worker_thread(), factory_->signaling_thread(),
473 port_allocator_.get(),
474 std::unique_ptr<cricket::TransportController>(
Honghai Zhangbfd398c2016-08-30 22:07:42 -0700475 factory_->CreateTransportController(
476 port_allocator_.get(),
deadbeef953c2ce2017-01-09 14:53:41 -0800477 configuration.redetermine_role_on_ice_restart)),
478#ifdef HAVE_SCTP
479 std::unique_ptr<cricket::SctpTransportInternalFactory>(
480 new cricket::SctpTransportFactory(factory_->network_thread()))
481#else
482 nullptr
483#endif
484 ));
zhihuang29ff8442016-07-27 11:07:25 -0700485
deadbeefab9b2d12015-10-14 11:33:11 -0700486 stats_.reset(new StatsCollector(this));
hbos74e1a4f2016-09-15 23:33:01 -0700487 stats_collector_ = RTCStatsCollector::Create(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488
489 // Initialize the WebRtcSession. It creates transport channels etc.
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200490 if (!session_->Initialize(factory_->options(), std::move(cert_generator),
htaa2a49d92016-03-04 02:51:39 -0800491 configuration)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000492 return false;
deadbeefab9b2d12015-10-14 11:33:11 -0700493 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000494
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000495 // Register PeerConnection as receiver of local ice candidates.
496 // All the callbacks will be posted to the application from PeerConnection.
497 session_->RegisterIceObserver(this);
498 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700499 session_->SignalVoiceChannelCreated.connect(
500 this, &PeerConnection::OnVoiceChannelCreated);
deadbeefab9b2d12015-10-14 11:33:11 -0700501 session_->SignalVoiceChannelDestroyed.connect(
502 this, &PeerConnection::OnVoiceChannelDestroyed);
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700503 session_->SignalVideoChannelCreated.connect(
504 this, &PeerConnection::OnVideoChannelCreated);
deadbeefab9b2d12015-10-14 11:33:11 -0700505 session_->SignalVideoChannelDestroyed.connect(
506 this, &PeerConnection::OnVideoChannelDestroyed);
507 session_->SignalDataChannelCreated.connect(
508 this, &PeerConnection::OnDataChannelCreated);
509 session_->SignalDataChannelDestroyed.connect(
510 this, &PeerConnection::OnDataChannelDestroyed);
511 session_->SignalDataChannelOpenMessage.connect(
512 this, &PeerConnection::OnDataChannelOpenMessage);
deadbeef46c73892016-11-16 19:42:04 -0800513
514 configuration_ = configuration;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515 return true;
516}
517
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000518rtc::scoped_refptr<StreamCollectionInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519PeerConnection::local_streams() {
deadbeefab9b2d12015-10-14 11:33:11 -0700520 return local_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521}
522
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000523rtc::scoped_refptr<StreamCollectionInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524PeerConnection::remote_streams() {
deadbeefab9b2d12015-10-14 11:33:11 -0700525 return remote_streams_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526}
527
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000528bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100529 TRACE_EVENT0("webrtc", "PeerConnection::AddStream");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 if (IsClosed()) {
531 return false;
532 }
deadbeefab9b2d12015-10-14 11:33:11 -0700533 if (!CanAddLocalMediaStream(local_streams_, local_stream)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000534 return false;
535 }
deadbeefab9b2d12015-10-14 11:33:11 -0700536
537 local_streams_->AddStream(local_stream);
deadbeefeb459812015-12-15 19:24:43 -0800538 MediaStreamObserver* observer = new MediaStreamObserver(local_stream);
539 observer->SignalAudioTrackAdded.connect(this,
540 &PeerConnection::OnAudioTrackAdded);
541 observer->SignalAudioTrackRemoved.connect(
542 this, &PeerConnection::OnAudioTrackRemoved);
543 observer->SignalVideoTrackAdded.connect(this,
544 &PeerConnection::OnVideoTrackAdded);
545 observer->SignalVideoTrackRemoved.connect(
546 this, &PeerConnection::OnVideoTrackRemoved);
kwibergd1fe2812016-04-27 06:47:29 -0700547 stream_observers_.push_back(std::unique_ptr<MediaStreamObserver>(observer));
deadbeefab9b2d12015-10-14 11:33:11 -0700548
deadbeefab9b2d12015-10-14 11:33:11 -0700549 for (const auto& track : local_stream->GetAudioTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800550 OnAudioTrackAdded(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700551 }
552 for (const auto& track : local_stream->GetVideoTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800553 OnVideoTrackAdded(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700554 }
555
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000556 stats_->AddStream(local_stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 observer_->OnRenegotiationNeeded();
558 return true;
559}
560
561void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100562 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
deadbeefab9b2d12015-10-14 11:33:11 -0700563 for (const auto& track : local_stream->GetAudioTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800564 OnAudioTrackRemoved(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700565 }
566 for (const auto& track : local_stream->GetVideoTracks()) {
deadbeefeb459812015-12-15 19:24:43 -0800567 OnVideoTrackRemoved(track.get(), local_stream);
deadbeefab9b2d12015-10-14 11:33:11 -0700568 }
569
570 local_streams_->RemoveStream(local_stream);
deadbeefeb459812015-12-15 19:24:43 -0800571 stream_observers_.erase(
572 std::remove_if(
573 stream_observers_.begin(), stream_observers_.end(),
kwibergd1fe2812016-04-27 06:47:29 -0700574 [local_stream](const std::unique_ptr<MediaStreamObserver>& observer) {
deadbeefeb459812015-12-15 19:24:43 -0800575 return observer->stream()->label().compare(local_stream->label()) ==
576 0;
577 }),
578 stream_observers_.end());
deadbeefab9b2d12015-10-14 11:33:11 -0700579
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580 if (IsClosed()) {
581 return;
582 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 observer_->OnRenegotiationNeeded();
584}
585
deadbeefe1f9d832016-01-14 15:35:42 -0800586rtc::scoped_refptr<RtpSenderInterface> PeerConnection::AddTrack(
587 MediaStreamTrackInterface* track,
588 std::vector<MediaStreamInterface*> streams) {
589 TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
590 if (IsClosed()) {
591 return nullptr;
592 }
593 if (streams.size() >= 2) {
594 LOG(LS_ERROR)
595 << "Adding a track with two streams is not currently supported.";
596 return nullptr;
597 }
598 // TODO(deadbeef): Support adding a track to two different senders.
599 if (FindSenderForTrack(track) != senders_.end()) {
600 LOG(LS_ERROR) << "Sender for track " << track->id() << " already exists.";
601 return nullptr;
602 }
603
604 // TODO(deadbeef): Support adding a track to multiple streams.
deadbeefa601f5c2016-06-06 14:27:39 -0700605 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
deadbeefe1f9d832016-01-14 15:35:42 -0800606 if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
deadbeefa601f5c2016-06-06 14:27:39 -0700607 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
deadbeefe1f9d832016-01-14 15:35:42 -0800608 signaling_thread(),
609 new AudioRtpSender(static_cast<AudioTrackInterface*>(track),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700610 session_->voice_channel(), stats_.get()));
deadbeefe1f9d832016-01-14 15:35:42 -0800611 if (!streams.empty()) {
deadbeefa601f5c2016-06-06 14:27:39 -0700612 new_sender->internal()->set_stream_id(streams[0]->label());
deadbeefe1f9d832016-01-14 15:35:42 -0800613 }
614 const TrackInfo* track_info = FindTrackInfo(
deadbeefa601f5c2016-06-06 14:27:39 -0700615 local_audio_tracks_, new_sender->internal()->stream_id(), track->id());
deadbeefe1f9d832016-01-14 15:35:42 -0800616 if (track_info) {
deadbeefa601f5c2016-06-06 14:27:39 -0700617 new_sender->internal()->SetSsrc(track_info->ssrc);
deadbeefe1f9d832016-01-14 15:35:42 -0800618 }
619 } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
deadbeefa601f5c2016-06-06 14:27:39 -0700620 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
deadbeefe1f9d832016-01-14 15:35:42 -0800621 signaling_thread(),
622 new VideoRtpSender(static_cast<VideoTrackInterface*>(track),
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700623 session_->video_channel()));
deadbeefe1f9d832016-01-14 15:35:42 -0800624 if (!streams.empty()) {
deadbeefa601f5c2016-06-06 14:27:39 -0700625 new_sender->internal()->set_stream_id(streams[0]->label());
deadbeefe1f9d832016-01-14 15:35:42 -0800626 }
627 const TrackInfo* track_info = FindTrackInfo(
deadbeefa601f5c2016-06-06 14:27:39 -0700628 local_video_tracks_, new_sender->internal()->stream_id(), track->id());
deadbeefe1f9d832016-01-14 15:35:42 -0800629 if (track_info) {
deadbeefa601f5c2016-06-06 14:27:39 -0700630 new_sender->internal()->SetSsrc(track_info->ssrc);
deadbeefe1f9d832016-01-14 15:35:42 -0800631 }
632 } else {
633 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << track->kind();
634 return rtc::scoped_refptr<RtpSenderInterface>();
635 }
636
637 senders_.push_back(new_sender);
638 observer_->OnRenegotiationNeeded();
639 return new_sender;
640}
641
642bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) {
643 TRACE_EVENT0("webrtc", "PeerConnection::RemoveTrack");
644 if (IsClosed()) {
645 return false;
646 }
647
648 auto it = std::find(senders_.begin(), senders_.end(), sender);
649 if (it == senders_.end()) {
650 LOG(LS_ERROR) << "Couldn't find sender " << sender->id() << " to remove.";
651 return false;
652 }
deadbeefa601f5c2016-06-06 14:27:39 -0700653 (*it)->internal()->Stop();
deadbeefe1f9d832016-01-14 15:35:42 -0800654 senders_.erase(it);
655
656 observer_->OnRenegotiationNeeded();
657 return true;
658}
659
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000660rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 AudioTrackInterface* track) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100662 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
zhihuang29ff8442016-07-27 11:07:25 -0700663 if (IsClosed()) {
664 return nullptr;
665 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 if (!track) {
667 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL.";
deadbeef20cb0c12017-02-01 20:27:00 -0800668 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 }
deadbeef20cb0c12017-02-01 20:27:00 -0800670 auto it = FindSenderForTrack(track);
671 if (it == senders_.end()) {
672 LOG(LS_ERROR) << "CreateDtmfSender called with a non-added track.";
673 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 }
675
deadbeef20cb0c12017-02-01 20:27:00 -0800676 return (*it)->GetDtmfSender();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677}
678
deadbeeffac06552015-11-25 11:26:01 -0800679rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
deadbeefbd7d8f72015-12-18 16:58:44 -0800680 const std::string& kind,
681 const std::string& stream_id) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100682 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
zhihuang29ff8442016-07-27 11:07:25 -0700683 if (IsClosed()) {
684 return nullptr;
685 }
deadbeefa601f5c2016-06-06 14:27:39 -0700686 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800687 if (kind == MediaStreamTrackInterface::kAudioKind) {
deadbeefa601f5c2016-06-06 14:27:39 -0700688 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700689 signaling_thread(),
690 new AudioRtpSender(session_->voice_channel(), stats_.get()));
deadbeeffac06552015-11-25 11:26:01 -0800691 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
deadbeefa601f5c2016-06-06 14:27:39 -0700692 new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -0700693 signaling_thread(), new VideoRtpSender(session_->video_channel()));
deadbeeffac06552015-11-25 11:26:01 -0800694 } else {
695 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
deadbeefe1f9d832016-01-14 15:35:42 -0800696 return new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800697 }
deadbeefbd7d8f72015-12-18 16:58:44 -0800698 if (!stream_id.empty()) {
deadbeefa601f5c2016-06-06 14:27:39 -0700699 new_sender->internal()->set_stream_id(stream_id);
deadbeefbd7d8f72015-12-18 16:58:44 -0800700 }
deadbeeffac06552015-11-25 11:26:01 -0800701 senders_.push_back(new_sender);
deadbeefe1f9d832016-01-14 15:35:42 -0800702 return new_sender;
deadbeeffac06552015-11-25 11:26:01 -0800703}
704
deadbeef70ab1a12015-09-28 16:53:55 -0700705std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
706 const {
deadbeefa601f5c2016-06-06 14:27:39 -0700707 std::vector<rtc::scoped_refptr<RtpSenderInterface>> ret;
708 for (const auto& sender : senders_) {
709 ret.push_back(sender.get());
710 }
711 return ret;
deadbeef70ab1a12015-09-28 16:53:55 -0700712}
713
714std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
715PeerConnection::GetReceivers() const {
deadbeefa601f5c2016-06-06 14:27:39 -0700716 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> ret;
717 for (const auto& receiver : receivers_) {
718 ret.push_back(receiver.get());
719 }
720 return ret;
deadbeef70ab1a12015-09-28 16:53:55 -0700721}
722
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723bool PeerConnection::GetStats(StatsObserver* observer,
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000724 MediaStreamTrackInterface* track,
725 StatsOutputLevel level) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100726 TRACE_EVENT0("webrtc", "PeerConnection::GetStats");
deadbeef0a6c4ca2015-10-06 11:38:28 -0700727 RTC_DCHECK(signaling_thread()->IsCurrent());
nisse7ce109a2017-01-31 00:57:56 -0800728 if (!observer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729 LOG(LS_ERROR) << "GetStats - observer is NULL.";
730 return false;
731 }
732
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000733 stats_->UpdateStats(level);
zhihuange9e94c32016-11-04 11:38:15 -0700734 // The StatsCollector is used to tell if a track is valid because it may
735 // remember tracks that the PeerConnection previously removed.
736 if (track && !stats_->IsValidTrack(track->id())) {
737 LOG(LS_WARNING) << "GetStats is called with an invalid track: "
738 << track->id();
739 return false;
740 }
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700741 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_GETSTATS,
tommi@webrtc.org5b06b062014-08-15 08:38:30 +0000742 new GetStatsMsg(observer, track));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743 return true;
744}
745
hbos74e1a4f2016-09-15 23:33:01 -0700746void PeerConnection::GetStats(RTCStatsCollectorCallback* callback) {
747 RTC_DCHECK(stats_collector_);
748 stats_collector_->GetStatsReport(callback);
749}
750
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000751PeerConnectionInterface::SignalingState PeerConnection::signaling_state() {
752 return signaling_state_;
753}
754
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000755PeerConnectionInterface::IceConnectionState
756PeerConnection::ice_connection_state() {
757 return ice_connection_state_;
758}
759
760PeerConnectionInterface::IceGatheringState
761PeerConnection::ice_gathering_state() {
762 return ice_gathering_state_;
763}
764
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000765rtc::scoped_refptr<DataChannelInterface>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766PeerConnection::CreateDataChannel(
767 const std::string& label,
768 const DataChannelInit* config) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100769 TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
zhihuang9763d562016-08-05 11:14:50 -0700770#ifdef HAVE_QUIC
771 if (session_->data_channel_type() == cricket::DCT_QUIC) {
772 // TODO(zhihuang): Handle case when config is NULL.
773 if (!config) {
774 LOG(LS_ERROR) << "Missing config for QUIC data channel.";
775 return nullptr;
776 }
777 // TODO(zhihuang): Allow unreliable or ordered QUIC data channels.
778 if (!config->reliable || config->ordered) {
779 LOG(LS_ERROR) << "QUIC data channel does not implement unreliable or "
780 "ordered delivery.";
781 return nullptr;
782 }
783 return session_->quic_data_transport()->CreateDataChannel(label, config);
784 }
785#endif // HAVE_QUIC
786
deadbeefab9b2d12015-10-14 11:33:11 -0700787 bool first_datachannel = !HasDataChannels();
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +0000788
kwibergd1fe2812016-04-27 06:47:29 -0700789 std::unique_ptr<InternalDataChannelInit> internal_config;
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000790 if (config) {
791 internal_config.reset(new InternalDataChannelInit(*config));
792 }
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000793 rtc::scoped_refptr<DataChannelInterface> channel(
deadbeefab9b2d12015-10-14 11:33:11 -0700794 InternalCreateDataChannel(label, internal_config.get()));
795 if (!channel.get()) {
796 return nullptr;
797 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +0000799 // Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or
800 // the first SCTP DataChannel.
801 if (session_->data_channel_type() == cricket::DCT_RTP || first_datachannel) {
802 observer_->OnRenegotiationNeeded();
803 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000804
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 return DataChannelProxy::Create(signaling_thread(), channel.get());
806}
807
808void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
809 const MediaConstraintsInterface* constraints) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100810 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
nisse7ce109a2017-01-31 00:57:56 -0800811 if (!observer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000812 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
813 return;
814 }
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000815 RTCOfferAnswerOptions options;
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000816
817 bool value;
818 size_t mandatory_constraints = 0;
819
820 if (FindConstraint(constraints,
821 MediaConstraintsInterface::kOfferToReceiveAudio,
822 &value,
823 &mandatory_constraints)) {
824 options.offer_to_receive_audio =
825 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
826 }
827
828 if (FindConstraint(constraints,
829 MediaConstraintsInterface::kOfferToReceiveVideo,
830 &value,
831 &mandatory_constraints)) {
832 options.offer_to_receive_video =
833 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
834 }
835
836 if (FindConstraint(constraints,
837 MediaConstraintsInterface::kVoiceActivityDetection,
838 &value,
839 &mandatory_constraints)) {
840 options.voice_activity_detection = value;
841 }
842
843 if (FindConstraint(constraints,
844 MediaConstraintsInterface::kIceRestart,
845 &value,
846 &mandatory_constraints)) {
847 options.ice_restart = value;
848 }
849
850 if (FindConstraint(constraints,
851 MediaConstraintsInterface::kUseRtpMux,
852 &value,
853 &mandatory_constraints)) {
854 options.use_rtp_mux = value;
855 }
856
857 CreateOffer(observer, options);
858}
859
860void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
861 const RTCOfferAnswerOptions& options) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100862 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
nisse7ce109a2017-01-31 00:57:56 -0800863 if (!observer) {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000864 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
865 return;
866 }
deadbeefab9b2d12015-10-14 11:33:11 -0700867
868 cricket::MediaSessionOptions session_options;
869 if (!GetOptionsForOffer(options, &session_options)) {
870 std::string error = "CreateOffer called with invalid options.";
871 LOG(LS_ERROR) << error;
872 PostCreateSessionDescriptionFailure(observer, error);
873 return;
874 }
875
876 session_->CreateOffer(observer, options, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877}
878
879void PeerConnection::CreateAnswer(
880 CreateSessionDescriptionObserver* observer,
881 const MediaConstraintsInterface* constraints) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100882 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
nisse7ce109a2017-01-31 00:57:56 -0800883 if (!observer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000884 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
885 return;
886 }
deadbeefab9b2d12015-10-14 11:33:11 -0700887
888 cricket::MediaSessionOptions session_options;
889 if (!GetOptionsForAnswer(constraints, &session_options)) {
890 std::string error = "CreateAnswer called with invalid constraints.";
891 LOG(LS_ERROR) << error;
892 PostCreateSessionDescriptionFailure(observer, error);
893 return;
894 }
895
htaa2a49d92016-03-04 02:51:39 -0800896 session_->CreateAnswer(observer, session_options);
897}
898
899void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
900 const RTCOfferAnswerOptions& options) {
901 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
nisse7ce109a2017-01-31 00:57:56 -0800902 if (!observer) {
htaa2a49d92016-03-04 02:51:39 -0800903 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
904 return;
905 }
906
907 cricket::MediaSessionOptions session_options;
908 if (!GetOptionsForAnswer(options, &session_options)) {
909 std::string error = "CreateAnswer called with invalid options.";
910 LOG(LS_ERROR) << error;
911 PostCreateSessionDescriptionFailure(observer, error);
912 return;
913 }
914
915 session_->CreateAnswer(observer, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000916}
917
918void PeerConnection::SetLocalDescription(
919 SetSessionDescriptionObserver* observer,
920 SessionDescriptionInterface* desc) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100921 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
zhihuang29ff8442016-07-27 11:07:25 -0700922 if (IsClosed()) {
923 return;
924 }
nisse7ce109a2017-01-31 00:57:56 -0800925 if (!observer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL.";
927 return;
928 }
929 if (!desc) {
930 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
931 return;
932 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 // Update stats here so that we have the most recent stats for tracks and
934 // streams that might be removed by updating the session description.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +0000935 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000936 std::string error;
937 if (!session_->SetLocalDescription(desc, &error)) {
938 PostSetSessionDescriptionFailure(observer, error);
939 return;
940 }
deadbeefab9b2d12015-10-14 11:33:11 -0700941
942 // If setting the description decided our SSL role, allocate any necessary
943 // SCTP sids.
944 rtc::SSLRole role;
945 if (session_->data_channel_type() == cricket::DCT_SCTP &&
deadbeef953c2ce2017-01-09 14:53:41 -0800946 session_->GetSctpSslRole(&role)) {
deadbeefab9b2d12015-10-14 11:33:11 -0700947 AllocateSctpSids(role);
948 }
949
950 // Update state and SSRC of local MediaStreams and DataChannels based on the
951 // local session description.
952 const cricket::ContentInfo* audio_content =
953 GetFirstAudioContent(desc->description());
954 if (audio_content) {
deadbeeffaac4972015-11-12 15:33:07 -0800955 if (audio_content->rejected) {
956 RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
957 } else {
958 const cricket::AudioContentDescription* audio_desc =
959 static_cast<const cricket::AudioContentDescription*>(
960 audio_content->description);
961 UpdateLocalTracks(audio_desc->streams(), audio_desc->type());
962 }
deadbeefab9b2d12015-10-14 11:33:11 -0700963 }
964
965 const cricket::ContentInfo* video_content =
966 GetFirstVideoContent(desc->description());
967 if (video_content) {
deadbeeffaac4972015-11-12 15:33:07 -0800968 if (video_content->rejected) {
969 RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
970 } else {
971 const cricket::VideoContentDescription* video_desc =
972 static_cast<const cricket::VideoContentDescription*>(
973 video_content->description);
974 UpdateLocalTracks(video_desc->streams(), video_desc->type());
975 }
deadbeefab9b2d12015-10-14 11:33:11 -0700976 }
977
978 const cricket::ContentInfo* data_content =
979 GetFirstDataContent(desc->description());
980 if (data_content) {
981 const cricket::DataContentDescription* data_desc =
982 static_cast<const cricket::DataContentDescription*>(
983 data_content->description);
984 if (rtc::starts_with(data_desc->protocol().data(),
985 cricket::kMediaProtocolRtpPrefix)) {
986 UpdateLocalRtpDataChannels(data_desc->streams());
987 }
988 }
989
990 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700991 signaling_thread()->Post(RTC_FROM_HERE, this,
992 MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
deadbeefab9b2d12015-10-14 11:33:11 -0700993
deadbeef42a42632017-03-10 15:18:00 -0800994 // According to JSEP, after setLocalDescription, changing the candidate pool
995 // size is not allowed, and changing the set of ICE servers will not result
996 // in new candidates being gathered.
997 port_allocator_->FreezeCandidatePool();
998
deadbeefcbecd352015-09-23 11:50:27 -0700999 // MaybeStartGathering needs to be called after posting
1000 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
1001 // before signaling that SetLocalDescription completed.
1002 session_->MaybeStartGathering();
deadbeef42a42632017-03-10 15:18:00 -08001003
1004 if (desc->type() == SessionDescriptionInterface::kAnswer) {
1005 // TODO(deadbeef): We already had to hop to the network thread for
1006 // MaybeStartGathering...
1007 network_thread()->Invoke<void>(
1008 RTC_FROM_HERE,
1009 rtc::Bind(&cricket::PortAllocator::DiscardCandidatePool,
1010 port_allocator_.get()));
1011 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001012}
1013
1014void PeerConnection::SetRemoteDescription(
1015 SetSessionDescriptionObserver* observer,
1016 SessionDescriptionInterface* desc) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001017 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription");
zhihuang29ff8442016-07-27 11:07:25 -07001018 if (IsClosed()) {
1019 return;
1020 }
nisse7ce109a2017-01-31 00:57:56 -08001021 if (!observer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001022 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL.";
1023 return;
1024 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001025 if (!desc) {
1026 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
1027 return;
1028 }
1029 // Update stats here so that we have the most recent stats for tracks and
1030 // streams that might be removed by updating the session description.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +00001031 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001032 std::string error;
1033 if (!session_->SetRemoteDescription(desc, &error)) {
1034 PostSetSessionDescriptionFailure(observer, error);
1035 return;
1036 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037
deadbeefab9b2d12015-10-14 11:33:11 -07001038 // If setting the description decided our SSL role, allocate any necessary
1039 // SCTP sids.
1040 rtc::SSLRole role;
1041 if (session_->data_channel_type() == cricket::DCT_SCTP &&
deadbeef953c2ce2017-01-09 14:53:41 -08001042 session_->GetSctpSslRole(&role)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001043 AllocateSctpSids(role);
1044 }
1045
1046 const cricket::SessionDescription* remote_desc = desc->description();
deadbeefbda7e0b2015-12-08 17:13:40 -08001047 const cricket::ContentInfo* audio_content = GetFirstAudioContent(remote_desc);
1048 const cricket::ContentInfo* video_content = GetFirstVideoContent(remote_desc);
1049 const cricket::AudioContentDescription* audio_desc =
1050 GetFirstAudioContentDescription(remote_desc);
1051 const cricket::VideoContentDescription* video_desc =
1052 GetFirstVideoContentDescription(remote_desc);
1053 const cricket::DataContentDescription* data_desc =
1054 GetFirstDataContentDescription(remote_desc);
1055
1056 // Check if the descriptions include streams, just in case the peer supports
1057 // MSID, but doesn't indicate so with "a=msid-semantic".
1058 if (remote_desc->msid_supported() ||
1059 (audio_desc && !audio_desc->streams().empty()) ||
1060 (video_desc && !video_desc->streams().empty())) {
1061 remote_peer_supports_msid_ = true;
1062 }
deadbeefab9b2d12015-10-14 11:33:11 -07001063
1064 // We wait to signal new streams until we finish processing the description,
1065 // since only at that point will new streams have all their tracks.
1066 rtc::scoped_refptr<StreamCollection> new_streams(StreamCollection::Create());
1067
1068 // Find all audio rtp streams and create corresponding remote AudioTracks
1069 // and MediaStreams.
deadbeefab9b2d12015-10-14 11:33:11 -07001070 if (audio_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001071 if (audio_content->rejected) {
1072 RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
1073 } else {
deadbeefbda7e0b2015-12-08 17:13:40 -08001074 bool default_audio_track_needed =
1075 !remote_peer_supports_msid_ &&
1076 MediaContentDirectionHasSend(audio_desc->direction());
1077 UpdateRemoteStreamsList(GetActiveStreams(audio_desc),
1078 default_audio_track_needed, audio_desc->type(),
deadbeeffaac4972015-11-12 15:33:07 -08001079 new_streams);
deadbeeffaac4972015-11-12 15:33:07 -08001080 }
deadbeefab9b2d12015-10-14 11:33:11 -07001081 }
1082
1083 // Find all video rtp streams and create corresponding remote VideoTracks
1084 // and MediaStreams.
deadbeefab9b2d12015-10-14 11:33:11 -07001085 if (video_content) {
deadbeeffaac4972015-11-12 15:33:07 -08001086 if (video_content->rejected) {
1087 RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
1088 } else {
deadbeefbda7e0b2015-12-08 17:13:40 -08001089 bool default_video_track_needed =
1090 !remote_peer_supports_msid_ &&
1091 MediaContentDirectionHasSend(video_desc->direction());
1092 UpdateRemoteStreamsList(GetActiveStreams(video_desc),
1093 default_video_track_needed, video_desc->type(),
deadbeeffaac4972015-11-12 15:33:07 -08001094 new_streams);
deadbeeffaac4972015-11-12 15:33:07 -08001095 }
deadbeefab9b2d12015-10-14 11:33:11 -07001096 }
1097
1098 // Update the DataChannels with the information from the remote peer.
deadbeefbda7e0b2015-12-08 17:13:40 -08001099 if (data_desc) {
1100 if (rtc::starts_with(data_desc->protocol().data(),
deadbeefab9b2d12015-10-14 11:33:11 -07001101 cricket::kMediaProtocolRtpPrefix)) {
deadbeefbda7e0b2015-12-08 17:13:40 -08001102 UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc));
deadbeefab9b2d12015-10-14 11:33:11 -07001103 }
1104 }
1105
1106 // Iterate new_streams and notify the observer about new MediaStreams.
1107 for (size_t i = 0; i < new_streams->count(); ++i) {
1108 MediaStreamInterface* new_stream = new_streams->at(i);
1109 stats_->AddStream(new_stream);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001110 observer_->OnAddStream(
1111 rtc::scoped_refptr<MediaStreamInterface>(new_stream));
deadbeefab9b2d12015-10-14 11:33:11 -07001112 }
1113
deadbeefbda7e0b2015-12-08 17:13:40 -08001114 UpdateEndedRemoteMediaStreams();
deadbeefab9b2d12015-10-14 11:33:11 -07001115
1116 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001117 signaling_thread()->Post(RTC_FROM_HERE, this,
1118 MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
deadbeef42a42632017-03-10 15:18:00 -08001119
1120 if (desc->type() == SessionDescriptionInterface::kAnswer) {
1121 // TODO(deadbeef): We already had to hop to the network thread for
1122 // MaybeStartGathering...
1123 network_thread()->Invoke<void>(
1124 RTC_FROM_HERE,
1125 rtc::Bind(&cricket::PortAllocator::DiscardCandidatePool,
1126 port_allocator_.get()));
1127 }
deadbeeffc648b62015-10-13 16:42:33 -07001128}
1129
deadbeef46c73892016-11-16 19:42:04 -08001130PeerConnectionInterface::RTCConfiguration PeerConnection::GetConfiguration() {
1131 return configuration_;
1132}
1133
deadbeef293e9262017-01-11 12:28:30 -08001134bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration,
1135 RTCError* error) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001136 TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration");
deadbeef6de92f92016-12-12 18:49:32 -08001137
1138 if (session_->local_description() &&
1139 configuration.ice_candidate_pool_size !=
1140 configuration_.ice_candidate_pool_size) {
1141 LOG(LS_ERROR) << "Can't change candidate pool size after calling "
1142 "SetLocalDescription.";
deadbeef293e9262017-01-11 12:28:30 -08001143 return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001144 }
Taylor Brandstettera1c30352016-05-13 08:15:11 -07001145
deadbeef293e9262017-01-11 12:28:30 -08001146 // The simplest (and most future-compatible) way to tell if the config was
1147 // modified in an invalid way is to copy each property we do support
1148 // modifying, then use operator==. There are far more properties we don't
1149 // support modifying than those we do, and more could be added.
1150 RTCConfiguration modified_config = configuration_;
1151 modified_config.servers = configuration.servers;
1152 modified_config.type = configuration.type;
1153 modified_config.ice_candidate_pool_size =
1154 configuration.ice_candidate_pool_size;
1155 modified_config.prune_turn_ports = configuration.prune_turn_ports;
skvladd1f5fda2017-02-03 16:54:05 -08001156 modified_config.ice_check_min_interval = configuration.ice_check_min_interval;
deadbeef293e9262017-01-11 12:28:30 -08001157 if (configuration != modified_config) {
1158 LOG(LS_ERROR) << "Modifying the configuration in an unsupported way.";
1159 return SafeSetError(RTCErrorType::INVALID_MODIFICATION, error);
1160 }
1161
1162 // Note that this isn't possible through chromium, since it's an unsigned
1163 // short in WebIDL.
1164 if (configuration.ice_candidate_pool_size < 0 ||
1165 configuration.ice_candidate_pool_size > UINT16_MAX) {
1166 return SafeSetError(RTCErrorType::INVALID_RANGE, error);
1167 }
1168
1169 // Parse ICE servers before hopping to network thread.
1170 cricket::ServerAddresses stun_servers;
1171 std::vector<cricket::RelayServerConfig> turn_servers;
1172 RTCErrorType parse_error =
1173 ParseIceServers(configuration.servers, &stun_servers, &turn_servers);
1174 if (parse_error != RTCErrorType::NONE) {
1175 return SafeSetError(parse_error, error);
1176 }
1177
1178 // In theory this shouldn't fail.
1179 if (!network_thread()->Invoke<bool>(
1180 RTC_FROM_HERE,
1181 rtc::Bind(&PeerConnection::ReconfigurePortAllocator_n, this,
1182 stun_servers, turn_servers, modified_config.type,
1183 modified_config.ice_candidate_pool_size,
1184 modified_config.prune_turn_ports))) {
1185 LOG(LS_ERROR) << "Failed to apply configuration to PortAllocator.";
1186 return SafeSetError(RTCErrorType::INTERNAL_ERROR, error);
1187 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07001188
deadbeefd1a38b52016-12-10 13:15:33 -08001189 // As described in JSEP, calling setConfiguration with new ICE servers or
1190 // candidate policy must set a "needs-ice-restart" bit so that the next offer
1191 // triggers an ICE restart which will pick up the changes.
deadbeef293e9262017-01-11 12:28:30 -08001192 if (modified_config.servers != configuration_.servers ||
1193 modified_config.type != configuration_.type ||
1194 modified_config.prune_turn_ports != configuration_.prune_turn_ports) {
deadbeefd1a38b52016-12-10 13:15:33 -08001195 session_->SetNeedsIceRestartFlag();
1196 }
skvladd1f5fda2017-02-03 16:54:05 -08001197
1198 if (modified_config.ice_check_min_interval !=
1199 configuration_.ice_check_min_interval) {
1200 session_->SetIceConfig(session_->ParseIceConfig(modified_config));
1201 }
1202
deadbeef293e9262017-01-11 12:28:30 -08001203 configuration_ = modified_config;
1204 return SafeSetError(RTCErrorType::NONE, error);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001205}
1206
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001207bool PeerConnection::AddIceCandidate(
1208 const IceCandidateInterface* ice_candidate) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001209 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate");
zhihuang29ff8442016-07-27 11:07:25 -07001210 if (IsClosed()) {
1211 return false;
1212 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213 return session_->ProcessIceMessage(ice_candidate);
1214}
1215
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001216bool PeerConnection::RemoveIceCandidates(
1217 const std::vector<cricket::Candidate>& candidates) {
1218 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
1219 return session_->RemoveRemoteIceCandidates(candidates);
1220}
1221
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001222void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
Peter Boström1a9d6152015-12-08 22:15:17 +01001223 TRACE_EVENT0("webrtc", "PeerConnection::RegisterUmaObserver");
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001224 uma_observer_ = observer;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001225
1226 if (session_) {
1227 session_->set_metrics_observer(uma_observer_);
1228 }
1229
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001230 // Send information about IPv4/IPv6 status.
deadbeef293e9262017-01-11 12:28:30 -08001231 if (uma_observer_) {
Honghai Zhangd93f50c2016-10-05 11:47:22 -07001232 port_allocator_->SetMetricsObserver(uma_observer_);
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001233 if (port_allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6) {
Guo-wei Shiehdfbe6792015-09-03 17:12:07 -07001234 uma_observer_->IncrementEnumCounter(
1235 kEnumCounterAddressFamily, kPeerConnection_IPv6,
1236 kPeerConnectionAddressFamilyCounter_Max);
mallinath@webrtc.orgb445f262014-05-23 22:19:37 +00001237 } else {
Guo-wei Shiehdfbe6792015-09-03 17:12:07 -07001238 uma_observer_->IncrementEnumCounter(
1239 kEnumCounterAddressFamily, kPeerConnection_IPv4,
1240 kPeerConnectionAddressFamilyCounter_Max);
mallinath@webrtc.orgd37bcfa2014-05-12 23:10:18 +00001241 }
1242 }
buildbot@webrtc.org1567b8c2014-05-08 19:54:16 +00001243}
1244
ivoc14d5dbe2016-07-04 07:06:55 -07001245bool PeerConnection::StartRtcEventLog(rtc::PlatformFile file,
1246 int64_t max_size_bytes) {
1247 return factory_->worker_thread()->Invoke<bool>(
1248 RTC_FROM_HERE, rtc::Bind(&PeerConnection::StartRtcEventLog_w, this, file,
1249 max_size_bytes));
1250}
1251
1252void PeerConnection::StopRtcEventLog() {
1253 factory_->worker_thread()->Invoke<void>(
1254 RTC_FROM_HERE, rtc::Bind(&PeerConnection::StopRtcEventLog_w, this));
1255}
1256
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257const SessionDescriptionInterface* PeerConnection::local_description() const {
1258 return session_->local_description();
1259}
1260
1261const SessionDescriptionInterface* PeerConnection::remote_description() const {
1262 return session_->remote_description();
1263}
1264
deadbeeffe4a8a42016-12-20 17:56:17 -08001265const SessionDescriptionInterface* PeerConnection::current_local_description()
1266 const {
1267 return session_->current_local_description();
1268}
1269
1270const SessionDescriptionInterface* PeerConnection::current_remote_description()
1271 const {
1272 return session_->current_remote_description();
1273}
1274
1275const SessionDescriptionInterface* PeerConnection::pending_local_description()
1276 const {
1277 return session_->pending_local_description();
1278}
1279
1280const SessionDescriptionInterface* PeerConnection::pending_remote_description()
1281 const {
1282 return session_->pending_remote_description();
1283}
1284
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001285void PeerConnection::Close() {
Peter Boström1a9d6152015-12-08 22:15:17 +01001286 TRACE_EVENT0("webrtc", "PeerConnection::Close");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287 // Update stats here so that we have the most recent stats for tracks and
1288 // streams before the channels are closed.
tommi@webrtc.org03505bc2014-07-14 20:15:26 +00001289 stats_->UpdateStats(kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290
deadbeefd59daf82015-10-14 15:02:44 -07001291 session_->Close();
zhihuang77985012017-02-07 15:45:16 -08001292 event_log_.reset();
deadbeef42a42632017-03-10 15:18:00 -08001293 network_thread()->Invoke<void>(
1294 RTC_FROM_HERE,
1295 rtc::Bind(&cricket::PortAllocator::DiscardCandidatePool,
1296 port_allocator_.get()));
nisseeaabdf62017-05-05 02:23:02 -07001297
1298 factory_->worker_thread()->Invoke<void>(RTC_FROM_HERE,
1299 [this] { call_.reset(); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001300}
1301
deadbeefd59daf82015-10-14 15:02:44 -07001302void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
1303 WebRtcSession::State state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 switch (state) {
deadbeefd59daf82015-10-14 15:02:44 -07001305 case WebRtcSession::STATE_INIT:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 ChangeSignalingState(PeerConnectionInterface::kStable);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001307 break;
deadbeefd59daf82015-10-14 15:02:44 -07001308 case WebRtcSession::STATE_SENTOFFER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
1310 break;
deadbeefd59daf82015-10-14 15:02:44 -07001311 case WebRtcSession::STATE_SENTPRANSWER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001312 ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
1313 break;
deadbeefd59daf82015-10-14 15:02:44 -07001314 case WebRtcSession::STATE_RECEIVEDOFFER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001315 ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
1316 break;
deadbeefd59daf82015-10-14 15:02:44 -07001317 case WebRtcSession::STATE_RECEIVEDPRANSWER:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001318 ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
1319 break;
deadbeefd59daf82015-10-14 15:02:44 -07001320 case WebRtcSession::STATE_INPROGRESS:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001321 ChangeSignalingState(PeerConnectionInterface::kStable);
1322 break;
deadbeefd59daf82015-10-14 15:02:44 -07001323 case WebRtcSession::STATE_CLOSED:
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001324 ChangeSignalingState(PeerConnectionInterface::kClosed);
1325 break;
1326 default:
1327 break;
1328 }
1329}
1330
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001331void PeerConnection::OnMessage(rtc::Message* msg) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001332 switch (msg->message_id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001333 case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
1334 SetSessionDescriptionMsg* param =
1335 static_cast<SetSessionDescriptionMsg*>(msg->pdata);
1336 param->observer->OnSuccess();
1337 delete param;
1338 break;
1339 }
1340 case MSG_SET_SESSIONDESCRIPTION_FAILED: {
1341 SetSessionDescriptionMsg* param =
1342 static_cast<SetSessionDescriptionMsg*>(msg->pdata);
1343 param->observer->OnFailure(param->error);
1344 delete param;
1345 break;
1346 }
deadbeefab9b2d12015-10-14 11:33:11 -07001347 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
1348 CreateSessionDescriptionMsg* param =
1349 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
1350 param->observer->OnFailure(param->error);
1351 delete param;
1352 break;
1353 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001354 case MSG_GETSTATS: {
1355 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata);
nissee8abe3e2017-01-18 05:00:34 -08001356 StatsReports reports;
1357 stats_->GetStats(param->track, &reports);
1358 param->observer->OnComplete(reports);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001359 delete param;
1360 break;
1361 }
deadbeefbd292462015-12-14 18:15:29 -08001362 case MSG_FREE_DATACHANNELS: {
1363 sctp_data_channels_to_free_.clear();
1364 break;
1365 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366 default:
nisseeb4ca4e2017-01-12 02:24:27 -08001367 RTC_NOTREACHED() << "Not implemented";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001368 break;
1369 }
1370}
1371
deadbeefab9b2d12015-10-14 11:33:11 -07001372void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream,
perkjd61bf802016-03-24 03:16:19 -07001373 const std::string& track_id,
deadbeefab9b2d12015-10-14 11:33:11 -07001374 uint32_t ssrc) {
zhihuang81c3a032016-11-17 12:06:24 -08001375 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
1376 receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
deadbeefe814a0d2017-02-25 18:15:09 -08001377 signaling_thread(),
1378 new AudioRtpReceiver(track_id, ssrc, session_->voice_channel()));
1379 stream->AddTrack(
1380 static_cast<AudioTrackInterface*>(receiver->internal()->track().get()));
zhihuang81c3a032016-11-17 12:06:24 -08001381 receivers_.push_back(receiver);
1382 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
1383 streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
1384 observer_->OnAddTrack(receiver, streams);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001385}
1386
deadbeefab9b2d12015-10-14 11:33:11 -07001387void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream,
perkjf0dcfe22016-03-10 18:32:00 +01001388 const std::string& track_id,
deadbeefab9b2d12015-10-14 11:33:11 -07001389 uint32_t ssrc) {
zhihuang81c3a032016-11-17 12:06:24 -08001390 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
1391 receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
deadbeefa601f5c2016-06-06 14:27:39 -07001392 signaling_thread(),
deadbeefe814a0d2017-02-25 18:15:09 -08001393 new VideoRtpReceiver(track_id, factory_->worker_thread(), ssrc,
1394 session_->video_channel()));
1395 stream->AddTrack(
1396 static_cast<VideoTrackInterface*>(receiver->internal()->track().get()));
zhihuang81c3a032016-11-17 12:06:24 -08001397 receivers_.push_back(receiver);
1398 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
1399 streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
1400 observer_->OnAddTrack(receiver, streams);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001401}
1402
deadbeef70ab1a12015-09-28 16:53:55 -07001403// TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
1404// description.
perkjd61bf802016-03-24 03:16:19 -07001405void PeerConnection::DestroyReceiver(const std::string& track_id) {
1406 auto it = FindReceiverForTrack(track_id);
deadbeef70ab1a12015-09-28 16:53:55 -07001407 if (it == receivers_.end()) {
perkjd61bf802016-03-24 03:16:19 -07001408 LOG(LS_WARNING) << "RtpReceiver for track with id " << track_id
deadbeef70ab1a12015-09-28 16:53:55 -07001409 << " doesn't exist.";
1410 } else {
deadbeefa601f5c2016-06-06 14:27:39 -07001411 (*it)->internal()->Stop();
deadbeef70ab1a12015-09-28 16:53:55 -07001412 receivers_.erase(it);
1413 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414}
1415
zstein6dfd53a2017-03-06 13:49:03 -08001416void PeerConnection::OnIceConnectionStateChange(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001417 PeerConnectionInterface::IceConnectionState new_state) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001418 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -07001419 // After transitioning to "closed", ignore any additional states from
1420 // WebRtcSession (such as "disconnected").
deadbeefab9b2d12015-10-14 11:33:11 -07001421 if (IsClosed()) {
deadbeefcbecd352015-09-23 11:50:27 -07001422 return;
1423 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001424 ice_connection_state_ = new_state;
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001425 observer_->OnIceConnectionChange(ice_connection_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001426}
1427
1428void PeerConnection::OnIceGatheringChange(
1429 PeerConnectionInterface::IceGatheringState new_state) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001430 RTC_DCHECK(signaling_thread()->IsCurrent());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431 if (IsClosed()) {
1432 return;
1433 }
1434 ice_gathering_state_ = new_state;
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001435 observer_->OnIceGatheringChange(ice_gathering_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001436}
1437
jbauch81bf7b02017-03-25 08:31:12 -07001438void PeerConnection::OnIceCandidate(
1439 std::unique_ptr<IceCandidateInterface> candidate) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001440 RTC_DCHECK(signaling_thread()->IsCurrent());
zhihuang29ff8442016-07-27 11:07:25 -07001441 if (IsClosed()) {
1442 return;
1443 }
jbauch81bf7b02017-03-25 08:31:12 -07001444 observer_->OnIceCandidate(candidate.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445}
1446
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001447void PeerConnection::OnIceCandidatesRemoved(
1448 const std::vector<cricket::Candidate>& candidates) {
1449 RTC_DCHECK(signaling_thread()->IsCurrent());
zhihuang29ff8442016-07-27 11:07:25 -07001450 if (IsClosed()) {
1451 return;
1452 }
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001453 observer_->OnIceCandidatesRemoved(candidates);
1454}
1455
Peter Thatcher54360512015-07-08 11:08:35 -07001456void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
deadbeef0a6c4ca2015-10-06 11:38:28 -07001457 RTC_DCHECK(signaling_thread()->IsCurrent());
zhihuang29ff8442016-07-27 11:07:25 -07001458 if (IsClosed()) {
1459 return;
1460 }
Peter Thatcher54360512015-07-08 11:08:35 -07001461 observer_->OnIceConnectionReceivingChange(receiving);
1462}
1463
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001464void PeerConnection::ChangeSignalingState(
1465 PeerConnectionInterface::SignalingState signaling_state) {
1466 signaling_state_ = signaling_state;
1467 if (signaling_state == kClosed) {
1468 ice_connection_state_ = kIceConnectionClosed;
1469 observer_->OnIceConnectionChange(ice_connection_state_);
1470 if (ice_gathering_state_ != kIceGatheringComplete) {
1471 ice_gathering_state_ = kIceGatheringComplete;
1472 observer_->OnIceGatheringChange(ice_gathering_state_);
1473 }
1474 }
1475 observer_->OnSignalingChange(signaling_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001476}
1477
deadbeefeb459812015-12-15 19:24:43 -08001478void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
1479 MediaStreamInterface* stream) {
zhihuang29ff8442016-07-27 11:07:25 -07001480 if (IsClosed()) {
1481 return;
1482 }
deadbeefeb459812015-12-15 19:24:43 -08001483 auto sender = FindSenderForTrack(track);
1484 if (sender != senders_.end()) {
1485 // We already have a sender for this track, so just change the stream_id
1486 // so that it's correct in the next call to CreateOffer.
deadbeefa601f5c2016-06-06 14:27:39 -07001487 (*sender)->internal()->set_stream_id(stream->label());
deadbeefeb459812015-12-15 19:24:43 -08001488 return;
1489 }
1490
1491 // Normal case; we've never seen this track before.
deadbeefa601f5c2016-06-06 14:27:39 -07001492 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender =
1493 RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -07001494 signaling_thread(),
1495 new AudioRtpSender(track, stream->label(), session_->voice_channel(),
1496 stats_.get()));
deadbeefeb459812015-12-15 19:24:43 -08001497 senders_.push_back(new_sender);
1498 // If the sender has already been configured in SDP, we call SetSsrc,
1499 // which will connect the sender to the underlying transport. This can
1500 // occur if a local session description that contains the ID of the sender
1501 // is set before AddStream is called. It can also occur if the local
1502 // session description is not changed and RemoveStream is called, and
1503 // later AddStream is called again with the same stream.
1504 const TrackInfo* track_info =
1505 FindTrackInfo(local_audio_tracks_, stream->label(), track->id());
1506 if (track_info) {
deadbeefa601f5c2016-06-06 14:27:39 -07001507 new_sender->internal()->SetSsrc(track_info->ssrc);
deadbeefeb459812015-12-15 19:24:43 -08001508 }
1509}
1510
1511// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
1512// indefinitely, when we have unified plan SDP.
1513void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
1514 MediaStreamInterface* stream) {
zhihuang29ff8442016-07-27 11:07:25 -07001515 if (IsClosed()) {
1516 return;
1517 }
deadbeefeb459812015-12-15 19:24:43 -08001518 auto sender = FindSenderForTrack(track);
1519 if (sender == senders_.end()) {
1520 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1521 << " doesn't exist.";
1522 return;
1523 }
deadbeefa601f5c2016-06-06 14:27:39 -07001524 (*sender)->internal()->Stop();
deadbeefeb459812015-12-15 19:24:43 -08001525 senders_.erase(sender);
1526}
1527
1528void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
1529 MediaStreamInterface* stream) {
zhihuang29ff8442016-07-27 11:07:25 -07001530 if (IsClosed()) {
1531 return;
1532 }
deadbeefeb459812015-12-15 19:24:43 -08001533 auto sender = FindSenderForTrack(track);
1534 if (sender != senders_.end()) {
1535 // We already have a sender for this track, so just change the stream_id
1536 // so that it's correct in the next call to CreateOffer.
deadbeefa601f5c2016-06-06 14:27:39 -07001537 (*sender)->internal()->set_stream_id(stream->label());
deadbeefeb459812015-12-15 19:24:43 -08001538 return;
1539 }
1540
1541 // Normal case; we've never seen this track before.
deadbeefa601f5c2016-06-06 14:27:39 -07001542 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender =
1543 RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -07001544 signaling_thread(), new VideoRtpSender(track, stream->label(),
1545 session_->video_channel()));
deadbeefeb459812015-12-15 19:24:43 -08001546 senders_.push_back(new_sender);
1547 const TrackInfo* track_info =
1548 FindTrackInfo(local_video_tracks_, stream->label(), track->id());
1549 if (track_info) {
deadbeefa601f5c2016-06-06 14:27:39 -07001550 new_sender->internal()->SetSsrc(track_info->ssrc);
deadbeefeb459812015-12-15 19:24:43 -08001551 }
1552}
1553
1554void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
1555 MediaStreamInterface* stream) {
zhihuang29ff8442016-07-27 11:07:25 -07001556 if (IsClosed()) {
1557 return;
1558 }
deadbeefeb459812015-12-15 19:24:43 -08001559 auto sender = FindSenderForTrack(track);
1560 if (sender == senders_.end()) {
1561 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1562 << " doesn't exist.";
1563 return;
1564 }
deadbeefa601f5c2016-06-06 14:27:39 -07001565 (*sender)->internal()->Stop();
deadbeefeb459812015-12-15 19:24:43 -08001566 senders_.erase(sender);
1567}
1568
deadbeefab9b2d12015-10-14 11:33:11 -07001569void PeerConnection::PostSetSessionDescriptionFailure(
1570 SetSessionDescriptionObserver* observer,
1571 const std::string& error) {
1572 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer);
1573 msg->error = error;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001574 signaling_thread()->Post(RTC_FROM_HERE, this,
1575 MSG_SET_SESSIONDESCRIPTION_FAILED, msg);
deadbeefab9b2d12015-10-14 11:33:11 -07001576}
1577
1578void PeerConnection::PostCreateSessionDescriptionFailure(
1579 CreateSessionDescriptionObserver* observer,
1580 const std::string& error) {
1581 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
1582 msg->error = error;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07001583 signaling_thread()->Post(RTC_FROM_HERE, this,
1584 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
deadbeefab9b2d12015-10-14 11:33:11 -07001585}
1586
1587bool PeerConnection::GetOptionsForOffer(
1588 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
1589 cricket::MediaSessionOptions* session_options) {
deadbeef0ed85b22016-02-23 17:24:52 -08001590 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
1591 // ContentInfos.
1592 if (session_->local_description()) {
1593 for (const cricket::ContentInfo& content :
1594 session_->local_description()->description()->contents()) {
1595 session_options->transport_options[content.name] =
1596 cricket::TransportOptions();
1597 }
1598 }
deadbeef46c73892016-11-16 19:42:04 -08001599 session_options->enable_ice_renomination =
1600 configuration_.enable_ice_renomination;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07001601
htaaac2dea2016-03-10 13:35:55 -08001602 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) {
deadbeefab9b2d12015-10-14 11:33:11 -07001603 return false;
1604 }
1605
deadbeeffac06552015-11-25 11:26:01 -08001606 AddSendStreams(session_options, senders_, rtp_data_channels_);
deadbeefc80741f2015-10-22 13:14:45 -07001607 // Offer to receive audio/video if the constraint is not set and there are
1608 // send streams, or we're currently receiving.
1609 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) {
1610 session_options->recv_audio =
1611 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) ||
1612 !remote_audio_tracks_.empty();
1613 }
1614 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) {
1615 session_options->recv_video =
1616 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) ||
1617 !remote_video_tracks_.empty();
1618 }
deadbeefc80741f2015-10-22 13:14:45 -07001619
zhihuang9763d562016-08-05 11:14:50 -07001620 // Intentionally unset the data channel type for RTP data channel with the
1621 // second condition. Otherwise the RTP data channels would be successfully
1622 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail
1623 // when building with chromium. We want to leave RTP data channels broken, so
1624 // people won't try to use them.
1625 if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) {
1626 session_options->data_channel_type = session_->data_channel_type();
deadbeefab9b2d12015-10-14 11:33:11 -07001627 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001628
zhihuangaf388472016-11-02 16:49:48 -07001629 session_options->bundle_enabled =
1630 session_options->bundle_enabled &&
1631 (session_options->has_audio() || session_options->has_video() ||
1632 session_options->has_data());
1633
zhihuang8f65cdf2016-05-06 18:40:30 -07001634 session_options->rtcp_cname = rtcp_cname_;
jbauchcb560652016-08-04 05:20:32 -07001635 session_options->crypto_options = factory_->options().crypto_options;
deadbeefab9b2d12015-10-14 11:33:11 -07001636 return true;
1637}
1638
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07001639void PeerConnection::InitializeOptionsForAnswer(
1640 cricket::MediaSessionOptions* session_options) {
1641 session_options->recv_audio = false;
1642 session_options->recv_video = false;
deadbeef46c73892016-11-16 19:42:04 -08001643 session_options->enable_ice_renomination =
1644 configuration_.enable_ice_renomination;
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07001645}
1646
htaa2a49d92016-03-04 02:51:39 -08001647void PeerConnection::FinishOptionsForAnswer(
deadbeefab9b2d12015-10-14 11:33:11 -07001648 cricket::MediaSessionOptions* session_options) {
deadbeef0ed85b22016-02-23 17:24:52 -08001649 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
1650 // ContentInfos.
1651 if (session_->remote_description()) {
1652 // Initialize the transport_options map.
1653 for (const cricket::ContentInfo& content :
1654 session_->remote_description()->description()->contents()) {
1655 session_options->transport_options[content.name] =
1656 cricket::TransportOptions();
1657 }
1658 }
deadbeeffac06552015-11-25 11:26:01 -08001659 AddSendStreams(session_options, senders_, rtp_data_channels_);
deadbeefab9b2d12015-10-14 11:33:11 -07001660 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
1661 // are not signaled in the SDP so does not go through that path and must be
1662 // handled here.
zhihuang9763d562016-08-05 11:14:50 -07001663 // Intentionally unset the data channel type for RTP data channel. Otherwise
1664 // the RTP data channels would be successfully negotiated by default and the
1665 // unit tests in WebRtcDataBrowserTest will fail when building with chromium.
1666 // We want to leave RTP data channels broken, so people won't try to use them.
1667 if (session_->data_channel_type() != cricket::DCT_RTP) {
1668 session_options->data_channel_type = session_->data_channel_type();
deadbeef907abe42016-08-04 12:22:18 -07001669 }
zhihuangaf388472016-11-02 16:49:48 -07001670 session_options->bundle_enabled =
1671 session_options->bundle_enabled &&
1672 (session_options->has_audio() || session_options->has_video() ||
1673 session_options->has_data());
1674
jbauchcb560652016-08-04 05:20:32 -07001675 session_options->crypto_options = factory_->options().crypto_options;
htaa2a49d92016-03-04 02:51:39 -08001676}
1677
1678bool PeerConnection::GetOptionsForAnswer(
1679 const MediaConstraintsInterface* constraints,
1680 cricket::MediaSessionOptions* session_options) {
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07001681 InitializeOptionsForAnswer(session_options);
htaa2a49d92016-03-04 02:51:39 -08001682 if (!ParseConstraintsForAnswer(constraints, session_options)) {
1683 return false;
1684 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001685 session_options->rtcp_cname = rtcp_cname_;
1686
htaa2a49d92016-03-04 02:51:39 -08001687 FinishOptionsForAnswer(session_options);
1688 return true;
1689}
1690
1691bool PeerConnection::GetOptionsForAnswer(
1692 const RTCOfferAnswerOptions& options,
1693 cricket::MediaSessionOptions* session_options) {
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07001694 InitializeOptionsForAnswer(session_options);
htaaac2dea2016-03-10 13:35:55 -08001695 if (!ExtractMediaSessionOptions(options, false, session_options)) {
htaa2a49d92016-03-04 02:51:39 -08001696 return false;
1697 }
zhihuang8f65cdf2016-05-06 18:40:30 -07001698 session_options->rtcp_cname = rtcp_cname_;
1699
htaa2a49d92016-03-04 02:51:39 -08001700 FinishOptionsForAnswer(session_options);
deadbeefab9b2d12015-10-14 11:33:11 -07001701 return true;
1702}
1703
deadbeeffaac4972015-11-12 15:33:07 -08001704void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
1705 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type);
deadbeefbda7e0b2015-12-08 17:13:40 -08001706 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false,
1707 media_type, nullptr);
deadbeeffaac4972015-11-12 15:33:07 -08001708}
1709
deadbeefab9b2d12015-10-14 11:33:11 -07001710void PeerConnection::UpdateRemoteStreamsList(
1711 const cricket::StreamParamsVec& streams,
deadbeefbda7e0b2015-12-08 17:13:40 -08001712 bool default_track_needed,
deadbeefab9b2d12015-10-14 11:33:11 -07001713 cricket::MediaType media_type,
1714 StreamCollection* new_streams) {
1715 TrackInfos* current_tracks = GetRemoteTracks(media_type);
1716
1717 // Find removed tracks. I.e., tracks where the track id or ssrc don't match
deadbeeffac06552015-11-25 11:26:01 -08001718 // the new StreamParam.
deadbeefab9b2d12015-10-14 11:33:11 -07001719 auto track_it = current_tracks->begin();
1720 while (track_it != current_tracks->end()) {
1721 const TrackInfo& info = *track_it;
1722 const cricket::StreamParams* params =
1723 cricket::GetStreamBySsrc(streams, info.ssrc);
deadbeefbda7e0b2015-12-08 17:13:40 -08001724 bool track_exists = params && params->id == info.track_id;
1725 // If this is a default track, and we still need it, don't remove it.
1726 if ((info.stream_label == kDefaultStreamLabel && default_track_needed) ||
1727 track_exists) {
1728 ++track_it;
1729 } else {
deadbeefab9b2d12015-10-14 11:33:11 -07001730 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type);
1731 track_it = current_tracks->erase(track_it);
deadbeefab9b2d12015-10-14 11:33:11 -07001732 }
1733 }
1734
1735 // Find new and active tracks.
1736 for (const cricket::StreamParams& params : streams) {
1737 // The sync_label is the MediaStream label and the |stream.id| is the
1738 // track id.
1739 const std::string& stream_label = params.sync_label;
1740 const std::string& track_id = params.id;
1741 uint32_t ssrc = params.first_ssrc();
1742
1743 rtc::scoped_refptr<MediaStreamInterface> stream =
1744 remote_streams_->find(stream_label);
1745 if (!stream) {
1746 // This is a new MediaStream. Create a new remote MediaStream.
perkjd61bf802016-03-24 03:16:19 -07001747 stream = MediaStreamProxy::Create(rtc::Thread::Current(),
1748 MediaStream::Create(stream_label));
deadbeefab9b2d12015-10-14 11:33:11 -07001749 remote_streams_->AddStream(stream);
1750 new_streams->AddStream(stream);
1751 }
1752
1753 const TrackInfo* track_info =
1754 FindTrackInfo(*current_tracks, stream_label, track_id);
1755 if (!track_info) {
1756 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc));
1757 OnRemoteTrackSeen(stream_label, track_id, ssrc, media_type);
1758 }
1759 }
deadbeefbda7e0b2015-12-08 17:13:40 -08001760
1761 // Add default track if necessary.
1762 if (default_track_needed) {
1763 rtc::scoped_refptr<MediaStreamInterface> default_stream =
1764 remote_streams_->find(kDefaultStreamLabel);
1765 if (!default_stream) {
1766 // Create the new default MediaStream.
perkjd61bf802016-03-24 03:16:19 -07001767 default_stream = MediaStreamProxy::Create(
1768 rtc::Thread::Current(), MediaStream::Create(kDefaultStreamLabel));
deadbeefbda7e0b2015-12-08 17:13:40 -08001769 remote_streams_->AddStream(default_stream);
1770 new_streams->AddStream(default_stream);
1771 }
1772 std::string default_track_id = (media_type == cricket::MEDIA_TYPE_AUDIO)
1773 ? kDefaultAudioTrackLabel
1774 : kDefaultVideoTrackLabel;
1775 const TrackInfo* default_track_info =
1776 FindTrackInfo(*current_tracks, kDefaultStreamLabel, default_track_id);
1777 if (!default_track_info) {
1778 current_tracks->push_back(
1779 TrackInfo(kDefaultStreamLabel, default_track_id, 0));
1780 OnRemoteTrackSeen(kDefaultStreamLabel, default_track_id, 0, media_type);
1781 }
1782 }
deadbeefab9b2d12015-10-14 11:33:11 -07001783}
1784
1785void PeerConnection::OnRemoteTrackSeen(const std::string& stream_label,
1786 const std::string& track_id,
1787 uint32_t ssrc,
1788 cricket::MediaType media_type) {
1789 MediaStreamInterface* stream = remote_streams_->find(stream_label);
1790
1791 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
perkjd61bf802016-03-24 03:16:19 -07001792 CreateAudioReceiver(stream, track_id, ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001793 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
perkjf0dcfe22016-03-10 18:32:00 +01001794 CreateVideoReceiver(stream, track_id, ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001795 } else {
nisseeb4ca4e2017-01-12 02:24:27 -08001796 RTC_NOTREACHED() << "Invalid media type";
deadbeefab9b2d12015-10-14 11:33:11 -07001797 }
1798}
1799
1800void PeerConnection::OnRemoteTrackRemoved(const std::string& stream_label,
1801 const std::string& track_id,
1802 cricket::MediaType media_type) {
1803 MediaStreamInterface* stream = remote_streams_->find(stream_label);
1804
1805 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
perkjd61bf802016-03-24 03:16:19 -07001806 // When the MediaEngine audio channel is destroyed, the RemoteAudioSource
1807 // will be notified which will end the AudioRtpReceiver::track().
1808 DestroyReceiver(track_id);
deadbeefab9b2d12015-10-14 11:33:11 -07001809 rtc::scoped_refptr<AudioTrackInterface> audio_track =
1810 stream->FindAudioTrack(track_id);
1811 if (audio_track) {
deadbeefab9b2d12015-10-14 11:33:11 -07001812 stream->RemoveTrack(audio_track);
deadbeefab9b2d12015-10-14 11:33:11 -07001813 }
1814 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
perkjd61bf802016-03-24 03:16:19 -07001815 // Stopping or destroying a VideoRtpReceiver will end the
1816 // VideoRtpReceiver::track().
1817 DestroyReceiver(track_id);
deadbeefab9b2d12015-10-14 11:33:11 -07001818 rtc::scoped_refptr<VideoTrackInterface> video_track =
1819 stream->FindVideoTrack(track_id);
1820 if (video_track) {
perkjd61bf802016-03-24 03:16:19 -07001821 // There's no guarantee the track is still available, e.g. the track may
1822 // have been removed from the stream by an application.
deadbeefab9b2d12015-10-14 11:33:11 -07001823 stream->RemoveTrack(video_track);
deadbeefab9b2d12015-10-14 11:33:11 -07001824 }
1825 } else {
nisseede5da42017-01-12 05:15:36 -08001826 RTC_NOTREACHED() << "Invalid media type";
deadbeefab9b2d12015-10-14 11:33:11 -07001827 }
1828}
1829
1830void PeerConnection::UpdateEndedRemoteMediaStreams() {
1831 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_to_remove;
1832 for (size_t i = 0; i < remote_streams_->count(); ++i) {
1833 MediaStreamInterface* stream = remote_streams_->at(i);
1834 if (stream->GetAudioTracks().empty() && stream->GetVideoTracks().empty()) {
1835 streams_to_remove.push_back(stream);
1836 }
1837 }
1838
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001839 for (auto& stream : streams_to_remove) {
deadbeefab9b2d12015-10-14 11:33:11 -07001840 remote_streams_->RemoveStream(stream);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07001841 observer_->OnRemoveStream(std::move(stream));
deadbeefab9b2d12015-10-14 11:33:11 -07001842 }
1843}
1844
deadbeefab9b2d12015-10-14 11:33:11 -07001845void PeerConnection::UpdateLocalTracks(
1846 const std::vector<cricket::StreamParams>& streams,
1847 cricket::MediaType media_type) {
1848 TrackInfos* current_tracks = GetLocalTracks(media_type);
1849
1850 // Find removed tracks. I.e., tracks where the track id, stream label or ssrc
1851 // don't match the new StreamParam.
1852 TrackInfos::iterator track_it = current_tracks->begin();
1853 while (track_it != current_tracks->end()) {
1854 const TrackInfo& info = *track_it;
1855 const cricket::StreamParams* params =
1856 cricket::GetStreamBySsrc(streams, info.ssrc);
1857 if (!params || params->id != info.track_id ||
1858 params->sync_label != info.stream_label) {
1859 OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc,
1860 media_type);
1861 track_it = current_tracks->erase(track_it);
1862 } else {
1863 ++track_it;
1864 }
1865 }
1866
1867 // Find new and active tracks.
1868 for (const cricket::StreamParams& params : streams) {
1869 // The sync_label is the MediaStream label and the |stream.id| is the
1870 // track id.
1871 const std::string& stream_label = params.sync_label;
1872 const std::string& track_id = params.id;
1873 uint32_t ssrc = params.first_ssrc();
1874 const TrackInfo* track_info =
1875 FindTrackInfo(*current_tracks, stream_label, track_id);
1876 if (!track_info) {
1877 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc));
1878 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type);
1879 }
1880 }
1881}
1882
1883void PeerConnection::OnLocalTrackSeen(const std::string& stream_label,
1884 const std::string& track_id,
1885 uint32_t ssrc,
1886 cricket::MediaType media_type) {
deadbeefa601f5c2016-06-06 14:27:39 -07001887 RtpSenderInternal* sender = FindSenderById(track_id);
deadbeeffac06552015-11-25 11:26:01 -08001888 if (!sender) {
1889 LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id
1890 << " has been configured in the local description.";
deadbeefab9b2d12015-10-14 11:33:11 -07001891 return;
1892 }
1893
deadbeeffac06552015-11-25 11:26:01 -08001894 if (sender->media_type() != media_type) {
1895 LOG(LS_WARNING) << "An RtpSender has been configured in the local"
1896 << " description with an unexpected media type.";
1897 return;
deadbeefab9b2d12015-10-14 11:33:11 -07001898 }
deadbeeffac06552015-11-25 11:26:01 -08001899
1900 sender->set_stream_id(stream_label);
1901 sender->SetSsrc(ssrc);
deadbeefab9b2d12015-10-14 11:33:11 -07001902}
1903
1904void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label,
1905 const std::string& track_id,
1906 uint32_t ssrc,
1907 cricket::MediaType media_type) {
deadbeefa601f5c2016-06-06 14:27:39 -07001908 RtpSenderInternal* sender = FindSenderById(track_id);
deadbeeffac06552015-11-25 11:26:01 -08001909 if (!sender) {
1910 // This is the normal case. I.e., RemoveStream has been called and the
deadbeefab9b2d12015-10-14 11:33:11 -07001911 // SessionDescriptions has been renegotiated.
1912 return;
1913 }
deadbeeffac06552015-11-25 11:26:01 -08001914
1915 // A sender has been removed from the SessionDescription but it's still
1916 // associated with the PeerConnection. This only occurs if the SDP doesn't
1917 // match with the calls to CreateSender, AddStream and RemoveStream.
1918 if (sender->media_type() != media_type) {
1919 LOG(LS_WARNING) << "An RtpSender has been configured in the local"
1920 << " description with an unexpected media type.";
1921 return;
deadbeefab9b2d12015-10-14 11:33:11 -07001922 }
deadbeeffac06552015-11-25 11:26:01 -08001923
1924 sender->SetSsrc(0);
deadbeefab9b2d12015-10-14 11:33:11 -07001925}
1926
1927void PeerConnection::UpdateLocalRtpDataChannels(
1928 const cricket::StreamParamsVec& streams) {
1929 std::vector<std::string> existing_channels;
1930
1931 // Find new and active data channels.
1932 for (const cricket::StreamParams& params : streams) {
1933 // |it->sync_label| is actually the data channel label. The reason is that
1934 // we use the same naming of data channels as we do for
1935 // MediaStreams and Tracks.
1936 // For MediaStreams, the sync_label is the MediaStream label and the
1937 // track label is the same as |streamid|.
1938 const std::string& channel_label = params.sync_label;
1939 auto data_channel_it = rtp_data_channels_.find(channel_label);
nisse7ce109a2017-01-31 00:57:56 -08001940 if (data_channel_it == rtp_data_channels_.end()) {
1941 LOG(LS_ERROR) << "channel label not found";
deadbeefab9b2d12015-10-14 11:33:11 -07001942 continue;
1943 }
1944 // Set the SSRC the data channel should use for sending.
1945 data_channel_it->second->SetSendSsrc(params.first_ssrc());
1946 existing_channels.push_back(data_channel_it->first);
1947 }
1948
1949 UpdateClosingRtpDataChannels(existing_channels, true);
1950}
1951
1952void PeerConnection::UpdateRemoteRtpDataChannels(
1953 const cricket::StreamParamsVec& streams) {
1954 std::vector<std::string> existing_channels;
1955
1956 // Find new and active data channels.
1957 for (const cricket::StreamParams& params : streams) {
1958 // The data channel label is either the mslabel or the SSRC if the mslabel
1959 // does not exist. Ex a=ssrc:444330170 mslabel:test1.
1960 std::string label = params.sync_label.empty()
1961 ? rtc::ToString(params.first_ssrc())
1962 : params.sync_label;
1963 auto data_channel_it = rtp_data_channels_.find(label);
1964 if (data_channel_it == rtp_data_channels_.end()) {
1965 // This is a new data channel.
1966 CreateRemoteRtpDataChannel(label, params.first_ssrc());
1967 } else {
1968 data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
1969 }
1970 existing_channels.push_back(label);
1971 }
1972
1973 UpdateClosingRtpDataChannels(existing_channels, false);
1974}
1975
1976void PeerConnection::UpdateClosingRtpDataChannels(
1977 const std::vector<std::string>& active_channels,
1978 bool is_local_update) {
1979 auto it = rtp_data_channels_.begin();
1980 while (it != rtp_data_channels_.end()) {
1981 DataChannel* data_channel = it->second;
1982 if (std::find(active_channels.begin(), active_channels.end(),
1983 data_channel->label()) != active_channels.end()) {
1984 ++it;
1985 continue;
1986 }
1987
1988 if (is_local_update) {
1989 data_channel->SetSendSsrc(0);
1990 } else {
1991 data_channel->RemotePeerRequestClose();
1992 }
1993
1994 if (data_channel->state() == DataChannel::kClosed) {
1995 rtp_data_channels_.erase(it);
1996 it = rtp_data_channels_.begin();
1997 } else {
1998 ++it;
1999 }
2000 }
2001}
2002
2003void PeerConnection::CreateRemoteRtpDataChannel(const std::string& label,
2004 uint32_t remote_ssrc) {
2005 rtc::scoped_refptr<DataChannel> channel(
2006 InternalCreateDataChannel(label, nullptr));
2007 if (!channel.get()) {
2008 LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
2009 << "CreateDataChannel failed.";
2010 return;
2011 }
2012 channel->SetReceiveSsrc(remote_ssrc);
deadbeefa601f5c2016-06-06 14:27:39 -07002013 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
2014 DataChannelProxy::Create(signaling_thread(), channel);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07002015 observer_->OnDataChannel(std::move(proxy_channel));
deadbeefab9b2d12015-10-14 11:33:11 -07002016}
2017
2018rtc::scoped_refptr<DataChannel> PeerConnection::InternalCreateDataChannel(
2019 const std::string& label,
2020 const InternalDataChannelInit* config) {
2021 if (IsClosed()) {
2022 return nullptr;
2023 }
2024 if (session_->data_channel_type() == cricket::DCT_NONE) {
2025 LOG(LS_ERROR)
2026 << "InternalCreateDataChannel: Data is not supported in this call.";
2027 return nullptr;
2028 }
2029 InternalDataChannelInit new_config =
2030 config ? (*config) : InternalDataChannelInit();
2031 if (session_->data_channel_type() == cricket::DCT_SCTP) {
2032 if (new_config.id < 0) {
2033 rtc::SSLRole role;
deadbeef953c2ce2017-01-09 14:53:41 -08002034 if ((session_->GetSctpSslRole(&role)) &&
deadbeefab9b2d12015-10-14 11:33:11 -07002035 !sid_allocator_.AllocateSid(role, &new_config.id)) {
2036 LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel.";
2037 return nullptr;
2038 }
2039 } else if (!sid_allocator_.ReserveSid(new_config.id)) {
2040 LOG(LS_ERROR) << "Failed to create a SCTP data channel "
2041 << "because the id is already in use or out of range.";
2042 return nullptr;
2043 }
2044 }
2045
2046 rtc::scoped_refptr<DataChannel> channel(DataChannel::Create(
2047 session_.get(), session_->data_channel_type(), label, new_config));
2048 if (!channel) {
2049 sid_allocator_.ReleaseSid(new_config.id);
2050 return nullptr;
2051 }
2052
2053 if (channel->data_channel_type() == cricket::DCT_RTP) {
2054 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
2055 LOG(LS_ERROR) << "DataChannel with label " << channel->label()
2056 << " already exists.";
2057 return nullptr;
2058 }
2059 rtp_data_channels_[channel->label()] = channel;
2060 } else {
2061 RTC_DCHECK(channel->data_channel_type() == cricket::DCT_SCTP);
2062 sctp_data_channels_.push_back(channel);
2063 channel->SignalClosed.connect(this,
2064 &PeerConnection::OnSctpDataChannelClosed);
2065 }
2066
hbos82ebe022016-11-14 01:41:09 -08002067 SignalDataChannelCreated(channel.get());
deadbeefab9b2d12015-10-14 11:33:11 -07002068 return channel;
2069}
2070
2071bool PeerConnection::HasDataChannels() const {
zhihuang9763d562016-08-05 11:14:50 -07002072#ifdef HAVE_QUIC
2073 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty() ||
2074 (session_->quic_data_transport() &&
2075 session_->quic_data_transport()->HasDataChannels());
2076#else
deadbeefab9b2d12015-10-14 11:33:11 -07002077 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
zhihuang9763d562016-08-05 11:14:50 -07002078#endif // HAVE_QUIC
deadbeefab9b2d12015-10-14 11:33:11 -07002079}
2080
2081void PeerConnection::AllocateSctpSids(rtc::SSLRole role) {
2082 for (const auto& channel : sctp_data_channels_) {
2083 if (channel->id() < 0) {
2084 int sid;
2085 if (!sid_allocator_.AllocateSid(role, &sid)) {
2086 LOG(LS_ERROR) << "Failed to allocate SCTP sid.";
2087 continue;
2088 }
2089 channel->SetSctpSid(sid);
2090 }
2091 }
2092}
2093
2094void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) {
deadbeefbd292462015-12-14 18:15:29 -08002095 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefab9b2d12015-10-14 11:33:11 -07002096 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
2097 ++it) {
2098 if (it->get() == channel) {
2099 if (channel->id() >= 0) {
2100 sid_allocator_.ReleaseSid(channel->id());
2101 }
deadbeefbd292462015-12-14 18:15:29 -08002102 // Since this method is triggered by a signal from the DataChannel,
2103 // we can't free it directly here; we need to free it asynchronously.
2104 sctp_data_channels_to_free_.push_back(*it);
deadbeefab9b2d12015-10-14 11:33:11 -07002105 sctp_data_channels_.erase(it);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -07002106 signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FREE_DATACHANNELS,
2107 nullptr);
deadbeefab9b2d12015-10-14 11:33:11 -07002108 return;
2109 }
2110 }
2111}
2112
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -07002113void PeerConnection::OnVoiceChannelCreated() {
2114 SetChannelOnSendersAndReceivers<AudioRtpSender, AudioRtpReceiver>(
2115 session_->voice_channel(), senders_, receivers_,
2116 cricket::MEDIA_TYPE_AUDIO);
2117}
2118
deadbeefab9b2d12015-10-14 11:33:11 -07002119void PeerConnection::OnVoiceChannelDestroyed() {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -07002120 SetChannelOnSendersAndReceivers<AudioRtpSender, AudioRtpReceiver,
2121 cricket::VoiceChannel>(
2122 nullptr, senders_, receivers_, cricket::MEDIA_TYPE_AUDIO);
2123}
2124
2125void PeerConnection::OnVideoChannelCreated() {
2126 SetChannelOnSendersAndReceivers<VideoRtpSender, VideoRtpReceiver>(
2127 session_->video_channel(), senders_, receivers_,
2128 cricket::MEDIA_TYPE_VIDEO);
deadbeefab9b2d12015-10-14 11:33:11 -07002129}
2130
2131void PeerConnection::OnVideoChannelDestroyed() {
Taylor Brandstetterba29c6a2016-06-27 16:30:35 -07002132 SetChannelOnSendersAndReceivers<VideoRtpSender, VideoRtpReceiver,
2133 cricket::VideoChannel>(
2134 nullptr, senders_, receivers_, cricket::MEDIA_TYPE_VIDEO);
deadbeefab9b2d12015-10-14 11:33:11 -07002135}
2136
2137void PeerConnection::OnDataChannelCreated() {
2138 for (const auto& channel : sctp_data_channels_) {
2139 channel->OnTransportChannelCreated();
2140 }
2141}
2142
2143void PeerConnection::OnDataChannelDestroyed() {
2144 // Use a temporary copy of the RTP/SCTP DataChannel list because the
2145 // DataChannel may callback to us and try to modify the list.
2146 std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs;
2147 temp_rtp_dcs.swap(rtp_data_channels_);
2148 for (const auto& kv : temp_rtp_dcs) {
2149 kv.second->OnTransportChannelDestroyed();
2150 }
2151
2152 std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs;
2153 temp_sctp_dcs.swap(sctp_data_channels_);
2154 for (const auto& channel : temp_sctp_dcs) {
2155 channel->OnTransportChannelDestroyed();
2156 }
2157}
2158
2159void PeerConnection::OnDataChannelOpenMessage(
2160 const std::string& label,
2161 const InternalDataChannelInit& config) {
2162 rtc::scoped_refptr<DataChannel> channel(
2163 InternalCreateDataChannel(label, &config));
2164 if (!channel.get()) {
2165 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
2166 return;
2167 }
2168
deadbeefa601f5c2016-06-06 14:27:39 -07002169 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
2170 DataChannelProxy::Create(signaling_thread(), channel);
Taylor Brandstetter98cde262016-05-31 13:02:21 -07002171 observer_->OnDataChannel(std::move(proxy_channel));
deadbeefab9b2d12015-10-14 11:33:11 -07002172}
2173
deadbeefa601f5c2016-06-06 14:27:39 -07002174RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) {
2175 auto it = std::find_if(
2176 senders_.begin(), senders_.end(),
2177 [id](const rtc::scoped_refptr<
2178 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2179 return sender->id() == id;
2180 });
2181 return it != senders_.end() ? (*it)->internal() : nullptr;
deadbeeffac06552015-11-25 11:26:01 -08002182}
2183
deadbeefa601f5c2016-06-06 14:27:39 -07002184std::vector<
2185 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>::iterator
deadbeef70ab1a12015-09-28 16:53:55 -07002186PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) {
2187 return std::find_if(
2188 senders_.begin(), senders_.end(),
deadbeefa601f5c2016-06-06 14:27:39 -07002189 [track](const rtc::scoped_refptr<
2190 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
deadbeef70ab1a12015-09-28 16:53:55 -07002191 return sender->track() == track;
2192 });
2193}
2194
deadbeefa601f5c2016-06-06 14:27:39 -07002195std::vector<rtc::scoped_refptr<
2196 RtpReceiverProxyWithInternal<RtpReceiverInternal>>>::iterator
perkjd61bf802016-03-24 03:16:19 -07002197PeerConnection::FindReceiverForTrack(const std::string& track_id) {
deadbeef70ab1a12015-09-28 16:53:55 -07002198 return std::find_if(
2199 receivers_.begin(), receivers_.end(),
deadbeefa601f5c2016-06-06 14:27:39 -07002200 [track_id](const rtc::scoped_refptr<
2201 RtpReceiverProxyWithInternal<RtpReceiverInternal>>& receiver) {
perkjd61bf802016-03-24 03:16:19 -07002202 return receiver->id() == track_id;
deadbeef70ab1a12015-09-28 16:53:55 -07002203 });
2204}
2205
deadbeefab9b2d12015-10-14 11:33:11 -07002206PeerConnection::TrackInfos* PeerConnection::GetRemoteTracks(
2207 cricket::MediaType media_type) {
2208 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
2209 media_type == cricket::MEDIA_TYPE_VIDEO);
2210 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &remote_audio_tracks_
2211 : &remote_video_tracks_;
2212}
2213
2214PeerConnection::TrackInfos* PeerConnection::GetLocalTracks(
2215 cricket::MediaType media_type) {
2216 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
2217 media_type == cricket::MEDIA_TYPE_VIDEO);
2218 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_tracks_
2219 : &local_video_tracks_;
2220}
2221
2222const PeerConnection::TrackInfo* PeerConnection::FindTrackInfo(
2223 const PeerConnection::TrackInfos& infos,
2224 const std::string& stream_label,
2225 const std::string track_id) const {
2226 for (const TrackInfo& track_info : infos) {
2227 if (track_info.stream_label == stream_label &&
2228 track_info.track_id == track_id) {
2229 return &track_info;
2230 }
2231 }
2232 return nullptr;
2233}
2234
2235DataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
2236 for (const auto& channel : sctp_data_channels_) {
2237 if (channel->id() == sid) {
2238 return channel;
2239 }
2240 }
2241 return nullptr;
2242}
2243
deadbeef91dd5672016-05-18 16:55:30 -07002244bool PeerConnection::InitializePortAllocator_n(
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002245 const RTCConfiguration& configuration) {
2246 cricket::ServerAddresses stun_servers;
2247 std::vector<cricket::RelayServerConfig> turn_servers;
deadbeef293e9262017-01-11 12:28:30 -08002248 if (ParseIceServers(configuration.servers, &stun_servers, &turn_servers) !=
2249 RTCErrorType::NONE) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002250 return false;
2251 }
2252
Taylor Brandstetterf8e65772016-06-27 17:20:15 -07002253 port_allocator_->Initialize();
2254
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002255 // To handle both internal and externally created port allocator, we will
2256 // enable BUNDLE here.
2257 int portallocator_flags = port_allocator_->flags();
2258 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET |
zhihuangb09b3f92017-03-07 14:40:51 -08002259 cricket::PORTALLOCATOR_ENABLE_IPV6 |
2260 cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI;
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002261 // If the disable-IPv6 flag was specified, we'll not override it
2262 // by experiment.
2263 if (configuration.disable_ipv6) {
2264 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
sprangc1b57a12017-02-28 08:50:47 -08002265 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default")
2266 .find("Disabled") == 0) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002267 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6);
2268 }
2269
zhihuangb09b3f92017-03-07 14:40:51 -08002270 if (configuration.disable_ipv6_on_wifi) {
2271 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI);
2272 LOG(LS_INFO) << "IPv6 candidates on Wi-Fi are disabled.";
2273 }
2274
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002275 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) {
2276 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP;
2277 LOG(LS_INFO) << "TCP candidates are disabled.";
2278 }
2279
honghaiz60347052016-05-31 18:29:12 -07002280 if (configuration.candidate_network_policy ==
2281 kCandidateNetworkPolicyLowCost) {
2282 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS;
2283 LOG(LS_INFO) << "Do not gather candidates on high-cost networks";
2284 }
2285
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002286 port_allocator_->set_flags(portallocator_flags);
2287 // No step delay is used while allocating ports.
2288 port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
2289 port_allocator_->set_candidate_filter(
2290 ConvertIceTransportTypeToCandidateFilter(configuration.type));
2291
2292 // Call this last since it may create pooled allocator sessions using the
2293 // properties set above.
2294 port_allocator_->SetConfiguration(stun_servers, turn_servers,
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -07002295 configuration.ice_candidate_pool_size,
2296 configuration.prune_turn_ports);
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002297 return true;
2298}
2299
deadbeef91dd5672016-05-18 16:55:30 -07002300bool PeerConnection::ReconfigurePortAllocator_n(
deadbeef293e9262017-01-11 12:28:30 -08002301 const cricket::ServerAddresses& stun_servers,
2302 const std::vector<cricket::RelayServerConfig>& turn_servers,
2303 IceTransportsType type,
2304 int candidate_pool_size,
2305 bool prune_turn_ports) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002306 port_allocator_->set_candidate_filter(
deadbeef293e9262017-01-11 12:28:30 -08002307 ConvertIceTransportTypeToCandidateFilter(type));
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002308 // Call this last since it may create pooled allocator sessions using the
2309 // candidate filter set above.
deadbeef6de92f92016-12-12 18:49:32 -08002310 return port_allocator_->SetConfiguration(
deadbeef293e9262017-01-11 12:28:30 -08002311 stun_servers, turn_servers, candidate_pool_size, prune_turn_ports);
Taylor Brandstettera1c30352016-05-13 08:15:11 -07002312}
2313
ivoc14d5dbe2016-07-04 07:06:55 -07002314bool PeerConnection::StartRtcEventLog_w(rtc::PlatformFile file,
2315 int64_t max_size_bytes) {
zhihuang77985012017-02-07 15:45:16 -08002316 if (!event_log_) {
2317 return false;
2318 }
skvlad11a9cbf2016-10-07 11:53:05 -07002319 return event_log_->StartLogging(file, max_size_bytes);
ivoc14d5dbe2016-07-04 07:06:55 -07002320}
2321
2322void PeerConnection::StopRtcEventLog_w() {
zhihuang77985012017-02-07 15:45:16 -08002323 if (event_log_) {
2324 event_log_->StopLogging();
2325 }
ivoc14d5dbe2016-07-04 07:06:55 -07002326}
nisseeaabdf62017-05-05 02:23:02 -07002327
2328void PeerConnection::CreateCall_w() {
2329 RTC_DCHECK(!call_);
2330
2331 const int kMinBandwidthBps = 30000;
2332 const int kStartBandwidthBps = 300000;
2333 const int kMaxBandwidthBps = 2000000;
2334
2335 webrtc::Call::Config call_config(event_log_.get());
2336 call_config.audio_state =
2337 factory_->channel_manager() ->media_engine()->GetAudioState();
2338 call_config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
2339 call_config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
2340 call_config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;
2341
2342 call_.reset(webrtc::Call::Create(call_config));
2343}
2344
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002345} // namespace webrtc