1254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org/*
2254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * libjingle
3254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * Copyright 2015 Google Inc.
4254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *
5254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * Redistribution and use in source and binary forms, with or without
6254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * modification, are permitted provided that the following conditions are met:
7254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *
8254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
9254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *     this list of conditions and the following disclaimer.
10254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
11254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *     this list of conditions and the following disclaimer in the documentation
12254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *     and/or other materials provided with the distribution.
13254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *  3. The name of the author may not be used to endorse or promote products
14254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *     derived from this software without specific prior written permission.
15254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org *
16254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org */
27254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org
28254840692ef450d94d6a4b075eb139bb34305ec0jiayl@webrtc.org#include "talk/app/webrtc/dtlsidentitystore.h"
2961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
300eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg#include <utility>
310eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg
3261e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
3361e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org#include "webrtc/base/logging.h"
3461e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
355e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmusing webrtc::DtlsIdentityRequestObserver;
3661e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
3761e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.orgnamespace webrtc {
3861e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
395e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström// Passed to SSLIdentity::Generate, "WebRTC". Used for the certificates'
405e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström// subject and issuer name.
4197579a4e122ad42592b5d7da9475e128da63a948glaznevconst char kIdentityName[] = "WebRTC";
425e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström
4361e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.orgnamespace {
4461e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
4561e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.orgenum {
46d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu  MSG_DESTROY,
4761e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org  MSG_GENERATE_IDENTITY,
485e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  MSG_GENERATE_IDENTITY_RESULT
4961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org};
5061e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
5161e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}  // namespace
5261e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
53d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org// This class runs on the worker thread to generate the identity. It's necessary
54d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org// to separate this class from DtlsIdentityStore so that it can live on the
55d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org// worker thread after DtlsIdentityStore is destroyed.
565e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmclass DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>,
575e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström                                          public rtc::MessageHandler {
58d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org public:
595e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  WorkerTask(DtlsIdentityStoreImpl* store, rtc::KeyType key_type)
605e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      : signaling_thread_(rtc::Thread::Current()),
615e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        store_(store),
625e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        key_type_(key_type) {
63d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org    store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed);
64532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi  }
65d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
6691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  virtual ~WorkerTask() { RTC_DCHECK(signaling_thread_->IsCurrent()); }
67d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
68532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi private:
69532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi  void GenerateIdentity_w() {
70b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund    LOG(LS_INFO) << "Generating identity, using keytype " << key_type_;
71d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org    rtc::scoped_ptr<rtc::SSLIdentity> identity(
72b6d4ec418504fd947c6f96829c73180e9487e203Torbjorn Granlund        rtc::SSLIdentity::Generate(kIdentityName, key_type_));
73d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
745e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // Posting to |this| avoids touching |store_| on threads other than
755e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // |signaling_thread_| and thus avoids having to use locks.
765e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    IdentityResultMessageData* msg = new IdentityResultMessageData(
770eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg        new IdentityResult(key_type_, std::move(identity)));
785e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
79d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  }
80d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
81d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  void OnMessage(rtc::Message* msg) override {
82d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu    switch (msg->message_id) {
83d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu      case MSG_GENERATE_IDENTITY:
84532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi        // This message always runs on the worker thread.
85532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi        GenerateIdentity_w();
86d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu
87d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu        // Must delete |this|, owned by msg->pdata, on the signaling thread to
88d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu        // avoid races on disconnecting the signal.
89d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu        signaling_thread_->Post(this, MSG_DESTROY, msg->pdata);
90d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu        break;
915e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      case MSG_GENERATE_IDENTITY_RESULT:
9291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg        RTC_DCHECK(signaling_thread_->IsCurrent());
935e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        {
945e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström          rtc::scoped_ptr<IdentityResultMessageData> pdata(
955e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström              static_cast<IdentityResultMessageData*>(msg->pdata));
965e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström          if (store_) {
975e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström            store_->OnIdentityGenerated(pdata->data()->key_type_,
980eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg                                        std::move(pdata->data()->identity_));
995e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström          }
1005e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        }
1015e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        break;
102d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu      case MSG_DESTROY:
10391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg        RTC_DCHECK(signaling_thread_->IsCurrent());
104d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu        delete msg->pdata;
105532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi        // |this| has now been deleted. Don't touch member variables.
106d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu        break;
107d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu      default:
10891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg        RTC_CHECK(false) << "Unexpected message type";
109d61ebda94168e9057cfb3e27778401eafe52f163Jiayang Liu    }
110d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  }
111d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
112d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  void OnStoreDestroyed() {
11391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(signaling_thread_->IsCurrent());
1145e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    store_ = nullptr;
115d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  }
116d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
117532caeae2d3e8c043f61f72d2f909c081ce2e6b4Tommi  rtc::Thread* const signaling_thread_;
1185e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  DtlsIdentityStoreImpl* store_;  // Only touched on |signaling_thread_|.
1195e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  const rtc::KeyType key_type_;
120d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org};
121d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
1225e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik BoströmDtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread,
1235e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström                                             rtc::Thread* worker_thread)
12461e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org    : signaling_thread_(signaling_thread),
12561e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org      worker_thread_(worker_thread),
1265e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      request_info_() {
12791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
1285e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  // Preemptively generate identities unless the worker thread and signaling
1295e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  // thread are the same (only do preemptive work in the background).
130d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  if (worker_thread_ != signaling_thread_) {
1315e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // Only necessary for RSA.
1325e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    GenerateIdentity(rtc::KT_RSA, nullptr);
133d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  }
13461e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}
13561e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
1365e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik BoströmDtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() {
13791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
1385e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  SignalDestroyed();
1395e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström}
14061e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
1415e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmvoid DtlsIdentityStoreImpl::RequestIdentity(
1425e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    rtc::KeyType key_type,
1435e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) {
14491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
14591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(observer);
14661e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
1475e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  GenerateIdentity(key_type, observer);
14861e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}
14961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
1505e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmvoid DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) {
15191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
15261e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org  switch (msg->message_id) {
15361e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org    case MSG_GENERATE_IDENTITY_RESULT: {
15461e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org      rtc::scoped_ptr<IdentityResultMessageData> pdata(
15561e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org          static_cast<IdentityResultMessageData*>(msg->pdata));
1565e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      OnIdentityGenerated(pdata->data()->key_type_,
1570eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg                          std::move(pdata->data()->identity_));
15861e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org      break;
15961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org    }
16061e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org  }
16161e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}
16261e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
1635e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmbool DtlsIdentityStoreImpl::HasFreeIdentityForTesting(
1645e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    rtc::KeyType key_type) const {
16591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
1665e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  return request_info_[key_type].free_identity_.get() != nullptr;
16761e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}
16861e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
1695e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmvoid DtlsIdentityStoreImpl::GenerateIdentity(
1705e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    rtc::KeyType key_type,
1715e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) {
17291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
1735e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström
1745e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  // Enqueue observer to be informed when generation of |key_type| is completed.
1755e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  if (observer.get()) {
1765e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    request_info_[key_type].request_observers_.push(observer);
1775e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström
1785e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // Already have a free identity generated?
1795e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    if (request_info_[key_type].free_identity_.get()) {
1805e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      // Return identity async - post even though we are on |signaling_thread_|.
1815e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      LOG(LS_VERBOSE) << "Using a free DTLS identity.";
1825e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      ++request_info_[key_type].gen_in_progress_counts_;
1830eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg      IdentityResultMessageData* msg =
1840eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg          new IdentityResultMessageData(new IdentityResult(
1850eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg              key_type, std::move(request_info_[key_type].free_identity_)));
1865e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
1875e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      return;
1885e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    }
1895e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström
1905e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // Free identity in the process of being generated?
1915e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    if (request_info_[key_type].gen_in_progress_counts_ ==
1925e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström            request_info_[key_type].request_observers_.size()) {
1935e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      // No need to do anything, the free identity will be returned to the
1945e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      // observer in a MSG_GENERATE_IDENTITY_RESULT.
1955e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      return;
1965e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    }
1975e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  }
198d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org
1995e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  // Enqueue/Post a worker task to do the generation.
2005e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  ++request_info_[key_type].gen_in_progress_counts_;
2015e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  WorkerTask* task = new WorkerTask(this, key_type);  // Post 1 task/request.
202d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  // The WorkerTask is owned by the message data to make sure it will not be
203d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  // leaked even if the task does not get run.
2045e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  WorkerTaskMessageData* msg = new WorkerTaskMessageData(task);
205d83f4eff84d872da3e38e1a61d669fc407ce7adfjiayl@webrtc.org  worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg);
20661e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}
20761e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
2085e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boströmvoid DtlsIdentityStoreImpl::OnIdentityGenerated(
2095e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    rtc::KeyType key_type, rtc::scoped_ptr<rtc::SSLIdentity> identity) {
21091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(signaling_thread_->IsCurrent());
21161e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
21291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(request_info_[key_type].gen_in_progress_counts_);
2135e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  --request_info_[key_type].gen_in_progress_counts_;
21461e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
2155e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver> observer;
2165e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  if (!request_info_[key_type].request_observers_.empty()) {
2175e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    observer = request_info_[key_type].request_observers_.front();
2185e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    request_info_[key_type].request_observers_.pop();
21961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org  }
22061e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
2215e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström  if (observer.get() == nullptr) {
2225e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // No observer - store result in |free_identities_|.
22391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(!request_info_[key_type].free_identity_.get());
2245e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    request_info_[key_type].free_identity_.swap(identity);
2255e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    if (request_info_[key_type].free_identity_.get())
2265e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      LOG(LS_VERBOSE) << "A free DTLS identity was saved.";
2275e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    else
2285e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      LOG(LS_WARNING) << "Failed to generate DTLS identity (preemptively).";
22961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org  } else {
2305e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // Return the result to the observer.
2315e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    if (identity.get()) {
2325e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      LOG(LS_VERBOSE) << "A DTLS identity is returned to an observer.";
2330eb15ed7b806125774bd13fb214aeb403e2c6857kwiberg      observer->OnSuccess(std::move(identity));
2345e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    } else {
2355e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      LOG(LS_WARNING) << "Failed to generate DTLS identity.";
2365e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      observer->OnFailure(0);
2375e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    }
23861e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
2395e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    // Preemptively generate another identity of the same type?
2405e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    if (worker_thread_ != signaling_thread_ && // Only do in background thread.
2415e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        key_type == rtc::KT_RSA &&             // Only necessary for RSA.
2425e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        !request_info_[key_type].free_identity_.get() &&
2435e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström        request_info_[key_type].request_observers_.size() <=
2445e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström            request_info_[key_type].gen_in_progress_counts_) {
2455e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström      GenerateIdentity(key_type, nullptr);
2465e56c5927e097f095aef2e9f7be49fd3d59221e1Henrik Boström    }
24761e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org  }
24861e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}
24961e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org
25061e00b0bcab899a32f14c1e2e0f4b7f316cc1f03jiayl@webrtc.org}  // namespace webrtc
251