Revert "Generalize for non-address results in HostResolverImpl"
This reverts commit 07ee5f0f8712cd6783cc2bb00b17b59d72e04b4a.
Reason for revert: StartTestServer(SpawnedTestServer::SSLOptions())
started failing after this CL
https://ci.chromium.org/p/chromium/builders/luci.chromium.ci/Mac10.12%20Tests/17143
[ RUN ] SSLClientSocketReadTest.Read_WithSynchronousError/0
[56283:775:1128/182253.758810:39802574526192:ERROR:local_test_server_posix.cc(79)] poll() timed out; bytes_read=0
[56283:775:1128/182253.758860:39802574568901:ERROR:local_test_server_posix.cc(167)] Could not read server_data_len
[56283:775:1128/182253.760826:39802576544202:ERROR:ssl_client_socket_unittest.cc(830)] Could not start SpawnedTestServer
../../net/socket/ssl_client_socket_unittest.cc:1532: Failure
Value of: StartTestServer(SpawnedTestServer::SSLOptions())
Actual: false
Expected: true
Stack trace:
0 net_unittests 0x000000010f41750b testing::internal::UnitTestImpl::CurrentOsStackTraceExceptTop(int) + 91
1 net_unittests 0x000000010f416ec9 testing::internal::AssertHelper::operator=(testing::Message const&) const + 89
2 net_unittests 0x000000010e7d9239 net::SSLClientSocketReadTest_Read_WithSynchronousError_Test::TestBody() + 585
[ FAILED ] SSLClientSocketReadTest.Read_WithSynchronousError/0, where GetParam() = false (10083 ms)
Original change's description:
> Generalize for non-address results in HostResolverImpl
>
> Now extensively using HostCache::Entry internally (but only internally
> to preserve flexibility of HostCache) as a generalized results
> container within HostResolverImpl. Added some needed setter/merge
> functionality to Entry for that purpose. Many methods within the
> resolver changed to use Entry for consistency even if they only ever
> deal with address results, eg ResolveAsIP().
>
> Slightly modified results port-setting functionality to only set port
> to an input port (from |host.port()|) if the port in the results is 0
> (where before it would set it whenever it wasn't equal to the input
> port). This will be necessary eg for SRV support where DNS provides a
> specific port that needs to be maintained in the results. Also cleaned
> up the port setting to consistently only ever happen just before
> setting results on the RequestImpl and having 0 or a DNS-provided port
> until then.
>
> Bug: 846423
> Change-Id: I679c0ac915e0f81b49adb5ee769f250be49c9c90
> Reviewed-on: https://chromium-review.googlesource.com/c/1340835
> Reviewed-by: Matt Menke <[email protected]>
> Commit-Queue: Eric Orth <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#611963}
[email protected],[email protected]
Change-Id: Icc3121b6f6de985fb64ed9b2bee4951faf5378a3
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 846423
Reviewed-on: https://chromium-review.googlesource.com/c/1354746
Reviewed-by: Giovanni Ortuño Urquidi <[email protected]>
Commit-Queue: Giovanni Ortuño Urquidi <[email protected]>
Cr-Commit-Position: refs/heads/master@{#612052}
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 77febd3..70ea152 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -236,40 +236,10 @@
//-----------------------------------------------------------------------------
-// Creates a copy of |results| with the port of all address and hostname values
-// set to |port| if the current port is 0. Preserves any non-zero ports.
-HostCache::Entry SetPortOnResults(HostCache::Entry results, uint16_t port) {
- if (results.addresses() &&
- std::any_of(results.addresses().value().begin(),
- results.addresses().value().end(),
- [](const IPEndPoint& e) { return e.port() == 0; })) {
- AddressList addresses_with_port;
- addresses_with_port.set_canonical_name(
- results.addresses().value().canonical_name());
- for (const IPEndPoint& endpoint : results.addresses().value()) {
- if (endpoint.port() == 0)
- addresses_with_port.push_back(IPEndPoint(endpoint.address(), port));
- else
- addresses_with_port.push_back(endpoint);
- }
- results.set_addresses(addresses_with_port);
- }
-
- if (results.hostnames() &&
- std::any_of(results.hostnames().value().begin(),
- results.hostnames().value().end(),
- [](const HostPortPair& h) { return h.port() == 0; })) {
- std::vector<HostPortPair> hostnames_with_port;
- for (const HostPortPair& hostname : results.hostnames().value()) {
- if (hostname.port() == 0)
- hostnames_with_port.push_back(HostPortPair(hostname.host(), port));
- else
- hostnames_with_port.push_back(hostname);
- }
- results.set_hostnames(std::move(hostnames_with_port));
- }
-
- return results;
+AddressList EnsurePortOnAddressList(const AddressList& list, uint16_t port) {
+ if (list.empty() || list.front().port() == port)
+ return list;
+ return AddressList::CopyWithPort(list, port);
}
// Returns true if |addresses| contains only IPv4 loopback addresses.
@@ -381,14 +351,11 @@
std::unique_ptr<base::Value> NetLogDnsTaskFailedCallback(
int net_error,
int dns_error,
- NetLogParametersCallback results_callback,
- NetLogCaptureMode capture_mode) {
+ NetLogCaptureMode /* capture_mode */) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetInteger("net_error", net_error);
if (dns_error)
dict->SetInteger("dns_error", dns_error);
- if (results_callback)
- dict->Set("resolve_results", results_callback.Run(capture_mode));
return std::move(dict);
}
@@ -573,16 +540,18 @@
//-----------------------------------------------------------------------------
-bool ResolveLocalHostname(base::StringPiece host, AddressList* address_list) {
+bool ResolveLocalHostname(base::StringPiece host,
+ uint16_t port,
+ AddressList* address_list) {
address_list->clear();
bool is_local6;
if (!IsLocalHostname(host, &is_local6))
return false;
- address_list->push_back(IPEndPoint(IPAddress::IPv6Localhost(), 0));
+ address_list->push_back(IPEndPoint(IPAddress::IPv6Localhost(), port));
if (!is_local6) {
- address_list->push_back(IPEndPoint(IPAddress::IPv4Localhost(), 0));
+ address_list->push_back(IPEndPoint(IPAddress::IPv4Localhost(), port));
}
return true;
@@ -645,34 +614,17 @@
const base::Optional<AddressList>& GetAddressResults() const override {
DCHECK(complete_);
- static const base::NoDestructor<base::Optional<AddressList>> nullopt_result;
- return results_ ? results_.value().addresses() : *nullopt_result;
+ return address_results_;
}
- const base::Optional<std::vector<std::string>>& GetTextResults()
- const override {
- DCHECK(complete_);
- static const base::NoDestructor<base::Optional<std::vector<std::string>>>
- nullopt_result;
- return results_ ? results_.value().text_records() : *nullopt_result;
- }
-
- const base::Optional<std::vector<HostPortPair>>& GetHostnameResults()
- const override {
- DCHECK(complete_);
- static const base::NoDestructor<base::Optional<std::vector<HostPortPair>>>
- nullopt_result;
- return results_ ? results_.value().hostnames() : *nullopt_result;
- }
-
- void set_results(HostCache::Entry results) {
+ void set_address_results(const AddressList& address_results) {
// Should only be called at most once and before request is marked
// completed.
DCHECK(!complete_);
- DCHECK(!results_);
+ DCHECK(!address_results_);
DCHECK(!parameters_.is_speculative);
- results_ = std::move(results);
+ address_results_ = address_results;
}
void ChangeRequestPriority(RequestPriority priority);
@@ -693,7 +645,7 @@
callback_.Reset();
// No results should be set.
- DCHECK(!results_);
+ DCHECK(!address_results_);
}
// Cleans up Job assignment, marks request completed, and calls the completion
@@ -752,7 +704,7 @@
CompletionOnceCallback callback_;
bool complete_;
- base::Optional<HostCache::Entry> results_;
+ base::Optional<AddressList> address_results_;
base::TimeTicks request_time_;
@@ -1062,7 +1014,9 @@
class Delegate {
public:
virtual void OnDnsTaskComplete(base::TimeTicks start_time,
- const HostCache::Entry& results) = 0;
+ int net_error,
+ const AddressList& addr_list,
+ base::TimeDelta ttl) = 0;
// Called when the first of two jobs succeeds. If the first completed
// transaction fails, this is not called. Also not called when the DnsTask
@@ -1124,6 +1078,8 @@
transaction2_->Start();
}
+ base::TimeDelta ttl() { return ttl_; }
+
private:
std::unique_ptr<DnsTransaction> CreateTransaction(
DnsQueryType dns_query_type) {
@@ -1132,8 +1088,7 @@
client_->GetTransactionFactory()->CreateTransaction(
key_.hostname, DnsQueryTypeToQtype(dns_query_type),
base::BindOnce(&DnsTask::OnTransactionComplete,
- base::Unretained(this), tick_clock_->NowTicks(),
- dns_query_type),
+ base::Unretained(this), tick_clock_->NowTicks()),
net_log_);
trans->SetRequestContext(delegate_->url_request_context());
trans->SetRequestPriority(delegate_->priority());
@@ -1141,7 +1096,6 @@
}
void OnTransactionComplete(const base::TimeTicks& start_time,
- DnsQueryType dns_query_type,
DnsTransaction* transaction,
int net_error,
const DnsResponse* response) {
@@ -1150,7 +1104,7 @@
if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
response->IsValid())) {
UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.TransactionFailure", duration);
- OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt);
+ OnFailure(net_error, DnsResponse::DNS_PARSE_OK);
return;
}
@@ -1165,161 +1119,115 @@
break;
}
- DnsResponse::Result parse_result = DnsResponse::DNS_PARSE_RESULT_MAX;
- HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
- switch (dns_query_type) {
- case DnsQueryType::UNSPECIFIED:
- // Should create two separate transactions with specified type.
- NOTREACHED();
- break;
- case DnsQueryType::A:
- case DnsQueryType::AAAA:
- parse_result = ParseAddressDnsResponse(response, &results);
- break;
- }
- DCHECK_LT(parse_result, DnsResponse::DNS_PARSE_RESULT_MAX);
-
- if (results.error() != OK && results.error() != ERR_NAME_NOT_RESOLVED) {
- OnFailure(results.error(), parse_result, results.GetOptionalTtl());
+ AddressList addr_list;
+ base::TimeDelta ttl;
+ DnsResponse::Result result = response->ParseToAddressList(&addr_list, &ttl);
+ UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList",
+ result,
+ DnsResponse::DNS_PARSE_RESULT_MAX);
+ if (result != DnsResponse::DNS_PARSE_OK) {
+ // Fail even if the other query succeeds.
+ OnFailure(ERR_DNS_MALFORMED_RESPONSE, result);
return;
}
- // Merge results with saved results from previous transactions.
- if (saved_results_) {
- DCHECK(needs_two_transactions());
- DCHECK_GE(1u, num_completed_transactions_);
-
- switch (dns_query_type) {
- case DnsQueryType::A:
- // A results in |results| go after other results in |saved_results_|,
- // so merge |saved_results_| to the front.
- results = HostCache::Entry::MergeEntries(
- std::move(saved_results_).value(), std::move(results));
- break;
- case DnsQueryType::AAAA:
- // AAAA results in |results| go before other results in
- // |saved_results_|, so merge |saved_results_| to the back.
- results = HostCache::Entry::MergeEntries(
- std::move(results), std::move(saved_results_).value());
- break;
- default:
- // Only expect address query types with multiple transactions.
- NOTREACHED();
- }
+ ++num_completed_transactions_;
+ if (num_completed_transactions_ == 1) {
+ ttl_ = ttl;
+ } else {
+ ttl_ = std::min(ttl_, ttl);
}
- // If not all transactions are complete, the task cannot yet be completed
- // and the results so far must be saved to merge with additional results.
- ++num_completed_transactions_;
+ if (transaction->GetType() == dns_protocol::kTypeA) {
+ DCHECK_EQ(transaction1_.get(), transaction);
+ // Place IPv4 addresses after IPv6.
+ addr_list_.insert(addr_list_.end(), addr_list.begin(), addr_list.end());
+ } else if (transaction->GetType() == dns_protocol::kTypeAAAA) {
+ // Place IPv6 addresses before IPv4.
+ addr_list_.insert(addr_list_.begin(), addr_list.begin(), addr_list.end());
+ } else {
+ // TODO(crbug.com/846423): Add result parsing for non-address types.
+ NOTIMPLEMENTED();
+ }
+
+ // If requested via HOST_RESOLVER_CANONNAME, store the canonical name from
+ // the response. Prefer the name from the AAAA response. Only look at name
+ // if there is at least one address record.
+ if ((key_.host_resolver_flags & HOST_RESOLVER_CANONNAME) != 0 &&
+ !addr_list.empty() &&
+ (transaction->GetType() == dns_protocol::kTypeAAAA ||
+ addr_list_.canonical_name().empty())) {
+ addr_list_.set_canonical_name(addr_list.canonical_name());
+ }
+
if (needs_two_transactions() && num_completed_transactions_ == 1) {
- saved_results_ = std::move(results);
// No need to repeat the suffix search.
key_.hostname = transaction->GetHostname();
delegate_->OnFirstDnsTransactionComplete();
return;
}
- // If there are multiple addresses, and at least one is IPv6, need to sort
- // them. Note that IPv6 addresses are always put before IPv4 ones, so it's
- // sufficient to just check the family of the first address.
- if (results.addresses() && results.addresses().value().size() > 1 &&
- results.addresses().value()[0].GetFamily() == ADDRESS_FAMILY_IPV6) {
- // Sort addresses if needed. Sort could complete synchronously.
- client_->GetAddressSorter()->Sort(
- results.addresses().value(),
- base::BindOnce(&DnsTask::OnSortComplete, AsWeakPtr(),
- tick_clock_->NowTicks(), std::move(results)));
+ if (addr_list_.empty()) {
+ // TODO(szym): Don't fallback to ProcTask in this case.
+ OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
return;
}
- OnSuccess(results);
- }
-
- DnsResponse::Result ParseAddressDnsResponse(const DnsResponse* response,
- HostCache::Entry* out_results) {
- AddressList addresses;
- base::TimeDelta ttl;
- DnsResponse::Result parse_result =
- response->ParseToAddressList(&addresses, &ttl);
- UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ParseToAddressList", parse_result,
- DnsResponse::DNS_PARSE_RESULT_MAX);
-
- if (parse_result != DnsResponse::DNS_PARSE_OK) {
- *out_results = HostCache::Entry(ERR_DNS_MALFORMED_RESPONSE, AddressList(),
- HostCache::Entry::SOURCE_DNS);
- } else if (addresses.empty()) {
- *out_results = HostCache::Entry(ERR_NAME_NOT_RESOLVED, AddressList(),
- HostCache::Entry::SOURCE_DNS, ttl);
+ // If there are multiple addresses, and at least one is IPv6, need to sort
+ // them. Note that IPv6 addresses are always put before IPv4 ones, so it's
+ // sufficient to just check the family of the first address.
+ if (addr_list_.size() > 1 &&
+ addr_list_[0].GetFamily() == ADDRESS_FAMILY_IPV6) {
+ // Sort addresses if needed. Sort could complete synchronously.
+ client_->GetAddressSorter()->Sort(
+ addr_list_, base::BindOnce(&DnsTask::OnSortComplete, AsWeakPtr(),
+ tick_clock_->NowTicks()));
} else {
- *out_results = HostCache::Entry(OK, std::move(addresses),
- HostCache::Entry::SOURCE_DNS, ttl);
+ OnSuccess(addr_list_);
}
- return parse_result;
}
- void OnSortComplete(base::TimeTicks sort_start_time,
- HostCache::Entry results,
+ void OnSortComplete(base::TimeTicks start_time,
bool success,
const AddressList& addr_list) {
- results.set_addresses(addr_list);
-
if (!success) {
UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.SortFailure",
- tick_clock_->NowTicks() - sort_start_time);
- OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK,
- results.GetOptionalTtl());
+ tick_clock_->NowTicks() - start_time);
+ OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK);
return;
}
UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.SortSuccess",
- tick_clock_->NowTicks() - sort_start_time);
+ tick_clock_->NowTicks() - start_time);
// AddressSorter prunes unusable destinations.
- if (addr_list.empty() &&
- results.text_records().value_or(std::vector<std::string>()).empty() &&
- results.hostnames().value_or(std::vector<HostPortPair>()).empty()) {
+ if (addr_list.empty()) {
LOG(WARNING) << "Address list empty after RFC3484 sort";
- OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK,
- results.GetOptionalTtl());
+ OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
return;
}
- OnSuccess(results);
+ OnSuccess(addr_list);
}
- void OnFailure(int net_error,
- DnsResponse::Result parse_result,
- base::Optional<base::TimeDelta> ttl) {
+ void OnFailure(int net_error, DnsResponse::Result result) {
DCHECK_NE(OK, net_error);
-
- HostCache::Entry results(net_error, HostCache::Entry::SOURCE_UNKNOWN);
-
- net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
- base::Bind(&NetLogDnsTaskFailedCallback, results.error(),
- parse_result, results.CreateNetLogCallback()));
-
- // If we have a TTL from a previously completed transaction, use it.
- base::TimeDelta previous_transaction_ttl;
- if (saved_results_ && saved_results_.value().has_ttl() &&
- saved_results_.value().ttl() <
- base::TimeDelta::FromSeconds(
- std::numeric_limits<uint32_t>::max())) {
- previous_transaction_ttl = saved_results_.value().ttl();
- if (ttl)
- results.set_ttl(std::min(ttl.value(), previous_transaction_ttl));
- else
- results.set_ttl(previous_transaction_ttl);
- } else if (ttl) {
- results.set_ttl(ttl.value());
- }
-
- delegate_->OnDnsTaskComplete(task_start_time_, results);
+ net_log_.EndEvent(
+ NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
+ base::Bind(&NetLogDnsTaskFailedCallback, net_error, result));
+ base::TimeDelta ttl = ttl_ < base::TimeDelta::FromSeconds(
+ std::numeric_limits<uint32_t>::max()) &&
+ num_completed_transactions_ > 0
+ ? ttl_
+ : base::TimeDelta::FromSeconds(0);
+ delegate_->OnDnsTaskComplete(task_start_time_, net_error, AddressList(),
+ ttl);
}
- void OnSuccess(const HostCache::Entry& results) {
+ void OnSuccess(const AddressList& addr_list) {
net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
- results.CreateNetLogCallback());
- delegate_->OnDnsTaskComplete(task_start_time_, results);
+ addr_list.CreateNetLogCallback());
+ delegate_->OnDnsTaskComplete(task_start_time_, OK, addr_list, ttl_);
}
DnsClient* client_;
@@ -1338,9 +1246,10 @@
unsigned num_completed_transactions_;
- // Result from previously completed transactions. Only set if a transaction
- // has completed while others are still in progress.
- base::Optional<HostCache::Entry> saved_results_;
+ // These are updated as each transaction completes.
+ base::TimeDelta ttl_;
+ // IPv6 addresses must appear first in the list.
+ AddressList addr_list_;
const base::TickClock* tick_clock_;
base::TimeTicks task_start_time_;
@@ -1480,7 +1389,7 @@
// If we were called from a Request's callback within CompleteRequests,
// that Request could not have been cancelled, so num_active_requests()
// could not be 0. Therefore, we are not in CompleteRequests().
- CompleteRequestsWithError(ERR_FAILED /* cancelled */);
+ CompleteRequestsWithError(OK /* cancelled */);
}
}
@@ -1536,11 +1445,14 @@
// this Job was destroyed.
bool ServeFromHosts() {
DCHECK_GT(num_active_requests(), 0u);
- base::Optional<HostCache::Entry> results = resolver_->ServeFromHosts(key());
- if (results) {
+ AddressList addr_list;
+ if (resolver_->ServeFromHosts(
+ key(), requests_.head()->value()->request_host().port(),
+ &addr_list)) {
// This will destroy the Job.
- CompleteRequests(results.value(), base::TimeDelta(),
- true /* allow_cache */);
+ CompleteRequests(
+ MakeCacheEntry(OK, addr_list, HostCache::Entry::SOURCE_HOSTS),
+ base::TimeDelta(), true /* allow_cache */);
return true;
}
return false;
@@ -1580,6 +1492,35 @@
DCHECK_EQ(1u, num_occupied_job_slots_);
}
+ // MakeCacheEntry() and MakeCacheEntryWithTTL() are helpers to build a
+ // HostCache::Entry(). The address list is omited from the cache entry
+ // for errors.
+ HostCache::Entry MakeCacheEntry(int net_error,
+ const AddressList& addr_list,
+ HostCache::Entry::Source source) const {
+ return HostCache::Entry(
+ net_error,
+ net_error == OK ? MakeAddressListForRequest(addr_list) : AddressList(),
+ source);
+ }
+
+ HostCache::Entry MakeCacheEntryWithTTL(int net_error,
+ const AddressList& addr_list,
+ HostCache::Entry::Source source,
+ base::TimeDelta ttl) const {
+ return HostCache::Entry(
+ net_error,
+ net_error == OK ? MakeAddressListForRequest(addr_list) : AddressList(),
+ source, ttl);
+ }
+
+ AddressList MakeAddressListForRequest(const AddressList& list) const {
+ if (requests_.empty())
+ return list;
+ return AddressList::CopyWithPort(
+ list, requests_.head()->value()->request_host().port());
+ }
+
void UpdatePriority() {
if (is_queued())
handle_ = resolver_->dispatcher_->ChangePriority(handle_, priority());
@@ -1680,11 +1621,7 @@
// hosts file, its own cache, a DNS lookup or somewhere else.
// Don't store the |ttl| in cache since it's not obtained from the server.
CompleteRequests(
- HostCache::Entry(net_error,
- net_error == OK
- ? AddressList::CopyWithPort(addr_list, 0)
- : AddressList(),
- HostCache::Entry::SOURCE_UNKNOWN),
+ MakeCacheEntry(net_error, addr_list, HostCache::Entry::SOURCE_UNKNOWN),
ttl, true /* allow_cache */);
}
@@ -1713,10 +1650,9 @@
// Since we cannot complete synchronously from here, post a failure.
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(
- &Job::OnDnsTaskFailure, weak_ptr_factory_.GetWeakPtr(),
- dns_task_->AsWeakPtr(), base::TimeDelta(),
- HostCache::Entry(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN)));
+ base::BindOnce(&Job::OnDnsTaskFailure, weak_ptr_factory_.GetWeakPtr(),
+ dns_task_->AsWeakPtr(), base::TimeDelta(),
+ ERR_FAILED));
}
}
@@ -1730,9 +1666,7 @@
// so we use it as indicator whether Job is still valid.
void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task,
base::TimeDelta duration,
- const HostCache::Entry& failure_results) {
- DCHECK_NE(OK, failure_results.error());
-
+ int net_error) {
UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.FailureTime", duration);
if (!dns_task)
@@ -1740,12 +1674,12 @@
if (duration < base::TimeDelta::FromMilliseconds(10)) {
base::UmaHistogramSparse("Net.DNS.DnsTask.ErrorBeforeFallback.Fast",
- std::abs(failure_results.error()));
+ std::abs(net_error));
} else {
base::UmaHistogramSparse("Net.DNS.DnsTask.ErrorBeforeFallback.Slow",
- std::abs(failure_results.error()));
+ std::abs(net_error));
}
- dns_task_error_ = failure_results.error();
+ dns_task_error_ = net_error;
// TODO(szym): Run ServeFromHosts now if nsswitch.conf says so.
// http://crbug.com/117655
@@ -1758,42 +1692,50 @@
StartProcTask();
} else {
UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
- base::TimeDelta ttl = failure_results.has_ttl()
- ? failure_results.ttl()
- : base::TimeDelta::FromSeconds(0);
- CompleteRequests(failure_results, ttl, true /* allow_cache */);
+ // If the ttl is max, we didn't get one from the record, so set it to 0
+ base::TimeDelta ttl =
+ dns_task->ttl() < base::TimeDelta::FromSeconds(
+ std::numeric_limits<uint32_t>::max())
+ ? dns_task->ttl()
+ : base::TimeDelta::FromSeconds(0);
+ CompleteRequests(
+ HostCache::Entry(net_error, AddressList(),
+ HostCache::Entry::Source::SOURCE_UNKNOWN, ttl),
+ ttl, true /* allow_cache */);
}
}
// HostResolverImpl::DnsTask::Delegate implementation:
void OnDnsTaskComplete(base::TimeTicks start_time,
- const HostCache::Entry& results) override {
+ int net_error,
+ const AddressList& addr_list,
+ base::TimeDelta ttl) override {
DCHECK(is_dns_running());
base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
- if (results.error() != OK) {
- OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, results);
+ if (net_error != OK) {
+ OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, net_error);
return;
}
UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.SuccessTime", duration);
UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS);
- RecordTTL(results.ttl());
+ RecordTTL(ttl);
resolver_->OnDnsTaskResolve();
- base::TimeDelta bounded_ttl = std::max(
- results.ttl(), base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
+ base::TimeDelta bounded_ttl =
+ std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
- if (results.addresses() &&
- ContainsIcannNameCollisionIp(results.addresses().value())) {
+ if (ContainsIcannNameCollisionIp(addr_list)) {
CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION);
- return;
+ } else {
+ CompleteRequests(MakeCacheEntryWithTTL(net_error, addr_list,
+ HostCache::Entry::SOURCE_DNS, ttl),
+ bounded_ttl, true /* allow_cache */);
}
-
- CompleteRequests(results, bounded_ttl, true /* allow_cache */);
}
void OnFirstDnsTransactionComplete() override {
@@ -1832,18 +1774,18 @@
base::BindOnce(&Job::OnMdnsTaskComplete, base::Unretained(this)));
}
- void OnMdnsTaskComplete() {
+ void OnMdnsTaskComplete(int error) {
DCHECK(is_mdns_running());
// TODO(crbug.com/846423): Consider adding MDNS-specific logging.
- HostCache::Entry results = mdns_task_->GetResults();
- if (results.addresses() &&
- ContainsIcannNameCollisionIp(results.addresses().value())) {
+ if (error != OK) {
+ CompleteRequestsWithError(error);
+ } else if (ContainsIcannNameCollisionIp(mdns_task_->result_addresses())) {
CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION);
} else {
// MDNS uses a separate cache, so skip saving result to cache.
// TODO(crbug.com/846423): Consider merging caches.
- CompleteRequestsWithoutCache(results);
+ CompleteRequestsWithoutCache(error, mdns_task_->result_addresses());
}
}
@@ -1935,7 +1877,7 @@
//
// If not |allow_cache|, result will not be stored in the host cache, even if
// result would otherwise allow doing so.
- void CompleteRequests(const HostCache::Entry& results,
+ void CompleteRequests(const HostCache::Entry& entry,
base::TimeDelta ttl,
bool allow_cache) {
CHECK(resolver_.get());
@@ -1966,23 +1908,23 @@
}
net_log_.EndEventWithNetErrorCode(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
- results.error());
+ entry.error());
DCHECK(!requests_.empty());
- if (results.error() == OK || results.error() == ERR_ICANN_NAME_COLLISION) {
+ if (entry.error() == OK || entry.error() == ERR_ICANN_NAME_COLLISION) {
// Record this histogram here, when we know the system has a valid DNS
// configuration.
UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HaveDnsConfig",
resolver_->received_dns_config_);
}
- bool did_complete = (results.error() != ERR_NETWORK_CHANGED) &&
- (results.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
+ bool did_complete = (entry.error() != ERR_NETWORK_CHANGED) &&
+ (entry.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
if (did_complete && allow_cache)
- resolver_->CacheResult(key_, results, ttl);
+ resolver_->CacheResult(key_, entry, ttl);
- RecordJobHistograms(results.error());
+ RecordJobHistograms(entry.error());
// Complete all of the requests that were attached to the job and
// detach them.
@@ -1991,17 +1933,18 @@
req->RemoveFromList();
DCHECK_EQ(this, req->job());
// Update the net log and notify registered observers.
- LogFinishRequest(req->source_net_log(), results.error());
+ LogFinishRequest(req->source_net_log(), entry.error());
if (did_complete) {
// Record effective total time from creation to completion.
resolver_->RecordTotalTime(
req->parameters().is_speculative, false /* from_cache */,
tick_clock_->NowTicks() - req->request_time());
}
- if (results.error() == OK && !req->parameters().is_speculative) {
- req->set_results(SetPortOnResults(results, req->request_host().port()));
+ if (entry.error() == OK && !req->parameters().is_speculative) {
+ req->set_address_results(EnsurePortOnAddressList(
+ entry.addresses().value(), req->request_host().port()));
}
- req->OnJobCompleted(this, results.error());
+ req->OnJobCompleted(this, entry.error());
// Check if the resolver was destroyed as a result of running the
// callback. If it was, we could continue, but we choose to bail.
@@ -2010,16 +1953,17 @@
}
}
- void CompleteRequestsWithoutCache(const HostCache::Entry& results) {
- CompleteRequests(results, base::TimeDelta(), false /* allow_cache */);
+ void CompleteRequestsWithoutCache(int error, const AddressList& addresses) {
+ CompleteRequests(
+ MakeCacheEntry(error, addresses, HostCache::Entry::SOURCE_UNKNOWN),
+ base::TimeDelta(), false /* allow_cache */);
}
// Convenience wrapper for CompleteRequests in case of failure.
void CompleteRequestsWithError(int net_error) {
- DCHECK_NE(OK, net_error);
- CompleteRequests(
- HostCache::Entry(net_error, HostCache::Entry::SOURCE_UNKNOWN),
- base::TimeDelta(), true /* allow_cache */);
+ CompleteRequests(HostCache::Entry(net_error, AddressList(),
+ HostCache::Entry::SOURCE_UNKNOWN),
+ base::TimeDelta(), true /* allow_cache */);
}
RequestPriority priority() const override {
@@ -2240,20 +2184,14 @@
LogStartRequest(source_net_log, info);
Key key;
- HostCache::Entry results = ResolveLocally(
- info.host_port_pair().host(),
- AddressFamilyToDnsQueryType(info.address_family()),
+ int rv = ResolveLocally(
+ info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()),
FlagsToSource(info.host_resolver_flags()), info.host_resolver_flags(),
info.allow_cached_response(), false /* allow_stale */,
- nullptr /* stale_info */, source_net_log, &key);
+ nullptr /* stale_info */, source_net_log, addresses, &key);
- if (results.addresses()) {
- *addresses = AddressList::CopyWithPort(results.addresses().value(),
- info.host_port_pair().port());
- }
-
- LogFinishRequest(source_net_log, results.error());
- return results.error();
+ LogFinishRequest(source_net_log, rv);
+ return rv;
}
int HostResolverImpl::ResolveStaleFromCache(
@@ -2269,20 +2207,13 @@
LogStartRequest(source_net_log, info);
Key key;
- HostCache::Entry results =
- ResolveLocally(info.host_port_pair().host(),
- AddressFamilyToDnsQueryType(info.address_family()),
- FlagsToSource(info.host_resolver_flags()),
- info.host_resolver_flags(), info.allow_cached_response(),
- true /* allow_stale */, stale_info, source_net_log, &key);
-
- if (results.addresses()) {
- *addresses = AddressList::CopyWithPort(results.addresses().value(),
- info.host_port_pair().port());
- }
-
- LogFinishRequest(source_net_log, results.error());
- return results.error();
+ int rv = ResolveLocally(
+ info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()),
+ FlagsToSource(info.host_resolver_flags()), info.host_resolver_flags(),
+ info.allow_cached_response(), true /* allow_stale */, stale_info,
+ source_net_log, addresses, &key);
+ LogFinishRequest(source_net_log, rv);
+ return rv;
}
void HostResolverImpl::SetDnsClientEnabled(bool enabled) {
@@ -2426,103 +2357,96 @@
LogStartRequest(request->source_net_log(), request->request_host());
+ AddressList addresses;
Key key;
- HostCache::Entry results = ResolveLocally(
- request->request_host().host(), request->parameters().dns_query_type,
+ int rv = ResolveLocally(
+ request->request_host(), request->parameters().dns_query_type,
request->parameters().source, request->host_resolver_flags(),
request->parameters().allow_cached_response, false /* allow_stale */,
- nullptr /* stale_info */, request->source_net_log(), &key);
- if (results.error() == OK && !request->parameters().is_speculative) {
- request->set_results(
- SetPortOnResults(results, request->request_host().port()));
+ nullptr /* stale_info */, request->source_net_log(), &addresses, &key);
+ if (rv == OK && !request->parameters().is_speculative) {
+ request->set_address_results(
+ EnsurePortOnAddressList(addresses, request->request_host().port()));
}
- if (results.error() != ERR_DNS_CACHE_MISS) {
- LogFinishRequest(request->source_net_log(), results.error());
+ if (rv != ERR_DNS_CACHE_MISS) {
+ LogFinishRequest(request->source_net_log(), rv);
RecordTotalTime(request->parameters().is_speculative, true /* from_cache */,
base::TimeDelta());
- return results.error();
+ return rv;
}
- int rv = CreateAndStartJob(key, request);
+ rv = CreateAndStartJob(key, request);
// At this point, expect only async or errors.
DCHECK_NE(OK, rv);
return rv;
}
-HostCache::Entry HostResolverImpl::ResolveLocally(
- const std::string& hostname,
- DnsQueryType dns_query_type,
- HostResolverSource source,
- HostResolverFlags flags,
- bool allow_cache,
- bool allow_stale,
- HostCache::EntryStaleness* stale_info,
- const NetLogWithSource& source_net_log,
- Key* out_key) {
+int HostResolverImpl::ResolveLocally(const HostPortPair& host,
+ DnsQueryType dns_query_type,
+ HostResolverSource source,
+ HostResolverFlags flags,
+ bool allow_cache,
+ bool allow_stale,
+ HostCache::EntryStaleness* stale_info,
+ const NetLogWithSource& source_net_log,
+ AddressList* addresses,
+ Key* key) {
IPAddress ip_address;
IPAddress* ip_address_ptr = nullptr;
- if (ip_address.AssignFromIPLiteral(hostname)) {
+ if (ip_address.AssignFromIPLiteral(host.host())) {
ip_address_ptr = &ip_address;
} else {
// Check that the caller supplied a valid hostname to resolve.
- if (!IsValidDNSDomain(hostname)) {
- return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
- HostCache::Entry::SOURCE_UNKNOWN);
- }
+ if (!IsValidDNSDomain(host.host()))
+ return ERR_NAME_NOT_RESOLVED;
}
// Build a key that identifies the request in the cache and in the
// outstanding jobs map.
- *out_key = GetEffectiveKeyForRequest(hostname, dns_query_type, source, flags,
- ip_address_ptr, source_net_log);
+ *key = GetEffectiveKeyForRequest(host.host(), dns_query_type, source, flags,
+ ip_address_ptr, source_net_log);
DCHECK(allow_stale == !!stale_info);
// The result of |getaddrinfo| for empty hosts is inconsistent across systems.
// On Windows it gives the default interface's address, whereas on Linux it
// gives an error. We will make it fail on all platforms for consistency.
- if (hostname.empty() || hostname.size() > kMaxHostLength) {
+ if (host.host().empty() || host.host().size() > kMaxHostLength) {
MakeNotStale(stale_info);
- return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
- HostCache::Entry::SOURCE_UNKNOWN);
+ return ERR_NAME_NOT_RESOLVED;
}
- base::Optional<HostCache::Entry> resolved =
- ResolveAsIP(*out_key, ip_address_ptr);
- if (resolved) {
+ int net_error = ERR_UNEXPECTED;
+ if (ResolveAsIP(*key, host.port(), ip_address_ptr, &net_error, addresses)) {
MakeNotStale(stale_info);
- return resolved.value();
+ return net_error;
}
// Special-case localhost names, as per the recommendations in
// https://tools.ietf.org/html/draft-west-let-localhost-be-localhost.
- resolved = ServeLocalhost(*out_key);
- if (resolved) {
+ if (ServeLocalhost(*key, host.port(), addresses)) {
MakeNotStale(stale_info);
- return resolved.value();
+ return OK;
}
- if (allow_cache) {
- resolved = ServeFromCache(*out_key, allow_stale, stale_info);
- if (resolved) {
- source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_CACHE_HIT,
- resolved.value().CreateNetLogCallback());
- // |ServeFromCache()| will update |*stale_info| as needed.
- return resolved.value();
- }
+ if (allow_cache && ServeFromCache(*key, host.port(), &net_error, addresses,
+ allow_stale, stale_info)) {
+ source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_CACHE_HIT,
+ addresses->CreateNetLogCallback());
+ // |ServeFromCache()| will set |*stale_info| as needed.
+ return net_error;
}
// TODO(szym): Do not do this if nsswitch.conf instructs not to.
// http://crbug.com/117655
- resolved = ServeFromHosts(*out_key);
- if (resolved) {
+ if (ServeFromHosts(*key, host.port(), addresses)) {
source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_HOSTS_HIT,
- resolved.value().CreateNetLogCallback());
+ addresses->CreateNetLogCallback());
MakeNotStale(stale_info);
- return resolved.value();
+ return OK;
}
- return HostCache::Entry(ERR_DNS_CACHE_MISS, HostCache::Entry::SOURCE_UNKNOWN);
+ return ERR_DNS_CACHE_MISS;
}
int HostResolverImpl::CreateAndStartJob(const Key& key, RequestImpl* request) {
@@ -2556,34 +2480,41 @@
return ERR_IO_PENDING;
}
-base::Optional<HostCache::Entry> HostResolverImpl::ResolveAsIP(
- const Key& key,
- const IPAddress* ip_address) {
+bool HostResolverImpl::ResolveAsIP(const Key& key,
+ uint16_t host_port,
+ const IPAddress* ip_address,
+ int* net_error,
+ AddressList* addresses) {
+ DCHECK(addresses);
+ DCHECK(net_error);
if (ip_address == nullptr || !IsAddressType(key.dns_query_type))
- return base::nullopt;
+ return false;
+ *net_error = OK;
AddressFamily family = GetAddressFamily(*ip_address);
if (key.dns_query_type != DnsQueryType::UNSPECIFIED &&
key.dns_query_type != AddressFamilyToDnsQueryType(family)) {
// Don't return IPv6 addresses for IPv4 queries, and vice versa.
- return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
- HostCache::Entry::SOURCE_UNKNOWN);
+ *net_error = ERR_NAME_NOT_RESOLVED;
+ } else {
+ *addresses = AddressList::CreateFromIPAddress(*ip_address, host_port);
+ if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)
+ addresses->SetDefaultCanonicalName();
}
-
- AddressList addresses = AddressList::CreateFromIPAddress(*ip_address, 0);
- if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)
- addresses.SetDefaultCanonicalName();
- return HostCache::Entry(OK, std::move(addresses),
- HostCache::Entry::SOURCE_UNKNOWN);
+ return true;
}
-base::Optional<HostCache::Entry> HostResolverImpl::ServeFromCache(
- const Key& key,
- bool allow_stale,
- HostCache::EntryStaleness* stale_info) {
+bool HostResolverImpl::ServeFromCache(const Key& key,
+ uint16_t host_port,
+ int* net_error,
+ AddressList* addresses,
+ bool allow_stale,
+ HostCache::EntryStaleness* stale_info) {
+ DCHECK(addresses);
+ DCHECK(net_error);
DCHECK(allow_stale == !!stale_info);
if (!cache_.get())
- return base::nullopt;
+ return false;
const HostCache::Entry* cache_entry;
if (allow_stale)
@@ -2591,20 +2522,25 @@
else
cache_entry = cache_->Lookup(key, tick_clock_->NowTicks());
if (!cache_entry)
- return base::nullopt;
+ return false;
- if (cache_entry->error() == OK) {
+ *net_error = cache_entry->error();
+ if (*net_error == OK) {
if (cache_entry->has_ttl())
RecordTTL(cache_entry->ttl());
+ *addresses =
+ EnsurePortOnAddressList(cache_entry->addresses().value(), host_port);
}
-
- return *cache_entry;
+ return true;
}
-base::Optional<HostCache::Entry> HostResolverImpl::ServeFromHosts(
- const Key& key) {
- if (!HaveDnsConfig() || !IsAddressType(key.dns_query_type))
- return base::nullopt;
+bool HostResolverImpl::ServeFromHosts(const Key& key,
+ uint16_t host_port,
+ AddressList* addresses) {
+ DCHECK(addresses);
+ if (!HaveDnsConfig())
+ return false;
+ addresses->clear();
// HOSTS lookups are case-insensitive.
std::string hostname = base::ToLowerASCII(key.hostname);
@@ -2616,70 +2552,64 @@
// flexibility, but lose implicit ordering.
// We prefer IPv6 because "happy eyeballs" will fall back to IPv4 if
// necessary.
- AddressList addresses;
if (key.dns_query_type == DnsQueryType::AAAA ||
key.dns_query_type == DnsQueryType::UNSPECIFIED) {
auto it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6));
if (it != hosts.end())
- addresses.push_back(IPEndPoint(it->second, 0));
+ addresses->push_back(IPEndPoint(it->second, host_port));
}
if (key.dns_query_type == DnsQueryType::A ||
key.dns_query_type == DnsQueryType::UNSPECIFIED) {
auto it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV4));
if (it != hosts.end())
- addresses.push_back(IPEndPoint(it->second, 0));
+ addresses->push_back(IPEndPoint(it->second, host_port));
}
// If got only loopback addresses and the family was restricted, resolve
// again, without restrictions. See SystemHostResolverCall for rationale.
if ((key.host_resolver_flags &
- HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) &&
- IsAllIPv4Loopback(addresses)) {
+ HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) &&
+ IsAllIPv4Loopback(*addresses)) {
Key new_key(key);
new_key.dns_query_type = DnsQueryType::UNSPECIFIED;
new_key.host_resolver_flags &=
~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
- return ServeFromHosts(new_key);
+ return ServeFromHosts(new_key, host_port, addresses);
}
-
- if (!addresses.empty()) {
- return HostCache::Entry(OK, std::move(addresses),
- HostCache::Entry::SOURCE_HOSTS);
- }
-
- return base::nullopt;
+ return !addresses->empty();
}
-base::Optional<HostCache::Entry> HostResolverImpl::ServeLocalhost(
- const Key& key) {
+bool HostResolverImpl::ServeLocalhost(const Key& key,
+ uint16_t host_port,
+ AddressList* addresses) {
AddressList resolved_addresses;
- if (!IsAddressType(key.dns_query_type) ||
- !ResolveLocalHostname(key.hostname, &resolved_addresses)) {
- return base::nullopt;
- }
+ if (!ResolveLocalHostname(key.hostname, host_port, &resolved_addresses))
+ return false;
- AddressList filtered_addresses;
- for (const auto& address : resolved_addresses) {
- // Include the address if:
- // - caller didn't specify an address family, or
- // - caller specifically asked for the address family of this address, or
- // - this is an IPv6 address and caller specifically asked for IPv4 due
- // to lack of detected IPv6 support. (See SystemHostResolverCall for
- // rationale).
- if (key.dns_query_type == DnsQueryType::UNSPECIFIED ||
- DnsQueryTypeToAddressFamily(key.dns_query_type) ==
- address.GetFamily() ||
- (address.GetFamily() == ADDRESS_FAMILY_IPV6 &&
- key.dns_query_type == DnsQueryType::A &&
- (key.host_resolver_flags &
- HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6))) {
- filtered_addresses.push_back(address);
+ addresses->clear();
+
+ if (IsAddressType(key.dns_query_type)) {
+ for (const auto& address : resolved_addresses) {
+ // Include the address if:
+ // - caller didn't specify an address family, or
+ // - caller specifically asked for the address family of this address, or
+ // - this is an IPv6 address and caller specifically asked for IPv4 due
+ // to lack of detected IPv6 support. (See SystemHostResolverCall for
+ // rationale).
+ if (key.dns_query_type == DnsQueryType::UNSPECIFIED ||
+ DnsQueryTypeToAddressFamily(key.dns_query_type) ==
+ address.GetFamily() ||
+ (address.GetFamily() == ADDRESS_FAMILY_IPV6 &&
+ key.dns_query_type == DnsQueryType::A &&
+ (key.host_resolver_flags &
+ HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6))) {
+ addresses->push_back(address);
+ }
}
}
- return HostCache::Entry(OK, std::move(filtered_addresses),
- HostCache::Entry::SOURCE_UNKNOWN);
+ return true;
}
void HostResolverImpl::CacheResult(const Key& key,