| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |