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"
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"
25 char* do_strdup(const char* src
) {
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());
51 ai
->ai_canonname
= do_strdup(canonical_name
.c_str());
52 if (!addrlist
->head())
53 *addrlist
= AddressList::CreateByCopyingFirstAddress(result
.head());
55 addrlist
->Append(result
.head());
60 struct MockHostResolverBase::Request
{
61 Request(const RequestInfo
& req_info
,
63 const CompletionCallback
& cb
)
64 : info(req_info
), addresses(addr
), callback(cb
) {}
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
) {
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
);
92 *handle
= reinterpret_cast<RequestHandle
>(id
);
93 MessageLoop::current()->PostTask(FROM_HERE
,
94 base::Bind(&MockHostResolverBase::ResolveNow
,
97 return ERR_IO_PENDING
;
100 int MockHostResolverBase::ResolveFromCache(const RequestInfo
& info
,
101 AddressList
* addresses
,
102 const BoundNetLog
& net_log
) {
103 DCHECK(CalledOnValidThread());
105 int rv
= ResolveFromIPLiteralOrCache(info
, addresses
);
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
);
117 NOTREACHED() << "CancelRequest must NOT be called after request is "
118 "complete or canceled.";
122 HostCache
* MockHostResolverBase::GetHostCache() {
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();
133 cache_
.reset(new HostCache(
135 base::TimeDelta::FromMinutes(1),
136 base::TimeDelta::FromSeconds(0)));
140 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo
& info
,
141 AddressList
* addresses
) {
143 if (ParseIPLiteralToNumber(info
.hostname(), &ip
)) {
144 *addresses
= AddressList::CreateFromIPAddressWithCname(
145 ip
, info
.port(), info
.host_resolver_flags() & HOST_RESOLVER_CANONNAME
);
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());
157 *addresses
= CreateAddressListUsingPort(entry
->addrlist
, info
.port());
163 int MockHostResolverBase::ResolveProc(size_t id
,
164 const RequestInfo
& info
,
165 AddressList
* addresses
) {
167 int rv
= proc_
->Resolve(info
.hostname(),
168 info
.address_family(),
169 info
.host_resolver_flags(),
173 HostCache::Key
key(info
.hostname(),
174 info
.address_family(),
175 info
.host_resolver_flags());
176 cache_
->Set(key
, rv
, addr
, base::TimeTicks::Now());
179 *addresses
= CreateAddressListUsingPort(addr
, info
.port());
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
);
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
{
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
312 bool matches_flags
= (r
->host_resolver_flags
& 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
,
332 case Rule::kResolverTypeIPLiteral
:
333 return ParseAddressList(effective_host
,
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
354 catchall
->AddIPLiteralRule("*", "10.0.2.2", "localhost");
356 catchall
->AddIPLiteralRule("*", "127.0.0.1", "localhost");
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
) {
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_
);