diff --git a/talk/app/webrtc/dtlsidentityservice.cc b/talk/app/webrtc/dtlsidentityservice.cc deleted file mode 100644 index b4b7279c82..0000000000 --- a/talk/app/webrtc/dtlsidentityservice.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - * libjingle - * Copyright 2015 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "talk/app/webrtc/dtlsidentityservice.h" - -#include "talk/app/webrtc/dtlsidentitystore.h" -#include "webrtc/base/logging.h" - -namespace webrtc { - -bool DtlsIdentityService::RequestIdentity( - const std::string& identity_name, - const std::string& common_name, - webrtc::DTLSIdentityRequestObserver* observer) { - if (identity_name != DtlsIdentityStore::kIdentityName || - common_name != DtlsIdentityStore::kIdentityName) { - LOG(LS_WARNING) << "DtlsIdentityService::RequestIdentity called with " - << "unsupported params, identity_name=" << identity_name - << ", common_name=" << common_name; - return false; - } - store_->RequestIdentity(observer); - return true; -} - -} // namespace webrtc diff --git a/talk/app/webrtc/dtlsidentityservice.h b/talk/app/webrtc/dtlsidentityservice.h deleted file mode 100644 index 760cab4565..0000000000 --- a/talk/app/webrtc/dtlsidentityservice.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * libjingle - * Copyright 2015 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TALK_APP_WEBRTC_DTLSIDENTITYSERVICE_H_ -#define TALK_APP_WEBRTC_DTLSIDENTITYSERVICE_H_ - -#include - -#include "talk/app/webrtc/peerconnectioninterface.h" - -namespace webrtc { - -class DtlsIdentityStore; - -// This class forwards the request to DtlsIdentityStore to generate the -// identity. -class DtlsIdentityService : public webrtc::DTLSIdentityServiceInterface { - public: - explicit DtlsIdentityService(DtlsIdentityStore* store) : store_(store) {} - - // DTLSIdentityServiceInterface impl. - // |identity_name| and |common_name| must equal to - // DtlsIdentityStore::kIdentityName, otherwise the request will fail and false - // will be returned. - bool RequestIdentity(const std::string& identity_name, - const std::string& common_name, - webrtc::DTLSIdentityRequestObserver* observer) override; - - private: - DtlsIdentityStore* store_; -}; - -} // namespace webrtc - -#endif // TALK_APP_WEBRTC_DTLSIDENTITYSERVICE_H_ diff --git a/talk/app/webrtc/dtlsidentitystore.cc b/talk/app/webrtc/dtlsidentitystore.cc index 554a84a06f..eb9e5a5c86 100644 --- a/talk/app/webrtc/dtlsidentitystore.cc +++ b/talk/app/webrtc/dtlsidentitystore.cc @@ -30,47 +30,52 @@ #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" #include "webrtc/base/logging.h" -using webrtc::DTLSIdentityRequestObserver; +using webrtc::DtlsIdentityRequestObserver; namespace webrtc { +// Passed to SSLIdentity::Generate, "WebRTC". Used for the certificates' +// subject and issuer name. +static const char kIdentityName[] = "WebRTC"; + namespace { enum { MSG_DESTROY, MSG_GENERATE_IDENTITY, - MSG_GENERATE_IDENTITY_RESULT, - MSG_RETURN_FREE_IDENTITY + MSG_GENERATE_IDENTITY_RESULT }; -typedef rtc::ScopedMessageData IdentityResultMessageData; - } // 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 DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>, - public rtc::MessageHandler { +class DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>, + public rtc::MessageHandler { public: - explicit WorkerTask(DtlsIdentityStore* store) - : signaling_thread_(rtc::Thread::Current()), store_(store) { + 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() { DCHECK(rtc::Thread::Current() == signaling_thread_); } + virtual ~WorkerTask() { DCHECK(signaling_thread_->IsCurrent()); } private: void GenerateIdentity_w() { + // TODO(hbos): Use key_type_ when torbjorng's CL has landed. + LOG(LS_INFO) << "Generating identity. Key type (TODO(hbos): should use): " + << key_type_; rtc::scoped_ptr identity( - rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName)); + rtc::SSLIdentity::Generate(kIdentityName)); - { - rtc::CritScope cs(&cs_); - if (store_) { - store_->PostGenerateIdentityResult_w(identity.Pass()); - } - } + // 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_, identity.Pass())); + signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); } void OnMessage(rtc::Message* msg) override { @@ -83,8 +88,19 @@ class DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>, // avoid races on disconnecting the signal. signaling_thread_->Post(this, MSG_DESTROY, msg->pdata); break; + case MSG_GENERATE_IDENTITY_RESULT: + DCHECK(signaling_thread_->IsCurrent()); + { + rtc::scoped_ptr pdata( + static_cast(msg->pdata)); + if (store_) { + store_->OnIdentityGenerated(pdata->data()->key_type_, + pdata->data()->identity_.Pass()); + } + } + break; case MSG_DESTROY: - DCHECK(rtc::Thread::Current() == signaling_thread_); + DCHECK(signaling_thread_->IsCurrent()); delete msg->pdata; // |this| has now been deleted. Don't touch member variables. break; @@ -94,141 +110,141 @@ class DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>, } void OnStoreDestroyed() { - rtc::CritScope cs(&cs_); - store_ = NULL; + DCHECK(signaling_thread_->IsCurrent()); + store_ = nullptr; } rtc::Thread* const signaling_thread_; - rtc::CriticalSection cs_; - DtlsIdentityStore* store_; + DtlsIdentityStoreImpl* store_; // Only touched on |signaling_thread_|. + const rtc::KeyType key_type_; }; -// Arbitrary constant used as common name for the identity. -// Chosen to make the certificates more readable. -const char DtlsIdentityStore::kIdentityName[] = "WebRTC"; - -DtlsIdentityStore::DtlsIdentityStore(rtc::Thread* signaling_thread, - rtc::Thread* worker_thread) +DtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread, + rtc::Thread* worker_thread) : signaling_thread_(signaling_thread), worker_thread_(worker_thread), - pending_jobs_(0) {} + request_info_() { + DCHECK(signaling_thread_->IsCurrent()); + // Preemptively generate identities unless the worker thread and signaling + // thread are the same (only do preemptive work in the background). + if (worker_thread_ != signaling_thread_) { + // Only necessary for RSA. + GenerateIdentity(rtc::KT_RSA, nullptr); + } +} -DtlsIdentityStore::~DtlsIdentityStore() { +DtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() { + DCHECK(signaling_thread_->IsCurrent()); SignalDestroyed(); } -void DtlsIdentityStore::Initialize() { - DCHECK(rtc::Thread::Current() == signaling_thread_); - // Do not aggressively generate the free identity if the worker thread and the - // signaling thread are the same. - if (worker_thread_ != signaling_thread_) { - GenerateIdentity(); - } -} - -void DtlsIdentityStore::RequestIdentity(DTLSIdentityRequestObserver* observer) { - DCHECK(rtc::Thread::Current() == signaling_thread_); +void DtlsIdentityStoreImpl::RequestIdentity( + rtc::KeyType key_type, + const rtc::scoped_refptr& observer) { + DCHECK(signaling_thread_->IsCurrent()); DCHECK(observer); - // Must return the free identity async. - if (free_identity_.get()) { - IdentityResultMessageData* msg = - new IdentityResultMessageData(free_identity_.release()); - signaling_thread_->Post(this, MSG_RETURN_FREE_IDENTITY, msg); - } - - pending_observers_.push(observer); - GenerateIdentity(); + GenerateIdentity(key_type, observer); } -void DtlsIdentityStore::OnMessage(rtc::Message* msg) { - DCHECK(rtc::Thread::Current() == signaling_thread_); +void DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) { + DCHECK(signaling_thread_->IsCurrent()); switch (msg->message_id) { case MSG_GENERATE_IDENTITY_RESULT: { rtc::scoped_ptr pdata( static_cast(msg->pdata)); - OnIdentityGenerated(pdata->data().Pass()); - break; - } - case MSG_RETURN_FREE_IDENTITY: { - rtc::scoped_ptr pdata( - static_cast(msg->pdata)); - ReturnIdentity(pdata->data().Pass()); + OnIdentityGenerated(pdata->data()->key_type_, + pdata->data()->identity_.Pass()); break; } } } -bool DtlsIdentityStore::HasFreeIdentityForTesting() const { - DCHECK(rtc::Thread::Current() == signaling_thread_); - return free_identity_.get() != nullptr; +bool DtlsIdentityStoreImpl::HasFreeIdentityForTesting( + rtc::KeyType key_type) const { + DCHECK(signaling_thread_->IsCurrent()); + return request_info_[key_type].free_identity_.get() != nullptr; } -void DtlsIdentityStore::GenerateIdentity() { - DCHECK(rtc::Thread::Current() == signaling_thread_); - pending_jobs_++; - LOG(LS_VERBOSE) << "New DTLS identity generation is posted, " - << "pending_identities=" << pending_jobs_; +void DtlsIdentityStoreImpl::GenerateIdentity( + rtc::KeyType key_type, + const rtc::scoped_refptr& observer) { + DCHECK(signaling_thread_->IsCurrent()); - WorkerTask* task = new WorkerTask(this); + // 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, + request_info_[key_type].free_identity_.Pass())); + 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. - IdentityTaskMessageData* msg = new IdentityTaskMessageData(task); + WorkerTaskMessageData* msg = new WorkerTaskMessageData(task); worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); } -void DtlsIdentityStore::OnIdentityGenerated( - rtc::scoped_ptr identity) { - DCHECK(rtc::Thread::Current() == signaling_thread_); +void DtlsIdentityStoreImpl::OnIdentityGenerated( + rtc::KeyType key_type, rtc::scoped_ptr identity) { + DCHECK(signaling_thread_->IsCurrent()); - pending_jobs_--; - LOG(LS_VERBOSE) << "A DTLS identity generation job returned, " - << "pending_identities=" << pending_jobs_; + DCHECK(request_info_[key_type].gen_in_progress_counts_); + --request_info_[key_type].gen_in_progress_counts_; - if (pending_observers_.empty()) { - if (!free_identity_.get()) { - free_identity_.reset(identity.release()); - LOG(LS_VERBOSE) << "A free DTLS identity is saved"; - } - return; + rtc::scoped_refptr observer; + if (!request_info_[key_type].request_observers_.empty()) { + observer = request_info_[key_type].request_observers_.front(); + request_info_[key_type].request_observers_.pop(); } - ReturnIdentity(identity.Pass()); -} -void DtlsIdentityStore::ReturnIdentity( - rtc::scoped_ptr identity) { - DCHECK(rtc::Thread::Current() == signaling_thread_); - DCHECK(!free_identity_.get()); - DCHECK(!pending_observers_.empty()); - - rtc::scoped_refptr observer = - pending_observers_.front(); - pending_observers_.pop(); - - if (identity.get()) { - observer->OnSuccessWithIdentityObj(identity.Pass()); + if (observer.get() == nullptr) { + // No observer - store result in |free_identities_|. + 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 { - // Pass an arbitrary error code. - observer->OnFailure(0); - LOG(LS_WARNING) << "Failed to generate SSL identity"; - } + // Return the result to the observer. + if (identity.get()) { + LOG(LS_VERBOSE) << "A DTLS identity is returned to an observer."; + observer->OnSuccess(identity.Pass()); + } else { + LOG(LS_WARNING) << "Failed to generate DTLS identity."; + observer->OnFailure(0); + } - // Do not aggressively generate the free identity if the worker thread and the - // signaling thread are the same. - if (worker_thread_ != signaling_thread_ && - pending_observers_.empty() && - pending_jobs_ == 0) { - // Generate a free identity in the background. - GenerateIdentity(); + // 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); + } } } -void DtlsIdentityStore::PostGenerateIdentityResult_w( - rtc::scoped_ptr identity) { - DCHECK(rtc::Thread::Current() == worker_thread_); - - IdentityResultMessageData* msg = - new IdentityResultMessageData(identity.release()); - signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); -} } // namespace webrtc diff --git a/talk/app/webrtc/dtlsidentitystore.h b/talk/app/webrtc/dtlsidentitystore.h index b655a7d1b2..6282870cfd 100644 --- a/talk/app/webrtc/dtlsidentitystore.h +++ b/talk/app/webrtc/dtlsidentitystore.h @@ -84,57 +84,78 @@ class DtlsIdentityStoreInterface { public: virtual ~DtlsIdentityStoreInterface() { } + // The |observer| will be called when the requested identity is ready, or when + // identity generation fails. virtual void RequestIdentity( rtc::KeyType key_type, const rtc::scoped_refptr& observer) = 0; }; -// This class implements an in-memory DTLS identity store, which generates the -// DTLS identity on the worker thread. -// APIs calls must be made on the signaling thread and the callbacks are also -// called on the signaling thread. -class DtlsIdentityStore : public rtc::MessageHandler { +// The WebRTC default implementation of DtlsIdentityStoreInterface. +// Identity generation is performed on the worker thread. +class DtlsIdentityStoreImpl : public DtlsIdentityStoreInterface, + public rtc::MessageHandler { public: - static const char kIdentityName[]; + // This will start to preemptively generating an RSA identity in the + // background if the worker thread is not the same as the signaling thread. + DtlsIdentityStoreImpl(rtc::Thread* signaling_thread, + rtc::Thread* worker_thread); + ~DtlsIdentityStoreImpl() override; - DtlsIdentityStore(rtc::Thread* signaling_thread, - rtc::Thread* worker_thread); - virtual ~DtlsIdentityStore(); - - // Initialize will start generating the free identity in the background. - void Initialize(); - - // The |observer| will be called when the requested identity is ready, or when - // identity generation fails. - void RequestIdentity(webrtc::DTLSIdentityRequestObserver* observer); + // DtlsIdentityStoreInterface override; + void RequestIdentity( + rtc::KeyType key_type, + const rtc::scoped_refptr& observer) override; // rtc::MessageHandler override; void OnMessage(rtc::Message* msg) override; - // Returns true if there is a free identity, used for unit tests. - bool HasFreeIdentityForTesting() const; + // Returns true if there is a free RSA identity, used for unit tests. + bool HasFreeIdentityForTesting(rtc::KeyType key_type) const; private: - sigslot::signal0<> SignalDestroyed; + void GenerateIdentity( + rtc::KeyType key_type, + const rtc::scoped_refptr& observer); + void OnIdentityGenerated(rtc::KeyType key_type, + rtc::scoped_ptr identity); + class WorkerTask; - typedef rtc::ScopedMessageData - IdentityTaskMessageData; + typedef rtc::ScopedMessageData + WorkerTaskMessageData; - void GenerateIdentity(); - void OnIdentityGenerated(rtc::scoped_ptr identity); - void ReturnIdentity(rtc::scoped_ptr identity); + // A key type-identity pair. + struct IdentityResult { + IdentityResult(rtc::KeyType key_type, + rtc::scoped_ptr identity) + : key_type_(key_type), identity_(identity.Pass()) {} - void PostGenerateIdentityResult_w(rtc::scoped_ptr identity); + rtc::KeyType key_type_; + rtc::scoped_ptr identity_; + }; + + typedef rtc::ScopedMessageData IdentityResultMessageData; + + sigslot::signal0<> SignalDestroyed; rtc::Thread* const signaling_thread_; + // TODO(hbos): RSA generation is slow and would be VERY slow if we switch over + // to 2048, DtlsIdentityStore should use a new thread and not the "general + // purpose" worker thread. rtc::Thread* const worker_thread_; - // These members should be accessed on the signaling thread only. - int pending_jobs_; - rtc::scoped_ptr free_identity_; - typedef std::queue> - ObserverList; - ObserverList pending_observers_; + struct RequestInfo { + RequestInfo() + : request_observers_(), gen_in_progress_counts_(0), free_identity_() {} + + std::queue> + request_observers_; + size_t gen_in_progress_counts_; + rtc::scoped_ptr free_identity_; + }; + + // One RequestInfo per KeyType. Only touch on the |signaling_thread_|. + RequestInfo request_info_[rtc::KT_LAST]; }; } // namespace webrtc diff --git a/talk/app/webrtc/dtlsidentitystore_unittest.cc b/talk/app/webrtc/dtlsidentitystore_unittest.cc index 12f58feea5..3e21a47fd5 100644 --- a/talk/app/webrtc/dtlsidentitystore_unittest.cc +++ b/talk/app/webrtc/dtlsidentitystore_unittest.cc @@ -32,12 +32,12 @@ #include "webrtc/base/logging.h" #include "webrtc/base/ssladapter.h" -using webrtc::DtlsIdentityStore; +using webrtc::DtlsIdentityStoreImpl; static const int kTimeoutMs = 10000; class MockDtlsIdentityRequestObserver : - public webrtc::DTLSIdentityRequestObserver { + public webrtc::DtlsIdentityRequestObserver { public: MockDtlsIdentityRequestObserver() : call_back_called_(false), last_request_success_(false) {} @@ -47,12 +47,11 @@ class MockDtlsIdentityRequestObserver : last_request_success_ = false; } void OnSuccess(const std::string& der_cert, - const std::string& der_private_key) { + const std::string& der_private_key) override { LOG(LS_WARNING) << "The string version of OnSuccess is called unexpectedly"; EXPECT_TRUE(false); } - void OnSuccessWithIdentityObj( - rtc::scoped_ptr identity) override { + void OnSuccess(rtc::scoped_ptr identity) override { EXPECT_FALSE(call_back_called_); call_back_called_ = true; last_request_success_ = true; @@ -80,12 +79,11 @@ class DtlsIdentityStoreTest : public testing::Test { protected: DtlsIdentityStoreTest() : worker_thread_(new rtc::Thread()), - store_(new DtlsIdentityStore(rtc::Thread::Current(), - worker_thread_.get())), + store_(new DtlsIdentityStoreImpl(rtc::Thread::Current(), + worker_thread_.get())), observer_( new rtc::RefCountedObject()) { CHECK(worker_thread_->Start()); - store_->Initialize(); } ~DtlsIdentityStoreTest() {} @@ -97,30 +95,55 @@ class DtlsIdentityStoreTest : public testing::Test { } rtc::scoped_ptr worker_thread_; - rtc::scoped_ptr store_; + rtc::scoped_ptr store_; rtc::scoped_refptr observer_; }; -TEST_F(DtlsIdentityStoreTest, RequestIdentitySuccess) { - EXPECT_TRUE_WAIT(store_->HasFreeIdentityForTesting(), kTimeoutMs); +TEST_F(DtlsIdentityStoreTest, RequestIdentitySuccessRSA) { + EXPECT_TRUE_WAIT(store_->HasFreeIdentityForTesting(rtc::KT_RSA), kTimeoutMs); - store_->RequestIdentity(observer_.get()); + store_->RequestIdentity(rtc::KT_RSA, observer_.get()); EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); - EXPECT_TRUE_WAIT(store_->HasFreeIdentityForTesting(), kTimeoutMs); + EXPECT_TRUE_WAIT(store_->HasFreeIdentityForTesting(rtc::KT_RSA), kTimeoutMs); observer_->Reset(); // Verifies that the callback is async when a free identity is ready. - store_->RequestIdentity(observer_.get()); + store_->RequestIdentity(rtc::KT_RSA, observer_.get()); EXPECT_FALSE(observer_->call_back_called()); EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); } -TEST_F(DtlsIdentityStoreTest, DeleteStoreEarlyNoCrash) { - EXPECT_FALSE(store_->HasFreeIdentityForTesting()); +TEST_F(DtlsIdentityStoreTest, RequestIdentitySuccessECDSA) { + // Since store currently does not preemptively generate free ECDSA identities + // we do not invoke HasFreeIdentityForTesting between requests. - store_->RequestIdentity(observer_.get()); + store_->RequestIdentity(rtc::KT_ECDSA, observer_.get()); + EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); + + observer_->Reset(); + + // Verifies that the callback is async when a free identity is ready. + store_->RequestIdentity(rtc::KT_ECDSA, observer_.get()); + EXPECT_FALSE(observer_->call_back_called()); + EXPECT_TRUE_WAIT(observer_->LastRequestSucceeded(), kTimeoutMs); +} + +TEST_F(DtlsIdentityStoreTest, DeleteStoreEarlyNoCrashRSA) { + EXPECT_FALSE(store_->HasFreeIdentityForTesting(rtc::KT_RSA)); + + store_->RequestIdentity(rtc::KT_RSA, observer_.get()); + store_.reset(); + + worker_thread_->Stop(); + EXPECT_FALSE(observer_->call_back_called()); +} + +TEST_F(DtlsIdentityStoreTest, DeleteStoreEarlyNoCrashECDSA) { + EXPECT_FALSE(store_->HasFreeIdentityForTesting(rtc::KT_ECDSA)); + + store_->RequestIdentity(rtc::KT_ECDSA, observer_.get()); store_.reset(); worker_thread_->Stop(); diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc index 6932f82072..ef5836bbdd 100644 --- a/talk/app/webrtc/peerconnection.cc +++ b/talk/app/webrtc/peerconnection.cc @@ -349,7 +349,7 @@ bool PeerConnection::Initialize( const PeerConnectionInterface::RTCConfiguration& configuration, const MediaConstraintsInterface* constraints, PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, PeerConnectionObserver* observer) { ASSERT(observer != NULL); if (!observer) @@ -404,7 +404,7 @@ bool PeerConnection::Initialize( // Initialize the WebRtcSession. It creates transport channels etc. if (!session_->Initialize(factory_->options(), constraints, - dtls_identity_service, configuration)) + dtls_identity_store.Pass(), configuration)) return false; // Register PeerConnection as receiver of local ice candidates. diff --git a/talk/app/webrtc/peerconnection.h b/talk/app/webrtc/peerconnection.h index 0162596616..df4cb78fc1 100644 --- a/talk/app/webrtc/peerconnection.h +++ b/talk/app/webrtc/peerconnection.h @@ -30,6 +30,7 @@ #include +#include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/mediastreamsignaling.h" #include "talk/app/webrtc/peerconnectionfactory.h" #include "talk/app/webrtc/peerconnectioninterface.h" @@ -61,7 +62,7 @@ class PeerConnection : public PeerConnectionInterface, const PeerConnectionInterface::RTCConfiguration& configuration, const MediaConstraintsInterface* constraints, PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, PeerConnectionObserver* observer); virtual rtc::scoped_refptr local_streams(); virtual rtc::scoped_refptr remote_streams(); @@ -157,14 +158,6 @@ class PeerConnection : public PeerConnectionInterface, cricket::BaseSession::State state); void ChangeSignalingState(SignalingState signaling_state); - bool DoInitialize(IceTransportsType type, - const StunConfigurations& stun_config, - const TurnConfigurations& turn_config, - const MediaConstraintsInterface* constraints, - PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, - PeerConnectionObserver* observer); - rtc::Thread* signaling_thread() const { return factory_->signaling_thread(); } diff --git a/talk/app/webrtc/peerconnection_unittest.cc b/talk/app/webrtc/peerconnection_unittest.cc index fd58ecdff6..08e6cef1c6 100644 --- a/talk/app/webrtc/peerconnection_unittest.cc +++ b/talk/app/webrtc/peerconnection_unittest.cc @@ -41,7 +41,7 @@ #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/app/webrtc/test/fakeaudiocapturemodule.h" #include "talk/app/webrtc/test/fakeconstraints.h" -#include "talk/app/webrtc/test/fakedtlsidentityservice.h" +#include "talk/app/webrtc/test/fakedtlsidentitystore.h" #include "talk/app/webrtc/test/fakeperiodicvideocapturer.h" #include "talk/app/webrtc/test/fakevideotrackrenderer.h" #include "talk/app/webrtc/test/mockpeerconnectionobservers.h" @@ -780,20 +780,21 @@ class JsepTestClient remove_sdes_(false) { } - virtual rtc::scoped_refptr - CreatePeerConnection(webrtc::PortAllocatorFactoryInterface* factory, - const MediaConstraintsInterface* constraints) { + rtc::scoped_refptr + CreatePeerConnection( + webrtc::PortAllocatorFactoryInterface* factory, + const MediaConstraintsInterface* constraints) override { // CreatePeerConnection with IceServers. webrtc::PeerConnectionInterface::IceServers ice_servers; webrtc::PeerConnectionInterface::IceServer ice_server; ice_server.uri = "stun:stun.l.google.com:19302"; ice_servers.push_back(ice_server); - FakeIdentityService* dtls_service = - rtc::SSLStreamAdapter::HaveDtlsSrtp() ? - new FakeIdentityService() : NULL; + rtc::scoped_ptr dtls_identity_store( + rtc::SSLStreamAdapter::HaveDtlsSrtp() ? new FakeDtlsIdentityStore() + : nullptr); return peer_connection_factory()->CreatePeerConnection( - ice_servers, constraints, factory, dtls_service, this); + ice_servers, constraints, factory, dtls_identity_store.Pass(), this); } void HandleIncomingOffer(const std::string& msg) { diff --git a/talk/app/webrtc/peerconnectionfactory.cc b/talk/app/webrtc/peerconnectionfactory.cc index 3524af7932..26765d2109 100644 --- a/talk/app/webrtc/peerconnectionfactory.cc +++ b/talk/app/webrtc/peerconnectionfactory.cc @@ -28,8 +28,6 @@ #include "talk/app/webrtc/peerconnectionfactory.h" #include "talk/app/webrtc/audiotrack.h" -#include "talk/app/webrtc/dtlsidentityservice.h" -#include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/localaudiosource.h" #include "talk/app/webrtc/mediastreamproxy.h" #include "talk/app/webrtc/mediastreamtrackproxy.h" @@ -49,6 +47,30 @@ namespace webrtc { +namespace { + +// Passes down the calls to |store_|. See usage in CreatePeerConnection. +class DtlsIdentityStoreWrapper : public DtlsIdentityStoreInterface { + public: + DtlsIdentityStoreWrapper( + const rtc::scoped_refptr& store) + : store_(store) { + DCHECK(store_); + } + + void RequestIdentity( + rtc::KeyType key_type, + const rtc::scoped_refptr& + observer) override { + store_->RequestIdentity(key_type, observer); + } + + private: + rtc::scoped_refptr store_; +}; + +} // anonymous namespace + rtc::scoped_refptr CreatePeerConnectionFactory() { rtc::scoped_refptr pc_factory( @@ -130,12 +152,12 @@ PeerConnectionFactory::PeerConnectionFactory( PeerConnectionFactory::~PeerConnectionFactory() { DCHECK(signaling_thread_->IsCurrent()); - channel_manager_.reset(NULL); - default_allocator_factory_ = NULL; + channel_manager_.reset(nullptr); + default_allocator_factory_ = nullptr; // Make sure |worker_thread_| and |signaling_thread_| outlive // |dtls_identity_store_|. - dtls_identity_store_.reset(NULL); + dtls_identity_store_ = nullptr; if (owns_ptrs_) { if (wraps_current_thread_) @@ -169,9 +191,8 @@ bool PeerConnectionFactory::Initialize() { return false; } - dtls_identity_store_.reset( - new DtlsIdentityStore(signaling_thread_, worker_thread_)); - dtls_identity_store_->Initialize(); + dtls_identity_store_ = new RefCountedDtlsIdentityStore( + signaling_thread_, worker_thread_); return true; } @@ -205,13 +226,17 @@ PeerConnectionFactory::CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, const MediaConstraintsInterface* constraints, PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, PeerConnectionObserver* observer) { DCHECK(signaling_thread_->IsCurrent()); DCHECK(allocator_factory || default_allocator_factory_); - if (!dtls_identity_service) { - dtls_identity_service = new DtlsIdentityService(dtls_identity_store_.get()); + if (!dtls_identity_store.get()) { + // Because |pc|->Initialize takes ownership of the store we need a new + // wrapper object that can be deleted without deleting the underlying + // |dtls_identity_store_|, protecting it from being deleted multiple times. + dtls_identity_store.reset( + new DtlsIdentityStoreWrapper(dtls_identity_store_)); } PortAllocatorFactoryInterface* chosen_allocator_factory = @@ -224,7 +249,7 @@ PeerConnectionFactory::CreatePeerConnection( configuration, constraints, chosen_allocator_factory, - dtls_identity_service, + dtls_identity_store.Pass(), observer)) { return NULL; } diff --git a/talk/app/webrtc/peerconnectionfactory.h b/talk/app/webrtc/peerconnectionfactory.h index d6bf03f3d1..c5855f452b 100644 --- a/talk/app/webrtc/peerconnectionfactory.h +++ b/talk/app/webrtc/peerconnectionfactory.h @@ -30,15 +30,18 @@ #include +#include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/mediastreaminterface.h" #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/session/media/channelmanager.h" #include "webrtc/base/scoped_ptr.h" +#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/thread.h" namespace webrtc { -class DtlsIdentityStore; +typedef rtc::RefCountedObject + RefCountedDtlsIdentityStore; class PeerConnectionFactory : public PeerConnectionFactoryInterface { public: @@ -46,13 +49,14 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { options_ = options; } - virtual rtc::scoped_refptr + // webrtc::PeerConnectionFactoryInterface override; + rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, const MediaConstraintsInterface* constraints, PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, - PeerConnectionObserver* observer); + rtc::scoped_ptr dtls_identity_store, + PeerConnectionObserver* observer) override; bool Initialize(); @@ -112,7 +116,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { rtc::scoped_ptr video_decoder_factory_; - rtc::scoped_ptr dtls_identity_store_; + rtc::scoped_refptr dtls_identity_store_; }; } // namespace webrtc diff --git a/talk/app/webrtc/peerconnectionfactory_unittest.cc b/talk/app/webrtc/peerconnectionfactory_unittest.cc index 8088588852..8cf08f549b 100644 --- a/talk/app/webrtc/peerconnectionfactory_unittest.cc +++ b/talk/app/webrtc/peerconnectionfactory_unittest.cc @@ -30,7 +30,7 @@ #include "talk/app/webrtc/fakeportallocatorfactory.h" #include "talk/app/webrtc/mediastreaminterface.h" #include "talk/app/webrtc/peerconnectionfactory.h" -#include "talk/app/webrtc/test/fakedtlsidentityservice.h" +#include "talk/app/webrtc/test/fakedtlsidentitystore.h" #include "talk/app/webrtc/test/fakevideotrackrenderer.h" #include "talk/app/webrtc/videosourceinterface.h" #include "talk/media/base/fakevideocapturer.h" @@ -40,8 +40,9 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread.h" -using webrtc::FakeVideoTrackRenderer; using webrtc::DataChannelInterface; +using webrtc::DtlsIdentityStoreInterface; +using webrtc::FakeVideoTrackRenderer; using webrtc::MediaStreamInterface; using webrtc::PeerConnectionFactoryInterface; using webrtc::PeerConnectionInterface; @@ -157,11 +158,13 @@ TEST(PeerConnectionFactoryTestInternal, CreatePCUsingInternalModules) { NullPeerConnectionObserver observer; webrtc::PeerConnectionInterface::IceServers servers; + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( factory->CreatePeerConnection( - servers, NULL, NULL, new FakeIdentityService(), &observer)); + servers, nullptr, nullptr, dtls_identity_store.Pass(), &observer)); - EXPECT_TRUE(pc.get() != NULL); + EXPECT_TRUE(pc.get() != nullptr); } // This test verifies creation of PeerConnection with valid STUN and TURN @@ -177,10 +180,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServers) { ice_server.uri = kTurnIceServerWithTransport; ice_server.password = kTurnPassword; config.servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(config, NULL, + factory_->CreatePeerConnection(config, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); StunConfigurations stun_configs; @@ -209,10 +214,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServersUrls) { ice_server.urls.push_back(kTurnIceServerWithTransport); ice_server.password = kTurnPassword; config.servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(config, NULL, + factory_->CreatePeerConnection(config, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); StunConfigurations stun_configs; @@ -245,10 +252,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIceServersOldSignature) { ice_server.uri = kTurnIceServerWithTransport; ice_server.password = kTurnPassword; ice_servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(ice_servers, NULL, + factory_->CreatePeerConnection(ice_servers, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); StunConfigurations stun_configs; @@ -275,10 +284,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingNoUsernameInUri) { ice_server.username = kTurnUsername; ice_server.password = kTurnPassword; config.servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(config, NULL, + factory_->CreatePeerConnection(config, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); TurnConfigurations turn_configs; @@ -296,10 +307,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingTurnUrlWithTransportParam) { ice_server.uri = kTurnIceServerWithTransport; ice_server.password = kTurnPassword; config.servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(config, NULL, + factory_->CreatePeerConnection(config, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); TurnConfigurations turn_configs; @@ -321,10 +334,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingSecureTurnUrl) { ice_server.uri = kSecureTurnIceServerWithoutTransportAndPortParam; ice_server.password = kTurnPassword; config.servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(config, NULL, + factory_->CreatePeerConnection(config, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); TurnConfigurations turn_configs; @@ -358,10 +373,12 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingIPLiteralAddress) { ice_server.uri = kTurnIceServerWithIPv6Address; ice_server.password = kTurnPassword; config.servers.push_back(ice_server); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); rtc::scoped_refptr pc( - factory_->CreatePeerConnection(config, NULL, + factory_->CreatePeerConnection(config, nullptr, allocator_factory_.get(), - new FakeIdentityService(), + dtls_identity_store.Pass(), &observer_)); EXPECT_TRUE(pc.get() != NULL); StunConfigurations stun_configs; diff --git a/talk/app/webrtc/peerconnectionfactoryproxy.h b/talk/app/webrtc/peerconnectionfactoryproxy.h index 2f5ddd6892..4a8cd8758c 100644 --- a/talk/app/webrtc/peerconnectionfactoryproxy.h +++ b/talk/app/webrtc/peerconnectionfactoryproxy.h @@ -32,18 +32,24 @@ #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/app/webrtc/proxy.h" +#include "webrtc/base/bind.h" namespace webrtc { BEGIN_PROXY_MAP(PeerConnectionFactory) PROXY_METHOD1(void, SetOptions, const Options&) - PROXY_METHOD5(rtc::scoped_refptr, - CreatePeerConnection, - const PeerConnectionInterface::RTCConfiguration&, - const MediaConstraintsInterface*, - PortAllocatorFactoryInterface*, - DTLSIdentityServiceInterface*, - PeerConnectionObserver*) + // Can't use PROXY_METHOD5 because scoped_ptr must be Pass()ed. + // TODO(tommi,hbos): Use of templates to support scoped_ptr? + rtc::scoped_refptr CreatePeerConnection( + const PeerConnectionInterface::RTCConfiguration& a1, + const MediaConstraintsInterface* a2, + PortAllocatorFactoryInterface* a3, + rtc::scoped_ptr a4, + PeerConnectionObserver* a5) override { + return owner_thread_->Invoke>( + rtc::Bind(&PeerConnectionFactoryProxy::CreatePeerConnection_ot, this, + a1, a2, a3, a4.release(), a5)); + } PROXY_METHOD1(rtc::scoped_refptr, CreateLocalMediaStream, const std::string&) PROXY_METHOD1(rtc::scoped_refptr, @@ -56,6 +62,17 @@ BEGIN_PROXY_MAP(PeerConnectionFactory) PROXY_METHOD2(rtc::scoped_refptr, CreateAudioTrack, const std::string&, AudioSourceInterface*) PROXY_METHOD1(bool, StartAecDump, rtc::PlatformFile) + + private: + rtc::scoped_refptr CreatePeerConnection_ot( + const PeerConnectionInterface::RTCConfiguration& a1, + const MediaConstraintsInterface* a2, + PortAllocatorFactoryInterface* a3, + DtlsIdentityStoreInterface* a4, + PeerConnectionObserver* a5) { + rtc::scoped_ptr ptr_a4(a4); + return c_->CreatePeerConnection(a1, a2, a3, ptr_a4.Pass(), a5); + } END_PROXY() } // namespace webrtc diff --git a/talk/app/webrtc/peerconnectioninterface.h b/talk/app/webrtc/peerconnectioninterface.h index 946b1253c9..5268187e8f 100644 --- a/talk/app/webrtc/peerconnectioninterface.h +++ b/talk/app/webrtc/peerconnectioninterface.h @@ -74,6 +74,7 @@ #include "talk/app/webrtc/datachannelinterface.h" #include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/dtmfsenderinterface.h" +#include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/jsep.h" #include "talk/app/webrtc/mediastreaminterface.h" #include "talk/app/webrtc/statstypes.h" @@ -467,6 +468,7 @@ class PortAllocatorFactoryInterface : public rtc::RefCountInterface { ~PortAllocatorFactoryInterface() {} }; +// TODO(hbos): Remove once cr/1176383004 lands. class DTLSIdentityServiceInterface { public: // Asynchronously request a DTLS identity, including a self-signed certificate @@ -535,6 +537,7 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { // TODO(hbos): Temporary CreatePeerConnection function while we transition // from DTLSIdentityServiceInterface to DtlsIdentityStoreInterface. + // This method takes the ownership of |dtls_identity_service|. rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, @@ -543,21 +546,23 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { DTLSIdentityServiceInterface* dtls_identity_service, rtc::scoped_ptr dtls_identity_store, PeerConnectionObserver* observer) { + if (dtls_identity_service) { + // Store used instead of service, our ownership responsibility to delete. + delete dtls_identity_service; + } return CreatePeerConnection(configuration, constraints, allocator_factory, - dtls_identity_service, observer); + dtls_identity_store.Pass(), observer); } - // This method takes the ownership of |dtls_identity_service|. virtual rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, const MediaConstraintsInterface* constraints, PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, PeerConnectionObserver* observer) = 0; - // TODO(mallinath) : Remove below versions after clients are updated - // to above method. + // TODO(hbos): Remove below version after clients are updated to above method. // In latest W3C WebRTC draft, PC constructor will take RTCConfiguration, // and not IceServers. RTCConfiguration is made up of ice servers and // ice transport type. @@ -567,12 +572,12 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { const PeerConnectionInterface::IceServers& servers, const MediaConstraintsInterface* constraints, PortAllocatorFactoryInterface* allocator_factory, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, PeerConnectionObserver* observer) { PeerConnectionInterface::RTCConfiguration rtc_config; rtc_config.servers = servers; return CreatePeerConnection(rtc_config, constraints, allocator_factory, - dtls_identity_service, observer); + dtls_identity_store.Pass(), observer); } virtual rtc::scoped_refptr diff --git a/talk/app/webrtc/peerconnectioninterface_unittest.cc b/talk/app/webrtc/peerconnectioninterface_unittest.cc index 9e68f5a5b1..03ceaf2e10 100644 --- a/talk/app/webrtc/peerconnectioninterface_unittest.cc +++ b/talk/app/webrtc/peerconnectioninterface_unittest.cc @@ -32,7 +32,7 @@ #include "talk/app/webrtc/mediastreaminterface.h" #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/app/webrtc/test/fakeconstraints.h" -#include "talk/app/webrtc/test/fakedtlsidentityservice.h" +#include "talk/app/webrtc/test/fakedtlsidentitystore.h" #include "talk/app/webrtc/test/mockpeerconnectionobservers.h" #include "talk/app/webrtc/test/testsdpstrings.h" #include "talk/app/webrtc/videosource.h" @@ -264,17 +264,17 @@ class PeerConnectionInterfaceTest : public testing::Test { webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false); } - FakeIdentityService* dtls_service = NULL; + scoped_ptr dtls_identity_store; bool dtls; if (FindConstraint(constraints, webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, &dtls, - NULL) && dtls) { - dtls_service = new FakeIdentityService(); + nullptr) && dtls) { + dtls_identity_store.reset(new FakeDtlsIdentityStore()); } pc_ = pc_factory_->CreatePeerConnection(servers, constraints, port_allocator_factory_.get(), - dtls_service, + dtls_identity_store.Pass(), &observer_); ASSERT_TRUE(pc_.get() != NULL); observer_.SetPeerConnectionInterface(pc_.get()); diff --git a/talk/app/webrtc/test/fakedtlsidentityservice.h b/talk/app/webrtc/test/fakedtlsidentitystore.h similarity index 70% rename from talk/app/webrtc/test/fakedtlsidentityservice.h rename to talk/app/webrtc/test/fakedtlsidentitystore.h index 6c59d4115a..5ef19004a0 100644 --- a/talk/app/webrtc/test/fakedtlsidentityservice.h +++ b/talk/app/webrtc/test/fakedtlsidentitystore.h @@ -28,6 +28,9 @@ #ifndef TALK_APP_WEBRTC_TEST_FAKEDTLSIDENTITYSERVICE_H_ #define TALK_APP_WEBRTC_TEST_FAKEDTLSIDENTITYSERVICE_H_ +#include + +#include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/peerconnectioninterface.h" static const char kRSA_PRIVATE_KEY_PEM[] = @@ -61,38 +64,28 @@ static const char kCERT_PEM[] = "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" "-----END CERTIFICATE-----\n"; -using webrtc::DTLSIdentityRequestObserver; - -class FakeIdentityService : public webrtc::DTLSIdentityServiceInterface, - public rtc::MessageHandler { +class FakeDtlsIdentityStore : public webrtc::DtlsIdentityStoreInterface, + public rtc::MessageHandler { public: - struct Request { - Request(const std::string& common_name, - DTLSIdentityRequestObserver* observer) - : common_name(common_name), observer(observer) {} + typedef rtc::TypedMessageData > MessageData; - std::string common_name; - rtc::scoped_refptr observer; - }; - typedef rtc::TypedMessageData MessageData; - - FakeIdentityService() : should_fail_(false) {} + FakeDtlsIdentityStore() : should_fail_(false) {} void set_should_fail(bool should_fail) { should_fail_ = should_fail; } - // DTLSIdentityServiceInterface implemenation. - virtual bool RequestIdentity(const std::string& identity_name, - const std::string& common_name, - DTLSIdentityRequestObserver* observer) { - MessageData* msg = new MessageData(Request(common_name, observer)); - if (should_fail_) { - rtc::Thread::Current()->Post(this, MSG_FAILURE, msg); - } else { - rtc::Thread::Current()->Post(this, MSG_SUCCESS, msg); - } - return true; + void RequestIdentity( + rtc::KeyType key_type, + const rtc::scoped_refptr& + observer) override { + // TODO(hbos): Should be able to generate KT_ECDSA too. + DCHECK(key_type == rtc::KT_RSA || should_fail_); + MessageData* msg = new MessageData( + rtc::scoped_refptr(observer)); + rtc::Thread::Current()->Post( + this, should_fail_ ? MSG_FAILURE : MSG_SUCCESS, msg); } private: @@ -103,13 +96,16 @@ class FakeIdentityService : public webrtc::DTLSIdentityServiceInterface, // rtc::MessageHandler implementation. void OnMessage(rtc::Message* msg) { - FakeIdentityService::MessageData* message_data = - static_cast(msg->pdata); - DTLSIdentityRequestObserver* observer = message_data->data().observer.get(); + MessageData* message_data = static_cast(msg->pdata); + rtc::scoped_refptr observer = + message_data->data(); switch (msg->message_id) { case MSG_SUCCESS: { - std::string cert, key; - GenerateIdentity(message_data->data().common_name, &cert, &key); + std::string cert; + std::string key; + rtc::SSLIdentity::PemToDer("CERTIFICATE", kCERT_PEM, &cert); + rtc::SSLIdentity::PemToDer("RSA PRIVATE KEY", kRSA_PRIVATE_KEY_PEM, + &key); observer->OnSuccess(cert, key); break; } @@ -120,16 +116,6 @@ class FakeIdentityService : public webrtc::DTLSIdentityServiceInterface, delete message_data; } - void GenerateIdentity( - const std::string& common_name, - std::string* der_cert, - std::string* der_key) { - rtc::SSLIdentity::PemToDer("CERTIFICATE", kCERT_PEM, der_cert); - rtc::SSLIdentity::PemToDer("RSA PRIVATE KEY", - kRSA_PRIVATE_KEY_PEM, - der_key); - } - bool should_fail_; }; diff --git a/talk/app/webrtc/test/peerconnectiontestwrapper.cc b/talk/app/webrtc/test/peerconnectiontestwrapper.cc index 91d4f508f7..aecdcbb52f 100644 --- a/talk/app/webrtc/test/peerconnectiontestwrapper.cc +++ b/talk/app/webrtc/test/peerconnectiontestwrapper.cc @@ -26,7 +26,7 @@ */ #include "talk/app/webrtc/fakeportallocatorfactory.h" -#include "talk/app/webrtc/test/fakedtlsidentityservice.h" +#include "talk/app/webrtc/test/fakedtlsidentitystore.h" #include "talk/app/webrtc/test/fakeperiodicvideocapturer.h" #include "talk/app/webrtc/test/mockpeerconnectionobservers.h" #include "talk/app/webrtc/test/peerconnectiontestwrapper.h" @@ -93,11 +93,12 @@ bool PeerConnectionTestWrapper::CreatePc( webrtc::PeerConnectionInterface::IceServer ice_server; ice_server.uri = "stun:stun.l.google.com:19302"; ice_servers.push_back(ice_server); - FakeIdentityService* dtls_service = + rtc::scoped_ptr dtls_identity_store( rtc::SSLStreamAdapter::HaveDtlsSrtp() ? - new FakeIdentityService() : NULL; + new FakeDtlsIdentityStore() : nullptr); peer_connection_ = peer_connection_factory_->CreatePeerConnection( - ice_servers, constraints, allocator_factory_.get(), dtls_service, this); + ice_servers, constraints, allocator_factory_.get(), + dtls_identity_store.Pass(), this); return peer_connection_.get() != NULL; } diff --git a/talk/app/webrtc/test/peerconnectiontestwrapper.h b/talk/app/webrtc/test/peerconnectiontestwrapper.h index 136f6660e6..21ee7dc16f 100644 --- a/talk/app/webrtc/test/peerconnectiontestwrapper.h +++ b/talk/app/webrtc/test/peerconnectiontestwrapper.h @@ -36,6 +36,7 @@ #include "webrtc/base/thread.h" namespace webrtc { +class DtlsIdentityStoreInterface; class PortAllocatorFactoryInterface; } diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc index b6a178cf39..c37eadb8a8 100644 --- a/talk/app/webrtc/webrtcsession.cc +++ b/talk/app/webrtc/webrtcsession.cc @@ -523,7 +523,7 @@ WebRtcSession::~WebRtcSession() { bool WebRtcSession::Initialize( const PeerConnectionFactoryInterface::Options& options, const MediaConstraintsInterface* constraints, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { bundle_policy_ = rtc_configuration.bundle_policy; rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy; @@ -537,8 +537,8 @@ bool WebRtcSession::Initialize( if (options.disable_encryption) { dtls_enabled_ = false; } else { - // Enable DTLS by default if |dtls_identity_service| is valid. - dtls_enabled_ = (dtls_identity_service != NULL); + // Enable DTLS by default if we have a |dtls_identity_store|. + dtls_enabled_ = (dtls_identity_store != nullptr); // |constraints| can override the default |dtls_enabled_| value. if (FindConstraint( constraints, @@ -664,7 +664,7 @@ bool WebRtcSession::Initialize( signaling_thread(), channel_manager_, mediastream_signaling_, - dtls_identity_service, + dtls_identity_store.Pass(), this, id(), data_channel_type_, diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h index 30ebc1e49e..47b49b661a 100644 --- a/talk/app/webrtc/webrtcsession.h +++ b/talk/app/webrtc/webrtcsession.h @@ -39,6 +39,7 @@ #include "webrtc/p2p/base/session.h" #include "talk/session/media/mediasession.h" #include "webrtc/base/sigslot.h" +#include "webrtc/base/sslidentity.h" #include "webrtc/base/thread.h" namespace cricket { @@ -125,7 +126,7 @@ class WebRtcSession : public cricket::BaseSession, bool Initialize( const PeerConnectionFactoryInterface::Options& options, const MediaConstraintsInterface* constraints, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, const PeerConnectionInterface::RTCConfiguration& rtc_configuration); // Deletes the voice, video and data channel and changes the session state // to STATE_RECEIVEDTERMINATE. diff --git a/talk/app/webrtc/webrtcsession_unittest.cc b/talk/app/webrtc/webrtcsession_unittest.cc index 9bdd8203f6..a96f62435d 100644 --- a/talk/app/webrtc/webrtcsession_unittest.cc +++ b/talk/app/webrtc/webrtcsession_unittest.cc @@ -32,7 +32,7 @@ #include "talk/app/webrtc/mediastreamsignaling.h" #include "talk/app/webrtc/streamcollection.h" #include "talk/app/webrtc/test/fakeconstraints.h" -#include "talk/app/webrtc/test/fakedtlsidentityservice.h" +#include "talk/app/webrtc/test/fakedtlsidentitystore.h" #include "talk/app/webrtc/test/fakemediastreamsignaling.h" #include "talk/app/webrtc/videotrack.h" #include "talk/app/webrtc/webrtcsession.h" @@ -55,6 +55,7 @@ #include "webrtc/base/network.h" #include "webrtc/base/physicalsocketserver.h" #include "webrtc/base/ssladapter.h" +#include "webrtc/base/sslidentity.h" #include "webrtc/base/sslstreamadapter.h" #include "webrtc/base/stringutils.h" #include "webrtc/base/thread.h" @@ -77,8 +78,7 @@ using rtc::Thread; using webrtc::CreateSessionDescription; using webrtc::CreateSessionDescriptionObserver; using webrtc::CreateSessionDescriptionRequest; -using webrtc::DTLSIdentityRequestObserver; -using webrtc::DTLSIdentityServiceInterface; +using webrtc::DtlsIdentityStoreInterface; using webrtc::FakeConstraints; using webrtc::FakeMetricsObserver; using webrtc::IceCandidateCollection; @@ -353,7 +353,7 @@ class WebRtcSessionTest : public testing::Test { } void Init( - DTLSIdentityServiceInterface* identity_service, + rtc::scoped_ptr dtls_identity_store, const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { ASSERT_TRUE(session_.get() == NULL); session_.reset(new WebRtcSessionForTest( @@ -367,42 +367,44 @@ class WebRtcSessionTest : public testing::Test { EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, observer_.ice_gathering_state_); - EXPECT_TRUE(session_->Initialize(options_, constraints_.get(), - identity_service, rtc_configuration)); + EXPECT_TRUE(session_->Initialize( + options_, constraints_.get(), dtls_identity_store.Pass(), + rtc_configuration)); session_->set_metrics_observer(metrics_observer_); } void Init() { PeerConnectionInterface::RTCConfiguration configuration; - Init(NULL, configuration); + Init(nullptr, configuration); } void InitWithIceTransport( PeerConnectionInterface::IceTransportsType ice_transport_type) { PeerConnectionInterface::RTCConfiguration configuration; configuration.type = ice_transport_type; - Init(NULL, configuration); + Init(nullptr, configuration); } void InitWithBundlePolicy( PeerConnectionInterface::BundlePolicy bundle_policy) { PeerConnectionInterface::RTCConfiguration configuration; configuration.bundle_policy = bundle_policy; - Init(NULL, configuration); + Init(nullptr, configuration); } void InitWithRtcpMuxPolicy( PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy) { PeerConnectionInterface::RTCConfiguration configuration; configuration.rtcp_mux_policy = rtcp_mux_policy; - Init(NULL, configuration); + Init(nullptr, configuration); } void InitWithDtls(bool identity_request_should_fail = false) { - FakeIdentityService* identity_service = new FakeIdentityService(); - identity_service->set_should_fail(identity_request_should_fail); + rtc::scoped_ptr dtls_identity_store( + new FakeDtlsIdentityStore()); + dtls_identity_store->set_should_fail(identity_request_should_fail); PeerConnectionInterface::RTCConfiguration configuration; - Init(identity_service, configuration); + Init(dtls_identity_store.Pass(), configuration); } void InitWithDtmfCodec() { diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc index 739730ad00..6c6981ce5a 100644 --- a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc +++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc @@ -33,6 +33,7 @@ #include "talk/app/webrtc/mediaconstraintsinterface.h" #include "talk/app/webrtc/mediastreamsignaling.h" #include "talk/app/webrtc/webrtcsession.h" +#include "webrtc/base/sslidentity.h" using cricket::MediaSessionOptions; @@ -67,8 +68,7 @@ static bool ValidStreams(const MediaSessionOptions::Streams& streams) { enum { MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, - MSG_CREATE_SESSIONDESCRIPTION_FAILED, - MSG_GENERATE_IDENTITY, + MSG_CREATE_SESSIONDESCRIPTION_FAILED }; struct CreateSessionDescriptionMsg : public rtc::MessageData { @@ -102,7 +102,7 @@ void WebRtcIdentityRequestObserver::OnSuccess( SignalIdentityReady(identity); } -void WebRtcIdentityRequestObserver::OnSuccessWithIdentityObj( +void WebRtcIdentityRequestObserver::OnSuccess( rtc::scoped_ptr identity) { SignalIdentityReady(identity.release()); } @@ -130,7 +130,7 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( rtc::Thread* signaling_thread, cricket::ChannelManager* channel_manager, MediaStreamSignaling* mediastream_signaling, - DTLSIdentityServiceInterface* dtls_identity_service, + rtc::scoped_ptr dtls_identity_store, WebRtcSession* session, const std::string& session_id, cricket::DataChannelType dct, @@ -143,7 +143,7 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( // to just use a random number as session id and start version from // |kInitSessionVersion|. session_version_(kInitSessionVersion), - identity_service_(dtls_identity_service), + dtls_identity_store_(dtls_identity_store.Pass()), session_(session), session_id_(session_id), data_channel_type_(dct), @@ -152,11 +152,10 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( // SRTP-SDES is disabled if DTLS is on. SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); - if (!dtls_enabled) { - return; - } + // If |dtls_enabled| we must have a |dtls_identity_store_|. + DCHECK(!dtls_enabled || dtls_identity_store_); - if (identity_service_.get()) { + if (dtls_enabled && dtls_identity_store_) { identity_request_observer_ = new rtc::RefCountedObject(); @@ -165,21 +164,10 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( identity_request_observer_->SignalIdentityReady.connect( this, &WebRtcSessionDescriptionFactory::SetIdentity); - if (identity_service_->RequestIdentity( - DtlsIdentityStore::kIdentityName, - DtlsIdentityStore::kIdentityName, - identity_request_observer_)) { - LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sent DTLS identity request."; - identity_request_state_ = IDENTITY_WAITING; - } else { - LOG(LS_ERROR) << "Failed to send DTLS identity request."; - identity_request_state_ = IDENTITY_FAILED; - } - } else { + LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request."; identity_request_state_ = IDENTITY_WAITING; - // Do not generate the identity in the constructor since the caller has - // not got a chance to connect to SignalIdentityReady. - signaling_thread_->Post(this, MSG_GENERATE_IDENTITY, NULL); + dtls_identity_store_->RequestIdentity(rtc::KT_DEFAULT, + identity_request_observer_); } } @@ -323,11 +311,6 @@ void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) { delete param; break; } - case MSG_GENERATE_IDENTITY: { - LOG(LS_INFO) << "Generating identity."; - SetIdentity(rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName)); - break; - } default: ASSERT(false); break; diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.h b/talk/app/webrtc/webrtcsessiondescriptionfactory.h index 860532dec9..5d91a61dbb 100644 --- a/talk/app/webrtc/webrtcsessiondescriptionfactory.h +++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.h @@ -28,9 +28,10 @@ #ifndef TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ #define TALK_APP_WEBRTC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ +#include "talk/app/webrtc/dtlsidentitystore.h" #include "talk/app/webrtc/peerconnectioninterface.h" -#include "webrtc/p2p/base/transportdescriptionfactory.h" #include "talk/session/media/mediasession.h" +#include "webrtc/p2p/base/transportdescriptionfactory.h" #include "webrtc/base/messagehandler.h" namespace cricket { @@ -46,15 +47,14 @@ class SessionDescriptionInterface; class WebRtcSession; // DTLS identity request callback class. -class WebRtcIdentityRequestObserver : public DTLSIdentityRequestObserver, +class WebRtcIdentityRequestObserver : public DtlsIdentityRequestObserver, public sigslot::has_slots<> { public: - // DTLSIdentityRequestObserver overrides. + // DtlsIdentityRequestObserver overrides. void OnFailure(int error) override; void OnSuccess(const std::string& der_cert, const std::string& der_private_key) override; - void OnSuccessWithIdentityObj( - rtc::scoped_ptr identity) override; + void OnSuccess(rtc::scoped_ptr identity) override; sigslot::signal1 SignalRequestFailed; sigslot::signal1 SignalIdentityReady; @@ -85,14 +85,14 @@ struct CreateSessionDescriptionRequest { // request has completed, i.e. when OnIdentityRequestFailed or OnIdentityReady // is called. class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, - public sigslot::has_slots<> { + public sigslot::has_slots<> { public: WebRtcSessionDescriptionFactory( rtc::Thread* signaling_thread, cricket::ChannelManager* channel_manager, MediaStreamSignaling* mediastream_signaling, - DTLSIdentityServiceInterface* dtls_identity_service, - // TODO(jiayl): remove the dependency on session once b/10226852 is fixed. + rtc::scoped_ptr dtls_identity_store, + // TODO(jiayl): remove the dependency on session once bug 2264 is fixed. WebRtcSession* session, const std::string& session_id, cricket::DataChannelType dct, @@ -152,7 +152,7 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, cricket::TransportDescriptionFactory transport_desc_factory_; cricket::MediaSessionDescriptionFactory session_desc_factory_; uint64 session_version_; - rtc::scoped_ptr identity_service_; + rtc::scoped_ptr dtls_identity_store_; rtc::scoped_refptr identity_request_observer_; WebRtcSession* const session_; const std::string session_id_; diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index cf7af99e8f..15272519a2 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -708,8 +708,6 @@ 'app/webrtc/datachannel.cc', 'app/webrtc/datachannel.h', 'app/webrtc/datachannelinterface.h', - 'app/webrtc/dtlsidentityservice.cc', - 'app/webrtc/dtlsidentityservice.h', 'app/webrtc/dtlsidentitystore.cc', 'app/webrtc/dtlsidentitystore.h', 'app/webrtc/dtmfsender.cc', diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp index 159eefcbd5..e3d514e3e8 100755 --- a/talk/libjingle_tests.gyp +++ b/talk/libjingle_tests.gyp @@ -218,7 +218,7 @@ 'app/webrtc/test/fakeaudiocapturemodule_unittest.cc', 'app/webrtc/test/fakeconstraints.h', 'app/webrtc/test/fakedatachannelprovider.h', - 'app/webrtc/test/fakedtlsidentityservice.h', + 'app/webrtc/test/fakedtlsidentitystore.h', 'app/webrtc/test/fakemediastreamsignaling.h', 'app/webrtc/test/fakeperiodicvideocapturer.h', 'app/webrtc/test/fakevideotrackrenderer.h', diff --git a/webrtc/base/sslidentity.h b/webrtc/base/sslidentity.h index ca1aa11f83..59f87d07d2 100644 --- a/webrtc/base/sslidentity.h +++ b/webrtc/base/sslidentity.h @@ -22,8 +22,6 @@ namespace rtc { -enum KeyType { KT_RSA, KT_ECDSA, KT_LAST, KT_DEFAULT = KT_RSA }; - // Forward declaration due to circular dependency with SSLCertificate. class SSLCertChain; @@ -109,6 +107,8 @@ class SSLCertChain { DISALLOW_COPY_AND_ASSIGN(SSLCertChain); }; +enum KeyType { KT_RSA, KT_ECDSA, KT_LAST, KT_DEFAULT = KT_RSA }; + // Parameters for generating an identity for testing. If common_name is // non-empty, it will be used for the certificate's subject and issuer name, // otherwise a random string will be used. |not_before| and |not_after| are