| OLD | NEW | 
|---|
| 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/base/async_host_resolver.h" | 5 #include "net/base/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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 73                                       NetLog* net_log) { | 73                                       NetLog* net_log) { | 
| 74   size_t max_transactions = max_concurrent_resolves; | 74   size_t max_transactions = max_concurrent_resolves; | 
| 75   if (max_transactions == 0) | 75   if (max_transactions == 0) | 
| 76     max_transactions = 20; | 76     max_transactions = 20; | 
| 77   size_t max_pending_requests = max_transactions * 100; | 77   size_t max_pending_requests = max_transactions * 100; | 
| 78   HostResolver* resolver = new AsyncHostResolver( | 78   HostResolver* resolver = new AsyncHostResolver( | 
| 79       IPEndPoint(dns_ip, 53), | 79       IPEndPoint(dns_ip, 53), | 
| 80       max_transactions, | 80       max_transactions, | 
| 81       max_pending_requests, | 81       max_pending_requests, | 
| 82       base::Bind(&base::RandInt), | 82       base::Bind(&base::RandInt), | 
|  | 83       HostCache::CreateDefaultCache(), | 
| 83       NULL, | 84       NULL, | 
| 84       net_log); | 85       net_log); | 
| 85   return resolver; | 86   return resolver; | 
| 86 } | 87 } | 
| 87 | 88 | 
| 88 //----------------------------------------------------------------------------- | 89 //----------------------------------------------------------------------------- | 
| 89 class AsyncHostResolver::Request { | 90 class AsyncHostResolver::Request { | 
| 90  public: | 91  public: | 
| 91   Request(const BoundNetLog& source_net_log, | 92   Request(const BoundNetLog& source_net_log, | 
| 92           const BoundNetLog& request_net_log, | 93           const BoundNetLog& request_net_log, | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 104         addresses_(addresses) { | 105         addresses_(addresses) { | 
| 105     DCHECK(addresses_); | 106     DCHECK(addresses_); | 
| 106   } | 107   } | 
| 107 | 108 | 
| 108   int id() const { return id_; } | 109   int id() const { return id_; } | 
| 109   const HostResolver::RequestInfo& info() const { return info_; } | 110   const HostResolver::RequestInfo& info() const { return info_; } | 
| 110   const Key& key() const { return key_; } | 111   const Key& key() const { return key_; } | 
| 111   RequestPriority priority() const { return info_.priority(); } | 112   RequestPriority priority() const { return info_.priority(); } | 
| 112   const BoundNetLog& source_net_log() const { return source_net_log_; } | 113   const BoundNetLog& source_net_log() const { return source_net_log_; } | 
| 113   const BoundNetLog& request_net_log() const { return request_net_log_; } | 114   const BoundNetLog& request_net_log() const { return request_net_log_; } | 
| 114   const AddressList* addresses() const { return addresses_; } | 115   void set_addresses(const AddressList& addresses) { *addresses_ = addresses; } | 
| 115 | 116 | 
| 116   void OnComplete(int result, const IPAddressList& ip_addresses) { | 117   void OnComplete(int result, const IPAddressList& ip_addresses) { | 
| 117     DCHECK(callback_); | 118     DCHECK(callback_); | 
| 118     if (result == OK) | 119     if (result == OK) | 
| 119       *addresses_ = | 120       *addresses_ = | 
| 120           AddressList::CreateFromIPAddressList(ip_addresses, info_.port()); | 121           AddressList::CreateFromIPAddressList(ip_addresses, info_.port()); | 
| 121     callback_->Run(result); | 122     callback_->Run(result); | 
| 122   } | 123   } | 
| 123 | 124 | 
| 124  private: | 125  private: | 
| 125   BoundNetLog source_net_log_; | 126   BoundNetLog source_net_log_; | 
| 126   BoundNetLog request_net_log_; | 127   BoundNetLog request_net_log_; | 
| 127   const int id_; | 128   const int id_; | 
| 128   const HostResolver::RequestInfo info_; | 129   const HostResolver::RequestInfo info_; | 
| 129   const Key key_; | 130   const Key key_; | 
| 130   CompletionCallback* callback_; | 131   CompletionCallback* callback_; | 
| 131   AddressList* addresses_; | 132   AddressList* addresses_; | 
| 132 }; | 133 }; | 
| 133 | 134 | 
| 134 //----------------------------------------------------------------------------- | 135 //----------------------------------------------------------------------------- | 
| 135 AsyncHostResolver::AsyncHostResolver(const IPEndPoint& dns_server, | 136 AsyncHostResolver::AsyncHostResolver(const IPEndPoint& dns_server, | 
| 136                                      size_t max_transactions, | 137                                      size_t max_transactions, | 
| 137                                      size_t max_pending_requests, | 138                                      size_t max_pending_requests, | 
| 138                                      const RandIntCallback& rand_int_cb, | 139                                      const RandIntCallback& rand_int_cb, | 
|  | 140                                      HostCache* cache, | 
| 139                                      ClientSocketFactory* factory, | 141                                      ClientSocketFactory* factory, | 
| 140                                      NetLog* net_log) | 142                                      NetLog* net_log) | 
| 141     : max_transactions_(max_transactions), | 143     : max_transactions_(max_transactions), | 
| 142       max_pending_requests_(max_pending_requests), | 144       max_pending_requests_(max_pending_requests), | 
| 143       dns_server_(dns_server), | 145       dns_server_(dns_server), | 
| 144       rand_int_cb_(rand_int_cb), | 146       rand_int_cb_(rand_int_cb), | 
|  | 147       cache_(cache), | 
| 145       factory_(factory), | 148       factory_(factory), | 
| 146       next_request_id_(0), | 149       next_request_id_(0), | 
| 147       net_log_(net_log) { | 150       net_log_(net_log) { | 
| 148 } | 151 } | 
| 149 | 152 | 
| 150 AsyncHostResolver::~AsyncHostResolver() { | 153 AsyncHostResolver::~AsyncHostResolver() { | 
| 151   // Destroy request lists. | 154   // Destroy request lists. | 
| 152   for (KeyRequestListMap::iterator it = requestlist_map_.begin(); | 155   for (KeyRequestListMap::iterator it = requestlist_map_.begin(); | 
| 153        it != requestlist_map_.end(); ++it) | 156        it != requestlist_map_.end(); ++it) | 
| 154     STLDeleteElements(&it->second); | 157     STLDeleteElements(&it->second); | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 169   DCHECK(addresses); | 172   DCHECK(addresses); | 
| 170   IPAddressNumber ip_number; | 173   IPAddressNumber ip_number; | 
| 171   std::string dns_name; | 174   std::string dns_name; | 
| 172   int rv = ERR_UNEXPECTED; | 175   int rv = ERR_UNEXPECTED; | 
| 173   if (info.hostname().empty()) | 176   if (info.hostname().empty()) | 
| 174     rv = ERR_NAME_NOT_RESOLVED; | 177     rv = ERR_NAME_NOT_RESOLVED; | 
| 175   else if (ParseIPLiteralToNumber(info.hostname(), &ip_number)) | 178   else if (ParseIPLiteralToNumber(info.hostname(), &ip_number)) | 
| 176     rv = ResolveAsIp(info, ip_number, addresses); | 179     rv = ResolveAsIp(info, ip_number, addresses); | 
| 177   else if (!DNSDomainFromDot(info.hostname(), &dns_name)) | 180   else if (!DNSDomainFromDot(info.hostname(), &dns_name)) | 
| 178     rv = ERR_NAME_NOT_RESOLVED; | 181     rv = ERR_NAME_NOT_RESOLVED; | 
| 179   else if (info.only_use_cached_response())  // TODO(agayev): support caching |  | 
| 180     rv = ERR_NAME_NOT_RESOLVED; |  | 
| 181 | 182 | 
| 182   Request* request = CreateNewRequest( | 183   Request* request = CreateNewRequest( | 
| 183       info, dns_name, callback, addresses, source_net_log); | 184       info, dns_name, callback, addresses, source_net_log); | 
| 184 | 185 | 
| 185   OnStart(request); | 186   OnStart(request); | 
|  | 187   if (rv == ERR_UNEXPECTED) { | 
|  | 188     if (ServeFromCache(request)) | 
|  | 189       rv = OK; | 
|  | 190     else if (info.only_use_cached_response()) | 
|  | 191       rv = ERR_NAME_NOT_RESOLVED; | 
|  | 192   } | 
|  | 193 | 
| 186   if (rv != ERR_UNEXPECTED) { | 194   if (rv != ERR_UNEXPECTED) { | 
| 187     OnFinish(request, rv); | 195     OnFinish(request, rv); | 
| 188     delete request; | 196     delete request; | 
| 189     return rv; | 197     return rv;  // Synchronous resolution ends here. | 
| 190   } | 198   } | 
| 191 | 199 | 
| 192   if (out_req) | 200   if (out_req) | 
| 193     *out_req = reinterpret_cast<RequestHandle>(request); | 201     *out_req = reinterpret_cast<RequestHandle>(request); | 
| 194 |  | 
| 195   if (AttachToRequestList(request)) | 202   if (AttachToRequestList(request)) | 
| 196     return ERR_IO_PENDING; | 203     return ERR_IO_PENDING; | 
| 197   if (transactions_.size() < max_transactions_) | 204   if (transactions_.size() < max_transactions_) | 
| 198     return StartNewTransactionFor(request); | 205     return StartNewTransactionFor(request); | 
| 199   return Enqueue(request); | 206   return Enqueue(request); | 
| 200 } | 207 } | 
| 201 | 208 | 
| 202 void AsyncHostResolver::OnStart(Request* request) { | 209 void AsyncHostResolver::OnStart(Request* request) { | 
| 203   DCHECK(request); | 210   DCHECK(request); | 
| 204 | 211 | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 278 } | 285 } | 
| 279 | 286 | 
| 280 HostResolverImpl* AsyncHostResolver::GetAsHostResolverImpl() { | 287 HostResolverImpl* AsyncHostResolver::GetAsHostResolverImpl() { | 
| 281   return NULL; | 288   return NULL; | 
| 282 } | 289 } | 
| 283 | 290 | 
| 284 void AsyncHostResolver::OnTransactionComplete( | 291 void AsyncHostResolver::OnTransactionComplete( | 
| 285     int result, | 292     int result, | 
| 286     const DnsTransaction* transaction, | 293     const DnsTransaction* transaction, | 
| 287     const IPAddressList& ip_addresses) { | 294     const IPAddressList& ip_addresses) { | 
| 288 |  | 
| 289   DCHECK(std::find(transactions_.begin(), transactions_.end(), transaction) | 295   DCHECK(std::find(transactions_.begin(), transactions_.end(), transaction) | 
| 290          != transactions_.end()); | 296          != transactions_.end()); | 
| 291   DCHECK(requestlist_map_.find(transaction->key()) != requestlist_map_.end()); | 297   DCHECK(requestlist_map_.find(transaction->key()) != requestlist_map_.end()); | 
| 292 | 298 | 
| 293   // Run callback of every request that was depending on this transaction, | 299   // Run callback of every request that was depending on this transaction, | 
| 294   // also notify observers. | 300   // also notify observers. | 
| 295   RequestList& requests = requestlist_map_[transaction->key()]; | 301   RequestList& requests = requestlist_map_[transaction->key()]; | 
| 296   for (RequestList::iterator it = requests.begin(); it != requests.end(); | 302   for (RequestList::iterator it = requests.begin(); it != requests.end(); | 
| 297        ++it) { | 303        ++it) { | 
| 298     Request* request = *it; | 304     Request* request = *it; | 
| 299     OnFinish(request, result); | 305     OnFinish(request, result); | 
| 300     request->OnComplete(result, ip_addresses); | 306     request->OnComplete(result, ip_addresses); | 
| 301   } | 307   } | 
| 302 | 308 | 
|  | 309   // It is possible that the requests that caused |transaction| to be | 
|  | 310   // created are cancelled by the time |transaction| completes.  In that | 
|  | 311   // case |requests| would be empty.  We are knowingly throwing away the | 
|  | 312   // result of a DNS resolution in that case, because (a) if there are no | 
|  | 313   // requests, we do not have info to obtain a key from, (b) DnsTransaction | 
|  | 314   // does not have info(), adding one into it just temporarily doesn't make | 
|  | 315   // sense, since HostCache will be replaced with RR cache soon, (c) | 
|  | 316   // recreating info from DnsTransaction::Key adds a lot of temporary | 
|  | 317   // code/functions (like converting back from qtype to AddressFamily.) | 
|  | 318   // Also, we only cache positive results.  All of this will change when RR | 
|  | 319   // cache is added. | 
|  | 320   if (result == OK && cache_.get() && !requests.empty()) { | 
|  | 321     Request* request = requests.front(); | 
|  | 322     HostResolver::RequestInfo info = request->info(); | 
|  | 323     HostCache::Key key( | 
|  | 324         info.hostname(), info.address_family(), info.host_resolver_flags()); | 
|  | 325     AddressList addrlist = | 
|  | 326       AddressList::CreateFromIPAddressList(ip_addresses, info.port()); | 
|  | 327     cache_->Set(key, result, addrlist, base::TimeTicks::Now()); | 
|  | 328   } | 
|  | 329 | 
| 303   // Cleanup requests. | 330   // Cleanup requests. | 
| 304   STLDeleteElements(&requests); | 331   STLDeleteElements(&requests); | 
| 305   requestlist_map_.erase(transaction->key()); | 332   requestlist_map_.erase(transaction->key()); | 
| 306 | 333 | 
| 307   // Cleanup transaction and start a new one if there are pending requests. | 334   // Cleanup transaction and start a new one if there are pending requests. | 
| 308   delete transaction; | 335   delete transaction; | 
| 309   transactions_.remove(transaction); | 336   transactions_.remove(transaction); | 
| 310   ProcessPending(); | 337   ProcessPending(); | 
| 311 } | 338 } | 
| 312 | 339 | 
|  | 340 bool AsyncHostResolver::ServeFromCache(Request* request) const { | 
|  | 341   // Sanity check -- it shouldn't be the case that allow_cached_response is | 
|  | 342   // false while only_use_cached_response is true. | 
|  | 343   DCHECK(request->info().allow_cached_response() || | 
|  | 344          !request->info().only_use_cached_response()); | 
|  | 345 | 
|  | 346   if (!cache_.get() || !request->info().allow_cached_response()) | 
|  | 347     return false; | 
|  | 348 | 
|  | 349   HostResolver::RequestInfo info = request->info(); | 
|  | 350   HostCache::Key key(info.hostname(), info.address_family(), | 
|  | 351                      info.host_resolver_flags()); | 
|  | 352   const HostCache::Entry* cache_entry = cache_->Lookup( | 
|  | 353       key, base::TimeTicks::Now()); | 
|  | 354   if (cache_entry) { | 
|  | 355     request->request_net_log().AddEvent( | 
|  | 356         NetLog::TYPE_ASYNC_HOST_RESOLVER_CACHE_HIT, NULL); | 
|  | 357     DCHECK_EQ(OK, cache_entry->error); | 
|  | 358     request->set_addresses( | 
|  | 359         CreateAddressListUsingPort(cache_entry->addrlist, info.port())); | 
|  | 360     return true; | 
|  | 361   } | 
|  | 362   return false; | 
|  | 363 } | 
|  | 364 | 
| 313 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( | 365 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( | 
| 314     const RequestInfo& info, | 366     const RequestInfo& info, | 
| 315     const std::string& dns_name, | 367     const std::string& dns_name, | 
| 316     CompletionCallback* callback, | 368     CompletionCallback* callback, | 
| 317     AddressList* addresses, | 369     AddressList* addresses, | 
| 318     const BoundNetLog& source_net_log) { | 370     const BoundNetLog& source_net_log) { | 
| 319 | 371 | 
| 320   uint16 query_type = QueryTypeFromAddressFamily(info.address_family()); | 372   uint16 query_type = QueryTypeFromAddressFamily(info.address_family()); | 
| 321   Key key(dns_name, query_type); | 373   Key key(dns_name, query_type); | 
| 322 | 374 | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 371 AsyncHostResolver::Request* AsyncHostResolver::Insert(Request* request) { | 423 AsyncHostResolver::Request* AsyncHostResolver::Insert(Request* request) { | 
| 372   pending_requests_[request->priority()].push_back(request); | 424   pending_requests_[request->priority()].push_back(request); | 
| 373   if (GetNumPending() > max_pending_requests_) { | 425   if (GetNumPending() > max_pending_requests_) { | 
| 374     Request* req = RemoveLowest(); | 426     Request* req = RemoveLowest(); | 
| 375     DCHECK(req); | 427     DCHECK(req); | 
| 376     return req; | 428     return req; | 
| 377   } | 429   } | 
| 378   return NULL; | 430   return NULL; | 
| 379 } | 431 } | 
| 380 | 432 | 
| 381 size_t AsyncHostResolver::GetNumPending() { | 433 size_t AsyncHostResolver::GetNumPending() const { | 
| 382   size_t num_pending = 0; | 434   size_t num_pending = 0; | 
| 383   for (size_t i = 0; i < arraysize(pending_requests_); ++i) | 435   for (size_t i = 0; i < arraysize(pending_requests_); ++i) | 
| 384     num_pending += pending_requests_[i].size(); | 436     num_pending += pending_requests_[i].size(); | 
| 385   return num_pending; | 437   return num_pending; | 
| 386 } | 438 } | 
| 387 | 439 | 
| 388 AsyncHostResolver::Request* AsyncHostResolver::RemoveLowest() { | 440 AsyncHostResolver::Request* AsyncHostResolver::RemoveLowest() { | 
| 389   for (int i = static_cast<int>(arraysize(pending_requests_)) - 1; | 441   for (int i = static_cast<int>(arraysize(pending_requests_)) - 1; | 
| 390        i >= 0; --i) { | 442        i >= 0; --i) { | 
| 391     RequestList& requests = pending_requests_[i]; | 443     RequestList& requests = pending_requests_[i]; | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 423         it = requests.erase(it); | 475         it = requests.erase(it); | 
| 424       } else { | 476       } else { | 
| 425         ++it; | 477         ++it; | 
| 426       } | 478       } | 
| 427     } | 479     } | 
| 428   } | 480   } | 
| 429   StartNewTransactionFor(request); | 481   StartNewTransactionFor(request); | 
| 430 } | 482 } | 
| 431 | 483 | 
| 432 }  // namespace net | 484 }  // namespace net | 
| OLD | NEW | 
|---|