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

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

Issue 302010: Add a mechanism to disable IPv6.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Address darin's comments Created 11 years, 2 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
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_impl.h" 5 #include "net/base/host_resolver_impl.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)
(...skipping 23 matching lines...) Expand all
34 namespace net { 34 namespace net {
35 35
36 HostResolver* CreateSystemHostResolver() { 36 HostResolver* CreateSystemHostResolver() {
37 static const size_t kMaxHostCacheEntries = 100; 37 static const size_t kMaxHostCacheEntries = 100;
38 static const size_t kHostCacheExpirationMs = 60000; // 1 minute. 38 static const size_t kHostCacheExpirationMs = 60000; // 1 minute.
39 return new HostResolverImpl( 39 return new HostResolverImpl(
40 NULL, kMaxHostCacheEntries, kHostCacheExpirationMs); 40 NULL, kMaxHostCacheEntries, kHostCacheExpirationMs);
41 } 41 }
42 42
43 static int ResolveAddrInfo(HostResolverProc* resolver_proc, 43 static int ResolveAddrInfo(HostResolverProc* resolver_proc,
44 const std::string& host, AddressList* out) { 44 const std::string& host,
45 AddressFamily address_family,
46 AddressList* out) {
45 if (resolver_proc) { 47 if (resolver_proc) {
46 // Use the custom procedure. 48 // Use the custom procedure.
47 return resolver_proc->Resolve(host, out); 49 return resolver_proc->Resolve(host, address_family, out);
48 } else { 50 } else {
49 // Use the system procedure (getaddrinfo). 51 // Use the system procedure (getaddrinfo).
50 return SystemHostResolverProc(host, out); 52 return SystemHostResolverProc(host, address_family, out);
51 } 53 }
52 } 54 }
53 55
54 //----------------------------------------------------------------------------- 56 //-----------------------------------------------------------------------------
55 57
56 class HostResolverImpl::Request { 58 class HostResolverImpl::Request {
57 public: 59 public:
58 Request(LoadLog* load_log, 60 Request(LoadLog* load_log,
59 int id, 61 int id,
60 const RequestInfo& info, 62 const RequestInfo& info,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 DISALLOW_COPY_AND_ASSIGN(Request); 137 DISALLOW_COPY_AND_ASSIGN(Request);
136 }; 138 };
137 139
138 //----------------------------------------------------------------------------- 140 //-----------------------------------------------------------------------------
139 141
140 // This class represents a request to the worker pool for a "getaddrinfo()" 142 // This class represents a request to the worker pool for a "getaddrinfo()"
141 // call. 143 // call.
142 class HostResolverImpl::Job 144 class HostResolverImpl::Job
143 : public base::RefCountedThreadSafe<HostResolverImpl::Job> { 145 : public base::RefCountedThreadSafe<HostResolverImpl::Job> {
144 public: 146 public:
145 Job(HostResolverImpl* resolver, const std::string& host) 147 Job(HostResolverImpl* resolver, const Key& key)
146 : host_(host), 148 : key_(key),
147 resolver_(resolver), 149 resolver_(resolver),
148 origin_loop_(MessageLoop::current()), 150 origin_loop_(MessageLoop::current()),
149 resolver_proc_(resolver->effective_resolver_proc()), 151 resolver_proc_(resolver->effective_resolver_proc()),
150 error_(OK) { 152 error_(OK) {
151 } 153 }
152 154
153 ~Job() { 155 ~Job() {
154 // Free the requests attached to this job. 156 // Free the requests attached to this job.
155 STLDeleteElements(&requests_); 157 STLDeleteElements(&requests_);
156 } 158 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 resolver->CancelRequest(req); 201 resolver->CancelRequest(req);
200 } 202 }
201 } 203 }
202 204
203 // Called from origin thread. 205 // Called from origin thread.
204 bool was_cancelled() const { 206 bool was_cancelled() const {
205 return resolver_ == NULL; 207 return resolver_ == NULL;
206 } 208 }
207 209
208 // Called from origin thread. 210 // Called from origin thread.
209 const std::string& host() const { 211 const Key& key() const {
210 return host_; 212 return key_;
211 } 213 }
212 214
213 // Called from origin thread. 215 // Called from origin thread.
214 const RequestsList& requests() const { 216 const RequestsList& requests() const {
215 return requests_; 217 return requests_;
216 } 218 }
217 219
218 private: 220 private:
219 void DoLookup() { 221 void DoLookup() {
220 // Running on the worker thread 222 // Running on the worker thread
221 error_ = ResolveAddrInfo(resolver_proc_, host_, &results_); 223 error_ = ResolveAddrInfo(resolver_proc_,
224 key_.hostname,
225 key_.address_family,
226 &results_);
222 227
223 Task* reply = NewRunnableMethod(this, &Job::OnLookupComplete); 228 Task* reply = NewRunnableMethod(this, &Job::OnLookupComplete);
224 229
225 // The origin loop could go away while we are trying to post to it, so we 230 // The origin loop could go away while we are trying to post to it, so we
226 // need to call its PostTask method inside a lock. See ~HostResolver. 231 // need to call its PostTask method inside a lock. See ~HostResolver.
227 { 232 {
228 AutoLock locked(origin_loop_lock_); 233 AutoLock locked(origin_loop_lock_);
229 if (origin_loop_) { 234 if (origin_loop_) {
230 origin_loop_->PostTask(FROM_HERE, reply); 235 origin_loop_->PostTask(FROM_HERE, reply);
231 reply = NULL; 236 reply = NULL;
(...skipping 18 matching lines...) Expand all
250 DCHECK(!requests_.empty()); 255 DCHECK(!requests_.empty());
251 256
252 // Use the port number of the first request. 257 // Use the port number of the first request.
253 if (error_ == OK) 258 if (error_ == OK)
254 results_.SetPort(requests_[0]->port()); 259 results_.SetPort(requests_[0]->port());
255 260
256 resolver_->OnJobComplete(this, error_, results_); 261 resolver_->OnJobComplete(this, error_, results_);
257 } 262 }
258 263
259 // Set on the origin thread, read on the worker thread. 264 // Set on the origin thread, read on the worker thread.
260 std::string host_; 265 Key key_;
261 266
262 // Only used on the origin thread (where Resolve was called). 267 // Only used on the origin thread (where Resolve was called).
263 HostResolverImpl* resolver_; 268 HostResolverImpl* resolver_;
264 RequestsList requests_; // The requests waiting on this job. 269 RequestsList requests_; // The requests waiting on this job.
265 270
266 // Used to post ourselves onto the origin thread. 271 // Used to post ourselves onto the origin thread.
267 Lock origin_loop_lock_; 272 Lock origin_loop_lock_;
268 MessageLoop* origin_loop_; 273 MessageLoop* origin_loop_;
269 274
270 // Hold an owning reference to the HostResolverProc that we are going to use. 275 // Hold an owning reference to the HostResolverProc that we are going to use.
271 // This may not be the current resolver procedure by the time we call 276 // This may not be the current resolver procedure by the time we call
272 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning 277 // ResolveAddrInfo, but that's OK... we'll use it anyways, and the owning
273 // reference ensures that it remains valid until we are done. 278 // reference ensures that it remains valid until we are done.
274 scoped_refptr<HostResolverProc> resolver_proc_; 279 scoped_refptr<HostResolverProc> resolver_proc_;
275 280
276 // Assigned on the worker thread, read on the origin thread. 281 // Assigned on the worker thread, read on the origin thread.
277 int error_; 282 int error_;
278 AddressList results_; 283 AddressList results_;
279 284
280 DISALLOW_COPY_AND_ASSIGN(Job); 285 DISALLOW_COPY_AND_ASSIGN(Job);
281 }; 286 };
282 287
283 //----------------------------------------------------------------------------- 288 //-----------------------------------------------------------------------------
284 289
285 HostResolverImpl::HostResolverImpl(HostResolverProc* resolver_proc, 290 HostResolverImpl::HostResolverImpl(HostResolverProc* resolver_proc,
286 int max_cache_entries, 291 int max_cache_entries,
287 int cache_duration_ms) 292 int cache_duration_ms)
288 : cache_(max_cache_entries, cache_duration_ms), next_request_id_(0), 293 : cache_(max_cache_entries, cache_duration_ms),
289 resolver_proc_(resolver_proc), shutdown_(false) { 294 next_request_id_(0),
295 resolver_proc_(resolver_proc),
296 disable_ipv6_(false),
297 shutdown_(false) {
290 #if defined(OS_WIN) 298 #if defined(OS_WIN)
291 EnsureWinsockInit(); 299 EnsureWinsockInit();
292 #endif 300 #endif
293 } 301 }
294 302
295 HostResolverImpl::~HostResolverImpl() { 303 HostResolverImpl::~HostResolverImpl() {
296 // Cancel the outstanding jobs. Those jobs may contain several attached 304 // Cancel the outstanding jobs. Those jobs may contain several attached
297 // requests, which will also be cancelled. 305 // requests, which will also be cancelled.
298 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 306 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
299 it->second->Cancel(); 307 it->second->Cancel();
(...skipping 12 matching lines...) Expand all
312 LoadLog* load_log) { 320 LoadLog* load_log) {
313 if (shutdown_) 321 if (shutdown_)
314 return ERR_UNEXPECTED; 322 return ERR_UNEXPECTED;
315 323
316 // Choose a unique ID number for observers to see. 324 // Choose a unique ID number for observers to see.
317 int request_id = next_request_id_++; 325 int request_id = next_request_id_++;
318 326
319 // Update the load log and notify registered observers. 327 // Update the load log and notify registered observers.
320 OnStartRequest(load_log, request_id, info); 328 OnStartRequest(load_log, request_id, info);
321 329
330 // Build a key that identifies the request in the cache and in the
331 // outstanding jobs map.
332 Key key(info.hostname(), info.address_family());
333 if (disable_ipv6_)
334 key.address_family = ADDRESS_FAMILY_IPV4_ONLY;
335
322 // If we have an unexpired cache entry, use it. 336 // If we have an unexpired cache entry, use it.
323 if (info.allow_cached_response()) { 337 if (info.allow_cached_response()) {
324 const HostCache::Entry* cache_entry = cache_.Lookup( 338 const HostCache::Entry* cache_entry = cache_.Lookup(
325 info.hostname(), base::TimeTicks::Now()); 339 key, base::TimeTicks::Now());
326 if (cache_entry) { 340 if (cache_entry) {
327 addresses->SetFrom(cache_entry->addrlist, info.port()); 341 addresses->SetFrom(cache_entry->addrlist, info.port());
328 int error = cache_entry->error; 342 int error = cache_entry->error;
329 343
330 // Update the load log and notify registered observers. 344 // Update the load log and notify registered observers.
331 OnFinishRequest(load_log, request_id, info, error); 345 OnFinishRequest(load_log, request_id, info, error);
332 346
333 return error; 347 return error;
334 } 348 }
335 } 349 }
336 350
337 // If no callback was specified, do a synchronous resolution. 351 // If no callback was specified, do a synchronous resolution.
338 if (!callback) { 352 if (!callback) {
339 AddressList addrlist; 353 AddressList addrlist;
340 int error = ResolveAddrInfo( 354 int error = ResolveAddrInfo(
341 effective_resolver_proc(), info.hostname(), &addrlist); 355 effective_resolver_proc(), key.hostname, key.address_family, &addrlist);
342 if (error == OK) { 356 if (error == OK) {
343 addrlist.SetPort(info.port()); 357 addrlist.SetPort(info.port());
344 *addresses = addrlist; 358 *addresses = addrlist;
345 } 359 }
346 360
347 // Write to cache. 361 // Write to cache.
348 cache_.Set(info.hostname(), error, addrlist, base::TimeTicks::Now()); 362 cache_.Set(key, error, addrlist, base::TimeTicks::Now());
349 363
350 // Update the load log and notify registered observers. 364 // Update the load log and notify registered observers.
351 OnFinishRequest(load_log, request_id, info, error); 365 OnFinishRequest(load_log, request_id, info, error);
352 366
353 return error; 367 return error;
354 } 368 }
355 369
356 // Create a handle for this request, and pass it back to the user if they 370 // Create a handle for this request, and pass it back to the user if they
357 // asked for it (out_req != NULL). 371 // asked for it (out_req != NULL).
358 Request* req = new Request(load_log, request_id, info, callback, addresses); 372 Request* req = new Request(load_log, request_id, info, callback, addresses);
359 if (out_req) 373 if (out_req)
360 *out_req = reinterpret_cast<RequestHandle>(req); 374 *out_req = reinterpret_cast<RequestHandle>(req);
361 375
362 // Next we need to attach our request to a "job". This job is responsible for 376 // Next we need to attach our request to a "job". This job is responsible for
363 // calling "getaddrinfo(hostname)" on a worker thread. 377 // calling "getaddrinfo(hostname)" on a worker thread.
364 scoped_refptr<Job> job; 378 scoped_refptr<Job> job;
365 379
366 // If there is already an outstanding job to resolve |info.hostname()|, use 380 // If there is already an outstanding job to resolve |key|, use
367 // it. This prevents starting concurrent resolves for the same hostname. 381 // it. This prevents starting concurrent resolves for the same hostname.
368 job = FindOutstandingJob(info.hostname()); 382 job = FindOutstandingJob(key);
369 if (job) { 383 if (job) {
370 job->AddRequest(req); 384 job->AddRequest(req);
371 } else { 385 } else {
372 // Create a new job for this request. 386 // Create a new job for this request.
373 job = new Job(this, info.hostname()); 387 job = new Job(this, key);
374 job->AddRequest(req); 388 job->AddRequest(req);
375 AddOutstandingJob(job); 389 AddOutstandingJob(job);
376 // TODO(eroman): Bound the total number of concurrent jobs. 390 // TODO(eroman): Bound the total number of concurrent jobs.
377 // http://crbug.com/9598 391 // http://crbug.com/9598
378 job->Start(); 392 job->Start();
379 } 393 }
380 394
381 // Completion happens during OnJobComplete(Job*). 395 // Completion happens during OnJobComplete(Job*).
382 return ERR_IO_PENDING; 396 return ERR_IO_PENDING;
383 } 397 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 void HostResolverImpl::Shutdown() { 438 void HostResolverImpl::Shutdown() {
425 shutdown_ = true; 439 shutdown_ = true;
426 440
427 // Cancel the outstanding jobs. 441 // Cancel the outstanding jobs.
428 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it) 442 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
429 it->second->Cancel(); 443 it->second->Cancel();
430 jobs_.clear(); 444 jobs_.clear();
431 } 445 }
432 446
433 void HostResolverImpl::AddOutstandingJob(Job* job) { 447 void HostResolverImpl::AddOutstandingJob(Job* job) {
434 scoped_refptr<Job>& found_job = jobs_[job->host()]; 448 scoped_refptr<Job>& found_job = jobs_[job->key()];
435 DCHECK(!found_job); 449 DCHECK(!found_job);
436 found_job = job; 450 found_job = job;
437 } 451 }
438 452
439 HostResolverImpl::Job* HostResolverImpl::FindOutstandingJob( 453 HostResolverImpl::Job* HostResolverImpl::FindOutstandingJob(const Key& key) {
440 const std::string& hostname) { 454 JobMap::iterator it = jobs_.find(key);
441 JobMap::iterator it = jobs_.find(hostname);
442 if (it != jobs_.end()) 455 if (it != jobs_.end())
443 return it->second; 456 return it->second;
444 return NULL; 457 return NULL;
445 } 458 }
446 459
447 void HostResolverImpl::RemoveOutstandingJob(Job* job) { 460 void HostResolverImpl::RemoveOutstandingJob(Job* job) {
448 JobMap::iterator it = jobs_.find(job->host()); 461 JobMap::iterator it = jobs_.find(job->key());
449 DCHECK(it != jobs_.end()); 462 DCHECK(it != jobs_.end());
450 DCHECK_EQ(it->second.get(), job); 463 DCHECK_EQ(it->second.get(), job);
451 jobs_.erase(it); 464 jobs_.erase(it);
452 } 465 }
453 466
454 void HostResolverImpl::OnJobComplete(Job* job, 467 void HostResolverImpl::OnJobComplete(Job* job,
455 int error, 468 int error,
456 const AddressList& addrlist) { 469 const AddressList& addrlist) {
457 RemoveOutstandingJob(job); 470 RemoveOutstandingJob(job);
458 471
459 // Write result to the cache. 472 // Write result to the cache.
460 cache_.Set(job->host(), error, addrlist, base::TimeTicks::Now()); 473 cache_.Set(job->key(), error, addrlist, base::TimeTicks::Now());
461 474
462 // Make a note that we are executing within OnJobComplete() in case the 475 // Make a note that we are executing within OnJobComplete() in case the
463 // HostResolver is deleted by a callback invocation. 476 // HostResolver is deleted by a callback invocation.
464 DCHECK(!cur_completing_job_); 477 DCHECK(!cur_completing_job_);
465 cur_completing_job_ = job; 478 cur_completing_job_ = job;
466 479
467 // Complete all of the requests that were attached to the job. 480 // Complete all of the requests that were attached to the job.
468 for (RequestsList::const_iterator it = job->requests().begin(); 481 for (RequestsList::const_iterator it = job->requests().begin();
469 it != job->requests().end(); ++it) { 482 it != job->requests().end(); ++it) {
470 Request* req = *it; 483 Request* req = *it;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 } 557 }
545 558
546 LoadLog::EndEvent( 559 LoadLog::EndEvent(
547 load_log, LoadLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONCANCEL); 560 load_log, LoadLog::TYPE_HOST_RESOLVER_IMPL_OBSERVER_ONCANCEL);
548 } 561 }
549 562
550 LoadLog::EndEvent(load_log, LoadLog::TYPE_HOST_RESOLVER_IMPL); 563 LoadLog::EndEvent(load_log, LoadLog::TYPE_HOST_RESOLVER_IMPL);
551 } 564 }
552 565
553 } // namespace net 566 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698