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

Side by Side Diff: net/dns/async_host_resolver.cc

Issue 9190031: DnsClient refactoring + features (timeout, suffix search, server rotation). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Delinted. Created 8 years, 11 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/dns/async_host_resolver.h ('k') | net/dns/async_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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/dns/async_host_resolver.h" 5 #include "net/dns/async_host_resolver.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 config.nameservers.push_back(IPEndPoint(dns_ip, 53)); 68 config.nameservers.push_back(IPEndPoint(dns_ip, 53));
69 DnsSession* session = new DnsSession( 69 DnsSession* session = new DnsSession(
70 config, 70 config,
71 ClientSocketFactory::GetDefaultFactory(), 71 ClientSocketFactory::GetDefaultFactory(),
72 base::Bind(&base::RandInt), 72 base::Bind(&base::RandInt),
73 net_log); 73 net_log);
74 HostResolver* resolver = new AsyncHostResolver( 74 HostResolver* resolver = new AsyncHostResolver(
75 max_dns_requests, 75 max_dns_requests,
76 max_pending_requests, 76 max_pending_requests,
77 HostCache::CreateDefaultCache(), 77 HostCache::CreateDefaultCache(),
78 DnsClient::CreateClient(session), 78 DnsTransactionFactory::CreateFactory(session),
79 net_log); 79 net_log);
80 return resolver; 80 return resolver;
81 } 81 }
82 82
83 //----------------------------------------------------------------------------- 83 //-----------------------------------------------------------------------------
84 // Every call to Resolve() results in Request object being created. Such a 84 // Every call to Resolve() results in Request object being created. Such a
85 // call may complete either synchronously or asynchronously or it may get 85 // call may complete either synchronously or asynchronously or it may get
86 // cancelled, which can be either through specific CancelRequest call or by 86 // cancelled, which can be either through specific CancelRequest call or by
87 // the destruction of AsyncHostResolver, which would destruct pending or 87 // the destruction of AsyncHostResolver, which would destruct pending or
88 // in-progress requests, causing them to be cancelled. Synchronous 88 // in-progress requests, causing them to be cancelled. Synchronous
(...skipping 10 matching lines...) Expand all
99 : resolver_(resolver), 99 : resolver_(resolver),
100 source_net_log_(source_net_log), 100 source_net_log_(source_net_log),
101 request_net_log_(request_net_log), 101 request_net_log_(request_net_log),
102 info_(info), 102 info_(info),
103 callback_(callback), 103 callback_(callback),
104 addresses_(addresses), 104 addresses_(addresses),
105 result_(ERR_UNEXPECTED) { 105 result_(ERR_UNEXPECTED) {
106 DCHECK(addresses_); 106 DCHECK(addresses_);
107 DCHECK(resolver_); 107 DCHECK(resolver_);
108 resolver_->OnStart(this); 108 resolver_->OnStart(this);
109 std::string dns_name; 109 key_ = Key(info.hostname(),
110 if (DNSDomainFromDot(info.hostname(), &dns_name)) 110 QueryTypeFromAddressFamily(info.address_family()));
111 key_ = Key(dns_name, QueryTypeFromAddressFamily(info.address_family()));
112 } 111 }
113 112
114 ~Request() { 113 ~Request() {
115 if (!callback_.is_null()) 114 if (!callback_.is_null())
116 resolver_->OnCancel(this); 115 resolver_->OnCancel(this);
117 } 116 }
118 117
119 int result() const { return result_; } 118 int result() const { return result_; }
120 const Key& key() const { 119 const Key& key() const {
121 DCHECK(IsValid()); 120 DCHECK(IsValid());
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 Key key_; 197 Key key_;
199 CompletionCallback callback_; 198 CompletionCallback callback_;
200 AddressList* addresses_; 199 AddressList* addresses_;
201 int result_; 200 int result_;
202 }; 201 };
203 202
204 //----------------------------------------------------------------------------- 203 //-----------------------------------------------------------------------------
205 AsyncHostResolver::AsyncHostResolver(size_t max_dns_requests, 204 AsyncHostResolver::AsyncHostResolver(size_t max_dns_requests,
206 size_t max_pending_requests, 205 size_t max_pending_requests,
207 HostCache* cache, 206 HostCache* cache,
208 DnsClient* client, 207 scoped_ptr<DnsTransactionFactory> client,
209 NetLog* net_log) 208 NetLog* net_log)
210 : max_dns_requests_(max_dns_requests), 209 : max_dns_transactions_(max_dns_requests),
211 max_pending_requests_(max_pending_requests), 210 max_pending_requests_(max_pending_requests),
212 cache_(cache), 211 cache_(cache),
213 client_(client), 212 client_(client.Pass()),
214 net_log_(net_log) { 213 net_log_(net_log) {
215 } 214 }
216 215
217 AsyncHostResolver::~AsyncHostResolver() { 216 AsyncHostResolver::~AsyncHostResolver() {
218 // Destroy request lists. 217 // Destroy request lists.
219 for (KeyRequestListMap::iterator it = requestlist_map_.begin(); 218 for (KeyRequestListMap::iterator it = requestlist_map_.begin();
220 it != requestlist_map_.end(); ++it) 219 it != requestlist_map_.end(); ++it)
221 STLDeleteElements(&it->second); 220 STLDeleteElements(&it->second);
222 221
223 // Destroy DNS requests. 222 // Destroy DNS transactions.
224 STLDeleteElements(&dns_requests_); 223 STLDeleteElements(&dns_transactions_);
225 224
226 // Destroy pending requests. 225 // Destroy pending requests.
227 for (size_t i = 0; i < arraysize(pending_requests_); ++i) 226 for (size_t i = 0; i < arraysize(pending_requests_); ++i)
228 STLDeleteElements(&pending_requests_[i]); 227 STLDeleteElements(&pending_requests_[i]);
229 } 228 }
230 229
231 int AsyncHostResolver::Resolve(const RequestInfo& info, 230 int AsyncHostResolver::Resolve(const RequestInfo& info,
232 AddressList* addresses, 231 AddressList* addresses,
233 const CompletionCallback& callback, 232 const CompletionCallback& callback,
234 RequestHandle* out_req, 233 RequestHandle* out_req,
235 const BoundNetLog& source_net_log) { 234 const BoundNetLog& source_net_log) {
236 DCHECK(addresses); 235 DCHECK(addresses);
237 DCHECK_EQ(false, callback.is_null()); 236 DCHECK_EQ(false, callback.is_null());
238 scoped_ptr<Request> request( 237 scoped_ptr<Request> request(
239 CreateNewRequest(info, callback, addresses, source_net_log)); 238 CreateNewRequest(info, callback, addresses, source_net_log));
240 239
241 int rv = ERR_UNEXPECTED; 240 int rv = ERR_UNEXPECTED;
242 if (!request->IsValid()) 241 if (!request->IsValid())
243 rv = ERR_NAME_NOT_RESOLVED; 242 rv = ERR_NAME_NOT_RESOLVED;
244 else if (request->ResolveAsIp() || request->ServeFromCache()) 243 else if (request->ResolveAsIp() || request->ServeFromCache())
245 rv = request->result(); 244 rv = request->result();
246 else if (AttachToRequestList(request.get())) 245 else if (AttachToRequestList(request.get()))
247 rv = ERR_IO_PENDING; 246 rv = ERR_IO_PENDING;
248 else if (dns_requests_.size() < max_dns_requests_) 247 else if (dns_transactions_.size() < max_dns_transactions_)
249 rv = StartNewDnsRequestFor(request.get()); 248 rv = StartNewDnsRequestFor(request.get());
250 else 249 else
251 rv = Enqueue(request.get()); 250 rv = Enqueue(request.get());
252 251
253 if (rv != ERR_IO_PENDING) { 252 if (rv != ERR_IO_PENDING) {
254 request->OnSyncComplete(rv); 253 request->OnSyncComplete(rv);
255 } else { 254 } else {
256 Request* req = request.release(); 255 Request* req = request.release();
257 if (out_req) 256 if (out_req)
258 *out_req = reinterpret_cast<RequestHandle>(req); 257 *out_req = reinterpret_cast<RequestHandle>(req);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 } 324 }
326 325
327 AddressFamily AsyncHostResolver::GetDefaultAddressFamily() const { 326 AddressFamily AsyncHostResolver::GetDefaultAddressFamily() const {
328 return ADDRESS_FAMILY_IPV4; 327 return ADDRESS_FAMILY_IPV4;
329 } 328 }
330 329
331 HostCache* AsyncHostResolver::GetHostCache() { 330 HostCache* AsyncHostResolver::GetHostCache() {
332 return cache_.get(); 331 return cache_.get();
333 } 332 }
334 333
335 void AsyncHostResolver::OnDnsRequestComplete( 334 void AsyncHostResolver::OnDnsTransactionComplete(
336 DnsClient::Request* dns_req, 335 DnsTransaction* transaction,
337 int result, 336 int result,
338 const DnsResponse* response) { 337 const DnsResponse* response) {
339 DCHECK(std::find(dns_requests_.begin(), dns_requests_.end(), dns_req) 338 DCHECK(std::find(dns_transactions_.begin(),
340 != dns_requests_.end()); 339 dns_transactions_.end(),
340 transaction) != dns_transactions_.end());
341 341
342 // If by the time requests that caused |dns_req| are cancelled, we do 342 // If by the time requests that caused |transaction| are cancelled, we do
343 // not have a port number to associate with the result, therefore, we 343 // not have a port number to associate with the result, therefore, we
344 // assume the most common port, otherwise we use the port number of the 344 // assume the most common port, otherwise we use the port number of the
345 // first request. 345 // first request.
346 KeyRequestListMap::iterator rit = requestlist_map_.find( 346 KeyRequestListMap::iterator rit = requestlist_map_.find(
347 std::make_pair(dns_req->qname(), dns_req->qtype())); 347 std::make_pair(transaction->GetHostname(), transaction->GetType()));
348 DCHECK(rit != requestlist_map_.end()); 348 DCHECK(rit != requestlist_map_.end());
349 RequestList& requests = rit->second; 349 RequestList& requests = rit->second;
350 int port = requests.empty() ? 80 : requests.front()->info().port(); 350 int port = requests.empty() ? 80 : requests.front()->info().port();
351 351
352 // Extract AddressList and TTL out of DnsResponse. 352 // Extract AddressList and TTL out of DnsResponse.
353 AddressList addr_list; 353 AddressList addr_list;
354 uint32 ttl = kuint32max; 354 uint32 ttl = kuint32max;
355 if (result == OK) { 355 if (result == OK) {
356 IPAddressList ip_addresses; 356 IPAddressList ip_addresses;
357 DnsRecordParser parser = response->Parser(); 357 DnsRecordParser parser = response->Parser();
358 DnsResourceRecord record; 358 DnsResourceRecord record;
359 // TODO(szym): Add stricter checking of names, aliases and address lengths. 359 // TODO(szym): Add stricter checking of names, aliases and address lengths.
360 while (parser.ParseRecord(&record)) { 360 while (parser.ParseRecord(&record)) {
361 if (record.type == dns_req->qtype() && 361 if (record.type == transaction->GetType() &&
362 (record.rdata.size() == kIPv4AddressSize || 362 (record.rdata.size() == kIPv4AddressSize ||
363 record.rdata.size() == kIPv6AddressSize)) { 363 record.rdata.size() == kIPv6AddressSize)) {
364 ip_addresses.push_back(IPAddressNumber(record.rdata.begin(), 364 ip_addresses.push_back(IPAddressNumber(record.rdata.begin(),
365 record.rdata.end())); 365 record.rdata.end()));
366 ttl = std::min(ttl, record.ttl); 366 ttl = std::min(ttl, record.ttl);
367 } 367 }
368 } 368 }
369 if (!ip_addresses.empty()) 369 if (!ip_addresses.empty())
370 addr_list = AddressList::CreateFromIPAddressList(ip_addresses, port); 370 addr_list = AddressList::CreateFromIPAddressList(ip_addresses, port);
371 else 371 else
372 result = ERR_NAME_NOT_RESOLVED; 372 result = ERR_NAME_NOT_RESOLVED;
373 } 373 }
374 374
375 // Run callback of every request that was depending on this DNS request, 375 // Run callback of every request that was depending on this DNS request,
376 // also notify observers. 376 // also notify observers.
377 for (RequestList::iterator it = requests.begin(); it != requests.end(); ++it) 377 for (RequestList::iterator it = requests.begin(); it != requests.end(); ++it)
378 (*it)->OnAsyncComplete(result, addr_list); 378 (*it)->OnAsyncComplete(result, addr_list);
379 379
380 // It is possible that the requests that caused |dns_req| to be 380 // It is possible that the requests that caused |transaction| to be
381 // created are cancelled by the time |dns_req| completes. In that 381 // created are cancelled by the time |transaction| completes. In that
382 // case |requests| would be empty. We are knowingly throwing away the 382 // case |requests| would be empty. We are knowingly throwing away the
383 // result of a DNS resolution in that case, because (a) if there are no 383 // result of a DNS resolution in that case, because (a) if there are no
384 // requests, we do not have info to obtain a key from, (b) DnsTransaction 384 // requests, we do not have info to obtain a key from, (b) DnsTransaction
385 // does not have info(). 385 // does not have info().
386 // TODO(szym): Should DnsTransaction ignore HostResolverFlags or use defaults? 386 // TODO(szym): Should DnsTransaction ignore HostResolverFlags or use defaults?
387 if ((result == OK || result == ERR_NAME_NOT_RESOLVED) && cache_.get() && 387 if ((result == OK || result == ERR_NAME_NOT_RESOLVED) && cache_.get() &&
388 !requests.empty()) { 388 !requests.empty()) {
389 Request* request = requests.front(); 389 Request* request = requests.front();
390 HostResolver::RequestInfo info = request->info(); 390 HostResolver::RequestInfo info = request->info();
391 HostCache::Key key( 391 HostCache::Key key(
392 info.hostname(), info.address_family(), info.host_resolver_flags()); 392 info.hostname(), info.address_family(), info.host_resolver_flags());
393 // Store negative results with TTL 0 to flush out the old entry. 393 // Store negative results with TTL 0 to flush out the old entry.
394 cache_->Set(key, 394 cache_->Set(key,
395 result, 395 result,
396 addr_list, 396 addr_list,
397 base::TimeTicks::Now(), 397 base::TimeTicks::Now(),
398 (result == OK) ? base::TimeDelta::FromSeconds(ttl) 398 (result == OK) ? base::TimeDelta::FromSeconds(ttl)
399 : base::TimeDelta()); 399 : base::TimeDelta());
400 } 400 }
401 401
402 // Cleanup requests. 402 // Cleanup requests.
403 STLDeleteElements(&requests); 403 STLDeleteElements(&requests);
404 requestlist_map_.erase(rit); 404 requestlist_map_.erase(rit);
405 405
406 // Cleanup |dns_req| and start a new one if there are pending requests. 406 // Cleanup |transaction| and start a new one if there are pending requests.
407 dns_requests_.remove(dns_req); 407 dns_transactions_.remove(transaction);
408 delete dns_req; 408 delete transaction;
409 ProcessPending(); 409 ProcessPending();
410 } 410 }
411 411
412 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( 412 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest(
413 const RequestInfo& info, 413 const RequestInfo& info,
414 const CompletionCallback& callback, 414 const CompletionCallback& callback,
415 AddressList* addresses, 415 AddressList* addresses,
416 const BoundNetLog& source_net_log) { 416 const BoundNetLog& source_net_log) {
417 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, 417 BoundNetLog request_net_log = BoundNetLog::Make(net_log_,
418 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST); 418 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST);
419 return new Request( 419 return new Request(
420 this, source_net_log, request_net_log, info, callback, addresses); 420 this, source_net_log, request_net_log, info, callback, addresses);
421 } 421 }
422 422
423 bool AsyncHostResolver::AttachToRequestList(Request* request) { 423 bool AsyncHostResolver::AttachToRequestList(Request* request) {
424 KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); 424 KeyRequestListMap::iterator it = requestlist_map_.find(request->key());
425 if (it == requestlist_map_.end()) 425 if (it == requestlist_map_.end())
426 return false; 426 return false;
427 it->second.push_back(request); 427 it->second.push_back(request);
428 return true; 428 return true;
429 } 429 }
430 430
431 int AsyncHostResolver::StartNewDnsRequestFor(Request* request) { 431 int AsyncHostResolver::StartNewDnsRequestFor(Request* request) {
432 DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end()); 432 DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end());
433 DCHECK(dns_requests_.size() < max_dns_requests_); 433 DCHECK(dns_transactions_.size() < max_dns_transactions_);
434 434
435 request->request_net_log().AddEvent( 435 request->request_net_log().AddEvent(
436 NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL); 436 NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL);
437 437
438 requestlist_map_[request->key()].push_back(request); 438 requestlist_map_[request->key()].push_back(request);
439 DnsClient::Request* dns_req = client_->CreateRequest( 439 scoped_ptr<DnsTransaction> transaction(client_->CreateTransaction(
440 request->key().first, 440 request->key().first,
441 request->key().second, 441 request->key().second,
442 base::Bind(&AsyncHostResolver::OnDnsRequestComplete, 442 base::Bind(&AsyncHostResolver::OnDnsTransactionComplete,
443 base::Unretained(this)), 443 base::Unretained(this)),
444 request->request_net_log()); 444 request->request_net_log()));
445 dns_requests_.push_back(dns_req); 445 int rv = transaction->Start();
446 return dns_req->Start(); 446 if (rv == ERR_IO_PENDING)
447 dns_transactions_.push_back(transaction.release());
448 return rv;
447 } 449 }
448 450
449 int AsyncHostResolver::Enqueue(Request* request) { 451 int AsyncHostResolver::Enqueue(Request* request) {
450 Request* evicted_request = Insert(request); 452 Request* evicted_request = Insert(request);
451 int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; 453 int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
452 if (evicted_request == request) 454 if (evicted_request == request)
453 return rv; 455 return rv;
454 if (evicted_request != NULL) { 456 if (evicted_request != NULL) {
455 evicted_request->OnAsyncComplete(rv, AddressList()); 457 evicted_request->OnAsyncComplete(rv, AddressList());
456 delete evicted_request; 458 delete evicted_request;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 it = requests.erase(it); 515 it = requests.erase(it);
514 } else { 516 } else {
515 ++it; 517 ++it;
516 } 518 }
517 } 519 }
518 } 520 }
519 StartNewDnsRequestFor(request); 521 StartNewDnsRequestFor(request);
520 } 522 }
521 523
522 } // namespace net 524 } // namespace net
OLDNEW
« no previous file with comments | « net/dns/async_host_resolver.h ('k') | net/dns/async_host_resolver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698