Commit 25406959 authored by Eric Orth's avatar Eric Orth Committed by Commit Bot

Implement new ResolveHost API in MappedHostResolver.

Generally just applies the mapping to the input HostPortPair and passes
on to the wrapped implementation. Some special handling for when the
input is mapped to an error.

Bug: 821021
Change-Id: I0d108976e363993ebb36b8081948ef410894fa47
Reviewed-on: https://chromium-review.googlesource.com/1156856Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Commit-Queue: Eric Orth <ericorth@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579587}
parent e03a1164
......@@ -6,6 +6,7 @@
#include <utility>
#include "base/no_destructor.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
......@@ -13,6 +14,22 @@
namespace net {
class MappedHostResolver::AlwaysErrorRequestImpl
: public HostResolver::ResolveHostRequest {
public:
explicit AlwaysErrorRequestImpl(int error) : error_(error) {}
int Start(CompletionOnceCallback callback) override { return error_; }
const base::Optional<AddressList>& GetAddressResults() const override {
static base::NoDestructor<base::Optional<AddressList>> nullopt_address_list;
return *nullopt_address_list;
}
private:
const int error_;
};
MappedHostResolver::MappedHostResolver(std::unique_ptr<HostResolver> impl)
: impl_(std::move(impl)) {}
......@@ -21,9 +38,13 @@ MappedHostResolver::~MappedHostResolver() = default;
std::unique_ptr<HostResolver::ResolveHostRequest>
MappedHostResolver::CreateRequest(const HostPortPair& host,
const NetLogWithSource& source_net_log) {
// TODO(crbug.com/821021): Implement.
NOTIMPLEMENTED();
return nullptr;
HostPortPair rewritten = host;
rules_.RewriteHost(&rewritten);
if (rewritten.host() == "~NOTFOUND")
return std::make_unique<AlwaysErrorRequestImpl>(ERR_NAME_NOT_RESOLVED);
return impl_->CreateRequest(rewritten, source_net_log);
}
int MappedHostResolver::Resolve(const RequestInfo& original_info,
......
......@@ -74,6 +74,8 @@ class NET_EXPORT MappedHostResolver : public HostResolver {
bool GetNoIPv6OnWifi() override;
private:
class AlwaysErrorRequestImpl;
// Modify the request |info| according to |rules_|. Returns either OK or
// the network error code that the hostname's resolution mapped to.
int ApplyRules(RequestInfo* info) const;
......
......@@ -99,6 +99,73 @@ TEST(MappedHostResolverTest, Inclusion) {
EXPECT_EQ("192.168.1.11:99", FirstAddress(address_list));
}
TEST(MappedHostResolverTest, Inclusion_ResolveHost) {
base::test::ScopedTaskEnvironment scoped_task_environment;
// Create a mock host resolver, with specific hostname to IP mappings.
std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
resolver_impl->rules()->AddSimulatedFailure("*google.com");
resolver_impl->rules()->AddRule("baz.com", "192.168.1.5");
resolver_impl->rules()->AddRule("foo.com", "192.168.1.8");
resolver_impl->rules()->AddRule("proxy", "192.168.1.11");
// Create a remapped resolver that uses |resolver_impl|.
std::unique_ptr<MappedHostResolver> resolver(
new MappedHostResolver(std::move(resolver_impl)));
// Try resolving "www.google.com:80". There are no mappings yet, so this
// hits |resolver_impl| and fails.
TestCompletionCallback callback;
std::unique_ptr<HostResolver::ResolveHostRequest> request =
resolver->CreateRequest(HostPortPair("www.google.com", 80),
NetLogWithSource());
int rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_FALSE(request->GetAddressResults());
// Remap *.google.com to baz.com.
EXPECT_TRUE(resolver->AddRuleFromString("map *.google.com baz.com"));
request.reset();
// Try resolving "www.google.com:80". Should be remapped to "baz.com:80".
request = resolver->CreateRequest(HostPortPair("www.google.com", 80),
NetLogWithSource());
rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.5:80",
FirstAddress(request->GetAddressResults().value()));
request.reset();
// Try resolving "foo.com:77". This will NOT be remapped, so result
// is "foo.com:77".
request =
resolver->CreateRequest(HostPortPair("foo.com", 77), NetLogWithSource());
rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.8:77",
FirstAddress(request->GetAddressResults().value()));
request.reset();
// Remap "*.org" to "proxy:99".
EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99"));
// Try resolving "chromium.org:61". Should be remapped to "proxy:99".
request = resolver->CreateRequest(HostPortPair("chromium.org", 61),
NetLogWithSource());
rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.11:99",
FirstAddress(request->GetAddressResults().value()));
}
// Tests that exclusions are respected.
TEST(MappedHostResolverTest, Exclusion) {
base::test::ScopedTaskEnvironment scoped_task_environment;
......@@ -146,6 +213,50 @@ TEST(MappedHostResolverTest, Exclusion) {
EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list));
}
// Tests that exclusions are respected.
TEST(MappedHostResolverTest, Exclusion_ResolveHost) {
base::test::ScopedTaskEnvironment scoped_task_environment;
// Create a mock host resolver, with specific hostname to IP mappings.
std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
resolver_impl->rules()->AddRule("baz", "192.168.1.5");
resolver_impl->rules()->AddRule("www.google.com", "192.168.1.3");
// Create a remapped resolver that uses |resolver_impl|.
std::unique_ptr<MappedHostResolver> resolver(
new MappedHostResolver(std::move(resolver_impl)));
TestCompletionCallback callback;
// Remap "*.com" to "baz".
EXPECT_TRUE(resolver->AddRuleFromString("map *.com baz"));
// Add an exclusion for "*.google.com".
EXPECT_TRUE(resolver->AddRuleFromString("EXCLUDE *.google.com"));
// Try resolving "www.google.com". Should not be remapped due to exclusion).
std::unique_ptr<HostResolver::ResolveHostRequest> request =
resolver->CreateRequest(HostPortPair("www.google.com", 80),
NetLogWithSource());
int rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.3:80",
FirstAddress(request->GetAddressResults().value()));
request.reset();
// Try resolving "chrome.com:80". Should be remapped to "baz:80".
request = resolver->CreateRequest(HostPortPair("chrome.com", 80),
NetLogWithSource());
rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.5:80",
FirstAddress(request->GetAddressResults().value()));
}
TEST(MappedHostResolverTest, SetRulesFromString) {
base::test::ScopedTaskEnvironment scoped_task_environment;
......@@ -189,6 +300,46 @@ TEST(MappedHostResolverTest, SetRulesFromString) {
EXPECT_EQ("192.168.1.9:60", FirstAddress(address_list));
}
TEST(MappedHostResolverTest, SetRulesFromString_ResolveHost) {
base::test::ScopedTaskEnvironment scoped_task_environment;
// Create a mock host resolver, with specific hostname to IP mappings.
std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
resolver_impl->rules()->AddRule("baz", "192.168.1.7");
resolver_impl->rules()->AddRule("bar", "192.168.1.9");
// Create a remapped resolver that uses |resolver_impl|.
std::unique_ptr<MappedHostResolver> resolver(
new MappedHostResolver(std::move(resolver_impl)));
TestCompletionCallback callback;
// Remap "*.com" to "baz", and *.net to "bar:60".
resolver->SetRulesFromString("map *.com baz , map *.net bar:60");
// Try resolving "www.google.com". Should be remapped to "baz".
std::unique_ptr<HostResolver::ResolveHostRequest> request =
resolver->CreateRequest(HostPortPair("www.google.com", 80),
NetLogWithSource());
int rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.7:80",
FirstAddress(request->GetAddressResults().value()));
request.reset();
// Try resolving "chrome.net:80". Should be remapped to "bar:60".
request = resolver->CreateRequest(HostPortPair("chrome.net", 80),
NetLogWithSource());
rv = request->Start(callback.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.9:60",
FirstAddress(request->GetAddressResults().value()));
}
// Parsing bad rules should silently discard the rule (and never crash).
TEST(MappedHostResolverTest, ParseInvalidRules) {
base::test::ScopedTaskEnvironment scoped_task_environment;
......@@ -245,6 +396,41 @@ TEST(MappedHostResolverTest, MapToError) {
EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list));
}
// Test mapping hostnames to resolving failures.
TEST(MappedHostResolverTest, MapToError_ResolveHost) {
base::test::ScopedTaskEnvironment scoped_task_environment;
// Outstanding request.
std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
resolver_impl->rules()->AddRule("*", "192.168.1.5");
std::unique_ptr<MappedHostResolver> resolver(
new MappedHostResolver(std::move(resolver_impl)));
// Remap *.google.com to resolving failures.
EXPECT_TRUE(resolver->AddRuleFromString("MAP *.google.com ~NOTFOUND"));
// Try resolving www.google.com --> Should give an error.
TestCompletionCallback callback1;
std::unique_ptr<HostResolver::ResolveHostRequest> request =
resolver->CreateRequest(HostPortPair("www.google.com", 80),
NetLogWithSource());
int rv = request->Start(callback1.callback());
EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
request.reset();
// Try resolving www.foo.com --> Should succeed.
TestCompletionCallback callback2;
request = resolver->CreateRequest(HostPortPair("www.foo.com", 80),
NetLogWithSource());
rv = request->Start(callback2.callback());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
rv = callback2.WaitForResult();
EXPECT_THAT(rv, IsOk());
EXPECT_EQ("192.168.1.5:80",
FirstAddress(request->GetAddressResults().value()));
}
} // namespace
} // namespace net
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment