1 // Copyright (c) 2012 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/dns/mock_host_resolver.h"
10 #include "base/bind.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "base/threading/platform_thread.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/net_util.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/dns/host_cache.h"
23 #include "net/base/winsock_init.h"
30 // Cache size for the MockCachingHostResolver.
31 const unsigned kMaxCacheEntries
= 100;
32 // TTL for the successful resolutions. Failures are not cached.
33 const unsigned kCacheEntryTTLSeconds
= 60;
37 int ParseAddressList(const std::string
& host_list
,
38 const std::string
& canonical_name
,
39 AddressList
* addrlist
) {
40 *addrlist
= AddressList();
41 std::vector
<std::string
> addresses
;
42 base::SplitString(host_list
, ',', &addresses
);
43 addrlist
->set_canonical_name(canonical_name
);
44 for (size_t index
= 0; index
< addresses
.size(); ++index
) {
45 IPAddressNumber ip_number
;
46 if (!ParseIPLiteralToNumber(addresses
[index
], &ip_number
)) {
47 LOG(WARNING
) << "Not a supported IP literal: " << addresses
[index
];
48 return ERR_UNEXPECTED
;
50 addrlist
->push_back(IPEndPoint(ip_number
, -1));
55 struct MockHostResolverBase::Request
{
56 Request(const RequestInfo
& req_info
,
58 const CompletionCallback
& cb
)
59 : info(req_info
), addresses(addr
), callback(cb
) {}
61 AddressList
* addresses
;
62 CompletionCallback callback
;
65 MockHostResolverBase::~MockHostResolverBase() {
66 STLDeleteValues(&requests_
);
69 int MockHostResolverBase::Resolve(const RequestInfo
& info
,
70 RequestPriority priority
,
71 AddressList
* addresses
,
72 const CompletionCallback
& callback
,
73 RequestHandle
* handle
,
74 const BoundNetLog
& net_log
) {
75 DCHECK(CalledOnValidThread());
76 last_request_priority_
= priority
;
78 size_t id
= next_request_id_
++;
79 int rv
= ResolveFromIPLiteralOrCache(info
, addresses
);
80 if (rv
!= ERR_DNS_CACHE_MISS
) {
83 if (synchronous_mode_
) {
84 return ResolveProc(id
, info
, addresses
);
86 // Store the request for asynchronous resolution
87 Request
* req
= new Request(info
, addresses
, callback
);
90 *handle
= reinterpret_cast<RequestHandle
>(id
);
92 if (!ondemand_mode_
) {
93 base::MessageLoop::current()->PostTask(
95 base::Bind(&MockHostResolverBase::ResolveNow
, AsWeakPtr(), id
));
98 return ERR_IO_PENDING
;
101 int MockHostResolverBase::ResolveFromCache(const RequestInfo
& info
,
102 AddressList
* addresses
,
103 const BoundNetLog
& net_log
) {
104 num_resolve_from_cache_
++;
105 DCHECK(CalledOnValidThread());
107 int rv
= ResolveFromIPLiteralOrCache(info
, addresses
);
111 void MockHostResolverBase::CancelRequest(RequestHandle handle
) {
112 DCHECK(CalledOnValidThread());
113 size_t id
= reinterpret_cast<size_t>(handle
);
114 RequestMap::iterator it
= requests_
.find(id
);
115 if (it
!= requests_
.end()) {
116 scoped_ptr
<Request
> req(it
->second
);
119 NOTREACHED() << "CancelRequest must NOT be called after request is "
120 "complete or canceled.";
124 HostCache
* MockHostResolverBase::GetHostCache() {
128 void MockHostResolverBase::ResolveAllPending() {
129 DCHECK(CalledOnValidThread());
130 DCHECK(ondemand_mode_
);
131 for (RequestMap::iterator i
= requests_
.begin(); i
!= requests_
.end(); ++i
) {
132 base::MessageLoop::current()->PostTask(
134 base::Bind(&MockHostResolverBase::ResolveNow
, AsWeakPtr(), i
->first
));
138 // start id from 1 to distinguish from NULL RequestHandle
139 MockHostResolverBase::MockHostResolverBase(bool use_caching
)
140 : last_request_priority_(DEFAULT_PRIORITY
),
141 synchronous_mode_(false),
142 ondemand_mode_(false),
145 num_resolve_from_cache_(0) {
146 rules_
= CreateCatchAllHostResolverProc();
149 cache_
.reset(new HostCache(kMaxCacheEntries
));
153 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo
& info
,
154 AddressList
* addresses
) {
156 if (ParseIPLiteralToNumber(info
.hostname(), &ip
)) {
157 *addresses
= AddressList::CreateFromIPAddress(ip
, info
.port());
158 if (info
.host_resolver_flags() & HOST_RESOLVER_CANONNAME
)
159 addresses
->SetDefaultCanonicalName();
162 int rv
= ERR_DNS_CACHE_MISS
;
163 if (cache_
.get() && info
.allow_cached_response()) {
164 HostCache::Key
key(info
.hostname(),
165 info
.address_family(),
166 info
.host_resolver_flags());
167 const HostCache::Entry
* entry
= cache_
->Lookup(key
, base::TimeTicks::Now());
171 *addresses
= AddressList::CopyWithPort(entry
->addrlist
, info
.port());
177 int MockHostResolverBase::ResolveProc(size_t id
,
178 const RequestInfo
& info
,
179 AddressList
* addresses
) {
181 int rv
= rules_
->Resolve(info
.hostname(),
182 info
.address_family(),
183 info
.host_resolver_flags(),
187 HostCache::Key
key(info
.hostname(),
188 info
.address_family(),
189 info
.host_resolver_flags());
190 // Storing a failure with TTL 0 so that it overwrites previous value.
193 ttl
= base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds
);
194 cache_
->Set(key
, HostCache::Entry(rv
, addr
), base::TimeTicks::Now(), ttl
);
197 *addresses
= AddressList::CopyWithPort(addr
, info
.port());
201 void MockHostResolverBase::ResolveNow(size_t id
) {
202 RequestMap::iterator it
= requests_
.find(id
);
203 if (it
== requests_
.end())
204 return; // was canceled
206 scoped_ptr
<Request
> req(it
->second
);
208 int rv
= ResolveProc(id
, req
->info
, req
->addresses
);
209 if (!req
->callback
.is_null())
210 req
->callback
.Run(rv
);
213 //-----------------------------------------------------------------------------
215 struct RuleBasedHostResolverProc::Rule
{
219 kResolverTypeIPLiteral
,
222 ResolverType resolver_type
;
223 std::string host_pattern
;
224 AddressFamily address_family
;
225 HostResolverFlags host_resolver_flags
;
226 std::string replacement
;
227 std::string canonical_name
;
228 int latency_ms
; // In milliseconds.
230 Rule(ResolverType resolver_type
,
231 const std::string
& host_pattern
,
232 AddressFamily address_family
,
233 HostResolverFlags host_resolver_flags
,
234 const std::string
& replacement
,
235 const std::string
& canonical_name
,
237 : resolver_type(resolver_type
),
238 host_pattern(host_pattern
),
239 address_family(address_family
),
240 host_resolver_flags(host_resolver_flags
),
241 replacement(replacement
),
242 canonical_name(canonical_name
),
243 latency_ms(latency_ms
) {}
246 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc
* previous
)
247 : HostResolverProc(previous
) {
250 void RuleBasedHostResolverProc::AddRule(const std::string
& host_pattern
,
251 const std::string
& replacement
) {
252 AddRuleForAddressFamily(host_pattern
, ADDRESS_FAMILY_UNSPECIFIED
,
256 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
257 const std::string
& host_pattern
,
258 AddressFamily address_family
,
259 const std::string
& replacement
) {
260 DCHECK(!replacement
.empty());
261 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
262 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
263 Rule
rule(Rule::kResolverTypeSystem
,
270 rules_
.push_back(rule
);
273 void RuleBasedHostResolverProc::AddIPLiteralRule(
274 const std::string
& host_pattern
,
275 const std::string
& ip_literal
,
276 const std::string
& canonical_name
) {
277 // Literals are always resolved to themselves by HostResolverImpl,
278 // consequently we do not support remapping them.
279 IPAddressNumber ip_number
;
280 DCHECK(!ParseIPLiteralToNumber(host_pattern
, &ip_number
));
281 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
282 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
283 if (!canonical_name
.empty())
284 flags
|= HOST_RESOLVER_CANONNAME
;
285 Rule
rule(Rule::kResolverTypeIPLiteral
, host_pattern
,
286 ADDRESS_FAMILY_UNSPECIFIED
, flags
, ip_literal
, canonical_name
,
288 rules_
.push_back(rule
);
291 void RuleBasedHostResolverProc::AddRuleWithLatency(
292 const std::string
& host_pattern
,
293 const std::string
& replacement
,
295 DCHECK(!replacement
.empty());
296 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
297 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
298 Rule
rule(Rule::kResolverTypeSystem
,
300 ADDRESS_FAMILY_UNSPECIFIED
,
305 rules_
.push_back(rule
);
308 void RuleBasedHostResolverProc::AllowDirectLookup(
309 const std::string
& host_pattern
) {
310 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
311 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
312 Rule
rule(Rule::kResolverTypeSystem
,
314 ADDRESS_FAMILY_UNSPECIFIED
,
319 rules_
.push_back(rule
);
322 void RuleBasedHostResolverProc::AddSimulatedFailure(
323 const std::string
& host_pattern
) {
324 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
325 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
326 Rule
rule(Rule::kResolverTypeFail
,
328 ADDRESS_FAMILY_UNSPECIFIED
,
333 rules_
.push_back(rule
);
336 void RuleBasedHostResolverProc::ClearRules() {
340 int RuleBasedHostResolverProc::Resolve(const std::string
& host
,
341 AddressFamily address_family
,
342 HostResolverFlags host_resolver_flags
,
343 AddressList
* addrlist
,
345 RuleList::iterator r
;
346 for (r
= rules_
.begin(); r
!= rules_
.end(); ++r
) {
347 bool matches_address_family
=
348 r
->address_family
== ADDRESS_FAMILY_UNSPECIFIED
||
349 r
->address_family
== address_family
;
350 // Ignore HOST_RESOLVER_SYSTEM_ONLY, since it should have no impact on
351 // whether a rule matches.
352 HostResolverFlags flags
= host_resolver_flags
& ~HOST_RESOLVER_SYSTEM_ONLY
;
353 // Flags match if all of the bitflags in host_resolver_flags are enabled
354 // in the rule's host_resolver_flags. However, the rule may have additional
355 // flags specified, in which case the flags should still be considered a
357 bool matches_flags
= (r
->host_resolver_flags
& flags
) == flags
;
358 if (matches_flags
&& matches_address_family
&&
359 MatchPattern(host
, r
->host_pattern
)) {
360 if (r
->latency_ms
!= 0) {
361 base::PlatformThread::Sleep(
362 base::TimeDelta::FromMilliseconds(r
->latency_ms
));
365 // Remap to a new host.
366 const std::string
& effective_host
=
367 r
->replacement
.empty() ? host
: r
->replacement
;
369 // Apply the resolving function to the remapped hostname.
370 switch (r
->resolver_type
) {
371 case Rule::kResolverTypeFail
:
372 return ERR_NAME_NOT_RESOLVED
;
373 case Rule::kResolverTypeSystem
:
375 net::EnsureWinsockInit();
377 return SystemHostResolverCall(effective_host
,
381 case Rule::kResolverTypeIPLiteral
:
382 return ParseAddressList(effective_host
,
387 return ERR_UNEXPECTED
;
391 return ResolveUsingPrevious(host
, address_family
,
392 host_resolver_flags
, addrlist
, os_error
);
395 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
398 RuleBasedHostResolverProc
* CreateCatchAllHostResolverProc() {
399 RuleBasedHostResolverProc
* catchall
= new RuleBasedHostResolverProc(NULL
);
400 catchall
->AddIPLiteralRule("*", "127.0.0.1", "localhost");
402 // Next add a rules-based layer the use controls.
403 return new RuleBasedHostResolverProc(catchall
);
406 //-----------------------------------------------------------------------------
408 int HangingHostResolver::Resolve(const RequestInfo
& info
,
409 RequestPriority priority
,
410 AddressList
* addresses
,
411 const CompletionCallback
& callback
,
412 RequestHandle
* out_req
,
413 const BoundNetLog
& net_log
) {
414 return ERR_IO_PENDING
;
417 int HangingHostResolver::ResolveFromCache(const RequestInfo
& info
,
418 AddressList
* addresses
,
419 const BoundNetLog
& net_log
) {
420 return ERR_DNS_CACHE_MISS
;
423 //-----------------------------------------------------------------------------
425 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
427 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
428 HostResolverProc
* proc
) {
432 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
433 HostResolverProc
* old_proc
=
434 HostResolverProc::SetDefault(previous_proc_
.get());
435 // The lifetimes of multiple instances must be nested.
436 CHECK_EQ(old_proc
, current_proc_
);
439 void ScopedDefaultHostResolverProc::Init(HostResolverProc
* proc
) {
440 current_proc_
= proc
;
441 previous_proc_
= HostResolverProc::SetDefault(current_proc_
.get());
442 current_proc_
->SetLastProc(previous_proc_
.get());