| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * libjingle | 2  * libjingle | 
| 3  * Copyright 2015 Google Inc. | 3  * Copyright 2015 Google Inc. | 
| 4  * | 4  * | 
| 5  * Redistribution and use in source and binary forms, with or without | 5  * Redistribution and use in source and binary forms, with or without | 
| 6  * modification, are permitted provided that the following conditions are met: | 6  * modification, are permitted provided that the following conditions are met: | 
| 7  * | 7  * | 
| 8  *  1. Redistributions of source code must retain the above copyright notice, | 8  *  1. Redistributions of source code must retain the above copyright notice, | 
| 9  *     this list of conditions and the following disclaimer. | 9  *     this list of conditions and the following disclaimer. | 
| 10  *  2. Redistributions in binary form must reproduce the above copyright notice, | 10  *  2. Redistributions in binary form must reproduce the above copyright notice, | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 54 class DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>, | 54 class DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>, | 
| 55                                           public rtc::MessageHandler { | 55                                           public rtc::MessageHandler { | 
| 56  public: | 56  public: | 
| 57   WorkerTask(DtlsIdentityStoreImpl* store, rtc::KeyType key_type) | 57   WorkerTask(DtlsIdentityStoreImpl* store, rtc::KeyType key_type) | 
| 58       : signaling_thread_(rtc::Thread::Current()), | 58       : signaling_thread_(rtc::Thread::Current()), | 
| 59         store_(store), | 59         store_(store), | 
| 60         key_type_(key_type) { | 60         key_type_(key_type) { | 
| 61     store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed); | 61     store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed); | 
| 62   } | 62   } | 
| 63 | 63 | 
| 64   virtual ~WorkerTask() { DCHECK(signaling_thread_->IsCurrent()); } | 64   virtual ~WorkerTask() { RTC_DCHECK(signaling_thread_->IsCurrent()); } | 
| 65 | 65 | 
| 66  private: | 66  private: | 
| 67   void GenerateIdentity_w() { | 67   void GenerateIdentity_w() { | 
| 68     LOG(LS_INFO) << "Generating identity, using keytype " << key_type_; | 68     LOG(LS_INFO) << "Generating identity, using keytype " << key_type_; | 
| 69     rtc::scoped_ptr<rtc::SSLIdentity> identity( | 69     rtc::scoped_ptr<rtc::SSLIdentity> identity( | 
| 70         rtc::SSLIdentity::Generate(kIdentityName, key_type_)); | 70         rtc::SSLIdentity::Generate(kIdentityName, key_type_)); | 
| 71 | 71 | 
| 72     // Posting to |this| avoids touching |store_| on threads other than | 72     // Posting to |this| avoids touching |store_| on threads other than | 
| 73     // |signaling_thread_| and thus avoids having to use locks. | 73     // |signaling_thread_| and thus avoids having to use locks. | 
| 74     IdentityResultMessageData* msg = new IdentityResultMessageData( | 74     IdentityResultMessageData* msg = new IdentityResultMessageData( | 
| 75         new IdentityResult(key_type_, identity.Pass())); | 75         new IdentityResult(key_type_, identity.Pass())); | 
| 76     signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); | 76     signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); | 
| 77   } | 77   } | 
| 78 | 78 | 
| 79   void OnMessage(rtc::Message* msg) override { | 79   void OnMessage(rtc::Message* msg) override { | 
| 80     switch (msg->message_id) { | 80     switch (msg->message_id) { | 
| 81       case MSG_GENERATE_IDENTITY: | 81       case MSG_GENERATE_IDENTITY: | 
| 82         // This message always runs on the worker thread. | 82         // This message always runs on the worker thread. | 
| 83         GenerateIdentity_w(); | 83         GenerateIdentity_w(); | 
| 84 | 84 | 
| 85         // Must delete |this|, owned by msg->pdata, on the signaling thread to | 85         // Must delete |this|, owned by msg->pdata, on the signaling thread to | 
| 86         // avoid races on disconnecting the signal. | 86         // avoid races on disconnecting the signal. | 
| 87         signaling_thread_->Post(this, MSG_DESTROY, msg->pdata); | 87         signaling_thread_->Post(this, MSG_DESTROY, msg->pdata); | 
| 88         break; | 88         break; | 
| 89       case MSG_GENERATE_IDENTITY_RESULT: | 89       case MSG_GENERATE_IDENTITY_RESULT: | 
| 90         DCHECK(signaling_thread_->IsCurrent()); | 90         RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 91         { | 91         { | 
| 92           rtc::scoped_ptr<IdentityResultMessageData> pdata( | 92           rtc::scoped_ptr<IdentityResultMessageData> pdata( | 
| 93               static_cast<IdentityResultMessageData*>(msg->pdata)); | 93               static_cast<IdentityResultMessageData*>(msg->pdata)); | 
| 94           if (store_) { | 94           if (store_) { | 
| 95             store_->OnIdentityGenerated(pdata->data()->key_type_, | 95             store_->OnIdentityGenerated(pdata->data()->key_type_, | 
| 96                                         pdata->data()->identity_.Pass()); | 96                                         pdata->data()->identity_.Pass()); | 
| 97           } | 97           } | 
| 98         } | 98         } | 
| 99         break; | 99         break; | 
| 100       case MSG_DESTROY: | 100       case MSG_DESTROY: | 
| 101         DCHECK(signaling_thread_->IsCurrent()); | 101         RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 102         delete msg->pdata; | 102         delete msg->pdata; | 
| 103         // |this| has now been deleted. Don't touch member variables. | 103         // |this| has now been deleted. Don't touch member variables. | 
| 104         break; | 104         break; | 
| 105       default: | 105       default: | 
| 106         CHECK(false) << "Unexpected message type"; | 106         RTC_CHECK(false) << "Unexpected message type"; | 
| 107     } | 107     } | 
| 108   } | 108   } | 
| 109 | 109 | 
| 110   void OnStoreDestroyed() { | 110   void OnStoreDestroyed() { | 
| 111     DCHECK(signaling_thread_->IsCurrent()); | 111     RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 112     store_ = nullptr; | 112     store_ = nullptr; | 
| 113   } | 113   } | 
| 114 | 114 | 
| 115   rtc::Thread* const signaling_thread_; | 115   rtc::Thread* const signaling_thread_; | 
| 116   DtlsIdentityStoreImpl* store_;  // Only touched on |signaling_thread_|. | 116   DtlsIdentityStoreImpl* store_;  // Only touched on |signaling_thread_|. | 
| 117   const rtc::KeyType key_type_; | 117   const rtc::KeyType key_type_; | 
| 118 }; | 118 }; | 
| 119 | 119 | 
| 120 DtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread, | 120 DtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread, | 
| 121                                              rtc::Thread* worker_thread) | 121                                              rtc::Thread* worker_thread) | 
| 122     : signaling_thread_(signaling_thread), | 122     : signaling_thread_(signaling_thread), | 
| 123       worker_thread_(worker_thread), | 123       worker_thread_(worker_thread), | 
| 124       request_info_() { | 124       request_info_() { | 
| 125   DCHECK(signaling_thread_->IsCurrent()); | 125   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 126   // Preemptively generate identities unless the worker thread and signaling | 126   // Preemptively generate identities unless the worker thread and signaling | 
| 127   // thread are the same (only do preemptive work in the background). | 127   // thread are the same (only do preemptive work in the background). | 
| 128   if (worker_thread_ != signaling_thread_) { | 128   if (worker_thread_ != signaling_thread_) { | 
| 129     // Only necessary for RSA. | 129     // Only necessary for RSA. | 
| 130     GenerateIdentity(rtc::KT_RSA, nullptr); | 130     GenerateIdentity(rtc::KT_RSA, nullptr); | 
| 131   } | 131   } | 
| 132 } | 132 } | 
| 133 | 133 | 
| 134 DtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() { | 134 DtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() { | 
| 135   DCHECK(signaling_thread_->IsCurrent()); | 135   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 136   SignalDestroyed(); | 136   SignalDestroyed(); | 
| 137 } | 137 } | 
| 138 | 138 | 
| 139 void DtlsIdentityStoreImpl::RequestIdentity( | 139 void DtlsIdentityStoreImpl::RequestIdentity( | 
| 140     rtc::KeyType key_type, | 140     rtc::KeyType key_type, | 
| 141     const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) { | 141     const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) { | 
| 142   DCHECK(signaling_thread_->IsCurrent()); | 142   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 143   DCHECK(observer); | 143   RTC_DCHECK(observer); | 
| 144 | 144 | 
| 145   GenerateIdentity(key_type, observer); | 145   GenerateIdentity(key_type, observer); | 
| 146 } | 146 } | 
| 147 | 147 | 
| 148 void DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) { | 148 void DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) { | 
| 149   DCHECK(signaling_thread_->IsCurrent()); | 149   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 150   switch (msg->message_id) { | 150   switch (msg->message_id) { | 
| 151     case MSG_GENERATE_IDENTITY_RESULT: { | 151     case MSG_GENERATE_IDENTITY_RESULT: { | 
| 152       rtc::scoped_ptr<IdentityResultMessageData> pdata( | 152       rtc::scoped_ptr<IdentityResultMessageData> pdata( | 
| 153           static_cast<IdentityResultMessageData*>(msg->pdata)); | 153           static_cast<IdentityResultMessageData*>(msg->pdata)); | 
| 154       OnIdentityGenerated(pdata->data()->key_type_, | 154       OnIdentityGenerated(pdata->data()->key_type_, | 
| 155                           pdata->data()->identity_.Pass()); | 155                           pdata->data()->identity_.Pass()); | 
| 156       break; | 156       break; | 
| 157     } | 157     } | 
| 158   } | 158   } | 
| 159 } | 159 } | 
| 160 | 160 | 
| 161 bool DtlsIdentityStoreImpl::HasFreeIdentityForTesting( | 161 bool DtlsIdentityStoreImpl::HasFreeIdentityForTesting( | 
| 162     rtc::KeyType key_type) const { | 162     rtc::KeyType key_type) const { | 
| 163   DCHECK(signaling_thread_->IsCurrent()); | 163   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 164   return request_info_[key_type].free_identity_.get() != nullptr; | 164   return request_info_[key_type].free_identity_.get() != nullptr; | 
| 165 } | 165 } | 
| 166 | 166 | 
| 167 void DtlsIdentityStoreImpl::GenerateIdentity( | 167 void DtlsIdentityStoreImpl::GenerateIdentity( | 
| 168     rtc::KeyType key_type, | 168     rtc::KeyType key_type, | 
| 169     const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) { | 169     const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer) { | 
| 170   DCHECK(signaling_thread_->IsCurrent()); | 170   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 171 | 171 | 
| 172   // Enqueue observer to be informed when generation of |key_type| is completed. | 172   // Enqueue observer to be informed when generation of |key_type| is completed. | 
| 173   if (observer.get()) { | 173   if (observer.get()) { | 
| 174     request_info_[key_type].request_observers_.push(observer); | 174     request_info_[key_type].request_observers_.push(observer); | 
| 175 | 175 | 
| 176     // Already have a free identity generated? | 176     // Already have a free identity generated? | 
| 177     if (request_info_[key_type].free_identity_.get()) { | 177     if (request_info_[key_type].free_identity_.get()) { | 
| 178       // Return identity async - post even though we are on |signaling_thread_|. | 178       // Return identity async - post even though we are on |signaling_thread_|. | 
| 179       LOG(LS_VERBOSE) << "Using a free DTLS identity."; | 179       LOG(LS_VERBOSE) << "Using a free DTLS identity."; | 
| 180       ++request_info_[key_type].gen_in_progress_counts_; | 180       ++request_info_[key_type].gen_in_progress_counts_; | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 198   ++request_info_[key_type].gen_in_progress_counts_; | 198   ++request_info_[key_type].gen_in_progress_counts_; | 
| 199   WorkerTask* task = new WorkerTask(this, key_type);  // Post 1 task/request. | 199   WorkerTask* task = new WorkerTask(this, key_type);  // Post 1 task/request. | 
| 200   // The WorkerTask is owned by the message data to make sure it will not be | 200   // The WorkerTask is owned by the message data to make sure it will not be | 
| 201   // leaked even if the task does not get run. | 201   // leaked even if the task does not get run. | 
| 202   WorkerTaskMessageData* msg = new WorkerTaskMessageData(task); | 202   WorkerTaskMessageData* msg = new WorkerTaskMessageData(task); | 
| 203   worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); | 203   worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); | 
| 204 } | 204 } | 
| 205 | 205 | 
| 206 void DtlsIdentityStoreImpl::OnIdentityGenerated( | 206 void DtlsIdentityStoreImpl::OnIdentityGenerated( | 
| 207     rtc::KeyType key_type, rtc::scoped_ptr<rtc::SSLIdentity> identity) { | 207     rtc::KeyType key_type, rtc::scoped_ptr<rtc::SSLIdentity> identity) { | 
| 208   DCHECK(signaling_thread_->IsCurrent()); | 208   RTC_DCHECK(signaling_thread_->IsCurrent()); | 
| 209 | 209 | 
| 210   DCHECK(request_info_[key_type].gen_in_progress_counts_); | 210   RTC_DCHECK(request_info_[key_type].gen_in_progress_counts_); | 
| 211   --request_info_[key_type].gen_in_progress_counts_; | 211   --request_info_[key_type].gen_in_progress_counts_; | 
| 212 | 212 | 
| 213   rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver> observer; | 213   rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver> observer; | 
| 214   if (!request_info_[key_type].request_observers_.empty()) { | 214   if (!request_info_[key_type].request_observers_.empty()) { | 
| 215     observer = request_info_[key_type].request_observers_.front(); | 215     observer = request_info_[key_type].request_observers_.front(); | 
| 216     request_info_[key_type].request_observers_.pop(); | 216     request_info_[key_type].request_observers_.pop(); | 
| 217   } | 217   } | 
| 218 | 218 | 
| 219   if (observer.get() == nullptr) { | 219   if (observer.get() == nullptr) { | 
| 220     // No observer - store result in |free_identities_|. | 220     // No observer - store result in |free_identities_|. | 
| 221     DCHECK(!request_info_[key_type].free_identity_.get()); | 221     RTC_DCHECK(!request_info_[key_type].free_identity_.get()); | 
| 222     request_info_[key_type].free_identity_.swap(identity); | 222     request_info_[key_type].free_identity_.swap(identity); | 
| 223     if (request_info_[key_type].free_identity_.get()) | 223     if (request_info_[key_type].free_identity_.get()) | 
| 224       LOG(LS_VERBOSE) << "A free DTLS identity was saved."; | 224       LOG(LS_VERBOSE) << "A free DTLS identity was saved."; | 
| 225     else | 225     else | 
| 226       LOG(LS_WARNING) << "Failed to generate DTLS identity (preemptively)."; | 226       LOG(LS_WARNING) << "Failed to generate DTLS identity (preemptively)."; | 
| 227   } else { | 227   } else { | 
| 228     // Return the result to the observer. | 228     // Return the result to the observer. | 
| 229     if (identity.get()) { | 229     if (identity.get()) { | 
| 230       LOG(LS_VERBOSE) << "A DTLS identity is returned to an observer."; | 230       LOG(LS_VERBOSE) << "A DTLS identity is returned to an observer."; | 
| 231       observer->OnSuccess(identity.Pass()); | 231       observer->OnSuccess(identity.Pass()); | 
| 232     } else { | 232     } else { | 
| 233       LOG(LS_WARNING) << "Failed to generate DTLS identity."; | 233       LOG(LS_WARNING) << "Failed to generate DTLS identity."; | 
| 234       observer->OnFailure(0); | 234       observer->OnFailure(0); | 
| 235     } | 235     } | 
| 236 | 236 | 
| 237     // Preemptively generate another identity of the same type? | 237     // Preemptively generate another identity of the same type? | 
| 238     if (worker_thread_ != signaling_thread_ && // Only do in background thread. | 238     if (worker_thread_ != signaling_thread_ && // Only do in background thread. | 
| 239         key_type == rtc::KT_RSA &&             // Only necessary for RSA. | 239         key_type == rtc::KT_RSA &&             // Only necessary for RSA. | 
| 240         !request_info_[key_type].free_identity_.get() && | 240         !request_info_[key_type].free_identity_.get() && | 
| 241         request_info_[key_type].request_observers_.size() <= | 241         request_info_[key_type].request_observers_.size() <= | 
| 242             request_info_[key_type].gen_in_progress_counts_) { | 242             request_info_[key_type].gen_in_progress_counts_) { | 
| 243       GenerateIdentity(key_type, nullptr); | 243       GenerateIdentity(key_type, nullptr); | 
| 244     } | 244     } | 
| 245   } | 245   } | 
| 246 } | 246 } | 
| 247 | 247 | 
| 248 }  // namespace webrtc | 248 }  // namespace webrtc | 
| OLD | NEW | 
|---|