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/base/host_resolver_impl.h" | 5 #include "net/base/host_resolver_impl.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <Winsock2.h> | 8 #include <Winsock2.h> |
9 #elif defined(OS_POSIX) | 9 #elif defined(OS_POSIX) |
10 #include <netdb.h> | 10 #include <netdb.h> |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 } | 198 } |
199 } else { | 199 } else { |
200 if (speculative) { | 200 if (speculative) { |
201 DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); | 201 DNS_HISTOGRAM("DNS.TotalTime_speculative", duration); |
202 } else { | 202 } else { |
203 DNS_HISTOGRAM("DNS.TotalTime", duration); | 203 DNS_HISTOGRAM("DNS.TotalTime", duration); |
204 } | 204 } |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
| 208 void RecordTTL(base::TimeDelta ttl) { |
| 209 UMA_HISTOGRAM_CUSTOM_TIMES("AsyncDNS.TTL", ttl, |
| 210 base::TimeDelta::FromSeconds(1), |
| 211 base::TimeDelta::FromDays(1), 100); |
| 212 } |
| 213 |
208 //----------------------------------------------------------------------------- | 214 //----------------------------------------------------------------------------- |
209 | 215 |
210 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. | 216 // Wraps call to SystemHostResolverProc as an instance of HostResolverProc. |
211 // TODO(szym): This should probably be declared in host_resolver_proc.h. | 217 // TODO(szym): This should probably be declared in host_resolver_proc.h. |
212 class CallSystemHostResolverProc : public HostResolverProc { | 218 class CallSystemHostResolverProc : public HostResolverProc { |
213 public: | 219 public: |
214 CallSystemHostResolverProc() : HostResolverProc(NULL) {} | 220 CallSystemHostResolverProc() : HostResolverProc(NULL) {} |
215 virtual int Resolve(const std::string& hostname, | 221 virtual int Resolve(const std::string& hostname, |
216 AddressFamily address_family, | 222 AddressFamily address_family, |
217 HostResolverFlags host_resolver_flags, | 223 HostResolverFlags host_resolver_flags, |
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 base::Bind(&NetLogJobAttachCallback, | 1330 base::Bind(&NetLogJobAttachCallback, |
1325 req->request_net_log().source(), | 1331 req->request_net_log().source(), |
1326 priority())); | 1332 priority())); |
1327 | 1333 |
1328 if (num_active_requests() > 0) { | 1334 if (num_active_requests() > 0) { |
1329 UpdatePriority(); | 1335 UpdatePriority(); |
1330 } else { | 1336 } else { |
1331 // If we were called from a Request's callback within CompleteRequests, | 1337 // If we were called from a Request's callback within CompleteRequests, |
1332 // that Request could not have been cancelled, so num_active_requests() | 1338 // that Request could not have been cancelled, so num_active_requests() |
1333 // could not be 0. Therefore, we are not in CompleteRequests(). | 1339 // could not be 0. Therefore, we are not in CompleteRequests(). |
1334 CompleteRequests(OK, AddressList(), base::TimeDelta()); | 1340 CompleteRequestsWithError(OK /* cancelled */); |
1335 } | 1341 } |
1336 } | 1342 } |
1337 | 1343 |
1338 // Called from AbortAllInProgressJobs. Completes all requests as aborted | 1344 // Called from AbortAllInProgressJobs. Completes all requests as aborted |
1339 // and destroys the job. | 1345 // and destroys the job. |
1340 void Abort() { | 1346 void Abort() { |
1341 DCHECK(is_running()); | 1347 DCHECK(is_running()); |
1342 CompleteRequests(ERR_ABORTED, AddressList(), base::TimeDelta()); | 1348 CompleteRequestsWithError(ERR_ABORTED); |
1343 } | 1349 } |
1344 | 1350 |
1345 // Called by HostResolverImpl when this job is evicted due to queue overflow. | 1351 // Called by HostResolverImpl when this job is evicted due to queue overflow. |
1346 // Completes all requests and destroys the job. | 1352 // Completes all requests and destroys the job. |
1347 void OnEvicted() { | 1353 void OnEvicted() { |
1348 DCHECK(!is_running()); | 1354 DCHECK(!is_running()); |
1349 DCHECK(is_queued()); | 1355 DCHECK(is_queued()); |
1350 handle_.Reset(); | 1356 handle_.Reset(); |
1351 | 1357 |
1352 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); | 1358 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED); |
1353 | 1359 |
1354 // This signals to CompleteRequests that this job never ran. | 1360 // This signals to CompleteRequests that this job never ran. |
1355 CompleteRequests(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, | 1361 CompleteRequestsWithError(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); |
1356 AddressList(), | |
1357 base::TimeDelta()); | |
1358 } | 1362 } |
1359 | 1363 |
1360 // Attempts to serve the job from HOSTS. Returns true if succeeded and | 1364 // Attempts to serve the job from HOSTS. Returns true if succeeded and |
1361 // this Job was destroyed. | 1365 // this Job was destroyed. |
1362 bool ServeFromHosts() { | 1366 bool ServeFromHosts() { |
1363 DCHECK_GT(num_active_requests(), 0u); | 1367 DCHECK_GT(num_active_requests(), 0u); |
1364 AddressList addr_list; | 1368 AddressList addr_list; |
1365 if (resolver_->ServeFromHosts(key(), | 1369 if (resolver_->ServeFromHosts(key(), |
1366 requests_.front()->info(), | 1370 requests_.front()->info(), |
1367 &addr_list)) { | 1371 &addr_list)) { |
1368 // This will destroy the Job. | 1372 // This will destroy the Job. |
1369 CompleteRequests(OK, addr_list, base::TimeDelta()); | 1373 CompleteRequests(OK, addr_list, base::TimeDelta(), false /* true_ttl */); |
1370 return true; | 1374 return true; |
1371 } | 1375 } |
1372 return false; | 1376 return false; |
1373 } | 1377 } |
1374 | 1378 |
1375 const Key key() const { | 1379 const Key key() const { |
1376 return key_; | 1380 return key_; |
1377 } | 1381 } |
1378 | 1382 |
1379 bool is_queued() const { | 1383 bool is_queued() const { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); | 1461 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_PROC_SUCCESS); |
1458 } | 1462 } |
1459 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", | 1463 UMA_HISTOGRAM_CUSTOM_ENUMERATION("AsyncDNS.ResolveError", |
1460 std::abs(dns_task_error_), | 1464 std::abs(dns_task_error_), |
1461 GetAllErrorCodesForUma()); | 1465 GetAllErrorCodesForUma()); |
1462 } else { | 1466 } else { |
1463 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); | 1467 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL); |
1464 } | 1468 } |
1465 } | 1469 } |
1466 | 1470 |
1467 base::TimeDelta ttl = base::TimeDelta::FromSeconds( | 1471 base::TimeDelta ttl = |
1468 kNegativeCacheEntryTTLSeconds); | 1472 base::TimeDelta::FromSeconds(kNegativeCacheEntryTTLSeconds); |
1469 if (net_error == OK) | 1473 if (net_error == OK) |
1470 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | 1474 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
1471 | 1475 |
1472 CompleteRequests(net_error, addr_list, ttl); | 1476 CompleteRequests(net_error, addr_list, ttl, false /* true_ttl */); |
1473 } | 1477 } |
1474 | 1478 |
1475 void StartDnsTask() { | 1479 void StartDnsTask() { |
1476 DCHECK(resolver_->HaveDnsConfig()); | 1480 DCHECK(resolver_->HaveDnsConfig()); |
1477 dns_task_.reset(new DnsTask( | 1481 dns_task_.reset(new DnsTask( |
1478 resolver_->dns_client_.get(), | 1482 resolver_->dns_client_.get(), |
1479 key_, | 1483 key_, |
1480 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), | 1484 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), |
1481 net_log_)); | 1485 net_log_)); |
1482 | 1486 |
(...skipping 19 matching lines...) Expand all Loading... |
1502 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. | 1506 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. |
1503 // http://crbug.com/117655 | 1507 // http://crbug.com/117655 |
1504 | 1508 |
1505 // TODO(szym): Some net errors indicate lack of connectivity. Starting | 1509 // TODO(szym): Some net errors indicate lack of connectivity. Starting |
1506 // ProcTask in that case is a waste of time. | 1510 // ProcTask in that case is a waste of time. |
1507 StartProcTask(); | 1511 StartProcTask(); |
1508 return; | 1512 return; |
1509 } | 1513 } |
1510 | 1514 |
1511 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); | 1515 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); |
| 1516 RecordTTL(ttl); |
1512 | 1517 |
1513 CompleteRequests(net_error, addr_list, ttl); | 1518 CompleteRequests(net_error, addr_list, ttl, true /* true_ttl */); |
1514 } | 1519 } |
1515 | 1520 |
1516 // Performs Job's last rites. Completes all Requests. Deletes this. | 1521 // Performs Job's last rites. Completes all Requests. Deletes this. |
1517 void CompleteRequests(int net_error, | 1522 void CompleteRequests(int net_error, |
1518 const AddressList& addr_list, | 1523 const AddressList& addr_list, |
1519 base::TimeDelta ttl) { | 1524 base::TimeDelta ttl, |
| 1525 bool true_ttl) { |
1520 CHECK(resolver_); | 1526 CHECK(resolver_); |
1521 | 1527 |
1522 // This job must be removed from resolver's |jobs_| now to make room for a | 1528 // This job must be removed from resolver's |jobs_| now to make room for a |
1523 // new job with the same key in case one of the OnComplete callbacks decides | 1529 // new job with the same key in case one of the OnComplete callbacks decides |
1524 // to spawn one. Consequently, the job deletes itself when CompleteRequests | 1530 // to spawn one. Consequently, the job deletes itself when CompleteRequests |
1525 // is done. | 1531 // is done. |
1526 scoped_ptr<Job> self_deleter(this); | 1532 scoped_ptr<Job> self_deleter(this); |
1527 | 1533 |
1528 resolver_->RemoveJob(this); | 1534 resolver_->RemoveJob(this); |
1529 | 1535 |
1530 // |addr_list| will be destroyed once we destroy |proc_task_| and | 1536 // |addr_list| will be destroyed with |proc_task_| and |dns_task_|. |
1531 // |dns_task_|. | |
1532 AddressList list = addr_list; | 1537 AddressList list = addr_list; |
1533 | 1538 |
1534 if (is_running()) { | 1539 if (is_running()) { |
1535 DCHECK(!is_queued()); | 1540 DCHECK(!is_queued()); |
1536 if (is_proc_running()) { | 1541 if (is_proc_running()) { |
1537 proc_task_->Cancel(); | 1542 proc_task_->Cancel(); |
1538 proc_task_ = NULL; | 1543 proc_task_ = NULL; |
1539 } | 1544 } |
1540 dns_task_.reset(); | 1545 dns_task_.reset(); |
1541 | 1546 |
(...skipping 19 matching lines...) Expand all Loading... |
1561 if (net_error == OK) { | 1566 if (net_error == OK) { |
1562 SetPortOnAddressList(requests_.front()->info().port(), &list); | 1567 SetPortOnAddressList(requests_.front()->info().port(), &list); |
1563 // Record this histogram here, when we know the system has a valid DNS | 1568 // Record this histogram here, when we know the system has a valid DNS |
1564 // configuration. | 1569 // configuration. |
1565 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", | 1570 UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig", |
1566 resolver_->received_dns_config_); | 1571 resolver_->received_dns_config_); |
1567 } | 1572 } |
1568 | 1573 |
1569 bool did_complete = (net_error != ERR_ABORTED) && | 1574 bool did_complete = (net_error != ERR_ABORTED) && |
1570 (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); | 1575 (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE); |
1571 if (did_complete) | 1576 if (did_complete) { |
1572 resolver_->CacheResult(key_, net_error, list, ttl); | 1577 HostCache::Entry entry = true_ttl ? |
| 1578 HostCache::Entry(net_error, list, ttl) : |
| 1579 HostCache::Entry(net_error, list); |
| 1580 resolver_->CacheResult(key_, entry, ttl); |
| 1581 } |
1573 | 1582 |
1574 // Complete all of the requests that were attached to the job. | 1583 // Complete all of the requests that were attached to the job. |
1575 for (RequestsList::const_iterator it = requests_.begin(); | 1584 for (RequestsList::const_iterator it = requests_.begin(); |
1576 it != requests_.end(); ++it) { | 1585 it != requests_.end(); ++it) { |
1577 Request* req = *it; | 1586 Request* req = *it; |
1578 | 1587 |
1579 if (req->was_canceled()) | 1588 if (req->was_canceled()) |
1580 continue; | 1589 continue; |
1581 | 1590 |
1582 DCHECK_EQ(this, req->job()); | 1591 DCHECK_EQ(this, req->job()); |
1583 // Update the net log and notify registered observers. | 1592 // Update the net log and notify registered observers. |
1584 LogFinishRequest(req->source_net_log(), req->request_net_log(), | 1593 LogFinishRequest(req->source_net_log(), req->request_net_log(), |
1585 req->info(), net_error); | 1594 req->info(), net_error); |
1586 if (did_complete) { | 1595 if (did_complete) { |
1587 // Record effective total time from creation to completion. | 1596 // Record effective total time from creation to completion. |
1588 RecordTotalTime(had_dns_config_, req->info().is_speculative(), | 1597 RecordTotalTime(had_dns_config_, req->info().is_speculative(), |
1589 base::TimeTicks::Now() - req->request_time()); | 1598 base::TimeTicks::Now() - req->request_time()); |
1590 } | 1599 } |
1591 req->OnComplete(net_error, list); | 1600 req->OnComplete(net_error, list); |
1592 | 1601 |
1593 // Check if the resolver was destroyed as a result of running the | 1602 // Check if the resolver was destroyed as a result of running the |
1594 // callback. If it was, we could continue, but we choose to bail. | 1603 // callback. If it was, we could continue, but we choose to bail. |
1595 if (!resolver_) | 1604 if (!resolver_) |
1596 return; | 1605 return; |
1597 } | 1606 } |
1598 } | 1607 } |
1599 | 1608 |
| 1609 // Convenience wrapper for CompleteRequests in case of failure. |
| 1610 void CompleteRequestsWithError(int net_error) { |
| 1611 CompleteRequests(net_error, AddressList(), base::TimeDelta(), false); |
| 1612 } |
| 1613 |
1600 RequestPriority priority() const { | 1614 RequestPriority priority() const { |
1601 return priority_tracker_.highest_priority(); | 1615 return priority_tracker_.highest_priority(); |
1602 } | 1616 } |
1603 | 1617 |
1604 // Number of non-canceled requests in |requests_|. | 1618 // Number of non-canceled requests in |requests_|. |
1605 size_t num_active_requests() const { | 1619 size_t num_active_requests() const { |
1606 return priority_tracker_.total_count(); | 1620 return priority_tracker_.total_count(); |
1607 } | 1621 } |
1608 | 1622 |
1609 bool is_dns_running() const { | 1623 bool is_dns_running() const { |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 if (!info.allow_cached_response() || !cache_.get()) | 1965 if (!info.allow_cached_response() || !cache_.get()) |
1952 return false; | 1966 return false; |
1953 | 1967 |
1954 const HostCache::Entry* cache_entry = cache_->Lookup( | 1968 const HostCache::Entry* cache_entry = cache_->Lookup( |
1955 key, base::TimeTicks::Now()); | 1969 key, base::TimeTicks::Now()); |
1956 if (!cache_entry) | 1970 if (!cache_entry) |
1957 return false; | 1971 return false; |
1958 | 1972 |
1959 *net_error = cache_entry->error; | 1973 *net_error = cache_entry->error; |
1960 if (*net_error == OK) { | 1974 if (*net_error == OK) { |
| 1975 if (cache_entry->has_ttl()) |
| 1976 RecordTTL(cache_entry->ttl); |
1961 *addresses = cache_entry->addrlist; | 1977 *addresses = cache_entry->addrlist; |
1962 EnsurePortOnAddressList(info.port(), addresses); | 1978 EnsurePortOnAddressList(info.port(), addresses); |
1963 } | 1979 } |
1964 return true; | 1980 return true; |
1965 } | 1981 } |
1966 | 1982 |
1967 bool HostResolverImpl::ServeFromHosts(const Key& key, | 1983 bool HostResolverImpl::ServeFromHosts(const Key& key, |
1968 const RequestInfo& info, | 1984 const RequestInfo& info, |
1969 AddressList* addresses) { | 1985 AddressList* addresses) { |
1970 DCHECK(addresses); | 1986 DCHECK(addresses); |
(...skipping 20 matching lines...) Expand all Loading... |
1991 it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); | 2007 it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); |
1992 if (it == hosts.end()) | 2008 if (it == hosts.end()) |
1993 return false; | 2009 return false; |
1994 } | 2010 } |
1995 | 2011 |
1996 *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); | 2012 *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); |
1997 return true; | 2013 return true; |
1998 } | 2014 } |
1999 | 2015 |
2000 void HostResolverImpl::CacheResult(const Key& key, | 2016 void HostResolverImpl::CacheResult(const Key& key, |
2001 int net_error, | 2017 const HostCache::Entry& entry, |
2002 const AddressList& addr_list, | |
2003 base::TimeDelta ttl) { | 2018 base::TimeDelta ttl) { |
2004 if (cache_.get()) | 2019 if (cache_.get()) |
2005 cache_->Set(key, net_error, addr_list, base::TimeTicks::Now(), ttl); | 2020 cache_->Set(key, entry, base::TimeTicks::Now(), ttl); |
2006 } | 2021 } |
2007 | 2022 |
2008 void HostResolverImpl::RemoveJob(Job* job) { | 2023 void HostResolverImpl::RemoveJob(Job* job) { |
2009 DCHECK(job); | 2024 DCHECK(job); |
2010 JobMap::iterator it = jobs_.find(job->key()); | 2025 JobMap::iterator it = jobs_.find(job->key()); |
2011 if (it != jobs_.end() && it->second == job) | 2026 if (it != jobs_.end() && it->second == job) |
2012 jobs_.erase(it); | 2027 jobs_.erase(it); |
2013 } | 2028 } |
2014 | 2029 |
2015 void HostResolverImpl::DiscardIPv6ProbeJob() { | 2030 void HostResolverImpl::DiscardIPv6ProbeJob() { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2146 // |this| may be deleted inside AbortAllInProgressJobs(). | 2161 // |this| may be deleted inside AbortAllInProgressJobs(). |
2147 if (self) | 2162 if (self) |
2148 TryServingAllJobsFromHosts(); | 2163 TryServingAllJobsFromHosts(); |
2149 } | 2164 } |
2150 | 2165 |
2151 bool HostResolverImpl::HaveDnsConfig() const { | 2166 bool HostResolverImpl::HaveDnsConfig() const { |
2152 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); | 2167 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); |
2153 } | 2168 } |
2154 | 2169 |
2155 } // namespace net | 2170 } // namespace net |
OLD | NEW |