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.
4
5#include "net/base/mock_host_resolver.h"
6
7#include "base/memory/ref_counted.h"
8#include "base/string_split.h"
9#include "base/string_util.h"
10#include "base/threading/platform_thread.h"
11#include "net/base/net_errors.h"
12#include "net/base/net_util.h"
13#include "net/base/sys_addrinfo.h"
14
15namespace net {
16
17namespace {
18
19char* do_strdup(const char* src) {
20#if defined(OS_WIN)
21  return _strdup(src);
22#else
23  return strdup(src);
24#endif
25}
26
27// Fills |*addrlist| with a socket address for |host_list| which should be a
28// comma-separated list of IPv4 or IPv6 literal(s) without enclosing brackets.
29// If |canonical_name| is non-empty it is used as the DNS canonical name for
30// the host. Returns OK on success, ERR_UNEXPECTED otherwise.
31int CreateIPAddressList(const std::string& host_list,
32                        const std::string& canonical_name,
33                        AddressList* addrlist) {
34  *addrlist = AddressList();
35  std::vector<std::string> addresses;
36  base::SplitString(host_list, ',', &addresses);
37  for (size_t index = 0; index < addresses.size(); ++index) {
38    IPAddressNumber ip_number;
39    if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) {
40      LOG(WARNING) << "Not a supported IP literal: " << addresses[index];
41      return ERR_UNEXPECTED;
42    }
43
44    AddressList result(ip_number, -1, false);
45    struct addrinfo* ai = const_cast<struct addrinfo*>(result.head());
46    if (index == 0)
47      ai->ai_canonname = do_strdup(canonical_name.c_str());
48    if (!addrlist->head())
49      addrlist->Copy(result.head(), false);
50    else
51      addrlist->Append(result.head());
52  }
53  return OK;
54}
55
56}  // namespace
57
58MockHostResolverBase::~MockHostResolverBase() {}
59
60void MockHostResolverBase::Reset(HostResolverProc* interceptor) {
61  synchronous_mode_ = false;
62
63  // At the root of the chain, map everything to localhost.
64  scoped_refptr<RuleBasedHostResolverProc> catchall(
65      new RuleBasedHostResolverProc(NULL));
66  catchall->AddRule("*", "127.0.0.1");
67
68  // Next add a rules-based layer the use controls.
69  rules_ = new RuleBasedHostResolverProc(catchall);
70
71  HostResolverProc* proc = rules_;
72
73  // Lastly add the provided interceptor to the front of the chain.
74  if (interceptor) {
75    interceptor->SetPreviousProc(proc);
76    proc = interceptor;
77  }
78
79  HostCache* cache = NULL;
80
81  if (use_caching_) {
82    cache = new HostCache(
83        100,  // max entries.
84        base::TimeDelta::FromMinutes(1),
85        base::TimeDelta::FromSeconds(0));
86  }
87
88  impl_.reset(new HostResolverImpl(proc, cache, 50u, NULL));
89}
90
91int MockHostResolverBase::Resolve(const RequestInfo& info,
92                                  AddressList* addresses,
93                                  CompletionCallback* callback,
94                                  RequestHandle* out_req,
95                                  const BoundNetLog& net_log) {
96  if (synchronous_mode_) {
97    callback = NULL;
98    out_req = NULL;
99  }
100  return impl_->Resolve(info, addresses, callback, out_req, net_log);
101}
102
103void MockHostResolverBase::CancelRequest(RequestHandle req) {
104  impl_->CancelRequest(req);
105}
106
107void MockHostResolverBase::AddObserver(Observer* observer) {
108  impl_->AddObserver(observer);
109}
110
111void MockHostResolverBase::RemoveObserver(Observer* observer) {
112  impl_->RemoveObserver(observer);
113}
114
115MockHostResolverBase::MockHostResolverBase(bool use_caching)
116    : use_caching_(use_caching) {
117  Reset(NULL);
118}
119
120//-----------------------------------------------------------------------------
121
122struct RuleBasedHostResolverProc::Rule {
123  enum ResolverType {
124    kResolverTypeFail,
125    kResolverTypeSystem,
126    kResolverTypeIPLiteral,
127  };
128
129  ResolverType resolver_type;
130  std::string host_pattern;
131  AddressFamily address_family;
132  HostResolverFlags host_resolver_flags;
133  std::string replacement;
134  std::string canonical_name;
135  int latency_ms;  // In milliseconds.
136
137  Rule(ResolverType resolver_type,
138       const std::string& host_pattern,
139       AddressFamily address_family,
140       HostResolverFlags host_resolver_flags,
141       const std::string& replacement,
142       const std::string& canonical_name,
143       int latency_ms)
144      : resolver_type(resolver_type),
145        host_pattern(host_pattern),
146        address_family(address_family),
147        host_resolver_flags(host_resolver_flags),
148        replacement(replacement),
149        canonical_name(canonical_name),
150        latency_ms(latency_ms) {}
151};
152
153RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
154    : HostResolverProc(previous) {
155}
156
157void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
158                                        const std::string& replacement) {
159  AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
160                          replacement);
161}
162
163void RuleBasedHostResolverProc::AddRuleForAddressFamily(
164    const std::string& host_pattern,
165    AddressFamily address_family,
166    const std::string& replacement) {
167  DCHECK(!replacement.empty());
168  HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
169      HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
170  Rule rule(Rule::kResolverTypeSystem, host_pattern, address_family, flags,
171            replacement, "", 0);
172  rules_.push_back(rule);
173}
174
175void RuleBasedHostResolverProc::AddIPLiteralRule(
176    const std::string& host_pattern,
177    const std::string& ip_literal,
178    const std::string& canonical_name) {
179  // Literals are always resolved to themselves by HostResolverImpl,
180  // consequently we do not support remapping them.
181  IPAddressNumber ip_number;
182  DCHECK(!ParseIPLiteralToNumber(host_pattern, &ip_number));
183  HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
184      HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
185  if (!canonical_name.empty())
186    flags |= HOST_RESOLVER_CANONNAME;
187  Rule rule(Rule::kResolverTypeIPLiteral, host_pattern,
188            ADDRESS_FAMILY_UNSPECIFIED, flags, ip_literal, canonical_name,
189            0);
190  rules_.push_back(rule);
191}
192
193void RuleBasedHostResolverProc::AddRuleWithLatency(
194    const std::string& host_pattern,
195    const std::string& replacement,
196    int latency_ms) {
197  DCHECK(!replacement.empty());
198  HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
199      HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
200  Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
201            flags, replacement, "", latency_ms);
202  rules_.push_back(rule);
203}
204
205void RuleBasedHostResolverProc::AllowDirectLookup(
206    const std::string& host_pattern) {
207  HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
208      HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
209  Rule rule(Rule::kResolverTypeSystem, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
210            flags, "", "", 0);
211  rules_.push_back(rule);
212}
213
214void RuleBasedHostResolverProc::AddSimulatedFailure(
215    const std::string& host_pattern) {
216  HostResolverFlags flags = HOST_RESOLVER_LOOPBACK_ONLY |
217      HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
218  Rule rule(Rule::kResolverTypeFail, host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
219            flags, "", "", 0);
220  rules_.push_back(rule);
221}
222
223int RuleBasedHostResolverProc::Resolve(const std::string& host,
224                                       AddressFamily address_family,
225                                       HostResolverFlags host_resolver_flags,
226                                       AddressList* addrlist,
227                                       int* os_error) {
228  RuleList::iterator r;
229  for (r = rules_.begin(); r != rules_.end(); ++r) {
230    bool matches_address_family =
231        r->address_family == ADDRESS_FAMILY_UNSPECIFIED ||
232        r->address_family == address_family;
233    // Flags match if all of the bitflags in host_resolver_flags are enabled
234    // in the rule's host_resolver_flags. However, the rule may have additional
235    // flags specified, in which case the flags should still be considered a
236    // match.
237    bool matches_flags = (r->host_resolver_flags & host_resolver_flags) ==
238        host_resolver_flags;
239    if (matches_flags && matches_address_family &&
240        MatchPattern(host, r->host_pattern)) {
241      if (r->latency_ms != 0)
242        base::PlatformThread::Sleep(r->latency_ms);
243
244      // Remap to a new host.
245      const std::string& effective_host =
246          r->replacement.empty() ? host : r->replacement;
247
248      // Apply the resolving function to the remapped hostname.
249      switch (r->resolver_type) {
250        case Rule::kResolverTypeFail:
251          return ERR_NAME_NOT_RESOLVED;
252        case Rule::kResolverTypeSystem:
253          return SystemHostResolverProc(effective_host,
254                                        address_family,
255                                        host_resolver_flags,
256                                        addrlist, os_error);
257        case Rule::kResolverTypeIPLiteral:
258          return CreateIPAddressList(effective_host,
259                                     r->canonical_name,
260                                     addrlist);
261        default:
262          NOTREACHED();
263          return ERR_UNEXPECTED;
264      }
265    }
266  }
267  return ResolveUsingPrevious(host, address_family,
268                              host_resolver_flags, addrlist, os_error);
269}
270
271RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
272}
273
274//-----------------------------------------------------------------------------
275
276WaitingHostResolverProc::WaitingHostResolverProc(HostResolverProc* previous)
277    : HostResolverProc(previous), event_(false, false) {}
278
279void WaitingHostResolverProc::Signal() {
280  event_.Signal();
281}
282
283int WaitingHostResolverProc::Resolve(const std::string& host,
284                                     AddressFamily address_family,
285                                     HostResolverFlags host_resolver_flags,
286                                     AddressList* addrlist,
287                                     int* os_error) {
288  event_.Wait();
289  return ResolveUsingPrevious(host, address_family, host_resolver_flags,
290                              addrlist, os_error);
291}
292
293WaitingHostResolverProc::~WaitingHostResolverProc() {}
294
295//-----------------------------------------------------------------------------
296
297ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
298
299ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
300    HostResolverProc* proc) {
301  Init(proc);
302}
303
304ScopedDefaultHostResolverProc::~ScopedDefaultHostResolverProc() {
305  HostResolverProc* old_proc = HostResolverProc::SetDefault(previous_proc_);
306  // The lifetimes of multiple instances must be nested.
307  CHECK_EQ(old_proc, current_proc_);
308}
309
310void ScopedDefaultHostResolverProc::Init(HostResolverProc* proc) {
311  current_proc_ = proc;
312  previous_proc_ = HostResolverProc::SetDefault(current_proc_);
313  current_proc_->SetLastProc(previous_proc_);
314}
315
316}  // namespace net
317