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

Side by Side Diff: net/base/host_resolver.cc

Issue 125107: * Move the global "DnsResolutionObserver" code depended on by DNS prefetcher,... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Address jar's comments Created 11 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 | Annotate | Revision Log
« no previous file with comments | « net/base/host_resolver.h ('k') | net/base/host_resolver_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 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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/base/host_resolver.h" 5 #include "net/base/host_resolver.h"
6 6
7 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <ws2tcpip.h> 8 #include <ws2tcpip.h>
9 #include <wspiapi.h> // Needed for Win2k compat. 9 #include <wspiapi.h> // Needed for Win2k compat.
10 #elif defined(OS_POSIX) 10 #elif defined(OS_POSIX)
11 #include <netdb.h> 11 #include <netdb.h>
12 #include <sys/socket.h> 12 #include <sys/socket.h>
13 #endif 13 #endif
14 #if defined(OS_LINUX) 14 #if defined(OS_LINUX)
15 #include <resolv.h> 15 #include <resolv.h>
16 #endif 16 #endif
17 17
18 #include "base/compiler_specific.h" 18 #include "base/compiler_specific.h"
19 #include "base/message_loop.h" 19 #include "base/message_loop.h"
20 #include "base/stl_util-inl.h" 20 #include "base/stl_util-inl.h"
21 #include "base/string_util.h" 21 #include "base/string_util.h"
22 #include "base/time.h" 22 #include "base/time.h"
23 #include "base/worker_pool.h" 23 #include "base/worker_pool.h"
24 #include "net/base/address_list.h" 24 #include "net/base/address_list.h"
25 #include "net/base/dns_resolution_observer.h"
25 #include "net/base/net_errors.h" 26 #include "net/base/net_errors.h"
26 27
27 #if defined(OS_LINUX) 28 #if defined(OS_LINUX)
28 #include "base/singleton.h" 29 #include "base/singleton.h"
29 #include "base/thread_local_storage.h" 30 #include "base/thread_local_storage.h"
30 #endif 31 #endif
31 32
32 #if defined(OS_WIN) 33 #if defined(OS_WIN)
33 #include "net/base/winsock_init.h" 34 #include "net/base/winsock_init.h"
34 #endif 35 #endif
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 return HostResolverProc(mapped_host, out); 172 return HostResolverProc(mapped_host, out);
172 } else { 173 } else {
173 return HostResolverProc(host, out); 174 return HostResolverProc(host, out);
174 } 175 }
175 } 176 }
176 177
177 //----------------------------------------------------------------------------- 178 //-----------------------------------------------------------------------------
178 179
179 class HostResolver::Request { 180 class HostResolver::Request {
180 public: 181 public:
181 Request(CompletionCallback* callback, AddressList* addresses, int port) 182 Request(int id, const RequestInfo& info, CompletionCallback* callback,
182 : job_(NULL), callback_(callback), addresses_(addresses), port_(port) {} 183 AddressList* addresses)
184 : id_(id), info_(info), job_(NULL), callback_(callback),
185 addresses_(addresses) {}
183 186
184 // Mark the request as cancelled. 187 // Mark the request as cancelled.
185 void Cancel() { 188 void Cancel() {
186 job_ = NULL; 189 job_ = NULL;
187 callback_ = NULL; 190 callback_ = NULL;
188 addresses_ = NULL; 191 addresses_ = NULL;
189 } 192 }
190 193
191 bool was_cancelled() const { 194 bool was_cancelled() const {
192 return callback_ == NULL; 195 return callback_ == NULL;
193 } 196 }
194 197
195 void set_job(Job* job) { 198 void set_job(Job* job) {
196 DCHECK(job != NULL); 199 DCHECK(job != NULL);
197 // Identify which job the request is waiting on. 200 // Identify which job the request is waiting on.
198 job_ = job; 201 job_ = job;
199 } 202 }
200 203
201 void OnComplete(int error, const AddressList& addrlist) { 204 void OnComplete(int error, const AddressList& addrlist) {
202 if (error == OK) 205 if (error == OK)
203 addresses_->SetFrom(addrlist, port_); 206 addresses_->SetFrom(addrlist, port());
204 callback_->Run(error); 207 callback_->Run(error);
205 } 208 }
206 209
207 int port() const { 210 int port() const {
208 return port_; 211 return info_.port();
209 } 212 }
210 213
211 Job* job() const { 214 Job* job() const {
212 return job_; 215 return job_;
213 } 216 }
214 217
218 int id() const {
219 return id_;
220 }
221
222 const RequestInfo& info() const {
223 return info_;
224 }
225
215 private: 226 private:
227 // Unique ID for this request. Used by observers to identify requests.
228 int id_;
229
230 // The request info that started the request.
231 RequestInfo info_;
232
216 // The resolve job (running in worker pool) that this request is dependent on. 233 // The resolve job (running in worker pool) that this request is dependent on.
217 Job* job_; 234 Job* job_;
218 235
219 // The user's callback to invoke when the request completes. 236 // The user's callback to invoke when the request completes.
220 CompletionCallback* callback_; 237 CompletionCallback* callback_;
221 238
222 // The address list to save result into. 239 // The address list to save result into.
223 AddressList* addresses_; 240 AddressList* addresses_;
224 241
225 // The desired port number for the socket addresses.
226 int port_;
227
228 DISALLOW_COPY_AND_ASSIGN(Request); 242 DISALLOW_COPY_AND_ASSIGN(Request);
229 }; 243 };
230 244
231 //----------------------------------------------------------------------------- 245 //-----------------------------------------------------------------------------
232 246
233 // This class represents a request to the worker pool for a "getaddrinfo()" 247 // This class represents a request to the worker pool for a "getaddrinfo()"
234 // call. 248 // call.
235 class HostResolver::Job : public base::RefCountedThreadSafe<HostResolver::Job> { 249 class HostResolver::Job : public base::RefCountedThreadSafe<HostResolver::Job> {
236 public: 250 public:
237 Job(HostResolver* resolver, const std::string& host) 251 Job(HostResolver* resolver, const std::string& host)
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 // Assigned on the worker thread, read on the origin thread. 376 // Assigned on the worker thread, read on the origin thread.
363 int error_; 377 int error_;
364 struct addrinfo* results_; 378 struct addrinfo* results_;
365 379
366 DISALLOW_COPY_AND_ASSIGN(Job); 380 DISALLOW_COPY_AND_ASSIGN(Job);
367 }; 381 };
368 382
369 //----------------------------------------------------------------------------- 383 //-----------------------------------------------------------------------------
370 384
371 HostResolver::HostResolver(int max_cache_entries, int cache_duration_ms) 385 HostResolver::HostResolver(int max_cache_entries, int cache_duration_ms)
372 : cache_(max_cache_entries, cache_duration_ms) { 386 : cache_(max_cache_entries, cache_duration_ms), next_request_id_(0) {
373 #if defined(OS_WIN) 387 #if defined(OS_WIN)
374 EnsureWinsockInit(); 388 EnsureWinsockInit();
375 #endif 389 #endif
376 } 390 }
377 391
378 HostResolver::~HostResolver() { 392 HostResolver::~HostResolver() {
379 // Cancel the outstanding jobs. Those jobs may contain several attached 393 // Cancel the outstanding jobs. Those jobs may contain several attached
380 // requests, which will now never be completed. 394 // requests, which will now never be completed.
381 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 395 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
382 it->second->Cancel(); 396 it->second->Cancel();
383 397
384 // In case we are being deleted during the processing of a callback. 398 // In case we are being deleted during the processing of a callback.
385 if (cur_completing_job_) 399 if (cur_completing_job_)
386 cur_completing_job_->Cancel(); 400 cur_completing_job_->Cancel();
387 } 401 }
388 402
389 // TODO(eroman): Don't create cache entries for hostnames which are simply IP 403 // TODO(eroman): Don't create cache entries for hostnames which are simply IP
390 // address literals. 404 // address literals.
391 int HostResolver::Resolve(const std::string& hostname, int port, 405 int HostResolver::Resolve(const RequestInfo& info,
392 AddressList* addresses, 406 AddressList* addresses,
393 CompletionCallback* callback, 407 CompletionCallback* callback,
394 Request** out_req) { 408 Request** out_req) {
409 // Choose a unique ID number for observers to see.
410 int request_id = next_request_id_++;
411
412 // Notify registered observers.
413 NotifyObserversStartRequest(request_id, info);
414
395 // If we have an unexpired cache entry, use it. 415 // If we have an unexpired cache entry, use it.
396 const HostCache::Entry* cache_entry = cache_.Lookup( 416 if (info.allow_cached_response()) {
397 hostname, base::TimeTicks::Now()); 417 const HostCache::Entry* cache_entry = cache_.Lookup(
398 if (cache_entry) { 418 info.hostname(), base::TimeTicks::Now());
399 addresses->SetFrom(cache_entry->addrlist, port); 419 if (cache_entry) {
400 return OK; 420 addresses->SetFrom(cache_entry->addrlist, info.port());
421 return OK;
422 }
401 } 423 }
402 424
403 // If no callback was specified, do a synchronous resolution. 425 // If no callback was specified, do a synchronous resolution.
404 if (!callback) { 426 if (!callback) {
405 struct addrinfo* results; 427 struct addrinfo* results;
406 int error = ResolveAddrInfo(host_mapper, hostname, &results); 428 int error = ResolveAddrInfo(host_mapper, info.hostname(), &results);
407 429
408 // Adopt the address list. 430 // Adopt the address list.
409 AddressList addrlist; 431 AddressList addrlist;
410 if (error == OK) { 432 if (error == OK) {
411 addrlist.Adopt(results); 433 addrlist.Adopt(results);
412 addrlist.SetPort(port); 434 addrlist.SetPort(info.port());
413 *addresses = addrlist; 435 *addresses = addrlist;
414 } 436 }
415 437
416 // Write to cache. 438 // Write to cache.
417 cache_.Set(hostname, error, addrlist, base::TimeTicks::Now()); 439 cache_.Set(info.hostname(), error, addrlist, base::TimeTicks::Now());
440
441 // Notify registered observers.
442 NotifyObserversFinishRequest(request_id, info, error);
418 443
419 return error; 444 return error;
420 } 445 }
421 446
422 // Create a handle for this request, and pass it back to the user if they 447 // Create a handle for this request, and pass it back to the user if they
423 // asked for it (out_req != NULL). 448 // asked for it (out_req != NULL).
424 Request* req = new Request(callback, addresses, port); 449 Request* req = new Request(request_id, info, callback, addresses);
425 if (out_req) 450 if (out_req)
426 *out_req = req; 451 *out_req = req;
427 452
428 // Next we need to attach our request to a "job". This job is responsible for 453 // Next we need to attach our request to a "job". This job is responsible for
429 // calling "getaddrinfo(hostname)" on a worker thread. 454 // calling "getaddrinfo(hostname)" on a worker thread.
430 scoped_refptr<Job> job; 455 scoped_refptr<Job> job;
431 456
432 // If there is already an outstanding job to resolve |hostname|, use it. 457 // If there is already an outstanding job to resolve |info.hostname()|, use
433 // This prevents starting concurrent resolves for the same hostname. 458 // it. This prevents starting concurrent resolves for the same hostname.
434 job = FindOutstandingJob(hostname); 459 job = FindOutstandingJob(info.hostname());
435 if (job) { 460 if (job) {
436 job->AddRequest(req); 461 job->AddRequest(req);
437 } else { 462 } else {
438 // Create a new job for this request. 463 // Create a new job for this request.
439 job = new Job(this, hostname); 464 job = new Job(this, info.hostname());
440 job->AddRequest(req); 465 job->AddRequest(req);
441 AddOutstandingJob(job); 466 AddOutstandingJob(job);
442 // TODO(eroman): Bound the total number of concurrent jobs. 467 // TODO(eroman): Bound the total number of concurrent jobs.
443 // http://crbug.com/9598 468 // http://crbug.com/9598
444 job->Start(); 469 job->Start();
445 } 470 }
446 471
447 // Completion happens during OnJobComplete(Job*). 472 // Completion happens during OnJobComplete(Job*).
448 return ERR_IO_PENDING; 473 return ERR_IO_PENDING;
449 } 474 }
450 475
451 // See OnJobComplete(Job*) for why it is important not to clean out 476 // See OnJobComplete(Job*) for why it is important not to clean out
452 // cancelled requests from Job::requests_. 477 // cancelled requests from Job::requests_.
453 void HostResolver::CancelRequest(Request* req) { 478 void HostResolver::CancelRequest(Request* req) {
454 DCHECK(req); 479 DCHECK(req);
455 DCHECK(req->job()); 480 DCHECK(req->job());
456 // NULL out the fields of req, to mark it as cancelled. 481 // NULL out the fields of req, to mark it as cancelled.
457 req->Cancel(); 482 req->Cancel();
458 } 483 }
459 484
485 void HostResolver::AddObserver(DnsResolutionObserver* observer) {
486 observers_.push_back(observer);
487 }
488
489 void HostResolver::RemoveObserver(DnsResolutionObserver* observer) {
490 ObserversList::iterator it =
491 std::find(observers_.begin(), observers_.end(), observer);
492
493 // Observer must exist.
494 DCHECK(it != observers_.end());
495
496 observers_.erase(it);
497 }
498
460 void HostResolver::AddOutstandingJob(Job* job) { 499 void HostResolver::AddOutstandingJob(Job* job) {
461 scoped_refptr<Job>& found_job = jobs_[job->host()]; 500 scoped_refptr<Job>& found_job = jobs_[job->host()];
462 DCHECK(!found_job); 501 DCHECK(!found_job);
463 found_job = job; 502 found_job = job;
464 } 503 }
465 504
466 HostResolver::Job* HostResolver::FindOutstandingJob( 505 HostResolver::Job* HostResolver::FindOutstandingJob(
467 const std::string& hostname) { 506 const std::string& hostname) {
468 JobMap::iterator it = jobs_.find(hostname); 507 JobMap::iterator it = jobs_.find(hostname);
469 if (it != jobs_.end()) 508 if (it != jobs_.end())
(...skipping 20 matching lines...) Expand all
490 // HostResolver is deleted by a callback invocation. 529 // HostResolver is deleted by a callback invocation.
491 DCHECK(!cur_completing_job_); 530 DCHECK(!cur_completing_job_);
492 cur_completing_job_ = job; 531 cur_completing_job_ = job;
493 532
494 // Complete all of the requests that were attached to the job. 533 // Complete all of the requests that were attached to the job.
495 for (RequestsList::const_iterator it = job->requests().begin(); 534 for (RequestsList::const_iterator it = job->requests().begin();
496 it != job->requests().end(); ++it) { 535 it != job->requests().end(); ++it) {
497 Request* req = *it; 536 Request* req = *it;
498 if (!req->was_cancelled()) { 537 if (!req->was_cancelled()) {
499 DCHECK_EQ(job, req->job()); 538 DCHECK_EQ(job, req->job());
539
540 // Notify registered observers.
541 NotifyObserversFinishRequest(req->id(), req->info(), error);
542
500 req->OnComplete(error, addrlist); 543 req->OnComplete(error, addrlist);
501 544
502 // Check if the job was cancelled as a result of running the callback. 545 // Check if the job was cancelled as a result of running the callback.
503 // (Meaning that |this| was deleted). 546 // (Meaning that |this| was deleted).
504 if (job->was_cancelled()) 547 if (job->was_cancelled())
505 return; 548 return;
506 } 549 }
507 } 550 }
508 551
509 cur_completing_job_ = NULL; 552 cur_completing_job_ = NULL;
510 } 553 }
511 554
555 void HostResolver::NotifyObserversStartRequest(int request_id,
556 const RequestInfo& info) {
557 for (ObserversList::iterator it = observers_.begin();
558 it != observers_.end(); ++it) {
559 (*it)->OnStartResolution(request_id, info);
560 }
561 }
562
563 void HostResolver::NotifyObserversFinishRequest(int request_id,
564 const RequestInfo& info,
565 int error) {
566 bool was_resolved = error == OK;
567 for (ObserversList::iterator it = observers_.begin();
568 it != observers_.end(); ++it) {
569 (*it)->OnFinishResolutionWithStatus(request_id, was_resolved, info);
570 }
571 }
572
512 //----------------------------------------------------------------------------- 573 //-----------------------------------------------------------------------------
513 574
514 SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver) 575 SingleRequestHostResolver::SingleRequestHostResolver(HostResolver* resolver)
515 : resolver_(resolver), 576 : resolver_(resolver),
516 cur_request_(NULL), 577 cur_request_(NULL),
517 cur_request_callback_(NULL), 578 cur_request_callback_(NULL),
518 ALLOW_THIS_IN_INITIALIZER_LIST( 579 ALLOW_THIS_IN_INITIALIZER_LIST(
519 callback_(this, &SingleRequestHostResolver::OnResolveCompletion)) { 580 callback_(this, &SingleRequestHostResolver::OnResolveCompletion)) {
520 DCHECK(resolver_ != NULL); 581 DCHECK(resolver_ != NULL);
521 } 582 }
522 583
523 SingleRequestHostResolver::~SingleRequestHostResolver() { 584 SingleRequestHostResolver::~SingleRequestHostResolver() {
524 if (cur_request_) { 585 if (cur_request_) {
525 resolver_->CancelRequest(cur_request_); 586 resolver_->CancelRequest(cur_request_);
526 } 587 }
527 } 588 }
528 589
529 int SingleRequestHostResolver::Resolve( 590 int SingleRequestHostResolver::Resolve(const HostResolver::RequestInfo& info,
530 const std::string& hostname, int port, 591 AddressList* addresses,
531 AddressList* addresses, 592 CompletionCallback* callback) {
532 CompletionCallback* callback) {
533 DCHECK(!cur_request_ && !cur_request_callback_) << "resolver already in use"; 593 DCHECK(!cur_request_ && !cur_request_callback_) << "resolver already in use";
534 594
535 HostResolver::Request* request = NULL; 595 HostResolver::Request* request = NULL;
536 596
537 // We need to be notified of completion before |callback| is called, so that 597 // We need to be notified of completion before |callback| is called, so that
538 // we can clear out |cur_request_*|. 598 // we can clear out |cur_request_*|.
539 CompletionCallback* transient_callback = callback ? &callback_ : NULL; 599 CompletionCallback* transient_callback = callback ? &callback_ : NULL;
540 600
541 int rv = resolver_->Resolve( 601 int rv = resolver_->Resolve(info, addresses, transient_callback, &request);
542 hostname, port, addresses, transient_callback, &request);
543 602
544 if (rv == ERR_IO_PENDING) { 603 if (rv == ERR_IO_PENDING) {
545 // Cleared in OnResolveCompletion(). 604 // Cleared in OnResolveCompletion().
546 cur_request_ = request; 605 cur_request_ = request;
547 cur_request_callback_ = callback; 606 cur_request_callback_ = callback;
548 } 607 }
549 608
550 return rv; 609 return rv;
551 } 610 }
552 611
553 void SingleRequestHostResolver::OnResolveCompletion(int result) { 612 void SingleRequestHostResolver::OnResolveCompletion(int result) {
554 DCHECK(cur_request_ && cur_request_callback_); 613 DCHECK(cur_request_ && cur_request_callback_);
555 614
556 CompletionCallback* callback = cur_request_callback_; 615 CompletionCallback* callback = cur_request_callback_;
557 616
558 // Clear the outstanding request information. 617 // Clear the outstanding request information.
559 cur_request_ = NULL; 618 cur_request_ = NULL;
560 cur_request_callback_ = NULL; 619 cur_request_callback_ = NULL;
561 620
562 // Call the user's original callback. 621 // Call the user's original callback.
563 callback->Run(result); 622 callback->Run(result);
564 } 623 }
565 624
566 } // namespace net 625 } // namespace net
OLDNEW
« no previous file with comments | « net/base/host_resolver.h ('k') | net/base/host_resolver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698