| 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 |