DtlsIdentityStoreInterface added and the implementation is called DtlsIdentityStoreImpl (previously named without the -Impl bit and without an interface).

DtlsIdentityStoreImpl is updated to take KeyType into account, something which will be relevant after this CL lands:
https://codereview.webrtc.org/1189583002

The DtlsIdentityService[Interface] classes are about to be removed (to be removed when Chromium no longer implements and uses the interface). This was an unnecessary layer of complexity. The FakeIdentityService is now instead a FakeDtlsIdentityStore.
Where a service was previously passed around, a store is now passed around.

Identity generation is now commonly performed using DtlsIdentityStoreInterface. Previously, if a service was not specified, WebRtcSessionDescriptionFactory could fall back on its own generation code. Now, a store has to be provided for generation to occur.

For more information about the steps being taken to land this without breaking Chromium, see referenced bug.

BUG=webrtc:4899
R=magjed@webrtc.org, tommi@webrtc.org

Review URL: https://codereview.webrtc.org/1176383004 .

Cr-Commit-Position: refs/heads/master@{#9696}
This commit is contained in:
Henrik Boström
2015-08-11 10:33:13 +02:00
parent 0365a27f56
commit 5e56c5927e
25 changed files with 433 additions and 448 deletions

View File

@ -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

View File

@ -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 <string>
#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_

View File

@ -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<rtc::SSLIdentity> 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<rtc::SSLIdentity> 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<IdentityResultMessageData> pdata(
static_cast<IdentityResultMessageData*>(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<webrtc::DtlsIdentityRequestObserver>& 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<IdentityResultMessageData> pdata(
static_cast<IdentityResultMessageData*>(msg->pdata));
OnIdentityGenerated(pdata->data().Pass());
break;
}
case MSG_RETURN_FREE_IDENTITY: {
rtc::scoped_ptr<IdentityResultMessageData> pdata(
static_cast<IdentityResultMessageData*>(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<webrtc::DtlsIdentityRequestObserver>& 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<rtc::SSLIdentity> identity) {
DCHECK(rtc::Thread::Current() == signaling_thread_);
void DtlsIdentityStoreImpl::OnIdentityGenerated(
rtc::KeyType key_type, rtc::scoped_ptr<rtc::SSLIdentity> 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<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();
}
ReturnIdentity(identity.Pass());
}
void DtlsIdentityStore::ReturnIdentity(
rtc::scoped_ptr<rtc::SSLIdentity> identity) {
DCHECK(rtc::Thread::Current() == signaling_thread_);
DCHECK(!free_identity_.get());
DCHECK(!pending_observers_.empty());
rtc::scoped_refptr<DTLSIdentityRequestObserver> 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<rtc::SSLIdentity> identity) {
DCHECK(rtc::Thread::Current() == worker_thread_);
IdentityResultMessageData* msg =
new IdentityResultMessageData(identity.release());
signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
}
} // namespace webrtc

View File

@ -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<DtlsIdentityRequestObserver>& 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<DtlsIdentityRequestObserver>& 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<DtlsIdentityRequestObserver>& observer);
void OnIdentityGenerated(rtc::KeyType key_type,
rtc::scoped_ptr<rtc::SSLIdentity> identity);
class WorkerTask;
typedef rtc::ScopedMessageData<DtlsIdentityStore::WorkerTask>
IdentityTaskMessageData;
typedef rtc::ScopedMessageData<DtlsIdentityStoreImpl::WorkerTask>
WorkerTaskMessageData;
void GenerateIdentity();
void OnIdentityGenerated(rtc::scoped_ptr<rtc::SSLIdentity> identity);
void ReturnIdentity(rtc::scoped_ptr<rtc::SSLIdentity> identity);
// A key type-identity pair.
struct IdentityResult {
IdentityResult(rtc::KeyType key_type,
rtc::scoped_ptr<rtc::SSLIdentity> identity)
: key_type_(key_type), identity_(identity.Pass()) {}
void PostGenerateIdentityResult_w(rtc::scoped_ptr<rtc::SSLIdentity> identity);
rtc::KeyType key_type_;
rtc::scoped_ptr<rtc::SSLIdentity> identity_;
};
typedef rtc::ScopedMessageData<IdentityResult> 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<rtc::SSLIdentity> free_identity_;
typedef std::queue<rtc::scoped_refptr<webrtc::DTLSIdentityRequestObserver>>
ObserverList;
ObserverList pending_observers_;
struct RequestInfo {
RequestInfo()
: request_observers_(), gen_in_progress_counts_(0), free_identity_() {}
std::queue<rtc::scoped_refptr<DtlsIdentityRequestObserver>>
request_observers_;
size_t gen_in_progress_counts_;
rtc::scoped_ptr<rtc::SSLIdentity> free_identity_;
};
// One RequestInfo per KeyType. Only touch on the |signaling_thread_|.
RequestInfo request_info_[rtc::KT_LAST];
};
} // namespace webrtc

View File

@ -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<rtc::SSLIdentity> identity) override {
void OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity> 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<MockDtlsIdentityRequestObserver>()) {
CHECK(worker_thread_->Start());
store_->Initialize();
}
~DtlsIdentityStoreTest() {}
@ -97,30 +95,55 @@ class DtlsIdentityStoreTest : public testing::Test {
}
rtc::scoped_ptr<rtc::Thread> worker_thread_;
rtc::scoped_ptr<DtlsIdentityStore> store_;
rtc::scoped_ptr<DtlsIdentityStoreImpl> store_;
rtc::scoped_refptr<MockDtlsIdentityRequestObserver> 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();

View File

@ -349,7 +349,7 @@ bool PeerConnection::Initialize(
const PeerConnectionInterface::RTCConfiguration& configuration,
const MediaConstraintsInterface* constraints,
PortAllocatorFactoryInterface* allocator_factory,
DTLSIdentityServiceInterface* dtls_identity_service,
rtc::scoped_ptr<DtlsIdentityStoreInterface> 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.

View File

@ -30,6 +30,7 @@
#include <string>
#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<DtlsIdentityStoreInterface> dtls_identity_store,
PeerConnectionObserver* observer);
virtual rtc::scoped_refptr<StreamCollectionInterface> local_streams();
virtual rtc::scoped_refptr<StreamCollectionInterface> 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();
}

View File

@ -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<webrtc::PeerConnectionInterface>
CreatePeerConnection(webrtc::PortAllocatorFactoryInterface* factory,
const MediaConstraintsInterface* constraints) {
rtc::scoped_refptr<webrtc::PeerConnectionInterface>
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<webrtc::DtlsIdentityStoreInterface> 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) {

View File

@ -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<RefCountedDtlsIdentityStore>& store)
: store_(store) {
DCHECK(store_);
}
void RequestIdentity(
rtc::KeyType key_type,
const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>&
observer) override {
store_->RequestIdentity(key_type, observer);
}
private:
rtc::scoped_refptr<RefCountedDtlsIdentityStore> store_;
};
} // anonymous namespace
rtc::scoped_refptr<PeerConnectionFactoryInterface>
CreatePeerConnectionFactory() {
rtc::scoped_refptr<PeerConnectionFactory> 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<DtlsIdentityStoreInterface> 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;
}

View File

@ -30,15 +30,18 @@
#include <string>
#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<DtlsIdentityStoreImpl>
RefCountedDtlsIdentityStore;
class PeerConnectionFactory : public PeerConnectionFactoryInterface {
public:
@ -46,13 +49,14 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface {
options_ = options;
}
virtual rtc::scoped_refptr<PeerConnectionInterface>
// webrtc::PeerConnectionFactoryInterface override;
rtc::scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& configuration,
const MediaConstraintsInterface* constraints,
PortAllocatorFactoryInterface* allocator_factory,
DTLSIdentityServiceInterface* dtls_identity_service,
PeerConnectionObserver* observer);
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
PeerConnectionObserver* observer) override;
bool Initialize();
@ -112,7 +116,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface {
rtc::scoped_ptr<cricket::WebRtcVideoDecoderFactory>
video_decoder_factory_;
rtc::scoped_ptr<webrtc::DtlsIdentityStore> dtls_identity_store_;
rtc::scoped_refptr<RefCountedDtlsIdentityStore> dtls_identity_store_;
};
} // namespace webrtc

View File

@ -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<FakeDtlsIdentityStore> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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<DtlsIdentityStoreInterface> dtls_identity_store(
new FakeDtlsIdentityStore());
rtc::scoped_refptr<PeerConnectionInterface> 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;

View File

@ -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<PeerConnectionInterface>,
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<PeerConnectionInterface> CreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& a1,
const MediaConstraintsInterface* a2,
PortAllocatorFactoryInterface* a3,
rtc::scoped_ptr<DtlsIdentityStoreInterface> a4,
PeerConnectionObserver* a5) override {
return owner_thread_->Invoke<rtc::scoped_refptr<PeerConnectionInterface>>(
rtc::Bind(&PeerConnectionFactoryProxy::CreatePeerConnection_ot, this,
a1, a2, a3, a4.release(), a5));
}
PROXY_METHOD1(rtc::scoped_refptr<MediaStreamInterface>,
CreateLocalMediaStream, const std::string&)
PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>,
@ -56,6 +62,17 @@ BEGIN_PROXY_MAP(PeerConnectionFactory)
PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>,
CreateAudioTrack, const std::string&, AudioSourceInterface*)
PROXY_METHOD1(bool, StartAecDump, rtc::PlatformFile)
private:
rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection_ot(
const PeerConnectionInterface::RTCConfiguration& a1,
const MediaConstraintsInterface* a2,
PortAllocatorFactoryInterface* a3,
DtlsIdentityStoreInterface* a4,
PeerConnectionObserver* a5) {
rtc::scoped_ptr<DtlsIdentityStoreInterface> ptr_a4(a4);
return c_->CreatePeerConnection(a1, a2, a3, ptr_a4.Pass(), a5);
}
END_PROXY()
} // namespace webrtc

View File

@ -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<PeerConnectionInterface>
CreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& configuration,
@ -543,21 +546,23 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface {
DTLSIdentityServiceInterface* dtls_identity_service,
rtc::scoped_ptr<DtlsIdentityStoreInterface> 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<PeerConnectionInterface>
CreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& configuration,
const MediaConstraintsInterface* constraints,
PortAllocatorFactoryInterface* allocator_factory,
DTLSIdentityServiceInterface* dtls_identity_service,
rtc::scoped_ptr<DtlsIdentityStoreInterface> 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<DtlsIdentityStoreInterface> 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<MediaStreamInterface>

View File

@ -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<webrtc::DtlsIdentityStoreInterface> 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());

View File

@ -28,6 +28,9 @@
#ifndef TALK_APP_WEBRTC_TEST_FAKEDTLSIDENTITYSERVICE_H_
#define TALK_APP_WEBRTC_TEST_FAKEDTLSIDENTITYSERVICE_H_
#include <string>
#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<rtc::scoped_refptr<
webrtc::DtlsIdentityRequestObserver> > MessageData;
std::string common_name;
rtc::scoped_refptr<DTLSIdentityRequestObserver> observer;
};
typedef rtc::TypedMessageData<Request> 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<webrtc::DtlsIdentityRequestObserver>&
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<webrtc::DtlsIdentityRequestObserver>(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<FakeIdentityService::MessageData*>(msg->pdata);
DTLSIdentityRequestObserver* observer = message_data->data().observer.get();
MessageData* message_data = static_cast<MessageData*>(msg->pdata);
rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver> 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_;
};

View File

@ -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<webrtc::DtlsIdentityStoreInterface> 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;
}

View File

@ -36,6 +36,7 @@
#include "webrtc/base/thread.h"
namespace webrtc {
class DtlsIdentityStoreInterface;
class PortAllocatorFactoryInterface;
}

View File

@ -523,7 +523,7 @@ WebRtcSession::~WebRtcSession() {
bool WebRtcSession::Initialize(
const PeerConnectionFactoryInterface::Options& options,
const MediaConstraintsInterface* constraints,
DTLSIdentityServiceInterface* dtls_identity_service,
rtc::scoped_ptr<DtlsIdentityStoreInterface> 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_,

View File

@ -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<DtlsIdentityStoreInterface> dtls_identity_store,
const PeerConnectionInterface::RTCConfiguration& rtc_configuration);
// Deletes the voice, video and data channel and changes the session state
// to STATE_RECEIVEDTERMINATE.

View File

@ -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<webrtc::DtlsIdentityStoreInterface> 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<FakeDtlsIdentityStore> 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() {

View File

@ -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<rtc::SSLIdentity> 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<DtlsIdentityStoreInterface> 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<WebRtcIdentityRequestObserver>();
@ -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;

View File

@ -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<rtc::SSLIdentity> identity) override;
void OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity> identity) override;
sigslot::signal1<int> SignalRequestFailed;
sigslot::signal1<rtc::SSLIdentity*> 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<DtlsIdentityStoreInterface> 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<DTLSIdentityServiceInterface> identity_service_;
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store_;
rtc::scoped_refptr<WebRtcIdentityRequestObserver> identity_request_observer_;
WebRtcSession* const session_;
const std::string session_id_;

View File

@ -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',

View File

@ -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',

View File

@ -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