Revert "Allow and sort multi-address hosts entries"
This reverts commit 59be7b29cd
.
Reason for revert: Suspected to cause lots of flaky tests on Linux ASAN https://crbug.com/1266340
Original change's description:
> Allow and sort multi-address hosts entries
>
> Instead of a single IPAddress, HOSTS files are parsed to a
> std::vector<IPAddress> of all addresses for the same hostname, in the
> order they appear in the file. Any entry with 2 or more addresses is
> then run through the AddressSorter during the SerialWorker "followup"
> phase of HostsReader.
>
> Fixed: 1257639
> Change-Id: Iae36a1e22aa3a7cd985938de96acac101b01e824
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3226048
> Commit-Queue: Eric Orth <ericorth@chromium.org>
> Reviewed-by: Dan McArdle <dmcardle@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#937054}
Bug: 1266340, 1257639
Change-Id: Ib73ee34a74948733dc2c11444077b7ae5fd20855
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3259045
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Christian Dullweber <dullweber@chromium.org>
Commit-Queue: Lingqi Chi <lingqi@chromium.org>
Owners-Override: Christian Dullweber <dullweber@chromium.org>
Auto-Submit: Christian Dullweber <dullweber@chromium.org>
Reviewed-by: Lingqi Chi <lingqi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#937822}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
bc28ed33bb
commit
1b2df5916d
net
base
dns
BUILD.gnaddress_sorter.haddress_sorter_ios.ccaddress_sorter_posix.ccaddress_sorter_posix.haddress_sorter_posix_unittest.ccaddress_sorter_unittest.ccaddress_sorter_win.ccdns_config_service.ccdns_config_service.hdns_config_service_unittest.ccdns_config_service_win.ccdns_hosts.ccdns_hosts.hdns_hosts_unittest.ccfuzzed_host_resolver_util.cchost_resolver_manager.cchost_resolver_manager_unittest.cctest_dns_config_service.cctest_dns_config_service.h
@ -6,7 +6,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <ostream>
|
||||
|
||||
#include "base/check_op.h"
|
||||
#include "base/containers/stack_container.h"
|
||||
@ -504,8 +503,4 @@ size_t MaskPrefixLength(const IPAddress& mask) {
|
||||
IPAddress(all_ones->data(), all_ones->size()));
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const IPAddress& ip_address) {
|
||||
return os << ip_address.ToString();
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -300,9 +299,6 @@ bool IPAddressStartsWith(const IPAddress& address, const uint8_t (&prefix)[N]) {
|
||||
return std::equal(prefix, prefix + N, address.bytes().begin());
|
||||
}
|
||||
|
||||
NET_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
|
||||
const IPAddress& ip_address);
|
||||
|
||||
} // namespace net
|
||||
|
||||
#endif // NET_BASE_IP_ADDRESS_H_
|
||||
|
@ -106,10 +106,6 @@ source_set("dns") {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
sources += [ "address_sorter_ios.cc" ]
|
||||
}
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"dns_config_service_android.cc",
|
||||
@ -419,7 +415,7 @@ source_set("tests") {
|
||||
sources += [ "dns_config_service_android_unittest.cc" ]
|
||||
} else if (is_linux) {
|
||||
sources += [ "dns_config_service_linux_unittest.cc" ]
|
||||
} else if (is_posix && !is_ios) {
|
||||
} else if (is_posix) {
|
||||
sources += [ "dns_config_service_posix_unittest.cc" ]
|
||||
}
|
||||
|
||||
|
@ -9,18 +9,20 @@
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/macros.h"
|
||||
#include "net/base/address_list.h"
|
||||
#include "net/base/net_export.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
class AddressList;
|
||||
|
||||
// Sorts AddressList according to RFC3484, by likelihood of successful
|
||||
// connection. Depending on the platform, the sort could be performed
|
||||
// asynchronously by the OS, or synchronously by local implementation.
|
||||
// AddressSorter does not necessarily preserve port numbers on the sorted list.
|
||||
class NET_EXPORT AddressSorter {
|
||||
public:
|
||||
using CallbackType = base::OnceCallback<void(bool success, AddressList list)>;
|
||||
using CallbackType =
|
||||
base::OnceCallback<void(bool success, const AddressList& list)>;
|
||||
|
||||
AddressSorter(const AddressSorter&) = delete;
|
||||
AddressSorter& operator=(const AddressSorter&) = delete;
|
||||
|
@ -1,20 +0,0 @@
|
||||
// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "net/dns/address_sorter.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/notreached.h"
|
||||
|
||||
namespace net {
|
||||
|
||||
// static
|
||||
std::unique_ptr<AddressSorter> AddressSorter::CreateAddressSorter() {
|
||||
// Not expected to ever need an AddressSorter on iOS.
|
||||
NOTREACHED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace net
|
@ -264,13 +264,13 @@ AddressSorterPosix::AddressSorterPosix(ClientSocketFactory* socket_factory)
|
||||
}
|
||||
|
||||
AddressSorterPosix::~AddressSorterPosix() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
NetworkChangeNotifier::RemoveIPAddressObserver(this);
|
||||
}
|
||||
|
||||
void AddressSorterPosix::Sort(const AddressList& list,
|
||||
CallbackType callback) const {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
std::vector<std::unique_ptr<DestinationInfo>> sort_list;
|
||||
|
||||
for (size_t i = 0; i < list.size(); ++i) {
|
||||
@ -325,11 +325,11 @@ void AddressSorterPosix::Sort(const AddressList& list,
|
||||
for (size_t i = 0; i < sort_list.size(); ++i)
|
||||
result.push_back(IPEndPoint(sort_list[i]->address, 0 /* port */));
|
||||
|
||||
std::move(callback).Run(true, std::move(result));
|
||||
std::move(callback).Run(true, result);
|
||||
}
|
||||
|
||||
void AddressSorterPosix::OnIPAddressChanged() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
source_map_.clear();
|
||||
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
|
||||
const internal::AddressTrackerLinux* tracker =
|
||||
@ -399,7 +399,7 @@ void AddressSorterPosix::OnIPAddressChanged() {
|
||||
|
||||
void AddressSorterPosix::FillPolicy(const IPAddress& address,
|
||||
SourceAddressInfo* info) const {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
info->scope = GetScope(ipv4_scope_table_, address);
|
||||
info->label = GetPolicyValue(label_table_, address);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "net/base/address_list.h"
|
||||
#include "net/base/ip_address.h"
|
||||
#include "net/base/net_export.h"
|
||||
@ -87,7 +87,7 @@ class NET_EXPORT_PRIVATE AddressSorterPosix
|
||||
PolicyTable label_table_;
|
||||
PolicyTable ipv4_scope_table_;
|
||||
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -199,10 +199,10 @@ class TestSocketFactory : public ClientSocketFactory {
|
||||
void OnSortComplete(AddressList* result_buf,
|
||||
CompletionOnceCallback callback,
|
||||
bool success,
|
||||
AddressList result) {
|
||||
const AddressList& result) {
|
||||
EXPECT_TRUE(success);
|
||||
if (success)
|
||||
*result_buf = std::move(result);
|
||||
*result_buf = result;
|
||||
std::move(callback).Run(OK);
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@ IPEndPoint MakeEndPoint(const std::string& str) {
|
||||
void OnSortComplete(AddressList* result_buf,
|
||||
CompletionOnceCallback callback,
|
||||
bool success,
|
||||
AddressList result) {
|
||||
const AddressList& result) {
|
||||
if (success)
|
||||
*result_buf = std::move(result);
|
||||
*result_buf = result;
|
||||
std::move(callback).Run(success ? OK : ERR_FAILED);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ class AddressSorterWin : public AddressSorter {
|
||||
list.push_back(ipe);
|
||||
}
|
||||
}
|
||||
std::move(callback_).Run(success_, std::move(list));
|
||||
std::move(callback_).Run(success_, list);
|
||||
}
|
||||
|
||||
CallbackType callback_;
|
||||
|
@ -6,11 +6,8 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/barrier_callback.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/location.h"
|
||||
@ -20,8 +17,6 @@
|
||||
#include "base/threading/scoped_blocking_call.h"
|
||||
#include "base/threading/sequenced_task_runner_handle.h"
|
||||
#include "base/time/time.h"
|
||||
#include "net/base/address_list.h"
|
||||
#include "net/dns/address_sorter.h"
|
||||
#include "net/dns/dns_hosts.h"
|
||||
#include "net/dns/serial_worker.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
@ -104,12 +99,9 @@ DnsConfigService::HostsReader::HostsReader(
|
||||
DnsConfigService::HostsReader::~HostsReader() = default;
|
||||
|
||||
DnsConfigService::HostsReader::WorkItem::WorkItem(
|
||||
std::unique_ptr<DnsHostsParser> dns_hosts_parser,
|
||||
std::unique_ptr<AddressSorter> address_sorter)
|
||||
: dns_hosts_parser_(std::move(dns_hosts_parser)),
|
||||
address_sorter_(std::move(address_sorter)) {
|
||||
std::unique_ptr<DnsHostsParser> dns_hosts_parser)
|
||||
: dns_hosts_parser_(std::move(dns_hosts_parser)) {
|
||||
DCHECK(dns_hosts_parser_);
|
||||
DCHECK(address_sorter_);
|
||||
}
|
||||
|
||||
DnsConfigService::HostsReader::WorkItem::~WorkItem() = default;
|
||||
@ -139,89 +131,10 @@ void DnsConfigService::HostsReader::WorkItem::DoWork() {
|
||||
hosts_.reset();
|
||||
}
|
||||
|
||||
void DnsConfigService::HostsReader::WorkItem::FollowupWork(
|
||||
base::OnceClosure closure) {
|
||||
if (!hosts_.has_value()) {
|
||||
std::move(closure).Run();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<const DnsHosts::value_type*> to_sort;
|
||||
for (const auto& host : hosts_.value()) {
|
||||
const std::vector<IPAddress>& addresses = host.second;
|
||||
if (addresses.size() >= 2) {
|
||||
to_sort.push_back(&host);
|
||||
}
|
||||
}
|
||||
|
||||
// This `sort_barrier` is called when each individual sort operation
|
||||
// completes. It accumulates all of the inputs it is given into a vector. When
|
||||
// it is called for the last time (after `to_sort.size()` calls), it invokes
|
||||
// `OnAddressSortComplete()` with that vector of inputs. Should immediately
|
||||
// trigger `OnAddressSortComplete()` if `to_sort` is empty.
|
||||
SortBarrier sort_barrier =
|
||||
base::BarrierCallback<std::pair<DnsHostsKey, AddressList>>(
|
||||
to_sort.size(),
|
||||
base::BindOnce(&WorkItem::OnAddressSortComplete,
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(closure)));
|
||||
|
||||
for (const auto* sort_entry : to_sort) {
|
||||
const DnsHostsKey& key = sort_entry->first;
|
||||
const std::vector<IPAddress>& addresses = sort_entry->second;
|
||||
address_sorter_->Sort(
|
||||
AddressList::CreateFromIPAddressList(addresses,
|
||||
/*aliases=*/{}),
|
||||
base::BindOnce(&WorkItem::OnIndividualAddressSortComplete,
|
||||
weak_ptr_factory_.GetWeakPtr(), key, sort_barrier));
|
||||
}
|
||||
}
|
||||
|
||||
void DnsConfigService::HostsReader::WorkItem::OnIndividualAddressSortComplete(
|
||||
DnsHostsKey key,
|
||||
SortBarrier barrier,
|
||||
bool sort_success,
|
||||
AddressList sorted) {
|
||||
DCHECK(hosts_.has_value());
|
||||
DCHECK(hosts_.value().find(key) != hosts_.value().end());
|
||||
DCHECK_GE(hosts_.value()[key].size(), 2u);
|
||||
|
||||
if (sort_success) {
|
||||
barrier.Run(std::make_pair(std::move(key), std::move(sorted)));
|
||||
} else {
|
||||
barrier.Run(std::make_pair(std::move(key), AddressList()));
|
||||
}
|
||||
}
|
||||
|
||||
void DnsConfigService::HostsReader::WorkItem::OnAddressSortComplete(
|
||||
base::OnceClosure closure,
|
||||
std::vector<std::pair<DnsHostsKey, AddressList>> sorted) {
|
||||
DCHECK(hosts_.has_value());
|
||||
|
||||
for (const std::pair<DnsHostsKey, AddressList>& sorted_host : sorted) {
|
||||
auto it = hosts_.value().find(sorted_host.first);
|
||||
DCHECK(it != hosts_.value().end());
|
||||
DCHECK_GE(it->second.size(), 2u);
|
||||
|
||||
if (sorted_host.second.empty()) {
|
||||
// Empty list means sort failure. Remove from hosts.
|
||||
hosts_.value().erase(it);
|
||||
} else {
|
||||
// Replace `hosts_` entry with addresses from `sorted_host`.
|
||||
it->second.clear();
|
||||
for (const IPEndPoint& endpoint : sorted_host.second) {
|
||||
it->second.push_back(endpoint.address());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::move(closure).Run();
|
||||
}
|
||||
|
||||
std::unique_ptr<SerialWorker::WorkItem>
|
||||
DnsConfigService::HostsReader::CreateWorkItem() {
|
||||
return std::make_unique<WorkItem>(
|
||||
std::make_unique<DnsHostsFileParser>(hosts_file_path_),
|
||||
AddressSorter::CreateAddressSorter());
|
||||
std::make_unique<DnsHostsFileParser>(hosts_file_path_));
|
||||
}
|
||||
|
||||
void DnsConfigService::HostsReader::OnWorkFinished(
|
||||
|
@ -7,9 +7,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
@ -17,7 +15,6 @@
|
||||
#include "base/time/time.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "net/base/net_export.h"
|
||||
#include "net/dns/address_sorter.h"
|
||||
#include "net/dns/dns_config.h"
|
||||
#include "net/dns/dns_hosts.h"
|
||||
#include "net/dns/serial_worker.h"
|
||||
@ -26,8 +23,6 @@
|
||||
|
||||
namespace net {
|
||||
|
||||
class AddressList;
|
||||
|
||||
// Service for reading system DNS settings, on demand or when signalled by
|
||||
// internal watchers and NetworkChangeNotifier. This object is not thread-safe
|
||||
// and methods may perform blocking I/O so methods must be called on a sequence
|
||||
@ -136,8 +131,7 @@ class NET_EXPORT_PRIVATE DnsConfigService {
|
||||
protected:
|
||||
class NET_EXPORT_PRIVATE WorkItem : public SerialWorker::WorkItem {
|
||||
public:
|
||||
WorkItem(std::unique_ptr<DnsHostsParser> dns_hosts_parser,
|
||||
std::unique_ptr<AddressSorter> address_sorter);
|
||||
explicit WorkItem(std::unique_ptr<DnsHostsParser> dns_hosts_parser);
|
||||
~WorkItem() override;
|
||||
|
||||
// Override if needed to implement platform-specific behavior, e.g. for a
|
||||
@ -152,28 +146,12 @@ class NET_EXPORT_PRIVATE DnsConfigService {
|
||||
|
||||
// SerialWorker::WorkItem:
|
||||
void DoWork() final;
|
||||
void FollowupWork(base::OnceClosure closure) final;
|
||||
|
||||
private:
|
||||
friend HostsReader;
|
||||
|
||||
using SortBarrier =
|
||||
base::RepeatingCallback<void(std::pair<DnsHostsKey, AddressList>)>;
|
||||
|
||||
void OnIndividualAddressSortComplete(DnsHostsKey key,
|
||||
SortBarrier barrier,
|
||||
bool success,
|
||||
AddressList sorted);
|
||||
void OnAddressSortComplete(
|
||||
base::OnceClosure closure,
|
||||
std::vector<std::pair<DnsHostsKey, AddressList>> sorted);
|
||||
|
||||
absl::optional<DnsHosts> hosts_;
|
||||
|
||||
std::unique_ptr<DnsHostsParser> dns_hosts_parser_;
|
||||
std::unique_ptr<AddressSorter> address_sorter_;
|
||||
|
||||
base::WeakPtrFactory<WorkItem> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
// SerialWorker:
|
||||
|
@ -7,14 +7,10 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/cancelable_callback.h"
|
||||
#include "base/immediate_crash.h"
|
||||
#include "base/location.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/strings/string_split.h"
|
||||
@ -22,14 +18,10 @@
|
||||
#include "base/task/thread_pool/thread_pool_instance.h"
|
||||
#include "base/test/bind.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/threading/sequenced_task_runner_handle.h"
|
||||
#include "base/test/test_timeouts.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "build/build_config.h"
|
||||
#include "net/base/address_family.h"
|
||||
#include "net/base/address_list.h"
|
||||
#include "net/base/ip_address.h"
|
||||
#include "net/base/ip_endpoint.h"
|
||||
#include "net/dns/address_sorter.h"
|
||||
#include "net/dns/dns_hosts.h"
|
||||
#include "net/dns/public/dns_protocol.h"
|
||||
#include "net/dns/test_dns_config_service.h"
|
||||
@ -43,7 +35,6 @@ namespace {
|
||||
|
||||
using testing::_;
|
||||
using testing::DoAll;
|
||||
using testing::InvokeWithoutArgs;
|
||||
using testing::Return;
|
||||
using testing::SetArgPointee;
|
||||
|
||||
@ -184,54 +175,9 @@ MockHostsParserFactory::GetFactory() {
|
||||
|
||||
DnsHosts::value_type CreateHostsEntry(base::StringPiece name,
|
||||
AddressFamily family,
|
||||
std::vector<IPAddress> addresses) {
|
||||
IPAddress address) {
|
||||
DnsHostsKey key = std::make_pair(std::string(name), family);
|
||||
return std::make_pair(std::move(key), std::move(addresses));
|
||||
}
|
||||
|
||||
// `AddressSorter` that will always crash if invoked. Useful to validate cases
|
||||
// where no sort is expected to be needed.
|
||||
class CrashingAddressSorter : public AddressSorter {
|
||||
public:
|
||||
void Sort(const AddressList& list, CallbackType callback) const override {
|
||||
IMMEDIATE_CRASH();
|
||||
}
|
||||
|
||||
static HostsReadingTestDnsConfigService::AddressSorterFactory GetFactory() {
|
||||
return base::BindRepeating([]() -> std::unique_ptr<AddressSorter> {
|
||||
return std::make_unique<CrashingAddressSorter>();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class MockAddressSorterFactory : public AddressSorter {
|
||||
public:
|
||||
HostsReadingTestDnsConfigService::AddressSorterFactory GetFactory();
|
||||
|
||||
MOCK_METHOD(void,
|
||||
Sort,
|
||||
(const AddressList&, CallbackType),
|
||||
(const, override));
|
||||
|
||||
private:
|
||||
class Delegator : public AddressSorter {
|
||||
public:
|
||||
explicit Delegator(MockAddressSorterFactory* factory) : factory_(factory) {}
|
||||
|
||||
void Sort(const AddressList& list, CallbackType callback) const override {
|
||||
return factory_->Sort(list, std::move(callback));
|
||||
}
|
||||
|
||||
private:
|
||||
MockAddressSorterFactory* factory_;
|
||||
};
|
||||
};
|
||||
|
||||
HostsReadingTestDnsConfigService::AddressSorterFactory
|
||||
MockAddressSorterFactory::GetFactory() {
|
||||
return base::BindLambdaForTesting([this]() -> std::unique_ptr<AddressSorter> {
|
||||
return std::make_unique<Delegator>(this);
|
||||
});
|
||||
return std::make_pair(std::move(key), address);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -377,8 +323,8 @@ TEST_F(DnsConfigServiceTest, HostsReadFailure) {
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(DnsHosts()), Return(false)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
service->OnConfigRead(MakeConfig(1));
|
||||
@ -396,8 +342,8 @@ TEST_F(DnsConfigServiceTest, ReadEmptyHosts) {
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(DnsHosts()), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
@ -422,8 +368,8 @@ TEST_F(DnsConfigServiceTest, ReadSingleHosts) {
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
@ -452,8 +398,8 @@ TEST_F(DnsConfigServiceTest, ReadMultipleHosts) {
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
@ -479,8 +425,8 @@ TEST_F(DnsConfigServiceTest, HostsReadSubsequentFailure) {
|
||||
.WillOnce(DoAll(SetArgPointee<0>(hosts), Return(true)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(DnsHosts()), Return(false)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
@ -505,8 +451,8 @@ TEST_F(DnsConfigServiceTest, HostsReadSubsequentSuccess) {
|
||||
.WillOnce(DoAll(SetArgPointee<0>(DnsHosts()), Return(false)))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
@ -529,8 +475,8 @@ TEST_F(DnsConfigServiceTest, ConfigReadDuringHostsReRead) {
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
@ -566,8 +512,8 @@ TEST_F(DnsConfigServiceTest, HostsWatcherFailure) {
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), CrashingAddressSorter::GetFactory());
|
||||
auto service =
|
||||
std::make_unique<HostsReadingTestDnsConfigService>(parser.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
@ -583,282 +529,4 @@ TEST_F(DnsConfigServiceTest, HostsWatcherFailure) {
|
||||
EXPECT_EQ(last_config_, DnsConfig());
|
||||
}
|
||||
|
||||
TEST_F(DnsConfigServiceTest, ReadMultiAddressHosts) {
|
||||
DnsHosts hosts = {
|
||||
CreateHostsEntry(
|
||||
"name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2), IPAddress(3, 3, 3, 3),
|
||||
IPAddress(4, 4, 4, 4), IPAddress(5, 5, 5, 5)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(6, 6, 6, 6)})};
|
||||
|
||||
MockHostsParserFactory parser;
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
// AddressSorter that reverses order and then removes element 3 (if 4 or more
|
||||
// elements). Really just an arbitrary operation to prove the sort occurred.
|
||||
MockAddressSorterFactory sorter;
|
||||
EXPECT_CALL(sorter, Sort(_, _))
|
||||
.WillRepeatedly(
|
||||
[](const AddressList& list, AddressSorter::CallbackType callback) {
|
||||
std::vector<IPEndPoint> reversed = list.endpoints();
|
||||
base::ranges::reverse(reversed);
|
||||
|
||||
AddressList sorted;
|
||||
for (size_t i = 0; i < reversed.size(); ++i) {
|
||||
if (i == 3)
|
||||
continue;
|
||||
sorted.push_back(reversed[i]);
|
||||
}
|
||||
|
||||
std::move(callback).Run(/*success=*/true, sorted);
|
||||
});
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), sorter.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
service->OnConfigRead(config);
|
||||
|
||||
DnsHosts expected_hosts = {
|
||||
CreateHostsEntry("name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(5, 5, 5, 5), IPAddress(4, 4, 4, 4),
|
||||
IPAddress(3, 3, 3, 3), IPAddress(1, 1, 1, 1)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(6, 6, 6, 6)})};
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
// been read on initting watch in `SetUpService()`.
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, expected_hosts);
|
||||
|
||||
// No change from retriggering read.
|
||||
service->TriggerHostsChangeNotification(/*success=*/true);
|
||||
ValidateNoNotification();
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, expected_hosts);
|
||||
}
|
||||
|
||||
TEST_F(DnsConfigServiceTest, ReadMultipleMultiAddressHosts) {
|
||||
DnsHosts hosts = {
|
||||
CreateHostsEntry(
|
||||
"name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2), IPAddress(3, 3, 3, 3),
|
||||
IPAddress(4, 4, 4, 4), IPAddress(5, 5, 5, 5)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(6, 6, 6, 6)}),
|
||||
CreateHostsEntry("name3", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(7, 7, 7, 7), IPAddress(8, 8, 8, 8)})};
|
||||
|
||||
MockHostsParserFactory parser;
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
// AddressSorter that reverses order and then removes element 3 (if 4 or more
|
||||
// elements). Really just an arbitrary operation to prove the sort occurred.
|
||||
MockAddressSorterFactory sorter;
|
||||
EXPECT_CALL(sorter, Sort(_, _))
|
||||
.WillRepeatedly(
|
||||
[](const AddressList& list, AddressSorter::CallbackType callback) {
|
||||
std::vector<IPEndPoint> reversed = list.endpoints();
|
||||
base::ranges::reverse(reversed);
|
||||
|
||||
AddressList sorted;
|
||||
for (size_t i = 0; i < reversed.size(); ++i) {
|
||||
if (i == 3)
|
||||
continue;
|
||||
sorted.push_back(reversed[i]);
|
||||
}
|
||||
|
||||
std::move(callback).Run(/*success=*/true, sorted);
|
||||
});
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), sorter.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
service->OnConfigRead(config);
|
||||
|
||||
DnsHosts expected_hosts = {
|
||||
CreateHostsEntry("name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(5, 5, 5, 5), IPAddress(4, 4, 4, 4),
|
||||
IPAddress(3, 3, 3, 3), IPAddress(1, 1, 1, 1)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(6, 6, 6, 6)}),
|
||||
CreateHostsEntry("name3", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(8, 8, 8, 8), IPAddress(7, 7, 7, 7)})};
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
// been read on initting watch in `SetUpService()`.
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, expected_hosts);
|
||||
|
||||
// No change from retriggering read.
|
||||
service->TriggerHostsChangeNotification(/*success=*/true);
|
||||
ValidateNoNotification();
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, expected_hosts);
|
||||
}
|
||||
|
||||
TEST_F(DnsConfigServiceTest, FailedSortResultsAreExcluded) {
|
||||
DnsHosts hosts = {
|
||||
CreateHostsEntry("name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(3, 3, 3, 3)})};
|
||||
|
||||
MockHostsParserFactory parser;
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
// AddressSorter that always fails.
|
||||
MockAddressSorterFactory sorter;
|
||||
EXPECT_CALL(sorter, Sort(_, _))
|
||||
.WillRepeatedly(
|
||||
[](const AddressList& list, AddressSorter::CallbackType callback) {
|
||||
std::move(callback).Run(/*success=*/false, AddressList());
|
||||
});
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), sorter.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
service->OnConfigRead(config);
|
||||
|
||||
// Expect only the unsorted single-address entry.
|
||||
DnsHosts expected_hosts = {
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(3, 3, 3, 3)})};
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
// been read on initting watch in `SetUpService()`.
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, expected_hosts);
|
||||
|
||||
// No change from retriggering read.
|
||||
service->TriggerHostsChangeNotification(/*success=*/true);
|
||||
ValidateNoNotification();
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, expected_hosts);
|
||||
}
|
||||
|
||||
TEST_F(DnsConfigServiceTest, HandlesAsyncSort) {
|
||||
DnsHosts hosts = {
|
||||
CreateHostsEntry("name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(3, 3, 3, 3)})};
|
||||
|
||||
MockHostsParserFactory parser;
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
// Noop sorter that always succeeds and doesn't change any ordering, but does
|
||||
// so asynchronously.
|
||||
MockAddressSorterFactory sorter;
|
||||
EXPECT_CALL(sorter, Sort(_, _))
|
||||
.WillRepeatedly(
|
||||
[](const AddressList& list, AddressSorter::CallbackType callback) {
|
||||
base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(std::move(callback), /*success=*/true, list));
|
||||
});
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), sorter.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
service->OnConfigRead(config);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
// been read on initting watch in `SetUpService()`.
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, hosts);
|
||||
|
||||
// No change from retriggering read.
|
||||
service->TriggerHostsChangeNotification(/*success=*/true);
|
||||
ValidateNoNotification();
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
EXPECT_EQ(last_config_.hosts, hosts);
|
||||
}
|
||||
|
||||
TEST_F(DnsConfigServiceTest, DestroyServiceDuringSort) {
|
||||
DnsHosts hosts = {
|
||||
CreateHostsEntry("name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(3, 3, 3, 3)})};
|
||||
|
||||
MockHostsParserFactory parser;
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
// Sorter that saves out the callback and never invokes it itself.
|
||||
MockAddressSorterFactory sorter;
|
||||
AddressSorter::CallbackType saved_callback;
|
||||
EXPECT_CALL(sorter, Sort(_, _))
|
||||
.WillOnce([&saved_callback](const AddressList& list,
|
||||
AddressSorter::CallbackType callback) {
|
||||
saved_callback = std::move(callback);
|
||||
});
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(), sorter.GetFactory());
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
service->OnConfigRead(config);
|
||||
|
||||
// Expect hung sorting.
|
||||
EXPECT_EQ(last_config_, DnsConfig());
|
||||
ASSERT_TRUE(saved_callback);
|
||||
|
||||
// Destroy the service and then resume the sort.
|
||||
service.reset();
|
||||
std::move(saved_callback).Run(/*success=*/true, AddressList());
|
||||
ValidateNoNotification();
|
||||
EXPECT_EQ(last_config_, DnsConfig());
|
||||
}
|
||||
|
||||
// Only test actual platform sort on platforms with a sort implementation.
|
||||
#if !defined(OS_IOS)
|
||||
TEST_F(DnsConfigServiceTest, ActualPlatformSort) {
|
||||
DnsHosts hosts = {
|
||||
CreateHostsEntry("name1", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2)}),
|
||||
CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4, {IPAddress(3, 3, 3, 3)})};
|
||||
|
||||
MockHostsParserFactory parser;
|
||||
EXPECT_CALL(parser, ParseHosts(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(hosts), Return(true)));
|
||||
|
||||
auto service = std::make_unique<HostsReadingTestDnsConfigService>(
|
||||
parser.GetFactory(),
|
||||
base::BindRepeating(&AddressSorter::CreateAddressSorter));
|
||||
SetUpService(*service);
|
||||
|
||||
DnsConfig config = MakeConfig(1);
|
||||
service->OnConfigRead(config);
|
||||
|
||||
// Expect immediate result on reading config because HOSTS should already have
|
||||
// been read on initting watch in `SetUpService()`.
|
||||
EXPECT_TRUE(last_config_.EqualsIgnoreHosts(config));
|
||||
|
||||
// Expect results to at least contain the single-address result.
|
||||
EXPECT_LE(last_config_.hosts.size(), 2u);
|
||||
EXPECT_THAT(last_config_.hosts,
|
||||
testing::Contains(CreateHostsEntry("name2", ADDRESS_FAMILY_IPV4,
|
||||
{IPAddress(3, 3, 3, 3)})));
|
||||
|
||||
// Expect results to maybe contain the multi-address result with 1 or 2 of the
|
||||
// addresses. Specific addresses and order could depend on system
|
||||
// configuration.
|
||||
auto multi_address_entry =
|
||||
last_config_.hosts.find(DnsHostsKey("name1", ADDRESS_FAMILY_IPV4));
|
||||
if (multi_address_entry != last_config_.hosts.end()) {
|
||||
EXPECT_FALSE(multi_address_entry->second.empty());
|
||||
EXPECT_THAT(
|
||||
multi_address_entry->second,
|
||||
testing::IsSubsetOf({IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2)}));
|
||||
}
|
||||
}
|
||||
#endif // !defined(OS_IOS)
|
||||
|
||||
} // namespace net
|
||||
|
@ -91,13 +91,11 @@ bool AddLocalhostEntriesTo(DnsHosts& in_out_hosts) {
|
||||
IPAddress loopback_ipv4 = IPAddress::IPv4Localhost();
|
||||
IPAddress loopback_ipv6 = IPAddress::IPv6Localhost();
|
||||
|
||||
// Should only add "localhost" entries if not already present in the file.
|
||||
// Accomplish this by relying on `std::map::emplace()`s behavior of not
|
||||
// modifying the map when the key is already present.
|
||||
in_out_hosts.emplace(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4),
|
||||
std::vector<IPAddress>{loopback_ipv4});
|
||||
in_out_hosts.emplace(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6),
|
||||
std::vector<IPAddress>{loopback_ipv6});
|
||||
// This does not override any pre-existing entries from the HOSTS file.
|
||||
in_out_hosts.insert(std::make_pair(
|
||||
DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4), loopback_ipv4));
|
||||
in_out_hosts.insert(std::make_pair(
|
||||
DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6), loopback_ipv6));
|
||||
|
||||
wchar_t buffer[MAX_PATH];
|
||||
DWORD size = MAX_PATH;
|
||||
@ -141,12 +139,12 @@ bool AddLocalhostEntriesTo(DnsHosts& in_out_hosts) {
|
||||
}
|
||||
if (!have_ipv4 && (ipe.GetFamily() == ADDRESS_FAMILY_IPV4)) {
|
||||
have_ipv4 = true;
|
||||
in_out_hosts[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] = {
|
||||
ipe.address()};
|
||||
in_out_hosts[DnsHostsKey(localname, ADDRESS_FAMILY_IPV4)] =
|
||||
ipe.address();
|
||||
} else if (!have_ipv6 && (ipe.GetFamily() == ADDRESS_FAMILY_IPV6)) {
|
||||
have_ipv6 = true;
|
||||
in_out_hosts[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] = {
|
||||
ipe.address()};
|
||||
in_out_hosts[DnsHostsKey(localname, ADDRESS_FAMILY_IPV6)] =
|
||||
ipe.address();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -562,8 +560,8 @@ class DnsConfigServiceWin::HostsReader : public DnsConfigService::HostsReader {
|
||||
public:
|
||||
explicit WorkItem(base::FilePath hosts_file_path)
|
||||
: DnsConfigService::HostsReader::WorkItem(
|
||||
std::make_unique<DnsHostsFileParser>(std::move(hosts_file_path)),
|
||||
AddressSorter::CreateAddressSorter()) {}
|
||||
std::make_unique<DnsHostsFileParser>(
|
||||
std::move(hosts_file_path))) {}
|
||||
|
||||
~WorkItem() override = default;
|
||||
|
||||
|
@ -165,7 +165,10 @@ void ParseHostsWithCommaMode(const std::string& contents,
|
||||
if (!IsValidDNSDomain(key.first))
|
||||
continue;
|
||||
key.first = base::ToLowerASCII(key.first);
|
||||
(*dns_hosts)[key].push_back(ip);
|
||||
IPAddress* mapped_ip = &(*dns_hosts)[key];
|
||||
if (mapped_ip->empty())
|
||||
*mapped_ip = ip;
|
||||
// else ignore this entry (first hit counts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,12 +43,14 @@ enum ParseHostsCommaMode {
|
||||
// Parsed results of a Hosts file.
|
||||
//
|
||||
// Although Hosts files map IP address to a list of domain names, for name
|
||||
// resolution the desired mapping direction is: (domain name, address family) to
|
||||
// IP address. A (domain name, address family) pair may match with multiple IP
|
||||
// addresses (stored as a `std::vector`) if the same name appears in multiple
|
||||
// (IP address) -> hostname mapping entries for the same family.
|
||||
using DnsHosts =
|
||||
std::unordered_map<DnsHostsKey, std::vector<IPAddress>, DnsHostsKeyHash>;
|
||||
// resolution the desired mapping direction is: domain name to IP address.
|
||||
// When parsing Hosts, we apply the "first hit" rule as Windows and glibc do.
|
||||
// With a Hosts file of:
|
||||
// 300.300.300.300 localhost # bad ip
|
||||
// 127.0.0.1 localhost
|
||||
// 10.0.0.1 localhost
|
||||
// The expected resolution of localhost is 127.0.0.1.
|
||||
using DnsHosts = std::unordered_map<DnsHostsKey, IPAddress, DnsHostsKeyHash>;
|
||||
|
||||
// Parses |contents| (as read from /etc/hosts or equivalent) and stores results
|
||||
// in |dns_hosts|. Invalid lines are ignored (as in most implementations).
|
||||
@ -60,8 +62,7 @@ void NET_EXPORT_PRIVATE ParseHostsWithCommaModeForTesting(
|
||||
ParseHostsCommaMode comma_mode);
|
||||
|
||||
// Parses |contents| (as read from /etc/hosts or equivalent) and stores results
|
||||
// in |dns_hosts|, with addresses in the order in which they were read. Invalid
|
||||
// lines are ignored (as in most implementations).
|
||||
// in |dns_hosts|. Invalid lines are ignored (as in most implementations).
|
||||
void NET_EXPORT_PRIVATE ParseHosts(const std::string& contents,
|
||||
DnsHosts* dns_hosts);
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "net/dns/dns_hosts.h"
|
||||
|
||||
#include "base/cxx17_backports.h"
|
||||
#include "build/build_config.h"
|
||||
#include "net/base/ip_address.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -24,10 +23,11 @@ void PopulateExpectedHosts(const ExpectedHostsEntry* entries,
|
||||
DnsHosts* expected_hosts_out) {
|
||||
for (size_t i = 0; i < num_entries; ++i) {
|
||||
DnsHostsKey key(entries[i].host, entries[i].family);
|
||||
IPAddress ip;
|
||||
ASSERT_TRUE(ip.AssignFromIPLiteral(entries[i].ip));
|
||||
ASSERT_EQ(ip.size(), (entries[i].family == ADDRESS_FAMILY_IPV4) ? 4u : 16u);
|
||||
(*expected_hosts_out)[key].push_back(ip);
|
||||
IPAddress& ip_ref = (*expected_hosts_out)[key];
|
||||
ASSERT_TRUE(ip_ref.empty());
|
||||
ASSERT_TRUE(ip_ref.AssignFromIPLiteral(entries[i].ip));
|
||||
ASSERT_EQ(ip_ref.size(),
|
||||
(entries[i].family == ADDRESS_FAMILY_IPV4) ? 4u : 16u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ TEST(DnsHostsTest, ParseHosts) {
|
||||
const std::string kContents =
|
||||
"127.0.0.1 localhost # standard\n"
|
||||
"\n"
|
||||
"1.0.0.1 localhost\n"
|
||||
"1.0.0.1 localhost # ignored, first hit above\n"
|
||||
"fe00::x example company # ignored, malformed IPv6\n"
|
||||
"1.0.0.300 company # ignored, malformed IPv4\n"
|
||||
"1.0.0.1 # ignored, missing hostname\n"
|
||||
@ -43,7 +43,7 @@ TEST(DnsHostsTest, ParseHosts) {
|
||||
"::1\tlocalhost ip6-localhost ip6-loopback # comment # within a comment\n"
|
||||
"\t fe00::0 ip6-localnet\r\n"
|
||||
"2048::2 example\n"
|
||||
"2048::1 company example\n"
|
||||
"2048::1 company example # ignored for 'example' \n"
|
||||
"127.0.0.1 cache1\n"
|
||||
"127.0.0.1 cache2 # should reuse parsed IP\n"
|
||||
"256.0.0.0 cache3 # bogus IP should not clear parsed IP cache\n"
|
||||
@ -56,7 +56,6 @@ TEST(DnsHostsTest, ParseHosts) {
|
||||
|
||||
const ExpectedHostsEntry kEntries[] = {
|
||||
{"localhost", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
|
||||
{"localhost", ADDRESS_FAMILY_IPV4, "1.0.0.1"},
|
||||
{"company", ADDRESS_FAMILY_IPV4, "1.0.0.1"},
|
||||
{"localhost", ADDRESS_FAMILY_IPV6, "::1"},
|
||||
{"ip6-localhost", ADDRESS_FAMILY_IPV6, "::1"},
|
||||
@ -64,7 +63,6 @@ TEST(DnsHostsTest, ParseHosts) {
|
||||
{"ip6-localnet", ADDRESS_FAMILY_IPV6, "fe00::0"},
|
||||
{"company", ADDRESS_FAMILY_IPV6, "2048::1"},
|
||||
{"example", ADDRESS_FAMILY_IPV6, "2048::2"},
|
||||
{"example", ADDRESS_FAMILY_IPV6, "2048::1"},
|
||||
{"cache1", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
|
||||
{"cache2", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
|
||||
{"cache4", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
|
||||
|
@ -123,8 +123,8 @@ DnsConfig GetFuzzedDnsConfig(FuzzedDataProvider* data_provider) {
|
||||
"bar", "localhost", "localhost6"};
|
||||
const char* hostname = data_provider->PickValueInArray(kHostnames);
|
||||
net::IPAddress address = FuzzIPAddress(data_provider);
|
||||
config.hosts[net::DnsHostsKey(hostname, net::GetAddressFamily(address))]
|
||||
.push_back(address);
|
||||
config.hosts[net::DnsHostsKey(hostname, net::GetAddressFamily(address))] =
|
||||
address;
|
||||
}
|
||||
|
||||
config.unhandled_options = data_provider->ConsumeBool();
|
||||
|
@ -1726,7 +1726,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
|
||||
HostCache::Entry results,
|
||||
bool secure,
|
||||
bool success,
|
||||
AddressList addr_list) {
|
||||
const AddressList& addr_list) {
|
||||
results.set_addresses(addr_list);
|
||||
|
||||
if (!success) {
|
||||
@ -3385,23 +3385,15 @@ absl::optional<HostCache::Entry> HostResolverManager::ServeFromHosts(
|
||||
if (query_type == DnsQueryType::AAAA ||
|
||||
query_type == DnsQueryType::UNSPECIFIED) {
|
||||
auto it = hosts->find(DnsHostsKey(effective_hostname, ADDRESS_FAMILY_IPV6));
|
||||
if (it != hosts->end()) {
|
||||
for (const IPAddress& ip : it->second) {
|
||||
DCHECK(ip.IsIPv6());
|
||||
addresses.push_back(IPEndPoint(ip, 0));
|
||||
}
|
||||
}
|
||||
if (it != hosts->end())
|
||||
addresses.push_back(IPEndPoint(it->second, 0));
|
||||
}
|
||||
|
||||
if (query_type == DnsQueryType::A ||
|
||||
query_type == DnsQueryType::UNSPECIFIED) {
|
||||
auto it = hosts->find(DnsHostsKey(effective_hostname, ADDRESS_FAMILY_IPV4));
|
||||
if (it != hosts->end()) {
|
||||
for (const IPAddress& ip : it->second) {
|
||||
DCHECK(ip.IsIPv4());
|
||||
addresses.push_back(IPEndPoint(ip, 0));
|
||||
}
|
||||
}
|
||||
if (it != hosts->end())
|
||||
addresses.push_back(IPEndPoint(it->second, 0));
|
||||
}
|
||||
|
||||
// If got only loopback addresses and the family was restricted, resolve
|
||||
|
@ -4324,10 +4324,10 @@ TEST_F(HostResolverManagerDnsTest, LocalhostLookup) {
|
||||
// file is active.
|
||||
TEST_F(HostResolverManagerDnsTest, LocalhostLookupWithHosts) {
|
||||
DnsHosts hosts;
|
||||
hosts[DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4)] = {
|
||||
IPAddress({192, 168, 1, 1})};
|
||||
hosts[DnsHostsKey("foo.localhost", ADDRESS_FAMILY_IPV4)] = {
|
||||
IPAddress({192, 168, 1, 2})};
|
||||
hosts[DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4)] =
|
||||
IPAddress({192, 168, 1, 1});
|
||||
hosts[DnsHostsKey("foo.localhost", ADDRESS_FAMILY_IPV4)] =
|
||||
IPAddress({192, 168, 1, 2});
|
||||
|
||||
DnsConfig config = CreateValidDnsConfig();
|
||||
config.hosts = hosts;
|
||||
@ -4715,10 +4715,10 @@ TEST_F(HostResolverManagerDnsTest, ServeFromHosts) {
|
||||
IPAddress local_ipv6 = IPAddress::IPv6Localhost();
|
||||
|
||||
DnsHosts hosts;
|
||||
hosts[DnsHostsKey("nx_ipv4", ADDRESS_FAMILY_IPV4)] = {local_ipv4};
|
||||
hosts[DnsHostsKey("nx_ipv6", ADDRESS_FAMILY_IPV6)] = {local_ipv6};
|
||||
hosts[DnsHostsKey("nx_both", ADDRESS_FAMILY_IPV4)] = {local_ipv4};
|
||||
hosts[DnsHostsKey("nx_both", ADDRESS_FAMILY_IPV6)] = {local_ipv6};
|
||||
hosts[DnsHostsKey("nx_ipv4", ADDRESS_FAMILY_IPV4)] = local_ipv4;
|
||||
hosts[DnsHostsKey("nx_ipv6", ADDRESS_FAMILY_IPV6)] = local_ipv6;
|
||||
hosts[DnsHostsKey("nx_both", ADDRESS_FAMILY_IPV4)] = local_ipv4;
|
||||
hosts[DnsHostsKey("nx_both", ADDRESS_FAMILY_IPV6)] = local_ipv6;
|
||||
|
||||
// Update HOSTS file.
|
||||
config.hosts = hosts;
|
||||
@ -4786,28 +4786,6 @@ TEST_F(HostResolverManagerDnsTest, ServeFromHosts) {
|
||||
EXPECT_FALSE(response_upper.request()->GetDnsAliasResults());
|
||||
}
|
||||
|
||||
TEST_F(HostResolverManagerDnsTest, ServeMultiAddressEntryFromHosts) {
|
||||
DnsHosts hosts;
|
||||
hosts[DnsHostsKey("multi_address", ADDRESS_FAMILY_IPV4)] = {
|
||||
IPAddress(1, 1, 1, 1), IPAddress(2, 2, 2, 2)};
|
||||
|
||||
// Update HOSTS file.
|
||||
DnsConfig config = CreateValidDnsConfig();
|
||||
config.hosts = std::move(hosts);
|
||||
ChangeDnsConfig(config);
|
||||
|
||||
ResolveHostResponseHelper response(resolver_->CreateRequest(
|
||||
HostPortPair("multi_address", 443), NetworkIsolationKey(),
|
||||
NetLogWithSource(),
|
||||
/*optional_parameters=*/absl::nullopt, resolve_context_.get(),
|
||||
resolve_context_->host_cache()));
|
||||
EXPECT_THAT(response.result_error(), IsOk());
|
||||
EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(),
|
||||
testing::UnorderedElementsAre(CreateExpected("1.1.1.1", 443),
|
||||
CreateExpected("2.2.2.2", 443)));
|
||||
EXPECT_FALSE(response.request()->GetDnsAliasResults());
|
||||
}
|
||||
|
||||
TEST_F(HostResolverManagerDnsTest, SkipHostsWithUpcomingProcTask) {
|
||||
// Disable the DnsClient.
|
||||
resolver_->SetInsecureDnsClientEnabled(
|
||||
@ -4820,8 +4798,7 @@ TEST_F(HostResolverManagerDnsTest, SkipHostsWithUpcomingProcTask) {
|
||||
|
||||
DnsConfig config = CreateValidDnsConfig();
|
||||
DnsHosts hosts;
|
||||
hosts[DnsHostsKey("hosts", ADDRESS_FAMILY_IPV4)] = {
|
||||
IPAddress::IPv4Localhost()};
|
||||
hosts[DnsHostsKey("hosts", ADDRESS_FAMILY_IPV4)] = IPAddress::IPv4Localhost();
|
||||
|
||||
// Update HOSTS file.
|
||||
config.hosts = hosts;
|
||||
@ -7580,7 +7557,7 @@ TEST_F(HostResolverManagerDnsTest, SetDnsConfigOverrides) {
|
||||
|
||||
DnsConfig original_config = CreateValidDnsConfig();
|
||||
original_config.hosts = {
|
||||
{DnsHostsKey("host", ADDRESS_FAMILY_IPV4), {IPAddress(192, 168, 1, 1)}}};
|
||||
{DnsHostsKey("host", ADDRESS_FAMILY_IPV4), IPAddress(192, 168, 1, 1)}};
|
||||
ChangeDnsConfig(original_config);
|
||||
|
||||
// Confirm pre-override state.
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "net/dns/address_sorter.h"
|
||||
#include "net/dns/dns_hosts.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
@ -35,12 +34,10 @@ void TestDnsConfigService::RefreshConfig() {
|
||||
}
|
||||
|
||||
HostsReadingTestDnsConfigService::HostsReadingTestDnsConfigService(
|
||||
HostsParserFactory hosts_parser_factory,
|
||||
AddressSorterFactory address_sorter_factory)
|
||||
HostsParserFactory hosts_parser_factory)
|
||||
: hosts_reader_(
|
||||
std::make_unique<HostsReader>(*this,
|
||||
std::move(hosts_parser_factory),
|
||||
std::move(address_sorter_factory))) {}
|
||||
std::move(hosts_parser_factory))) {}
|
||||
|
||||
HostsReadingTestDnsConfigService::~HostsReadingTestDnsConfigService() = default;
|
||||
|
||||
@ -55,20 +52,17 @@ bool HostsReadingTestDnsConfigService::StartWatching() {
|
||||
|
||||
HostsReadingTestDnsConfigService::HostsReader::HostsReader(
|
||||
TestDnsConfigService& service,
|
||||
HostsParserFactory hosts_parser_factory,
|
||||
AddressSorterFactory address_sorter_factory)
|
||||
HostsParserFactory hosts_parser_factory)
|
||||
: DnsConfigService::HostsReader(
|
||||
/*hosts_file_path=*/base::FilePath::StringPieceType(),
|
||||
service),
|
||||
hosts_parser_factory_(std::move(hosts_parser_factory)),
|
||||
address_sorter_factory_(std::move(address_sorter_factory)) {}
|
||||
hosts_parser_factory_(std::move(hosts_parser_factory)) {}
|
||||
|
||||
HostsReadingTestDnsConfigService::HostsReader::~HostsReader() = default;
|
||||
|
||||
std::unique_ptr<SerialWorker::WorkItem>
|
||||
HostsReadingTestDnsConfigService::HostsReader::CreateWorkItem() {
|
||||
return std::make_unique<WorkItem>(hosts_parser_factory_.Run(),
|
||||
address_sorter_factory_.Run());
|
||||
return std::make_unique<WorkItem>(hosts_parser_factory_.Run());
|
||||
}
|
||||
|
||||
HostsReadingTestDnsConfigService::Watcher::Watcher(DnsConfigService& service)
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
namespace net {
|
||||
|
||||
class AddressSorter;
|
||||
class DnsHostsParser;
|
||||
|
||||
// Simple test implementation of DnsConfigService that will trigger
|
||||
@ -55,18 +54,15 @@ class TestDnsConfigService : public DnsConfigService {
|
||||
};
|
||||
|
||||
// Test implementation of `DnsConfigService` that exercises the
|
||||
// `DnsConfigService::HostsReader`. Uses an injected `DnsHostsParser` and
|
||||
// `AddressSorter`. `Watcher` change notifications are simulated using
|
||||
// `TriggerHostsChangeNotification()`.
|
||||
// `DnsConfigService::HostsReader`. Uses an injected `DnsHostsParser`. `Watcher`
|
||||
// change notifications are simulated using `TriggerHostsChangeNotification()`.
|
||||
class HostsReadingTestDnsConfigService : public TestDnsConfigService {
|
||||
public:
|
||||
using HostsParserFactory =
|
||||
base::RepeatingCallback<std::unique_ptr<DnsHostsParser>(void)>;
|
||||
using AddressSorterFactory =
|
||||
base::RepeatingCallback<std::unique_ptr<AddressSorter>(void)>;
|
||||
|
||||
HostsReadingTestDnsConfigService(HostsParserFactory hosts_parser_factory,
|
||||
AddressSorterFactory address_sorter_factory);
|
||||
explicit HostsReadingTestDnsConfigService(
|
||||
HostsParserFactory hosts_parser_factory);
|
||||
~HostsReadingTestDnsConfigService() override;
|
||||
|
||||
// Simulate a `Watcher` change notification for the HOSTS file.
|
||||
@ -82,8 +78,7 @@ class HostsReadingTestDnsConfigService : public TestDnsConfigService {
|
||||
class HostsReader : public DnsConfigService::HostsReader {
|
||||
public:
|
||||
HostsReader(TestDnsConfigService& service,
|
||||
HostsParserFactory hosts_parser_factory,
|
||||
AddressSorterFactory address_sorter_factory);
|
||||
HostsParserFactory hosts_parser_factory);
|
||||
~HostsReader() override;
|
||||
|
||||
// DnsConfigService::HostsReader:
|
||||
@ -91,7 +86,6 @@ class HostsReadingTestDnsConfigService : public TestDnsConfigService {
|
||||
|
||||
private:
|
||||
HostsParserFactory hosts_parser_factory_;
|
||||
AddressSorterFactory address_sorter_factory_;
|
||||
};
|
||||
|
||||
class Watcher : public DnsConfigService::Watcher {
|
||||
|
Reference in New Issue
Block a user