OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
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 | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/base/rtccertificategenerator.h" | |
12 | |
13 #include "webrtc/base/checks.h" | |
14 #include "webrtc/base/sslidentity.h" | |
15 | |
16 namespace rtc { | |
17 | |
18 namespace { | |
19 | |
20 // A certificates' subject and issuer name. | |
21 const char kIdentityName[] = "WebRTC"; | |
22 | |
23 uint64_t kYearInSeconds = 365 * 24 * 60 * 60; | |
24 | |
25 enum { | |
26 MSG_GENERATE, | |
27 MSG_GENERATE_DONE, | |
28 }; | |
29 | |
30 // Helper class for generating certificates asynchronously; a single task | |
31 // instance is responsible for a single asynchronous certificate generation | |
32 // request. We are using a separate helper class so that a generation request | |
33 // can outlive the |RTCCertificateGenerator| that spawned it. | |
34 class RTCCertificateGenerationTask : public RefCountInterface, | |
35 public MessageHandler { | |
36 public: | |
37 RTCCertificateGenerationTask( | |
38 Thread* signaling_thread, | |
39 Thread* worker_thread, | |
40 const KeyParams& key_params, | |
41 const Optional<uint64_t>& expires_ms, | |
42 const scoped_refptr<RTCCertificateGeneratorCallback>& callback) | |
43 : signaling_thread_(signaling_thread), | |
44 worker_thread_(worker_thread), | |
45 key_params_(key_params), | |
46 expires_ms_(expires_ms), | |
47 callback_(callback) { | |
48 RTC_DCHECK(signaling_thread_); | |
49 RTC_DCHECK(worker_thread_); | |
50 RTC_DCHECK(callback_); | |
51 } | |
52 ~RTCCertificateGenerationTask() override {} | |
53 | |
54 // Handles |MSG_GENERATE| and its follow-up |MSG_GENERATE_DONE|. | |
55 void OnMessage(Message* msg) override { | |
56 switch (msg->message_id) { | |
57 case MSG_GENERATE: | |
58 RTC_DCHECK(worker_thread_->IsCurrent()); | |
59 | |
60 // Perform the certificate generation work here on the worker thread. | |
61 certificate_ = RTCCertificateGenerator::GenerateCertificate( | |
62 key_params_, expires_ms_); | |
63 | |
64 // Handle callbacks on signaling thread. Pass on the |msg->pdata| | |
65 // (which references |this| with ref counting) to that thread. | |
66 signaling_thread_->Post(this, MSG_GENERATE_DONE, msg->pdata); | |
67 break; | |
68 case MSG_GENERATE_DONE: | |
69 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
70 | |
71 // Perform callback with result here on the signaling thread. | |
72 if (certificate_) { | |
73 callback_->OnSuccess(certificate_); | |
74 } else { | |
75 callback_->OnFailure(); | |
76 } | |
77 | |
78 // Destroy |msg->pdata| which references |this| with ref counting. This | |
79 // may result in |this| being deleted - do not touch member variables | |
80 // after this line. | |
81 delete msg->pdata; | |
82 return; | |
83 default: | |
84 RTC_NOTREACHED(); | |
85 } | |
86 } | |
87 | |
88 private: | |
89 Thread* const signaling_thread_; | |
90 Thread* const worker_thread_; | |
91 const KeyParams key_params_; | |
92 const Optional<uint64_t> expires_ms_; | |
93 const scoped_refptr<RTCCertificateGeneratorCallback> callback_; | |
94 scoped_refptr<RTCCertificate> certificate_; | |
95 }; | |
96 | |
97 } // namespace | |
98 | |
99 // static | |
100 scoped_refptr<RTCCertificate> | |
101 RTCCertificateGenerator::GenerateCertificate( | |
102 const KeyParams& key_params, | |
103 const Optional<uint64_t>& expires_ms) { | |
104 if (!key_params.IsValid()) | |
105 return nullptr; | |
106 SSLIdentity* identity; | |
107 if (!expires_ms) { | |
108 identity = SSLIdentity::Generate(kIdentityName, key_params); | |
109 } else { | |
110 uint64_t expires_s = *expires_ms / 1000; | |
111 // Limit the expiration time to something reasonable (a year). This was | |
112 // somewhat arbitrarily chosen. It also ensures that the value is not too | |
113 // large for the unspecified |time_t|. | |
114 if (expires_s > kYearInSeconds) | |
torbjorng (webrtc)
2016/04/15 12:17:48
Consider using std::max.
hbos
2016/04/15 13:24:14
Done. (std::min)
| |
115 expires_s = kYearInSeconds; | |
116 // TODO(torbjorng): Stop using |time_t|, its type is unspecified. It it safe | |
117 // to assume it can hold up to a year's worth of seconds (and more), but | |
118 // |SSLIdentity::Generate| should stop relying on |time_t|. | |
119 // See bugs.webrtc.org/5720. | |
120 time_t cert_lifetime_s = static_cast<time_t>(expires_s); | |
121 identity = SSLIdentity::GenerateWithExpiration( | |
122 kIdentityName, key_params, cert_lifetime_s); | |
123 } | |
124 if (!identity) | |
125 return nullptr; | |
126 scoped_ptr<SSLIdentity> identity_sptr(identity); | |
127 return RTCCertificate::Create(std::move(identity_sptr)); | |
128 } | |
129 | |
130 RTCCertificateGenerator::RTCCertificateGenerator( | |
131 Thread* signaling_thread, Thread* worker_thread) | |
132 : signaling_thread_(signaling_thread), | |
133 worker_thread_(worker_thread) { | |
134 RTC_DCHECK(signaling_thread_); | |
135 RTC_DCHECK(worker_thread_); | |
136 } | |
137 | |
138 void RTCCertificateGenerator::GenerateCertificateAsync( | |
139 const KeyParams& key_params, | |
140 const Optional<uint64_t>& expires_ms, | |
141 const scoped_refptr<RTCCertificateGeneratorCallback>& callback) { | |
142 RTC_DCHECK(signaling_thread_->IsCurrent()); | |
143 RTC_DCHECK(callback); | |
144 | |
145 // Create a new |RTCCertificateGenerationTask| for this generation request. It | |
146 // is reference counted and referenced by the message data, ensuring it lives | |
147 // until the task has completed (independent of |RTCCertificateGenerator|). | |
148 ScopedRefMessageData<RTCCertificateGenerationTask>* msg_data = | |
149 new ScopedRefMessageData<RTCCertificateGenerationTask>( | |
150 new RefCountedObject<RTCCertificateGenerationTask>( | |
151 signaling_thread_, worker_thread_, key_params, expires_ms, | |
152 callback)); | |
153 worker_thread_->Post(msg_data->data().get(), MSG_GENERATE, msg_data); | |
154 } | |
155 | |
156 } // namespace rtc | |
OLD | NEW |