Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Side by Side Diff: net/base/host_resolver_impl.cc

Issue 10442098: [net/dns] Resolve AF_UNSPEC on dual-stacked systems. Sort addresses according to RFC3484. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Working AddressSorterWin + measurements. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 21 matching lines...) Expand all
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/address_list_net_log_param.h" 35 #include "net/base/address_list_net_log_param.h"
36 #include "net/base/dns_reloader.h" 36 #include "net/base/dns_reloader.h"
37 #include "net/base/host_port_pair.h" 37 #include "net/base/host_port_pair.h"
38 #include "net/base/host_resolver_proc.h" 38 #include "net/base/host_resolver_proc.h"
39 #include "net/base/net_errors.h" 39 #include "net/base/net_errors.h"
40 #include "net/base/net_log.h" 40 #include "net/base/net_log.h"
41 #include "net/base/net_util.h" 41 #include "net/base/net_util.h"
42 #include "net/dns/address_sorter.h"
42 #include "net/dns/dns_client.h" 43 #include "net/dns/dns_client.h"
43 #include "net/dns/dns_config_service.h" 44 #include "net/dns/dns_config_service.h"
44 #include "net/dns/dns_protocol.h" 45 #include "net/dns/dns_protocol.h"
45 #include "net/dns/dns_response.h" 46 #include "net/dns/dns_response.h"
46 #include "net/dns/dns_transaction.h" 47 #include "net/dns/dns_transaction.h"
47 48
48 #if defined(OS_WIN) 49 #if defined(OS_WIN)
49 #include "net/base/winsock_init.h" 50 #include "net/base/winsock_init.h"
50 #endif 51 #endif
51 52
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 //----------------------------------------------------------------------------- 1047 //-----------------------------------------------------------------------------
1047 1048
1048 // Resolves the hostname using DnsTransaction. 1049 // Resolves the hostname using DnsTransaction.
1049 // TODO(szym): This could be moved to separate source file as well. 1050 // TODO(szym): This could be moved to separate source file as well.
1050 class HostResolverImpl::DnsTask { 1051 class HostResolverImpl::DnsTask {
1051 public: 1052 public:
1052 typedef base::Callback<void(int net_error, 1053 typedef base::Callback<void(int net_error,
1053 const AddressList& addr_list, 1054 const AddressList& addr_list,
1054 base::TimeDelta ttl)> Callback; 1055 base::TimeDelta ttl)> Callback;
1055 1056
1056 DnsTask(DnsTransactionFactory* factory, 1057 DnsTask(DnsClient* client,
1057 const Key& key, 1058 const Key& key,
1058 const Callback& callback, 1059 const Callback& callback,
1059 const BoundNetLog& job_net_log) 1060 const BoundNetLog& job_net_log)
1060 : callback_(callback), net_log_(job_net_log) { 1061 : client_(client),
1061 DCHECK(factory); 1062 family_(key.address_family),
1063 callback_(callback),
1064 net_log_(job_net_log) {
1065 DCHECK(client);
1062 DCHECK(!callback.is_null()); 1066 DCHECK(!callback.is_null());
1063 1067
1064 // For now we treat ADDRESS_FAMILY_UNSPEC as if it was IPV4. 1068 uint16 qtype = (family_ == ADDRESS_FAMILY_IPV4) ?
1065 uint16 qtype = (key.address_family == ADDRESS_FAMILY_IPV6) 1069 dns_protocol::kTypeA :
1066 ? dns_protocol::kTypeAAAA 1070 dns_protocol::kTypeAAAA; // If unspecified, do IPv6 first.
1067 : dns_protocol::kTypeA; 1071 transaction_ = client_->GetTransactionFactory()->CreateTransaction(
1068 // TODO(szym): Implement "happy eyeballs".
1069 transaction_ = factory->CreateTransaction(
1070 key.hostname, 1072 key.hostname,
1071 qtype, 1073 qtype,
1072 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this), 1074 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this),
1073 base::TimeTicks::Now()), 1075 true /* first_query */,
1076 base::TimeTicks::Now()),
1074 net_log_); 1077 net_log_);
1075 DCHECK(transaction_.get());
1076 } 1078 }
1077 1079
1078 int Start() { 1080 int Start() {
1079 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, NULL); 1081 net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, NULL);
1080 return transaction_->Start(); 1082 return transaction_->Start();
1081 } 1083 }
1082 1084
1083 void OnTransactionComplete(const base::TimeTicks& start_time, 1085 private:
1086 void OnTransactionComplete(bool first_query,
1087 const base::TimeTicks& start_time,
1084 DnsTransaction* transaction, 1088 DnsTransaction* transaction,
1085 int net_error, 1089 int net_error,
1086 const DnsResponse* response) { 1090 const DnsResponse* response) {
1087 DCHECK(transaction); 1091 DCHECK(transaction);
1088 // Run |callback_| last since the owning Job will then delete this DnsTask. 1092 // Run |callback_| last since the owning Job will then delete this DnsTask.
1089 DnsResponse::Result result = DnsResponse::DNS_SUCCESS; 1093 if (net_error != OK) {
1090 if (net_error == OK) { 1094 DNS_HISTOGRAM("AsyncDNS.TransactionFailure",
1091 CHECK(response);
1092 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess",
1093 base::TimeTicks::Now() - start_time); 1095 base::TimeTicks::Now() - start_time);
1094 AddressList addr_list; 1096 OnFailure(net_error, DnsResponse::DNS_SUCCESS);
mmenke 2012/06/07 18:32:34 These DNS_SUCCESSes everywhere caused me a fair bi
1095 base::TimeDelta ttl; 1097 return;
1096 result = response->ParseToAddressList(&addr_list, &ttl); 1098 }
1097 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", 1099
1098 result, 1100 CHECK(response);
1099 DnsResponse::DNS_PARSE_RESULT_MAX); 1101 DNS_HISTOGRAM("AsyncDNS.TransactionSuccess",
1100 if (result == DnsResponse::DNS_SUCCESS) { 1102 base::TimeTicks::Now() - start_time);
1101 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, 1103 AddressList addr_list;
1102 new AddressListNetLogParam(addr_list)); 1104 base::TimeDelta ttl;
1103 callback_.Run(net_error, addr_list, ttl); 1105 DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl);
1106 UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList",
1107 result,
1108 DnsResponse::DNS_PARSE_RESULT_MAX);
1109 if (result != DnsResponse::DNS_SUCCESS) {
1110 // Fail even if the other query succeeds.
1111 OnFailure(ERR_DNS_MALFORMED_RESPONSE, result);
1112 return;
1113 }
1114
1115 bool needs_sort = false;
1116 if (first_query) {
1117 if (family_ == ADDRESS_FAMILY_UNSPECIFIED) {
mmenke 2012/06/07 18:32:34 nit: You might want to swap these two if's, so th
1118 first_addr_list_ = addr_list;
1119 first_ttl_ = ttl;
1120 // Use fully-qualified domain name to avoid search.
1121 transaction_ = client_->GetTransactionFactory()->CreateTransaction(
1122 response->GetDottedName() + ".",
1123 dns_protocol::kTypeA,
1124 base::Bind(&DnsTask::OnTransactionComplete, base::Unretained(this),
1125 false /* first_query */,
1126 base::TimeTicks::Now()),
1127 net_log_);
1128 net_error = transaction_->Start();
1129 if (net_error != ERR_IO_PENDING)
1130 OnFailure(net_error, DnsResponse::DNS_SUCCESS);
1131 return;
1132 } else if (family_ == ADDRESS_FAMILY_IPV6) {
1133 needs_sort = true;
1134 }
1135 } else {
1136 if (!first_addr_list_.empty()) {
1137 ttl = std::min(ttl, first_ttl_);
1138 addr_list.insert(addr_list.begin(), first_addr_list_.begin(),
1139 first_addr_list_.end());
1140 needs_sort = true;
1141 }
1142 }
1143
1144 if (addr_list.empty()) {
1145 // TODO(szym): Don't fallback to ProcTask in this case.
1146 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_NO_ADDRESSES);
1147 return;
1148 }
1149
1150 if (needs_sort) {
1151 base::TimeTicks start_time = base::TimeTicks::Now();
1152 if (!client_->GetAddressSorter()->Sort(&addr_list)) {
1153 DNS_HISTOGRAM("AsyncDNS.SortFailure",
1154 base::TimeTicks::Now() - start_time);
1155 OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_SUCCESS);
1104 return; 1156 return;
1105 } 1157 }
1106 net_error = ERR_DNS_MALFORMED_RESPONSE; 1158 DNS_HISTOGRAM("AsyncDNS.SortSuccess",
1107 } else {
1108 DNS_HISTOGRAM("AsyncDNS.TransactionFailure",
1109 base::TimeTicks::Now() - start_time); 1159 base::TimeTicks::Now() - start_time);
1110 } 1160 }
1161
1162 // AddressSorter prunes unusable destinations.
1163 if (addr_list.empty()) {
1164 OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_SUCCESS);
1165 return;
1166 }
1167
1168 OnSuccess(addr_list, ttl);
1169 }
1170
1171 void OnFailure(int net_error, DnsResponse::Result result) {
1172 DCHECK_NE(OK, net_error);
1111 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK, 1173 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
1112 new DnsTaskFailedParams(net_error, result)); 1174 new DnsTaskFailedParams(net_error, result));
1113 callback_.Run(net_error, AddressList(), base::TimeDelta()); 1175 callback_.Run(net_error, AddressList(), base::TimeDelta());
1114 } 1176 }
1115 1177
1116 private: 1178 void OnSuccess(const AddressList& addr_list, base::TimeDelta ttl) {
1179 net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_DNS_TASK,
1180 new AddressListNetLogParam(addr_list));
1181 callback_.Run(OK, addr_list, ttl);
1182 }
1183
1184 DnsClient* client_;
1185 AddressFamily family_;
1117 // The listener to the results of this DnsTask. 1186 // The listener to the results of this DnsTask.
1118 Callback callback_; 1187 Callback callback_;
1119
1120 const BoundNetLog net_log_; 1188 const BoundNetLog net_log_;
1121 1189
1122 scoped_ptr<DnsTransaction> transaction_; 1190 scoped_ptr<DnsTransaction> transaction_;
1191
1192 // TODO(szym): wrap this up as HostResolver::Result, add canonical name.
1193 // Results from the first transaction. Used only if |family_| is unspecified.
1194 AddressList first_addr_list_;
1195 base::TimeDelta first_ttl_;
1123 }; 1196 };
1124 1197
1125 //----------------------------------------------------------------------------- 1198 //-----------------------------------------------------------------------------
1126 1199
1127 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch. 1200 // Aggregates all Requests for the same Key. Dispatched via PriorityDispatch.
1128 class HostResolverImpl::Job : public PrioritizedDispatcher::Job { 1201 class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
1129 public: 1202 public:
1130 // Creates new job for |key| where |request_net_log| is bound to the 1203 // Creates new job for |key| where |request_net_log| is bound to the
1131 // request that spawned it. 1204 // request that spawned it.
1132 Job(HostResolverImpl* resolver, 1205 Job(HostResolverImpl* resolver,
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 proc_task_->set_had_non_speculative_request(); 1279 proc_task_->set_had_non_speculative_request();
1207 } 1280 }
1208 1281
1209 requests_.push_back(req.release()); 1282 requests_.push_back(req.release());
1210 1283
1211 if (is_queued()) 1284 if (is_queued())
1212 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority()); 1285 handle_ = resolver_->dispatcher_.ChangePriority(handle_, priority());
1213 } 1286 }
1214 1287
1215 // Marks |req| as cancelled. If it was the last active Request, also finishes 1288 // Marks |req| as cancelled. If it was the last active Request, also finishes
1216 // this Job marking it either as aborted or cancelled, and deletes it. 1289 // this Job marking it as cancelled, and deletes it.
1217 void CancelRequest(Request* req) { 1290 void CancelRequest(Request* req) {
1218 DCHECK_EQ(key_.hostname, req->info().hostname()); 1291 DCHECK_EQ(key_.hostname, req->info().hostname());
1219 DCHECK(!req->was_canceled()); 1292 DCHECK(!req->was_canceled());
1220 1293
1221 // Don't remove it from |requests_| just mark it canceled. 1294 // Don't remove it from |requests_| just mark it canceled.
1222 req->MarkAsCanceled(); 1295 req->MarkAsCanceled();
1223 LogCancelRequest(req->source_net_log(), req->request_net_log(), 1296 LogCancelRequest(req->source_net_log(), req->request_net_log(),
1224 req->info()); 1297 req->info());
1225 1298
1226 priority_tracker_.Remove(req->info().priority()); 1299 priority_tracker_.Remove(req->info().priority());
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 kNegativeCacheEntryTTLSeconds); 1415 kNegativeCacheEntryTTLSeconds);
1343 if (net_error == OK) 1416 if (net_error == OK)
1344 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); 1417 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
1345 1418
1346 CompleteRequests(net_error, addr_list, ttl); 1419 CompleteRequests(net_error, addr_list, ttl);
1347 } 1420 }
1348 1421
1349 void StartDnsTask() { 1422 void StartDnsTask() {
1350 DCHECK(resolver_->HaveDnsConfig()); 1423 DCHECK(resolver_->HaveDnsConfig());
1351 dns_task_.reset(new DnsTask( 1424 dns_task_.reset(new DnsTask(
1352 resolver_->dns_client_->GetTransactionFactory(), 1425 resolver_->dns_client_.get(),
1353 key_, 1426 key_,
1354 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)), 1427 base::Bind(&Job::OnDnsTaskComplete, base::Unretained(this)),
1355 net_log_)); 1428 net_log_));
1356 1429
1357 int rv = dns_task_->Start(); 1430 int rv = dns_task_->Start();
1358 if (rv != ERR_IO_PENDING) { 1431 if (rv != ERR_IO_PENDING) {
1359 DCHECK_NE(OK, rv); 1432 DCHECK_NE(OK, rv);
1360 dns_task_.reset(); 1433 dns_task_.reset();
1361 StartProcTask(); 1434 StartProcTask();
1362 } 1435 }
(...skipping 11 matching lines...) Expand all
1374 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so. 1447 // TODO(szym): Run ServeFromHosts now if nsswitch.conf says so.
1375 // http://crbug.com/117655 1448 // http://crbug.com/117655
1376 1449
1377 // TODO(szym): Some net errors indicate lack of connectivity. Starting 1450 // TODO(szym): Some net errors indicate lack of connectivity. Starting
1378 // ProcTask in that case is a waste of time. 1451 // ProcTask in that case is a waste of time.
1379 StartProcTask(); 1452 StartProcTask();
1380 return; 1453 return;
1381 } 1454 }
1382 1455
1383 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS); 1456 UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS);
1457
1384 CompleteRequests(net_error, addr_list, ttl); 1458 CompleteRequests(net_error, addr_list, ttl);
1385 } 1459 }
1386 1460
1387 // Performs Job's last rites. Completes all Requests. Deletes this. 1461 // Performs Job's last rites. Completes all Requests. Deletes this.
1388 void CompleteRequests(int net_error, 1462 void CompleteRequests(int net_error,
1389 const AddressList& addr_list, 1463 const AddressList& addr_list,
1390 base::TimeDelta ttl) { 1464 base::TimeDelta ttl) {
1391 CHECK(resolver_); 1465 CHECK(resolver_);
1392 1466
1393 // This job must be removed from resolver's |jobs_| now to make room for a 1467 // This job must be removed from resolver's |jobs_| now to make room for a
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
1980 if (self) 2054 if (self)
1981 TryServingAllJobsFromHosts(); 2055 TryServingAllJobsFromHosts();
1982 } 2056 }
1983 } 2057 }
1984 2058
1985 bool HostResolverImpl::HaveDnsConfig() const { 2059 bool HostResolverImpl::HaveDnsConfig() const {
1986 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL); 2060 return (dns_client_.get() != NULL) && (dns_client_->GetConfig() != NULL);
1987 } 2061 }
1988 2062
1989 } // namespace net 2063 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698