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 |