blob: 1909b0ed78dfe2c6cd5c6c82481d7560ca935ceb [file] [log] [blame]
wu@webrtc.org91053e72013-08-10 07:18:04 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2013 Google Inc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
29
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +000030#include "talk/app/webrtc/dtlsidentitystore.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000031#include "talk/app/webrtc/jsep.h"
32#include "talk/app/webrtc/jsepsessiondescription.h"
33#include "talk/app/webrtc/mediaconstraintsinterface.h"
34#include "talk/app/webrtc/mediastreamsignaling.h"
35#include "talk/app/webrtc/webrtcsession.h"
36
wu@webrtc.org364f2042013-11-20 21:49:41 +000037using cricket::MediaSessionOptions;
38
wu@webrtc.org91053e72013-08-10 07:18:04 +000039namespace webrtc {
wu@webrtc.org91053e72013-08-10 07:18:04 +000040namespace {
wu@webrtc.org91053e72013-08-10 07:18:04 +000041static const char kFailedDueToIdentityFailed[] =
42 " failed because DTLS identity request failed";
tommi0f620f42015-07-09 03:25:02 -070043static const char kFailedDueToSessionShutdown[] =
44 " failed because the session was shut down";
wu@webrtc.org91053e72013-08-10 07:18:04 +000045
wu@webrtc.org91053e72013-08-10 07:18:04 +000046static const uint64 kInitSessionVersion = 2;
47
wu@webrtc.org364f2042013-11-20 21:49:41 +000048static bool CompareStream(const MediaSessionOptions::Stream& stream1,
49 const MediaSessionOptions::Stream& stream2) {
50 return stream1.id < stream2.id;
wu@webrtc.org91053e72013-08-10 07:18:04 +000051}
52
wu@webrtc.org364f2042013-11-20 21:49:41 +000053static bool SameId(const MediaSessionOptions::Stream& stream1,
54 const MediaSessionOptions::Stream& stream2) {
55 return stream1.id == stream2.id;
wu@webrtc.org91053e72013-08-10 07:18:04 +000056}
57
58// Checks if each Stream within the |streams| has unique id.
wu@webrtc.org364f2042013-11-20 21:49:41 +000059static bool ValidStreams(const MediaSessionOptions::Streams& streams) {
60 MediaSessionOptions::Streams sorted_streams = streams;
wu@webrtc.org91053e72013-08-10 07:18:04 +000061 std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream);
wu@webrtc.org364f2042013-11-20 21:49:41 +000062 MediaSessionOptions::Streams::iterator it =
wu@webrtc.org91053e72013-08-10 07:18:04 +000063 std::adjacent_find(sorted_streams.begin(), sorted_streams.end(),
64 SameId);
wu@webrtc.org364f2042013-11-20 21:49:41 +000065 return it == sorted_streams.end();
wu@webrtc.org91053e72013-08-10 07:18:04 +000066}
67
68enum {
69 MSG_CREATE_SESSIONDESCRIPTION_SUCCESS,
70 MSG_CREATE_SESSIONDESCRIPTION_FAILED,
71 MSG_GENERATE_IDENTITY,
72};
73
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000074struct CreateSessionDescriptionMsg : public rtc::MessageData {
wu@webrtc.org91053e72013-08-10 07:18:04 +000075 explicit CreateSessionDescriptionMsg(
76 webrtc::CreateSessionDescriptionObserver* observer)
77 : observer(observer) {
78 }
79
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000080 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer;
wu@webrtc.org91053e72013-08-10 07:18:04 +000081 std::string error;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000082 rtc::scoped_ptr<webrtc::SessionDescriptionInterface> description;
wu@webrtc.org91053e72013-08-10 07:18:04 +000083};
wu@webrtc.org91053e72013-08-10 07:18:04 +000084} // namespace
85
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +000086void WebRtcIdentityRequestObserver::OnFailure(int error) {
87 SignalRequestFailed(error);
88}
89
90void WebRtcIdentityRequestObserver::OnSuccess(
91 const std::string& der_cert, const std::string& der_private_key) {
92 std::string pem_cert = rtc::SSLIdentity::DerToPem(
93 rtc::kPemTypeCertificate,
94 reinterpret_cast<const unsigned char*>(der_cert.data()),
95 der_cert.length());
96 std::string pem_key = rtc::SSLIdentity::DerToPem(
97 rtc::kPemTypeRsaPrivateKey,
98 reinterpret_cast<const unsigned char*>(der_private_key.data()),
99 der_private_key.length());
100 rtc::SSLIdentity* identity =
101 rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert);
102 SignalIdentityReady(identity);
103}
104
105void WebRtcIdentityRequestObserver::OnSuccessWithIdentityObj(
106 rtc::scoped_ptr<rtc::SSLIdentity> identity) {
107 SignalIdentityReady(identity.release());
108}
109
wu@webrtc.org91053e72013-08-10 07:18:04 +0000110// static
111void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
112 const SessionDescriptionInterface* source_desc,
113 SessionDescriptionInterface* dest_desc) {
114 if (!source_desc)
115 return;
116 for (size_t m = 0; m < source_desc->number_of_mediasections() &&
117 m < dest_desc->number_of_mediasections(); ++m) {
118 const IceCandidateCollection* source_candidates =
119 source_desc->candidates(m);
120 const IceCandidateCollection* dest_candidates = dest_desc->candidates(m);
121 for (size_t n = 0; n < source_candidates->count(); ++n) {
122 const IceCandidateInterface* new_candidate = source_candidates->at(n);
123 if (!dest_candidates->HasCandidate(new_candidate))
124 dest_desc->AddCandidate(source_candidates->at(n));
125 }
126 }
127}
128
129WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000130 rtc::Thread* signaling_thread,
wu@webrtc.org91053e72013-08-10 07:18:04 +0000131 cricket::ChannelManager* channel_manager,
132 MediaStreamSignaling* mediastream_signaling,
133 DTLSIdentityServiceInterface* dtls_identity_service,
134 WebRtcSession* session,
135 const std::string& session_id,
136 cricket::DataChannelType dct,
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +0000137 bool dtls_enabled)
wu@webrtc.org91053e72013-08-10 07:18:04 +0000138 : signaling_thread_(signaling_thread),
139 mediastream_signaling_(mediastream_signaling),
140 session_desc_factory_(channel_manager, &transport_desc_factory_),
141 // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp
142 // as the session id and session version. To simplify, it should be fine
143 // to just use a random number as session id and start version from
144 // |kInitSessionVersion|.
145 session_version_(kInitSessionVersion),
146 identity_service_(dtls_identity_service),
147 session_(session),
148 session_id_(session_id),
149 data_channel_type_(dct),
150 identity_request_state_(IDENTITY_NOT_NEEDED) {
jlmiller@webrtc.org804eb462015-02-20 02:20:03 +0000151 transport_desc_factory_.set_protocol(cricket::ICEPROTO_RFC5245);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000152 session_desc_factory_.set_add_legacy_streams(false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000153 // SRTP-SDES is disabled if DTLS is on.
154 SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000155
wu@webrtc.org364f2042013-11-20 21:49:41 +0000156 if (!dtls_enabled) {
157 return;
158 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000159
wu@webrtc.org364f2042013-11-20 21:49:41 +0000160 if (identity_service_.get()) {
161 identity_request_observer_ =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000162 new rtc::RefCountedObject<WebRtcIdentityRequestObserver>();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000163
wu@webrtc.org364f2042013-11-20 21:49:41 +0000164 identity_request_observer_->SignalRequestFailed.connect(
165 this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed);
166 identity_request_observer_->SignalIdentityReady.connect(
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000167 this, &WebRtcSessionDescriptionFactory::SetIdentity);
wu@webrtc.org364f2042013-11-20 21:49:41 +0000168
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000169 if (identity_service_->RequestIdentity(
170 DtlsIdentityStore::kIdentityName,
171 DtlsIdentityStore::kIdentityName,
172 identity_request_observer_)) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000173 LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sent DTLS identity request.";
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +0000174 identity_request_state_ = IDENTITY_WAITING;
wu@webrtc.org364f2042013-11-20 21:49:41 +0000175 } else {
176 LOG(LS_ERROR) << "Failed to send DTLS identity request.";
177 identity_request_state_ = IDENTITY_FAILED;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000178 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000179 } else {
180 identity_request_state_ = IDENTITY_WAITING;
181 // Do not generate the identity in the constructor since the caller has
182 // not got a chance to connect to SignalIdentityReady.
183 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY, NULL);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000184 }
185}
186
187WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() {
tommi0f620f42015-07-09 03:25:02 -0700188 ASSERT(signaling_thread_->IsCurrent());
189
190 // Fail any requests that were asked for before identity generation completed.
191 FailPendingRequests(kFailedDueToSessionShutdown);
192
193 // Process all pending notifications in the message queue. If we don't do
194 // this, requests will linger and not know they succeeded or failed.
195 rtc::MessageList list;
196 signaling_thread_->Clear(this, rtc::MQID_ANY, &list);
197 for (auto& msg : list)
198 OnMessage(&msg);
199
wu@webrtc.org91053e72013-08-10 07:18:04 +0000200 transport_desc_factory_.set_identity(NULL);
201}
202
203void WebRtcSessionDescriptionFactory::CreateOffer(
204 CreateSessionDescriptionObserver* observer,
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000205 const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
206 cricket::MediaSessionOptions session_options;
207
wu@webrtc.org91053e72013-08-10 07:18:04 +0000208 std::string error = "CreateOffer";
209 if (identity_request_state_ == IDENTITY_FAILED) {
210 error += kFailedDueToIdentityFailed;
211 LOG(LS_ERROR) << error;
212 PostCreateSessionDescriptionFailed(observer, error);
213 return;
214 }
215
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000216 if (!mediastream_signaling_->GetOptionsForOffer(options,
217 &session_options)) {
218 error += " called with invalid options.";
wu@webrtc.org91053e72013-08-10 07:18:04 +0000219 LOG(LS_ERROR) << error;
220 PostCreateSessionDescriptionFailed(observer, error);
221 return;
222 }
223
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000224 if (!ValidStreams(session_options.streams)) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000225 error += " called with invalid media streams.";
226 LOG(LS_ERROR) << error;
227 PostCreateSessionDescriptionFailed(observer, error);
228 return;
229 }
230
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +0000231 if (data_channel_type_ == cricket::DCT_SCTP &&
232 mediastream_signaling_->HasDataChannels()) {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000233 session_options.data_channel_type = cricket::DCT_SCTP;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000234 }
235
236 CreateSessionDescriptionRequest request(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000237 CreateSessionDescriptionRequest::kOffer, observer, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000238 if (identity_request_state_ == IDENTITY_WAITING) {
239 create_session_description_requests_.push(request);
240 } else {
241 ASSERT(identity_request_state_ == IDENTITY_SUCCEEDED ||
242 identity_request_state_ == IDENTITY_NOT_NEEDED);
243 InternalCreateOffer(request);
244 }
245}
246
247void WebRtcSessionDescriptionFactory::CreateAnswer(
248 CreateSessionDescriptionObserver* observer,
249 const MediaConstraintsInterface* constraints) {
250 std::string error = "CreateAnswer";
251 if (identity_request_state_ == IDENTITY_FAILED) {
252 error += kFailedDueToIdentityFailed;
253 LOG(LS_ERROR) << error;
254 PostCreateSessionDescriptionFailed(observer, error);
255 return;
256 }
257 if (!session_->remote_description()) {
258 error += " can't be called before SetRemoteDescription.";
259 LOG(LS_ERROR) << error;
260 PostCreateSessionDescriptionFailed(observer, error);
261 return;
262 }
263 if (session_->remote_description()->type() !=
264 JsepSessionDescription::kOffer) {
265 error += " failed because remote_description is not an offer.";
266 LOG(LS_ERROR) << error;
267 PostCreateSessionDescriptionFailed(observer, error);
268 return;
269 }
270
271 cricket::MediaSessionOptions options;
272 if (!mediastream_signaling_->GetOptionsForAnswer(constraints, &options)) {
273 error += " called with invalid constraints.";
274 LOG(LS_ERROR) << error;
275 PostCreateSessionDescriptionFailed(observer, error);
276 return;
277 }
278 if (!ValidStreams(options.streams)) {
279 error += " called with invalid media streams.";
280 LOG(LS_ERROR) << error;
281 PostCreateSessionDescriptionFailed(observer, error);
282 return;
283 }
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000284 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
285 // are not signaled in the SDP so does not go through that path and must be
286 // handled here.
287 if (data_channel_type_ == cricket::DCT_SCTP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000288 options.data_channel_type = cricket::DCT_SCTP;
289 }
290
291 CreateSessionDescriptionRequest request(
292 CreateSessionDescriptionRequest::kAnswer, observer, options);
293 if (identity_request_state_ == IDENTITY_WAITING) {
294 create_session_description_requests_.push(request);
295 } else {
296 ASSERT(identity_request_state_ == IDENTITY_SUCCEEDED ||
297 identity_request_state_ == IDENTITY_NOT_NEEDED);
298 InternalCreateAnswer(request);
299 }
300}
301
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000302void WebRtcSessionDescriptionFactory::SetSdesPolicy(
303 cricket::SecurePolicy secure_policy) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000304 session_desc_factory_.set_secure(secure_policy);
305}
306
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000307cricket::SecurePolicy WebRtcSessionDescriptionFactory::SdesPolicy() const {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000308 return session_desc_factory_.secure();
309}
310
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000311void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000312 switch (msg->message_id) {
313 case MSG_CREATE_SESSIONDESCRIPTION_SUCCESS: {
314 CreateSessionDescriptionMsg* param =
315 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
316 param->observer->OnSuccess(param->description.release());
317 delete param;
318 break;
319 }
320 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: {
321 CreateSessionDescriptionMsg* param =
322 static_cast<CreateSessionDescriptionMsg*>(msg->pdata);
323 param->observer->OnFailure(param->error);
324 delete param;
325 break;
326 }
327 case MSG_GENERATE_IDENTITY: {
328 LOG(LS_INFO) << "Generating identity.";
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000329 SetIdentity(rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000330 break;
331 }
332 default:
333 ASSERT(false);
334 break;
335 }
336}
337
338void WebRtcSessionDescriptionFactory::InternalCreateOffer(
339 CreateSessionDescriptionRequest request) {
340 cricket::SessionDescription* desc(
341 session_desc_factory_.CreateOffer(
342 request.options,
343 static_cast<cricket::BaseSession*>(session_)->local_description()));
344 // RFC 3264
345 // When issuing an offer that modifies the session,
346 // the "o=" line of the new SDP MUST be identical to that in the
347 // previous SDP, except that the version in the origin field MUST
348 // increment by one from the previous SDP.
349
350 // Just increase the version number by one each time when a new offer
351 // is created regardless if it's identical to the previous one or not.
352 // The |session_version_| is a uint64, the wrap around should not happen.
353 ASSERT(session_version_ + 1 > session_version_);
354 JsepSessionDescription* offer(new JsepSessionDescription(
355 JsepSessionDescription::kOffer));
356 if (!offer->Initialize(desc, session_id_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000357 rtc::ToString(session_version_++))) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000358 delete offer;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000359 PostCreateSessionDescriptionFailed(request.observer,
360 "Failed to initialize the offer.");
wu@webrtc.org91053e72013-08-10 07:18:04 +0000361 return;
362 }
363 if (session_->local_description() &&
364 !request.options.transport_options.ice_restart) {
365 // Include all local ice candidates in the SessionDescription unless
366 // the an ice restart has been requested.
367 CopyCandidatesFromSessionDescription(session_->local_description(), offer);
368 }
369 PostCreateSessionDescriptionSucceeded(request.observer, offer);
370}
371
372void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
373 CreateSessionDescriptionRequest request) {
374 // According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1
375 // an answer should also contain new ice ufrag and password if an offer has
376 // been received with new ufrag and password.
377 request.options.transport_options.ice_restart = session_->IceRestartPending();
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000378 // We should pass current ssl role to the transport description factory, if
379 // there is already an existing ongoing session.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000380 rtc::SSLRole ssl_role;
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000381 if (session_->GetSslRole(&ssl_role)) {
382 request.options.transport_options.prefer_passive_role =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000383 (rtc::SSL_SERVER == ssl_role);
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000384 }
wu@webrtc.org91053e72013-08-10 07:18:04 +0000385
386 cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer(
387 static_cast<cricket::BaseSession*>(session_)->remote_description(),
388 request.options,
389 static_cast<cricket::BaseSession*>(session_)->local_description()));
390 // RFC 3264
391 // If the answer is different from the offer in any way (different IP
392 // addresses, ports, etc.), the origin line MUST be different in the answer.
393 // In that case, the version number in the "o=" line of the answer is
394 // unrelated to the version number in the o line of the offer.
395 // Get a new version number by increasing the |session_version_answer_|.
396 // The |session_version_| is a uint64, the wrap around should not happen.
397 ASSERT(session_version_ + 1 > session_version_);
398 JsepSessionDescription* answer(new JsepSessionDescription(
399 JsepSessionDescription::kAnswer));
400 if (!answer->Initialize(desc, session_id_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000401 rtc::ToString(session_version_++))) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000402 delete answer;
403 PostCreateSessionDescriptionFailed(request.observer,
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000404 "Failed to initialize the answer.");
wu@webrtc.org91053e72013-08-10 07:18:04 +0000405 return;
406 }
407 if (session_->local_description() &&
408 !request.options.transport_options.ice_restart) {
409 // Include all local ice candidates in the SessionDescription unless
410 // the remote peer has requested an ice restart.
411 CopyCandidatesFromSessionDescription(session_->local_description(), answer);
412 }
413 session_->ResetIceRestartLatch();
414 PostCreateSessionDescriptionSucceeded(request.observer, answer);
415}
416
tommi0f620f42015-07-09 03:25:02 -0700417void WebRtcSessionDescriptionFactory::FailPendingRequests(
418 const std::string& reason) {
419 ASSERT(signaling_thread_->IsCurrent());
420 while (!create_session_description_requests_.empty()) {
421 const CreateSessionDescriptionRequest& request =
422 create_session_description_requests_.front();
423 PostCreateSessionDescriptionFailed(request.observer,
424 ((request.type == CreateSessionDescriptionRequest::kOffer) ?
425 "CreateOffer" : "CreateAnswer") + reason);
426 create_session_description_requests_.pop();
427 }
428}
429
wu@webrtc.org91053e72013-08-10 07:18:04 +0000430void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionFailed(
431 CreateSessionDescriptionObserver* observer, const std::string& error) {
432 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
433 msg->error = error;
434 signaling_thread_->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000435 LOG(LS_ERROR) << "Create SDP failed: " << error;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000436}
437
438void WebRtcSessionDescriptionFactory::PostCreateSessionDescriptionSucceeded(
439 CreateSessionDescriptionObserver* observer,
440 SessionDescriptionInterface* description) {
441 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
442 msg->description.reset(description);
443 signaling_thread_->Post(this, MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, msg);
444}
445
446void WebRtcSessionDescriptionFactory::OnIdentityRequestFailed(int error) {
447 ASSERT(signaling_thread_->IsCurrent());
448
449 LOG(LS_ERROR) << "Async identity request failed: error = " << error;
450 identity_request_state_ = IDENTITY_FAILED;
451
tommi0f620f42015-07-09 03:25:02 -0700452 FailPendingRequests(kFailedDueToIdentityFailed);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000453}
454
wu@webrtc.org91053e72013-08-10 07:18:04 +0000455void WebRtcSessionDescriptionFactory::SetIdentity(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000456 rtc::SSLIdentity* identity) {
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000457 LOG(LS_VERBOSE) << "Setting new identity";
458
wu@webrtc.org91053e72013-08-10 07:18:04 +0000459 identity_request_state_ = IDENTITY_SUCCEEDED;
460 SignalIdentityReady(identity);
461
462 transport_desc_factory_.set_identity(identity);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000463 transport_desc_factory_.set_secure(cricket::SEC_ENABLED);
464
465 while (!create_session_description_requests_.empty()) {
466 if (create_session_description_requests_.front().type ==
467 CreateSessionDescriptionRequest::kOffer) {
468 InternalCreateOffer(create_session_description_requests_.front());
469 } else {
470 InternalCreateAnswer(create_session_description_requests_.front());
471 }
472 create_session_description_requests_.pop();
473 }
474}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000475} // namespace webrtc