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