Updating trunk VERSION from 1014.0 to 1015.0
[chromium-blink-merge.git] / net / base / mock_host_resolver.cc
blob612c6007a48d1f076ee3058552c04ebb498e841d
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/base/mock_host_resolver.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop.h"
11 #include "base/stl_util.h"
12 #include "base/string_split.h"
13 #include "base/string_util.h"
14 #include "base/threading/platform_thread.h"
15 #include "net/base/host_cache.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h"
18 #include "net/base/sys_addrinfo.h"
19 #include "net/base/test_completion_callback.h"
21 namespace net {
23 namespace {
25 char* do_strdup(const char* src) {
26 #if defined(OS_WIN)
27 return _strdup(src);
28 #else
29 return strdup(src);
30 #endif
33 } // namespace
35 int ParseAddressList(const std::string& host_list,
36 const std::string& canonical_name,
37 AddressList* addrlist) {
38 *addrlist = AddressList();
39 std::vector<std::string> addresses;
40 base::SplitString(host_list, ',', &addresses);
41 for (size_t index = 0; index < addresses.size(); ++index) {
42 IPAddressNumber ip_number;
43 if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) {
44 LOG(WARNING) << "Not a supported IP literal: " << addresses[index];
45 return ERR_UNEXPECTED;
48 AddressList result = AddressList::CreateFromIPAddress(ip_number, -1);
49 struct addrinfo* ai = const_cast<struct addrinfo*>(result.head());
50 if (index == 0)
51 ai->ai_canonname = do_strdup(canonical_name.c_str());
52 if (!addrlist->head())
53 *addrlist = AddressList::CreateByCopyingFirstAddress(result.head());
54 else
55 addrlist->Append(result.head());
57 return OK;
60 struct MockHostResolverBase::Request {
61 Request(const RequestInfo& req_info,
62 AddressList* addr,
63 const CompletionCallback& cb)
64 : info(req_info), addresses(addr), callback(cb) {}
65 RequestInfo info;
66 AddressList* addresses;
67 CompletionCallback callback;
70 MockHostResolverBase::~MockHostResolverBase() {
71 STLDeleteValues(&requests_);
74 int MockHostResolverBase::Resolve(const RequestInfo& info,
75 AddressList* addresses,
76 const CompletionCallback& callback,
77 RequestHandle* handle,
78 const BoundNetLog& net_log) {
79 DCHECK(CalledOnValidThread());
80 size_t id = next_request_id_++;
81 int rv = ResolveFromIPLiteralOrCache(info, addresses);
82 if (rv != ERR_DNS_CACHE_MISS) {
83 return rv;
85 if (synchronous_mode_) {
86 return ResolveProc(id, info, addresses);
88 // Store the request for asynchronous resolution
89 Request* req = new Request(info, addresses, callback);
90 requests_[id] = req;
91 if (handle)
92 *handle = reinterpret_cast<RequestHandle>(id);
93 MessageLoop::current()->PostTask(FROM_HERE,
94 base::Bind(&MockHostResolverBase::ResolveNow,
95 AsWeakPtr(),
96 id));
97 return ERR_IO_PENDING;
100 int MockHostResolverBase::ResolveFromCache(const RequestInfo& info,
101 AddressList* addresses,
102 const BoundNetLog& net_log) {
103 DCHECK(CalledOnValidThread());
104 next_request_id_++;
105 int rv = ResolveFromIPLiteralOrCache(info, addresses);
106 return rv;
109 void MockHostResolverBase::CancelRequest(RequestHandle handle) {
110 DCHECK(CalledOnValidThread());
111 size_t id = reinterpret_cast<size_t>(handle);
112 RequestMap::iterator it = requests_.find(id);
113 if (it != requests_.end()) {
114 scoped_ptr<Request> req(it->second);
115 requests_.erase(it);
116 } else {
117 NOTREACHED() << "CancelRequest must NOT be called after request is "
118 "complete or canceled.";
122 HostCache* MockHostResolverBase::GetHostCache() {
123 return cache_.get();
126 // start id from 1 to distinguish from NULL RequestHandle
127 MockHostResolverBase::MockHostResolverBase(bool use_caching)
128 : synchronous_mode_(false), next_request_id_(1) {
129 rules_ = CreateCatchAllHostResolverProc();
130 proc_ = rules_;
132 if (use_caching) {
133 cache_.reset(new HostCache(
134 100, // max entries.
135 base::TimeDelta::FromMinutes(1),
136 base::TimeDelta::FromSeconds(0)));
140 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info,
141 AddressList* addresses) {
142 IPAddressNumber ip;
143 if (ParseIPLiteralToNumber(info.hostname(), &ip)) {
144 *addresses = AddressList::CreateFromIPAddressWithCname(
145 ip, info.port(), info.host_resolver_flags() & HOST_RESOLVER_CANONNAME);
146 return OK;
148 int rv = ERR_DNS_CACHE_MISS;
149 if (cache_.get() && info.allow_cached_response()) {
150 HostCache::Key key(info.hostname(),
151 info.address_family(),
152 info.host_resolver_flags());
153 const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now());
154 if (entry) {
155 rv = entry->error;
156 if (rv == OK)
157 *addresses = CreateAddressListUsingPort(entry->addrlist, info.port());
160 return rv;
163 int MockHostResolverBase::ResolveProc(size_t id,
164 const RequestInfo& info,
165 AddressList* addresses) {
166 AddressList addr;
167 int rv = proc_->Resolve(info.hostname(),
168 info.address_family(),
169 info.host_resolver_flags(),
170 &addr,
171 NULL);
172 if (cache_.get()) {
173 HostCache::Key key(info.hostname(),
174 info.address_family(),
175 info.host_resolver_flags());
176 cache_->Set(key, rv, addr, base::TimeTicks::Now());
178 if (rv == OK)
179 *addresses = CreateAddressListUsingPort(addr, info.port());
180 return rv;
183 void MockHostResolverBase::ResolveNow(size_t id) {
184 RequestMap::iterator it = requests_.find(id);
185 if (it == requests_.end())
186 return; // was canceled
188 scoped_ptr<Request> req(it->second);
189 requests_.erase(it);
190 int rv = ResolveProc(id, req->info, req->addresses);
191 if (!req->callback.is_null())
192 req->callback.Run(rv);
195 //-----------------------------------------------------------------------------
197 struct RuleBasedHostResolverProc::Rule {
198 enum ResolverType {
199 kResolverTypeFail,
200 kResolverTypeSystem,
201 kResolverTypeIPLiteral,
204 ResolverType resolver_type;
205 std::string host_pattern;
206 AddressFamily address_family;
207 HostResolverFlags host_resolver_flags;
208 std::string replacement;
209 std::string canonical_name;
210 int latency_ms; // In milliseconds.
212 Rule(ResolverType resolver_type,
213 const std::string& host_pattern,
214 AddressFamily address_family,
215 HostResolverFlags host_resolver_flags,
216 const std::string& replacement,
217 const std::string& canonical_name,
218 int latency_ms)
219 : resolver_type(resolver_type),
220 host_pattern(host_pattern),
221 address_family(address_family),
222 host_resolver_flags(host_resolver_flags),
223 replacement(replacement),
224 canonical_name(canonical_name),
225 latency_ms(latency_ms) {}
228 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
229 : HostResolverProc(previous) {
232 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
233 const std::string& replacement) {
234 AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
235 replacement);
238 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
239 const std::string& host_pattern,
240 AddressFamily address_family,
241 const std::string& replacement) {
242 DCHECK(!replacement.empty());
243 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
244 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
245 Rule rule(Rule::kResolverTypeSystem, host_pattern, address_family, flags,
246 replacement, "", 0);
247 rules_.push_back(rule);
250 void RuleBasedHostResolverProc::AddIPLiteralRule(
251 const std::string& host_pattern,
252 const std::string& ip_literal,
253 const std::string& canonical_name) {
254 // Literals are always resolved to themselves by HostResolverImpl,
255 // consequently we do not support remapping them.
256 IPAddressNumber ip_number;
257 DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
258 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
259 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
260 if (!canonical_name.empty())
261 flags |= HOST_RESOLVER_CANONNAME;
262 Rule rule(Rule::kResolverTypeIPLiteral, host_pattern,
263 ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name,
265 rules_.push_back(rule);
268 void RuleBasedHostResolverProc::AddRuleWithLatency(
269 const std::string& host_pattern,
270 const std::string& replacement,
271 int latency_ms) {
272 DCHECK(!replacement.empty());
273 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
274 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
275 Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
276 flags, replacement, "", latency_ms);
277 rules_.push_back(rule);
280 void RuleBasedHostResolverProc::AllowDirectLookup(
281 const std::string& host_pattern) {
282 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
283 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
284 Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
285 flags, "", "", 0);
286 rules_.push_back(rule);
289 void RuleBasedHostResolverProc::AddSimulatedFailure(
290 const std::string& host_pattern) {
291 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
292 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
293 Rule rule(Rule::kResolverTypeFail, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
294 flags, "", "", 0);
295 rules_.push_back(rule);
298 int RuleBasedHostResolverProc::Resolve(const std::string& host,
299 AddressFamily address_family,
300 HostResolverFlags host_resolver_flags,
301 AddressList* addrlist,
302 int* os_error) {
303 RuleList::iterator r;
304 for (r = rules_.begin(); r != rules_.end(); ++r) {
305 bool matches_address_family =
306 r->address_family == ADDRESS_FAMILY_UNSPECIFIED ||
307 r->address_family == address_family;
308 // Flags match if all of the bitflags in host_resolver_flags are enabled
309 // in the rule's host_resolver_flags. However, the rule may have additional
310 // flags specified, in which case the flags should still be considered a
311 // match.
312 bool matches_flags = (r->host_resolver_flags & host_resolver_flags) ==
313 host_resolver_flags;
314 if (matches_flags && matches_address_family &&
315 MatchPattern(host, r->host_pattern)) {
316 if (r->latency_ms != 0)
317 base::PlatformThread::Sleep(r->latency_ms);
319 // Remap to a new host.
320 const std::string& effective_host =
321 r->replacement.empty() ? host : r->replacement;
323 // Apply the resolving function to the remapped hostname.
324 switch (r->resolver_type) {
325 case Rule::kResolverTypeFail:
326 return ERR_NAME_NOT_RESOLVED;
327 case Rule::kResolverTypeSystem:
328 return SystemHostResolverProc(effective_host,
329 address_family,
330 host_resolver_flags,
331 addrlist, os_error);
332 case Rule::kResolverTypeIPLiteral:
333 return ParseAddressList(effective_host,
334 r->canonical_name,
335 addrlist);
336 default:
337 NOTREACHED();
338 return ERR_UNEXPECTED;
342 return ResolveUsingPrevious(host, address_family,
343 host_resolver_flags, addrlist, os_error);
346 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
349 RuleBasedHostResolverProc* CreateCatchAllHostResolverProc() {
350 RuleBasedHostResolverProc* catchall = new RuleBasedHostResolverProc(NULL);
351 #if defined(OS_ANDROID)
352 // In Android emulator, the development machine's '127.0.0.1' is mapped to
353 // '10.0.2.2'.
354 catchall->AddIPLiteralRule("*", "10.0.2.2", "localhost");
355 #else
356 catchall->AddIPLiteralRule("*", "127.0.0.1", "localhost");
357 #endif
359 // Next add a rules-based layer the use controls.
360 return new RuleBasedHostResolverProc(catchall);
363 //-----------------------------------------------------------------------------
365 int HangingHostResolver::Resolve(const RequestInfo& info,
366 AddressList* addresses,
367 const CompletionCallback& callback,
368 RequestHandle* out_req,
369 const BoundNetLog& net_log) {
370 return ERR_IO_PENDING;
373 int HangingHostResolver::ResolveFromCache(const RequestInfo& info,
374 AddressList* addresses,
375 const BoundNetLog& net_log) {
376 return ERR_DNS_CACHE_MISS;
379 //-----------------------------------------------------------------------------
381 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
383 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
384 HostResolverProc* proc) {
385 Init(proc);
388 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
389 HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_);
390 // The lifetimes of multiple instances must be nested.
391 CHECK_EQ(old_proc, current_proc_);
394 void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
395 current_proc_ = proc;
396 previous_proc_ = HostResolverProc::SetDefault(current_proc_);
397 current_proc_->SetLastProc(previous_proc_);
400 } // namespace net