| 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 |