Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: net/base/mock_host_resolver.cc

Issue 12518036: net: move host_resolver files from net/base to net/dns (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "net/base/mock_host_resolver.h"
6
7 #include <string>
8 #include <vector>
9
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_util.h"
15 #include "base/strings/string_split.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"
21 #if defined(OS_WIN)
22 #include "net/base/winsock_init.h"
23 #endif
24
25 namespace net {
26
27 namespace {
28
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;
33
34 } // namespace
35
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;
48 }
49 addrlist->push_back(IPEndPoint(ip_number, -1));
50 }
51 return OK;
52 }
53
54 struct MockHostResolverBase::Request {
55 Request(const RequestInfo& req_info,
56 AddressList* addr,
57 const CompletionCallback& cb)
58 : info(req_info), addresses(addr), callback(cb) {}
59 RequestInfo info;
60 AddressList* addresses;
61 CompletionCallback callback;
62 };
63
64 MockHostResolverBase::~MockHostResolverBase() {
65 STLDeleteValues(&requests_);
66 }
67
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 num_resolve_++;
75 size_t id = next_request_id_++;
76 int rv = ResolveFromIPLiteralOrCache(info, addresses);
77 if (rv != ERR_DNS_CACHE_MISS) {
78 return rv;
79 }
80 if (synchronous_mode_) {
81 return ResolveProc(id, info, addresses);
82 }
83 // Store the request for asynchronous resolution
84 Request* req = new Request(info, addresses, callback);
85 requests_[id] = req;
86 if (handle)
87 *handle = reinterpret_cast<RequestHandle>(id);
88
89 if (!ondemand_mode_) {
90 MessageLoop::current()->PostTask(
91 FROM_HERE,
92 base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), id));
93 }
94
95 return ERR_IO_PENDING;
96 }
97
98 int MockHostResolverBase::ResolveFromCache(const RequestInfo& info,
99 AddressList* addresses,
100 const BoundNetLog& net_log) {
101 num_resolve_from_cache_++;
102 DCHECK(CalledOnValidThread());
103 next_request_id_++;
104 int rv = ResolveFromIPLiteralOrCache(info, addresses);
105 return rv;
106 }
107
108 void MockHostResolverBase::CancelRequest(RequestHandle handle) {
109 DCHECK(CalledOnValidThread());
110 size_t id = reinterpret_cast<size_t>(handle);
111 RequestMap::iterator it = requests_.find(id);
112 if (it != requests_.end()) {
113 scoped_ptr<Request> req(it->second);
114 requests_.erase(it);
115 } else {
116 NOTREACHED() << "CancelRequest must NOT be called after request is "
117 "complete or canceled.";
118 }
119 }
120
121 HostCache* MockHostResolverBase::GetHostCache() {
122 return cache_.get();
123 }
124
125 void MockHostResolverBase::ResolveAllPending() {
126 DCHECK(CalledOnValidThread());
127 DCHECK(ondemand_mode_);
128 for (RequestMap::iterator i = requests_.begin(); i != requests_.end(); ++i) {
129 MessageLoop::current()->PostTask(
130 FROM_HERE,
131 base::Bind(&MockHostResolverBase::ResolveNow, AsWeakPtr(), i->first));
132 }
133 }
134
135 // start id from 1 to distinguish from NULL RequestHandle
136 MockHostResolverBase::MockHostResolverBase(bool use_caching)
137 : synchronous_mode_(false),
138 ondemand_mode_(false),
139 next_request_id_(1),
140 num_resolve_(0),
141 num_resolve_from_cache_(0) {
142 rules_ = CreateCatchAllHostResolverProc();
143
144 if (use_caching) {
145 cache_.reset(new HostCache(kMaxCacheEntries));
146 }
147 }
148
149 int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info,
150 AddressList* addresses) {
151 IPAddressNumber ip;
152 if (ParseIPLiteralToNumber(info.hostname(), &ip)) {
153 *addresses = AddressList::CreateFromIPAddress(ip, info.port());
154 if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME)
155 addresses->SetDefaultCanonicalName();
156 return OK;
157 }
158 int rv = ERR_DNS_CACHE_MISS;
159 if (cache_.get() && info.allow_cached_response()) {
160 HostCache::Key key(info.hostname(),
161 info.address_family(),
162 info.host_resolver_flags());
163 const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now());
164 if (entry) {
165 rv = entry->error;
166 if (rv == OK)
167 *addresses = AddressList::CopyWithPort(entry->addrlist, info.port());
168 }
169 }
170 return rv;
171 }
172
173 int MockHostResolverBase::ResolveProc(size_t id,
174 const RequestInfo& info,
175 AddressList* addresses) {
176 AddressList addr;
177 int rv = rules_->Resolve(info.hostname(),
178 info.address_family(),
179 info.host_resolver_flags(),
180 &addr,
181 NULL);
182 if (cache_.get()) {
183 HostCache::Key key(info.hostname(),
184 info.address_family(),
185 info.host_resolver_flags());
186 // Storing a failure with TTL 0 so that it overwrites previous value.
187 base::TimeDelta ttl;
188 if (rv == OK)
189 ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds);
190 cache_->Set(key, HostCache::Entry(rv, addr), base::TimeTicks::Now(), ttl);
191 }
192 if (rv == OK)
193 *addresses = AddressList::CopyWithPort(addr, info.port());
194 return rv;
195 }
196
197 void MockHostResolverBase::ResolveNow(size_t id) {
198 RequestMap::iterator it = requests_.find(id);
199 if (it == requests_.end())
200 return; // was canceled
201
202 scoped_ptr<Request> req(it->second);
203 requests_.erase(it);
204 int rv = ResolveProc(id, req->info, req->addresses);
205 if (!req->callback.is_null())
206 req->callback.Run(rv);
207 }
208
209 //-----------------------------------------------------------------------------
210
211 struct RuleBasedHostResolverProc::Rule {
212 enum ResolverType {
213 kResolverTypeFail,
214 kResolverTypeSystem,
215 kResolverTypeIPLiteral,
216 };
217
218 ResolverType resolver_type;
219 std::string host_pattern;
220 AddressFamily address_family;
221 HostResolverFlags host_resolver_flags;
222 std::string replacement;
223 std::string canonical_name;
224 int latency_ms; // In milliseconds.
225
226 Rule(ResolverType resolver_type,
227 const std::string& host_pattern,
228 AddressFamily address_family,
229 HostResolverFlags host_resolver_flags,
230 const std::string& replacement,
231 const std::string& canonical_name,
232 int latency_ms)
233 : resolver_type(resolver_type),
234 host_pattern(host_pattern),
235 address_family(address_family),
236 host_resolver_flags(host_resolver_flags),
237 replacement(replacement),
238 canonical_name(canonical_name),
239 latency_ms(latency_ms) {}
240 };
241
242 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
243 : HostResolverProc(previous) {
244 }
245
246 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
247 const std::string& replacement) {
248 AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
249 replacement);
250 }
251
252 void RuleBasedHostResolverProc::AddRuleForAddressFamily(
253 const std::string& host_pattern,
254 AddressFamily address_family,
255 const std::string& replacement) {
256 DCHECK(!replacement.empty());
257 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
258 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
259 Rule rule(Rule::kResolverTypeSystem, host_pattern, address_family, flags,
260 replacement, "", 0);
261 rules_.push_back(rule);
262 }
263
264 void RuleBasedHostResolverProc::AddIPLiteralRule(
265 const std::string& host_pattern,
266 const std::string& ip_literal,
267 const std::string& canonical_name) {
268 // Literals are always resolved to themselves by HostResolverImpl,
269 // consequently we do not support remapping them.
270 IPAddressNumber ip_number;
271 DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
272 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
273 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
274 if (!canonical_name.empty())
275 flags |= HOST_RESOLVER_CANONNAME;
276 Rule rule(Rule::kResolverTypeIPLiteral, host_pattern,
277 ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name,
278 0);
279 rules_.push_back(rule);
280 }
281
282 void RuleBasedHostResolverProc::AddRuleWithLatency(
283 const std::string& host_pattern,
284 const std::string& replacement,
285 int latency_ms) {
286 DCHECK(!replacement.empty());
287 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
288 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
289 Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
290 flags, replacement, "", latency_ms);
291 rules_.push_back(rule);
292 }
293
294 void RuleBasedHostResolverProc::AllowDirectLookup(
295 const std::string& host_pattern) {
296 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
297 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
298 Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
299 flags, "", "", 0);
300 rules_.push_back(rule);
301 }
302
303 void RuleBasedHostResolverProc::AddSimulatedFailure(
304 const std::string& host_pattern) {
305 HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
306 HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
307 Rule rule(Rule::kResolverTypeFail, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
308 flags, "", "", 0);
309 rules_.push_back(rule);
310 }
311
312 void RuleBasedHostResolverProc::ClearRules() {
313 rules_.clear();
314 }
315
316 int RuleBasedHostResolverProc::Resolve(const std::string& host,
317 AddressFamily address_family,
318 HostResolverFlags host_resolver_flags,
319 AddressList* addrlist,
320 int* os_error) {
321 RuleList::iterator r;
322 for (r = rules_.begin(); r != rules_.end(); ++r) {
323 bool matches_address_family =
324 r->address_family == ADDRESS_FAMILY_UNSPECIFIED ||
325 r->address_family == address_family;
326 // Flags match if all of the bitflags in host_resolver_flags are enabled
327 // in the rule's host_resolver_flags. However, the rule may have additional
328 // flags specified, in which case the flags should still be considered a
329 // match.
330 bool matches_flags = (r->host_resolver_flags & host_resolver_flags) ==
331 host_resolver_flags;
332 if (matches_flags && matches_address_family &&
333 MatchPattern(host, r->host_pattern)) {
334 if (r->latency_ms != 0) {
335 base::PlatformThread::Sleep(
336 base::TimeDelta::FromMilliseconds(r->latency_ms));
337 }
338
339 // Remap to a new host.
340 const std::string& effective_host =
341 r->replacement.empty() ? host : r->replacement;
342
343 // Apply the resolving function to the remapped hostname.
344 switch (r->resolver_type) {
345 case Rule::kResolverTypeFail:
346 return ERR_NAME_NOT_RESOLVED;
347 case Rule::kResolverTypeSystem:
348 #if defined(OS_WIN)
349 net::EnsureWinsockInit();
350 #endif
351 return SystemHostResolverProc(effective_host,
352 address_family,
353 host_resolver_flags,
354 addrlist, os_error);
355 case Rule::kResolverTypeIPLiteral:
356 return ParseAddressList(effective_host,
357 r->canonical_name,
358 addrlist);
359 default:
360 NOTREACHED();
361 return ERR_UNEXPECTED;
362 }
363 }
364 }
365 return ResolveUsingPrevious(host, address_family,
366 host_resolver_flags, addrlist, os_error);
367 }
368
369 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
370 }
371
372 RuleBasedHostResolverProc* CreateCatchAllHostResolverProc() {
373 RuleBasedHostResolverProc* catchall = new RuleBasedHostResolverProc(NULL);
374 catchall->AddIPLiteralRule("*", "127.0.0.1", "localhost");
375
376 // Next add a rules-based layer the use controls.
377 return new RuleBasedHostResolverProc(catchall);
378 }
379
380 //-----------------------------------------------------------------------------
381
382 int HangingHostResolver::Resolve(const RequestInfo& info,
383 AddressList* addresses,
384 const CompletionCallback& callback,
385 RequestHandle* out_req,
386 const BoundNetLog& net_log) {
387 return ERR_IO_PENDING;
388 }
389
390 int HangingHostResolver::ResolveFromCache(const RequestInfo& info,
391 AddressList* addresses,
392 const BoundNetLog& net_log) {
393 return ERR_DNS_CACHE_MISS;
394 }
395
396 //-----------------------------------------------------------------------------
397
398 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
399
400 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
401 HostResolverProc* proc) {
402 Init(proc);
403 }
404
405 ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
406 HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_);
407 // The lifetimes of multiple instances must be nested.
408 CHECK_EQ(old_proc, current_proc_);
409 }
410
411 void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
412 current_proc_ = proc;
413 previous_proc_ = HostResolverProc::SetDefault(current_proc_);
414 current_proc_->SetLastProc(previous_proc_);
415 }
416
417 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698