blob: beb8d1e5a1bb86b7b04722f9baa329d433e206f7 [file] [log] [blame]
wu@webrtc.org91053e72013-08-10 07:18:04 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2013 The WebRTC project authors. All Rights Reserved.
wu@webrtc.org91053e72013-08-10 07:18:04 +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.
wu@webrtc.org91053e72013-08-10 07:18:04 +00009 */
10
ossu7bb87ee2017-01-23 04:56:25 -080011#include "webrtc/pc/webrtcsessiondescriptionfactory.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000012
kwiberg0eb15ed2015-12-17 03:04:15 -080013#include <utility>
14
Henrik Kjellander15583c12016-02-10 10:53:12 +010015#include "webrtc/api/jsep.h"
16#include "webrtc/api/jsepsessiondescription.h"
17#include "webrtc/api/mediaconstraintsinterface.h"
ossu7bb87ee2017-01-23 04:56:25 -080018#include "webrtc/pc/webrtcsession.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/rtc_base/checks.h"
20#include "webrtc/rtc_base/sslidentity.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000021
wu@webrtc.org364f2042013-11-20 21:49:41 +000022using cricket::MediaSessionOptions;
23
wu@webrtc.org91053e72013-08-10 07:18:04 +000024namespace webrtc {
wu@webrtc.org91053e72013-08-10 07:18:04 +000025namespace {
wu@webrtc.org91053e72013-08-10 07:18:04 +000026static const char kFailedDueToIdentityFailed[] =
27 " failed because DTLS identity request failed";
tommi0f620f42015-07-09 03:25:02 -070028static const char kFailedDueToSessionShutdown[] =
29 " failed because the session was shut down";
wu@webrtc.org91053e72013-08-10 07:18:04 +000030
Peter Boström0c4e06b2015-10-07 12:23:21 +020031static const uint64_t kInitSessionVersion = 2;
wu@webrtc.org91053e72013-08-10 07:18:04 +000032
zhihuang1c378ed2017-08-17 14:10:50 -070033static bool CompareSenderOptions(const cricket::SenderOptions& sender1,
34 const cricket::SenderOptions& sender2) {
35 return sender1.track_id < sender2.track_id;
wu@webrtc.org91053e72013-08-10 07:18:04 +000036}
37
zhihuang1c378ed2017-08-17 14:10:50 -070038static bool SameId(const cricket::SenderOptions& sender1,
39 const cricket::SenderOptions& sender2) {
40 return sender1.track_id == sender2.track_id;
wu@webrtc.org91053e72013-08-10 07:18:04 +000041}
42
zhihuang1c378ed2017-08-17 14:10:50 -070043// Check that each sender has a unique ID.
44static bool ValidMediaSessionOptions(
45 const cricket::MediaSessionOptions& session_options) {
46 std::vector<cricket::SenderOptions> sorted_senders;
47 for (const cricket::MediaDescriptionOptions& media_description_options :
48 session_options.media_description_options) {
49 sorted_senders.insert(sorted_senders.end(),
50 media_description_options.sender_options.begin(),
51 media_description_options.sender_options.end());
52 }
53 std::sort(sorted_senders.begin(), sorted_senders.end(), CompareSenderOptions);
54 std::vector<cricket::SenderOptions>::iterator it =
55 std::adjacent_find(sorted_senders.begin(), sorted_senders.end(), SameId);
56 return it == sorted_senders.end();
wu@webrtc.org91053e72013-08-10 07:18:04 +000057}
58
59enum {
60 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS,
Henrik Boström87713d02015-08-25 09:53:21 +020061 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
62 MSG_USE_CONSTRUCTOR_CERTIFICATE
wu@webrtc.org91053e72013-08-10 07:18:04 +000063};
64
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000065struct CreateSessionDescriptionMsg : public rtc::MessageData {
wu@webrtc.org91053e72013-08-10 07:18:04 +000066 explicit CreateSessionDescriptionMsg(
67 webrtc::CreateSessionDescriptionObserver* observer)
68 : observer(observer) {
69 }
70
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000071 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
wu@webrtc.org91053e72013-08-10 07:18:04 +000072 std::string error;
kwibergd1fe2812016-04-27 06:47:29 -070073 std::unique_ptr<webrtc::SessionDescriptionInterface> description;
wu@webrtc.org91053e72013-08-10 07:18:04 +000074};
wu@webrtc.org91053e72013-08-10 07:18:04 +000075} // namespace
76
Henrik Boströmd03c23b2016-06-01 11:44:18 +020077void WebRtcCertificateGeneratorCallback::OnFailure() {
78 SignalRequestFailed();
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +000079}
80
Henrik Boströmd03c23b2016-06-01 11:44:18 +020081void WebRtcCertificateGeneratorCallback::OnSuccess(
82 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
83 SignalCertificateReady(certificate);
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +000084}
85
wu@webrtc.org91053e72013-08-10 07:18:04 +000086// static
87void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
88 const SessionDescriptionInterface* source_desc,
deadbeef0ed85b22016-02-23 17:24:52 -080089 const std::string& content_name,
wu@webrtc.org91053e72013-08-10 07:18:04 +000090 SessionDescriptionInterface* dest_desc) {
deadbeef0ed85b22016-02-23 17:24:52 -080091 if (!source_desc) {
wu@webrtc.org91053e72013-08-10 07:18:04 +000092 return;
deadbeef0ed85b22016-02-23 17:24:52 -080093 }
94 const cricket::ContentInfos& contents =
95 source_desc->description()->contents();
96 const cricket::ContentInfo* cinfo =
97 source_desc->description()->GetContentByName(content_name);
98 if (!cinfo) {
99 return;
100 }
101 size_t mediasection_index = static_cast<int>(cinfo - &contents[0]);
102 const IceCandidateCollection* source_candidates =
103 source_desc->candidates(mediasection_index);
104 const IceCandidateCollection* dest_candidates =
105 dest_desc->candidates(mediasection_index);
Taylor Brandstetter4eb1ddd2016-03-01 16:21:07 -0800106 if (!source_candidates || !dest_candidates) {
107 return;
108 }
deadbeef0ed85b22016-02-23 17:24:52 -0800109 for (size_t n = 0; n < source_candidates->count(); ++n) {
110 const IceCandidateInterface* new_candidate = source_candidates->at(n);
111 if (!dest_candidates->HasCandidate(new_candidate)) {
112 dest_desc->AddCandidate(source_candidates->at(n));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000113 }
114 }
115}
116
Henrik Boström87713d02015-08-25 09:53:21 +0200117// Private constructor called by other constructors.
wu@webrtc.org91053e72013-08-10 07:18:04 +0000118WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000119 rtc::Thread* signaling_thread,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000120 cricket::ChannelManager* channel_manager,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000121 WebRtcSession* session,
122 const std::string& session_id,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200123 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
124 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
wu@webrtc.org91053e72013-08-10 07:18:04 +0000125 : signaling_thread_(signaling_thread),
wu@webrtc.org91053e72013-08-10 07:18:04 +0000126 session_desc_factory_(channel_manager, &transport_desc_factory_),
127 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp
128 // as the session id and session version. To simplify, it should be fine
129 // to just use a random number as session id and start version from
130 // |kInitSessionVersion|.
131 session_version_(kInitSessionVersion),
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200132 cert_generator_(std::move(cert_generator)),
wu@webrtc.org91053e72013-08-10 07:18:04 +0000133 session_(session),
134 session_id_(session_id),
Henrik Boström87713d02015-08-25 09:53:21 +0200135 certificate_request_state_(CERTIFICATE_NOT_NEEDED) {
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200136 RTC_DCHECK(signaling_thread_);
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200137 bool dtls_enabled = cert_generator_ || certificate;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000138 // SRTP-SDES is disabled if DTLS is on.
139 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED);
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200140 if (!dtls_enabled) {
141 LOG(LS_VERBOSE) << "DTLS-SRTP disabled.";
142 return;
143 }
144
145 if (certificate) {
146 // Use |certificate|.
147 certificate_request_state_ = CERTIFICATE_WAITING;
148
149 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter.";
150 // We already have a certificate but we wait to do |SetIdentity|; if we do
151 // it in the constructor then the caller has not had a chance to connect to
152 // |SignalCertificateReady|.
153 signaling_thread_->Post(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700154 RTC_FROM_HERE, this, MSG_USE_CONSTRUCTOR_CERTIFICATE,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200155 new rtc::ScopedRefMessageData<rtc::RTCCertificate>(certificate));
156 } else {
157 // Generate certificate.
158 certificate_request_state_ = CERTIFICATE_WAITING;
159
160 rtc::scoped_refptr<WebRtcCertificateGeneratorCallback> callback(
161 new rtc::RefCountedObject<WebRtcCertificateGeneratorCallback>());
162 callback->SignalRequestFailed.connect(
163 this, &WebRtcSessionDescriptionFactory::OnCertificateRequestFailed);
164 callback->SignalCertificateReady.connect(
165 this, &WebRtcSessionDescriptionFactory::SetCertificate);
166
167 rtc::KeyParams key_params = rtc::KeyParams();
168 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key "
169 << "type: " << key_params.type() << ").";
170
171 // Request certificate. This happens asynchronously, so that the caller gets
172 // a chance to connect to |SignalCertificateReady|.
173 cert_generator_->GenerateCertificateAsync(
174 key_params, rtc::Optional<uint64_t>(), callback);
175 }
Henrik Boström87713d02015-08-25 09:53:21 +0200176}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000177
Henrik Boström87713d02015-08-25 09:53:21 +0200178WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
179 rtc::Thread* signaling_thread,
180 cricket::ChannelManager* channel_manager,
Henrik Boström87713d02015-08-25 09:53:21 +0200181 WebRtcSession* session,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200182 const std::string& session_id,
183 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator)
Henrik Boström87713d02015-08-25 09:53:21 +0200184 : WebRtcSessionDescriptionFactory(
deadbeefab9b2d12015-10-14 11:33:11 -0700185 signaling_thread,
186 channel_manager,
deadbeefab9b2d12015-10-14 11:33:11 -0700187 session,
188 session_id,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200189 std::move(cert_generator),
190 nullptr) {
Henrik Boström87713d02015-08-25 09:53:21 +0200191}
192
193WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
194 rtc::Thread* signaling_thread,
195 cricket::ChannelManager* channel_manager,
Henrik Boström87713d02015-08-25 09:53:21 +0200196 WebRtcSession* session,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200197 const std::string& session_id,
198 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
deadbeefab9b2d12015-10-14 11:33:11 -0700199 : WebRtcSessionDescriptionFactory(signaling_thread,
200 channel_manager,
deadbeefab9b2d12015-10-14 11:33:11 -0700201 session,
202 session_id,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200203 nullptr,
204 certificate) {
henrikg91d6ede2015-09-17 00:24:34 -0700205 RTC_DCHECK(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000206}
207
208WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
nisseede5da42017-01-12 05:15:36 -0800209 RTC_DCHECK(signaling_thread_->IsCurrent());
tommi0f620f42015-07-09 03:25:02 -0700210
211 // Fail any requests that were asked for before identity generation completed.
212 FailPendingRequests(kFailedDueToSessionShutdown);
213
214 // Process all pending notifications in the message queue. If we don't do
215 // this, requests will linger and not know they succeeded or failed.
216 rtc::MessageList list;
217 signaling_thread_->Clear(this, rtc::MQID_ANY, &list);
Henrik Boström87713d02015-08-25 09:53:21 +0200218 for (auto& msg : list) {
219 if (msg.message_id != MSG_USE_CONSTRUCTOR_CERTIFICATE) {
220 OnMessage(&msg);
221 } else {
222 // Skip MSG_USE_CONSTRUCTOR_CERTIFICATE because we don't want to trigger
223 // SetIdentity-related callbacks in the destructor. This can be a problem
224 // when WebRtcSession listens to the callback but it was the WebRtcSession
225 // destructor that caused WebRtcSessionDescriptionFactory's destruction.
226 // The callback is then ignored, leaking memory allocated by OnMessage for
227 // MSG_USE_CONSTRUCTOR_CERTIFICATE.
228 delete msg.pdata;
229 }
230 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000231}
232
233void WebRtcSessionDescriptionFactory::CreateOffer(
234 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 11:33:11 -0700235 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
236 const cricket::MediaSessionOptions& session_options) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000237 std::string error = "CreateOffer";
Henrik Boström87713d02015-08-25 09:53:21 +0200238 if (certificate_request_state_ == CERTIFICATE_FAILED) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000239 error += kFailedDueToIdentityFailed;
240 LOG(LS_ERROR) << error;
241 PostCreateSessionDescriptionFailed(observer, error);
242 return;
243 }
244
zhihuang1c378ed2017-08-17 14:10:50 -0700245 if (!ValidMediaSessionOptions(session_options)) {
246 error += " called with invalid session options";
wu@webrtc.org91053e72013-08-10 07:18:04 +0000247 LOG(LS_ERROR) << error;
248 PostCreateSessionDescriptionFailed(observer, error);
249 return;
250 }
251
wu@webrtc.org91053e72013-08-10 07:18:04 +0000252 CreateSessionDescriptionRequest request(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000253 CreateSessionDescriptionRequest::kOffer, observer, session_options);
Henrik Boström87713d02015-08-25 09:53:21 +0200254 if (certificate_request_state_ == CERTIFICATE_WAITING) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000255 create_session_description_requests_.push(request);
256 } else {
nisseede5da42017-01-12 05:15:36 -0800257 RTC_DCHECK(certificate_request_state_ == CERTIFICATE_SUCCEEDED ||
258 certificate_request_state_ == CERTIFICATE_NOT_NEEDED);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000259 InternalCreateOffer(request);
260 }
261}
262
263void WebRtcSessionDescriptionFactory::CreateAnswer(
264 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 11:33:11 -0700265 const cricket::MediaSessionOptions& session_options) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000266 std::string error = "CreateAnswer";
Henrik Boström87713d02015-08-25 09:53:21 +0200267 if (certificate_request_state_ == CERTIFICATE_FAILED) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000268 error += kFailedDueToIdentityFailed;
269 LOG(LS_ERROR) << error;
270 PostCreateSessionDescriptionFailed(observer, error);
271 return;
272 }
273 if (!session_->remote_description()) {
274 error += " can't be called before SetRemoteDescription.";
275 LOG(LS_ERROR) << error;
276 PostCreateSessionDescriptionFailed(observer, error);
277 return;
278 }
279 if (session_->remote_description()->type() !=
280 JsepSessionDescription::kOffer) {
281 error += " failed because remote_description is not an offer.";
282 LOG(LS_ERROR) << error;
283 PostCreateSessionDescriptionFailed(observer, error);
284 return;
285 }
286
zhihuang1c378ed2017-08-17 14:10:50 -0700287 if (!ValidMediaSessionOptions(session_options)) {
288 error += " called with invalid session options.";
wu@webrtc.org91053e72013-08-10 07:18:04 +0000289 LOG(LS_ERROR) << error;
290 PostCreateSessionDescriptionFailed(observer, error);
291 return;
292 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000293
294 CreateSessionDescriptionRequest request(
deadbeefab9b2d12015-10-14 11:33:11 -0700295 CreateSessionDescriptionRequest::kAnswer, observer, session_options);
Henrik Boström87713d02015-08-25 09:53:21 +0200296 if (certificate_request_state_ == CERTIFICATE_WAITING) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000297 create_session_description_requests_.push(request);
298 } else {
nisseede5da42017-01-12 05:15:36 -0800299 RTC_DCHECK(certificate_request_state_ == CERTIFICATE_SUCCEEDED ||
300 certificate_request_state_ == CERTIFICATE_NOT_NEEDED);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000301 InternalCreateAnswer(request);
302 }
303}
304
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000305void WebRtcSessionDescriptionFactory::SetSdesPolicy(
306 cricket::SecurePolicy secure_policy) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000307 session_desc_factory_.set_secure(secure_policy);
308}
309
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000310cricket::SecurePolicy WebRtcSessionDescriptionFactory::SdesPolicy() const {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000311 return session_desc_factory_.secure();
312}
313
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000314void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000315 switch (msg->message_id) {
316 case MSG_CREATE_SESSIONDESCRIPTION_SUCCESS: {
317 CreateSessionDescriptionMsg* param =
318 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
319 param->observer->OnSuccess(param->description.release());
320 delete param;
321 break;
322 }
323 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
324 CreateSessionDescriptionMsg* param =
325 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
326 param->observer->OnFailure(param->error);
327 delete param;
328 break;
329 }
Henrik Boström87713d02015-08-25 09:53:21 +0200330 case MSG_USE_CONSTRUCTOR_CERTIFICATE: {
331 rtc::ScopedRefMessageData<rtc::RTCCertificate>* param =
332 static_cast<rtc::ScopedRefMessageData<rtc::RTCCertificate>*>(
333 msg->pdata);
334 LOG(LS_INFO) << "Using certificate supplied to the constructor.";
Henrik Boströmd8281982015-08-27 10:12:24 +0200335 SetCertificate(param->data());
Henrik Boström87713d02015-08-25 09:53:21 +0200336 delete param;
337 break;
338 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000339 default:
nissec80e7412017-01-11 05:56:46 -0800340 RTC_NOTREACHED();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000341 break;
342 }
343}
344
345void WebRtcSessionDescriptionFactory::InternalCreateOffer(
346 CreateSessionDescriptionRequest request) {
deadbeefd1a38b52016-12-10 13:15:33 -0800347 if (session_->local_description()) {
zhihuang1c378ed2017-08-17 14:10:50 -0700348 // If the needs-ice-restart flag is set as described by JSEP, we should
349 // generate an offer with a new ufrag/password to trigger an ICE restart.
350 for (cricket::MediaDescriptionOptions& options :
351 request.options.media_description_options) {
352 if (session_->NeedsIceRestart(options.mid)) {
353 options.transport_options.ice_restart = true;
deadbeefd1a38b52016-12-10 13:15:33 -0800354 }
355 }
356 }
357
deadbeefd59daf82015-10-14 15:02:44 -0700358 cricket::SessionDescription* desc(session_desc_factory_.CreateOffer(
359 request.options, session_->local_description()
360 ? session_->local_description()->description()
361 : nullptr));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000362 // RFC 3264
363 // When issuing an offer that modifies the session,
364 // the "o=" line of the new SDP MUST be identical to that in the
365 // previous SDP, except that the version in the origin field MUST
366 // increment by one from the previous SDP.
367
368 // Just increase the version number by one each time when a new offer
369 // is created regardless if it's identical to the previous one or not.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200370 // The |session_version_| is a uint64_t, the wrap around should not happen.
nisseede5da42017-01-12 05:15:36 -0800371 RTC_DCHECK(session_version_ + 1 > session_version_);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000372 JsepSessionDescription* offer(new JsepSessionDescription(
373 JsepSessionDescription::kOffer));
374 if (!offer->Initialize(desc, session_id_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000375 rtc::ToString(session_version_++))) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000376 delete offer;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000377 PostCreateSessionDescriptionFailed(request.observer,
378 "Failed to initialize the offer.");
wu@webrtc.org91053e72013-08-10 07:18:04 +0000379 return;
380 }
deadbeef0ed85b22016-02-23 17:24:52 -0800381 if (session_->local_description()) {
zhihuang1c378ed2017-08-17 14:10:50 -0700382 for (const cricket::MediaDescriptionOptions& options :
383 request.options.media_description_options) {
384 if (!options.transport_options.ice_restart) {
deadbeef0ed85b22016-02-23 17:24:52 -0800385 CopyCandidatesFromSessionDescription(session_->local_description(),
zhihuang1c378ed2017-08-17 14:10:50 -0700386 options.mid, offer);
deadbeef0ed85b22016-02-23 17:24:52 -0800387 }
388 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000389 }
390 PostCreateSessionDescriptionSucceeded(request.observer, offer);
391}
392
393void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
394 CreateSessionDescriptionRequest request) {
deadbeef0ed85b22016-02-23 17:24:52 -0800395 if (session_->remote_description()) {
zhihuang1c378ed2017-08-17 14:10:50 -0700396 for (cricket::MediaDescriptionOptions& options :
397 request.options.media_description_options) {
deadbeef0ed85b22016-02-23 17:24:52 -0800398 // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1
399 // an answer should also contain new ICE ufrag and password if an offer
400 // has been received with new ufrag and password.
zhihuang1c378ed2017-08-17 14:10:50 -0700401 options.transport_options.ice_restart =
402 session_->IceRestartPending(options.mid);
deadbeef0ed85b22016-02-23 17:24:52 -0800403 // We should pass the current SSL role to the transport description
404 // factory, if there is already an existing ongoing session.
405 rtc::SSLRole ssl_role;
zhihuang1c378ed2017-08-17 14:10:50 -0700406 if (session_->GetSslRole(options.mid, &ssl_role)) {
407 options.transport_options.prefer_passive_role =
deadbeef0ed85b22016-02-23 17:24:52 -0800408 (rtc::SSL_SERVER == ssl_role);
409 }
410 }
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000411 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000412
413 cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer(
deadbeefd59daf82015-10-14 15:02:44 -0700414 session_->remote_description()
415 ? session_->remote_description()->description()
416 : nullptr,
417 request.options, session_->local_description()
418 ? session_->local_description()->description()
419 : nullptr));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000420 // RFC 3264
421 // If the answer is different from the offer in any way (different IP
422 // addresses, ports, etc.), the origin line MUST be different in the answer.
423 // In that case, the version number in the "o=" line of the answer is
424 // unrelated to the version number in the o line of the offer.
425 // Get a new version number by increasing the |session_version_answer_|.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200426 // The |session_version_| is a uint64_t, the wrap around should not happen.
nisseede5da42017-01-12 05:15:36 -0800427 RTC_DCHECK(session_version_ + 1 > session_version_);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000428 JsepSessionDescription* answer(new JsepSessionDescription(
429 JsepSessionDescription::kAnswer));
430 if (!answer->Initialize(desc, session_id_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000431 rtc::ToString(session_version_++))) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000432 delete answer;
433 PostCreateSessionDescriptionFailed(request.observer,
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000434 "Failed to initialize the answer.");
wu@webrtc.org91053e72013-08-10 07:18:04 +0000435 return;
436 }
deadbeef0ed85b22016-02-23 17:24:52 -0800437 if (session_->local_description()) {
zhihuang1c378ed2017-08-17 14:10:50 -0700438 // Include all local ICE candidates in the SessionDescription unless
439 // the remote peer has requested an ICE restart.
440 for (const cricket::MediaDescriptionOptions& options :
441 request.options.media_description_options) {
442 if (!options.transport_options.ice_restart) {
deadbeef0ed85b22016-02-23 17:24:52 -0800443 CopyCandidatesFromSessionDescription(session_->local_description(),
zhihuang1c378ed2017-08-17 14:10:50 -0700444 options.mid, answer);
deadbeef0ed85b22016-02-23 17:24:52 -0800445 }
446 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000447 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000448 PostCreateSessionDescriptionSucceeded(request.observer, answer);
449}
450
tommi0f620f42015-07-09 03:25:02 -0700451void WebRtcSessionDescriptionFactory::FailPendingRequests(
452 const std::string& reason) {
nisseede5da42017-01-12 05:15:36 -0800453 RTC_DCHECK(signaling_thread_->IsCurrent());
tommi0f620f42015-07-09 03:25:02 -0700454 while (!create_session_description_requests_.empty()) {
455 const CreateSessionDescriptionRequest& request =
456 create_session_description_requests_.front();
457 PostCreateSessionDescriptionFailed(request.observer,
458 ((request.type == CreateSessionDescriptionRequest::kOffer) ?
459 "CreateOffer" : "CreateAnswer") + reason);
460 create_session_description_requests_.pop();
461 }
462}
463
wu@webrtc.org91053e72013-08-10 07:18:04 +0000464void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionFailed(
465 CreateSessionDescriptionObserver* observer, const std::string& error) {
466 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
467 msg->error = error;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700468 signaling_thread_->Post(RTC_FROM_HERE, this,
469 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000470 LOG(LS_ERROR) << "Create SDP failed: " << error;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000471}
472
473void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionSucceeded(
474 CreateSessionDescriptionObserver* observer,
475 SessionDescriptionInterface* description) {
476 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
477 msg->description.reset(description);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700478 signaling_thread_->Post(RTC_FROM_HERE, this,
479 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, msg);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000480}
481
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200482void WebRtcSessionDescriptionFactory::OnCertificateRequestFailed() {
nisseede5da42017-01-12 05:15:36 -0800483 RTC_DCHECK(signaling_thread_->IsCurrent());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000484
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200485 LOG(LS_ERROR) << "Asynchronous certificate generation request failed.";
Henrik Boström87713d02015-08-25 09:53:21 +0200486 certificate_request_state_ = CERTIFICATE_FAILED;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000487
tommi0f620f42015-07-09 03:25:02 -0700488 FailPendingRequests(kFailedDueToIdentityFailed);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000489}
490
Henrik Boströmd8281982015-08-27 10:12:24 +0200491void WebRtcSessionDescriptionFactory::SetCertificate(
492 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
henrikg91d6ede2015-09-17 00:24:34 -0700493 RTC_DCHECK(certificate);
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200494 LOG(LS_VERBOSE) << "Setting new certificate.";
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000495
Henrik Boström87713d02015-08-25 09:53:21 +0200496 certificate_request_state_ = CERTIFICATE_SUCCEEDED;
Henrik Boströmd8281982015-08-27 10:12:24 +0200497 SignalCertificateReady(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000498
Henrik Boström3a14bf32015-08-31 09:27:58 +0200499 transport_desc_factory_.set_certificate(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000500 transport_desc_factory_.set_secure(cricket::SEC_ENABLED);
501
502 while (!create_session_description_requests_.empty()) {
503 if (create_session_description_requests_.front().type ==
504 CreateSessionDescriptionRequest::kOffer) {
505 InternalCreateOffer(create_session_description_requests_.front());
506 } else {
507 InternalCreateAnswer(create_session_description_requests_.front());
508 }
509 create_session_description_requests_.pop();
510 }
511}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000512} // namespace webrtc