Chromium Code Reviews| Index: webrtc/api/dtlsidentitystore.cc |
| diff --git a/webrtc/api/dtlsidentitystore.cc b/webrtc/api/dtlsidentitystore.cc |
| index 3652e21877c7a702f2a484527e3865c7e9835593..620b942102fe8fcd22d7ab5fecd5ee8cd4611ff1 100644 |
| --- a/webrtc/api/dtlsidentitystore.cc |
| +++ b/webrtc/api/dtlsidentitystore.cc |
| @@ -10,282 +10,10 @@ |
| #include "webrtc/api/dtlsidentitystore.h" |
| -#include <utility> |
| - |
| -#include "webrtc/api/webrtcsessiondescriptionfactory.h" |
| -#include "webrtc/base/logging.h" |
| - |
| -using webrtc::DtlsIdentityRequestObserver; |
| - |
| namespace webrtc { |
| // Passed to SSLIdentity::Generate, "WebRTC". Used for the certificates' |
| // subject and issuer name. |
| const char kIdentityName[] = "WebRTC"; |
|
tommi
2016/06/01 12:36:31
can we move this constant to where it is used and
hbos
2016/06/01 13:41:48
Yes, but can I do that in a separate CL?
Turns ou
|
| -namespace { |
| - |
| -enum { |
| - MSG_DESTROY, |
| - MSG_GENERATE_IDENTITY, |
| - MSG_GENERATE_IDENTITY_RESULT |
| -}; |
| - |
| -// A |DtlsIdentityRequestObserver| that informs an |
| -// |RTCCertificateGeneratorCallback| of the result of an identity request. On |
| -// success, a certificate is created using the identity before passing it to |
| -// the callback. |
| -class RTCCertificateStoreCallbackObserver |
| - : public webrtc::DtlsIdentityRequestObserver { |
| - public: |
| - RTCCertificateStoreCallbackObserver( |
| - const rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback>& callback) |
| - : callback_(callback) {} |
| - |
| - private: |
| - void OnFailure(int error) override { |
| - LOG(LS_WARNING) << "DtlsIdentityRequestObserver failure code: " << error; |
| - Callback(nullptr); |
| - } |
| - void OnSuccess(const std::string& der_cert, |
| - const std::string& der_private_key) override { |
| - std::string pem_cert = rtc::SSLIdentity::DerToPem( |
| - rtc::kPemTypeCertificate, |
| - reinterpret_cast<const unsigned char*>(der_cert.data()), |
| - der_cert.length()); |
| - std::string pem_key = rtc::SSLIdentity::DerToPem( |
| - rtc::kPemTypeRsaPrivateKey, |
| - reinterpret_cast<const unsigned char*>(der_private_key.data()), |
| - der_private_key.length()); |
| - std::unique_ptr<rtc::SSLIdentity> identity( |
| - rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert)); |
| - OnSuccess(std::move(identity)); |
| - } |
| - void OnSuccess(std::unique_ptr<rtc::SSLIdentity> identity) override { |
| - Callback(rtc::RTCCertificate::Create(std::move(identity))); |
| - } |
| - |
| - void Callback(rtc::scoped_refptr<rtc::RTCCertificate> certificate) { |
| - if (certificate) |
| - callback_->OnSuccess(certificate); |
| - else |
| - callback_->OnFailure(); |
| - } |
| - |
| - rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback> callback_; |
| -}; |
| - |
| -} // namespace |
| - |
| -// This class runs on the worker thread to generate the identity. It's necessary |
| -// to separate this class from DtlsIdentityStore so that it can live on the |
| -// worker thread after DtlsIdentityStore is destroyed. |
| -class DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>, |
| - public rtc::MessageHandler { |
| - public: |
| - WorkerTask(DtlsIdentityStoreImpl* store, rtc::KeyType key_type) |
| - : signaling_thread_(rtc::Thread::Current()), |
| - store_(store), |
| - key_type_(key_type) { |
| - store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed); |
| - } |
| - |
| - virtual ~WorkerTask() { RTC_DCHECK(signaling_thread_->IsCurrent()); } |
| - |
| - private: |
| - void GenerateIdentity_w() { |
| - LOG(LS_INFO) << "Generating identity, using keytype " << key_type_; |
| - std::unique_ptr<rtc::SSLIdentity> identity( |
| - rtc::SSLIdentity::Generate(kIdentityName, key_type_)); |
| - |
| - // Posting to |this| avoids touching |store_| on threads other than |
| - // |signaling_thread_| and thus avoids having to use locks. |
| - IdentityResultMessageData* msg = new IdentityResultMessageData( |
| - new IdentityResult(key_type_, std::move(identity))); |
| - signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); |
| - } |
| - |
| - void OnMessage(rtc::Message* msg) override { |
| - switch (msg->message_id) { |
| - case MSG_GENERATE_IDENTITY: |
| - // This message always runs on the worker thread. |
| - GenerateIdentity_w(); |
| - |
| - // Must delete |this|, owned by msg->pdata, on the signaling thread to |
| - // avoid races on disconnecting the signal. |
| - signaling_thread_->Post(this, MSG_DESTROY, msg->pdata); |
| - break; |
| - case MSG_GENERATE_IDENTITY_RESULT: |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - { |
| - std::unique_ptr<IdentityResultMessageData> pdata( |
| - static_cast<IdentityResultMessageData*>(msg->pdata)); |
| - if (store_) { |
| - store_->OnIdentityGenerated(pdata->data()->key_type_, |
| - std::move(pdata->data()->identity_)); |
| - } |
| - } |
| - break; |
| - case MSG_DESTROY: |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - delete msg->pdata; |
| - // |this| has now been deleted. Don't touch member variables. |
| - break; |
| - default: |
| - RTC_CHECK(false) << "Unexpected message type"; |
| - } |
| - } |
| - |
| - void OnStoreDestroyed() { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - store_ = nullptr; |
| - } |
| - |
| - rtc::Thread* const signaling_thread_; |
| - DtlsIdentityStoreImpl* store_; // Only touched on |signaling_thread_|. |
| - const rtc::KeyType key_type_; |
| -}; |
| - |
| -DtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread, |
| - rtc::Thread* worker_thread) |
| - : signaling_thread_(signaling_thread), |
| - worker_thread_(worker_thread), |
| - request_info_() { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| -} |
| - |
| -DtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - SignalDestroyed(); |
| -} |
| - |
| -void DtlsIdentityStoreImpl::RequestIdentity( |
| - const rtc::KeyParams& key_params, |
| - const rtc::Optional<uint64_t>& expires_ms, |
| - const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - RTC_DCHECK(observer); |
| - |
| - // Dropping parameterization and |expires_ms|. |
| - // TODO(hbos,torbjorng): Use parameterizaton/expiration. webrtc:5092. |
| - GenerateIdentity(key_params.type(), observer); |
| -} |
| - |
| -void DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - switch (msg->message_id) { |
| - case MSG_GENERATE_IDENTITY_RESULT: { |
| - std::unique_ptr<IdentityResultMessageData> pdata( |
| - static_cast<IdentityResultMessageData*>(msg->pdata)); |
| - OnIdentityGenerated(pdata->data()->key_type_, |
| - std::move(pdata->data()->identity_)); |
| - break; |
| - } |
| - } |
| -} |
| - |
| -bool DtlsIdentityStoreImpl::HasFreeIdentityForTesting( |
| - rtc::KeyType key_type) const { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - return request_info_[key_type].free_identity_.get() != nullptr; |
| -} |
| - |
| -void DtlsIdentityStoreImpl::GenerateIdentity( |
| - rtc::KeyType key_type, |
| - const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - |
| - // Enqueue observer to be informed when generation of |key_type| is completed. |
| - if (observer.get()) { |
| - request_info_[key_type].request_observers_.push(observer); |
| - |
| - // Already have a free identity generated? |
| - if (request_info_[key_type].free_identity_.get()) { |
| - // Return identity async - post even though we are on |signaling_thread_|. |
| - LOG(LS_VERBOSE) << "Using a free DTLS identity."; |
| - ++request_info_[key_type].gen_in_progress_counts_; |
| - IdentityResultMessageData* msg = |
| - new IdentityResultMessageData(new IdentityResult( |
| - key_type, std::move(request_info_[key_type].free_identity_))); |
| - signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); |
| - return; |
| - } |
| - |
| - // Free identity in the process of being generated? |
| - if (request_info_[key_type].gen_in_progress_counts_ == |
| - request_info_[key_type].request_observers_.size()) { |
| - // No need to do anything, the free identity will be returned to the |
| - // observer in a MSG_GENERATE_IDENTITY_RESULT. |
| - return; |
| - } |
| - } |
| - |
| - // Enqueue/Post a worker task to do the generation. |
| - ++request_info_[key_type].gen_in_progress_counts_; |
| - WorkerTask* task = new WorkerTask(this, key_type); // Post 1 task/request. |
| - // The WorkerTask is owned by the message data to make sure it will not be |
| - // leaked even if the task does not get run. |
| - WorkerTaskMessageData* msg = new WorkerTaskMessageData(task); |
| - worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); |
| -} |
| - |
| -void DtlsIdentityStoreImpl::OnIdentityGenerated( |
| - rtc::KeyType key_type, |
| - std::unique_ptr<rtc::SSLIdentity> identity) { |
| - RTC_DCHECK(signaling_thread_->IsCurrent()); |
| - |
| - RTC_DCHECK(request_info_[key_type].gen_in_progress_counts_); |
| - --request_info_[key_type].gen_in_progress_counts_; |
| - |
| - rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver> observer; |
| - if (!request_info_[key_type].request_observers_.empty()) { |
| - observer = request_info_[key_type].request_observers_.front(); |
| - request_info_[key_type].request_observers_.pop(); |
| - } |
| - |
| - if (observer.get() == nullptr) { |
| - // No observer - store result in |free_identities_|. |
| - RTC_DCHECK(!request_info_[key_type].free_identity_.get()); |
| - request_info_[key_type].free_identity_.swap(identity); |
| - if (request_info_[key_type].free_identity_.get()) |
| - LOG(LS_VERBOSE) << "A free DTLS identity was saved."; |
| - else |
| - LOG(LS_WARNING) << "Failed to generate DTLS identity (preemptively)."; |
| - } else { |
| - // Return the result to the observer. |
| - if (identity.get()) { |
| - LOG(LS_VERBOSE) << "A DTLS identity is returned to an observer."; |
| - observer->OnSuccess(std::move(identity)); |
| - } else { |
| - LOG(LS_WARNING) << "Failed to generate DTLS identity."; |
| - observer->OnFailure(0); |
| - } |
| - |
| - // Preemptively generate another identity of the same type? |
| - if (worker_thread_ != signaling_thread_ && // Only do in background thread. |
| - key_type == rtc::KT_RSA && // Only necessary for RSA. |
| - !request_info_[key_type].free_identity_.get() && |
| - request_info_[key_type].request_observers_.size() == |
| - request_info_[key_type].gen_in_progress_counts_) { |
| - GenerateIdentity(key_type, nullptr); |
| - } |
| - } |
| -} |
| - |
| -RTCCertificateGeneratorStoreWrapper::RTCCertificateGeneratorStoreWrapper( |
| - std::unique_ptr<DtlsIdentityStoreInterface> store) |
| - : store_(std::move(store)) { |
| - RTC_DCHECK(store_); |
| -} |
| - |
| -void RTCCertificateGeneratorStoreWrapper::GenerateCertificateAsync( |
| - const rtc::KeyParams& key_params, |
| - const rtc::Optional<uint64_t>& expires_ms, |
| - const rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback>& callback) { |
| - store_->RequestIdentity( |
| - key_params, |
| - expires_ms, |
| - new rtc::RefCountedObject<RTCCertificateStoreCallbackObserver>(callback)); |
| -} |
| - |
| } // namespace webrtc |