Reland "Generalize for non-address results in HostResolverImpl"
This reverts commit e369ab31552568d193787e5dc591ff2785d906d0.
Reason for revert: The CL in question did not cause issue 869227, which is a pre-existing infra problem.
Original change's description:
> 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}
[email protected],[email protected],[email protected]
Change-Id: Ie2f80d423a5370f976918357b32b8eb772c4f57c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 846423
Reviewed-on: https://chromium-review.googlesource.com/c/1354267
Reviewed-by: Matt Menke <[email protected]>
Commit-Queue: Matt Menke <[email protected]>
Cr-Commit-Position: refs/heads/master@{#612164}
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 70ea152..77febd3 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -236,10 +236,40 @@
//-----------------------------------------------------------------------------
-AddressList EnsurePortOnAddressList(const AddressList& list, uint16_t port) {
- if (list.empty() || list.front().port() == port)
- return list;
- return AddressList::CopyWithPort(list, port);
+// 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;
}
// Returns true if |addresses| contains only IPv4 loopback addresses.
@@ -351,11 +381,14 @@
std::unique_ptr<base::Value> NetLogDnsTaskFailedCallback(
int net_error,
int dns_error,
- NetLogCaptureMode /* capture_mode */) {
+ NetLogParametersCallback results_callback,
+ 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);
}
@@ -540,18 +573,16 @@
//-----------------------------------------------------------------------------
-bool ResolveLocalHostname(base::StringPiece host,
- uint16_t port,
- AddressList* address_list) {
+bool ResolveLocalHostname(base::StringPiece host, AddressList* address_list) {
address_list->clear();
bool is_local6;
if (!IsLocalHostname(host, &is_local6))
return false;
- address_list->push_back(IPEndPoint(IPAddress::IPv6Localhost(), port));
+ address_list->push_back(IPEndPoint(IPAddress::IPv6Localhost(), 0));
if (!is_local6) {
- address_list->push_back(IPEndPoint(IPAddress::IPv4Localhost(), port));
+ address_list->push_back(IPEndPoint(IPAddress::IPv4Localhost(), 0));
}
return true;
@@ -614,17 +645,34 @@
const base::Optional<AddressList>& GetAddressResults() const override {
DCHECK(complete_);
- return address_results_;
+ static const base::NoDestructor<base::Optional<AddressList>> nullopt_result;
+ return results_ ? results_.value().addresses() : *nullopt_result;
}
- void set_address_results(const AddressList& 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) {
// Should only be called at most once and before request is marked
// completed.
DCHECK(!complete_);
- DCHECK(!address_results_);
+ DCHECK(!results_);
DCHECK(!parameters_.is_speculative);
- address_results_ = address_results;
+ results_ = std::move(results);
}
void ChangeRequestPriority(RequestPriority priority);
@@ -645,7 +693,7 @@
callback_.Reset();
// No results should be set.
- DCHECK(!address_results_);
+ DCHECK(!results_);
}
// Cleans up Job assignment, marks request completed, and calls the completion
@@ -704,7 +752,7 @@
CompletionOnceCallback callback_;
bool complete_;
- base::Optional<AddressList> address_results_;
+ base::Optional<HostCache::Entry> results_;
base::TimeTicks request_time_;
@@ -1014,9 +1062,7 @@
class Delegate {
public:
virtual void OnDnsTaskComplete(base::TimeTicks start_time,
- int net_error,
- const AddressList& addr_list,
- base::TimeDelta ttl) = 0;
+ const HostCache::Entry& results) = 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
@@ -1078,8 +1124,6 @@
transaction2_->Start();
}
- base::TimeDelta ttl() { return ttl_; }
-
private:
std::unique_ptr<DnsTransaction> CreateTransaction(
DnsQueryType dns_query_type) {
@@ -1088,7 +1132,8 @@
client_->GetTransactionFactory()->CreateTransaction(
key_.hostname, DnsQueryTypeToQtype(dns_query_type),
base::BindOnce(&DnsTask::OnTransactionComplete,
- base::Unretained(this), tick_clock_->NowTicks()),
+ base::Unretained(this), tick_clock_->NowTicks(),
+ dns_query_type),
net_log_);
trans->SetRequestContext(delegate_->url_request_context());
trans->SetRequestPriority(delegate_->priority());
@@ -1096,6 +1141,7 @@
}
void OnTransactionComplete(const base::TimeTicks& start_time,
+ DnsQueryType dns_query_type,
DnsTransaction* transaction,
int net_error,
const DnsResponse* response) {
@@ -1104,7 +1150,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);
+ OnFailure(net_error, DnsResponse::DNS_PARSE_OK, base::nullopt);
return;
}
@@ -1119,115 +1165,161 @@
break;
}
- 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);
+ 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());
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();
+ }
+ }
+
+ // 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 (num_completed_transactions_ == 1) {
- ttl_ = ttl;
- } else {
- ttl_ = std::min(ttl_, ttl);
- }
-
- 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 (addr_list_.empty()) {
- // TODO(szym): Don't fallback to ProcTask in this case.
- OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
- 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 (addr_list_.size() > 1 &&
- addr_list_[0].GetFamily() == ADDRESS_FAMILY_IPV6) {
+ 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(
- addr_list_, base::BindOnce(&DnsTask::OnSortComplete, AsWeakPtr(),
- tick_clock_->NowTicks()));
- } else {
- OnSuccess(addr_list_);
+ results.addresses().value(),
+ base::BindOnce(&DnsTask::OnSortComplete, AsWeakPtr(),
+ tick_clock_->NowTicks(), std::move(results)));
+ return;
}
+
+ OnSuccess(results);
}
- void OnSortComplete(base::TimeTicks start_time,
+ 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);
+ } else {
+ *out_results = HostCache::Entry(OK, std::move(addresses),
+ HostCache::Entry::SOURCE_DNS, ttl);
+ }
+ return parse_result;
+ }
+
+ void OnSortComplete(base::TimeTicks sort_start_time,
+ HostCache::Entry results,
bool success,
const AddressList& addr_list) {
+ results.set_addresses(addr_list);
+
if (!success) {
UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.SortFailure",
- tick_clock_->NowTicks() - start_time);
- OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK);
+ tick_clock_->NowTicks() - sort_start_time);
+ OnFailure(ERR_DNS_SORT_ERROR, DnsResponse::DNS_PARSE_OK,
+ results.GetOptionalTtl());
return;
}
UMA_HISTOGRAM_LONG_TIMES_100("AsyncDNS.SortSuccess",
- tick_clock_->NowTicks() - start_time);
+ tick_clock_->NowTicks() - sort_start_time);
// AddressSorter prunes unusable destinations.
- if (addr_list.empty()) {
+ if (addr_list.empty() &&
+ results.text_records().value_or(std::vector<std::string>()).empty() &&
+ results.hostnames().value_or(std::vector<HostPortPair>()).empty()) {
LOG(WARNING) << "Address list empty after RFC3484 sort";
- OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK);
+ OnFailure(ERR_NAME_NOT_RESOLVED, DnsResponse::DNS_PARSE_OK,
+ results.GetOptionalTtl());
return;
}
- OnSuccess(addr_list);
+ OnSuccess(results);
}
- void OnFailure(int net_error, DnsResponse::Result result) {
+ void OnFailure(int net_error,
+ DnsResponse::Result parse_result,
+ base::Optional<base::TimeDelta> ttl) {
DCHECK_NE(OK, net_error);
- 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);
+
+ 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);
}
- void OnSuccess(const AddressList& addr_list) {
+ void OnSuccess(const HostCache::Entry& results) {
net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
- addr_list.CreateNetLogCallback());
- delegate_->OnDnsTaskComplete(task_start_time_, OK, addr_list, ttl_);
+ results.CreateNetLogCallback());
+ delegate_->OnDnsTaskComplete(task_start_time_, results);
}
DnsClient* client_;
@@ -1246,10 +1338,9 @@
unsigned num_completed_transactions_;
- // These are updated as each transaction completes.
- base::TimeDelta ttl_;
- // IPv6 addresses must appear first in the list.
- AddressList addr_list_;
+ // Result from previously completed transactions. Only set if a transaction
+ // has completed while others are still in progress.
+ base::Optional<HostCache::Entry> saved_results_;
const base::TickClock* tick_clock_;
base::TimeTicks task_start_time_;
@@ -1389,7 +1480,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(OK /* cancelled */);
+ CompleteRequestsWithError(ERR_FAILED /* cancelled */);
}
}
@@ -1445,14 +1536,11 @@
// this Job was destroyed.
bool ServeFromHosts() {
DCHECK_GT(num_active_requests(), 0u);
- AddressList addr_list;
- if (resolver_->ServeFromHosts(
- key(), requests_.head()->value()->request_host().port(),
- &addr_list)) {
+ base::Optional<HostCache::Entry> results = resolver_->ServeFromHosts(key());
+ if (results) {
// This will destroy the Job.
- CompleteRequests(
- MakeCacheEntry(OK, addr_list, HostCache::Entry::SOURCE_HOSTS),
- base::TimeDelta(), true /* allow_cache */);
+ CompleteRequests(results.value(), base::TimeDelta(),
+ true /* allow_cache */);
return true;
}
return false;
@@ -1492,35 +1580,6 @@
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());
@@ -1621,7 +1680,11 @@
// 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(
- MakeCacheEntry(net_error, addr_list, HostCache::Entry::SOURCE_UNKNOWN),
+ HostCache::Entry(net_error,
+ net_error == OK
+ ? AddressList::CopyWithPort(addr_list, 0)
+ : AddressList(),
+ HostCache::Entry::SOURCE_UNKNOWN),
ttl, true /* allow_cache */);
}
@@ -1650,9 +1713,10 @@
// 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(),
- ERR_FAILED));
+ base::BindOnce(
+ &Job::OnDnsTaskFailure, weak_ptr_factory_.GetWeakPtr(),
+ dns_task_->AsWeakPtr(), base::TimeDelta(),
+ HostCache::Entry(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN)));
}
}
@@ -1666,7 +1730,9 @@
// so we use it as indicator whether Job is still valid.
void OnDnsTaskFailure(const base::WeakPtr<DnsTask>& dns_task,
base::TimeDelta duration,
- int net_error) {
+ const HostCache::Entry& failure_results) {
+ DCHECK_NE(OK, failure_results.error());
+
UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.FailureTime", duration);
if (!dns_task)
@@ -1674,12 +1740,12 @@
if (duration < base::TimeDelta::FromMilliseconds(10)) {
base::UmaHistogramSparse("Net.DNS.DnsTask.ErrorBeforeFallback.Fast",
- std::abs(net_error));
+ std::abs(failure_results.error()));
} else {
base::UmaHistogramSparse("Net.DNS.DnsTask.ErrorBeforeFallback.Slow",
- std::abs(net_error));
+ std::abs(failure_results.error()));
}
- dns_task_error_ = net_error;
+ dns_task_error_ = failure_results.error();
// TODO(szym): Run ServeFromHosts now if nsswitch.conf says so.
// http://crbug.com/117655
@@ -1692,50 +1758,42 @@
StartProcTask();
} else {
UmaAsyncDnsResolveStatus(RESOLVE_STATUS_FAIL);
- // 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 */);
+ base::TimeDelta ttl = failure_results.has_ttl()
+ ? failure_results.ttl()
+ : base::TimeDelta::FromSeconds(0);
+ CompleteRequests(failure_results, ttl, true /* allow_cache */);
}
}
// HostResolverImpl::DnsTask::Delegate implementation:
void OnDnsTaskComplete(base::TimeTicks start_time,
- int net_error,
- const AddressList& addr_list,
- base::TimeDelta ttl) override {
+ const HostCache::Entry& results) override {
DCHECK(is_dns_running());
base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
- if (net_error != OK) {
- OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, net_error);
+ if (results.error() != OK) {
+ OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, results);
return;
}
UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.DnsTask.SuccessTime", duration);
UmaAsyncDnsResolveStatus(RESOLVE_STATUS_DNS_SUCCESS);
- RecordTTL(ttl);
+ RecordTTL(results.ttl());
resolver_->OnDnsTaskResolve();
- base::TimeDelta bounded_ttl =
- std::max(ttl, base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
+ base::TimeDelta bounded_ttl = std::max(
+ results.ttl(), base::TimeDelta::FromSeconds(kMinimumTTLSeconds));
- if (ContainsIcannNameCollisionIp(addr_list)) {
+ if (results.addresses() &&
+ ContainsIcannNameCollisionIp(results.addresses().value())) {
CompleteRequestsWithError(ERR_ICANN_NAME_COLLISION);
- } else {
- CompleteRequests(MakeCacheEntryWithTTL(net_error, addr_list,
- HostCache::Entry::SOURCE_DNS, ttl),
- bounded_ttl, true /* allow_cache */);
+ return;
}
+
+ CompleteRequests(results, bounded_ttl, true /* allow_cache */);
}
void OnFirstDnsTransactionComplete() override {
@@ -1774,18 +1832,18 @@
base::BindOnce(&Job::OnMdnsTaskComplete, base::Unretained(this)));
}
- void OnMdnsTaskComplete(int error) {
+ void OnMdnsTaskComplete() {
DCHECK(is_mdns_running());
// TODO(crbug.com/846423): Consider adding MDNS-specific logging.
- if (error != OK) {
- CompleteRequestsWithError(error);
- } else if (ContainsIcannNameCollisionIp(mdns_task_->result_addresses())) {
+ HostCache::Entry results = mdns_task_->GetResults();
+ if (results.addresses() &&
+ ContainsIcannNameCollisionIp(results.addresses().value())) {
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(error, mdns_task_->result_addresses());
+ CompleteRequestsWithoutCache(results);
}
}
@@ -1877,7 +1935,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& entry,
+ void CompleteRequests(const HostCache::Entry& results,
base::TimeDelta ttl,
bool allow_cache) {
CHECK(resolver_.get());
@@ -1908,23 +1966,23 @@
}
net_log_.EndEventWithNetErrorCode(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
- entry.error());
+ results.error());
DCHECK(!requests_.empty());
- if (entry.error() == OK || entry.error() == ERR_ICANN_NAME_COLLISION) {
+ if (results.error() == OK || results.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 = (entry.error() != ERR_NETWORK_CHANGED) &&
- (entry.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
+ bool did_complete = (results.error() != ERR_NETWORK_CHANGED) &&
+ (results.error() != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE);
if (did_complete && allow_cache)
- resolver_->CacheResult(key_, entry, ttl);
+ resolver_->CacheResult(key_, results, ttl);
- RecordJobHistograms(entry.error());
+ RecordJobHistograms(results.error());
// Complete all of the requests that were attached to the job and
// detach them.
@@ -1933,18 +1991,17 @@
req->RemoveFromList();
DCHECK_EQ(this, req->job());
// Update the net log and notify registered observers.
- LogFinishRequest(req->source_net_log(), entry.error());
+ LogFinishRequest(req->source_net_log(), results.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 (entry.error() == OK && !req->parameters().is_speculative) {
- req->set_address_results(EnsurePortOnAddressList(
- entry.addresses().value(), req->request_host().port()));
+ if (results.error() == OK && !req->parameters().is_speculative) {
+ req->set_results(SetPortOnResults(results, req->request_host().port()));
}
- req->OnJobCompleted(this, entry.error());
+ req->OnJobCompleted(this, results.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.
@@ -1953,17 +2010,16 @@
}
}
- void CompleteRequestsWithoutCache(int error, const AddressList& addresses) {
- CompleteRequests(
- MakeCacheEntry(error, addresses, HostCache::Entry::SOURCE_UNKNOWN),
- base::TimeDelta(), false /* allow_cache */);
+ void CompleteRequestsWithoutCache(const HostCache::Entry& results) {
+ CompleteRequests(results, base::TimeDelta(), false /* allow_cache */);
}
// Convenience wrapper for CompleteRequests in case of failure.
void CompleteRequestsWithError(int net_error) {
- CompleteRequests(HostCache::Entry(net_error, AddressList(),
- HostCache::Entry::SOURCE_UNKNOWN),
- base::TimeDelta(), true /* allow_cache */);
+ DCHECK_NE(OK, net_error);
+ CompleteRequests(
+ HostCache::Entry(net_error, HostCache::Entry::SOURCE_UNKNOWN),
+ base::TimeDelta(), true /* allow_cache */);
}
RequestPriority priority() const override {
@@ -2184,14 +2240,20 @@
LogStartRequest(source_net_log, info);
Key key;
- int rv = ResolveLocally(
- info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()),
+ 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(), false /* allow_stale */,
- nullptr /* stale_info */, source_net_log, addresses, &key);
+ nullptr /* stale_info */, source_net_log, &key);
- LogFinishRequest(source_net_log, rv);
- return rv;
+ if (results.addresses()) {
+ *addresses = AddressList::CopyWithPort(results.addresses().value(),
+ info.host_port_pair().port());
+ }
+
+ LogFinishRequest(source_net_log, results.error());
+ return results.error();
}
int HostResolverImpl::ResolveStaleFromCache(
@@ -2207,13 +2269,20 @@
LogStartRequest(source_net_log, info);
Key key;
- 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;
+ 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();
}
void HostResolverImpl::SetDnsClientEnabled(bool enabled) {
@@ -2357,96 +2426,103 @@
LogStartRequest(request->source_net_log(), request->request_host());
- AddressList addresses;
Key key;
- int rv = ResolveLocally(
- request->request_host(), request->parameters().dns_query_type,
+ HostCache::Entry results = ResolveLocally(
+ request->request_host().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(), &addresses, &key);
- if (rv == OK && !request->parameters().is_speculative) {
- request->set_address_results(
- EnsurePortOnAddressList(addresses, request->request_host().port()));
+ 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()));
}
- if (rv != ERR_DNS_CACHE_MISS) {
- LogFinishRequest(request->source_net_log(), rv);
+ if (results.error() != ERR_DNS_CACHE_MISS) {
+ LogFinishRequest(request->source_net_log(), results.error());
RecordTotalTime(request->parameters().is_speculative, true /* from_cache */,
base::TimeDelta());
- return rv;
+ return results.error();
}
- rv = CreateAndStartJob(key, request);
+ int rv = CreateAndStartJob(key, request);
// At this point, expect only async or errors.
DCHECK_NE(OK, rv);
return rv;
}
-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) {
+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) {
IPAddress ip_address;
IPAddress* ip_address_ptr = nullptr;
- if (ip_address.AssignFromIPLiteral(host.host())) {
+ if (ip_address.AssignFromIPLiteral(hostname)) {
ip_address_ptr = &ip_address;
} else {
// Check that the caller supplied a valid hostname to resolve.
- if (!IsValidDNSDomain(host.host()))
- return ERR_NAME_NOT_RESOLVED;
+ if (!IsValidDNSDomain(hostname)) {
+ return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
+ HostCache::Entry::SOURCE_UNKNOWN);
+ }
}
// Build a key that identifies the request in the cache and in the
// outstanding jobs map.
- *key = GetEffectiveKeyForRequest(host.host(), dns_query_type, source, flags,
- ip_address_ptr, source_net_log);
+ *out_key = GetEffectiveKeyForRequest(hostname, 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 (host.host().empty() || host.host().size() > kMaxHostLength) {
+ if (hostname.empty() || hostname.size() > kMaxHostLength) {
MakeNotStale(stale_info);
- return ERR_NAME_NOT_RESOLVED;
+ return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
+ HostCache::Entry::SOURCE_UNKNOWN);
}
- int net_error = ERR_UNEXPECTED;
- if (ResolveAsIP(*key, host.port(), ip_address_ptr, &net_error, addresses)) {
+ base::Optional<HostCache::Entry> resolved =
+ ResolveAsIP(*out_key, ip_address_ptr);
+ if (resolved) {
MakeNotStale(stale_info);
- return net_error;
+ return resolved.value();
}
// Special-case localhost names, as per the recommendations in
// https://tools.ietf.org/html/draft-west-let-localhost-be-localhost.
- if (ServeLocalhost(*key, host.port(), addresses)) {
+ resolved = ServeLocalhost(*out_key);
+ if (resolved) {
MakeNotStale(stale_info);
- return OK;
+ 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;
+ 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();
+ }
}
// TODO(szym): Do not do this if nsswitch.conf instructs not to.
// http://crbug.com/117655
- if (ServeFromHosts(*key, host.port(), addresses)) {
+ resolved = ServeFromHosts(*out_key);
+ if (resolved) {
source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_HOSTS_HIT,
- addresses->CreateNetLogCallback());
+ resolved.value().CreateNetLogCallback());
MakeNotStale(stale_info);
- return OK;
+ return resolved.value();
}
- return ERR_DNS_CACHE_MISS;
+ return HostCache::Entry(ERR_DNS_CACHE_MISS, HostCache::Entry::SOURCE_UNKNOWN);
}
int HostResolverImpl::CreateAndStartJob(const Key& key, RequestImpl* request) {
@@ -2480,41 +2556,34 @@
return ERR_IO_PENDING;
}
-bool HostResolverImpl::ResolveAsIP(const Key& key,
- uint16_t host_port,
- const IPAddress* ip_address,
- int* net_error,
- AddressList* addresses) {
- DCHECK(addresses);
- DCHECK(net_error);
+base::Optional<HostCache::Entry> HostResolverImpl::ResolveAsIP(
+ const Key& key,
+ const IPAddress* ip_address) {
if (ip_address == nullptr || !IsAddressType(key.dns_query_type))
- return false;
+ return base::nullopt;
- *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.
- *net_error = ERR_NAME_NOT_RESOLVED;
- } else {
- *addresses = AddressList::CreateFromIPAddress(*ip_address, host_port);
- if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)
- addresses->SetDefaultCanonicalName();
+ return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
+ HostCache::Entry::SOURCE_UNKNOWN);
}
- return true;
+
+ 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);
}
-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);
+base::Optional<HostCache::Entry> HostResolverImpl::ServeFromCache(
+ const Key& key,
+ bool allow_stale,
+ HostCache::EntryStaleness* stale_info) {
DCHECK(allow_stale == !!stale_info);
if (!cache_.get())
- return false;
+ return base::nullopt;
const HostCache::Entry* cache_entry;
if (allow_stale)
@@ -2522,25 +2591,20 @@
else
cache_entry = cache_->Lookup(key, tick_clock_->NowTicks());
if (!cache_entry)
- return false;
+ return base::nullopt;
- *net_error = cache_entry->error();
- if (*net_error == OK) {
+ if (cache_entry->error() == OK) {
if (cache_entry->has_ttl())
RecordTTL(cache_entry->ttl());
- *addresses =
- EnsurePortOnAddressList(cache_entry->addresses().value(), host_port);
}
- return true;
+
+ return *cache_entry;
}
-bool HostResolverImpl::ServeFromHosts(const Key& key,
- uint16_t host_port,
- AddressList* addresses) {
- DCHECK(addresses);
- if (!HaveDnsConfig())
- return false;
- addresses->clear();
+base::Optional<HostCache::Entry> HostResolverImpl::ServeFromHosts(
+ const Key& key) {
+ if (!HaveDnsConfig() || !IsAddressType(key.dns_query_type))
+ return base::nullopt;
// HOSTS lookups are case-insensitive.
std::string hostname = base::ToLowerASCII(key.hostname);
@@ -2552,64 +2616,70 @@
// 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, host_port));
+ addresses.push_back(IPEndPoint(it->second, 0));
}
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, host_port));
+ addresses.push_back(IPEndPoint(it->second, 0));
}
// 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, host_port, addresses);
+ return ServeFromHosts(new_key);
}
- return !addresses->empty();
+
+ if (!addresses.empty()) {
+ return HostCache::Entry(OK, std::move(addresses),
+ HostCache::Entry::SOURCE_HOSTS);
+ }
+
+ return base::nullopt;
}
-bool HostResolverImpl::ServeLocalhost(const Key& key,
- uint16_t host_port,
- AddressList* addresses) {
+base::Optional<HostCache::Entry> HostResolverImpl::ServeLocalhost(
+ const Key& key) {
AddressList resolved_addresses;
- if (!ResolveLocalHostname(key.hostname, host_port, &resolved_addresses))
- return false;
+ if (!IsAddressType(key.dns_query_type) ||
+ !ResolveLocalHostname(key.hostname, &resolved_addresses)) {
+ return base::nullopt;
+ }
- 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);
- }
+ 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);
}
}
- return true;
+ return HostCache::Entry(OK, std::move(filtered_addresses),
+ HostCache::Entry::SOURCE_UNKNOWN);
}
void HostResolverImpl::CacheResult(const Key& key,