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/base/mock_host_resolver.h"
10 #include "base/bind.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/message_loop.h"
13 #include "base/stl_util.h"
14 #include "base/string_split.h"
15 #include "base/string_util.h"
16 #include "base/threading/platform_thread.h"
17 #include "net/base/host_cache.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/net_util.h"
20 #include "net/base/test_completion_callback.h"
22 #include "net/base/winsock_init.h"
29 // Cache size for the MockCachingHostResolver.
30 const unsigned kMaxCacheEntries
= 100;
31 // TTL for the successful resolutions. Failures are not cached.
32 const unsigned kCacheEntryTTLSeconds
= 60;
36 int ParseAddressList(const std::string
& host_list
,
37 const std::string
& canonical_name
,
38 AddressList
* addrlist
) {
39 *addrlist
= AddressList();
40 std::vector
<std::string
> addresses
;
41 base::SplitString(host_list
, ',', &addresses
);
42 addrlist
->set_canonical_name(canonical_name
);
43 for (size_t index
= 0; index
< addresses
.size(); ++index
) {
44 IPAddressNumber ip_number
;
45 if (!ParseIPLiteralToNumber(addresses
[index
], &ip_number
)) {
46 LOG(WARNING
) << "Not a supported IP literal: " << addresses
[index
];
47 return ERR_UNEXPECTED
;
49 addrlist
->push_back(IPEndPoint(ip_number
, -1));
54 struct MockHostResolverBase::Request
{
55 Request(const RequestInfo
& req_info
,
57 const CompletionCallback
& cb
)
58 : info(req_info
), addresses(addr
), callback(cb
) {}
60 AddressList
* addresses
;
61 CompletionCallback callback
;
64 MockHostResolverBase::~MockHostResolverBase() {
65 STLDeleteValues(&requests_
);
68 int MockHostResolverBase::Resolve(const RequestInfo
& info
,
69 AddressList
* addresses
,
70 const CompletionCallback
& callback
,
71 RequestHandle
* handle
,
72 const BoundNetLog
& net_log
) {
73 DCHECK(CalledOnValidThread());
74 size_t id
= next_request_id_
++;
75 int rv
= ResolveFromIPLiteralOrCache(info
, addresses
);
76 if (rv
!= ERR_DNS_CACHE_MISS
) {
79 if (synchronous_mode_
) {
80 return ResolveProc(id
, info
, addresses
);
82 // Store the request for asynchronous resolution
83 Request
* req
= new Request(info
, addresses
, callback
);
86 *handle
= reinterpret_cast<RequestHandle
>(id
);
87 MessageLoop::current()->PostTask(FROM_HERE
,
88 base::Bind(&MockHostResolverBase::ResolveNow
,
91 return ERR_IO_PENDING
;
94 int MockHostResolverBase::ResolveFromCache(const RequestInfo
& info
,
95 AddressList
* addresses
,
96 const BoundNetLog
& net_log
) {
97 DCHECK(CalledOnValidThread());
99 int rv
= ResolveFromIPLiteralOrCache(info
, addresses
);
103 void MockHostResolverBase::CancelRequest(RequestHandle handle
) {
104 DCHECK(CalledOnValidThread());
105 size_t id
= reinterpret_cast<size_t>(handle
);
106 RequestMap::iterator it
= requests_
.find(id
);
107 if (it
!= requests_
.end()) {
108 scoped_ptr
<Request
> req(it
->second
);
111 NOTREACHED() << "CancelRequest must NOT be called after request is "
112 "complete or canceled.";
116 HostCache
* MockHostResolverBase::GetHostCache() {
120 // start id from 1 to distinguish from NULL RequestHandle
121 MockHostResolverBase::MockHostResolverBase(bool use_caching
)
122 : synchronous_mode_(false), next_request_id_(1) {
123 rules_
= CreateCatchAllHostResolverProc();
126 cache_
.reset(new HostCache(kMaxCacheEntries
));
130 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo
& info
,
131 AddressList
* addresses
) {
133 if (ParseIPLiteralToNumber(info
.hostname(), &ip
)) {
134 *addresses
= AddressList::CreateFromIPAddress(ip
, info
.port());
135 if (info
.host_resolver_flags() & HOST_RESOLVER_CANONNAME
)
136 addresses
->SetDefaultCanonicalName();
139 int rv
= ERR_DNS_CACHE_MISS
;
140 if (cache_
.get() && info
.allow_cached_response()) {
141 HostCache::Key
key(info
.hostname(),
142 info
.address_family(),
143 info
.host_resolver_flags());
144 const HostCache::Entry
* entry
= cache_
->Lookup(key
, base::TimeTicks::Now());
148 *addresses
= AddressList::CopyWithPort(entry
->addrlist
, info
.port());
154 int MockHostResolverBase::ResolveProc(size_t id
,
155 const RequestInfo
& info
,
156 AddressList
* addresses
) {
158 int rv
= rules_
->Resolve(info
.hostname(),
159 info
.address_family(),
160 info
.host_resolver_flags(),
164 HostCache::Key
key(info
.hostname(),
165 info
.address_family(),
166 info
.host_resolver_flags());
167 // Storing a failure with TTL 0 so that it overwrites previous value.
170 ttl
= base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds
);
171 cache_
->Set(key
, HostCache::Entry(rv
, addr
), base::TimeTicks::Now(), ttl
);
174 *addresses
= AddressList::CopyWithPort(addr
, info
.port());
178 void MockHostResolverBase::ResolveNow(size_t id
) {
179 RequestMap::iterator it
= requests_
.find(id
);
180 if (it
== requests_
.end())
181 return; // was canceled
183 scoped_ptr
<Request
> req(it
->second
);
185 int rv
= ResolveProc(id
, req
->info
, req
->addresses
);
186 if (!req
->callback
.is_null())
187 req
->callback
.Run(rv
);
190 //-----------------------------------------------------------------------------
192 struct RuleBasedHostResolverProc::Rule
{
196 kResolverTypeIPLiteral
,
199 ResolverType resolver_type
;
200 std::string host_pattern
;
201 AddressFamily address_family
;
202 HostResolverFlags host_resolver_flags
;
203 std::string replacement
;
204 std::string canonical_name
;
205 int latency_ms
; // In milliseconds.
207 Rule(ResolverType resolver_type
,
208 const std::string
& host_pattern
,
209 AddressFamily address_family
,
210 HostResolverFlags host_resolver_flags
,
211 const std::string
& replacement
,
212 const std::string
& canonical_name
,
214 : resolver_type(resolver_type
),
215 host_pattern(host_pattern
),
216 address_family(address_family
),
217 host_resolver_flags(host_resolver_flags
),
218 replacement(replacement
),
219 canonical_name(canonical_name
),
220 latency_ms(latency_ms
) {}
223 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc
* previous
)
224 : HostResolverProc(previous
) {
227 void RuleBasedHostResolverProc::AddRule(const std::string
& host_pattern
,
228 const std::string
& replacement
) {
229 AddRuleForAddressFamily(host_pattern
, ADDRESS_FAMILY_UNSPECIFIED
,
233 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
234 const std::string
& host_pattern
,
235 AddressFamily address_family
,
236 const std::string
& replacement
) {
237 DCHECK(!replacement
.empty());
238 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
239 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
240 Rule
rule(Rule::kResolverTypeSystem
, host_pattern
, address_family
, flags
,
242 rules_
.push_back(rule
);
245 void RuleBasedHostResolverProc::AddIPLiteralRule(
246 const std::string
& host_pattern
,
247 const std::string
& ip_literal
,
248 const std::string
& canonical_name
) {
249 // Literals are always resolved to themselves by HostResolverImpl,
250 // consequently we do not support remapping them.
251 IPAddressNumber ip_number
;
252 DCHECK(!ParseIPLiteralToNumber(host_pattern
, &ip_number
));
253 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
254 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
255 if (!canonical_name
.empty())
256 flags
|= HOST_RESOLVER_CANONNAME
;
257 Rule
rule(Rule::kResolverTypeIPLiteral
, host_pattern
,
258 ADDRESS_FAMILY_UNSPECIFIED
, flags
, ip_literal
, canonical_name
,
260 rules_
.push_back(rule
);
263 void RuleBasedHostResolverProc::AddRuleWithLatency(
264 const std::string
& host_pattern
,
265 const std::string
& replacement
,
267 DCHECK(!replacement
.empty());
268 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
269 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
270 Rule
rule(Rule::kResolverTypeSystem
, host_pattern
, ADDRESS_FAMILY_UNSPECIFIED
,
271 flags
, replacement
, "", latency_ms
);
272 rules_
.push_back(rule
);
275 void RuleBasedHostResolverProc::AllowDirectLookup(
276 const std::string
& host_pattern
) {
277 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
278 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
279 Rule
rule(Rule::kResolverTypeSystem
, host_pattern
, ADDRESS_FAMILY_UNSPECIFIED
,
281 rules_
.push_back(rule
);
284 void RuleBasedHostResolverProc::AddSimulatedFailure(
285 const std::string
& host_pattern
) {
286 HostResolverFlags flags
= HOST_RESOLVER_LOOPBACK_ONLY
|
287 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6
;
288 Rule
rule(Rule::kResolverTypeFail
, host_pattern
, ADDRESS_FAMILY_UNSPECIFIED
,
290 rules_
.push_back(rule
);
293 int RuleBasedHostResolverProc::Resolve(const std::string
& host
,
294 AddressFamily address_family
,
295 HostResolverFlags host_resolver_flags
,
296 AddressList
* addrlist
,
298 RuleList::iterator r
;
299 for (r
= rules_
.begin(); r
!= rules_
.end(); ++r
) {
300 bool matches_address_family
=
301 r
->address_family
== ADDRESS_FAMILY_UNSPECIFIED
||
302 r
->address_family
== address_family
;
303 // Flags match if all of the bitflags in host_resolver_flags are enabled
304 // in the rule's host_resolver_flags. However, the rule may have additional
305 // flags specified, in which case the flags should still be considered a
307 bool matches_flags
= (r
->host_resolver_flags
& host_resolver_flags
) ==
309 if (matches_flags
&& matches_address_family
&&
310 MatchPattern(host
, r
->host_pattern
)) {
311 if (r
->latency_ms
!= 0) {
312 base::PlatformThread::Sleep(
313 base::TimeDelta::FromMilliseconds(r
->latency_ms
));
316 // Remap to a new host.
317 const std::string
& effective_host
=
318 r
->replacement
.empty() ? host
: r
->replacement
;
320 // Apply the resolving function to the remapped hostname.
321 switch (r
->resolver_type
) {
322 case Rule::kResolverTypeFail
:
323 return ERR_NAME_NOT_RESOLVED
;
324 case Rule::kResolverTypeSystem
:
326 net::EnsureWinsockInit();
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 catchall
->AddIPLiteralRule("*", "127.0.0.1", "localhost");
353 // Next add a rules-based layer the use controls.
354 return new RuleBasedHostResolverProc(catchall
);
357 //-----------------------------------------------------------------------------
359 int HangingHostResolver::Resolve(const RequestInfo
& info
,
360 AddressList
* addresses
,
361 const CompletionCallback
& callback
,
362 RequestHandle
* out_req
,
363 const BoundNetLog
& net_log
) {
364 return ERR_IO_PENDING
;
367 int HangingHostResolver::ResolveFromCache(const RequestInfo
& info
,
368 AddressList
* addresses
,
369 const BoundNetLog
& net_log
) {
370 return ERR_DNS_CACHE_MISS
;
373 //-----------------------------------------------------------------------------
375 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
377 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
378 HostResolverProc
* proc
) {
382 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
383 HostResolverProc
* old_proc
= HostResolverProc::SetDefault(previous_proc_
);
384 // The lifetimes of multiple instances must be nested.
385 CHECK_EQ(old_proc
, current_proc_
);
388 void ScopedDefaultHostResolverProc::Init(HostResolverProc
* proc
) {
389 current_proc_
= proc
;
390 previous_proc_
= HostResolverProc::SetDefault(current_proc_
);
391 current_proc_
->SetLastProc(previous_proc_
);