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

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: Addressed code review. 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 out of DnsResponse. 352 // Extract AddressList out of DnsResponse.
353 AddressList addr_list; 353 AddressList addr_list;
354 if (result == OK) { 354 if (result == OK) {
355 IPAddressList ip_addresses; 355 IPAddressList ip_addresses;
356 DnsRecordParser parser = response->Parser(); 356 DnsRecordParser parser = response->Parser();
357 DnsResourceRecord record; 357 DnsResourceRecord record;
358 // TODO(szym): Add stricter checking of names, aliases and address lengths. 358 // TODO(szym): Add stricter checking of names, aliases and address lengths.
359 while (parser.ParseRecord(&record)) { 359 while (parser.ParseRecord(&record)) {
360 if (record.type == dns_req->qtype() && 360 if (record.type == transaction->GetType() &&
361 (record.rdata.size() == kIPv4AddressSize || 361 (record.rdata.size() == kIPv4AddressSize ||
362 record.rdata.size() == kIPv6AddressSize)) { 362 record.rdata.size() == kIPv6AddressSize)) {
363 ip_addresses.push_back(IPAddressNumber(record.rdata.begin(), 363 ip_addresses.push_back(IPAddressNumber(record.rdata.begin(),
364 record.rdata.end())); 364 record.rdata.end()));
365 } 365 }
366 } 366 }
367 if (!ip_addresses.empty()) 367 if (!ip_addresses.empty())
368 addr_list = AddressList::CreateFromIPAddressList(ip_addresses, port); 368 addr_list = AddressList::CreateFromIPAddressList(ip_addresses, port);
369 else 369 else
370 result = ERR_NAME_NOT_RESOLVED; 370 result = ERR_NAME_NOT_RESOLVED;
371 } 371 }
372 372
373 // Run callback of every request that was depending on this DNS request, 373 // Run callback of every request that was depending on this DNS request,
374 // also notify observers. 374 // also notify observers.
375 for (RequestList::iterator it = requests.begin(); it != requests.end(); ++it) 375 for (RequestList::iterator it = requests.begin(); it != requests.end(); ++it)
376 (*it)->OnAsyncComplete(result, addr_list); 376 (*it)->OnAsyncComplete(result, addr_list);
377 377
378 // It is possible that the requests that caused |dns_req| to be 378 // It is possible that the requests that caused |transaction| to be
379 // created are cancelled by the time |dns_req| completes. In that 379 // created are cancelled by the time |transaction| completes. In that
380 // case |requests| would be empty. We are knowingly throwing away the 380 // case |requests| would be empty. We are knowingly throwing away the
381 // result of a DNS resolution in that case, because (a) if there are no 381 // result of a DNS resolution in that case, because (a) if there are no
382 // requests, we do not have info to obtain a key from, (b) DnsTransaction 382 // requests, we do not have info to obtain a key from, (b) DnsTransaction
383 // does not have info(), adding one into it just temporarily doesn't make 383 // does not have info(), adding one into it just temporarily doesn't make
384 // sense, since HostCache will be replaced with RR cache soon. 384 // sense, since HostCache will be replaced with RR cache soon.
385 // Also, we only cache positive results. All of this will change when RR 385 // Also, we only cache positive results. All of this will change when RR
386 // cache is added. 386 // cache is added.
387 if (result == OK && cache_.get() && !requests.empty()) { 387 if (result == OK && cache_.get() && !requests.empty()) {
388 Request* request = requests.front(); 388 Request* request = requests.front();
389 HostResolver::RequestInfo info = request->info(); 389 HostResolver::RequestInfo info = request->info();
390 HostCache::Key key( 390 HostCache::Key key(
391 info.hostname(), info.address_family(), info.host_resolver_flags()); 391 info.hostname(), info.address_family(), info.host_resolver_flags());
392 cache_->Set(key, result, addr_list, base::TimeTicks::Now()); 392 cache_->Set(key, result, addr_list, base::TimeTicks::Now());
393 } 393 }
394 394
395 // Cleanup requests. 395 // Cleanup requests.
396 STLDeleteElements(&requests); 396 STLDeleteElements(&requests);
397 requestlist_map_.erase(rit); 397 requestlist_map_.erase(rit);
398 398
399 // Cleanup |dns_req| and start a new one if there are pending requests. 399 // Cleanup |transaction| and start a new one if there are pending requests.
400 dns_requests_.remove(dns_req); 400 dns_transactions_.remove(transaction);
401 delete dns_req; 401 delete transaction;
402 ProcessPending(); 402 ProcessPending();
403 } 403 }
404 404
405 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( 405 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest(
406 const RequestInfo& info, 406 const RequestInfo& info,
407 const CompletionCallback& callback, 407 const CompletionCallback& callback,
408 AddressList* addresses, 408 AddressList* addresses,
409 const BoundNetLog& source_net_log) { 409 const BoundNetLog& source_net_log) {
410 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, 410 BoundNetLog request_net_log = BoundNetLog::Make(net_log_,
411 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST); 411 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST);
412 return new Request( 412 return new Request(
413 this, source_net_log, request_net_log, info, callback, addresses); 413 this, source_net_log, request_net_log, info, callback, addresses);
414 } 414 }
415 415
416 bool AsyncHostResolver::AttachToRequestList(Request* request) { 416 bool AsyncHostResolver::AttachToRequestList(Request* request) {
417 KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); 417 KeyRequestListMap::iterator it = requestlist_map_.find(request->key());
418 if (it == requestlist_map_.end()) 418 if (it == requestlist_map_.end())
419 return false; 419 return false;
420 it->second.push_back(request); 420 it->second.push_back(request);
421 return true; 421 return true;
422 } 422 }
423 423
424 int AsyncHostResolver::StartNewDnsRequestFor(Request* request) { 424 int AsyncHostResolver::StartNewDnsRequestFor(Request* request) {
425 DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end()); 425 DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end());
426 DCHECK(dns_requests_.size() < max_dns_requests_); 426 DCHECK(dns_transactions_.size() < max_dns_transactions_);
427 427
428 request->request_net_log().AddEvent( 428 request->request_net_log().AddEvent(
429 NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL); 429 NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL);
430 430
431 requestlist_map_[request->key()].push_back(request); 431 requestlist_map_[request->key()].push_back(request);
432 DnsClient::Request* dns_req = client_->CreateRequest( 432 scoped_ptr<DnsTransaction> transaction(client_->CreateTransaction(
433 request->key().first, 433 request->key().first,
434 request->key().second, 434 request->key().second,
435 base::Bind(&AsyncHostResolver::OnDnsRequestComplete, 435 base::Bind(&AsyncHostResolver::OnDnsTransactionComplete,
436 base::Unretained(this)), 436 base::Unretained(this)),
437 request->request_net_log()); 437 request->request_net_log()));
438 dns_requests_.push_back(dns_req); 438 int rv = transaction->Start();
439 return dns_req->Start(); 439 if (rv == ERR_IO_PENDING)
440 dns_transactions_.push_back(transaction.release());
441 return rv;
440 } 442 }
441 443
442 int AsyncHostResolver::Enqueue(Request* request) { 444 int AsyncHostResolver::Enqueue(Request* request) {
443 Request* evicted_request = Insert(request); 445 Request* evicted_request = Insert(request);
444 int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; 446 int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
445 if (evicted_request == request) 447 if (evicted_request == request)
446 return rv; 448 return rv;
447 if (evicted_request != NULL) { 449 if (evicted_request != NULL) {
448 evicted_request->OnAsyncComplete(rv, AddressList()); 450 evicted_request->OnAsyncComplete(rv, AddressList());
449 delete evicted_request; 451 delete evicted_request;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 it = requests.erase(it); 508 it = requests.erase(it);
507 } else { 509 } else {
508 ++it; 510 ++it;
509 } 511 }
510 } 512 }
511 } 513 }
512 StartNewDnsRequestFor(request); 514 StartNewDnsRequestFor(request);
513 } 515 }
514 516
515 } // namespace net 517 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698