Index: talk/app/webrtc/webrtcsessiondescriptionfactory.cc |
diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc |
index 6c6981ce5a9987e12f185cc4b351bb105d438bbf..2abfd170e1386b2ef7a53e622a4d86e3a73f15b1 100644 |
--- a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc |
+++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc |
@@ -68,7 +68,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 { |
@@ -126,11 +127,14 @@ void WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( |
} |
} |
+// Private constructor called by other constructors. |
WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
rtc::Thread* signaling_thread, |
cricket::ChannelManager* channel_manager, |
MediaStreamSignaling* mediastream_signaling, |
rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
+ const rtc::scoped_refptr<WebRtcIdentityRequestObserver>& |
+ identity_request_observer, |
WebRtcSession* session, |
const std::string& session_id, |
cricket::DataChannelType dct, |
@@ -144,31 +148,87 @@ WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
// |kInitSessionVersion|. |
session_version_(kInitSessionVersion), |
dtls_identity_store_(dtls_identity_store.Pass()), |
+ identity_request_observer_(identity_request_observer), |
session_(session), |
session_id_(session_id), |
data_channel_type_(dct), |
- identity_request_state_(IDENTITY_NOT_NEEDED) { |
+ certificate_request_state_(CERTIFICATE_NOT_NEEDED) { |
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_); |
- |
- if (dtls_enabled && dtls_identity_store_) { |
- identity_request_observer_ = |
- new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(); |
+WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
+ rtc::Thread* signaling_thread, |
+ cricket::ChannelManager* channel_manager, |
+ MediaStreamSignaling* mediastream_signaling, |
+ WebRtcSession* session, |
+ const std::string& session_id, |
+ cricket::DataChannelType dct) |
+ : WebRtcSessionDescriptionFactory( |
+ signaling_thread, channel_manager, mediastream_signaling, nullptr, |
+ nullptr, session, session_id, dct, false) { |
+ LOG(LS_VERBOSE) << "DTLS-SRTP disabled."; |
+} |
- identity_request_observer_->SignalRequestFailed.connect( |
- this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); |
- identity_request_observer_->SignalIdentityReady.connect( |
- this, &WebRtcSessionDescriptionFactory::SetIdentity); |
+WebRtcSessionDescriptionFactory::WebRtcSessionDescriptionFactory( |
+ rtc::Thread* signaling_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, |
+ channel_manager, |
+ mediastream_signaling, |
+ dtls_identity_store.Pass(), |
+ new rtc::RefCountedObject<WebRtcIdentityRequestObserver>(), |
+ session, |
+ session_id, |
+ dct, |
+ true) { |
+ DCHECK(dtls_identity_store_); |
+ |
+ certificate_request_state_ = CERTIFICATE_WAITING; |
+ |
+ identity_request_observer_->SignalRequestFailed.connect( |
+ this, &WebRtcSessionDescriptionFactory::OnIdentityRequestFailed); |
+ identity_request_observer_->SignalIdentityReady.connect( |
+ this, &WebRtcSessionDescriptionFactory::SetIdentity); |
+ |
+ rtc::KeyType key_type = rtc::KT_DEFAULT; |
+ LOG(LS_VERBOSE) << "DTLS-SRTP enabled; sending DTLS identity request (key " |
+ << "type: " << key_type << ")."; |
+ |
+ // Request identity. This happens asynchronously, so the caller will have a |
+ // chance to connect to SignalIdentityReady. |
+ dtls_identity_store_->RequestIdentity(key_type, identity_request_observer_); |
+} |
- 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, |
+ cricket::ChannelManager* channel_manager, |
+ MediaStreamSignaling* mediastream_signaling, |
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate, |
+ WebRtcSession* session, |
+ const std::string& session_id, |
+ cricket::DataChannelType dct) |
+ : WebRtcSessionDescriptionFactory( |
+ signaling_thread, channel_manager, mediastream_signaling, nullptr, |
+ nullptr, session, session_id, dct, true) { |
+ DCHECK(certificate); |
+ |
+ certificate_request_state_ = CERTIFICATE_WAITING; |
+ |
+ LOG(LS_VERBOSE) << "DTLS-SRTP enabled; has certificate parameter."; |
+ // We already have a certificate but we wait to do SetIdentity; if we do |
+ // it in the constructor then the caller has not had a chance to connect to |
+ // SignalIdentityReady. |
+ signaling_thread_->Post(this, MSG_USE_CONSTRUCTOR_CERTIFICATE, |
+ new rtc::ScopedRefMessageData<rtc::RTCCertificate>( |
+ certificate)); |
} |
WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() { |
@@ -181,8 +241,19 @@ WebRtcSessionDescriptionFactory::~WebRtcSessionDescriptionFactory() { |
// this, requests will linger and not know they succeeded or failed. |
rtc::MessageList list; |
signaling_thread_->Clear(this, rtc::MQID_ANY, &list); |
- for (auto& msg : list) |
- OnMessage(&msg); |
+ for (auto& msg : list) { |
+ if (msg.message_id != MSG_USE_CONSTRUCTOR_CERTIFICATE) |
+ OnMessage(&msg); |
+ else { |
+ // Skip MSG_USE_CONSTRUCTOR_CERTIFICATE because we don't want to trigger |
+ // SetIdentity-related callbacks in the destructor. This can be a problem |
+ // when WebRtcSession listens to the callback but it was the WebRtcSession |
+ // destructor that caused WebRtcSessionDescriptionFactory's destruction. |
+ // The callback is then ignored, leaking memory allocated by OnMessage for |
+ // MSG_USE_CONSTRUCTOR_CERTIFICATE. |
+ delete msg.pdata; |
+ } |
+ } |
transport_desc_factory_.set_identity(NULL); |
} |
@@ -193,7 +264,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); |
@@ -222,11 +293,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); |
} |
} |
@@ -235,7 +306,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); |
@@ -277,11 +348,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); |
} |
} |
@@ -311,6 +382,17 @@ void WebRtcSessionDescriptionFactory::OnMessage(rtc::Message* msg) { |
delete param; |
break; |
} |
+ case MSG_USE_CONSTRUCTOR_CERTIFICATE: { |
+ rtc::ScopedRefMessageData<rtc::RTCCertificate>* param = |
+ static_cast<rtc::ScopedRefMessageData<rtc::RTCCertificate>*>( |
+ msg->pdata); |
+ LOG(LS_INFO) << "Using certificate supplied to the constructor."; |
+ // TODO(hbos): Pass around scoped_refptr<RTCCertificate> instead of |
+ // SSLIdentity* (then there will be no need to do GetReference here). |
torbjorng (webrtc)
2015/08/21 12:39:19
Perhaps we ought to rename GetReference to make th
hbos
2015/08/24 10:16:44
Sure but let's do that in a separate CL, added a T
|
+ SetIdentity(param->data()->identity()->GetReference()); |
+ delete param; |
+ break; |
+ } |
default: |
ASSERT(false); |
break; |
@@ -429,7 +511,7 @@ 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); |
} |
@@ -438,7 +520,7 @@ void WebRtcSessionDescriptionFactory::SetIdentity( |
rtc::SSLIdentity* identity) { |
LOG(LS_VERBOSE) << "Setting new identity"; |
- identity_request_state_ = IDENTITY_SUCCEEDED; |
+ certificate_request_state_ = CERTIFICATE_SUCCEEDED; |
SignalIdentityReady(identity); |
transport_desc_factory_.set_identity(identity); |