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

Side by Side Diff: webrtc/api/dtlsidentitystore.cc

Issue 2028033002: Remove DtlsIdentityStoreImpl and RTCCertificateGeneratorStoreWrapper. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Added TODO and rebase Created 4 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
« no previous file with comments | « webrtc/api/dtlsidentitystore.h ('k') | webrtc/api/dtlsidentitystore_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/api/dtlsidentitystore.h" 11 #include "webrtc/api/dtlsidentitystore.h"
12 12
13 #include <utility>
14
15 #include "webrtc/api/webrtcsessiondescriptionfactory.h"
16 #include "webrtc/base/logging.h"
17
18 using webrtc::DtlsIdentityRequestObserver;
19
20 namespace webrtc { 13 namespace webrtc {
21 14
22 // Passed to SSLIdentity::Generate, "WebRTC". Used for the certificates' 15 // Passed to SSLIdentity::Generate, "WebRTC". Used for the certificates'
23 // subject and issuer name. 16 // subject and issuer name.
24 const char kIdentityName[] = "WebRTC"; 17 const char kIdentityName[] = "WebRTC";
25 18
26 namespace {
27
28 enum {
29 MSG_DESTROY,
30 MSG_GENERATE_IDENTITY,
31 MSG_GENERATE_IDENTITY_RESULT
32 };
33
34 // A |DtlsIdentityRequestObserver| that informs an
35 // |RTCCertificateGeneratorCallback| of the result of an identity request. On
36 // success, a certificate is created using the identity before passing it to
37 // the callback.
38 class RTCCertificateStoreCallbackObserver
39 : public webrtc::DtlsIdentityRequestObserver {
40 public:
41 RTCCertificateStoreCallbackObserver(
42 const rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback>& callback)
43 : callback_(callback) {}
44
45 private:
46 void OnFailure(int error) override {
47 LOG(LS_WARNING) << "DtlsIdentityRequestObserver failure code: " << error;
48 Callback(nullptr);
49 }
50 void OnSuccess(const std::string& der_cert,
51 const std::string& der_private_key) override {
52 std::string pem_cert = rtc::SSLIdentity::DerToPem(
53 rtc::kPemTypeCertificate,
54 reinterpret_cast<const unsigned char*>(der_cert.data()),
55 der_cert.length());
56 std::string pem_key = rtc::SSLIdentity::DerToPem(
57 rtc::kPemTypeRsaPrivateKey,
58 reinterpret_cast<const unsigned char*>(der_private_key.data()),
59 der_private_key.length());
60 std::unique_ptr<rtc::SSLIdentity> identity(
61 rtc::SSLIdentity::FromPEMStrings(pem_key, pem_cert));
62 OnSuccess(std::move(identity));
63 }
64 void OnSuccess(std::unique_ptr<rtc::SSLIdentity> identity) override {
65 Callback(rtc::RTCCertificate::Create(std::move(identity)));
66 }
67
68 void Callback(rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
69 if (certificate)
70 callback_->OnSuccess(certificate);
71 else
72 callback_->OnFailure();
73 }
74
75 rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback> callback_;
76 };
77
78 } // namespace
79
80 // This class runs on the worker thread to generate the identity. It's necessary
81 // to separate this class from DtlsIdentityStore so that it can live on the
82 // worker thread after DtlsIdentityStore is destroyed.
83 class DtlsIdentityStoreImpl::WorkerTask : public sigslot::has_slots<>,
84 public rtc::MessageHandler {
85 public:
86 WorkerTask(DtlsIdentityStoreImpl* store, rtc::KeyType key_type)
87 : signaling_thread_(rtc::Thread::Current()),
88 store_(store),
89 key_type_(key_type) {
90 store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed);
91 }
92
93 virtual ~WorkerTask() { RTC_DCHECK(signaling_thread_->IsCurrent()); }
94
95 private:
96 void GenerateIdentity_w() {
97 LOG(LS_INFO) << "Generating identity, using keytype " << key_type_;
98 std::unique_ptr<rtc::SSLIdentity> identity(
99 rtc::SSLIdentity::Generate(kIdentityName, key_type_));
100
101 // Posting to |this| avoids touching |store_| on threads other than
102 // |signaling_thread_| and thus avoids having to use locks.
103 IdentityResultMessageData* msg = new IdentityResultMessageData(
104 new IdentityResult(key_type_, std::move(identity)));
105 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
106 }
107
108 void OnMessage(rtc::Message* msg) override {
109 switch (msg->message_id) {
110 case MSG_GENERATE_IDENTITY:
111 // This message always runs on the worker thread.
112 GenerateIdentity_w();
113
114 // Must delete |this|, owned by msg->pdata, on the signaling thread to
115 // avoid races on disconnecting the signal.
116 signaling_thread_->Post(this, MSG_DESTROY, msg->pdata);
117 break;
118 case MSG_GENERATE_IDENTITY_RESULT:
119 RTC_DCHECK(signaling_thread_->IsCurrent());
120 {
121 std::unique_ptr<IdentityResultMessageData> pdata(
122 static_cast<IdentityResultMessageData*>(msg->pdata));
123 if (store_) {
124 store_->OnIdentityGenerated(pdata->data()->key_type_,
125 std::move(pdata->data()->identity_));
126 }
127 }
128 break;
129 case MSG_DESTROY:
130 RTC_DCHECK(signaling_thread_->IsCurrent());
131 delete msg->pdata;
132 // |this| has now been deleted. Don't touch member variables.
133 break;
134 default:
135 RTC_CHECK(false) << "Unexpected message type";
136 }
137 }
138
139 void OnStoreDestroyed() {
140 RTC_DCHECK(signaling_thread_->IsCurrent());
141 store_ = nullptr;
142 }
143
144 rtc::Thread* const signaling_thread_;
145 DtlsIdentityStoreImpl* store_; // Only touched on |signaling_thread_|.
146 const rtc::KeyType key_type_;
147 };
148
149 DtlsIdentityStoreImpl::DtlsIdentityStoreImpl(rtc::Thread* signaling_thread,
150 rtc::Thread* worker_thread)
151 : signaling_thread_(signaling_thread),
152 worker_thread_(worker_thread),
153 request_info_() {
154 RTC_DCHECK(signaling_thread_->IsCurrent());
155 }
156
157 DtlsIdentityStoreImpl::~DtlsIdentityStoreImpl() {
158 RTC_DCHECK(signaling_thread_->IsCurrent());
159 SignalDestroyed();
160 }
161
162 void DtlsIdentityStoreImpl::RequestIdentity(
163 const rtc::KeyParams& key_params,
164 const rtc::Optional<uint64_t>& expires_ms,
165 const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) {
166 RTC_DCHECK(signaling_thread_->IsCurrent());
167 RTC_DCHECK(observer);
168
169 // Dropping parameterization and |expires_ms|.
170 // TODO(hbos,torbjorng): Use parameterizaton/expiration. webrtc:5092.
171 GenerateIdentity(key_params.type(), observer);
172 }
173
174 void DtlsIdentityStoreImpl::OnMessage(rtc::Message* msg) {
175 RTC_DCHECK(signaling_thread_->IsCurrent());
176 switch (msg->message_id) {
177 case MSG_GENERATE_IDENTITY_RESULT: {
178 std::unique_ptr<IdentityResultMessageData> pdata(
179 static_cast<IdentityResultMessageData*>(msg->pdata));
180 OnIdentityGenerated(pdata->data()->key_type_,
181 std::move(pdata->data()->identity_));
182 break;
183 }
184 }
185 }
186
187 bool DtlsIdentityStoreImpl::HasFreeIdentityForTesting(
188 rtc::KeyType key_type) const {
189 RTC_DCHECK(signaling_thread_->IsCurrent());
190 return request_info_[key_type].free_identity_.get() != nullptr;
191 }
192
193 void DtlsIdentityStoreImpl::GenerateIdentity(
194 rtc::KeyType key_type,
195 const rtc::scoped_refptr<DtlsIdentityRequestObserver>& observer) {
196 RTC_DCHECK(signaling_thread_->IsCurrent());
197
198 // Enqueue observer to be informed when generation of |key_type| is completed.
199 if (observer.get()) {
200 request_info_[key_type].request_observers_.push(observer);
201
202 // Already have a free identity generated?
203 if (request_info_[key_type].free_identity_.get()) {
204 // Return identity async - post even though we are on |signaling_thread_|.
205 LOG(LS_VERBOSE) << "Using a free DTLS identity.";
206 ++request_info_[key_type].gen_in_progress_counts_;
207 IdentityResultMessageData* msg =
208 new IdentityResultMessageData(new IdentityResult(
209 key_type, std::move(request_info_[key_type].free_identity_)));
210 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg);
211 return;
212 }
213
214 // Free identity in the process of being generated?
215 if (request_info_[key_type].gen_in_progress_counts_ ==
216 request_info_[key_type].request_observers_.size()) {
217 // No need to do anything, the free identity will be returned to the
218 // observer in a MSG_GENERATE_IDENTITY_RESULT.
219 return;
220 }
221 }
222
223 // Enqueue/Post a worker task to do the generation.
224 ++request_info_[key_type].gen_in_progress_counts_;
225 WorkerTask* task = new WorkerTask(this, key_type); // Post 1 task/request.
226 // The WorkerTask is owned by the message data to make sure it will not be
227 // leaked even if the task does not get run.
228 WorkerTaskMessageData* msg = new WorkerTaskMessageData(task);
229 worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg);
230 }
231
232 void DtlsIdentityStoreImpl::OnIdentityGenerated(
233 rtc::KeyType key_type,
234 std::unique_ptr<rtc::SSLIdentity> identity) {
235 RTC_DCHECK(signaling_thread_->IsCurrent());
236
237 RTC_DCHECK(request_info_[key_type].gen_in_progress_counts_);
238 --request_info_[key_type].gen_in_progress_counts_;
239
240 rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver> observer;
241 if (!request_info_[key_type].request_observers_.empty()) {
242 observer = request_info_[key_type].request_observers_.front();
243 request_info_[key_type].request_observers_.pop();
244 }
245
246 if (observer.get() == nullptr) {
247 // No observer - store result in |free_identities_|.
248 RTC_DCHECK(!request_info_[key_type].free_identity_.get());
249 request_info_[key_type].free_identity_.swap(identity);
250 if (request_info_[key_type].free_identity_.get())
251 LOG(LS_VERBOSE) << "A free DTLS identity was saved.";
252 else
253 LOG(LS_WARNING) << "Failed to generate DTLS identity (preemptively).";
254 } else {
255 // Return the result to the observer.
256 if (identity.get()) {
257 LOG(LS_VERBOSE) << "A DTLS identity is returned to an observer.";
258 observer->OnSuccess(std::move(identity));
259 } else {
260 LOG(LS_WARNING) << "Failed to generate DTLS identity.";
261 observer->OnFailure(0);
262 }
263
264 // Preemptively generate another identity of the same type?
265 if (worker_thread_ != signaling_thread_ && // Only do in background thread.
266 key_type == rtc::KT_RSA && // Only necessary for RSA.
267 !request_info_[key_type].free_identity_.get() &&
268 request_info_[key_type].request_observers_.size() ==
269 request_info_[key_type].gen_in_progress_counts_) {
270 GenerateIdentity(key_type, nullptr);
271 }
272 }
273 }
274
275 RTCCertificateGeneratorStoreWrapper::RTCCertificateGeneratorStoreWrapper(
276 std::unique_ptr<DtlsIdentityStoreInterface> store)
277 : store_(std::move(store)) {
278 RTC_DCHECK(store_);
279 }
280
281 void RTCCertificateGeneratorStoreWrapper::GenerateCertificateAsync(
282 const rtc::KeyParams& key_params,
283 const rtc::Optional<uint64_t>& expires_ms,
284 const rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback>& callback) {
285 store_->RequestIdentity(
286 key_params,
287 expires_ms,
288 new rtc::RefCountedObject<RTCCertificateStoreCallbackObserver>(callback));
289 }
290
291 } // namespace webrtc 19 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/api/dtlsidentitystore.h ('k') | webrtc/api/dtlsidentitystore_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698