OLD | NEW |
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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 | 50 |
51 // This class runs on the worker thread to generate the identity. It's necessary | 51 // 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 | 52 // to separate this class from DtlsIdentityStore so that it can live on the |
53 // worker thread after DtlsIdentityStore is destroyed. | 53 // worker thread after DtlsIdentityStore is destroyed. |
54 class DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>, | 54 class DtlsIdentityStore::WorkerTask : public sigslot::has_slots<>, |
55 public rtc::MessageHandler { | 55 public rtc::MessageHandler { |
56 public: | 56 public: |
57 explicit WorkerTask(DtlsIdentityStore* store) | 57 explicit WorkerTask(DtlsIdentityStore* store) |
58 : signaling_thread_(rtc::Thread::Current()), store_(store) { | 58 : signaling_thread_(rtc::Thread::Current()), store_(store) { |
59 store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed); | 59 store_->SignalDestroyed.connect(this, &WorkerTask::OnStoreDestroyed); |
60 }; | 60 } |
61 | 61 |
62 virtual ~WorkerTask() { DCHECK(rtc::Thread::Current() == signaling_thread_); } | 62 virtual ~WorkerTask() { DCHECK(rtc::Thread::Current() == signaling_thread_); } |
63 | 63 |
64 void GenerateIdentity() { | 64 private: |
| 65 void GenerateIdentity_w() { |
65 rtc::scoped_ptr<rtc::SSLIdentity> identity( | 66 rtc::scoped_ptr<rtc::SSLIdentity> identity( |
66 rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName)); | 67 rtc::SSLIdentity::Generate(DtlsIdentityStore::kIdentityName)); |
67 | 68 |
68 { | 69 { |
69 rtc::CritScope cs(&cs_); | 70 rtc::CritScope cs(&cs_); |
70 if (store_) { | 71 if (store_) { |
71 store_->PostGenerateIdentityResult_w(identity.Pass()); | 72 store_->PostGenerateIdentityResult_w(identity.Pass()); |
72 } | 73 } |
73 } | 74 } |
74 } | 75 } |
75 | 76 |
76 void OnMessage(rtc::Message* msg) override { | 77 void OnMessage(rtc::Message* msg) override { |
77 switch (msg->message_id) { | 78 switch (msg->message_id) { |
78 case MSG_GENERATE_IDENTITY: | 79 case MSG_GENERATE_IDENTITY: |
79 GenerateIdentity(); | 80 // This message always runs on the worker thread. |
| 81 GenerateIdentity_w(); |
80 | 82 |
81 // Must delete |this|, owned by msg->pdata, on the signaling thread to | 83 // Must delete |this|, owned by msg->pdata, on the signaling thread to |
82 // avoid races on disconnecting the signal. | 84 // avoid races on disconnecting the signal. |
83 signaling_thread_->Post(this, MSG_DESTROY, msg->pdata); | 85 signaling_thread_->Post(this, MSG_DESTROY, msg->pdata); |
84 break; | 86 break; |
85 case MSG_DESTROY: | 87 case MSG_DESTROY: |
| 88 DCHECK(rtc::Thread::Current() == signaling_thread_); |
86 delete msg->pdata; | 89 delete msg->pdata; |
| 90 // |this| has now been deleted. Don't touch member variables. |
87 break; | 91 break; |
88 default: | 92 default: |
89 CHECK(false) << "Unexpected message type"; | 93 CHECK(false) << "Unexpected message type"; |
90 } | 94 } |
91 } | 95 } |
92 | 96 |
93 private: | |
94 void OnStoreDestroyed() { | 97 void OnStoreDestroyed() { |
95 rtc::CritScope cs(&cs_); | 98 rtc::CritScope cs(&cs_); |
96 store_ = NULL; | 99 store_ = NULL; |
97 } | 100 } |
98 | 101 |
99 rtc::Thread* signaling_thread_; | 102 rtc::Thread* const signaling_thread_; |
100 rtc::CriticalSection cs_; | 103 rtc::CriticalSection cs_; |
101 DtlsIdentityStore* store_; | 104 DtlsIdentityStore* store_; |
102 }; | 105 }; |
103 | 106 |
104 // Arbitrary constant used as common name for the identity. | 107 // Arbitrary constant used as common name for the identity. |
105 // Chosen to make the certificates more readable. | 108 // Chosen to make the certificates more readable. |
106 const char DtlsIdentityStore::kIdentityName[] = "WebRTC"; | 109 const char DtlsIdentityStore::kIdentityName[] = "WebRTC"; |
107 | 110 |
108 DtlsIdentityStore::DtlsIdentityStore(rtc::Thread* signaling_thread, | 111 DtlsIdentityStore::DtlsIdentityStore(rtc::Thread* signaling_thread, |
109 rtc::Thread* worker_thread) | 112 rtc::Thread* worker_thread) |
110 : signaling_thread_(signaling_thread), | 113 : signaling_thread_(signaling_thread), |
111 worker_thread_(worker_thread), | 114 worker_thread_(worker_thread), |
112 pending_jobs_(0) {} | 115 pending_jobs_(0) {} |
113 | 116 |
114 DtlsIdentityStore::~DtlsIdentityStore() { | 117 DtlsIdentityStore::~DtlsIdentityStore() { |
115 SignalDestroyed(); | 118 SignalDestroyed(); |
116 } | 119 } |
117 | 120 |
118 void DtlsIdentityStore::Initialize() { | 121 void DtlsIdentityStore::Initialize() { |
| 122 DCHECK(rtc::Thread::Current() == signaling_thread_); |
119 // Do not aggressively generate the free identity if the worker thread and the | 123 // Do not aggressively generate the free identity if the worker thread and the |
120 // signaling thread are the same. | 124 // signaling thread are the same. |
121 if (worker_thread_ != signaling_thread_) { | 125 if (worker_thread_ != signaling_thread_) { |
122 GenerateIdentity(); | 126 GenerateIdentity(); |
123 } | 127 } |
124 } | 128 } |
125 | 129 |
126 void DtlsIdentityStore::RequestIdentity(DTLSIdentityRequestObserver* observer) { | 130 void DtlsIdentityStore::RequestIdentity(DTLSIdentityRequestObserver* observer) { |
127 DCHECK(rtc::Thread::Current() == signaling_thread_); | 131 DCHECK(rtc::Thread::Current() == signaling_thread_); |
128 DCHECK(observer); | 132 DCHECK(observer); |
129 | 133 |
130 // Must return the free identity async. | 134 // Must return the free identity async. |
131 if (free_identity_.get()) { | 135 if (free_identity_.get()) { |
132 IdentityResultMessageData* msg = | 136 IdentityResultMessageData* msg = |
133 new IdentityResultMessageData(free_identity_.release()); | 137 new IdentityResultMessageData(free_identity_.release()); |
134 signaling_thread_->Post(this, MSG_RETURN_FREE_IDENTITY, msg); | 138 signaling_thread_->Post(this, MSG_RETURN_FREE_IDENTITY, msg); |
135 } | 139 } |
136 | 140 |
137 pending_observers_.push(observer); | 141 pending_observers_.push(observer); |
138 GenerateIdentity(); | 142 GenerateIdentity(); |
139 } | 143 } |
140 | 144 |
141 void DtlsIdentityStore::OnMessage(rtc::Message* msg) { | 145 void DtlsIdentityStore::OnMessage(rtc::Message* msg) { |
| 146 DCHECK(rtc::Thread::Current() == signaling_thread_); |
142 switch (msg->message_id) { | 147 switch (msg->message_id) { |
143 case MSG_GENERATE_IDENTITY_RESULT: { | 148 case MSG_GENERATE_IDENTITY_RESULT: { |
144 rtc::scoped_ptr<IdentityResultMessageData> pdata( | 149 rtc::scoped_ptr<IdentityResultMessageData> pdata( |
145 static_cast<IdentityResultMessageData*>(msg->pdata)); | 150 static_cast<IdentityResultMessageData*>(msg->pdata)); |
146 OnIdentityGenerated(pdata->data().Pass()); | 151 OnIdentityGenerated(pdata->data().Pass()); |
147 break; | 152 break; |
148 } | 153 } |
149 case MSG_RETURN_FREE_IDENTITY: { | 154 case MSG_RETURN_FREE_IDENTITY: { |
150 rtc::scoped_ptr<IdentityResultMessageData> pdata( | 155 rtc::scoped_ptr<IdentityResultMessageData> pdata( |
151 static_cast<IdentityResultMessageData*>(msg->pdata)); | 156 static_cast<IdentityResultMessageData*>(msg->pdata)); |
152 ReturnIdentity(pdata->data().Pass()); | 157 ReturnIdentity(pdata->data().Pass()); |
153 break; | 158 break; |
154 } | 159 } |
155 } | 160 } |
156 } | 161 } |
157 | 162 |
158 bool DtlsIdentityStore::HasFreeIdentityForTesting() const { | 163 bool DtlsIdentityStore::HasFreeIdentityForTesting() const { |
159 return free_identity_.get(); | 164 DCHECK(rtc::Thread::Current() == signaling_thread_); |
| 165 return free_identity_.get() != nullptr; |
160 } | 166 } |
161 | 167 |
162 void DtlsIdentityStore::GenerateIdentity() { | 168 void DtlsIdentityStore::GenerateIdentity() { |
| 169 DCHECK(rtc::Thread::Current() == signaling_thread_); |
163 pending_jobs_++; | 170 pending_jobs_++; |
164 LOG(LS_VERBOSE) << "New DTLS identity generation is posted, " | 171 LOG(LS_VERBOSE) << "New DTLS identity generation is posted, " |
165 << "pending_identities=" << pending_jobs_; | 172 << "pending_identities=" << pending_jobs_; |
166 | 173 |
167 WorkerTask* task = new WorkerTask(this); | 174 WorkerTask* task = new WorkerTask(this); |
168 // The WorkerTask is owned by the message data to make sure it will not be | 175 // The WorkerTask is owned by the message data to make sure it will not be |
169 // leaked even if the task does not get run. | 176 // leaked even if the task does not get run. |
170 IdentityTaskMessageData* msg = new IdentityTaskMessageData(task); | 177 IdentityTaskMessageData* msg = new IdentityTaskMessageData(task); |
171 worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); | 178 worker_thread_->Post(task, MSG_GENERATE_IDENTITY, msg); |
172 } | 179 } |
(...skipping 11 matching lines...) Expand all Loading... |
184 free_identity_.reset(identity.release()); | 191 free_identity_.reset(identity.release()); |
185 LOG(LS_VERBOSE) << "A free DTLS identity is saved"; | 192 LOG(LS_VERBOSE) << "A free DTLS identity is saved"; |
186 } | 193 } |
187 return; | 194 return; |
188 } | 195 } |
189 ReturnIdentity(identity.Pass()); | 196 ReturnIdentity(identity.Pass()); |
190 } | 197 } |
191 | 198 |
192 void DtlsIdentityStore::ReturnIdentity( | 199 void DtlsIdentityStore::ReturnIdentity( |
193 rtc::scoped_ptr<rtc::SSLIdentity> identity) { | 200 rtc::scoped_ptr<rtc::SSLIdentity> identity) { |
| 201 DCHECK(rtc::Thread::Current() == signaling_thread_); |
194 DCHECK(!free_identity_.get()); | 202 DCHECK(!free_identity_.get()); |
195 DCHECK(!pending_observers_.empty()); | 203 DCHECK(!pending_observers_.empty()); |
196 | 204 |
197 rtc::scoped_refptr<DTLSIdentityRequestObserver> observer = | 205 rtc::scoped_refptr<DTLSIdentityRequestObserver> observer = |
198 pending_observers_.front(); | 206 pending_observers_.front(); |
199 pending_observers_.pop(); | 207 pending_observers_.pop(); |
200 | 208 |
201 if (identity.get()) { | 209 if (identity.get()) { |
202 observer->OnSuccessWithIdentityObj(identity.Pass()); | 210 observer->OnSuccessWithIdentityObj(identity.Pass()); |
203 } else { | 211 } else { |
204 // Pass an arbitrary error code. | 212 // Pass an arbitrary error code. |
205 observer->OnFailure(0); | 213 observer->OnFailure(0); |
206 LOG(LS_WARNING) << "Failed to generate SSL identity"; | 214 LOG(LS_WARNING) << "Failed to generate SSL identity"; |
207 } | 215 } |
208 | 216 |
209 // Do not aggressively generate the free identity if the worker thread and the | 217 // Do not aggressively generate the free identity if the worker thread and the |
210 // signaling thread are the same. | 218 // signaling thread are the same. |
211 if (worker_thread_ != signaling_thread_ && | 219 if (worker_thread_ != signaling_thread_ && |
212 pending_observers_.empty() && | 220 pending_observers_.empty() && |
213 pending_jobs_ == 0) { | 221 pending_jobs_ == 0) { |
214 // Generate a free identity in the background. | 222 // Generate a free identity in the background. |
215 GenerateIdentity(); | 223 GenerateIdentity(); |
216 } | 224 } |
217 } | 225 } |
218 | 226 |
219 void DtlsIdentityStore::PostGenerateIdentityResult_w( | 227 void DtlsIdentityStore::PostGenerateIdentityResult_w( |
220 rtc::scoped_ptr<rtc::SSLIdentity> identity) { | 228 rtc::scoped_ptr<rtc::SSLIdentity> identity) { |
221 DCHECK(rtc::Thread::Current() == worker_thread_); | 229 DCHECK(rtc::Thread::Current() == worker_thread_); |
222 | 230 |
223 IdentityResultMessageData* msg = | 231 IdentityResultMessageData* msg = |
224 new IdentityResultMessageData(identity.release()); | 232 new IdentityResultMessageData(identity.release()); |
225 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); | 233 signaling_thread_->Post(this, MSG_GENERATE_IDENTITY_RESULT, msg); |
226 } | 234 } |
227 } // namespace webrtc | 235 } // namespace webrtc |
OLD | NEW |