Chromium Code Reviews| 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 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1198 handle_.Reset(); | 1198 handle_.Reset(); |
| 1199 | 1199 |
| 1200 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); | 1200 net_log_.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB_EVICTED, NULL); |
| 1201 | 1201 |
| 1202 // This signals to CompleteRequests that this job never ran. | 1202 // This signals to CompleteRequests that this job never ran. |
| 1203 CompleteRequests(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, | 1203 CompleteRequests(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, |
| 1204 AddressList(), | 1204 AddressList(), |
| 1205 base::TimeDelta()); | 1205 base::TimeDelta()); |
| 1206 } | 1206 } |
| 1207 | 1207 |
| 1208 // Attempt to serve the job from hosts. | |
| 1209 void ServeFromHosts() { | |
|
szym
2012/03/10 06:48:49
Add a bool return so that the caller knows if this
| |
| 1210 DCHECK_GT(num_active_requests(), 0u); | |
| 1211 AddressList addr_list; | |
| 1212 if (resolver_->ServeFromHosts(key(), | |
| 1213 requests_.front()->info(), | |
| 1214 &addr_list)) { | |
| 1215 CompleteRequests(OK, addr_list, base::TimeDelta()); | |
| 1216 } | |
| 1217 } | |
| 1218 | |
| 1208 private: | 1219 private: |
| 1209 RequestPriority priority() const { | 1220 RequestPriority priority() const { |
| 1210 return priority_tracker_.highest_priority(); | 1221 return priority_tracker_.highest_priority(); |
| 1211 } | 1222 } |
| 1212 | 1223 |
| 1213 // Number of non-canceled requests in |requests_|. | 1224 // Number of non-canceled requests in |requests_|. |
| 1214 size_t num_active_requests() const { | 1225 size_t num_active_requests() const { |
| 1215 return priority_tracker_.total_count(); | 1226 return priority_tracker_.total_count(); |
| 1216 } | 1227 } |
| 1217 | 1228 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1285 } | 1296 } |
| 1286 | 1297 |
| 1287 // Called by DnsTask when it completes. | 1298 // Called by DnsTask when it completes. |
| 1288 void OnDnsTaskComplete(int net_error, | 1299 void OnDnsTaskComplete(int net_error, |
| 1289 const AddressList& addr_list, | 1300 const AddressList& addr_list, |
| 1290 base::TimeDelta ttl) { | 1301 base::TimeDelta ttl) { |
| 1291 DCHECK(is_dns_running()); | 1302 DCHECK(is_dns_running()); |
| 1292 | 1303 |
| 1293 if (net_error != OK) { | 1304 if (net_error != OK) { |
| 1294 dns_task_.reset(); | 1305 dns_task_.reset(); |
| 1306 | |
| 1307 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. | |
| 1308 // http://crbug.com/117655 | |
| 1309 | |
| 1295 // TODO(szym): Some net errors indicate lack of connectivity. Starting | 1310 // TODO(szym): Some net errors indicate lack of connectivity. Starting |
| 1296 // ProcTask in that case is a waste of time. | 1311 // ProcTask in that case is a waste of time. |
| 1297 StartProcTask(); | 1312 StartProcTask(); |
| 1298 return; | 1313 return; |
| 1299 } | 1314 } |
| 1300 | 1315 |
| 1301 CompleteRequests(net_error, addr_list, ttl); | 1316 CompleteRequests(net_error, addr_list, ttl); |
| 1302 } | 1317 } |
| 1303 | 1318 |
| 1304 // Performs Job's last rites. Completes all Requests. Deletes this. | 1319 // Performs Job's last rites. Completes all Requests. Deletes this. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1337 if (num_active_requests() == 0) { | 1352 if (num_active_requests() == 0) { |
| 1338 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 1353 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
| 1339 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1354 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 1340 OK); | 1355 OK); |
| 1341 return; | 1356 return; |
| 1342 } | 1357 } |
| 1343 | 1358 |
| 1344 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, | 1359 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, |
| 1345 net_error); | 1360 net_error); |
| 1346 | 1361 |
| 1362 DCHECK(!requests_.empty()); | |
| 1363 | |
| 1347 // We are the only consumer of |list|, so we can safely change the port | 1364 // We are the only consumer of |list|, so we can safely change the port |
| 1348 // without copy-on-write. This pays off, when job has only one request. | 1365 // without copy-on-write. This pays off, when job has only one request. |
| 1349 if (net_error == OK && !requests_.empty()) | 1366 if (net_error == OK) |
| 1350 MutableSetPort(requests_.front()->info().port(), &list); | 1367 MutableSetPort(requests_.front()->info().port(), &list); |
| 1351 | 1368 |
| 1352 if ((net_error != ERR_ABORTED) && | 1369 if ((net_error != ERR_ABORTED) && |
| 1353 (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE)) { | 1370 (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE)) { |
| 1354 resolver_->CacheResult(key_, net_error, list, ttl); | 1371 resolver_->CacheResult(key_, net_error, list, ttl); |
| 1355 } | 1372 } |
| 1356 | 1373 |
| 1357 // Complete all of the requests that were attached to the job. | 1374 // Complete all of the requests that were attached to the job. |
| 1358 for (RequestsList::const_iterator it = requests_.begin(); | 1375 for (RequestsList::const_iterator it = requests_.begin(); |
| 1359 it != requests_.end(); ++it) { | 1376 it != requests_.end(); ++it) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1545 const BoundNetLog& request_net_log) { | 1562 const BoundNetLog& request_net_log) { |
| 1546 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. | 1563 // The result of |getaddrinfo| for empty hosts is inconsistent across systems. |
| 1547 // On Windows it gives the default interface's address, whereas on Linux it | 1564 // On Windows it gives the default interface's address, whereas on Linux it |
| 1548 // gives an error. We will make it fail on all platforms for consistency. | 1565 // gives an error. We will make it fail on all platforms for consistency. |
| 1549 if (info.hostname().empty() || info.hostname().size() > kMaxHostLength) | 1566 if (info.hostname().empty() || info.hostname().size() > kMaxHostLength) |
| 1550 return ERR_NAME_NOT_RESOLVED; | 1567 return ERR_NAME_NOT_RESOLVED; |
| 1551 | 1568 |
| 1552 int net_error = ERR_UNEXPECTED; | 1569 int net_error = ERR_UNEXPECTED; |
| 1553 if (ResolveAsIP(key, info, &net_error, addresses)) | 1570 if (ResolveAsIP(key, info, &net_error, addresses)) |
| 1554 return net_error; | 1571 return net_error; |
| 1555 net_error = ERR_DNS_CACHE_MISS; | 1572 if (ServeFromCache(key, info, &net_error, addresses)) { |
| 1556 ServeFromCache(key, info, request_net_log, &net_error, addresses); | 1573 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); |
| 1557 return net_error; | 1574 return net_error; |
| 1575 } | |
| 1576 // TODO(szym): Do not do this if nsswitch.conf instructs not to. | |
| 1577 // http://crbug.com/117655 | |
| 1578 if (ServeFromHosts(key, info, addresses)) { | |
| 1579 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_HOSTS_HIT, NULL); | |
| 1580 return OK; | |
| 1581 } | |
| 1582 return ERR_DNS_CACHE_MISS; | |
| 1558 } | 1583 } |
| 1559 | 1584 |
| 1560 int HostResolverImpl::ResolveFromCache(const RequestInfo& info, | 1585 int HostResolverImpl::ResolveFromCache(const RequestInfo& info, |
| 1561 AddressList* addresses, | 1586 AddressList* addresses, |
| 1562 const BoundNetLog& source_net_log) { | 1587 const BoundNetLog& source_net_log) { |
| 1563 DCHECK(CalledOnValidThread()); | 1588 DCHECK(CalledOnValidThread()); |
| 1564 DCHECK(addresses); | 1589 DCHECK(addresses); |
| 1565 | 1590 |
| 1566 // Make a log item for the request. | 1591 // Make a log item for the request. |
| 1567 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, | 1592 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1630 } else { | 1655 } else { |
| 1631 *addresses = AddressList::CreateFromIPAddressWithCname( | 1656 *addresses = AddressList::CreateFromIPAddressWithCname( |
| 1632 ip_number, info.port(), | 1657 ip_number, info.port(), |
| 1633 (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)); | 1658 (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)); |
| 1634 } | 1659 } |
| 1635 return true; | 1660 return true; |
| 1636 } | 1661 } |
| 1637 | 1662 |
| 1638 bool HostResolverImpl::ServeFromCache(const Key& key, | 1663 bool HostResolverImpl::ServeFromCache(const Key& key, |
| 1639 const RequestInfo& info, | 1664 const RequestInfo& info, |
| 1640 const BoundNetLog& request_net_log, | |
| 1641 int* net_error, | 1665 int* net_error, |
| 1642 AddressList* addresses) { | 1666 AddressList* addresses) { |
| 1643 DCHECK(addresses); | 1667 DCHECK(addresses); |
| 1644 DCHECK(net_error); | 1668 DCHECK(net_error); |
| 1645 if (!info.allow_cached_response() || !cache_.get()) | 1669 if (!info.allow_cached_response() || !cache_.get()) |
| 1646 return false; | 1670 return false; |
| 1647 | 1671 |
| 1648 const HostCache::Entry* cache_entry = cache_->Lookup( | 1672 const HostCache::Entry* cache_entry = cache_->Lookup( |
| 1649 key, base::TimeTicks::Now()); | 1673 key, base::TimeTicks::Now()); |
| 1650 if (!cache_entry) | 1674 if (!cache_entry) |
| 1651 return false; | 1675 return false; |
| 1652 | 1676 |
| 1653 request_net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_CACHE_HIT, NULL); | 1677 |
| 1654 *net_error = cache_entry->error; | 1678 *net_error = cache_entry->error; |
| 1655 if (*net_error == OK) | 1679 if (*net_error == OK) |
| 1656 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); | 1680 *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); |
| 1657 return true; | 1681 return true; |
| 1658 } | 1682 } |
| 1659 | 1683 |
| 1684 bool HostResolverImpl::ServeFromHosts(const Key& key, | |
| 1685 const RequestInfo& info, | |
| 1686 AddressList* addresses) { | |
| 1687 DCHECK(addresses); | |
| 1688 if (!dns_session_) | |
| 1689 return false; | |
| 1690 | |
| 1691 const DnsHosts& hosts = dns_session_->config().hosts; | |
| 1692 DnsHosts::const_iterator it = hosts.find(DnsHostsKey(key.hostname, | |
| 1693 key.address_family)); | |
| 1694 if (it == hosts.end()) | |
| 1695 return false; | |
| 1696 | |
| 1697 *addresses = AddressList::CreateFromIPAddress(it->second, info.port()); | |
| 1698 return true; | |
| 1699 } | |
| 1700 | |
| 1660 void HostResolverImpl::CacheResult(const Key& key, | 1701 void HostResolverImpl::CacheResult(const Key& key, |
| 1661 int net_error, | 1702 int net_error, |
| 1662 const AddressList& addr_list, | 1703 const AddressList& addr_list, |
| 1663 base::TimeDelta ttl) { | 1704 base::TimeDelta ttl) { |
| 1664 if (cache_.get()) | 1705 if (cache_.get()) |
| 1665 cache_->Set(key, net_error, addr_list, base::TimeTicks::Now(), ttl); | 1706 cache_->Set(key, net_error, addr_list, base::TimeTicks::Now(), ttl); |
| 1666 } | 1707 } |
| 1667 | 1708 |
| 1668 void HostResolverImpl::RemoveJob(Job* job) { | 1709 void HostResolverImpl::RemoveJob(Job* job) { |
| 1669 DCHECK(job); | 1710 DCHECK(job); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1727 | 1768 |
| 1728 // Life check to bail once |this| is deleted. | 1769 // Life check to bail once |this| is deleted. |
| 1729 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); | 1770 base::WeakPtr<HostResolverImpl> self = AsWeakPtr(); |
| 1730 | 1771 |
| 1731 // Then Abort them. | 1772 // Then Abort them. |
| 1732 for (size_t i = 0; self && i < jobs_to_abort.size(); ++i) { | 1773 for (size_t i = 0; self && i < jobs_to_abort.size(); ++i) { |
| 1733 jobs_to_abort[i]->Abort(); | 1774 jobs_to_abort[i]->Abort(); |
| 1734 } | 1775 } |
| 1735 } | 1776 } |
| 1736 | 1777 |
| 1778 void HostResolverImpl::TryServingAllJobsFromHosts() { | |
| 1779 if (!dns_session_) | |
| 1780 return; | |
| 1781 | |
| 1782 // TODO(szym): Do not do this if nsswitch.conf instructs not to. | |
| 1783 // http://crbug.com/117655 | |
| 1784 | |
| 1785 for (JobMap::iterator it = jobs_.begin(); it != jobs_.end(); ) { | |
| 1786 Job* job = (it++)->second; | |
| 1787 // This could remove |job| from |jobs_|, but iterators remain valid. | |
| 1788 job->ServeFromHosts(); | |
|
szym
2012/03/10 06:48:49
HostResolverImpl could be destroyed in Request cal
| |
| 1789 } | |
| 1790 } | |
| 1791 | |
| 1737 void HostResolverImpl::OnIPAddressChanged() { | 1792 void HostResolverImpl::OnIPAddressChanged() { |
| 1738 if (cache_.get()) | 1793 if (cache_.get()) |
| 1739 cache_->clear(); | 1794 cache_->clear(); |
| 1740 if (ipv6_probe_monitoring_) { | 1795 if (ipv6_probe_monitoring_) { |
| 1741 DiscardIPv6ProbeJob(); | 1796 DiscardIPv6ProbeJob(); |
| 1742 ipv6_probe_job_ = new IPv6ProbeJob(this); | 1797 ipv6_probe_job_ = new IPv6ProbeJob(this); |
| 1743 ipv6_probe_job_->Start(); | 1798 ipv6_probe_job_->Start(); |
| 1744 } | 1799 } |
| 1745 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 1800 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 1746 if (HaveOnlyLoopbackAddresses()) { | 1801 if (HaveOnlyLoopbackAddresses()) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1764 // be aborted. TODO(Craig): Should these jobs be restarted? | 1819 // be aborted. TODO(Craig): Should these jobs be restarted? |
| 1765 AbortAllInProgressJobs(); | 1820 AbortAllInProgressJobs(); |
| 1766 // |this| may be deleted inside AbortAllInProgressJobs(). | 1821 // |this| may be deleted inside AbortAllInProgressJobs(). |
| 1767 } | 1822 } |
| 1768 | 1823 |
| 1769 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { | 1824 void HostResolverImpl::OnConfigChanged(const DnsConfig& dns_config) { |
| 1770 // We want a new factory in place, before we Abort running Jobs, so that the | 1825 // We want a new factory in place, before we Abort running Jobs, so that the |
| 1771 // newly started jobs use the new factory. | 1826 // newly started jobs use the new factory. |
| 1772 bool had_factory = (dns_transaction_factory_.get() != NULL); | 1827 bool had_factory = (dns_transaction_factory_.get() != NULL); |
| 1773 if (dns_config.IsValid()) { | 1828 if (dns_config.IsValid()) { |
| 1774 dns_transaction_factory_ = DnsTransactionFactory::CreateFactory( | 1829 dns_session_ = new DnsSession(dns_config, |
| 1775 new DnsSession(dns_config, | 1830 ClientSocketFactory::GetDefaultFactory(), |
| 1776 ClientSocketFactory::GetDefaultFactory(), | 1831 base::Bind(&base::RandInt), |
| 1777 base::Bind(&base::RandInt), | 1832 net_log_); |
| 1778 net_log_)); | 1833 dns_transaction_factory_ = |
| 1834 DnsTransactionFactory::CreateFactory(dns_session_); | |
| 1835 | |
| 1836 TryServingAllJobsFromHosts(); | |
| 1779 } else { | 1837 } else { |
| 1780 dns_transaction_factory_.reset(); | 1838 dns_transaction_factory_.reset(); |
| 1839 dns_session_.release(); | |
| 1781 } | 1840 } |
| 1782 // Don't Abort running Jobs unless they were running on DnsTransaction. | 1841 // Don't Abort running Jobs unless they were running on DnsTransaction. |
| 1783 // TODO(szym): This will change once http://crbug.com/114827 is fixed. | 1842 // TODO(szym): This will change once http://crbug.com/114827 is fixed. |
| 1784 if (had_factory) | 1843 if (had_factory) |
| 1785 OnDNSChanged(NetworkChangeNotifier::CHANGE_DNS_SETTINGS); | 1844 OnDNSChanged(NetworkChangeNotifier::CHANGE_DNS_SETTINGS); |
| 1786 } | 1845 } |
| 1787 | 1846 |
| 1788 } // namespace net | 1847 } // namespace net |
| OLD | NEW |