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 20 matching lines...) Expand all Loading... |
31 #include "base/utf_string_conversions.h" | 31 #include "base/utf_string_conversions.h" |
32 #include "base/values.h" | 32 #include "base/values.h" |
33 #include "net/base/address_family.h" | 33 #include "net/base/address_family.h" |
34 #include "net/base/address_list.h" | 34 #include "net/base/address_list.h" |
35 #include "net/base/dns_reloader.h" | 35 #include "net/base/dns_reloader.h" |
36 #include "net/base/host_port_pair.h" | 36 #include "net/base/host_port_pair.h" |
37 #include "net/base/host_resolver_proc.h" | 37 #include "net/base/host_resolver_proc.h" |
38 #include "net/base/net_errors.h" | 38 #include "net/base/net_errors.h" |
39 #include "net/base/net_log.h" | 39 #include "net/base/net_log.h" |
40 #include "net/base/net_util.h" | 40 #include "net/base/net_util.h" |
| 41 #include "net/dns/address_sorter.h" |
41 #include "net/dns/dns_client.h" | 42 #include "net/dns/dns_client.h" |
42 #include "net/dns/dns_config_service.h" | 43 #include "net/dns/dns_config_service.h" |
43 #include "net/dns/dns_protocol.h" | 44 #include "net/dns/dns_protocol.h" |
44 #include "net/dns/dns_response.h" | 45 #include "net/dns/dns_response.h" |
45 #include "net/dns/dns_transaction.h" | 46 #include "net/dns/dns_transaction.h" |
46 | 47 |
47 #if defined(OS_WIN) | 48 #if defined(OS_WIN) |
48 #include "net/base/winsock_init.h" | 49 #include "net/base/winsock_init.h" |
49 #endif | 50 #endif |
50 | 51 |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); | 603 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); |
603 StartLookupAttempt(); | 604 StartLookupAttempt(); |
604 } | 605 } |
605 | 606 |
606 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve | 607 // Cancels this ProcTask. It will be orphaned. Any outstanding resolve |
607 // attempts running on worker threads will continue running. Only once all the | 608 // attempts running on worker threads will continue running. Only once all the |
608 // attempts complete will the final reference to this ProcTask be released. | 609 // attempts complete will the final reference to this ProcTask be released. |
609 void Cancel() { | 610 void Cancel() { |
610 DCHECK(origin_loop_->BelongsToCurrentThread()); | 611 DCHECK(origin_loop_->BelongsToCurrentThread()); |
611 | 612 |
612 if (was_canceled()) | 613 if (was_canceled() || was_completed()) |
613 return; | 614 return; |
614 | 615 |
615 callback_.Reset(); | 616 callback_.Reset(); |
616 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); | 617 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); |
617 } | 618 } |
618 | 619 |
619 void set_had_non_speculative_request() { | 620 void set_had_non_speculative_request() { |
620 DCHECK(origin_loop_->BelongsToCurrentThread()); | 621 DCHECK(origin_loop_->BelongsToCurrentThread()); |
621 had_non_speculative_request_ = true; | 622 had_non_speculative_request_ = true; |
622 } | 623 } |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 | 1036 |
1036 BoundNetLog net_log_; | 1037 BoundNetLog net_log_; |
1037 | 1038 |
1038 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); | 1039 DISALLOW_COPY_AND_ASSIGN(IPv6ProbeJob); |
1039 }; | 1040 }; |
1040 | 1041 |
1041 //----------------------------------------------------------------------------- | 1042 //----------------------------------------------------------------------------- |
1042 | 1043 |
1043 // Resolves the hostname using DnsTransaction. | 1044 // Resolves the hostname using DnsTransaction. |
1044 // TODO(szym): This could be moved to separate source file as well. | 1045 // TODO(szym): This could be moved to separate source file as well. |
1045 class HostResolverImpl::DnsTask { | 1046 class HostResolverImpl::DnsTask : public base::SupportsWeakPtr<DnsTask> { |
1046 public: | 1047 public: |
1047 typedef base::Callback<void(int net_error, | 1048 typedef base::Callback<void(int net_error, |
1048 const AddressList& addr_list, | 1049 const AddressList& addr_list, |
1049 base::TimeDelta ttl)> Callback; | 1050 base::TimeDelta ttl)> Callback; |
1050 | 1051 |
1051 DnsTask(DnsTransactionFactory* factory, | 1052 DnsTask(DnsClient* client, |
1052 const Key& key, | 1053 const Key& key, |
1053 const Callback& callback, | 1054 const Callback& callback, |
1054 const BoundNetLog& job_net_log) | 1055 const BoundNetLog& job_net_log) |
1055 : callback_(callback), net_log_(job_net_log) { | 1056 : client_(client), |
1056 DCHECK(factory); | 1057 family_(key.address_family), |
| 1058 callback_(callback), |
| 1059 net_log_(job_net_log) { |
| 1060 DCHECK(client); |
1057 DCHECK(!callback.is_null()); | 1061 DCHECK(!callback.is_null()); |
1058 | 1062 |
1059 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4. | 1063 // If unspecified, do IPv4 first, because suffix search will be faster. |
1060 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6) | 1064 uint16 qtype = (family_ == ADDRESS_FAMILY_IPV6) ? |
1061 ? dns_protocol::kTypeAAAA | 1065 dns_protocol::kTypeAAAA : |
1062 : dns_protocol::kTypeA; | 1066 dns_protocol::kTypeA; |
1063 // TODO(szym): Implement "happy eyeballs". | 1067 transaction_ = client_->GetTransactionFactory()->CreateTransaction( |
1064 transaction_ = factory->CreateTransaction( | |
1065 key.hostname, | 1068 key.hostname, |
1066 qtype, | 1069 qtype, |
1067 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), | 1070 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), |
1068 base::TimeTicks::Now()), | 1071 true /* first_query */, base::TimeTicks::Now()), |
1069 net_log_); | 1072 net_log_); |
1070 DCHECK(transaction_.get()); | |
1071 } | 1073 } |
1072 | 1074 |
1073 int Start() { | 1075 int Start() { |
1074 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK); | 1076 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK); |
1075 return transaction_->Start(); | 1077 return transaction_->Start(); |
1076 } | 1078 } |
1077 | 1079 |
1078 void OnTransactionComplete(const base::TimeTicks& start_time, | 1080 private: |
| 1081 void OnTransactionComplete(bool first_query, |
| 1082 const base::TimeTicks& start_time, |
1079 DnsTransaction* transaction, | 1083 DnsTransaction* transaction, |
1080 int net_error, | 1084 int net_error, |
1081 const DnsResponse* response) { | 1085 const DnsResponse* response) { |
1082 DCHECK(transaction); | 1086 DCHECK(transaction); |
1083 // Run |callback_| last since the owning Job will then delete this DnsTask. | 1087 // Run |callback_| last since the owning Job will then delete this DnsTask. |
1084 DnsResponse::Result result = DnsResponse::DNS_SUCCESS; | 1088 if (net_error != OK) { |
1085 if (net_error == OK) { | 1089 DNS_HISTOGRAM("AsyncDNS.TransactionFailure", |
1086 CHECK(response); | |
1087 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", | |
1088 base::TimeTicks::Now() - start_time); | 1090 base::TimeTicks::Now() - start_time); |
1089 AddressList addr_list; | 1091 OnFailure(net_error, DnsResponse::DNS_PARSE_OK); |
1090 base::TimeDelta ttl; | 1092 return; |
1091 result = response->ParseToAddressList(&addr_list, &ttl); | 1093 } |
1092 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", | 1094 |
1093 result, | 1095 CHECK(response); |
1094 DnsResponse::DNS_PARSE_RESULT_MAX); | 1096 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess", |
1095 if (result == DnsResponse::DNS_SUCCESS) { | 1097 base::TimeTicks::Now() - start_time); |
1096 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | 1098 AddressList addr_list; |
1097 addr_list.CreateNetLogCallback()); | 1099 base::TimeDelta ttl; |
1098 callback_.Run(net_error, addr_list, ttl); | 1100 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl); |
| 1101 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", |
| 1102 result, |
| 1103 DnsResponse::DNS_PARSE_RESULT_MAX); |
| 1104 if (result != DnsResponse::DNS_PARSE_OK) { |
| 1105 // Fail even if the other query succeeds. |
| 1106 OnFailure(ERR_DNS_MALFORMED_RESPONSE, result); |
| 1107 return; |
| 1108 } |
| 1109 |
| 1110 bool needs_sort = false; |
| 1111 if (first_query) { |
| 1112 DCHECK(client_->GetConfig()) << |
| 1113 "Transaction should have been aborted when config changed!"; |
| 1114 if (family_ == ADDRESS_FAMILY_IPV6) { |
| 1115 needs_sort = (addr_list.size() > 1); |
| 1116 } else if (family_ == ADDRESS_FAMILY_UNSPECIFIED) { |
| 1117 first_addr_list_ = addr_list; |
| 1118 first_ttl_ = ttl; |
| 1119 // Use fully-qualified domain name to avoid search. |
| 1120 transaction_ = client_->GetTransactionFactory()->CreateTransaction( |
| 1121 response->GetDottedName() + ".", |
| 1122 dns_protocol::kTypeAAAA, |
| 1123 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), |
| 1124 false /* first_query */, base::TimeTicks::Now()), |
| 1125 net_log_); |
| 1126 net_error = transaction_->Start(); |
| 1127 if (net_error != ERR_IO_PENDING) |
| 1128 OnFailure(net_error, DnsResponse::DNS_PARSE_OK); |
1099 return; | 1129 return; |
1100 } | 1130 } |
1101 net_error = ERR_DNS_MALFORMED_RESPONSE; | |
1102 } else { | 1131 } else { |
1103 DNS_HISTOGRAM("AsyncDNS.TransactionFailure", | 1132 DCHECK_EQ(ADDRESS_FAMILY_UNSPECIFIED, family_); |
| 1133 bool has_ipv6_addresses = !addr_list.empty(); |
| 1134 if (!first_addr_list_.empty()) { |
| 1135 ttl = std::min(ttl, first_ttl_); |
| 1136 // Place IPv4 addresses after IPv6. |
| 1137 addr_list.insert(addr_list.end(), first_addr_list_.begin(), |
| 1138 first_addr_list_.end()); |
| 1139 } |
| 1140 needs_sort = (has_ipv6_addresses && addr_list.size() > 1); |
| 1141 } |
| 1142 |
| 1143 if (addr_list.empty()) { |
| 1144 // TODO(szym): Don't fallback to ProcTask in this case. |
| 1145 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); |
| 1146 return; |
| 1147 } |
| 1148 |
| 1149 if (needs_sort) { |
| 1150 // Sort could complete synchronously. |
| 1151 client_->GetAddressSorter()->Sort( |
| 1152 addr_list, |
| 1153 base::Bind(&DnsTask::OnSortComplete, AsWeakPtr(), |
| 1154 base::TimeTicks::Now(), |
| 1155 ttl)); |
| 1156 } else { |
| 1157 OnSuccess(addr_list, ttl); |
| 1158 } |
| 1159 } |
| 1160 |
| 1161 void OnSortComplete(base::TimeTicks start_time, |
| 1162 base::TimeDelta ttl, |
| 1163 bool success, |
| 1164 const AddressList& addr_list) { |
| 1165 if (!success) { |
| 1166 DNS_HISTOGRAM("AsyncDNS.SortFailure", |
1104 base::TimeTicks::Now() - start_time); | 1167 base::TimeTicks::Now() - start_time); |
| 1168 OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK); |
| 1169 return; |
1105 } | 1170 } |
| 1171 |
| 1172 DNS_HISTOGRAM("AsyncDNS.SortSuccess", |
| 1173 base::TimeTicks::Now() - start_time); |
| 1174 |
| 1175 // AddressSorter prunes unusable destinations. |
| 1176 if (addr_list.empty()) { |
| 1177 LOG(WARNING) << "Address list empty after RFC3484 sort"; |
| 1178 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK); |
| 1179 return; |
| 1180 } |
| 1181 |
| 1182 OnSuccess(addr_list, ttl); |
| 1183 } |
| 1184 |
| 1185 void OnFailure(int net_error, DnsResponse::Result result) { |
| 1186 DCHECK_NE(OK, net_error); |
1106 net_log_.EndEvent( | 1187 net_log_.EndEvent( |
1107 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, | 1188 NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, |
1108 base::Bind(&NetLogDnsTaskFailedCallback, net_error, result)); | 1189 base::Bind(&NetLogDnsTaskFailedCallback, net_error, result)); |
1109 callback_.Run(net_error, AddressList(), base::TimeDelta()); | 1190 callback_.Run(net_error, AddressList(), base::TimeDelta()); |
1110 } | 1191 } |
1111 | 1192 |
1112 private: | 1193 void OnSuccess(const AddressList& addr_list, base::TimeDelta ttl) { |
| 1194 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, |
| 1195 addr_list.CreateNetLogCallback()); |
| 1196 callback_.Run(OK, addr_list, ttl); |
| 1197 } |
| 1198 |
| 1199 DnsClient* client_; |
| 1200 AddressFamily family_; |
1113 // The listener to the results of this DnsTask. | 1201 // The listener to the results of this DnsTask. |
1114 Callback callback_; | 1202 Callback callback_; |
1115 | |
1116 const BoundNetLog net_log_; | 1203 const BoundNetLog net_log_; |
1117 | 1204 |
1118 scoped_ptr<DnsTransaction> transaction_; | 1205 scoped_ptr<DnsTransaction> transaction_; |
| 1206 |
| 1207 // Results from the first transaction. Used only if |family_| is unspecified. |
| 1208 AddressList first_addr_list_; |
| 1209 base::TimeDelta first_ttl_; |
| 1210 |
| 1211 DISALLOW_COPY_AND_ASSIGN(DnsTask); |
1119 }; | 1212 }; |
1120 | 1213 |
1121 //----------------------------------------------------------------------------- | 1214 //----------------------------------------------------------------------------- |
1122 | 1215 |
1123 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. | 1216 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. |
1124 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { | 1217 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { |
1125 public: | 1218 public: |
1126 // Creates new job for |key| where |request_net_log| is bound to the | 1219 // Creates new job for |key| where |request_net_log| is bound to the |
1127 // request that spawned it. | 1220 // request that spawned it. |
1128 Job(HostResolverImpl* resolver, | 1221 Job(HostResolverImpl* resolver, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1207 if (proc_task_) | 1300 if (proc_task_) |
1208 proc_task_->set_had_non_speculative_request(); | 1301 proc_task_->set_had_non_speculative_request(); |
1209 } | 1302 } |
1210 | 1303 |
1211 requests_.push_back(req.release()); | 1304 requests_.push_back(req.release()); |
1212 | 1305 |
1213 UpdatePriority(); | 1306 UpdatePriority(); |
1214 } | 1307 } |
1215 | 1308 |
1216 // Marks |req| as cancelled. If it was the last active Request, also finishes | 1309 // Marks |req| as cancelled. If it was the last active Request, also finishes |
1217 // this Job marking it either as aborted or cancelled, and deletes it. | 1310 // this Job, marking it as cancelled, and deletes it. |
1218 void CancelRequest(Request* req) { | 1311 void CancelRequest(Request* req) { |
1219 DCHECK_EQ(key_.hostname, req->info().hostname()); | 1312 DCHECK_EQ(key_.hostname, req->info().hostname()); |
1220 DCHECK(!req->was_canceled()); | 1313 DCHECK(!req->was_canceled()); |
1221 | 1314 |
1222 // Don't remove it from |requests_| just mark it canceled. | 1315 // Don't remove it from |requests_| just mark it canceled. |
1223 req->MarkAsCanceled(); | 1316 req->MarkAsCanceled(); |
1224 LogCancelRequest(req->source_net_log(), req->request_net_log(), | 1317 LogCancelRequest(req->source_net_log(), req->request_net_log(), |
1225 req->info()); | 1318 req->info()); |
1226 | 1319 |
1227 priority_tracker_.Remove(req->info().priority()); | 1320 priority_tracker_.Remove(req->info().priority()); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1374 kNegativeCacheEntryTTLSeconds); | 1467 kNegativeCacheEntryTTLSeconds); |
1375 if (net_error == OK) | 1468 if (net_error == OK) |
1376 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); | 1469 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); |
1377 | 1470 |
1378 CompleteRequests(net_error, addr_list, ttl); | 1471 CompleteRequests(net_error, addr_list, ttl); |
1379 } | 1472 } |
1380 | 1473 |
1381 void StartDnsTask() { | 1474 void StartDnsTask() { |
1382 DCHECK(resolver_->HaveDnsConfig()); | 1475 DCHECK(resolver_->HaveDnsConfig()); |
1383 dns_task_.reset(new DnsTask( | 1476 dns_task_.reset(new DnsTask( |
1384 resolver_->dns_client_->GetTransactionFactory(), | 1477 resolver_->dns_client_.get(), |
1385 key_, | 1478 key_, |
1386 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), | 1479 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), |
1387 net_log_)); | 1480 net_log_)); |
1388 | 1481 |
1389 int rv = dns_task_->Start(); | 1482 int rv = dns_task_->Start(); |
1390 if (rv != ERR_IO_PENDING) { | 1483 if (rv != ERR_IO_PENDING) { |
1391 DCHECK_NE(OK, rv); | 1484 DCHECK_NE(OK, rv); |
1392 dns_task_error_ = rv; | 1485 dns_task_error_ = rv; |
1393 dns_task_.reset(); | 1486 dns_task_.reset(); |
1394 StartProcTask(); | 1487 StartProcTask(); |
(...skipping 13 matching lines...) Expand all Loading... |
1408 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. | 1501 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. |
1409 // http://crbug.com/117655 | 1502 // http://crbug.com/117655 |
1410 | 1503 |
1411 // TODO(szym): Some net errors indicate lack of connectivity. Starting | 1504 // TODO(szym): Some net errors indicate lack of connectivity. Starting |
1412 // ProcTask in that case is a waste of time. | 1505 // ProcTask in that case is a waste of time. |
1413 StartProcTask(); | 1506 StartProcTask(); |
1414 return; | 1507 return; |
1415 } | 1508 } |
1416 | 1509 |
1417 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); | 1510 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); |
| 1511 |
1418 CompleteRequests(net_error, addr_list, ttl); | 1512 CompleteRequests(net_error, addr_list, ttl); |
1419 } | 1513 } |
1420 | 1514 |
1421 // Performs Job's last rites. Completes all Requests. Deletes this. | 1515 // Performs Job's last rites. Completes all Requests. Deletes this. |
1422 void CompleteRequests(int net_error, | 1516 void CompleteRequests(int net_error, |
1423 const AddressList& addr_list, | 1517 const AddressList& addr_list, |
1424 base::TimeDelta ttl) { | 1518 base::TimeDelta ttl) { |
1425 CHECK(resolver_); | 1519 CHECK(resolver_); |
1426 | 1520 |
1427 // This job must be removed from resolver's |jobs_| now to make room for a | 1521 // This job must be removed from resolver's |jobs_| now to make room for a |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2051 // |this| may be deleted inside AbortAllInProgressJobs(). | 2145 // |this| may be deleted inside AbortAllInProgressJobs(). |
2052 if (self) | 2146 if (self) |
2053 TryServingAllJobsFromHosts(); | 2147 TryServingAllJobsFromHosts(); |
2054 } | 2148 } |
2055 | 2149 |
2056 bool HostResolverImpl::HaveDnsConfig() const { | 2150 bool HostResolverImpl::HaveDnsConfig() const { |
2057 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); | 2151 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); |
2058 } | 2152 } |
2059 | 2153 |
2060 } // namespace net | 2154 } // namespace net |
OLD | NEW |