summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-18 08:03:38 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-18 08:03:38 +0000
commit9087aa3c473281af9c216d060d00baa4e1af4216 (patch)
tree11020a066a239d0042247611052c43f7fd0859ef /net
parent3517fd50b20611670f08aedfff25451f6fe9e313 (diff)
downloadchromium_src-9087aa3c473281af9c216d060d00baa4e1af4216.zip
chromium_src-9087aa3c473281af9c216d060d00baa4e1af4216.tar.gz
chromium_src-9087aa3c473281af9c216d060d00baa4e1af4216.tar.bz2
Add a command-line flag to remap hostnames based on patterns.
This is a generalization of the --testing-fixed-server flag. BUG=36053 TEST=MappedHostResolverTest.* Review URL: http://codereview.chromium.org/647001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39342 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/fixed_host_resolver.cc46
-rw-r--r--net/base/fixed_host_resolver.h41
-rw-r--r--net/base/host_resolver.h7
-rw-r--r--net/base/mapped_host_resolver.cc111
-rw-r--r--net/base/mapped_host_resolver.h79
-rw-r--r--net/base/mapped_host_resolver_unittest.cc148
-rwxr-xr-xnet/net.gyp5
7 files changed, 348 insertions, 89 deletions
diff --git a/net/base/fixed_host_resolver.cc b/net/base/fixed_host_resolver.cc
deleted file mode 100644
index 47089f1..0000000
--- a/net/base/fixed_host_resolver.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2009 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/base/fixed_host_resolver.h"
-
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "net/base/host_resolver_impl.h"
-
-namespace net {
-
-FixedHostResolver::FixedHostResolver(const std::string& host)
- : initialized_(false) {
- int port;
- std::string parsed_host;
- if (!ParseHostAndPort(host, &parsed_host, &port)) {
- LOG(DFATAL) << "Invalid FixedHostResolver information: " << host;
- return;
- }
-
- int rv = SystemHostResolverProc(host, net::ADDRESS_FAMILY_UNSPECIFIED,
- &address_);
- if (rv != OK) {
- LOG(ERROR) << "Could not resolve fixed host: " << host;
- return;
- }
-
- initialized_ = true;
-}
-
-int FixedHostResolver::Resolve(const RequestInfo& info,
- AddressList* addresses,
- CompletionCallback* callback,
- RequestHandle* out_req,
- LoadLog* load_log) {
- if (!initialized_)
- return ERR_NAME_NOT_RESOLVED;
-
- DCHECK(addresses);
- addresses->Copy(address_.head());
- addresses->SetPort(info.port());
- return OK;
-}
-
-} // namespace net
diff --git a/net/base/fixed_host_resolver.h b/net/base/fixed_host_resolver.h
deleted file mode 100644
index ee7b114..0000000
--- a/net/base/fixed_host_resolver.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2009 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.
-
-#ifndef NET_BASE_FIXED_HOST_RESOLVER_H_
-#define NET_BASE_FIXED_HOST_RESOLVER_H_
-
-#include <string>
-
-#include "net/base/address_list.h"
-#include "net/base/host_resolver.h"
-
-namespace net {
-
-// A FixedHostResolver resolves all addresses to a single address.
-class FixedHostResolver : public HostResolver {
- public:
- // |host| is a string representing the resolution.
- // example: foo.myproxy.com
- explicit FixedHostResolver(const std::string& host);
-
- // HostResolver methods:
- virtual int Resolve(const RequestInfo& info,
- AddressList* addresses,
- CompletionCallback* callback,
- RequestHandle* out_req,
- LoadLog* load_log);
- virtual void CancelRequest(RequestHandle req) {}
- virtual void AddObserver(Observer* observer) {}
- virtual void RemoveObserver(Observer* observer) {}
-
- private:
- ~FixedHostResolver() {}
-
- AddressList address_;
- bool initialized_;
-};
-
-} // namespace net
-
-#endif // NET_BASE_MOCK_HOST_RESOLVER_H_
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h
index a960805..da431f3 100644
--- a/net/base/host_resolver.h
+++ b/net/base/host_resolver.h
@@ -46,7 +46,14 @@ class HostResolver : public base::RefCountedThreadSafe<HostResolver> {
priority_(MEDIUM) {}
int port() const { return port_; }
+ void set_port(int port) {
+ port_ = port;
+ }
+
const std::string& hostname() const { return hostname_; }
+ void set_hostname(const std::string& hostname) {
+ hostname_ = hostname;
+ }
AddressFamily address_family() const { return address_family_; }
void set_address_family(AddressFamily address_family) {
diff --git a/net/base/mapped_host_resolver.cc b/net/base/mapped_host_resolver.cc
new file mode 100644
index 0000000..3624a9b
--- /dev/null
+++ b/net/base/mapped_host_resolver.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2010 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/base/mapped_host_resolver.h"
+
+#include "base/string_tokenizer.h"
+#include "base/string_util.h"
+#include "net/base/net_util.h"
+
+namespace net {
+
+MappedHostResolver::MappedHostResolver(HostResolver* impl)
+ : impl_(impl) {
+}
+
+int MappedHostResolver::Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req,
+ LoadLog* load_log) {
+ // Modify the request before forwarding it to |impl_|.
+ RequestInfo modified_info = info;
+ RewriteRequest(&modified_info);
+ return impl_->Resolve(modified_info, addresses, callback, out_req, load_log);
+}
+
+void MappedHostResolver::CancelRequest(RequestHandle req) {
+ impl_->CancelRequest(req);
+}
+
+void MappedHostResolver::AddObserver(Observer* observer) {
+ impl_->AddObserver(observer);
+}
+
+void MappedHostResolver::RemoveObserver(Observer* observer) {
+ impl_->RemoveObserver(observer);
+}
+
+MappedHostResolver::~MappedHostResolver() {
+}
+
+bool MappedHostResolver::RewriteRequest(RequestInfo* info) const {
+ // Check if the hostname was excluded.
+ for (ExclusionRuleList::const_iterator it = exclusion_rules_.begin();
+ it != exclusion_rules_.end(); ++it) {
+ const ExclusionRule& rule = *it;
+ if (MatchPatternASCII(info->hostname(), rule.hostname_pattern))
+ return false;
+ }
+
+ // Check if the hostname was remapped.
+ for (MapRuleList::const_iterator it = map_rules_.begin();
+ it != map_rules_.end(); ++it) {
+ const MapRule& rule = *it;
+
+ if (!MatchPatternASCII(info->hostname(), rule.hostname_pattern))
+ continue; // This rule doesn't apply.
+
+ info->set_hostname(rule.replacement_hostname);
+ if (rule.replacement_port != -1)
+ info->set_port(rule.replacement_port);
+ return true;
+ }
+
+ return false;
+}
+
+bool MappedHostResolver::AddRuleFromString(const std::string& rule_string) {
+ std::string trimmed;
+ TrimWhitespaceASCII(rule_string, TRIM_ALL, &trimmed);
+ std::vector<std::string> parts;
+ SplitString(trimmed, ' ', &parts);
+
+ // Test for EXCLUSION rule.
+ if (parts.size() == 2 && LowerCaseEqualsASCII(parts[0], "exclude")) {
+ ExclusionRule rule;
+ rule.hostname_pattern = StringToLowerASCII(parts[1]);
+ exclusion_rules_.push_back(rule);
+ return true;
+ }
+
+ // Test for MAP rule.
+ if (parts.size() == 3 && LowerCaseEqualsASCII(parts[0], "map")) {
+ MapRule rule;
+ rule.hostname_pattern = StringToLowerASCII(parts[1]);
+
+ if (!ParseHostAndPort(parts[2], &rule.replacement_hostname,
+ &rule.replacement_port)) {
+ return false; // Failed parsing the hostname/port.
+ }
+
+ map_rules_.push_back(rule);
+ return true;
+ }
+
+ return false;
+}
+
+void MappedHostResolver::SetRulesFromString(const std::string& rules_string) {
+ exclusion_rules_.clear();
+ map_rules_.clear();
+
+ StringTokenizer rules(rules_string, ",");
+ while (rules.GetNext()) {
+ bool ok = AddRuleFromString(rules.token());
+ LOG_IF(ERROR, !ok) << "Failed parsing rule: " << rules.token();
+ }
+}
+
+} // namespace net
diff --git a/net/base/mapped_host_resolver.h b/net/base/mapped_host_resolver.h
new file mode 100644
index 0000000..af78a9c
--- /dev/null
+++ b/net/base/mapped_host_resolver.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2010 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.
+
+#ifndef NET_BASE_MAPPED_HOST_RESOLVER_H_
+#define NET_BASE_MAPPED_HOST_RESOLVER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "net/base/host_resolver.h"
+
+namespace net {
+
+// This class wraps an existing HostResolver instance, but modifies the
+// request before passing it off to |impl|. This is different from
+// MockHostResolver which does the remapping at the HostResolverProc
+// layer, so it is able to preserve the effectiveness of the cache.
+class MappedHostResolver : public HostResolver {
+ public:
+ // Creates a MappedHostResolver that forwards all of its requests through
+ // |impl|.
+ explicit MappedHostResolver(HostResolver* impl);
+
+ // HostResolver methods:
+ virtual int Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req,
+ LoadLog* load_log);
+ virtual void CancelRequest(RequestHandle req);
+ virtual void AddObserver(Observer* observer);
+ virtual void RemoveObserver(Observer* observer);
+
+ // Adds a rule to this mapper. The format of the rule can be one of:
+ //
+ // "MAP" <hostname_pattern> <replacement_host> [":" <replacement_port>]
+ // "EXCLUDE" <hostname_pattern>
+ //
+ // The <replacement_host> can be either a hostname, or an IP address literal.
+ //
+ // Returns true if the rule was successfully parsed and added.
+ bool AddRuleFromString(const std::string& rule_string);
+
+ // Takes a comma separated list of rules, and assigns them to this resolver.
+ void SetRulesFromString(const std::string& rules_string);
+
+ private:
+ struct MapRule {
+ MapRule() : replacement_port(-1) {}
+
+ std::string hostname_pattern;
+ std::string replacement_hostname;
+ int replacement_port;
+ };
+
+ struct ExclusionRule {
+ std::string hostname_pattern;
+ };
+
+ typedef std::vector<MapRule> MapRuleList;
+ typedef std::vector<ExclusionRule> ExclusionRuleList;
+
+ virtual ~MappedHostResolver();
+
+ // Modifies |*info| based on the current rules. Returns true if the
+ // RequestInfo was modified, false otherwise.
+ bool RewriteRequest(RequestInfo* info) const;
+
+ scoped_refptr<HostResolver> impl_;
+
+ MapRuleList map_rules_;
+ ExclusionRuleList exclusion_rules_;
+};
+
+} // namespace net
+
+#endif // NET_BASE_MAPPED_HOST_RESOLVER_H_
diff --git a/net/base/mapped_host_resolver_unittest.cc b/net/base/mapped_host_resolver_unittest.cc
new file mode 100644
index 0000000..6da84e0
--- /dev/null
+++ b/net/base/mapped_host_resolver_unittest.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2010 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/base/mapped_host_resolver.h"
+
+#include "net/base/mock_host_resolver.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+TEST(MappedHostResolverTest, Inclusion) {
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ scoped_refptr<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|.
+ scoped_refptr<MappedHostResolver> resolver =
+ new MappedHostResolver(resolver_impl);
+
+ int rv;
+ AddressList address_list;
+
+ // Try resolving "www.google.com:80". There are no mappings yet, so this
+ // hits |resolver_impl| and fails.
+ rv = resolver->Resolve(HostResolver::RequestInfo("www.google.com", 80),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
+
+ // Remap *.google.com to baz.com.
+ EXPECT_TRUE(resolver->AddRuleFromString("map *.google.com baz.com"));
+
+ // Try resolving "www.google.com:80". Should be remapped to "baz.com:80".
+ rv = resolver->Resolve(HostResolver::RequestInfo("www.google.com", 80),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.5", NetAddressToString(address_list.head()));
+ EXPECT_EQ(80, address_list.GetPort());
+
+ // Try resolving "foo.com:77". This will NOT be remapped, so result
+ // is "foo.com:77".
+ rv = resolver->Resolve(HostResolver::RequestInfo("foo.com", 77),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.8", NetAddressToString(address_list.head()));
+ EXPECT_EQ(77, address_list.GetPort());
+
+ // Remap "*.org" to "proxy:99".
+ EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99"));
+
+ // Try resolving "chromium.org:61". Should be remapped to "proxy:99".
+ rv = resolver->Resolve(HostResolver::RequestInfo("chromium.org", 61),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.11", NetAddressToString(address_list.head()));
+ EXPECT_EQ(99, address_list.GetPort());
+}
+
+// Tests that exclusions are respected.
+TEST(MappedHostResolverTest, Exclusion) {
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ scoped_refptr<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|.
+ scoped_refptr<MappedHostResolver> resolver =
+ new MappedHostResolver(resolver_impl);
+
+ int rv;
+ AddressList address_list;
+
+ // 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).
+ rv = resolver->Resolve(HostResolver::RequestInfo("www.google.com", 80),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.3", NetAddressToString(address_list.head()));
+ EXPECT_EQ(80, address_list.GetPort());
+
+ // Try resolving "chrome.com:80". Should be remapped to "baz:80".
+ rv = resolver->Resolve(HostResolver::RequestInfo("chrome.com", 80),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.5", NetAddressToString(address_list.head()));
+ EXPECT_EQ(80, address_list.GetPort());
+}
+
+TEST(MappedHostResolverTest, SetRulesFromString) {
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ scoped_refptr<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|.
+ scoped_refptr<MappedHostResolver> resolver =
+ new MappedHostResolver(resolver_impl);
+
+ int rv;
+ AddressList address_list;
+
+ // 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".
+ rv = resolver->Resolve(HostResolver::RequestInfo("www.google.com", 80),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.7", NetAddressToString(address_list.head()));
+ EXPECT_EQ(80, address_list.GetPort());
+
+ // Try resolving "chrome.net:80". Should be remapped to "bar:60".
+ rv = resolver->Resolve(HostResolver::RequestInfo("chrome.net", 80),
+ &address_list, NULL, NULL, NULL);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ("192.168.1.9", NetAddressToString(address_list.head()));
+ EXPECT_EQ(60, address_list.GetPort());
+}
+
+// Parsing bad rules should silently discard the rule (and never crash).
+TEST(MappedHostResolverTest, ParseInvalidRules) {
+ scoped_refptr<MappedHostResolver> resolver = new MappedHostResolver(NULL);
+
+ EXPECT_FALSE(resolver->AddRuleFromString("xyz"));
+ EXPECT_FALSE(resolver->AddRuleFromString(""));
+ EXPECT_FALSE(resolver->AddRuleFromString(" "));
+ EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE"));
+ EXPECT_FALSE(resolver->AddRuleFromString("EXCLUDE foo bar"));
+ EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE"));
+ EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x"));
+ EXPECT_FALSE(resolver->AddRuleFromString("INCLUDE x :10"));
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/net.gyp b/net/net.gyp
index b6f6062..599f683 100755
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -58,8 +58,6 @@
'base/file_stream_win.cc',
'base/filter.cc',
'base/filter.h',
- 'base/fixed_host_resolver.cc',
- 'base/fixed_host_resolver.h',
'base/gzip_filter.cc',
'base/gzip_filter.h',
'base/gzip_header.cc',
@@ -89,6 +87,8 @@
'base/load_log_util.cc',
'base/load_log_util.h',
'base/load_states.h',
+ 'base/mapped_host_resolver.cc',
+ 'base/mapped_host_resolver.h',
'base/mime_sniffer.cc',
'base/mime_sniffer.h',
'base/mime_util.cc',
@@ -600,6 +600,7 @@
'base/load_log_util_unittest.cc',
'base/listen_socket_unittest.cc',
'base/listen_socket_unittest.h',
+ 'base/mapped_host_resolver_unittest.cc',
'base/mime_sniffer_unittest.cc',
'base/mime_util_unittest.cc',
'base/mock_network_change_notifier.h',