Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: talk/app/webrtc/dtlsidentitystore.cc

Issue 1176383004: DtlsIdentityStore[Interface/Impl] updated, DtlsIdentityService to be removed (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Del old requestobserver & service interface (forgot), made global common_name_ const char* Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 12 matching lines...) Expand all
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "talk/app/webrtc/dtlsidentitystore.h" 28 #include "talk/app/webrtc/dtlsidentitystore.h"
29 29
30 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" 30 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
31 #include "webrtc/base/logging.h" 31 #include "webrtc/base/logging.h"
32 32
33 using webrtc::DTLSIdentityRequestObserver; 33 using webrtc::DtlsIdentityRequestObserver;
34 using webrtc::WebRtcSessionDescriptionFactory; 34 using webrtc::WebRtcSessionDescriptionFactory;
35 35
36 namespace webrtc { 36 namespace webrtc {
37 37
38 const char* DtlsIdentityStoreImpl::common_name_ = "WebRTC";
39
38 namespace { 40 namespace {
39 41
40 enum { 42 enum {
41 MSG_DESTROY, 43 MSG_DESTROY,
42 MSG_GENERATE_IDENTITY, 44 MSG_GENERATE_IDENTITY,
43 MSG_GENERATE_IDENTITY_RESULT, 45 MSG_GENERATE_IDENTITY_RESULT
44 MSG_RETURN_FREE_IDENTITY
45 }; 46 };
46 47
47 typedef rtc::ScopedMessageData<rtc::SSLIdentity> IdentityResultMessageData; 48 typedef rtc::ScopedMessageData<rtc::SSLIdentity> IdentityResultMessageData;
48 49
49 } // namespace 50 } // namespace
50 51
51 // This class runs on the worker thread to generate the identity. It's necessary 52 // This class runs on the worker thread to generate the identity. It's necessary
52 // to separate this class from DtlsIdentityStore so that it can live on the 53 // to separate this class from DtlsIdentityStore so that it can live on the
53 // worker thread after DtlsIdentityStore is destroyed. 54 // worker thread after DtlsIdentityStore is destroyed.
54 class DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>, 55 class DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>,
55 public rtc::MessageHandler { 56 public rtc::MessageHandler {
56 public: 57 public:
57 explicit WorkerTask(DtlsIdentityStore* store) 58 explicit WorkerTask(
58 : signaling_thread_(rtc::Thread::Current()), store_(store) { 59 DtlsIdentityStoreImpl* store, rtc::KeyType key_type,
60 bool is_preemptive)
61 : signaling_thread_(rtc::Thread::Current()),
62 store_(store),
63 key_type_(key_type),
64 is_preemptive_(is_preemptive) {
65 DCHECK(!is_preemptive_ || key_type_ == rtc::KT_RSA);
59 store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed); 66 store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed);
60 } 67 }
61 68
62 virtual ~WorkerTask() { DCHECK(rtc::Thread::Current() == signaling_thread_); } 69 virtual ~WorkerTask() { DCHECK(rtc::Thread::Current() == signaling_thread_); }
63 70
64 private: 71 private:
65 void GenerateIdentity_w() { 72 void GenerateIdentity_w() {
73 if (is_preemptive_) {
74 DCHECK(key_type_ == rtc::KT_RSA);
75 // If |store_| has a |free_rsa_identity_| we can take it and abort trying
76 // to generate one.
hbos 2015/06/15 10:10:34 In the old code, |free_identity_| was checked when
hbos 2015/06/18 08:43:12 In PS4 I changed the implementation quite a bit ag
77 rtc::CritScope cs(&cs_);
78 if (store_) {
79 rtc::scoped_ptr<rtc::SSLIdentity> identity(
80 store_->ReleaseFreeRSAIdentity());
81 if (identity.get()) {
82 store_->PostGenerateIdentityResult_w(identity.Pass());
83 return;
84 }
85 } else {
86 return; // Store has already been destroyed, no need to generate.
87 }
88 }
89
90 // TODO(hbos): Use key_type_ when torbjorng's CL has landed.
91 LOG(LS_INFO) << "Generating identity. Key type (TODO: should use): "
92 << key_type_;
66 rtc::scoped_ptr<rtc::SSLIdentity> identity( 93 rtc::scoped_ptr<rtc::SSLIdentity> identity(
67 rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName)); 94 rtc::SSLIdentity::Generate(common_name_));
68 95
69 { 96 {
70 rtc::CritScope cs(&cs_); 97 rtc::CritScope cs(&cs_);
71 if (store_) { 98 if (store_) {
72 store_->PostGenerateIdentityResult_w(identity.Pass()); 99 store_->PostGenerateIdentityResult_w(identity.Pass());
73 } 100 }
74 } 101 }
75 } 102 }
76 103
77 void OnMessage(rtc::Message* msg) override { 104 void OnMessage(rtc::Message* msg) override {
(...skipping 15 matching lines...) Expand all
93 CHECK(false) << "Unexpected message type"; 120 CHECK(false) << "Unexpected message type";
94 } 121 }
95 } 122 }
96 123
97 void OnStoreDestroyed() { 124 void OnStoreDestroyed() {
98 rtc::CritScope cs(&cs_); 125 rtc::CritScope cs(&cs_);
99 store_ = NULL; 126 store_ = NULL;
100 } 127 }
101 128
102 rtc::Thread* const signaling_thread_; 129 rtc::Thread* const signaling_thread_;
130 // Locking this prevents |store_| from being destroyed if it has not already
131 // been so.
103 rtc::CriticalSection cs_; 132 rtc::CriticalSection cs_;
104 DtlsIdentityStore* store_; 133 DtlsIdentityStoreImpl* store_;
134 rtc::KeyType key_type_;
135 bool is_preemptive_;
105 }; 136 };
106 137
107 // Arbitrary constant used as common name for the identity. 138 DtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread,
108 // Chosen to make the certificates more readable. 139 rtc::Thread* worker_thread)
109 const char DtlsIdentityStore::kIdentityName[] = "WebRTC";
110
111 DtlsIdentityStore::DtlsIdentityStore(rtc::Thread* signaling_thread,
112 rtc::Thread* worker_thread)
113 : signaling_thread_(signaling_thread), 140 : signaling_thread_(signaling_thread),
114 worker_thread_(worker_thread), 141 worker_thread_(worker_thread),
115 pending_jobs_(0) {} 142 pending_requests_(),
143 free_rsa_identity_(nullptr),
144 free_rsa_identity_cs_() {}
116 145
117 DtlsIdentityStore::~DtlsIdentityStore() { 146 DtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() {
118 SignalDestroyed(); 147 SignalDestroyed();
119 } 148 }
120 149
121 void DtlsIdentityStore::Initialize() { 150 void DtlsIdentityStoreImpl::Initialize() {
122 DCHECK(rtc::Thread::Current() == signaling_thread_); 151 DCHECK(rtc::Thread::Current() == signaling_thread_);
123 // Do not aggressively generate the free identity if the worker thread and the 152 // Preemptively generate an RSA identity (|free_rsa_identity_|) unless the
124 // signaling thread are the same. 153 // worker thread and signaling thread are the same (expensive).
125 if (worker_thread_ != signaling_thread_) { 154 if (worker_thread_ != signaling_thread_)
126 GenerateIdentity(); 155 GenerateIdentity(rtc::KT_RSA, nullptr);
127 }
128 } 156 }
129 157
130 void DtlsIdentityStore::RequestIdentity(DTLSIdentityRequestObserver* observer) { 158 void DtlsIdentityStoreImpl::RequestIdentity(
159 rtc::KeyType key_type, DtlsIdentityRequestObserver* observer) {
131 DCHECK(rtc::Thread::Current() == signaling_thread_); 160 DCHECK(rtc::Thread::Current() == signaling_thread_);
132 DCHECK(observer); 161 DCHECK(observer);
133 162
134 // Must return the free identity async. 163 GenerateIdentity(key_type, observer);
135 if (free_identity_.get()) {
136 IdentityResultMessageData* msg =
137 new IdentityResultMessageData(free_identity_.release());
138 signaling_thread_->Post(this, MSG_RETURN_FREE_IDENTITY, msg);
139 }
140
141 pending_observers_.push(observer);
142 GenerateIdentity();
143 } 164 }
144 165
145 void DtlsIdentityStore::OnMessage(rtc::Message* msg) { 166 void DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) {
146 DCHECK(rtc::Thread::Current() == signaling_thread_); 167 DCHECK(rtc::Thread::Current() == signaling_thread_);
147 switch (msg->message_id) { 168 switch (msg->message_id) {
148 case MSG_GENERATE_IDENTITY_RESULT: { 169 case MSG_GENERATE_IDENTITY_RESULT: {
149 rtc::scoped_ptr<IdentityResultMessageData> pdata( 170 rtc::scoped_ptr<IdentityResultMessageData> pdata(
150 static_cast<IdentityResultMessageData*>(msg->pdata)); 171 static_cast<IdentityResultMessageData*>(msg->pdata));
151 OnIdentityGenerated(pdata->data().Pass()); 172 OnIdentityGenerated(pdata->data().Pass());
152 break; 173 break;
153 } 174 }
154 case MSG_RETURN_FREE_IDENTITY: {
155 rtc::scoped_ptr<IdentityResultMessageData> pdata(
156 static_cast<IdentityResultMessageData*>(msg->pdata));
157 ReturnIdentity(pdata->data().Pass());
158 break;
159 }
160 } 175 }
161 } 176 }
162 177
163 bool DtlsIdentityStore::HasFreeIdentityForTesting() const { 178 bool DtlsIdentityStoreImpl::HasFreeIdentityForTesting() const {
164 DCHECK(rtc::Thread::Current() == signaling_thread_); 179 DCHECK(rtc::Thread::Current() == signaling_thread_);
165 return free_identity_.get() != nullptr; 180 rtc::CritScope cs(&free_rsa_identity_cs_);
181 return free_rsa_identity_.get() != nullptr;
166 } 182 }
167 183
168 void DtlsIdentityStore::GenerateIdentity() { 184 void DtlsIdentityStoreImpl::GenerateIdentity(
185 rtc::KeyType key_type, DtlsIdentityRequestObserver* observer) {
169 DCHECK(rtc::Thread::Current() == signaling_thread_); 186 DCHECK(rtc::Thread::Current() == signaling_thread_);
170 pending_jobs_++; 187 #if !defined(NDEBUG)
188 {
189 // Only grab lock for DCHECK if debugging.
190 rtc::CritScope cs(&free_rsa_identity_cs_);
191 // Preemptive generation requests (!|observer|) are only performed with RSA
192 // and must only be performed when we don't already have one generated
193 // (|free_rsa_identity_|) and don't already have such request pending.
194 DCHECK(observer || (key_type == rtc::KT_RSA && !free_rsa_identity_.get() &&
195 !HasPendingRSARequest()));
196 }
197 #endif
198
199 // Enqueue the request.
hbos 2015/06/15 10:10:34 I made it simple by always queuing a request and h
hbos 2015/06/18 08:43:12 Addressed in PS4.
200 pending_requests_.push_back(IdentityRequest(key_type, observer));
171 LOG(LS_VERBOSE) << "New DTLS identity generation is posted, " 201 LOG(LS_VERBOSE) << "New DTLS identity generation is posted, "
172 << "pending_identities=" << pending_jobs_; 202 << "pending requests: " << pending_requests_.size();
173 203 // Post one WorkerTask per request.
174 WorkerTask* task = new WorkerTask(this); 204 WorkerTask* task = new WorkerTask(this, key_type, !observer);
175 // The WorkerTask is owned by the message data to make sure it will not be 205 // The WorkerTask is owned by the message data to make sure it will not be
176 // leaked even if the task does not get run. 206 // leaked even if the task does not get run.
177 IdentityTaskMessageData* msg = new IdentityTaskMessageData(task); 207 IdentityTaskMessageData* msg = new IdentityTaskMessageData(task);
178 worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); 208 worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg);
179 } 209 }
180 210
181 void DtlsIdentityStore::OnIdentityGenerated( 211 void DtlsIdentityStoreImpl::OnIdentityGenerated(
182 rtc::scoped_ptr<rtc::SSLIdentity> identity) { 212 rtc::scoped_ptr<rtc::SSLIdentity> identity) {
183 DCHECK(rtc::Thread::Current() == signaling_thread_); 213 DCHECK(rtc::Thread::Current() == signaling_thread_);
184 214
185 pending_jobs_--; 215 DCHECK(!pending_requests_.empty());
216 IdentityRequest request = pending_requests_.front();
217 pending_requests_.pop_front();
218 // TODO(hbos): would be nice to be able to do:
219 //DCHECK(request.key_type_ == same as of the one generated);
220
186 LOG(LS_VERBOSE) << "A DTLS identity generation job returned, " 221 LOG(LS_VERBOSE) << "A DTLS identity generation job returned, "
187 << "pending_identities=" << pending_jobs_; 222 << "pending requests: " << pending_requests_.size();
188 223
189 if (pending_observers_.empty()) { 224
190 if (!free_identity_.get()) { 225 // Has on observer?
191 free_identity_.reset(identity.release()); 226 if (request.observer_.get() == nullptr) {
192 LOG(LS_VERBOSE) << "A free DTLS identity is saved"; 227 // Not having an observer: result should be stored in |free_rsa_identity_|.
228 rtc::CritScope cs(&free_rsa_identity_cs_);
229 DCHECK(!free_rsa_identity_.get());
230 free_rsa_identity_.reset(identity.release());
231 if (free_rsa_identity_.get())
232 LOG(LS_VERBOSE) << "A free SSL identity (RSA) was saved";
233 else
234 LOG(LS_WARNING) << "Failed to generate SSL identity (preemptively)";
235 } else {
236 // Return the result to the observer.
237 if (identity.get()) {
238 request.observer_->OnSuccessWithIdentityObj(identity.Pass());
239 } else {
240 LOG(LS_WARNING) << "Failed to generate SSL identity";
241 // Pass an arbitrary error code.
242 request.observer_->OnFailure(0);
193 } 243 }
194 return;
195 }
196 ReturnIdentity(identity.Pass());
197 }
198 244
199 void DtlsIdentityStore::ReturnIdentity( 245 // Preemptively generate (another) RSA identity?
200 rtc::scoped_ptr<rtc::SSLIdentity> identity) { 246 rtc::CritScope cs(&free_rsa_identity_cs_);
201 DCHECK(rtc::Thread::Current() == signaling_thread_); 247 if (!free_rsa_identity_.get() && !HasPendingRSARequest()) {
202 DCHECK(!free_identity_.get()); 248 // Preemptively generate an RSA identity (|free_rsa_identity_|) unless the
203 DCHECK(!pending_observers_.empty()); 249 // worker thread and signaling thread are the same (expensive).
204 250 if (worker_thread_ != signaling_thread_)
205 rtc::scoped_refptr<DTLSIdentityRequestObserver> observer = 251 GenerateIdentity(rtc::KT_RSA, nullptr);
206 pending_observers_.front(); 252 }
207 pending_observers_.pop();
208
209 if (identity.get()) {
210 observer->OnSuccessWithIdentityObj(identity.Pass());
211 } else {
212 // Pass an arbitrary error code.
213 observer->OnFailure(0);
214 LOG(LS_WARNING) << "Failed to generate SSL identity";
215 }
216
217 // Do not aggressively generate the free identity if the worker thread and the
218 // signaling thread are the same.
219 if (worker_thread_ != signaling_thread_ &&
220 pending_observers_.empty() &&
221 pending_jobs_ == 0) {
222 // Generate a free identity in the background.
223 GenerateIdentity();
224 } 253 }
225 } 254 }
226 255
227 void DtlsIdentityStore::PostGenerateIdentityResult_w( 256 void DtlsIdentityStoreImpl::PostGenerateIdentityResult_w(
228 rtc::scoped_ptr<rtc::SSLIdentity> identity) { 257 rtc::scoped_ptr<rtc::SSLIdentity> identity) {
229 DCHECK(rtc::Thread::Current() == worker_thread_); 258 DCHECK(rtc::Thread::Current() == worker_thread_);
230 259
231 IdentityResultMessageData* msg = 260 IdentityResultMessageData* msg =
232 new IdentityResultMessageData(identity.release()); 261 new IdentityResultMessageData(identity.release());
233 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); 262 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
234 } 263 }
264
265 bool DtlsIdentityStoreImpl::HasPendingRSARequest() {
266 for (const IdentityRequest& request : pending_requests_) {
267 if (request.key_type_ == rtc::KT_RSA)
268 return true;
269 }
270 return false;
271 }
272
273 rtc::SSLIdentity* DtlsIdentityStoreImpl::ReleaseFreeRSAIdentity() {
274 rtc::CritScope cs(&free_rsa_identity_cs_);
275 return free_rsa_identity_.release();
276 }
277
235 } // namespace webrtc 278 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698