blob: 1f811f59117afd539e2349d5010c52fd0aa0fc22 [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
Henrik Kjellander15583c12016-02-10 10:53:12 +010011#include "webrtc/api/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"
18#include "webrtc/api/webrtcsession.h"
Henrik Boström5e56c592015-08-11 10:33:13 +020019#include "webrtc/base/sslidentity.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000020
wu@webrtc.org364f2042013-11-20 21:49:41 +000021using cricket::MediaSessionOptions;
22
wu@webrtc.org91053e72013-08-10 07:18:04 +000023namespace webrtc {
wu@webrtc.org91053e72013-08-10 07:18:04 +000024namespace {
wu@webrtc.org91053e72013-08-10 07:18:04 +000025static const char kFailedDueToIdentityFailed[] =
26 " failed because DTLS identity request failed";
tommi0f620f42015-07-09 03:25:02 -070027static const char kFailedDueToSessionShutdown[] =
28 " failed because the session was shut down";
wu@webrtc.org91053e72013-08-10 07:18:04 +000029
Peter Boström0c4e06b2015-10-07 12:23:21 +020030static const uint64_t kInitSessionVersion = 2;
wu@webrtc.org91053e72013-08-10 07:18:04 +000031
wu@webrtc.org364f2042013-11-20 21:49:41 +000032static bool CompareStream(const MediaSessionOptions::Stream& stream1,
33 const MediaSessionOptions::Stream& stream2) {
34 return stream1.id < stream2.id;
wu@webrtc.org91053e72013-08-10 07:18:04 +000035}
36
wu@webrtc.org364f2042013-11-20 21:49:41 +000037static bool SameId(const MediaSessionOptions::Stream& stream1,
38 const MediaSessionOptions::Stream& stream2) {
39 return stream1.id == stream2.id;
wu@webrtc.org91053e72013-08-10 07:18:04 +000040}
41
42// Checks if each Stream within the |streams| has unique id.
wu@webrtc.org364f2042013-11-20 21:49:41 +000043static bool ValidStreams(const MediaSessionOptions::Streams& streams) {
44 MediaSessionOptions::Streams sorted_streams = streams;
wu@webrtc.org91053e72013-08-10 07:18:04 +000045 std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream);
wu@webrtc.org364f2042013-11-20 21:49:41 +000046 MediaSessionOptions::Streams::iterator it =
wu@webrtc.org91053e72013-08-10 07:18:04 +000047 std::adjacent_find(sorted_streams.begin(), sorted_streams.end(),
48 SameId);
wu@webrtc.org364f2042013-11-20 21:49:41 +000049 return it == sorted_streams.end();
wu@webrtc.org91053e72013-08-10 07:18:04 +000050}
51
52enum {
53 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS,
Henrik Boström87713d02015-08-25 09:53:21 +020054 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
55 MSG_USE_CONSTRUCTOR_CERTIFICATE
wu@webrtc.org91053e72013-08-10 07:18:04 +000056};
57
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000058struct CreateSessionDescriptionMsg : public rtc::MessageData {
wu@webrtc.org91053e72013-08-10 07:18:04 +000059 explicit CreateSessionDescriptionMsg(
60 webrtc::CreateSessionDescriptionObserver* observer)
61 : observer(observer) {
62 }
63
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000064 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
wu@webrtc.org91053e72013-08-10 07:18:04 +000065 std::string error;
kwibergd1fe2812016-04-27 06:47:29 -070066 std::unique_ptr<webrtc::SessionDescriptionInterface> description;
wu@webrtc.org91053e72013-08-10 07:18:04 +000067};
wu@webrtc.org91053e72013-08-10 07:18:04 +000068} // namespace
69
Henrik Boströmd03c23b2016-06-01 11:44:18 +020070void WebRtcCertificateGeneratorCallback::OnFailure() {
71 SignalRequestFailed();
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +000072}
73
Henrik Boströmd03c23b2016-06-01 11:44:18 +020074void WebRtcCertificateGeneratorCallback::OnSuccess(
75 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
76 SignalCertificateReady(certificate);
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +000077}
78
wu@webrtc.org91053e72013-08-10 07:18:04 +000079// static
80void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
81 const SessionDescriptionInterface* source_desc,
deadbeef0ed85b22016-02-23 17:24:52 -080082 const std::string& content_name,
wu@webrtc.org91053e72013-08-10 07:18:04 +000083 SessionDescriptionInterface* dest_desc) {
deadbeef0ed85b22016-02-23 17:24:52 -080084 if (!source_desc) {
wu@webrtc.org91053e72013-08-10 07:18:04 +000085 return;
deadbeef0ed85b22016-02-23 17:24:52 -080086 }
87 const cricket::ContentInfos& contents =
88 source_desc->description()->contents();
89 const cricket::ContentInfo* cinfo =
90 source_desc->description()->GetContentByName(content_name);
91 if (!cinfo) {
92 return;
93 }
94 size_t mediasection_index = static_cast<int>(cinfo - &contents[0]);
95 const IceCandidateCollection* source_candidates =
96 source_desc->candidates(mediasection_index);
97 const IceCandidateCollection* dest_candidates =
98 dest_desc->candidates(mediasection_index);
Taylor Brandstetter4eb1ddd2016-03-01 16:21:07 -080099 if (!source_candidates || !dest_candidates) {
100 return;
101 }
deadbeef0ed85b22016-02-23 17:24:52 -0800102 for (size_t n = 0; n < source_candidates->count(); ++n) {
103 const IceCandidateInterface* new_candidate = source_candidates->at(n);
104 if (!dest_candidates->HasCandidate(new_candidate)) {
105 dest_desc->AddCandidate(source_candidates->at(n));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000106 }
107 }
108}
109
Henrik Boström87713d02015-08-25 09:53:21 +0200110// Private constructor called by other constructors.
wu@webrtc.org91053e72013-08-10 07:18:04 +0000111WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000112 rtc::Thread* signaling_thread,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000113 cricket::ChannelManager* channel_manager,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000114 WebRtcSession* session,
115 const std::string& session_id,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200116 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
117 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
wu@webrtc.org91053e72013-08-10 07:18:04 +0000118 : signaling_thread_(signaling_thread),
wu@webrtc.org91053e72013-08-10 07:18:04 +0000119 session_desc_factory_(channel_manager, &transport_desc_factory_),
120 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp
121 // as the session id and session version. To simplify, it should be fine
122 // to just use a random number as session id and start version from
123 // |kInitSessionVersion|.
124 session_version_(kInitSessionVersion),
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200125 cert_generator_(std::move(cert_generator)),
wu@webrtc.org91053e72013-08-10 07:18:04 +0000126 session_(session),
127 session_id_(session_id),
Henrik Boström87713d02015-08-25 09:53:21 +0200128 certificate_request_state_(CERTIFICATE_NOT_NEEDED) {
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200129 RTC_DCHECK(signaling_thread_);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000130 session_desc_factory_.set_add_legacy_streams(false);
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200131 bool dtls_enabled = cert_generator_ || certificate;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000132 // SRTP-SDES is disabled if DTLS is on.
133 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED);
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200134 if (!dtls_enabled) {
135 LOG(LS_VERBOSE) << "DTLS-SRTP disabled.";
136 return;
137 }
138
139 if (certificate) {
140 // Use |certificate|.
141 certificate_request_state_ = CERTIFICATE_WAITING;
142
143 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter.";
144 // We already have a certificate but we wait to do |SetIdentity|; if we do
145 // it in the constructor then the caller has not had a chance to connect to
146 // |SignalCertificateReady|.
147 signaling_thread_->Post(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700148 RTC_FROM_HERE, this, MSG_USE_CONSTRUCTOR_CERTIFICATE,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200149 new rtc::ScopedRefMessageData<rtc::RTCCertificate>(certificate));
150 } else {
151 // Generate certificate.
152 certificate_request_state_ = CERTIFICATE_WAITING;
153
154 rtc::scoped_refptr<WebRtcCertificateGeneratorCallback> callback(
155 new rtc::RefCountedObject<WebRtcCertificateGeneratorCallback>());
156 callback->SignalRequestFailed.connect(
157 this, &WebRtcSessionDescriptionFactory::OnCertificateRequestFailed);
158 callback->SignalCertificateReady.connect(
159 this, &WebRtcSessionDescriptionFactory::SetCertificate);
160
161 rtc::KeyParams key_params = rtc::KeyParams();
162 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key "
163 << "type: " << key_params.type() << ").";
164
165 // Request certificate. This happens asynchronously, so that the caller gets
166 // a chance to connect to |SignalCertificateReady|.
167 cert_generator_->GenerateCertificateAsync(
168 key_params, rtc::Optional<uint64_t>(), callback);
169 }
Henrik Boström87713d02015-08-25 09:53:21 +0200170}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000171
Henrik Boström87713d02015-08-25 09:53:21 +0200172WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
173 rtc::Thread* signaling_thread,
174 cricket::ChannelManager* channel_manager,
Henrik Boström87713d02015-08-25 09:53:21 +0200175 WebRtcSession* session,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200176 const std::string& session_id,
177 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator)
Henrik Boström87713d02015-08-25 09:53:21 +0200178 : WebRtcSessionDescriptionFactory(
deadbeefab9b2d12015-10-14 11:33:11 -0700179 signaling_thread,
180 channel_manager,
deadbeefab9b2d12015-10-14 11:33:11 -0700181 session,
182 session_id,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200183 std::move(cert_generator),
184 nullptr) {
Henrik Boström87713d02015-08-25 09:53:21 +0200185}
186
187WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
188 rtc::Thread* signaling_thread,
189 cricket::ChannelManager* channel_manager,
Henrik Boström87713d02015-08-25 09:53:21 +0200190 WebRtcSession* session,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200191 const std::string& session_id,
192 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate)
deadbeefab9b2d12015-10-14 11:33:11 -0700193 : WebRtcSessionDescriptionFactory(signaling_thread,
194 channel_manager,
deadbeefab9b2d12015-10-14 11:33:11 -0700195 session,
196 session_id,
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200197 nullptr,
198 certificate) {
henrikg91d6ede2015-09-17 00:24:34 -0700199 RTC_DCHECK(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000200}
201
202WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
tommi0f620f42015-07-09 03:25:02 -0700203 ASSERT(signaling_thread_->IsCurrent());
204
205 // Fail any requests that were asked for before identity generation completed.
206 FailPendingRequests(kFailedDueToSessionShutdown);
207
208 // Process all pending notifications in the message queue. If we don't do
209 // this, requests will linger and not know they succeeded or failed.
210 rtc::MessageList list;
211 signaling_thread_->Clear(this, rtc::MQID_ANY, &list);
Henrik Boström87713d02015-08-25 09:53:21 +0200212 for (auto& msg : list) {
213 if (msg.message_id != MSG_USE_CONSTRUCTOR_CERTIFICATE) {
214 OnMessage(&msg);
215 } else {
216 // Skip MSG_USE_CONSTRUCTOR_CERTIFICATE because we don't want to trigger
217 // SetIdentity-related callbacks in the destructor. This can be a problem
218 // when WebRtcSession listens to the callback but it was the WebRtcSession
219 // destructor that caused WebRtcSessionDescriptionFactory's destruction.
220 // The callback is then ignored, leaking memory allocated by OnMessage for
221 // MSG_USE_CONSTRUCTOR_CERTIFICATE.
222 delete msg.pdata;
223 }
224 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000225}
226
227void WebRtcSessionDescriptionFactory::CreateOffer(
228 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 11:33:11 -0700229 const PeerConnectionInterface::RTCOfferAnswerOptions& options,
230 const cricket::MediaSessionOptions& session_options) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000231 std::string error = "CreateOffer";
Henrik Boström87713d02015-08-25 09:53:21 +0200232 if (certificate_request_state_ == CERTIFICATE_FAILED) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000233 error += kFailedDueToIdentityFailed;
234 LOG(LS_ERROR) << error;
235 PostCreateSessionDescriptionFailed(observer, error);
236 return;
237 }
238
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000239 if (!ValidStreams(session_options.streams)) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000240 error += " called with invalid media streams.";
241 LOG(LS_ERROR) << error;
242 PostCreateSessionDescriptionFailed(observer, error);
243 return;
244 }
245
wu@webrtc.org91053e72013-08-10 07:18:04 +0000246 CreateSessionDescriptionRequest request(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000247 CreateSessionDescriptionRequest::kOffer, observer, session_options);
Henrik Boström87713d02015-08-25 09:53:21 +0200248 if (certificate_request_state_ == CERTIFICATE_WAITING) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000249 create_session_description_requests_.push(request);
250 } else {
Henrik Boström87713d02015-08-25 09:53:21 +0200251 ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED ||
252 certificate_request_state_ == CERTIFICATE_NOT_NEEDED);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000253 InternalCreateOffer(request);
254 }
255}
256
257void WebRtcSessionDescriptionFactory::CreateAnswer(
258 CreateSessionDescriptionObserver* observer,
deadbeefab9b2d12015-10-14 11:33:11 -0700259 const cricket::MediaSessionOptions& session_options) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000260 std::string error = "CreateAnswer";
Henrik Boström87713d02015-08-25 09:53:21 +0200261 if (certificate_request_state_ == CERTIFICATE_FAILED) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000262 error += kFailedDueToIdentityFailed;
263 LOG(LS_ERROR) << error;
264 PostCreateSessionDescriptionFailed(observer, error);
265 return;
266 }
267 if (!session_->remote_description()) {
268 error += " can't be called before SetRemoteDescription.";
269 LOG(LS_ERROR) << error;
270 PostCreateSessionDescriptionFailed(observer, error);
271 return;
272 }
273 if (session_->remote_description()->type() !=
274 JsepSessionDescription::kOffer) {
275 error += " failed because remote_description is not an offer.";
276 LOG(LS_ERROR) << error;
277 PostCreateSessionDescriptionFailed(observer, error);
278 return;
279 }
280
deadbeefab9b2d12015-10-14 11:33:11 -0700281 if (!ValidStreams(session_options.streams)) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000282 error += " called with invalid media streams.";
283 LOG(LS_ERROR) << error;
284 PostCreateSessionDescriptionFailed(observer, error);
285 return;
286 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000287
288 CreateSessionDescriptionRequest request(
deadbeefab9b2d12015-10-14 11:33:11 -0700289 CreateSessionDescriptionRequest::kAnswer, observer, session_options);
Henrik Boström87713d02015-08-25 09:53:21 +0200290 if (certificate_request_state_ == CERTIFICATE_WAITING) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000291 create_session_description_requests_.push(request);
292 } else {
Henrik Boström87713d02015-08-25 09:53:21 +0200293 ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED ||
294 certificate_request_state_ == CERTIFICATE_NOT_NEEDED);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000295 InternalCreateAnswer(request);
296 }
297}
298
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000299void WebRtcSessionDescriptionFactory::SetSdesPolicy(
300 cricket::SecurePolicy secure_policy) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000301 session_desc_factory_.set_secure(secure_policy);
302}
303
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000304cricket::SecurePolicy WebRtcSessionDescriptionFactory::SdesPolicy() const {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000305 return session_desc_factory_.secure();
306}
307
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000308void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000309 switch (msg->message_id) {
310 case MSG_CREATE_SESSIONDESCRIPTION_SUCCESS: {
311 CreateSessionDescriptionMsg* param =
312 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
313 param->observer->OnSuccess(param->description.release());
314 delete param;
315 break;
316 }
317 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
318 CreateSessionDescriptionMsg* param =
319 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
320 param->observer->OnFailure(param->error);
321 delete param;
322 break;
323 }
Henrik Boström87713d02015-08-25 09:53:21 +0200324 case MSG_USE_CONSTRUCTOR_CERTIFICATE: {
325 rtc::ScopedRefMessageData<rtc::RTCCertificate>* param =
326 static_cast<rtc::ScopedRefMessageData<rtc::RTCCertificate>*>(
327 msg->pdata);
328 LOG(LS_INFO) << "Using certificate supplied to the constructor.";
Henrik Boströmd8281982015-08-27 10:12:24 +0200329 SetCertificate(param->data());
Henrik Boström87713d02015-08-25 09:53:21 +0200330 delete param;
331 break;
332 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000333 default:
334 ASSERT(false);
335 break;
336 }
337}
338
339void WebRtcSessionDescriptionFactory::InternalCreateOffer(
340 CreateSessionDescriptionRequest request) {
deadbeefd1a38b52016-12-10 13:15:33 -0800341 if (session_->local_description()) {
342 for (const cricket::TransportInfo& transport :
343 session_->local_description()->description()->transport_infos()) {
344 // If the needs-ice-restart flag is set as described by JSEP, we should
345 // generate an offer with a new ufrag/password to trigger an ICE restart.
346 if (session_->NeedsIceRestart(transport.content_name)) {
347 request.options.transport_options[transport.content_name].ice_restart =
348 true;
349 }
350 }
351 }
352
deadbeefd59daf82015-10-14 15:02:44 -0700353 cricket::SessionDescription* desc(session_desc_factory_.CreateOffer(
354 request.options, session_->local_description()
355 ? session_->local_description()->description()
356 : nullptr));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000357 // RFC 3264
358 // When issuing an offer that modifies the session,
359 // the "o=" line of the new SDP MUST be identical to that in the
360 // previous SDP, except that the version in the origin field MUST
361 // increment by one from the previous SDP.
362
363 // Just increase the version number by one each time when a new offer
364 // is created regardless if it's identical to the previous one or not.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200365 // The |session_version_| is a uint64_t, the wrap around should not happen.
wu@webrtc.org91053e72013-08-10 07:18:04 +0000366 ASSERT(session_version_ + 1 > session_version_);
367 JsepSessionDescription* offer(new JsepSessionDescription(
368 JsepSessionDescription::kOffer));
369 if (!offer->Initialize(desc, session_id_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000370 rtc::ToString(session_version_++))) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000371 delete offer;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000372 PostCreateSessionDescriptionFailed(request.observer,
373 "Failed to initialize the offer.");
wu@webrtc.org91053e72013-08-10 07:18:04 +0000374 return;
375 }
deadbeef0ed85b22016-02-23 17:24:52 -0800376 if (session_->local_description()) {
377 for (const cricket::ContentInfo& content :
378 session_->local_description()->description()->contents()) {
379 // Include all local ICE candidates in the SessionDescription unless
380 // the remote peer has requested an ICE restart.
381 if (!request.options.transport_options[content.name].ice_restart) {
382 CopyCandidatesFromSessionDescription(session_->local_description(),
383 content.name, offer);
384 }
385 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000386 }
387 PostCreateSessionDescriptionSucceeded(request.observer, offer);
388}
389
390void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
391 CreateSessionDescriptionRequest request) {
deadbeef0ed85b22016-02-23 17:24:52 -0800392 if (session_->remote_description()) {
393 for (const cricket::ContentInfo& content :
394 session_->remote_description()->description()->contents()) {
395 // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1
396 // an answer should also contain new ICE ufrag and password if an offer
397 // has been received with new ufrag and password.
398 request.options.transport_options[content.name].ice_restart =
399 session_->IceRestartPending(content.name);
400 // We should pass the current SSL role to the transport description
401 // factory, if there is already an existing ongoing session.
402 rtc::SSLRole ssl_role;
deadbeefc0dad892017-01-04 20:28:21 -0800403 if (session_->GetSslRole(session_->GetChannel(content.name), &ssl_role)) {
deadbeef0ed85b22016-02-23 17:24:52 -0800404 request.options.transport_options[content.name].prefer_passive_role =
405 (rtc::SSL_SERVER == ssl_role);
406 }
407 }
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000408 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000409
410 cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer(
deadbeefd59daf82015-10-14 15:02:44 -0700411 session_->remote_description()
412 ? session_->remote_description()->description()
413 : nullptr,
414 request.options, session_->local_description()
415 ? session_->local_description()->description()
416 : nullptr));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000417 // RFC 3264
418 // If the answer is different from the offer in any way (different IP
419 // addresses, ports, etc.), the origin line MUST be different in the answer.
420 // In that case, the version number in the "o=" line of the answer is
421 // unrelated to the version number in the o line of the offer.
422 // Get a new version number by increasing the |session_version_answer_|.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200423 // The |session_version_| is a uint64_t, the wrap around should not happen.
wu@webrtc.org91053e72013-08-10 07:18:04 +0000424 ASSERT(session_version_ + 1 > session_version_);
425 JsepSessionDescription* answer(new JsepSessionDescription(
426 JsepSessionDescription::kAnswer));
427 if (!answer->Initialize(desc, session_id_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000428 rtc::ToString(session_version_++))) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000429 delete answer;
430 PostCreateSessionDescriptionFailed(request.observer,
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000431 "Failed to initialize the answer.");
wu@webrtc.org91053e72013-08-10 07:18:04 +0000432 return;
433 }
deadbeef0ed85b22016-02-23 17:24:52 -0800434 if (session_->local_description()) {
435 for (const cricket::ContentInfo& content :
436 session_->local_description()->description()->contents()) {
437 // Include all local ICE candidates in the SessionDescription unless
438 // the remote peer has requested an ICE restart.
439 if (!request.options.transport_options[content.name].ice_restart) {
440 CopyCandidatesFromSessionDescription(session_->local_description(),
441 content.name, answer);
442 }
443 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000444 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000445 PostCreateSessionDescriptionSucceeded(request.observer, answer);
446}
447
tommi0f620f42015-07-09 03:25:02 -0700448void WebRtcSessionDescriptionFactory::FailPendingRequests(
449 const std::string& reason) {
450 ASSERT(signaling_thread_->IsCurrent());
451 while (!create_session_description_requests_.empty()) {
452 const CreateSessionDescriptionRequest& request =
453 create_session_description_requests_.front();
454 PostCreateSessionDescriptionFailed(request.observer,
455 ((request.type == CreateSessionDescriptionRequest::kOffer) ?
456 "CreateOffer" : "CreateAnswer") + reason);
457 create_session_description_requests_.pop();
458 }
459}
460
wu@webrtc.org91053e72013-08-10 07:18:04 +0000461void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionFailed(
462 CreateSessionDescriptionObserver* observer, const std::string& error) {
463 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
464 msg->error = error;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700465 signaling_thread_->Post(RTC_FROM_HERE, this,
466 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000467 LOG(LS_ERROR) << "Create SDP failed: " << error;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000468}
469
470void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionSucceeded(
471 CreateSessionDescriptionObserver* observer,
472 SessionDescriptionInterface* description) {
473 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
474 msg->description.reset(description);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700475 signaling_thread_->Post(RTC_FROM_HERE, this,
476 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, msg);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000477}
478
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200479void WebRtcSessionDescriptionFactory::OnCertificateRequestFailed() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000480 ASSERT(signaling_thread_->IsCurrent());
481
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200482 LOG(LS_ERROR) << "Asynchronous certificate generation request failed.";
Henrik Boström87713d02015-08-25 09:53:21 +0200483 certificate_request_state_ = CERTIFICATE_FAILED;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000484
tommi0f620f42015-07-09 03:25:02 -0700485 FailPendingRequests(kFailedDueToIdentityFailed);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000486}
487
Henrik Boströmd8281982015-08-27 10:12:24 +0200488void WebRtcSessionDescriptionFactory::SetCertificate(
489 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
henrikg91d6ede2015-09-17 00:24:34 -0700490 RTC_DCHECK(certificate);
Henrik Boströmd03c23b2016-06-01 11:44:18 +0200491 LOG(LS_VERBOSE) << "Setting new certificate.";
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000492
Henrik Boström87713d02015-08-25 09:53:21 +0200493 certificate_request_state_ = CERTIFICATE_SUCCEEDED;
Henrik Boströmd8281982015-08-27 10:12:24 +0200494 SignalCertificateReady(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000495
Henrik Boström3a14bf32015-08-31 09:27:58 +0200496 transport_desc_factory_.set_certificate(certificate);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000497 transport_desc_factory_.set_secure(cricket::SEC_ENABLED);
498
499 while (!create_session_description_requests_.empty()) {
500 if (create_session_description_requests_.front().type ==
501 CreateSessionDescriptionRequest::kOffer) {
502 InternalCreateOffer(create_session_description_requests_.front());
503 } else {
504 InternalCreateAnswer(create_session_description_requests_.front());
505 }
506 create_session_description_requests_.pop();
507 }
508}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000509} // namespace webrtc