blob: 477b1ff574df4a360625a267d6e2b11b2c2e6f28 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "pc/webrtcsession.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
pbos@webrtc.org371243d2014-03-07 15:22:04 +000013#include <limits.h>
14
henrike@webrtc.org28e20752013-07-10 00:45:36 +000015#include <algorithm>
deadbeefcbecd352015-09-23 11:50:27 -070016#include <set>
Tommif888bb52015-12-12 01:37:01 +010017#include <utility>
18#include <vector>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000019
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "api/call/audio_sink.h"
21#include "api/jsepicecandidate.h"
22#include "api/jsepsessiondescription.h"
23#include "api/peerconnectioninterface.h"
24#include "call/call.h"
25#include "media/base/mediaconstants.h"
26#include "media/sctp/sctptransportinternal.h"
27#include "p2p/base/portallocator.h"
28#include "pc/channel.h"
29#include "pc/channelmanager.h"
30#include "pc/mediasession.h"
31#include "pc/sctputils.h"
32#include "pc/webrtcsessiondescriptionfactory.h"
33#include "rtc_base/basictypes.h"
34#include "rtc_base/bind.h"
35#include "rtc_base/checks.h"
36#include "rtc_base/helpers.h"
37#include "rtc_base/logging.h"
38#include "rtc_base/stringencode.h"
39#include "rtc_base/stringutils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040
41using cricket::ContentInfo;
42using cricket::ContentInfos;
43using cricket::MediaContentDescription;
44using cricket::SessionDescription;
45using cricket::TransportInfo;
46
Guo-wei Shieh3d564c12015-08-19 16:51:15 -070047using cricket::LOCAL_PORT_TYPE;
48using cricket::STUN_PORT_TYPE;
49using cricket::RELAY_PORT_TYPE;
50using cricket::PRFLX_PORT_TYPE;
51
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052namespace webrtc {
53
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054// Error messages
Steve Anton6f25b092017-10-23 09:39:20 -070055const char kBundleWithoutRtcpMux[] =
56 "rtcp-mux must be enabled when BUNDLE "
57 "is enabled.";
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000058const char kCreateChannelFailed[] = "Failed to create channels.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059const char kInvalidCandidates[] = "Description contains invalid candidates.";
60const char kInvalidSdp[] = "Invalid session description.";
Zhi Huang2a5e4262017-09-14 01:15:03 -070061const char kMlineMismatchInAnswer[] =
62 "The order of m-lines in answer doesn't match order in offer. Rejecting "
63 "answer.";
64const char kMlineMismatchInSubsequentOffer[] =
65 "The order of m-lines in subsequent offer doesn't match order from "
66 "previous offer/answer.";
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000067const char kPushDownTDFailed[] =
68 "Failed to push down transport description:";
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000069const char kSdpWithoutDtlsFingerprint[] =
70 "Called with SDP without DTLS fingerprint.";
71const char kSdpWithoutSdesCrypto[] =
72 "Called with SDP without SDES crypto.";
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +000073const char kSdpWithoutIceUfragPwd[] =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000074 "Called with SDP without ice-ufrag and ice-pwd.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075const char kSessionError[] = "Session error code: ";
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000076const char kSessionErrorDesc[] = "Session error description: ";
deadbeef953c2ce2017-01-09 14:53:41 -080077const char kDtlsSrtpSetupFailureRtp[] =
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +000078 "Couldn't set up DTLS-SRTP on RTP channel.";
deadbeef953c2ce2017-01-09 14:53:41 -080079const char kDtlsSrtpSetupFailureRtcp[] =
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +000080 "Couldn't set up DTLS-SRTP on RTCP channel.";
deadbeefcbecd352015-09-23 11:50:27 -070081const char kEnableBundleFailed[] = "Failed to enable BUNDLE.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082
Guo-wei Shieh3d564c12015-08-19 16:51:15 -070083IceCandidatePairType GetIceCandidatePairCounter(
84 const cricket::Candidate& local,
85 const cricket::Candidate& remote) {
86 const auto& l = local.type();
87 const auto& r = remote.type();
88 const auto& host = LOCAL_PORT_TYPE;
89 const auto& srflx = STUN_PORT_TYPE;
90 const auto& relay = RELAY_PORT_TYPE;
91 const auto& prflx = PRFLX_PORT_TYPE;
Guo-wei Shieh3cc834a2015-09-04 15:52:14 -070092 if (l == host && r == host) {
93 bool local_private = IPIsPrivate(local.address().ipaddr());
94 bool remote_private = IPIsPrivate(remote.address().ipaddr());
95 if (local_private) {
96 if (remote_private) {
97 return kIceCandidatePairHostPrivateHostPrivate;
98 } else {
99 return kIceCandidatePairHostPrivateHostPublic;
100 }
101 } else {
102 if (remote_private) {
103 return kIceCandidatePairHostPublicHostPrivate;
104 } else {
105 return kIceCandidatePairHostPublicHostPublic;
106 }
107 }
108 }
Guo-wei Shieh3d564c12015-08-19 16:51:15 -0700109 if (l == host && r == srflx)
110 return kIceCandidatePairHostSrflx;
111 if (l == host && r == relay)
112 return kIceCandidatePairHostRelay;
113 if (l == host && r == prflx)
114 return kIceCandidatePairHostPrflx;
115 if (l == srflx && r == host)
116 return kIceCandidatePairSrflxHost;
117 if (l == srflx && r == srflx)
118 return kIceCandidatePairSrflxSrflx;
119 if (l == srflx && r == relay)
120 return kIceCandidatePairSrflxRelay;
121 if (l == srflx && r == prflx)
122 return kIceCandidatePairSrflxPrflx;
123 if (l == relay && r == host)
124 return kIceCandidatePairRelayHost;
125 if (l == relay && r == srflx)
126 return kIceCandidatePairRelaySrflx;
127 if (l == relay && r == relay)
128 return kIceCandidatePairRelayRelay;
129 if (l == relay && r == prflx)
130 return kIceCandidatePairRelayPrflx;
131 if (l == prflx && r == host)
132 return kIceCandidatePairPrflxHost;
133 if (l == prflx && r == srflx)
134 return kIceCandidatePairPrflxSrflx;
135 if (l == prflx && r == relay)
136 return kIceCandidatePairPrflxRelay;
137 return kIceCandidatePairMax;
138}
139
Zhi Huangb2d355e2017-10-26 17:26:37 -0700140// Verify that the order of media sections in |new_desc| matches
141// |existing_desc|. The number of m= sections in |new_desc| should be no less
142// than |existing_desc|.
143static bool MediaSectionsInSameOrder(const SessionDescription* existing_desc,
144 const SessionDescription* new_desc) {
145 if (!existing_desc || !new_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000146 return false;
Zhi Huang2a5e4262017-09-14 01:15:03 -0700147 }
Zhi Huangb2d355e2017-10-26 17:26:37 -0700148
149 if (existing_desc->contents().size() > new_desc->contents().size()) {
150 return false;
151 }
152
153 for (size_t i = 0; i < existing_desc->contents().size(); ++i) {
154 if (new_desc->contents()[i].name != existing_desc->contents()[i].name) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 return false;
156 }
Zhi Huangb2d355e2017-10-26 17:26:37 -0700157 const MediaContentDescription* new_desc_mdesc =
wu@webrtc.org4e393072014-04-07 17:04:35 +0000158 static_cast<const MediaContentDescription*>(
Zhi Huangb2d355e2017-10-26 17:26:37 -0700159 new_desc->contents()[i].description);
160 const MediaContentDescription* existing_desc_mdesc =
wu@webrtc.org4e393072014-04-07 17:04:35 +0000161 static_cast<const MediaContentDescription*>(
Zhi Huangb2d355e2017-10-26 17:26:37 -0700162 existing_desc->contents()[i].description);
163 if (new_desc_mdesc->type() != existing_desc_mdesc->type()) {
wu@webrtc.org4e393072014-04-07 17:04:35 +0000164 return false;
165 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000166 }
167 return true;
168}
169
Zhi Huang2a5e4262017-09-14 01:15:03 -0700170static bool MediaSectionsHaveSameCount(const SessionDescription* desc1,
171 const SessionDescription* desc2) {
172 if (!desc1 || !desc2) {
173 return false;
174 }
175 return desc1->contents().size() == desc2->contents().size();
176}
177
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178// Checks that each non-rejected content has SDES crypto keys or a DTLS
deadbeefb7892532017-02-22 19:35:18 -0800179// fingerprint, unless it's in a BUNDLE group, in which case only the
180// BUNDLE-tag section (first media section/description in the BUNDLE group)
181// needs a ufrag and pwd. Mismatches, such as replying with a DTLS fingerprint
182// to SDES keys, will be caught in JsepTransport negotiation, and backstopped
183// by Channel's |srtp_required| check.
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000184static bool VerifyCrypto(const SessionDescription* desc,
185 bool dtls_enabled,
186 std::string* error) {
deadbeefb7892532017-02-22 19:35:18 -0800187 const cricket::ContentGroup* bundle =
188 desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189 const ContentInfos& contents = desc->contents();
190 for (size_t index = 0; index < contents.size(); ++index) {
191 const ContentInfo* cinfo = &contents[index];
192 if (cinfo->rejected) {
193 continue;
194 }
deadbeefb7892532017-02-22 19:35:18 -0800195 if (bundle && bundle->HasContentName(cinfo->name) &&
196 cinfo->name != *(bundle->FirstContentName())) {
197 // This isn't the first media section in the BUNDLE group, so it's not
198 // required to have crypto attributes, since only the crypto attributes
199 // from the first section actually get used.
200 continue;
201 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000202
deadbeefb7892532017-02-22 19:35:18 -0800203 // If the content isn't rejected or bundled into another m= section, crypto
204 // must be present.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000205 const MediaContentDescription* media =
206 static_cast<const MediaContentDescription*>(cinfo->description);
207 const TransportInfo* tinfo = desc->GetTransportInfoByName(cinfo->name);
208 if (!media || !tinfo) {
209 // Something is not right.
210 LOG(LS_ERROR) << kInvalidSdp;
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000211 *error = kInvalidSdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 return false;
213 }
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000214 if (dtls_enabled) {
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000215 if (!tinfo->description.identity_fingerprint) {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000216 LOG(LS_WARNING) <<
217 "Session description must have DTLS fingerprint if DTLS enabled.";
218 *error = kSdpWithoutDtlsFingerprint;
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000219 return false;
220 }
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000221 } else {
222 if (media->cryptos().empty()) {
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000223 LOG(LS_WARNING) <<
224 "Session description must have SDES when DTLS disabled.";
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000225 *error = kSdpWithoutSdesCrypto;
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000226 return false;
227 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000228 }
229 }
230
231 return true;
232}
233
deadbeefb7892532017-02-22 19:35:18 -0800234// Checks that each non-rejected content has ice-ufrag and ice-pwd set, unless
235// it's in a BUNDLE group, in which case only the BUNDLE-tag section (first
236// media section/description in the BUNDLE group) needs a ufrag and pwd.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000237static bool VerifyIceUfragPwdPresent(const SessionDescription* desc) {
deadbeefb7892532017-02-22 19:35:18 -0800238 const cricket::ContentGroup* bundle =
239 desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000240 const ContentInfos& contents = desc->contents();
241 for (size_t index = 0; index < contents.size(); ++index) {
242 const ContentInfo* cinfo = &contents[index];
243 if (cinfo->rejected) {
244 continue;
245 }
deadbeefb7892532017-02-22 19:35:18 -0800246 if (bundle && bundle->HasContentName(cinfo->name) &&
247 cinfo->name != *(bundle->FirstContentName())) {
248 // This isn't the first media section in the BUNDLE group, so it's not
249 // required to have ufrag/password, since only the ufrag/password from
250 // the first section actually get used.
251 continue;
252 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000253
deadbeefb7892532017-02-22 19:35:18 -0800254 // If the content isn't rejected or bundled into another m= section,
255 // ice-ufrag and ice-pwd must be present.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000256 const TransportInfo* tinfo = desc->GetTransportInfoByName(cinfo->name);
257 if (!tinfo) {
258 // Something is not right.
259 LOG(LS_ERROR) << kInvalidSdp;
260 return false;
261 }
262 if (tinfo->description.ice_ufrag.empty() ||
263 tinfo->description.ice_pwd.empty()) {
264 LOG(LS_ERROR) << "Session description must have ice ufrag and pwd.";
265 return false;
266 }
267 }
268 return true;
269}
270
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271static bool GetTrackIdBySsrc(const SessionDescription* session_description,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200272 uint32_t ssrc,
273 std::string* track_id) {
nisseede5da42017-01-12 05:15:36 -0800274 RTC_DCHECK(track_id != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 const cricket::ContentInfo* audio_info =
277 cricket::GetFirstAudioContent(session_description);
jiayl@webrtc.orge21cc9a2014-08-28 22:21:34 +0000278 if (audio_info) {
279 const cricket::MediaContentDescription* audio_content =
280 static_cast<const cricket::MediaContentDescription*>(
281 audio_info->description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000282
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000283 const auto* found =
284 cricket::GetStreamBySsrc(audio_content->streams(), ssrc);
285 if (found) {
286 *track_id = found->id;
jiayl@webrtc.orge21cc9a2014-08-28 22:21:34 +0000287 return true;
288 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 }
290
291 const cricket::ContentInfo* video_info =
292 cricket::GetFirstVideoContent(session_description);
jiayl@webrtc.orge21cc9a2014-08-28 22:21:34 +0000293 if (video_info) {
294 const cricket::MediaContentDescription* video_content =
295 static_cast<const cricket::MediaContentDescription*>(
296 video_info->description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297
tommi@webrtc.org586f2ed2015-01-22 23:00:41 +0000298 const auto* found =
299 cricket::GetStreamBySsrc(video_content->streams(), ssrc);
300 if (found) {
301 *track_id = found->id;
jiayl@webrtc.orge21cc9a2014-08-28 22:21:34 +0000302 return true;
303 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 }
305 return false;
306}
307
deadbeef953c2ce2017-01-09 14:53:41 -0800308// Get the SCTP port out of a SessionDescription.
309// Return -1 if not found.
310static int GetSctpPort(const SessionDescription* session_description) {
311 const ContentInfo* content_info = GetFirstDataContent(session_description);
312 RTC_DCHECK(content_info);
313 if (!content_info) {
314 return -1;
315 }
316 const cricket::DataContentDescription* data =
317 static_cast<const cricket::DataContentDescription*>(
318 (content_info->description));
319 std::string value;
320 cricket::DataCodec match_pattern(cricket::kGoogleSctpDataCodecPlType,
321 cricket::kGoogleSctpDataCodecName);
322 for (const cricket::DataCodec& codec : data->codecs()) {
323 if (!codec.Matches(match_pattern)) {
324 continue;
325 }
326 if (codec.GetParam(cricket::kCodecParamPort, &value)) {
327 return rtc::FromString<int>(value);
328 }
329 }
330 return -1;
331}
332
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000333static bool BadSdp(const std::string& source,
334 const std::string& type,
335 const std::string& reason,
336 std::string* err_desc) {
337 std::ostringstream desc;
deadbeefd59daf82015-10-14 15:02:44 -0700338 desc << "Failed to set " << source;
339 if (!type.empty()) {
340 desc << " " << type;
341 }
Olga Sharonovaf2662f02017-10-20 09:42:08 +0000342 desc << " sdp: " << reason;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000343
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000344 if (err_desc) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000345 *err_desc = desc.str();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000347 LOG(LS_ERROR) << desc.str();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000348 return false;
349}
350
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000351static bool BadSdp(cricket::ContentSource source,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000352 const std::string& type,
353 const std::string& reason,
354 std::string* err_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000355 if (source == cricket::CS_LOCAL) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000356 return BadSdp("local", type, reason, err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000357 } else {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000358 return BadSdp("remote", type, reason, err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 }
360}
361
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000362static bool BadLocalSdp(const std::string& type,
363 const std::string& reason,
364 std::string* err_desc) {
365 return BadSdp(cricket::CS_LOCAL, type, reason, err_desc);
366}
367
368static bool BadRemoteSdp(const std::string& type,
369 const std::string& reason,
370 std::string* err_desc) {
371 return BadSdp(cricket::CS_REMOTE, type, reason, err_desc);
372}
373
374static bool BadOfferSdp(cricket::ContentSource source,
375 const std::string& reason,
376 std::string* err_desc) {
377 return BadSdp(source, SessionDescriptionInterface::kOffer, reason, err_desc);
378}
379
380static bool BadPranswerSdp(cricket::ContentSource source,
381 const std::string& reason,
382 std::string* err_desc) {
383 return BadSdp(source, SessionDescriptionInterface::kPrAnswer,
384 reason, err_desc);
385}
386
387static bool BadAnswerSdp(cricket::ContentSource source,
388 const std::string& reason,
389 std::string* err_desc) {
390 return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000391}
392
deadbeefd59daf82015-10-14 15:02:44 -0700393#define GET_STRING_OF_STATE(state) \
394 case webrtc::WebRtcSession::state: \
395 result = #state; \
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000396 break;
397
deadbeefd59daf82015-10-14 15:02:44 -0700398static std::string GetStateString(webrtc::WebRtcSession::State state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000399 std::string result;
400 switch (state) {
401 GET_STRING_OF_STATE(STATE_INIT)
deadbeefd59daf82015-10-14 15:02:44 -0700402 GET_STRING_OF_STATE(STATE_SENTOFFER)
403 GET_STRING_OF_STATE(STATE_RECEIVEDOFFER)
404 GET_STRING_OF_STATE(STATE_SENTPRANSWER)
405 GET_STRING_OF_STATE(STATE_RECEIVEDPRANSWER)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000406 GET_STRING_OF_STATE(STATE_INPROGRESS)
deadbeefd59daf82015-10-14 15:02:44 -0700407 GET_STRING_OF_STATE(STATE_CLOSED)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408 default:
nissec80e7412017-01-11 05:56:46 -0800409 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000410 break;
411 }
412 return result;
413}
414
deadbeefd59daf82015-10-14 15:02:44 -0700415#define GET_STRING_OF_ERROR_CODE(err) \
416 case webrtc::WebRtcSession::err: \
417 result = #err; \
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418 break;
419
deadbeefd59daf82015-10-14 15:02:44 -0700420static std::string GetErrorCodeString(webrtc::WebRtcSession::Error err) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 std::string result;
422 switch (err) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000423 GET_STRING_OF_ERROR_CODE(ERROR_NONE)
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000424 GET_STRING_OF_ERROR_CODE(ERROR_CONTENT)
425 GET_STRING_OF_ERROR_CODE(ERROR_TRANSPORT)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000426 default:
nisseeb4ca4e2017-01-12 02:24:27 -0800427 RTC_NOTREACHED();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428 break;
429 }
430 return result;
431}
432
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000433static std::string MakeErrorString(const std::string& error,
434 const std::string& desc) {
435 std::ostringstream ret;
436 ret << error << " " << desc;
437 return ret.str();
438}
439
440static std::string MakeTdErrorString(const std::string& desc) {
441 return MakeErrorString(kPushDownTDFailed, desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000442}
443
deadbeef0ed85b22016-02-23 17:24:52 -0800444// Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd).
445bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc,
446 const SessionDescriptionInterface* new_desc,
447 const std::string& content_name) {
448 if (!old_desc) {
honghaiz503726c2015-07-31 12:37:38 -0700449 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000450 }
deadbeef0ed85b22016-02-23 17:24:52 -0800451 const SessionDescription* new_sd = new_desc->description();
452 const SessionDescription* old_sd = old_desc->description();
453 const ContentInfo* cinfo = new_sd->GetContentByName(content_name);
454 if (!cinfo || cinfo->rejected) {
455 return false;
456 }
457 // If the content isn't rejected, check if ufrag and password has changed.
458 const cricket::TransportDescription* new_transport_desc =
459 new_sd->GetTransportDescriptionByName(content_name);
460 const cricket::TransportDescription* old_transport_desc =
461 old_sd->GetTransportDescriptionByName(content_name);
462 if (!new_transport_desc || !old_transport_desc) {
463 // No transport description exists. This is not an ICE restart.
464 return false;
465 }
466 if (cricket::IceCredentialsChanged(
467 old_transport_desc->ice_ufrag, old_transport_desc->ice_pwd,
468 new_transport_desc->ice_ufrag, new_transport_desc->ice_pwd)) {
469 LOG(LS_INFO) << "Remote peer requests ICE restart for " << content_name
470 << ".";
471 return true;
472 }
473 return false;
474}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000475
zhihuang29ff8442016-07-27 11:07:25 -0700476WebRtcSession::WebRtcSession(
nisseeaabdf62017-05-05 02:23:02 -0700477 Call* call,
478 cricket::ChannelManager* channel_manager,
479 const cricket::MediaConfig& media_config,
480 RtcEventLog* event_log,
zhihuang29ff8442016-07-27 11:07:25 -0700481 rtc::Thread* network_thread,
482 rtc::Thread* worker_thread,
483 rtc::Thread* signaling_thread,
484 cricket::PortAllocator* port_allocator,
deadbeef953c2ce2017-01-09 14:53:41 -0800485 std::unique_ptr<cricket::TransportController> transport_controller,
486 std::unique_ptr<cricket::SctpTransportInternalFactory> sctp_factory)
zhihuang9763d562016-08-05 11:14:50 -0700487 : network_thread_(network_thread),
488 worker_thread_(worker_thread),
danilchape9021a32016-05-17 01:52:02 -0700489 signaling_thread_(signaling_thread),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490 // RFC 3264: The numeric value of the session id and version in the
491 // o line MUST be representable with a "64 bit signed integer".
492 // Due to this constraint session id |sid_| is max limited to LLONG_MAX.
deadbeefd59daf82015-10-14 15:02:44 -0700493 sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
zhihuang29ff8442016-07-27 11:07:25 -0700494 transport_controller_(std::move(transport_controller)),
deadbeef953c2ce2017-01-09 14:53:41 -0800495 sctp_factory_(std::move(sctp_factory)),
nisseeaabdf62017-05-05 02:23:02 -0700496 media_config_(media_config),
497 event_log_(event_log),
498 call_(call),
499 channel_manager_(channel_manager),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000500 ice_observer_(NULL),
501 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
Peter Thatcher54360512015-07-08 11:08:35 -0700502 ice_connection_receiving_(true),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503 older_version_remote_peer_(false),
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000504 dtls_enabled_(false),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000505 data_channel_type_(cricket::DCT_NONE),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000506 metrics_observer_(NULL) {
deadbeefd59daf82015-10-14 15:02:44 -0700507 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
508 transport_controller_->SignalConnectionState.connect(
deadbeefcbecd352015-09-23 11:50:27 -0700509 this, &WebRtcSession::OnTransportControllerConnectionState);
deadbeefd59daf82015-10-14 15:02:44 -0700510 transport_controller_->SignalReceiving.connect(
deadbeefcbecd352015-09-23 11:50:27 -0700511 this, &WebRtcSession::OnTransportControllerReceiving);
deadbeefd59daf82015-10-14 15:02:44 -0700512 transport_controller_->SignalGatheringState.connect(
deadbeefcbecd352015-09-23 11:50:27 -0700513 this, &WebRtcSession::OnTransportControllerGatheringState);
deadbeefd59daf82015-10-14 15:02:44 -0700514 transport_controller_->SignalCandidatesGathered.connect(
deadbeefcbecd352015-09-23 11:50:27 -0700515 this, &WebRtcSession::OnTransportControllerCandidatesGathered);
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700516 transport_controller_->SignalCandidatesRemoved.connect(
517 this, &WebRtcSession::OnTransportControllerCandidatesRemoved);
zhihuangd82eee02016-08-26 11:25:05 -0700518 transport_controller_->SignalDtlsHandshakeError.connect(
deadbeef953c2ce2017-01-09 14:53:41 -0800519 this, &WebRtcSession::OnTransportControllerDtlsHandshakeError);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520}
521
522WebRtcSession::~WebRtcSession() {
nisseede5da42017-01-12 05:15:36 -0800523 RTC_DCHECK(signaling_thread()->IsCurrent());
Steve Anton169629a2017-08-30 17:36:36 -0700524 // Destroy video channels first since they may have a pointer to a voice
525 // channel.
526 for (auto* channel : video_channels_) {
527 DestroyVideoChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 }
Steve Anton169629a2017-08-30 17:36:36 -0700529 for (auto* channel : voice_channels_) {
530 DestroyVoiceChannel(channel);
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +0000531 }
deadbeef953c2ce2017-01-09 14:53:41 -0800532 if (rtp_data_channel_) {
zhihuangf5b251b2017-01-12 19:37:48 -0800533 DestroyDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -0800534 }
535 if (sctp_transport_) {
536 SignalDataChannelDestroyed();
537 network_thread_->Invoke<void>(
538 RTC_FROM_HERE, rtc::Bind(&WebRtcSession::DestroySctpTransport_n, this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539 }
deadbeefd59daf82015-10-14 15:02:44 -0700540
541 LOG(LS_INFO) << "Session: " << id() << " is destroyed.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542}
543
Steve Antond5585ca2017-10-23 14:49:26 -0700544void WebRtcSession::Initialize(
wu@webrtc.org97077a32013-10-25 21:18:33 +0000545 const PeerConnectionFactoryInterface::Options& options,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200546 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
Steve Antond5585ca2017-10-23 14:49:26 -0700547 const PeerConnectionInterface::RTCConfiguration& rtc_configuration,
548 PeerConnection* pc) {
Henrik Lundin64dad832015-05-11 12:44:23 +0200549 bundle_policy_ = rtc_configuration.bundle_policy;
Peter Thatcheraf55ccc2015-05-21 07:48:41 -0700550 rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy;
deadbeefd59daf82015-10-14 15:02:44 -0700551 transport_controller_->SetSslMaxProtocolVersion(options.ssl_max_version);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000552
Henrik Boström87713d02015-08-25 09:53:21 +0200553 // Obtain a certificate from RTCConfiguration if any were provided (optional).
554 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
555 if (!rtc_configuration.certificates.empty()) {
556 // TODO(hbos,torbjorng): Decide on certificate-selection strategy instead of
557 // just picking the first one. The decision should be made based on the DTLS
558 // handshake. The DTLS negotiations need to know about all certificates.
559 certificate = rtc_configuration.certificates[0];
560 }
561
honghaiz1f429e32015-09-28 07:57:34 -0700562 SetIceConfig(ParseIceConfig(rtc_configuration));
honghaiz4edc39c2015-09-01 09:53:56 -0700563
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000564 if (options.disable_encryption) {
565 dtls_enabled_ = false;
566 } else {
Henrik Boström87713d02015-08-25 09:53:21 +0200567 // Enable DTLS by default if we have an identity store or a certificate.
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200568 dtls_enabled_ = (cert_generator || certificate);
htaa2a49d92016-03-04 02:51:39 -0800569 // |rtc_configuration| can override the default |dtls_enabled_| value.
570 if (rtc_configuration.enable_dtls_srtp) {
571 dtls_enabled_ = *(rtc_configuration.enable_dtls_srtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000572 }
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +0000573 }
574
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575 // Enable creation of RTP data channels if the kEnableRtpDataChannels is set.
wu@webrtc.org97077a32013-10-25 21:18:33 +0000576 // It takes precendence over the disable_sctp_data_channels
577 // PeerConnectionFactoryInterface::Options.
htaa2a49d92016-03-04 02:51:39 -0800578 if (rtc_configuration.enable_rtp_data_channel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 data_channel_type_ = cricket::DCT_RTP;
Steve Antonc4faa9c2017-10-23 14:44:03 -0700580 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000581 // DTLS has to be enabled to use SCTP.
wu@webrtc.org97077a32013-10-25 21:18:33 +0000582 if (!options.disable_sctp_data_channels && dtls_enabled_) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000583 data_channel_type_ = cricket::DCT_SCTP;
584 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586
htaa2a49d92016-03-04 02:51:39 -0800587 video_options_.screencast_min_bitrate_kbps =
588 rtc_configuration.screencast_min_bitrate;
589 audio_options_.combined_audio_video_bwe =
590 rtc_configuration.combined_audio_video_bwe;
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +0000591
kwiberg102c6a62015-10-30 02:47:38 -0700592 audio_options_.audio_jitter_buffer_max_packets =
Karl Wibergbe579832015-11-10 22:34:18 +0100593 rtc::Optional<int>(rtc_configuration.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200594
Karl Wibergbe579832015-11-10 22:34:18 +0100595 audio_options_.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(
596 rtc_configuration.audio_jitter_buffer_fast_accelerate);
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200597
Steve Antond5585ca2017-10-23 14:49:26 -0700598 // Whether the certificate generator/certificate is null or not determines
599 // what WebRtcSessionDescriptionFactory will do, so make sure that we give it
600 // the right instructions by clearing the variables if needed.
Henrik Boström87713d02015-08-25 09:53:21 +0200601 if (!dtls_enabled_) {
Steve Antond5585ca2017-10-23 14:49:26 -0700602 cert_generator.reset();
603 certificate = nullptr;
604 } else if (certificate) {
605 // Favor generated certificate over the certificate generator.
606 cert_generator.reset();
Henrik Boström87713d02015-08-25 09:53:21 +0200607 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000608
Steve Antond5585ca2017-10-23 14:49:26 -0700609 webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
610 signaling_thread(), channel_manager_, pc, id(), std::move(cert_generator),
611 certificate));
Henrik Boströmd8281982015-08-27 10:12:24 +0200612 webrtc_session_desc_factory_->SignalCertificateReady.connect(
613 this, &WebRtcSession::OnCertificateReady);
mallinath@webrtc.org7e809c32013-09-30 18:59:08 +0000614
wu@webrtc.org97077a32013-10-25 21:18:33 +0000615 if (options.disable_encryption) {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000616 webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED);
mallinath@webrtc.org7e809c32013-09-30 18:59:08 +0000617 }
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700618
jbauch5869f502017-06-29 12:31:36 -0700619 webrtc_session_desc_factory_->set_enable_encrypted_rtp_header_extensions(
620 options.crypto_options.enable_encrypted_rtp_header_extensions);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621}
622
deadbeefd59daf82015-10-14 15:02:44 -0700623void WebRtcSession::Close() {
624 SetState(STATE_CLOSED);
625 RemoveUnusedChannels(nullptr);
stefanf79ade12017-06-02 06:44:03 -0700626 call_ = nullptr;
Steve Anton169629a2017-08-30 17:36:36 -0700627 RTC_DCHECK(voice_channels_.empty());
628 RTC_DCHECK(video_channels_.empty());
deadbeef953c2ce2017-01-09 14:53:41 -0800629 RTC_DCHECK(!rtp_data_channel_);
630 RTC_DCHECK(!sctp_transport_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631}
632
deadbeef0ed85b22016-02-23 17:24:52 -0800633cricket::BaseChannel* WebRtcSession::GetChannel(
634 const std::string& content_name) {
635 if (voice_channel() && voice_channel()->content_name() == content_name) {
636 return voice_channel();
637 }
638 if (video_channel() && video_channel()->content_name() == content_name) {
639 return video_channel();
640 }
deadbeef953c2ce2017-01-09 14:53:41 -0800641 if (rtp_data_channel() &&
642 rtp_data_channel()->content_name() == content_name) {
643 return rtp_data_channel();
deadbeef0ed85b22016-02-23 17:24:52 -0800644 }
645 return nullptr;
646}
647
deadbeef953c2ce2017-01-09 14:53:41 -0800648bool WebRtcSession::GetSctpSslRole(rtc::SSLRole* role) {
649 if (!local_description() || !remote_description()) {
650 LOG(LS_INFO) << "Local and Remote descriptions must be applied to get the "
651 << "SSL Role of the SCTP transport.";
652 return false;
653 }
654 if (!sctp_transport_) {
655 LOG(LS_INFO) << "Non-rejected SCTP m= section is needed to get the "
656 << "SSL Role of the SCTP transport.";
657 return false;
658 }
659
660 return transport_controller_->GetSslRole(*sctp_transport_name_, role);
661}
662
663bool WebRtcSession::GetSslRole(const std::string& content_name,
Taylor Brandstetterf475d362016-01-08 15:35:57 -0800664 rtc::SSLRole* role) {
deadbeeffe4a8a42016-12-20 17:56:17 -0800665 if (!local_description() || !remote_description()) {
deadbeef953c2ce2017-01-09 14:53:41 -0800666 LOG(LS_INFO) << "Local and Remote descriptions must be applied to get the "
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000667 << "SSL Role of the session.";
668 return false;
669 }
670
deadbeef953c2ce2017-01-09 14:53:41 -0800671 return transport_controller_->GetSslRole(GetTransportName(content_name),
672 role);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000673}
674
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000675void WebRtcSession::CreateOffer(
676 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 11:33:11 -0700677 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
678 const cricket::MediaSessionOptions& session_options) {
679 webrtc_session_desc_factory_->CreateOffer(observer, options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000680}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681
deadbeefab9b2d12015-10-14 11:33:11 -0700682void WebRtcSession::CreateAnswer(
683 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 11:33:11 -0700684 const cricket::MediaSessionOptions& session_options) {
htaa2a49d92016-03-04 02:51:39 -0800685 webrtc_session_desc_factory_->CreateAnswer(observer, session_options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686}
687
Steve Anton8d3444d2017-10-20 15:30:51 -0700688bool WebRtcSession::SetLocalDescription(
689 std::unique_ptr<SessionDescriptionInterface> desc,
690 std::string* err_desc) {
nisseede5da42017-01-12 05:15:36 -0800691 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700692
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000693 // Validate SDP.
Steve Anton8d3444d2017-10-20 15:30:51 -0700694 if (!ValidateSessionDescription(desc.get(), cricket::CS_LOCAL, err_desc)) {
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000695 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000696 }
697
deadbeefd59daf82015-10-14 15:02:44 -0700698 // Update the initial_offerer flag if this session is the initial_offerer.
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000699 Action action = GetAction(desc->type());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 if (state() == STATE_INIT && action == kOffer) {
deadbeefd59daf82015-10-14 15:02:44 -0700701 initial_offerer_ = true;
702 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703 }
704
deadbeeffe4a8a42016-12-20 17:56:17 -0800705 if (action == kAnswer) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700706 current_local_description_ = std::move(desc);
707 pending_local_description_ = nullptr;
708 current_remote_description_ = std::move(pending_remote_description_);
deadbeeffe4a8a42016-12-20 17:56:17 -0800709 } else {
Steve Anton8d3444d2017-10-20 15:30:51 -0700710 pending_local_description_ = std::move(desc);
deadbeeffe4a8a42016-12-20 17:56:17 -0800711 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000712
713 // Transport and Media channels will be created only when offer is set.
deadbeeffe4a8a42016-12-20 17:56:17 -0800714 if (action == kOffer && !CreateChannels(local_description()->description())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715 // TODO(mallinath) - Handle CreateChannel failure, as new local description
716 // is applied. Restore back to old description.
Steve Anton8d3444d2017-10-20 15:30:51 -0700717 return BadLocalSdp(local_description()->type(), kCreateChannelFailed,
718 err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 }
720
deadbeefcbecd352015-09-23 11:50:27 -0700721 // Remove unused channels if MediaContentDescription is rejected.
deadbeeffe4a8a42016-12-20 17:56:17 -0800722 RemoveUnusedChannels(local_description()->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000724 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725 return false;
726 }
deadbeeffe4a8a42016-12-20 17:56:17 -0800727 if (remote_description()) {
deadbeefd59daf82015-10-14 15:02:44 -0700728 // Now that we have a local description, we can push down remote candidates.
deadbeeffe4a8a42016-12-20 17:56:17 -0800729 UseCandidatesInSessionDescription(remote_description());
deadbeefcbecd352015-09-23 11:50:27 -0700730 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000731
deadbeef0ed85b22016-02-23 17:24:52 -0800732 pending_ice_restarts_.clear();
deadbeefd59daf82015-10-14 15:02:44 -0700733 if (error() != ERROR_NONE) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700734 return BadLocalSdp(local_description()->type(), GetSessionErrorMsg(),
735 err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736 }
737 return true;
738}
739
Steve Anton8d3444d2017-10-20 15:30:51 -0700740bool WebRtcSession::SetRemoteDescription(
741 std::unique_ptr<SessionDescriptionInterface> desc,
742 std::string* err_desc) {
nisseede5da42017-01-12 05:15:36 -0800743 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700744
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000745 // Validate SDP.
Steve Anton8d3444d2017-10-20 15:30:51 -0700746 if (!ValidateSessionDescription(desc.get(), cricket::CS_REMOTE, err_desc)) {
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000747 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748 }
749
Steve Anton8d3444d2017-10-20 15:30:51 -0700750 // Hold this pointer so candidates can be copied to it later in the method.
751 SessionDescriptionInterface* desc_ptr = desc.get();
752
deadbeeffe4a8a42016-12-20 17:56:17 -0800753 const SessionDescriptionInterface* old_remote_description =
754 remote_description();
755 // Grab ownership of the description being replaced for the remainder of this
Steve Anton8d3444d2017-10-20 15:30:51 -0700756 // method, since it's used below as |old_remote_description|.
deadbeeffe4a8a42016-12-20 17:56:17 -0800757 std::unique_ptr<SessionDescriptionInterface> replaced_remote_description;
758 Action action = GetAction(desc->type());
759 if (action == kAnswer) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700760 replaced_remote_description = pending_remote_description_
761 ? std::move(pending_remote_description_)
762 : std::move(current_remote_description_);
763 current_remote_description_ = std::move(desc);
764 pending_remote_description_ = nullptr;
765 current_local_description_ = std::move(pending_local_description_);
deadbeeffe4a8a42016-12-20 17:56:17 -0800766 } else {
Steve Anton8d3444d2017-10-20 15:30:51 -0700767 replaced_remote_description = std::move(pending_remote_description_);
768 pending_remote_description_ = std::move(desc);
deadbeeffe4a8a42016-12-20 17:56:17 -0800769 }
deadbeefd59daf82015-10-14 15:02:44 -0700770
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000771 // Transport and Media channels will be created only when offer is set.
Steve Anton8d3444d2017-10-20 15:30:51 -0700772 if (action == kOffer &&
773 !CreateChannels(remote_description()->description())) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000774 // TODO(mallinath) - Handle CreateChannel failure, as new local description
775 // is applied. Restore back to old description.
Steve Anton8d3444d2017-10-20 15:30:51 -0700776 return BadRemoteSdp(remote_description()->type(), kCreateChannelFailed,
777 err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000778 }
779
deadbeefcbecd352015-09-23 11:50:27 -0700780 // Remove unused channels if MediaContentDescription is rejected.
Steve Anton8d3444d2017-10-20 15:30:51 -0700781 RemoveUnusedChannels(remote_description()->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782
783 // NOTE: Candidates allocation will be initiated only when SetLocalDescription
784 // is called.
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000785 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000786 return false;
787 }
788
Steve Anton8d3444d2017-10-20 15:30:51 -0700789 if (local_description() &&
790 !UseCandidatesInSessionDescription(remote_description())) {
791 return BadRemoteSdp(remote_description()->type(), kInvalidCandidates,
792 err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 }
794
deadbeeffe4a8a42016-12-20 17:56:17 -0800795 if (old_remote_description) {
deadbeef0ed85b22016-02-23 17:24:52 -0800796 for (const cricket::ContentInfo& content :
deadbeeffe4a8a42016-12-20 17:56:17 -0800797 old_remote_description->description()->contents()) {
deadbeef0ed85b22016-02-23 17:24:52 -0800798 // Check if this new SessionDescription contains new ICE ufrag and
799 // password that indicates the remote peer requests an ICE restart.
800 // TODO(deadbeef): When we start storing both the current and pending
801 // remote description, this should reset pending_ice_restarts and compare
802 // against the current description.
Steve Anton8d3444d2017-10-20 15:30:51 -0700803 if (CheckForRemoteIceRestart(old_remote_description, remote_description(),
deadbeeffe4a8a42016-12-20 17:56:17 -0800804 content.name)) {
deadbeef0ed85b22016-02-23 17:24:52 -0800805 if (action == kOffer) {
806 pending_ice_restarts_.insert(content.name);
807 }
808 } else {
809 // We retain all received candidates only if ICE is not restarted.
810 // When ICE is restarted, all previous candidates belong to an old
811 // generation and should not be kept.
812 // TODO(deadbeef): This goes against the W3C spec which says the remote
813 // description should only contain candidates from the last set remote
814 // description plus any candidates added since then. We should remove
815 // this once we're sure it won't break anything.
816 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
Steve Anton8d3444d2017-10-20 15:30:51 -0700817 old_remote_description, content.name, desc_ptr);
deadbeef0ed85b22016-02-23 17:24:52 -0800818 }
819 }
honghaiz503726c2015-07-31 12:37:38 -0700820 }
821
deadbeefd59daf82015-10-14 15:02:44 -0700822 if (error() != ERROR_NONE) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700823 return BadRemoteSdp(remote_description()->type(), GetSessionErrorMsg(),
824 err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000825 }
jiayl@webrtc.orgdacdd942015-01-23 17:33:34 +0000826
827 // Set the the ICE connection state to connecting since the connection may
828 // become writable with peer reflexive candidates before any remote candidate
829 // is signaled.
830 // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix
831 // is to have a new signal the indicates a change in checking state from the
832 // transport and expose a new checking() member from transport that can be
833 // read to determine the current checking state. The existing SignalConnecting
834 // actually means "gathering candidates", so cannot be be used here.
Steve Anton8d3444d2017-10-20 15:30:51 -0700835 if (remote_description()->type() != SessionDescriptionInterface::kOffer &&
jiayl@webrtc.orgdacdd942015-01-23 17:33:34 +0000836 ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) {
837 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
838 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000839 return true;
840}
841
Steve Anton18ee1d52017-09-11 11:32:35 -0700842// TODO(steveanton): Eventually it'd be nice to store the channels as a single
843// vector of BaseChannel pointers instead of separate voice and video channel
844// vectors. At that point, this will become a simple getter.
845std::vector<cricket::BaseChannel*> WebRtcSession::Channels() const {
846 std::vector<cricket::BaseChannel*> channels;
847 channels.insert(channels.end(), voice_channels_.begin(),
848 voice_channels_.end());
849 channels.insert(channels.end(), video_channels_.begin(),
850 video_channels_.end());
851 if (rtp_data_channel_) {
852 channels.push_back(rtp_data_channel_.get());
853 }
854 return channels;
855}
856
deadbeefd59daf82015-10-14 15:02:44 -0700857void WebRtcSession::LogState(State old_state, State new_state) {
858 LOG(LS_INFO) << "Session:" << id()
859 << " Old state:" << GetStateString(old_state)
860 << " New state:" << GetStateString(new_state);
861}
862
863void WebRtcSession::SetState(State state) {
nisseede5da42017-01-12 05:15:36 -0800864 RTC_DCHECK(signaling_thread_->IsCurrent());
deadbeefd59daf82015-10-14 15:02:44 -0700865 if (state != state_) {
866 LogState(state_, state);
867 state_ = state;
868 SignalState(this, state_);
869 }
870}
871
872void WebRtcSession::SetError(Error error, const std::string& error_desc) {
nisseede5da42017-01-12 05:15:36 -0800873 RTC_DCHECK(signaling_thread_->IsCurrent());
deadbeefd59daf82015-10-14 15:02:44 -0700874 if (error != error_) {
875 error_ = error;
876 error_desc_ = error_desc;
877 }
878}
879
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000880bool WebRtcSession::UpdateSessionState(
881 Action action, cricket::ContentSource source,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000882 std::string* err_desc) {
nisseede5da42017-01-12 05:15:36 -0800883 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -0700884
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000885 // If there's already a pending error then no state transition should happen.
886 // But all call-sites should be verifying this before calling us!
nisseede5da42017-01-12 05:15:36 -0800887 RTC_DCHECK(error() == ERROR_NONE);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000888 std::string td_err;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000889 if (action == kOffer) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000890 if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
891 return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892 }
deadbeefd59daf82015-10-14 15:02:44 -0700893 SetState(source == cricket::CS_LOCAL ? STATE_SENTOFFER
894 : STATE_RECEIVEDOFFER);
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000895 if (!PushdownMediaDescription(cricket::CA_OFFER, source, err_desc)) {
deadbeefd59daf82015-10-14 15:02:44 -0700896 SetError(ERROR_CONTENT, *err_desc);
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000897 }
deadbeefd59daf82015-10-14 15:02:44 -0700898 if (error() != ERROR_NONE) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000899 return BadOfferSdp(source, GetSessionErrorMsg(), err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000900 }
901 } else if (action == kPrAnswer) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000902 if (!PushdownTransportDescription(source, cricket::CA_PRANSWER, &td_err)) {
903 return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904 }
905 EnableChannels();
deadbeefd59daf82015-10-14 15:02:44 -0700906 SetState(source == cricket::CS_LOCAL ? STATE_SENTPRANSWER
907 : STATE_RECEIVEDPRANSWER);
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000908 if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) {
deadbeefd59daf82015-10-14 15:02:44 -0700909 SetError(ERROR_CONTENT, *err_desc);
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000910 }
deadbeefd59daf82015-10-14 15:02:44 -0700911 if (error() != ERROR_NONE) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000912 return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000913 }
914 } else if (action == kAnswer) {
deadbeefcbecd352015-09-23 11:50:27 -0700915 const cricket::ContentGroup* local_bundle =
deadbeeffe4a8a42016-12-20 17:56:17 -0800916 local_description()->description()->GetGroupByName(
917 cricket::GROUP_TYPE_BUNDLE);
deadbeefcbecd352015-09-23 11:50:27 -0700918 const cricket::ContentGroup* remote_bundle =
deadbeeffe4a8a42016-12-20 17:56:17 -0800919 remote_description()->description()->GetGroupByName(
920 cricket::GROUP_TYPE_BUNDLE);
deadbeefcbecd352015-09-23 11:50:27 -0700921 if (local_bundle && remote_bundle) {
Taylor Brandstetterf475d362016-01-08 15:35:57 -0800922 // The answerer decides the transport to bundle on.
deadbeefcbecd352015-09-23 11:50:27 -0700923 const cricket::ContentGroup* answer_bundle =
924 (source == cricket::CS_LOCAL ? local_bundle : remote_bundle);
925 if (!EnableBundle(*answer_bundle)) {
926 LOG(LS_WARNING) << "Failed to enable BUNDLE.";
927 return BadAnswerSdp(source, kEnableBundleFailed, err_desc);
928 }
929 }
Taylor Brandstetterf475d362016-01-08 15:35:57 -0800930 // Only push down the transport description after enabling BUNDLE; we don't
931 // want to push down a description on a transport about to be destroyed.
932 if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) {
933 return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
934 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 EnableChannels();
deadbeefd59daf82015-10-14 15:02:44 -0700936 SetState(STATE_INPROGRESS);
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000937 if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) {
deadbeefd59daf82015-10-14 15:02:44 -0700938 SetError(ERROR_CONTENT, *err_desc);
pthatcher@webrtc.org592470b2015-03-16 21:15:37 +0000939 }
deadbeefd59daf82015-10-14 15:02:44 -0700940 if (error() != ERROR_NONE) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000941 return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000942 }
943 }
944 return true;
945}
946
947WebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
948 if (type == SessionDescriptionInterface::kOffer) {
949 return WebRtcSession::kOffer;
950 } else if (type == SessionDescriptionInterface::kPrAnswer) {
951 return WebRtcSession::kPrAnswer;
952 } else if (type == SessionDescriptionInterface::kAnswer) {
953 return WebRtcSession::kAnswer;
954 }
nisseede5da42017-01-12 05:15:36 -0800955 RTC_NOTREACHED() << "unknown action type";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956 return WebRtcSession::kOffer;
957}
958
deadbeefd59daf82015-10-14 15:02:44 -0700959bool WebRtcSession::PushdownMediaDescription(
960 cricket::ContentAction action,
961 cricket::ContentSource source,
962 std::string* err) {
Steve Anton18ee1d52017-09-11 11:32:35 -0700963 const SessionDescription* sdesc =
964 (source == cricket::CS_LOCAL ? local_description() : remote_description())
965 ->description();
966 RTC_DCHECK(sdesc);
967 bool all_success = true;
968 for (auto* channel : Channels()) {
969 // TODO(steveanton): Add support for multiple channels of the same type.
970 const ContentInfo* content_info =
971 cricket::GetFirstMediaContent(sdesc->contents(), channel->media_type());
972 if (!content_info) {
973 continue;
deadbeefd59daf82015-10-14 15:02:44 -0700974 }
Steve Anton18ee1d52017-09-11 11:32:35 -0700975 const MediaContentDescription* content_desc =
976 static_cast<const MediaContentDescription*>(content_info->description);
977 if (content_desc && !content_info->rejected) {
978 bool success = (source == cricket::CS_LOCAL)
979 ? channel->SetLocalContent(content_desc, action, err)
980 : channel->SetRemoteContent(content_desc, action, err);
981 if (!success) {
982 all_success = false;
983 break;
984 }
985 }
986 }
deadbeef953c2ce2017-01-09 14:53:41 -0800987 // Need complete offer/answer with an SCTP m= section before starting SCTP,
988 // according to https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-19
989 if (sctp_transport_ && local_description() && remote_description() &&
990 cricket::GetFirstDataContent(local_description()->description()) &&
991 cricket::GetFirstDataContent(remote_description()->description())) {
Steve Anton18ee1d52017-09-11 11:32:35 -0700992 all_success &= network_thread_->Invoke<bool>(
deadbeef953c2ce2017-01-09 14:53:41 -0800993 RTC_FROM_HERE,
994 rtc::Bind(&WebRtcSession::PushdownSctpParameters_n, this, source));
995 }
Steve Anton18ee1d52017-09-11 11:32:35 -0700996 return all_success;
deadbeef953c2ce2017-01-09 14:53:41 -0800997}
998
999bool WebRtcSession::PushdownSctpParameters_n(cricket::ContentSource source) {
1000 RTC_DCHECK(network_thread_->IsCurrent());
1001 RTC_DCHECK(local_description());
1002 RTC_DCHECK(remote_description());
1003 // Apply the SCTP port (which is hidden inside a DataCodec structure...)
1004 // When we support "max-message-size", that would also be pushed down here.
1005 return sctp_transport_->Start(
1006 GetSctpPort(local_description()->description()),
1007 GetSctpPort(remote_description()->description()));
deadbeefd59daf82015-10-14 15:02:44 -07001008}
1009
1010bool WebRtcSession::PushdownTransportDescription(cricket::ContentSource source,
1011 cricket::ContentAction action,
1012 std::string* error_desc) {
1013 RTC_DCHECK(signaling_thread()->IsCurrent());
1014
1015 if (source == cricket::CS_LOCAL) {
deadbeeffe4a8a42016-12-20 17:56:17 -08001016 return PushdownLocalTransportDescription(local_description()->description(),
1017 action, error_desc);
deadbeefd59daf82015-10-14 15:02:44 -07001018 }
deadbeeffe4a8a42016-12-20 17:56:17 -08001019 return PushdownRemoteTransportDescription(remote_description()->description(),
1020 action, error_desc);
deadbeefd59daf82015-10-14 15:02:44 -07001021}
1022
1023bool WebRtcSession::PushdownLocalTransportDescription(
1024 const SessionDescription* sdesc,
1025 cricket::ContentAction action,
1026 std::string* err) {
1027 RTC_DCHECK(signaling_thread()->IsCurrent());
1028
1029 if (!sdesc) {
1030 return false;
1031 }
1032
1033 for (const TransportInfo& tinfo : sdesc->transport_infos()) {
1034 if (!transport_controller_->SetLocalTransportDescription(
1035 tinfo.content_name, tinfo.description, action, err)) {
1036 return false;
1037 }
1038 }
1039
1040 return true;
1041}
1042
1043bool WebRtcSession::PushdownRemoteTransportDescription(
1044 const SessionDescription* sdesc,
1045 cricket::ContentAction action,
1046 std::string* err) {
1047 RTC_DCHECK(signaling_thread()->IsCurrent());
1048
1049 if (!sdesc) {
1050 return false;
1051 }
1052
1053 for (const TransportInfo& tinfo : sdesc->transport_infos()) {
1054 if (!transport_controller_->SetRemoteTransportDescription(
1055 tinfo.content_name, tinfo.description, action, err)) {
1056 return false;
1057 }
1058 }
1059
1060 return true;
1061}
1062
1063bool WebRtcSession::GetTransportDescription(
1064 const SessionDescription* description,
1065 const std::string& content_name,
1066 cricket::TransportDescription* tdesc) {
1067 if (!description || !tdesc) {
1068 return false;
1069 }
1070 const TransportInfo* transport_info =
1071 description->GetTransportInfoByName(content_name);
1072 if (!transport_info) {
1073 return false;
1074 }
1075 *tdesc = transport_info->description;
1076 return true;
1077}
1078
deadbeefcbecd352015-09-23 11:50:27 -07001079bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
1080 const std::string* first_content_name = bundle.FirstContentName();
1081 if (!first_content_name) {
1082 LOG(LS_WARNING) << "Tried to BUNDLE with no contents.";
1083 return false;
1084 }
1085 const std::string& transport_name = *first_content_name;
deadbeefcbecd352015-09-23 11:50:27 -07001086
deadbeef953c2ce2017-01-09 14:53:41 -08001087 auto maybe_set_transport = [this, bundle,
1088 transport_name](cricket::BaseChannel* ch) {
deadbeefcbecd352015-09-23 11:50:27 -07001089 if (!ch || !bundle.HasContentName(ch->content_name())) {
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001090 return true;
1091 }
1092
zhihuangf5b251b2017-01-12 19:37:48 -08001093 std::string old_transport_name = ch->transport_name();
1094 if (old_transport_name == transport_name) {
deadbeefcbecd352015-09-23 11:50:27 -07001095 LOG(LS_INFO) << "BUNDLE already enabled for " << ch->content_name()
1096 << " on " << transport_name << ".";
1097 return true;
deadbeef47ee2f32015-09-22 15:08:23 -07001098 }
torbjornga81a42f2015-09-23 02:16:58 -07001099
zhihuangb2cdd932017-01-19 16:54:25 -08001100 cricket::DtlsTransportInternal* rtp_dtls_transport =
1101 transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001102 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001103 bool need_rtcp = (ch->rtcp_dtls_transport() != nullptr);
1104 cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
zhihuangf5b251b2017-01-12 19:37:48 -08001105 if (need_rtcp) {
deadbeefd8cf08f2017-07-10 20:06:59 -07001106 rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001107 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
1108 }
1109
zhihuangb2cdd932017-01-19 16:54:25 -08001110 ch->SetTransports(rtp_dtls_transport, rtcp_dtls_transport);
deadbeefcbecd352015-09-23 11:50:27 -07001111 LOG(LS_INFO) << "Enabled BUNDLE for " << ch->content_name() << " on "
1112 << transport_name << ".";
zhihuangb2cdd932017-01-19 16:54:25 -08001113 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08001114 old_transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangf5b251b2017-01-12 19:37:48 -08001115 // If the channel needs rtcp, it means that the channel used to have a
1116 // rtcp transport which needs to be deleted now.
1117 if (need_rtcp) {
zhihuangb2cdd932017-01-19 16:54:25 -08001118 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08001119 old_transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
zhihuangf5b251b2017-01-12 19:37:48 -08001120 }
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001121 return true;
1122 };
1123
deadbeefcbecd352015-09-23 11:50:27 -07001124 if (!maybe_set_transport(voice_channel()) ||
1125 !maybe_set_transport(video_channel()) ||
deadbeef953c2ce2017-01-09 14:53:41 -08001126 !maybe_set_transport(rtp_data_channel())) {
deadbeefcbecd352015-09-23 11:50:27 -07001127 return false;
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001128 }
deadbeef953c2ce2017-01-09 14:53:41 -08001129 // For SCTP, transport creation/deletion happens here instead of in the
1130 // object itself.
1131 if (sctp_transport_) {
1132 RTC_DCHECK(sctp_transport_name_);
1133 RTC_DCHECK(sctp_content_name_);
1134 if (transport_name != *sctp_transport_name_ &&
1135 bundle.HasContentName(*sctp_content_name_)) {
1136 network_thread_->Invoke<void>(
1137 RTC_FROM_HERE, rtc::Bind(&WebRtcSession::ChangeSctpTransport_n, this,
1138 transport_name));
1139 }
1140 }
deadbeefcbecd352015-09-23 11:50:27 -07001141
pthatcher@webrtc.orgc04a97f2015-03-16 19:31:40 +00001142 return true;
1143}
1144
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001145bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) {
deadbeeffe4a8a42016-12-20 17:56:17 -08001146 if (!remote_description()) {
deadbeefd59daf82015-10-14 15:02:44 -07001147 LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
1148 << "without any remote session description.";
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001149 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001150 }
1151
1152 if (!candidate) {
deadbeefd59daf82015-10-14 15:02:44 -07001153 LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 return false;
1155 }
1156
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00001157 bool valid = false;
deadbeefd59daf82015-10-14 15:02:44 -07001158 bool ready = ReadyToUseRemoteCandidate(candidate, NULL, &valid);
1159 if (!valid) {
1160 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161 }
1162
1163 // Add this candidate to the remote session description.
deadbeeffe4a8a42016-12-20 17:56:17 -08001164 if (!mutable_remote_description()->AddCandidate(candidate)) {
deadbeefd59daf82015-10-14 15:02:44 -07001165 LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001166 return false;
1167 }
1168
deadbeefd59daf82015-10-14 15:02:44 -07001169 if (ready) {
1170 return UseCandidate(candidate);
1171 } else {
1172 LOG(LS_INFO) << "ProcessIceMessage: Not ready to use candidate.";
1173 return true;
1174 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175}
1176
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001177bool WebRtcSession::RemoveRemoteIceCandidates(
1178 const std::vector<cricket::Candidate>& candidates) {
deadbeeffe4a8a42016-12-20 17:56:17 -08001179 if (!remote_description()) {
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001180 LOG(LS_ERROR) << "RemoveRemoteIceCandidates: ICE candidates can't be "
1181 << "removed without any remote session description.";
1182 return false;
1183 }
1184
1185 if (candidates.empty()) {
1186 LOG(LS_ERROR) << "RemoveRemoteIceCandidates: candidates are empty.";
1187 return false;
1188 }
1189
deadbeeffe4a8a42016-12-20 17:56:17 -08001190 size_t number_removed =
1191 mutable_remote_description()->RemoveCandidates(candidates);
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001192 if (number_removed != candidates.size()) {
1193 LOG(LS_ERROR) << "RemoveRemoteIceCandidates: Failed to remove candidates. "
1194 << "Requested " << candidates.size() << " but only "
1195 << number_removed << " are removed.";
1196 }
1197
1198 // Remove the candidates from the transport controller.
1199 std::string error;
1200 bool res = transport_controller_->RemoveRemoteCandidates(candidates, &error);
1201 if (!res && !error.empty()) {
1202 LOG(LS_ERROR) << "Error when removing remote candidates: " << error;
1203 }
1204 return true;
1205}
1206
deadbeefd59daf82015-10-14 15:02:44 -07001207cricket::IceConfig WebRtcSession::ParseIceConfig(
1208 const PeerConnectionInterface::RTCConfiguration& config) const {
Honghai Zhang5622c5e2016-07-01 13:59:29 -07001209 cricket::ContinualGatheringPolicy gathering_policy;
1210 // TODO(honghaiz): Add the third continual gathering policy in
1211 // PeerConnectionInterface and map it to GATHER_CONTINUALLY_AND_RECOVER.
1212 switch (config.continual_gathering_policy) {
1213 case PeerConnectionInterface::GATHER_ONCE:
1214 gathering_policy = cricket::GATHER_ONCE;
1215 break;
1216 case PeerConnectionInterface::GATHER_CONTINUALLY:
1217 gathering_policy = cricket::GATHER_CONTINUALLY;
1218 break;
1219 default:
nisseeb4ca4e2017-01-12 02:24:27 -08001220 RTC_NOTREACHED();
Honghai Zhang5622c5e2016-07-01 13:59:29 -07001221 gathering_policy = cricket::GATHER_ONCE;
1222 }
deadbeefd59daf82015-10-14 15:02:44 -07001223 cricket::IceConfig ice_config;
Honghai Zhang049fbb12016-03-07 11:13:07 -08001224 ice_config.receiving_timeout = config.ice_connection_receiving_timeout;
guoweis36f01372016-03-02 18:02:40 -08001225 ice_config.prioritize_most_likely_candidate_pairs =
1226 config.prioritize_most_likely_ice_candidate_pairs;
Honghai Zhang381b4212015-12-04 12:24:03 -08001227 ice_config.backup_connection_ping_interval =
1228 config.ice_backup_candidate_pair_ping_interval;
Honghai Zhang5622c5e2016-07-01 13:59:29 -07001229 ice_config.continual_gathering_policy = gathering_policy;
Taylor Brandstettere9851112016-07-01 11:11:13 -07001230 ice_config.presume_writable_when_fully_relayed =
1231 config.presume_writable_when_fully_relayed;
skvlad51072462017-02-02 11:50:14 -08001232 ice_config.ice_check_min_interval = config.ice_check_min_interval;
Steve Anton300bf8e2017-07-14 10:13:10 -07001233 ice_config.regather_all_networks_interval_range =
1234 config.ice_regather_interval_range;
deadbeefd59daf82015-10-14 15:02:44 -07001235 return ice_config;
1236}
1237
1238void WebRtcSession::SetIceConfig(const cricket::IceConfig& config) {
1239 transport_controller_->SetIceConfig(config);
1240}
1241
1242void WebRtcSession::MaybeStartGathering() {
1243 transport_controller_->MaybeStartGathering();
1244}
1245
Peter Boström0c4e06b2015-10-07 12:23:21 +02001246bool WebRtcSession::GetLocalTrackIdBySsrc(uint32_t ssrc,
1247 std::string* track_id) {
deadbeeffe4a8a42016-12-20 17:56:17 -08001248 if (!local_description()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001249 return false;
deadbeefd59daf82015-10-14 15:02:44 -07001250 }
deadbeeffe4a8a42016-12-20 17:56:17 -08001251 return webrtc::GetTrackIdBySsrc(local_description()->description(), ssrc,
1252 track_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253}
1254
Peter Boström0c4e06b2015-10-07 12:23:21 +02001255bool WebRtcSession::GetRemoteTrackIdBySsrc(uint32_t ssrc,
1256 std::string* track_id) {
deadbeeffe4a8a42016-12-20 17:56:17 -08001257 if (!remote_description()) {
xians@webrtc.org4cb01282014-06-12 14:57:05 +00001258 return false;
deadbeefd59daf82015-10-14 15:02:44 -07001259 }
deadbeeffe4a8a42016-12-20 17:56:17 -08001260 return webrtc::GetTrackIdBySsrc(remote_description()->description(), ssrc,
1261 track_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262}
1263
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001264std::string WebRtcSession::BadStateErrMsg(State state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001265 std::ostringstream desc;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001266 desc << "Called in wrong state: " << GetStateString(state);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267 return desc.str();
1268}
1269
wu@webrtc.org78187522013-10-07 23:32:02 +00001270bool WebRtcSession::SendData(const cricket::SendDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07001271 const rtc::CopyOnWriteBuffer& payload,
wu@webrtc.org78187522013-10-07 23:32:02 +00001272 cricket::SendDataResult* result) {
deadbeef953c2ce2017-01-09 14:53:41 -08001273 if (!rtp_data_channel_ && !sctp_transport_) {
1274 LOG(LS_ERROR) << "SendData called when rtp_data_channel_ "
1275 << "and sctp_transport_ are NULL.";
wu@webrtc.org78187522013-10-07 23:32:02 +00001276 return false;
1277 }
deadbeef953c2ce2017-01-09 14:53:41 -08001278 return rtp_data_channel_
1279 ? rtp_data_channel_->SendData(params, payload, result)
1280 : network_thread_->Invoke<bool>(
1281 RTC_FROM_HERE,
1282 Bind(&cricket::SctpTransportInternal::SendData,
1283 sctp_transport_.get(), params, payload, result));
wu@webrtc.org78187522013-10-07 23:32:02 +00001284}
1285
1286bool WebRtcSession::ConnectDataChannel(DataChannel* webrtc_data_channel) {
deadbeef953c2ce2017-01-09 14:53:41 -08001287 if (!rtp_data_channel_ && !sctp_transport_) {
deadbeefdaf88b12016-10-05 22:29:30 -07001288 // Don't log an error here, because DataChannels are expected to call
1289 // ConnectDataChannel in this state. It's the only way to initially tell
1290 // whether or not the underlying transport is ready.
wu@webrtc.org78187522013-10-07 23:32:02 +00001291 return false;
1292 }
deadbeef953c2ce2017-01-09 14:53:41 -08001293 if (rtp_data_channel_) {
1294 rtp_data_channel_->SignalReadyToSendData.connect(
1295 webrtc_data_channel, &DataChannel::OnChannelReady);
1296 rtp_data_channel_->SignalDataReceived.connect(webrtc_data_channel,
1297 &DataChannel::OnDataReceived);
1298 } else {
1299 SignalSctpReadyToSendData.connect(webrtc_data_channel,
1300 &DataChannel::OnChannelReady);
1301 SignalSctpDataReceived.connect(webrtc_data_channel,
1302 &DataChannel::OnDataReceived);
1303 SignalSctpStreamClosedRemotely.connect(
1304 webrtc_data_channel, &DataChannel::OnStreamClosedRemotely);
1305 }
wu@webrtc.org78187522013-10-07 23:32:02 +00001306 return true;
1307}
1308
1309void WebRtcSession::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
deadbeef953c2ce2017-01-09 14:53:41 -08001310 if (!rtp_data_channel_ && !sctp_transport_) {
1311 LOG(LS_ERROR) << "DisconnectDataChannel called when rtp_data_channel_ and "
1312 "sctp_transport_ are NULL.";
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001313 return;
1314 }
deadbeef953c2ce2017-01-09 14:53:41 -08001315 if (rtp_data_channel_) {
1316 rtp_data_channel_->SignalReadyToSendData.disconnect(webrtc_data_channel);
1317 rtp_data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
1318 } else {
1319 SignalSctpReadyToSendData.disconnect(webrtc_data_channel);
1320 SignalSctpDataReceived.disconnect(webrtc_data_channel);
1321 SignalSctpStreamClosedRemotely.disconnect(webrtc_data_channel);
1322 }
wu@webrtc.org78187522013-10-07 23:32:02 +00001323}
1324
bemasc@webrtc.org9b5467e2014-12-04 23:16:52 +00001325void WebRtcSession::AddSctpDataStream(int sid) {
deadbeef953c2ce2017-01-09 14:53:41 -08001326 if (!sctp_transport_) {
1327 LOG(LS_ERROR) << "AddSctpDataStream called when sctp_transport_ is NULL.";
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001328 return;
1329 }
deadbeef953c2ce2017-01-09 14:53:41 -08001330 network_thread_->Invoke<void>(
1331 RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::OpenStream,
1332 sctp_transport_.get(), sid));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001333}
1334
bemasc@webrtc.org9b5467e2014-12-04 23:16:52 +00001335void WebRtcSession::RemoveSctpDataStream(int sid) {
deadbeef953c2ce2017-01-09 14:53:41 -08001336 if (!sctp_transport_) {
1337 LOG(LS_ERROR) << "RemoveSctpDataStream called when sctp_transport_ is "
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001338 << "NULL.";
1339 return;
1340 }
deadbeef953c2ce2017-01-09 14:53:41 -08001341 network_thread_->Invoke<void>(
1342 RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::ResetStream,
1343 sctp_transport_.get(), sid));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001344}
1345
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001346bool WebRtcSession::ReadyToSendData() const {
deadbeef953c2ce2017-01-09 14:53:41 -08001347 return (rtp_data_channel_ && rtp_data_channel_->ready_to_send_data()) ||
1348 sctp_ready_to_send_data_;
1349}
1350
1351std::unique_ptr<SessionStats> WebRtcSession::GetStats_s() {
nisseede5da42017-01-12 05:15:36 -08001352 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeef953c2ce2017-01-09 14:53:41 -08001353 ChannelNamePairs channel_name_pairs;
1354 if (voice_channel()) {
1355 channel_name_pairs.voice = rtc::Optional<ChannelNamePair>(ChannelNamePair(
1356 voice_channel()->content_name(), voice_channel()->transport_name()));
1357 }
1358 if (video_channel()) {
1359 channel_name_pairs.video = rtc::Optional<ChannelNamePair>(ChannelNamePair(
1360 video_channel()->content_name(), video_channel()->transport_name()));
1361 }
1362 if (rtp_data_channel()) {
1363 channel_name_pairs.data = rtc::Optional<ChannelNamePair>(
1364 ChannelNamePair(rtp_data_channel()->content_name(),
1365 rtp_data_channel()->transport_name()));
1366 }
1367 if (sctp_transport_) {
1368 RTC_DCHECK(sctp_content_name_);
1369 RTC_DCHECK(sctp_transport_name_);
1370 channel_name_pairs.data = rtc::Optional<ChannelNamePair>(
1371 ChannelNamePair(*sctp_content_name_, *sctp_transport_name_));
1372 }
1373 return GetStats(channel_name_pairs);
1374}
1375
1376std::unique_ptr<SessionStats> WebRtcSession::GetStats(
1377 const ChannelNamePairs& channel_name_pairs) {
1378 if (network_thread()->IsCurrent()) {
1379 return GetStats_n(channel_name_pairs);
1380 }
1381 return network_thread()->Invoke<std::unique_ptr<SessionStats>>(
1382 RTC_FROM_HERE,
1383 rtc::Bind(&WebRtcSession::GetStats_n, this, channel_name_pairs));
1384}
1385
1386bool WebRtcSession::GetLocalCertificate(
1387 const std::string& transport_name,
1388 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
1389 return transport_controller_->GetLocalCertificate(transport_name,
1390 certificate);
1391}
1392
1393std::unique_ptr<rtc::SSLCertificate> WebRtcSession::GetRemoteSSLCertificate(
1394 const std::string& transport_name) {
1395 return transport_controller_->GetRemoteSSLCertificate(transport_name);
wu@webrtc.org07a6fbe2013-11-04 18:41:34 +00001396}
1397
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001398cricket::DataChannelType WebRtcSession::data_channel_type() const {
1399 return data_channel_type_;
1400}
1401
deadbeef0ed85b22016-02-23 17:24:52 -08001402bool WebRtcSession::IceRestartPending(const std::string& content_name) const {
1403 return pending_ice_restarts_.find(content_name) !=
1404 pending_ice_restarts_.end();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001405}
1406
deadbeefd1a38b52016-12-10 13:15:33 -08001407void WebRtcSession::SetNeedsIceRestartFlag() {
1408 transport_controller_->SetNeedsIceRestartFlag();
1409}
1410
1411bool WebRtcSession::NeedsIceRestart(const std::string& content_name) const {
1412 return transport_controller_->NeedsIceRestart(content_name);
1413}
1414
Henrik Boströmd8281982015-08-27 10:12:24 +02001415void WebRtcSession::OnCertificateReady(
1416 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
deadbeefd59daf82015-10-14 15:02:44 -07001417 transport_controller_->SetLocalCertificate(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001418}
1419
deadbeef953c2ce2017-01-09 14:53:41 -08001420void WebRtcSession::OnDtlsSrtpSetupFailure(cricket::BaseChannel*, bool rtcp) {
1421 SetError(ERROR_TRANSPORT,
1422 rtcp ? kDtlsSrtpSetupFailureRtcp : kDtlsSrtpSetupFailureRtp);
1423}
1424
Henrik Boströmd8281982015-08-27 10:12:24 +02001425bool WebRtcSession::waiting_for_certificate_for_testing() const {
Henrik Boström87713d02015-08-25 09:53:21 +02001426 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001427}
1428
deadbeefcbecd352015-09-23 11:50:27 -07001429const rtc::scoped_refptr<rtc::RTCCertificate>&
1430WebRtcSession::certificate_for_testing() {
deadbeefd59daf82015-10-14 15:02:44 -07001431 return transport_controller_->certificate_for_testing();
deadbeefcbecd352015-09-23 11:50:27 -07001432}
1433
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001434void WebRtcSession::SetIceConnectionState(
1435 PeerConnectionInterface::IceConnectionState state) {
1436 if (ice_connection_state_ == state) {
1437 return;
1438 }
1439
deadbeefcbecd352015-09-23 11:50:27 -07001440 LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
1441 << " => " << state;
Taylor Brandstetter6aefc632016-05-26 16:08:23 -07001442 RTC_DCHECK(ice_connection_state_ !=
1443 PeerConnectionInterface::kIceConnectionClosed);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001444 ice_connection_state_ = state;
1445 if (ice_observer_) {
zstein6dfd53a2017-03-06 13:49:03 -08001446 ice_observer_->OnIceConnectionStateChange(ice_connection_state_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001447 }
1448}
1449
deadbeefcbecd352015-09-23 11:50:27 -07001450void WebRtcSession::OnTransportControllerConnectionState(
1451 cricket::IceConnectionState state) {
1452 switch (state) {
1453 case cricket::kIceConnectionConnecting:
1454 // If the current state is Connected or Completed, then there were
1455 // writable channels but now there are not, so the next state must
1456 // be Disconnected.
1457 // kIceConnectionConnecting is currently used as the default,
1458 // un-connected state by the TransportController, so its only use is
1459 // detecting disconnections.
1460 if (ice_connection_state_ ==
1461 PeerConnectionInterface::kIceConnectionConnected ||
1462 ice_connection_state_ ==
1463 PeerConnectionInterface::kIceConnectionCompleted) {
1464 SetIceConnectionState(
1465 PeerConnectionInterface::kIceConnectionDisconnected);
1466 }
torbjornga81a42f2015-09-23 02:16:58 -07001467 break;
deadbeefcbecd352015-09-23 11:50:27 -07001468 case cricket::kIceConnectionFailed:
1469 SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
1470 break;
1471 case cricket::kIceConnectionConnected:
1472 LOG(LS_INFO) << "Changing to ICE connected state because "
1473 << "all transports are writable.";
1474 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
1475 break;
1476 case cricket::kIceConnectionCompleted:
1477 LOG(LS_INFO) << "Changing to ICE completed state because "
1478 << "all transports are complete.";
1479 if (ice_connection_state_ !=
1480 PeerConnectionInterface::kIceConnectionConnected) {
1481 // If jumping directly from "checking" to "connected",
1482 // signal "connected" first.
1483 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
1484 }
1485 SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
1486 if (metrics_observer_) {
1487 ReportTransportStats();
1488 }
1489 break;
1490 default:
nissec80e7412017-01-11 05:56:46 -08001491 RTC_NOTREACHED();
torbjornga81a42f2015-09-23 02:16:58 -07001492 }
deadbeefcbecd352015-09-23 11:50:27 -07001493}
1494
1495void WebRtcSession::OnTransportControllerReceiving(bool receiving) {
Peter Thatcher54360512015-07-08 11:08:35 -07001496 SetIceConnectionReceiving(receiving);
1497}
1498
1499void WebRtcSession::SetIceConnectionReceiving(bool receiving) {
1500 if (ice_connection_receiving_ == receiving) {
1501 return;
1502 }
1503 ice_connection_receiving_ = receiving;
1504 if (ice_observer_) {
1505 ice_observer_->OnIceConnectionReceivingChange(receiving);
1506 }
1507}
1508
deadbeefcbecd352015-09-23 11:50:27 -07001509void WebRtcSession::OnTransportControllerCandidatesGathered(
1510 const std::string& transport_name,
1511 const cricket::Candidates& candidates) {
nisseede5da42017-01-12 05:15:36 -08001512 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -07001513 int sdp_mline_index;
1514 if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) {
1515 LOG(LS_ERROR) << "OnTransportControllerCandidatesGathered: content name "
1516 << transport_name << " not found";
1517 return;
1518 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519
deadbeefcbecd352015-09-23 11:50:27 -07001520 for (cricket::Candidates::const_iterator citer = candidates.begin();
1521 citer != candidates.end(); ++citer) {
1522 // Use transport_name as the candidate media id.
jbauch81bf7b02017-03-25 08:31:12 -07001523 std::unique_ptr<JsepIceCandidate> candidate(
1524 new JsepIceCandidate(transport_name, sdp_mline_index, *citer));
deadbeeffe4a8a42016-12-20 17:56:17 -08001525 if (local_description()) {
jbauch81bf7b02017-03-25 08:31:12 -07001526 mutable_local_description()->AddCandidate(candidate.get());
1527 }
1528 if (ice_observer_) {
1529 ice_observer_->OnIceCandidate(std::move(candidate));
deadbeefcbecd352015-09-23 11:50:27 -07001530 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531 }
1532}
1533
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001534void WebRtcSession::OnTransportControllerCandidatesRemoved(
1535 const std::vector<cricket::Candidate>& candidates) {
nisseede5da42017-01-12 05:15:36 -08001536 RTC_DCHECK(signaling_thread()->IsCurrent());
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001537 // Sanity check.
1538 for (const cricket::Candidate& candidate : candidates) {
1539 if (candidate.transport_name().empty()) {
1540 LOG(LS_ERROR) << "OnTransportControllerCandidatesRemoved: "
1541 << "empty content name in candidate "
1542 << candidate.ToString();
1543 return;
1544 }
1545 }
1546
deadbeeffe4a8a42016-12-20 17:56:17 -08001547 if (local_description()) {
1548 mutable_local_description()->RemoveCandidates(candidates);
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001549 }
1550 if (ice_observer_) {
1551 ice_observer_->OnIceCandidatesRemoved(candidates);
1552 }
1553}
1554
deadbeef953c2ce2017-01-09 14:53:41 -08001555void WebRtcSession::OnTransportControllerDtlsHandshakeError(
1556 rtc::SSLHandshakeError error) {
1557 if (metrics_observer_) {
1558 metrics_observer_->IncrementEnumCounter(
1559 webrtc::kEnumCounterDtlsHandshakeError, static_cast<int>(error),
1560 static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
1561 }
1562}
1563
Steve Anton169629a2017-08-30 17:36:36 -07001564// Enabling voice and video (and RTP data) channels.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001565void WebRtcSession::EnableChannels() {
Steve Anton169629a2017-08-30 17:36:36 -07001566 for (cricket::VoiceChannel* voice_channel : voice_channels_) {
1567 if (!voice_channel->enabled()) {
1568 voice_channel->Enable(true);
1569 }
1570 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571
Steve Anton169629a2017-08-30 17:36:36 -07001572 for (cricket::VideoChannel* video_channel : video_channels_) {
1573 if (!video_channel->enabled()) {
1574 video_channel->Enable(true);
1575 }
1576 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001577
deadbeef953c2ce2017-01-09 14:53:41 -08001578 if (rtp_data_channel_ && !rtp_data_channel_->enabled())
1579 rtp_data_channel_->Enable(true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580}
1581
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582// Returns the media index for a local ice candidate given the content name.
1583bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
1584 int* sdp_mline_index) {
deadbeeffe4a8a42016-12-20 17:56:17 -08001585 if (!local_description() || !sdp_mline_index) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586 return false;
deadbeefd59daf82015-10-14 15:02:44 -07001587 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588
1589 bool content_found = false;
deadbeeffe4a8a42016-12-20 17:56:17 -08001590 const ContentInfos& contents = local_description()->description()->contents();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591 for (size_t index = 0; index < contents.size(); ++index) {
1592 if (contents[index].name == content_name) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001593 *sdp_mline_index = static_cast<int>(index);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001594 content_found = true;
1595 break;
1596 }
1597 }
1598 return content_found;
1599}
1600
1601bool WebRtcSession::UseCandidatesInSessionDescription(
1602 const SessionDescriptionInterface* remote_desc) {
deadbeefd59daf82015-10-14 15:02:44 -07001603 if (!remote_desc) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604 return true;
deadbeefd59daf82015-10-14 15:02:44 -07001605 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606 bool ret = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00001607
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608 for (size_t m = 0; m < remote_desc->number_of_mediasections(); ++m) {
1609 const IceCandidateCollection* candidates = remote_desc->candidates(m);
deadbeefd59daf82015-10-14 15:02:44 -07001610 for (size_t n = 0; n < candidates->count(); ++n) {
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00001611 const IceCandidateInterface* candidate = candidates->at(n);
1612 bool valid = false;
1613 if (!ReadyToUseRemoteCandidate(candidate, remote_desc, &valid)) {
1614 if (valid) {
deadbeefd59daf82015-10-14 15:02:44 -07001615 LOG(LS_INFO) << "UseCandidatesInSessionDescription: Not ready to use "
1616 << "candidate.";
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00001617 }
1618 continue;
1619 }
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00001620 ret = UseCandidate(candidate);
deadbeefd59daf82015-10-14 15:02:44 -07001621 if (!ret) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 break;
deadbeefd59daf82015-10-14 15:02:44 -07001623 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001624 }
1625 }
1626 return ret;
1627}
1628
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001629bool WebRtcSession::UseCandidate(const IceCandidateInterface* candidate) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001630 size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index());
deadbeeffe4a8a42016-12-20 17:56:17 -08001631 size_t remote_content_size =
1632 remote_description()->description()->contents().size();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001633 if (mediacontent_index >= remote_content_size) {
Honghai Zhang7fb69db2016-03-14 11:59:18 -07001634 LOG(LS_ERROR) << "UseCandidate: Invalid candidate media index.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 return false;
1636 }
1637
1638 cricket::ContentInfo content =
deadbeeffe4a8a42016-12-20 17:56:17 -08001639 remote_description()->description()->contents()[mediacontent_index];
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640 std::vector<cricket::Candidate> candidates;
1641 candidates.push_back(candidate->candidate());
1642 // Invoking BaseSession method to handle remote candidates.
1643 std::string error;
deadbeefd59daf82015-10-14 15:02:44 -07001644 if (transport_controller_->AddRemoteCandidates(content.name, candidates,
1645 &error)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646 // Candidates successfully submitted for checking.
1647 if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
1648 ice_connection_state_ ==
1649 PeerConnectionInterface::kIceConnectionDisconnected) {
1650 // If state is New, then the session has just gotten its first remote ICE
1651 // candidates, so go to Checking.
1652 // If state is Disconnected, the session is re-using old candidates or
1653 // receiving additional ones, so go to Checking.
1654 // If state is Connected, stay Connected.
1655 // TODO(bemasc): If state is Connected, and the new candidates are for a
1656 // newly added transport, then the state actually _should_ move to
1657 // checking. Add a way to distinguish that case.
1658 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
1659 }
1660 // TODO(bemasc): If state is Completed, go back to Connected.
1661 } else {
fischman@webrtc.org4f2bd682014-03-28 18:13:34 +00001662 if (!error.empty()) {
1663 LOG(LS_WARNING) << error;
1664 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665 }
1666 return true;
1667}
1668
deadbeefcbecd352015-09-23 11:50:27 -07001669void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
Steve Anton169629a2017-08-30 17:36:36 -07001670 // TODO(steveanton): Add support for multiple audio/video channels.
1671 // Destroy video channel first since it may have a pointer to the
1672 // voice channel.
1673 const cricket::ContentInfo* video_info = cricket::GetFirstVideoContent(desc);
1674 if ((!video_info || video_info->rejected) && video_channel()) {
1675 RemoveAndDestroyVideoChannel(video_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001676 }
1677
Steve Anton169629a2017-08-30 17:36:36 -07001678 const cricket::ContentInfo* voice_info = cricket::GetFirstAudioContent(desc);
1679 if ((!voice_info || voice_info->rejected) && voice_channel()) {
1680 RemoveAndDestroyVoiceChannel(voice_channel());
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00001681 }
1682
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001683 const cricket::ContentInfo* data_info =
1684 cricket::GetFirstDataContent(desc);
zhihuang9763d562016-08-05 11:14:50 -07001685 if (!data_info || data_info->rejected) {
deadbeef953c2ce2017-01-09 14:53:41 -08001686 if (rtp_data_channel_) {
zhihuangf5b251b2017-01-12 19:37:48 -08001687 DestroyDataChannel();
deadbeef953c2ce2017-01-09 14:53:41 -08001688 }
1689 if (sctp_transport_) {
1690 SignalDataChannelDestroyed();
1691 network_thread_->Invoke<void>(
1692 RTC_FROM_HERE,
1693 rtc::Bind(&WebRtcSession::DestroySctpTransport_n, this));
zhihuang9763d562016-08-05 11:14:50 -07001694 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 }
1696}
1697
skvlad6c87a672016-05-17 17:49:52 -07001698// Returns the name of the transport channel when BUNDLE is enabled, or nullptr
1699// if the channel is not part of any bundle.
1700const std::string* WebRtcSession::GetBundleTransportName(
1701 const cricket::ContentInfo* content,
1702 const cricket::ContentGroup* bundle) {
1703 if (!bundle) {
1704 return nullptr;
1705 }
1706 const std::string* first_content_name = bundle->FirstContentName();
1707 if (!first_content_name) {
1708 LOG(LS_WARNING) << "Tried to BUNDLE with no contents.";
1709 return nullptr;
1710 }
1711 if (!bundle->HasContentName(content->name)) {
1712 LOG(LS_WARNING) << content->name << " is not part of any bundle group";
1713 return nullptr;
1714 }
1715 LOG(LS_INFO) << "Bundling " << content->name << " on " << *first_content_name;
1716 return first_content_name;
1717}
1718
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001719bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
Steve Anton169629a2017-08-30 17:36:36 -07001720 // TODO(steveanton): Add support for multiple audio/video channels.
skvlad6c87a672016-05-17 17:49:52 -07001721 const cricket::ContentGroup* bundle_group = nullptr;
1722 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) {
1723 bundle_group = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1724 if (!bundle_group) {
1725 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified";
1726 return false;
1727 }
1728 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001729 // Creating the media channels and transport proxies.
1730 const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc);
Steve Anton169629a2017-08-30 17:36:36 -07001731 if (voice && !voice->rejected && !voice_channel()) {
skvlad6c87a672016-05-17 17:49:52 -07001732 if (!CreateVoiceChannel(voice,
1733 GetBundleTransportName(voice, bundle_group))) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001734 LOG(LS_ERROR) << "Failed to create voice channel.";
1735 return false;
1736 }
1737 }
1738
1739 const cricket::ContentInfo* video = cricket::GetFirstVideoContent(desc);
Steve Anton169629a2017-08-30 17:36:36 -07001740 if (video && !video->rejected && !video_channel()) {
skvlad6c87a672016-05-17 17:49:52 -07001741 if (!CreateVideoChannel(video,
1742 GetBundleTransportName(video, bundle_group))) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001743 LOG(LS_ERROR) << "Failed to create video channel.";
1744 return false;
1745 }
1746 }
1747
1748 const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc);
deadbeef953c2ce2017-01-09 14:53:41 -08001749 if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected &&
1750 !rtp_data_channel_ && !sctp_transport_) {
skvlad6c87a672016-05-17 17:49:52 -07001751 if (!CreateDataChannel(data, GetBundleTransportName(data, bundle_group))) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001752 LOG(LS_ERROR) << "Failed to create data channel.";
1753 return false;
1754 }
1755 }
1756
1757 return true;
1758}
1759
skvlad6c87a672016-05-17 17:49:52 -07001760bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content,
1761 const std::string* bundle_transport) {
Steve Anton169629a2017-08-30 17:36:36 -07001762 // TODO(steveanton): Check to see if it's safe to create multiple voice
1763 // channels.
1764 RTC_DCHECK(voice_channels_.empty());
1765
skvlad6c87a672016-05-17 17:49:52 -07001766 bool require_rtcp_mux =
1767 rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
zhihuangf5b251b2017-01-12 19:37:48 -08001768
1769 std::string transport_name =
1770 bundle_transport ? *bundle_transport : content->name;
1771
zhihuangb2cdd932017-01-19 16:54:25 -08001772 cricket::DtlsTransportInternal* rtp_dtls_transport =
1773 transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001774 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001775 cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
deadbeefac22f702017-01-12 21:59:29 -08001776 if (!require_rtcp_mux) {
zhihuangb2cdd932017-01-19 16:54:25 -08001777 rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001778 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
1779 }
1780
Steve Anton169629a2017-08-30 17:36:36 -07001781 cricket::VoiceChannel* voice_channel = channel_manager_->CreateVoiceChannel(
nisseeaabdf62017-05-05 02:23:02 -07001782 call_, media_config_, rtp_dtls_transport, rtcp_dtls_transport,
deadbeef1a2183d2017-02-10 23:44:49 -08001783 transport_controller_->signaling_thread(), content->name, SrtpRequired(),
Steve Anton169629a2017-08-30 17:36:36 -07001784 audio_options_);
1785 if (!voice_channel) {
zhihuangb2cdd932017-01-19 16:54:25 -08001786 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08001787 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001788 if (rtcp_dtls_transport) {
1789 transport_controller_->DestroyDtlsTransport(
Steve Anton24efa722017-08-29 18:12:51 -07001790 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
deadbeefbad5dad2017-01-17 18:32:35 -08001791 }
wu@webrtc.orgde305012013-10-31 15:40:38 +00001792 return false;
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +00001793 }
zhihuangf5b251b2017-01-12 19:37:48 -08001794
Steve Anton169629a2017-08-30 17:36:36 -07001795 voice_channels_.push_back(voice_channel);
1796
1797 voice_channel->SignalRtcpMuxFullyActive.connect(
deadbeefac22f702017-01-12 21:59:29 -08001798 this, &WebRtcSession::DestroyRtcpTransport_n);
Steve Anton169629a2017-08-30 17:36:36 -07001799 voice_channel->SignalDtlsSrtpSetupFailure.connect(
deadbeef953c2ce2017-01-09 14:53:41 -08001800 this, &WebRtcSession::OnDtlsSrtpSetupFailure);
deadbeefab9b2d12015-10-14 11:33:11 -07001801
Steve Anton169629a2017-08-30 17:36:36 -07001802 // TODO(steveanton): This should signal which voice channel was created since
1803 // we can have multiple.
deadbeefab9b2d12015-10-14 11:33:11 -07001804 SignalVoiceChannelCreated();
Steve Anton169629a2017-08-30 17:36:36 -07001805 voice_channel->SignalSentPacket.connect(this, &WebRtcSession::OnSentPacket_w);
wu@webrtc.orgde305012013-10-31 15:40:38 +00001806 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807}
1808
skvlad6c87a672016-05-17 17:49:52 -07001809bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
1810 const std::string* bundle_transport) {
Steve Anton169629a2017-08-30 17:36:36 -07001811 // TODO(steveanton): Check to see if it's safe to create multiple video
1812 // channels.
1813 RTC_DCHECK(video_channels_.empty());
1814
skvlad6c87a672016-05-17 17:49:52 -07001815 bool require_rtcp_mux =
1816 rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
zhihuangf5b251b2017-01-12 19:37:48 -08001817
1818 std::string transport_name =
1819 bundle_transport ? *bundle_transport : content->name;
1820
zhihuangb2cdd932017-01-19 16:54:25 -08001821 cricket::DtlsTransportInternal* rtp_dtls_transport =
1822 transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001823 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001824 cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
deadbeefac22f702017-01-12 21:59:29 -08001825 if (!require_rtcp_mux) {
zhihuangb2cdd932017-01-19 16:54:25 -08001826 rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001827 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
1828 }
1829
Steve Anton169629a2017-08-30 17:36:36 -07001830 cricket::VideoChannel* video_channel = channel_manager_->CreateVideoChannel(
nisseeaabdf62017-05-05 02:23:02 -07001831 call_, media_config_, rtp_dtls_transport, rtcp_dtls_transport,
deadbeef1a2183d2017-02-10 23:44:49 -08001832 transport_controller_->signaling_thread(), content->name, SrtpRequired(),
Steve Anton169629a2017-08-30 17:36:36 -07001833 video_options_);
zhihuangf5b251b2017-01-12 19:37:48 -08001834
Steve Anton169629a2017-08-30 17:36:36 -07001835 if (!video_channel) {
zhihuangb2cdd932017-01-19 16:54:25 -08001836 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08001837 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001838 if (rtcp_dtls_transport) {
1839 transport_controller_->DestroyDtlsTransport(
Steve Anton24efa722017-08-29 18:12:51 -07001840 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
deadbeefbad5dad2017-01-17 18:32:35 -08001841 }
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +00001842 return false;
1843 }
zhihuangf5b251b2017-01-12 19:37:48 -08001844
Steve Anton169629a2017-08-30 17:36:36 -07001845 video_channels_.push_back(video_channel);
1846
1847 video_channel->SignalRtcpMuxFullyActive.connect(
deadbeefac22f702017-01-12 21:59:29 -08001848 this, &WebRtcSession::DestroyRtcpTransport_n);
Steve Anton169629a2017-08-30 17:36:36 -07001849 video_channel->SignalDtlsSrtpSetupFailure.connect(
deadbeef953c2ce2017-01-09 14:53:41 -08001850 this, &WebRtcSession::OnDtlsSrtpSetupFailure);
deadbeefab9b2d12015-10-14 11:33:11 -07001851
Steve Anton169629a2017-08-30 17:36:36 -07001852 // TODO(steveanton): This should signal which video channel was created since
1853 // we can have multiple.
deadbeefab9b2d12015-10-14 11:33:11 -07001854 SignalVideoChannelCreated();
Steve Anton169629a2017-08-30 17:36:36 -07001855 video_channel->SignalSentPacket.connect(this, &WebRtcSession::OnSentPacket_w);
pthatcher@webrtc.org4eeef582015-03-16 19:34:23 +00001856 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001857}
1858
skvlad6c87a672016-05-17 17:49:52 -07001859bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content,
1860 const std::string* bundle_transport) {
deadbeef953c2ce2017-01-09 14:53:41 -08001861 const std::string transport_name =
1862 bundle_transport ? *bundle_transport : content->name;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001863 bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
deadbeefc0dad892017-01-04 20:28:21 -08001864 if (sctp) {
deadbeef953c2ce2017-01-09 14:53:41 -08001865 if (!sctp_factory_) {
1866 LOG(LS_ERROR)
1867 << "Trying to create SCTP transport, but didn't compile with "
1868 "SCTP support (HAVE_SCTP)";
1869 return false;
1870 }
1871 if (!network_thread_->Invoke<bool>(
1872 RTC_FROM_HERE, rtc::Bind(&WebRtcSession::CreateSctpTransport_n,
1873 this, content->name, transport_name))) {
1874 return false;
Steve Anton36b29d12017-10-30 09:57:42 -07001875 }
deadbeef953c2ce2017-01-09 14:53:41 -08001876 } else {
1877 bool require_rtcp_mux =
1878 rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
zhihuangf5b251b2017-01-12 19:37:48 -08001879
1880 std::string transport_name =
1881 bundle_transport ? *bundle_transport : content->name;
zhihuangb2cdd932017-01-19 16:54:25 -08001882 cricket::DtlsTransportInternal* rtp_dtls_transport =
1883 transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001884 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001885 cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
deadbeefac22f702017-01-12 21:59:29 -08001886 if (!require_rtcp_mux) {
zhihuangb2cdd932017-01-19 16:54:25 -08001887 rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
zhihuangf5b251b2017-01-12 19:37:48 -08001888 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
1889 }
1890
deadbeef953c2ce2017-01-09 14:53:41 -08001891 rtp_data_channel_.reset(channel_manager_->CreateRtpDataChannel(
nisseeaabdf62017-05-05 02:23:02 -07001892 media_config_, rtp_dtls_transport, rtcp_dtls_transport,
zhihuangf5b251b2017-01-12 19:37:48 -08001893 transport_controller_->signaling_thread(), content->name,
deadbeef1a2183d2017-02-10 23:44:49 -08001894 SrtpRequired()));
zhihuangf5b251b2017-01-12 19:37:48 -08001895
deadbeef953c2ce2017-01-09 14:53:41 -08001896 if (!rtp_data_channel_) {
zhihuangb2cdd932017-01-19 16:54:25 -08001897 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08001898 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangb2cdd932017-01-19 16:54:25 -08001899 if (rtcp_dtls_transport) {
1900 transport_controller_->DestroyDtlsTransport(
Steve Anton24efa722017-08-29 18:12:51 -07001901 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
deadbeefbad5dad2017-01-17 18:32:35 -08001902 }
deadbeef953c2ce2017-01-09 14:53:41 -08001903 return false;
1904 }
zhihuangf5b251b2017-01-12 19:37:48 -08001905
deadbeefac22f702017-01-12 21:59:29 -08001906 rtp_data_channel_->SignalRtcpMuxFullyActive.connect(
1907 this, &WebRtcSession::DestroyRtcpTransport_n);
deadbeef953c2ce2017-01-09 14:53:41 -08001908 rtp_data_channel_->SignalDtlsSrtpSetupFailure.connect(
1909 this, &WebRtcSession::OnDtlsSrtpSetupFailure);
1910 rtp_data_channel_->SignalSentPacket.connect(this,
1911 &WebRtcSession::OnSentPacket_w);
deadbeefc0dad892017-01-04 20:28:21 -08001912 }
1913
deadbeefab9b2d12015-10-14 11:33:11 -07001914 SignalDataChannelCreated();
zhihuangf5b251b2017-01-12 19:37:48 -08001915
wu@webrtc.org91053e72013-08-10 07:18:04 +00001916 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917}
1918
stefanf79ade12017-06-02 06:44:03 -07001919Call::Stats WebRtcSession::GetCallStats() {
1920 if (!worker_thread()->IsCurrent()) {
1921 return worker_thread()->Invoke<Call::Stats>(
1922 RTC_FROM_HERE, rtc::Bind(&WebRtcSession::GetCallStats, this));
1923 }
zhihuang38ede132017-06-15 12:52:32 -07001924 if (!call_)
1925 return Call::Stats();
stefanf79ade12017-06-02 06:44:03 -07001926 return call_->GetStats();
1927}
1928
hbosdf6075a2016-12-19 04:58:02 -08001929std::unique_ptr<SessionStats> WebRtcSession::GetStats_n(
1930 const ChannelNamePairs& channel_name_pairs) {
nisseede5da42017-01-12 05:15:36 -08001931 RTC_DCHECK(network_thread()->IsCurrent());
hbosdf6075a2016-12-19 04:58:02 -08001932 std::unique_ptr<SessionStats> session_stats(new SessionStats());
1933 for (const auto channel_name_pair : { &channel_name_pairs.voice,
1934 &channel_name_pairs.video,
1935 &channel_name_pairs.data }) {
1936 if (*channel_name_pair) {
1937 cricket::TransportStats transport_stats;
1938 if (!transport_controller_->GetStats((*channel_name_pair)->transport_name,
1939 &transport_stats)) {
1940 return nullptr;
1941 }
1942 session_stats->proxy_to_transport[(*channel_name_pair)->content_name] =
1943 (*channel_name_pair)->transport_name;
1944 session_stats->transport_stats[(*channel_name_pair)->transport_name] =
1945 std::move(transport_stats);
1946 }
1947 }
1948 return session_stats;
1949}
1950
deadbeef953c2ce2017-01-09 14:53:41 -08001951bool WebRtcSession::CreateSctpTransport_n(const std::string& content_name,
1952 const std::string& transport_name) {
1953 RTC_DCHECK(network_thread_->IsCurrent());
1954 RTC_DCHECK(sctp_factory_);
zhihuangb2cdd932017-01-19 16:54:25 -08001955 cricket::DtlsTransportInternal* tc =
1956 transport_controller_->CreateDtlsTransport_n(
deadbeef953c2ce2017-01-09 14:53:41 -08001957 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
1958 sctp_transport_ = sctp_factory_->CreateSctpTransport(tc);
1959 RTC_DCHECK(sctp_transport_);
1960 sctp_invoker_.reset(new rtc::AsyncInvoker());
1961 sctp_transport_->SignalReadyToSendData.connect(
1962 this, &WebRtcSession::OnSctpTransportReadyToSendData_n);
1963 sctp_transport_->SignalDataReceived.connect(
1964 this, &WebRtcSession::OnSctpTransportDataReceived_n);
1965 sctp_transport_->SignalStreamClosedRemotely.connect(
1966 this, &WebRtcSession::OnSctpStreamClosedRemotely_n);
1967 sctp_transport_name_ = rtc::Optional<std::string>(transport_name);
1968 sctp_content_name_ = rtc::Optional<std::string>(content_name);
1969 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001970}
1971
deadbeef953c2ce2017-01-09 14:53:41 -08001972void WebRtcSession::ChangeSctpTransport_n(const std::string& transport_name) {
1973 RTC_DCHECK(network_thread_->IsCurrent());
1974 RTC_DCHECK(sctp_transport_);
1975 RTC_DCHECK(sctp_transport_name_);
1976 std::string old_sctp_transport_name = *sctp_transport_name_;
1977 sctp_transport_name_ = rtc::Optional<std::string>(transport_name);
zhihuangb2cdd932017-01-19 16:54:25 -08001978 cricket::DtlsTransportInternal* tc =
1979 transport_controller_->CreateDtlsTransport_n(
deadbeef953c2ce2017-01-09 14:53:41 -08001980 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
1981 sctp_transport_->SetTransportChannel(tc);
zhihuangb2cdd932017-01-19 16:54:25 -08001982 transport_controller_->DestroyDtlsTransport_n(
deadbeef953c2ce2017-01-09 14:53:41 -08001983 old_sctp_transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
1984}
1985
1986void WebRtcSession::DestroySctpTransport_n() {
1987 RTC_DCHECK(network_thread_->IsCurrent());
1988 sctp_transport_.reset(nullptr);
1989 sctp_content_name_.reset();
1990 sctp_transport_name_.reset();
1991 sctp_invoker_.reset(nullptr);
1992 sctp_ready_to_send_data_ = false;
1993}
1994
1995void WebRtcSession::OnSctpTransportReadyToSendData_n() {
1996 RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
1997 RTC_DCHECK(network_thread_->IsCurrent());
1998 sctp_invoker_->AsyncInvoke<void>(
1999 RTC_FROM_HERE, signaling_thread_,
2000 rtc::Bind(&WebRtcSession::OnSctpTransportReadyToSendData_s, this, true));
2001}
2002
2003void WebRtcSession::OnSctpTransportReadyToSendData_s(bool ready) {
2004 RTC_DCHECK(signaling_thread_->IsCurrent());
2005 sctp_ready_to_send_data_ = ready;
2006 SignalSctpReadyToSendData(ready);
2007}
2008
2009void WebRtcSession::OnSctpTransportDataReceived_n(
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00002010 const cricket::ReceiveDataParams& params,
jbaucheec21bd2016-03-20 06:15:43 -07002011 const rtc::CopyOnWriteBuffer& payload) {
deadbeefab9b2d12015-10-14 11:33:11 -07002012 RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
deadbeef953c2ce2017-01-09 14:53:41 -08002013 RTC_DCHECK(network_thread_->IsCurrent());
2014 sctp_invoker_->AsyncInvoke<void>(
2015 RTC_FROM_HERE, signaling_thread_,
2016 rtc::Bind(&WebRtcSession::OnSctpTransportDataReceived_s, this, params,
2017 payload));
2018}
2019
2020void WebRtcSession::OnSctpTransportDataReceived_s(
2021 const cricket::ReceiveDataParams& params,
2022 const rtc::CopyOnWriteBuffer& payload) {
2023 RTC_DCHECK(signaling_thread_->IsCurrent());
deadbeefab9b2d12015-10-14 11:33:11 -07002024 if (params.type == cricket::DMT_CONTROL && IsOpenMessage(payload)) {
2025 // Received OPEN message; parse and signal that a new data channel should
2026 // be created.
2027 std::string label;
2028 InternalDataChannelInit config;
2029 config.id = params.ssrc;
2030 if (!ParseDataChannelOpenMessage(payload, &label, &config)) {
2031 LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
2032 << params.ssrc;
2033 return;
2034 }
2035 config.open_handshake_role = InternalDataChannelInit::kAcker;
2036 SignalDataChannelOpenMessage(label, config);
deadbeef953c2ce2017-01-09 14:53:41 -08002037 } else {
2038 // Otherwise just forward the signal.
2039 SignalSctpDataReceived(params, payload);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040 }
deadbeef953c2ce2017-01-09 14:53:41 -08002041}
2042
2043void WebRtcSession::OnSctpStreamClosedRemotely_n(int sid) {
2044 RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
2045 RTC_DCHECK(network_thread_->IsCurrent());
2046 sctp_invoker_->AsyncInvoke<void>(
2047 RTC_FROM_HERE, signaling_thread_,
2048 rtc::Bind(&sigslot::signal1<int>::operator(),
2049 &SignalSctpStreamClosedRemotely, sid));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050}
2051
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002052// Returns false if bundle is enabled and rtcp_mux is disabled.
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002053bool WebRtcSession::ValidateBundleSettings(const SessionDescription* desc) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002054 bool bundle_enabled = desc->HasGroup(cricket::GROUP_TYPE_BUNDLE);
2055 if (!bundle_enabled)
2056 return true;
2057
2058 const cricket::ContentGroup* bundle_group =
2059 desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
nisseede5da42017-01-12 05:15:36 -08002060 RTC_DCHECK(bundle_group != NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002061
2062 const cricket::ContentInfos& contents = desc->contents();
2063 for (cricket::ContentInfos::const_iterator citer = contents.begin();
2064 citer != contents.end(); ++citer) {
2065 const cricket::ContentInfo* content = (&*citer);
nisseede5da42017-01-12 05:15:36 -08002066 RTC_DCHECK(content != NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002067 if (bundle_group->HasContentName(content->name) &&
2068 !content->rejected && content->type == cricket::NS_JINGLE_RTP) {
2069 if (!HasRtcpMuxEnabled(content))
2070 return false;
2071 }
2072 }
2073 // RTCP-MUX is enabled in all the contents.
2074 return true;
2075}
2076
2077bool WebRtcSession::HasRtcpMuxEnabled(
2078 const cricket::ContentInfo* content) {
2079 const cricket::MediaContentDescription* description =
2080 static_cast<cricket::MediaContentDescription*>(content->description);
2081 return description->rtcp_mux();
2082}
2083
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002084bool WebRtcSession::ValidateSessionDescription(
2085 const SessionDescriptionInterface* sdesc,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002086 cricket::ContentSource source, std::string* err_desc) {
2087 std::string type;
deadbeefd59daf82015-10-14 15:02:44 -07002088 if (error() != ERROR_NONE) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002089 return BadSdp(source, type, GetSessionErrorMsg(), err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002090 }
2091
2092 if (!sdesc || !sdesc->description()) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002093 return BadSdp(source, type, kInvalidSdp, err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002094 }
2095
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002096 type = sdesc->type();
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002097 Action action = GetAction(sdesc->type());
2098 if (source == cricket::CS_LOCAL) {
2099 if (!ExpectSetLocalDescription(action))
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002100 return BadLocalSdp(type, BadStateErrMsg(state()), err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002101 } else {
2102 if (!ExpectSetRemoteDescription(action))
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002103 return BadRemoteSdp(type, BadStateErrMsg(state()), err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002104 }
2105
2106 // Verify crypto settings.
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00002107 std::string crypto_error;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002108 if ((webrtc_session_desc_factory_->SdesPolicy() == cricket::SEC_REQUIRED ||
2109 dtls_enabled_) &&
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00002110 !VerifyCrypto(sdesc->description(), dtls_enabled_, &crypto_error)) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002111 return BadSdp(source, type, crypto_error, err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002112 }
2113
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002114 // Verify ice-ufrag and ice-pwd.
2115 if (!VerifyIceUfragPwdPresent(sdesc->description())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002116 return BadSdp(source, type, kSdpWithoutIceUfragPwd, err_desc);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002117 }
2118
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002119 if (!ValidateBundleSettings(sdesc->description())) {
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002120 return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002121 }
2122
skvlad6c87a672016-05-17 17:49:52 -07002123 // TODO(skvlad): When the local rtcp-mux policy is Require, reject any
2124 // m-lines that do not rtcp-mux enabled.
2125
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002126 // Verify m-lines in Answer when compared against Offer.
Zhi Huang2a5e4262017-09-14 01:15:03 -07002127 if (action == kAnswer || action == kPrAnswer) {
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002128 const cricket::SessionDescription* offer_desc =
deadbeeffe4a8a42016-12-20 17:56:17 -08002129 (source == cricket::CS_LOCAL) ? remote_description()->description()
2130 : local_description()->description();
Zhi Huangb2d355e2017-10-26 17:26:37 -07002131 if (!MediaSectionsHaveSameCount(offer_desc, sdesc->description()) ||
2132 !MediaSectionsInSameOrder(offer_desc, sdesc->description())) {
Zhi Huang2a5e4262017-09-14 01:15:03 -07002133 return BadAnswerSdp(source, kMlineMismatchInAnswer, err_desc);
2134 }
2135 } else {
Zhi Huangb2d355e2017-10-26 17:26:37 -07002136 const cricket::SessionDescription* current_desc = nullptr;
2137 if (source == cricket::CS_LOCAL && local_description()) {
2138 current_desc = local_description()->description();
2139 } else if (source == cricket::CS_REMOTE && remote_description()) {
2140 current_desc = remote_description()->description();
2141 }
2142 // The re-offers should respect the order of m= sections in current
Zhi Huang2a5e4262017-09-14 01:15:03 -07002143 // description. See RFC3264 Section 8 paragraph 4 for more details.
Zhi Huangb2d355e2017-10-26 17:26:37 -07002144 if (current_desc &&
2145 !MediaSectionsInSameOrder(current_desc, sdesc->description())) {
Zhi Huang2a5e4262017-09-14 01:15:03 -07002146 return BadOfferSdp(source, kMlineMismatchInSubsequentOffer, err_desc);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002147 }
2148 }
2149
2150 return true;
2151}
2152
2153bool WebRtcSession::ExpectSetLocalDescription(Action action) {
2154 return ((action == kOffer && state() == STATE_INIT) ||
2155 // update local offer
deadbeefd59daf82015-10-14 15:02:44 -07002156 (action == kOffer && state() == STATE_SENTOFFER) ||
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002157 // update the current ongoing session.
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002158 (action == kOffer && state() == STATE_INPROGRESS) ||
2159 // accept remote offer
deadbeefd59daf82015-10-14 15:02:44 -07002160 (action == kAnswer && state() == STATE_RECEIVEDOFFER) ||
2161 (action == kAnswer && state() == STATE_SENTPRANSWER) ||
2162 (action == kPrAnswer && state() == STATE_RECEIVEDOFFER) ||
2163 (action == kPrAnswer && state() == STATE_SENTPRANSWER));
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002164}
2165
2166bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
2167 return ((action == kOffer && state() == STATE_INIT) ||
2168 // update remote offer
deadbeefd59daf82015-10-14 15:02:44 -07002169 (action == kOffer && state() == STATE_RECEIVEDOFFER) ||
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002170 // update the current ongoing session
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002171 (action == kOffer && state() == STATE_INPROGRESS) ||
2172 // accept local offer
deadbeefd59daf82015-10-14 15:02:44 -07002173 (action == kAnswer && state() == STATE_SENTOFFER) ||
2174 (action == kAnswer && state() == STATE_RECEIVEDPRANSWER) ||
2175 (action == kPrAnswer && state() == STATE_SENTOFFER) ||
2176 (action == kPrAnswer && state() == STATE_RECEIVEDPRANSWER));
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +00002177}
2178
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002179std::string WebRtcSession::GetSessionErrorMsg() {
2180 std::ostringstream desc;
2181 desc << kSessionError << GetErrorCodeString(error()) << ". ";
2182 desc << kSessionErrorDesc << error_desc() << ".";
2183 return desc.str();
2184}
2185
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002186// We need to check the local/remote description for the Transport instead of
2187// the session, because a new Transport added during renegotiation may have
2188// them unset while the session has them set from the previous negotiation.
2189// Not doing so may trigger the auto generation of transport description and
2190// mess up DTLS identity information, ICE credential, etc.
2191bool WebRtcSession::ReadyToUseRemoteCandidate(
2192 const IceCandidateInterface* candidate,
2193 const SessionDescriptionInterface* remote_desc,
2194 bool* valid) {
zhihuang9763d562016-08-05 11:14:50 -07002195 *valid = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002196
2197 const SessionDescriptionInterface* current_remote_desc =
deadbeeffe4a8a42016-12-20 17:56:17 -08002198 remote_desc ? remote_desc : remote_description();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002199
deadbeefd59daf82015-10-14 15:02:44 -07002200 if (!current_remote_desc) {
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002201 return false;
deadbeefd59daf82015-10-14 15:02:44 -07002202 }
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002203
2204 size_t mediacontent_index =
2205 static_cast<size_t>(candidate->sdp_mline_index());
2206 size_t remote_content_size =
2207 current_remote_desc->description()->contents().size();
2208 if (mediacontent_index >= remote_content_size) {
Honghai Zhang7fb69db2016-03-14 11:59:18 -07002209 LOG(LS_ERROR) << "ReadyToUseRemoteCandidate: Invalid candidate media index "
2210 << mediacontent_index;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002211
2212 *valid = false;
2213 return false;
2214 }
2215
2216 cricket::ContentInfo content =
2217 current_remote_desc->description()->contents()[mediacontent_index];
zhihuang9763d562016-08-05 11:14:50 -07002218
2219 const std::string transport_name = GetTransportName(content.name);
2220 if (transport_name.empty()) {
deadbeefcbecd352015-09-23 11:50:27 -07002221 return false;
2222 }
zhihuang9763d562016-08-05 11:14:50 -07002223 return transport_controller_->ReadyForRemoteCandidates(transport_name);
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00002224}
2225
deadbeef7af91dd2016-12-13 11:29:11 -08002226bool WebRtcSession::SrtpRequired() const {
2227 return dtls_enabled_ ||
2228 webrtc_session_desc_factory_->SdesPolicy() == cricket::SEC_REQUIRED;
2229}
2230
deadbeefcbecd352015-09-23 11:50:27 -07002231void WebRtcSession::OnTransportControllerGatheringState(
2232 cricket::IceGatheringState state) {
nisseede5da42017-01-12 05:15:36 -08002233 RTC_DCHECK(signaling_thread()->IsCurrent());
deadbeefcbecd352015-09-23 11:50:27 -07002234 if (state == cricket::kIceGatheringGathering) {
2235 if (ice_observer_) {
2236 ice_observer_->OnIceGatheringChange(
2237 PeerConnectionInterface::kIceGatheringGathering);
2238 }
2239 } else if (state == cricket::kIceGatheringComplete) {
2240 if (ice_observer_) {
2241 ice_observer_->OnIceGatheringChange(
2242 PeerConnectionInterface::kIceGatheringComplete);
deadbeefcbecd352015-09-23 11:50:27 -07002243 }
2244 }
2245}
2246
2247void WebRtcSession::ReportTransportStats() {
2248 // Use a set so we don't report the same stats twice if two channels share
2249 // a transport.
2250 std::set<std::string> transport_names;
2251 if (voice_channel()) {
2252 transport_names.insert(voice_channel()->transport_name());
2253 }
2254 if (video_channel()) {
2255 transport_names.insert(video_channel()->transport_name());
2256 }
deadbeef953c2ce2017-01-09 14:53:41 -08002257 if (rtp_data_channel()) {
2258 transport_names.insert(rtp_data_channel()->transport_name());
2259 }
2260 if (sctp_transport_name_) {
2261 transport_names.insert(*sctp_transport_name_);
deadbeefcbecd352015-09-23 11:50:27 -07002262 }
2263 for (const auto& name : transport_names) {
2264 cricket::TransportStats stats;
deadbeefd59daf82015-10-14 15:02:44 -07002265 if (transport_controller_->GetStats(name, &stats)) {
deadbeefcbecd352015-09-23 11:50:27 -07002266 ReportBestConnectionState(stats);
2267 ReportNegotiatedCiphers(stats);
2268 }
2269 }
2270}
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002271// Walk through the ConnectionInfos to gather best connection usage
2272// for IPv4 and IPv6.
jbauchac8869e2015-07-03 01:36:14 -07002273void WebRtcSession::ReportBestConnectionState(
2274 const cricket::TransportStats& stats) {
henrikg91d6ede2015-09-17 00:24:34 -07002275 RTC_DCHECK(metrics_observer_ != NULL);
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002276 for (cricket::TransportChannelStatsList::const_iterator it =
2277 stats.channel_stats.begin();
2278 it != stats.channel_stats.end(); ++it) {
2279 for (cricket::ConnectionInfos::const_iterator it_info =
2280 it->connection_infos.begin();
2281 it_info != it->connection_infos.end(); ++it_info) {
2282 if (!it_info->best_connection) {
2283 continue;
2284 }
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07002285
2286 PeerConnectionEnumCounterType type = kPeerConnectionEnumCounterMax;
2287 const cricket::Candidate& local = it_info->local_candidate;
2288 const cricket::Candidate& remote = it_info->remote_candidate;
2289
2290 // Increment the counter for IceCandidatePairType.
2291 if (local.protocol() == cricket::TCP_PROTOCOL_NAME ||
2292 (local.type() == RELAY_PORT_TYPE &&
2293 local.relay_protocol() == cricket::TCP_PROTOCOL_NAME)) {
2294 type = kEnumCounterIceCandidatePairTypeTcp;
2295 } else if (local.protocol() == cricket::UDP_PROTOCOL_NAME) {
2296 type = kEnumCounterIceCandidatePairTypeUdp;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002297 } else {
henrikg91d6ede2015-09-17 00:24:34 -07002298 RTC_CHECK(0);
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002299 }
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07002300 metrics_observer_->IncrementEnumCounter(
2301 type, GetIceCandidatePairCounter(local, remote),
2302 kIceCandidatePairMax);
2303
2304 // Increment the counter for IP type.
2305 if (local.address().family() == AF_INET) {
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07002306 metrics_observer_->IncrementEnumCounter(
2307 kEnumCounterAddressFamily, kBestConnections_IPv4,
2308 kPeerConnectionAddressFamilyCounter_Max);
2309
2310 } else if (local.address().family() == AF_INET6) {
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07002311 metrics_observer_->IncrementEnumCounter(
2312 kEnumCounterAddressFamily, kBestConnections_IPv6,
2313 kPeerConnectionAddressFamilyCounter_Max);
2314 } else {
henrikg91d6ede2015-09-17 00:24:34 -07002315 RTC_CHECK(0);
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07002316 }
2317
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00002318 return;
2319 }
2320 }
2321}
2322
jbauchac8869e2015-07-03 01:36:14 -07002323void WebRtcSession::ReportNegotiatedCiphers(
2324 const cricket::TransportStats& stats) {
henrikg91d6ede2015-09-17 00:24:34 -07002325 RTC_DCHECK(metrics_observer_ != NULL);
jbauchac8869e2015-07-03 01:36:14 -07002326 if (!dtls_enabled_ || stats.channel_stats.empty()) {
2327 return;
2328 }
2329
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002330 int srtp_crypto_suite = stats.channel_stats[0].srtp_crypto_suite;
2331 int ssl_cipher_suite = stats.channel_stats[0].ssl_cipher_suite;
2332 if (srtp_crypto_suite == rtc::SRTP_INVALID_CRYPTO_SUITE &&
2333 ssl_cipher_suite == rtc::TLS_NULL_WITH_NULL_NULL) {
jbauchac8869e2015-07-03 01:36:14 -07002334 return;
2335 }
2336
Guo-wei Shieh456696a2015-09-30 21:48:54 -07002337 PeerConnectionEnumCounterType srtp_counter_type;
2338 PeerConnectionEnumCounterType ssl_counter_type;
deadbeefcbecd352015-09-23 11:50:27 -07002339 if (stats.transport_name == cricket::CN_AUDIO) {
Guo-wei Shieh456696a2015-09-30 21:48:54 -07002340 srtp_counter_type = kEnumCounterAudioSrtpCipher;
2341 ssl_counter_type = kEnumCounterAudioSslCipher;
deadbeefcbecd352015-09-23 11:50:27 -07002342 } else if (stats.transport_name == cricket::CN_VIDEO) {
Guo-wei Shieh456696a2015-09-30 21:48:54 -07002343 srtp_counter_type = kEnumCounterVideoSrtpCipher;
2344 ssl_counter_type = kEnumCounterVideoSslCipher;
deadbeefcbecd352015-09-23 11:50:27 -07002345 } else if (stats.transport_name == cricket::CN_DATA) {
Guo-wei Shieh456696a2015-09-30 21:48:54 -07002346 srtp_counter_type = kEnumCounterDataSrtpCipher;
2347 ssl_counter_type = kEnumCounterDataSslCipher;
jbauchac8869e2015-07-03 01:36:14 -07002348 } else {
2349 RTC_NOTREACHED();
2350 return;
2351 }
2352
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002353 if (srtp_crypto_suite != rtc::SRTP_INVALID_CRYPTO_SUITE) {
2354 metrics_observer_->IncrementSparseEnumCounter(srtp_counter_type,
2355 srtp_crypto_suite);
jbauchac8869e2015-07-03 01:36:14 -07002356 }
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -08002357 if (ssl_cipher_suite != rtc::TLS_NULL_WITH_NULL_NULL) {
2358 metrics_observer_->IncrementSparseEnumCounter(ssl_counter_type,
2359 ssl_cipher_suite);
jbauchac8869e2015-07-03 01:36:14 -07002360 }
2361}
2362
Danil Chapovalov33b01f22016-05-11 19:55:27 +02002363void WebRtcSession::OnSentPacket_w(const rtc::SentPacket& sent_packet) {
stefanc1aeaf02015-10-15 07:26:07 -07002364 RTC_DCHECK(worker_thread()->IsCurrent());
stefanf79ade12017-06-02 06:44:03 -07002365 RTC_DCHECK(call_);
nisseeaabdf62017-05-05 02:23:02 -07002366 call_->OnSentPacket(sent_packet);
stefanc1aeaf02015-10-15 07:26:07 -07002367}
2368
zhihuang9763d562016-08-05 11:14:50 -07002369const std::string WebRtcSession::GetTransportName(
2370 const std::string& content_name) {
2371 cricket::BaseChannel* channel = GetChannel(content_name);
2372 if (!channel) {
deadbeef953c2ce2017-01-09 14:53:41 -08002373 if (sctp_transport_) {
2374 RTC_DCHECK(sctp_content_name_);
2375 RTC_DCHECK(sctp_transport_name_);
2376 if (content_name == *sctp_content_name_) {
2377 return *sctp_transport_name_;
2378 }
2379 }
zhihuang9763d562016-08-05 11:14:50 -07002380 // Return an empty string if failed to retrieve the transport name.
2381 return "";
2382 }
2383 return channel->transport_name();
2384}
zhihuangd82eee02016-08-26 11:25:05 -07002385
deadbeefac22f702017-01-12 21:59:29 -08002386void WebRtcSession::DestroyRtcpTransport_n(const std::string& transport_name) {
nissea9dd4a12017-01-13 07:08:34 -08002387 RTC_DCHECK(network_thread()->IsCurrent());
zhihuangb2cdd932017-01-19 16:54:25 -08002388 transport_controller_->DestroyDtlsTransport_n(
zhihuangf5b251b2017-01-12 19:37:48 -08002389 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
2390}
2391
Steve Anton169629a2017-08-30 17:36:36 -07002392void WebRtcSession::RemoveAndDestroyVideoChannel(
2393 cricket::VideoChannel* video_channel) {
2394 auto it =
2395 std::find(video_channels_.begin(), video_channels_.end(), video_channel);
2396 RTC_DCHECK(it != video_channels_.end());
2397 if (it == video_channels_.end()) {
2398 return;
2399 }
2400 video_channels_.erase(it);
2401 DestroyVideoChannel(video_channel);
2402}
2403
2404void WebRtcSession::DestroyVideoChannel(cricket::VideoChannel* video_channel) {
2405 // TODO(steveanton): This should take an identifier for the video channel
2406 // since we now support more than one.
zhihuangf5b251b2017-01-12 19:37:48 -08002407 SignalVideoChannelDestroyed();
Steve Anton169629a2017-08-30 17:36:36 -07002408 RTC_DCHECK(video_channel->rtp_dtls_transport());
2409 const std::string transport_name =
2410 video_channel->rtp_dtls_transport()->transport_name();
2411 const bool need_to_delete_rtcp =
2412 (video_channel->rtcp_dtls_transport() != nullptr);
2413 // The above need to be cached before destroying the video channel so that we
2414 // do not access uninitialized memory.
2415 channel_manager_->DestroyVideoChannel(video_channel);
zhihuangb2cdd932017-01-19 16:54:25 -08002416 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08002417 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangf5b251b2017-01-12 19:37:48 -08002418 if (need_to_delete_rtcp) {
zhihuangb2cdd932017-01-19 16:54:25 -08002419 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08002420 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
zhihuangf5b251b2017-01-12 19:37:48 -08002421 }
2422}
2423
Steve Anton169629a2017-08-30 17:36:36 -07002424void WebRtcSession::RemoveAndDestroyVoiceChannel(
2425 cricket::VoiceChannel* voice_channel) {
2426 auto it =
2427 std::find(voice_channels_.begin(), voice_channels_.end(), voice_channel);
2428 RTC_DCHECK(it != voice_channels_.end());
2429 if (it == voice_channels_.end()) {
2430 return;
2431 }
2432 voice_channels_.erase(it);
2433 DestroyVoiceChannel(voice_channel);
2434}
2435
2436void WebRtcSession::DestroyVoiceChannel(cricket::VoiceChannel* voice_channel) {
2437 // TODO(steveanton): This should take an identifier for the voice channel
2438 // since we now support more than one.
zhihuangf5b251b2017-01-12 19:37:48 -08002439 SignalVoiceChannelDestroyed();
Steve Anton169629a2017-08-30 17:36:36 -07002440 RTC_DCHECK(voice_channel->rtp_dtls_transport());
2441 const std::string transport_name =
2442 voice_channel->rtp_dtls_transport()->transport_name();
2443 const bool need_to_delete_rtcp =
2444 (voice_channel->rtcp_dtls_transport() != nullptr);
2445 // The above need to be cached before destroying the video channel so that we
2446 // do not access uninitialized memory.
2447 channel_manager_->DestroyVoiceChannel(voice_channel);
zhihuangb2cdd932017-01-19 16:54:25 -08002448 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08002449 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangf5b251b2017-01-12 19:37:48 -08002450 if (need_to_delete_rtcp) {
zhihuangb2cdd932017-01-19 16:54:25 -08002451 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08002452 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
zhihuangf5b251b2017-01-12 19:37:48 -08002453 }
2454}
2455
2456void WebRtcSession::DestroyDataChannel() {
2457 SignalDataChannelDestroyed();
zhihuangb2cdd932017-01-19 16:54:25 -08002458 RTC_DCHECK(rtp_data_channel_->rtp_dtls_transport());
zhihuangf5b251b2017-01-12 19:37:48 -08002459 std::string transport_name;
zhihuangb2cdd932017-01-19 16:54:25 -08002460 transport_name = rtp_data_channel_->rtp_dtls_transport()->transport_name();
2461 bool need_to_delete_rtcp =
2462 (rtp_data_channel_->rtcp_dtls_transport() != nullptr);
zhihuangf5b251b2017-01-12 19:37:48 -08002463 channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
zhihuangb2cdd932017-01-19 16:54:25 -08002464 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08002465 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
zhihuangf5b251b2017-01-12 19:37:48 -08002466 if (need_to_delete_rtcp) {
zhihuangb2cdd932017-01-19 16:54:25 -08002467 transport_controller_->DestroyDtlsTransport(
deadbeefbad5dad2017-01-17 18:32:35 -08002468 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
zhihuangf5b251b2017-01-12 19:37:48 -08002469 }
2470}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002471} // namespace webrtc