Chromium Code Reviews| Index: talk/app/webrtc/webrtcsessiondescriptionfactory.cc | 
| diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc | 
| index 3dcc0a1a3b7a78a24da249a0f7b9271c07b7e405..2b2f7597bc1f2e4585f496253e3b7cedf90804de 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/messagequeue.h" | 
| #include "webrtc/base/sslidentity.h" | 
| using cricket::MediaSessionOptions; | 
| @@ -68,7 +69,8 @@ static bool ValidStreams(const MediaSessionOptions::Streams& streams) { | 
| enum { | 
| MSG_CREATE_SESSIONDESCRIPTION_SUCCESS, | 
| - MSG_CREATE_SESSIONDESCRIPTION_FAILED | 
| + MSG_CREATE_SESSIONDESCRIPTION_FAILED, | 
| + MSG_USE_CONSTRUCTOR_CERTIFICATE | 
| }; | 
| struct CreateSessionDescriptionMsg : public rtc::MessageData { | 
| @@ -97,14 +99,14 @@ void WebRtcIdentityRequestObserver::OnSuccess( | 
| rtc::kPemTypeRsaPrivateKey, | 
| reinterpret_cast<const unsigned char*>(der_private_key.data()), | 
| der_private_key.length()); | 
| - rtc::SSLIdentity* identity = | 
| - rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert); | 
| - SignalIdentityReady(identity); | 
| + rtc::scoped_ptr<rtc::SSLIdentity> identity( | 
| + rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert)); | 
| + SignalCertificateReady(DtlsCertificate::Create(identity.Pass())); | 
| } | 
| void WebRtcIdentityRequestObserver::OnSuccess( | 
| rtc::scoped_ptr<rtc::SSLIdentity> identity) { | 
| - SignalIdentityReady(identity.release()); | 
| + SignalCertificateReady(DtlsCertificate::Create(identity.Pass())); | 
| } | 
| // static | 
| @@ -126,16 +128,18 @@ void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( | 
| } | 
| } | 
| +// Private constructor called by other constructors. | 
| WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 
| rtc::Thread* signaling_thread, | 
| + rtc::Thread* worker_thread, | 
| cricket::ChannelManager* channel_manager, | 
| MediaStreamSignaling* mediastream_signaling, | 
| - rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 
| WebRtcSession* session, | 
| const std::string& session_id, | 
| cricket::DataChannelType dct, | 
| bool dtls_enabled) | 
| : signaling_thread_(signaling_thread), | 
| + worker_thread_(worker_thread), | 
| mediastream_signaling_(mediastream_signaling), | 
| session_desc_factory_(channel_manager, &transport_desc_factory_), | 
| // RFC 4566 suggested a Network Time Protocol (NTP) format timestamp | 
| @@ -143,33 +147,89 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 
| // to just use a random number as session id and start version from | 
| // |kInitSessionVersion|. | 
| session_version_(kInitSessionVersion), | 
| - dtls_identity_store_(dtls_identity_store.Pass()), | 
| session_(session), | 
| session_id_(session_id), | 
| data_channel_type_(dct), | 
| - identity_request_state_(IDENTITY_NOT_NEEDED) { | 
| + certificate_request_state_(CERTIFICATE_NOT_NEEDED) { | 
| transport_desc_factory_.set_protocol(cricket::ICEPROTO_RFC5245); | 
| session_desc_factory_.set_add_legacy_streams(false); | 
| // SRTP-SDES is disabled if DTLS is on. | 
| SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED); | 
| +} | 
| - // If |dtls_enabled| we must have a |dtls_identity_store_|. | 
| - DCHECK(!dtls_enabled || dtls_identity_store_); | 
| +WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 
| + rtc::Thread* signaling_thread, | 
| + rtc::Thread* worker_thread, | 
| + cricket::ChannelManager* channel_manager, | 
| + MediaStreamSignaling* mediastream_signaling, | 
| + WebRtcSession* session, | 
| + const std::string& session_id, | 
| + cricket::DataChannelType dct) | 
| + : WebRtcSessionDescriptionFactory(signaling_thread, worker_thread, | 
| + channel_manager, mediastream_signaling, | 
| + session, session_id, dct, false) { | 
| +} | 
| - if (dtls_enabled && dtls_identity_store_) { | 
| - identity_request_observer_ = | 
| - new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(); | 
| +WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 
| + rtc::Thread* signaling_thread, | 
| + rtc::Thread* worker_thread, | 
| + cricket::ChannelManager* channel_manager, | 
| + MediaStreamSignaling* mediastream_signaling, | 
| + rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 
| + WebRtcSession* session, | 
| + const std::string& session_id, | 
| + cricket::DataChannelType dct) | 
| + : WebRtcSessionDescriptionFactory(signaling_thread, worker_thread, | 
| + channel_manager, mediastream_signaling, | 
| + session, session_id, dct, true) { | 
| + dtls_identity_store_.reset(dtls_identity_store.release()); | 
| 
 
tommi (sloooow) - chröme
2015/08/18 14:49:35
dtls_identity_store_(dtls_identity_store.Pass()) i
 
 | 
| + | 
| + // Generate certificate. | 
| + certificate_request_state_ = CERTIFICATE_WAITING; | 
| + | 
| + identity_request_observer_ = | 
| + new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(); | 
| + identity_request_observer_->SignalRequestFailed.connect( | 
| + this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); | 
| + identity_request_observer_->SignalCertificateReady.connect( | 
| + this, &WebRtcSessionDescriptionFactory::SetCertificate); | 
| + | 
| + // If an |dtls_identity_store_| was not provided we default to using | 
| + // DtlsIdentityStore. | 
| + if (!dtls_identity_store_) { | 
| + dtls_identity_store_.reset( | 
| + new DtlsIdentityStoreImpl(signaling_thread_, worker_thread_)); | 
| + } | 
| - identity_request_observer_->SignalRequestFailed.connect( | 
| - this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); | 
| - identity_request_observer_->SignalIdentityReady.connect( | 
| - this, &WebRtcSessionDescriptionFactory::SetIdentity); | 
| + // Request identity. This happens asynchronously, so the caller will have a | 
| + // chance to connect to SignalCertificateReady. | 
| + dtls_identity_store_->RequestIdentity(rtc::KT_DEFAULT, | 
| + identity_request_observer_); | 
| + LOG(LS_VERBOSE) << "DTLS-SRTP enabled, sent DTLS identity request."; | 
| +} | 
| - LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request."; | 
| - identity_request_state_ = IDENTITY_WAITING; | 
| - dtls_identity_store_->RequestIdentity(rtc::KT_DEFAULT, | 
| - identity_request_observer_); | 
| - } | 
| +WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( | 
| + rtc::Thread* signaling_thread, | 
| + rtc::Thread* worker_thread, | 
| + cricket::ChannelManager* channel_manager, | 
| + MediaStreamSignaling* mediastream_signaling, | 
| + const rtc::scoped_refptr<DtlsCertificate>& certificate, | 
| + WebRtcSession* session, | 
| + const std::string& session_id, | 
| + cricket::DataChannelType dct) | 
| + : WebRtcSessionDescriptionFactory(signaling_thread, worker_thread, | 
| + channel_manager, mediastream_signaling, | 
| + session, session_id, dct, true) { | 
| + DCHECK(certificate.get()); | 
| + | 
| + LOG(LS_VERBOSE) << "DTLS-SRTP enabled; using DTLS certificate."; | 
| + // We already have a certificate but we wait to do SetCertificate; if we do | 
| + // it in the constructor then the caller has not had a chance to connect to | 
| + // SignalCertificateReady. | 
| + certificate_request_state_ = CERTIFICATE_WAITING; | 
| + signaling_thread_->Post(this, MSG_USE_CONSTRUCTOR_CERTIFICATE, | 
| + new rtc::ScopedRefMessageData<DtlsCertificate>( | 
| + certificate)); | 
| } | 
| WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() { | 
| @@ -185,7 +245,7 @@ WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() { | 
| for (auto& msg : list) | 
| OnMessage(&msg); | 
| - transport_desc_factory_.set_identity(NULL); | 
| + transport_desc_factory_.set_certificate(nullptr); | 
| } | 
| void WebRtcSessionDescriptionFactory::CreateOffer( | 
| @@ -194,7 +254,7 @@ void WebRtcSessionDescriptionFactory::CreateOffer( | 
| cricket::MediaSessionOptions session_options; | 
| std::string error = "CreateOffer"; | 
| - if (identity_request_state_ == IDENTITY_FAILED) { | 
| + if (certificate_request_state_ == CERTIFICATE_FAILED) { | 
| error += kFailedDueToIdentityFailed; | 
| LOG(LS_ERROR) << error; | 
| PostCreateSessionDescriptionFailed(observer, error); | 
| @@ -223,11 +283,11 @@ void WebRtcSessionDescriptionFactory::CreateOffer( | 
| CreateSessionDescriptionRequest request( | 
| CreateSessionDescriptionRequest::kOffer, observer, session_options); | 
| - if (identity_request_state_ == IDENTITY_WAITING) { | 
| + if (certificate_request_state_ == CERTIFICATE_WAITING) { | 
| create_session_description_requests_.push(request); | 
| } else { | 
| - ASSERT(identity_request_state_ == IDENTITY_SUCCEEDED || | 
| - identity_request_state_ == IDENTITY_NOT_NEEDED); | 
| + ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED || | 
| + certificate_request_state_ == CERTIFICATE_NOT_NEEDED); | 
| InternalCreateOffer(request); | 
| } | 
| } | 
| @@ -236,7 +296,7 @@ void WebRtcSessionDescriptionFactory::CreateAnswer( | 
| CreateSessionDescriptionObserver* observer, | 
| const MediaConstraintsInterface* constraints) { | 
| std::string error = "CreateAnswer"; | 
| - if (identity_request_state_ == IDENTITY_FAILED) { | 
| + if (certificate_request_state_ == CERTIFICATE_FAILED) { | 
| error += kFailedDueToIdentityFailed; | 
| LOG(LS_ERROR) << error; | 
| PostCreateSessionDescriptionFailed(observer, error); | 
| @@ -278,11 +338,11 @@ void WebRtcSessionDescriptionFactory::CreateAnswer( | 
| CreateSessionDescriptionRequest request( | 
| CreateSessionDescriptionRequest::kAnswer, observer, options); | 
| - if (identity_request_state_ == IDENTITY_WAITING) { | 
| + if (certificate_request_state_ == CERTIFICATE_WAITING) { | 
| create_session_description_requests_.push(request); | 
| } else { | 
| - ASSERT(identity_request_state_ == IDENTITY_SUCCEEDED || | 
| - identity_request_state_ == IDENTITY_NOT_NEEDED); | 
| + ASSERT(certificate_request_state_ == CERTIFICATE_SUCCEEDED || | 
| + certificate_request_state_ == CERTIFICATE_NOT_NEEDED); | 
| InternalCreateAnswer(request); | 
| } | 
| } | 
| @@ -312,6 +372,14 @@ void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) { | 
| delete param; | 
| break; | 
| } | 
| + case MSG_USE_CONSTRUCTOR_CERTIFICATE: { | 
| + rtc::ScopedRefMessageData<DtlsCertificate>* param = | 
| + static_cast<rtc::ScopedRefMessageData<DtlsCertificate>*>(msg->pdata); | 
| + LOG(LS_INFO) << "Using certificate supplied to constructor."; | 
| + SetCertificate(param->data()); | 
| + delete param; | 
| + break; | 
| + } | 
| default: | 
| ASSERT(false); | 
| break; | 
| @@ -430,19 +498,21 @@ void WebRtcSessionDescriptionFactory::OnIdentityRequestFailed(int error) { | 
| ASSERT(signaling_thread_->IsCurrent()); | 
| LOG(LS_ERROR) << "Async identity request failed: error = " << error; | 
| - identity_request_state_ = IDENTITY_FAILED; | 
| + certificate_request_state_ = CERTIFICATE_FAILED; | 
| FailPendingRequests(kFailedDueToIdentityFailed); | 
| } | 
| -void WebRtcSessionDescriptionFactory::SetIdentity( | 
| - rtc::SSLIdentity* identity) { | 
| - LOG(LS_VERBOSE) << "Setting new identity"; | 
| +void WebRtcSessionDescriptionFactory::SetCertificate( | 
| + const rtc::scoped_refptr<DtlsCertificate>& certificate) { | 
| + LOG(LS_VERBOSE) << "Setting new certificate"; | 
| + | 
| + DCHECK(certificate); | 
| - identity_request_state_ = IDENTITY_SUCCEEDED; | 
| - SignalIdentityReady(identity); | 
| + certificate_request_state_ = CERTIFICATE_SUCCEEDED; | 
| + SignalCertificateReady(certificate); | 
| - transport_desc_factory_.set_identity(identity); | 
| + transport_desc_factory_.set_certificate(certificate); | 
| transport_desc_factory_.set_secure(cricket::SEC_ENABLED); | 
| while (!create_session_description_requests_.empty()) { |