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

Side by Side Diff: net/ocsp/nss_ocsp.cc

Issue 404044: Fix race condition in OCSPRequestSession. (Closed)
Patch Set: Created 11 years, 1 month 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ocsp/nss_ocsp.h" 5 #include "net/ocsp/nss_ocsp.h"
6 6
7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424
8 // until NSS 3.12.2 comes out and we update to it. 8 // until NSS 3.12.2 comes out and we update to it.
9 #define Lock FOO_NSS_Lock 9 #define Lock FOO_NSS_Lock
10 #include <certt.h> 10 #include <certt.h>
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 : public base::RefCountedThreadSafe<OCSPRequestSession>, 86 : public base::RefCountedThreadSafe<OCSPRequestSession>,
87 public URLRequest::Delegate, 87 public URLRequest::Delegate,
88 public MessageLoop::DestructionObserver { 88 public MessageLoop::DestructionObserver {
89 public: 89 public:
90 OCSPRequestSession(const GURL& url, 90 OCSPRequestSession(const GURL& url,
91 const char* http_request_method, 91 const char* http_request_method,
92 base::TimeDelta timeout) 92 base::TimeDelta timeout)
93 : url_(url), 93 : url_(url),
94 http_request_method_(http_request_method), 94 http_request_method_(http_request_method),
95 timeout_(timeout), 95 timeout_(timeout),
96 io_loop_(Singleton<OCSPInitSingleton>::get()->io_thread()),
97 request_(NULL), 96 request_(NULL),
98 buffer_(new net::IOBuffer(kRecvBufferSize)), 97 buffer_(new net::IOBuffer(kRecvBufferSize)),
99 response_code_(-1), 98 response_code_(-1),
100 cv_(&lock_), 99 cv_(&lock_),
100 io_loop_(Singleton<OCSPInitSingleton>::get()->io_thread()),
101 finished_(false) {} 101 finished_(false) {}
102 102
103 void SetPostData(const char* http_data, PRUint32 http_data_len, 103 void SetPostData(const char* http_data, PRUint32 http_data_len,
104 const char* http_content_type) { 104 const char* http_content_type) {
105 upload_content_.assign(http_data, http_data_len); 105 upload_content_.assign(http_data, http_data_len);
106 upload_content_type_.assign(http_content_type); 106 upload_content_type_.assign(http_content_type);
107 } 107 }
108 108
109 void AddHeader(const char* http_header_name, const char* http_header_value) { 109 void AddHeader(const char* http_header_name, const char* http_header_value) {
110 if (!extra_request_headers_.empty()) 110 if (!extra_request_headers_.empty())
111 extra_request_headers_ += "\r\n"; 111 extra_request_headers_ += "\r\n";
112 StringAppendF(&extra_request_headers_, 112 StringAppendF(&extra_request_headers_,
113 "%s: %s", http_header_name, http_header_value); 113 "%s: %s", http_header_name, http_header_value);
114 } 114 }
115 115
116 void Start() { 116 void Start() {
117 // IO thread may set |io_loop_| to NULL, so protect by |lock_|.
118 AutoLock autolock(lock_);
117 if (io_loop_) { 119 if (io_loop_) {
118 io_loop_->PostTask( 120 io_loop_->PostTask(
119 FROM_HERE, 121 FROM_HERE,
120 NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest)); 122 NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest));
121 } 123 }
122 } 124 }
123 125
124 bool Started() const { 126 bool Started() const {
125 return request_ != NULL; 127 return request_ != NULL;
126 } 128 }
127 129
128 void Cancel() { 130 void Cancel() {
129 if (io_loop_ && request_) { 131 // IO thread may set |io_loop_| to NULL, so protect by |lock_|.
132 AutoLock autolock(lock_);
133 if (io_loop_) {
130 io_loop_->PostTask( 134 io_loop_->PostTask(
131 FROM_HERE, 135 FROM_HERE,
132 NewRunnableMethod(this, &OCSPRequestSession::CancelURLRequest)); 136 NewRunnableMethod(this, &OCSPRequestSession::CancelURLRequest));
133 } 137 }
134 } 138 }
135 139
136 bool Finished() const { 140 bool Finished() const {
137 AutoLock autolock(lock_); 141 AutoLock autolock(lock_);
138 return finished_; 142 return finished_;
139 } 143 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 DCHECK_EQ(request, request_); 211 DCHECK_EQ(request, request_);
208 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); 212 DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
209 213
210 do { 214 do {
211 if (!request_->status().is_success() || bytes_read <= 0) 215 if (!request_->status().is_success() || bytes_read <= 0)
212 break; 216 break;
213 data_.append(buffer_->data(), bytes_read); 217 data_.append(buffer_->data(), bytes_read);
214 } while (request_->Read(buffer_, kRecvBufferSize, &bytes_read)); 218 } while (request_->Read(buffer_, kRecvBufferSize, &bytes_read));
215 219
216 if (!request_->status().is_io_pending()) { 220 if (!request_->status().is_io_pending()) {
221 MessageLoop* io_loop = io_loop_;
217 { 222 {
218 AutoLock autolock(lock_); 223 AutoLock autolock(lock_);
219 finished_ = true; 224 finished_ = true;
225 io_loop_ = NULL;
220 } 226 }
221 cv_.Signal(); 227 cv_.Signal();
222 delete request_; 228 delete request_;
223 request_ = NULL; 229 request_ = NULL;
224 io_loop_->RemoveDestructionObserver(this); 230 io_loop->RemoveDestructionObserver(this);
225 io_loop_ = NULL;
226 } 231 }
227 } 232 }
228 233
229 virtual void WillDestroyCurrentMessageLoop() { 234 virtual void WillDestroyCurrentMessageLoop() {
230 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); 235 DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
236 {
237 AutoLock autolock(lock_);
238 io_loop_ = NULL;
239 }
231 if (request_) { 240 if (request_) {
232 request_->Cancel(); 241 request_->Cancel();
233 delete request_; 242 delete request_;
234 request_ = NULL; 243 request_ = NULL;
235 } 244 }
236 io_loop_ = NULL;
237 } 245 }
238 246
239 private: 247 private:
240 friend class base::RefCountedThreadSafe<OCSPRequestSession>; 248 friend class base::RefCountedThreadSafe<OCSPRequestSession>;
241 249
242 virtual ~OCSPRequestSession() { 250 virtual ~OCSPRequestSession() {
243 DCHECK(!request_); 251 DCHECK(!request_);
244 if (io_loop_) 252 if (io_loop_)
245 io_loop_->RemoveDestructionObserver(this); 253 io_loop_->RemoveDestructionObserver(this);
246 io_loop_ = NULL;
247 } 254 }
248 255
249 void StartURLRequest() { 256 void StartURLRequest() {
250 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); 257 DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
251 DCHECK(!request_); 258 DCHECK(!request_);
252 259
253 io_loop_->AddDestructionObserver(this); 260 io_loop_->AddDestructionObserver(this);
254 261
255 request_ = new URLRequest(url_, this); 262 request_ = new URLRequest(url_, this);
256 request_->set_context( 263 request_->set_context(
(...skipping 14 matching lines...) Expand all
271 request_->AppendBytesToUpload(upload_content_.data(), 278 request_->AppendBytesToUpload(upload_content_.data(),
272 static_cast<int>(upload_content_.size())); 279 static_cast<int>(upload_content_.size()));
273 } 280 }
274 if (!extra_request_headers_.empty()) 281 if (!extra_request_headers_.empty())
275 request_->SetExtraRequestHeaders(extra_request_headers_); 282 request_->SetExtraRequestHeaders(extra_request_headers_);
276 283
277 request_->Start(); 284 request_->Start();
278 } 285 }
279 286
280 void CancelURLRequest() { 287 void CancelURLRequest() {
281 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); 288 if (io_loop_)
289 DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
282 if (request_) { 290 if (request_) {
283 request_->Cancel(); 291 request_->Cancel();
284 delete request_; 292 delete request_;
285 request_ = NULL; 293 request_ = NULL;
286 } 294 }
287 } 295 }
288 296
289 GURL url_; // The URL we eventually wound up at 297 GURL url_; // The URL we eventually wound up at
290 std::string http_request_method_; 298 std::string http_request_method_;
291 base::TimeDelta timeout_; // The timeout for OCSP 299 base::TimeDelta timeout_; // The timeout for OCSP
292 MessageLoop* io_loop_; // Message loop of the IO thread
293 URLRequest* request_; // The actual request this wraps 300 URLRequest* request_; // The actual request this wraps
294 scoped_refptr<net::IOBuffer> buffer_; // Read buffer 301 scoped_refptr<net::IOBuffer> buffer_; // Read buffer
295 std::string extra_request_headers_; // Extra headers for the request, if any 302 std::string extra_request_headers_; // Extra headers for the request, if any
296 std::string upload_content_; // HTTP POST payload 303 std::string upload_content_; // HTTP POST payload
297 std::string upload_content_type_; // MIME type of POST payload 304 std::string upload_content_type_; // MIME type of POST payload
298 305
299 int response_code_; // HTTP status code for the request 306 int response_code_; // HTTP status code for the request
300 std::string response_content_type_; 307 std::string response_content_type_;
301 scoped_refptr<net::HttpResponseHeaders> response_headers_; 308 scoped_refptr<net::HttpResponseHeaders> response_headers_;
302 std::string data_; // Results of the requst 309 std::string data_; // Results of the requst
303 310
304 // |lock_| protects |finished_| only. 311 // |lock_| protects |finished_| and |io_loop_|.
305 mutable Lock lock_; 312 mutable Lock lock_;
306 ConditionVariable cv_; 313 ConditionVariable cv_;
307 314
315 MessageLoop* io_loop_; // Message loop of the IO thread
308 bool finished_; 316 bool finished_;
309 317
310 DISALLOW_COPY_AND_ASSIGN(OCSPRequestSession); 318 DISALLOW_COPY_AND_ASSIGN(OCSPRequestSession);
311 }; 319 };
312 320
313 // Concrete class for SEC_HTTP_SERVER_SESSION. 321 // Concrete class for SEC_HTTP_SERVER_SESSION.
314 class OCSPServerSession { 322 class OCSPServerSession {
315 public: 323 public:
316 OCSPServerSession(const char* host, PRUint16 port) 324 OCSPServerSession(const char* host, PRUint16 port)
317 : host_(host), port_(port) {} 325 : host_(host), port_(port) {}
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 // This function would be called before NSS initialization. 561 // This function would be called before NSS initialization.
554 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { 562 void SetURLRequestContextForOCSP(URLRequestContext* request_context) {
555 OCSPInitSingleton::set_url_request_context(request_context); 563 OCSPInitSingleton::set_url_request_context(request_context);
556 } 564 }
557 565
558 URLRequestContext* GetURLRequestContextForOCSP() { 566 URLRequestContext* GetURLRequestContextForOCSP() {
559 return OCSPInitSingleton::url_request_context(); 567 return OCSPInitSingleton::url_request_context();
560 } 568 }
561 569
562 } // namespace net 570 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698