• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 namespace net {
16 
17 namespace {
18 
do_strdup(const char * src)19 char* 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.
CreateIPAddressList(const std::string & host_list,const std::string & canonical_name,AddressList * addrlist)31 int 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 
~MockHostResolverBase()58 MockHostResolverBase::~MockHostResolverBase() {}
59 
Reset(HostResolverProc * interceptor)60 void 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 
Resolve(const RequestInfo & info,AddressList * addresses,CompletionCallback * callback,RequestHandle * out_req,const BoundNetLog & net_log)91 int 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 
CancelRequest(RequestHandle req)103 void MockHostResolverBase::CancelRequest(RequestHandle req) {
104   impl_->CancelRequest(req);
105 }
106 
AddObserver(Observer * observer)107 void MockHostResolverBase::AddObserver(Observer* observer) {
108   impl_->AddObserver(observer);
109 }
110 
RemoveObserver(Observer * observer)111 void MockHostResolverBase::RemoveObserver(Observer* observer) {
112   impl_->RemoveObserver(observer);
113 }
114 
MockHostResolverBase(bool use_caching)115 MockHostResolverBase::MockHostResolverBase(bool use_caching)
116     : use_caching_(use_caching) {
117   Reset(NULL);
118 }
119 
120 //-----------------------------------------------------------------------------
121 
122 struct 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 
Rulenet::RuleBasedHostResolverProc::Rule137   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 
RuleBasedHostResolverProc(HostResolverProc * previous)153 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
154     : HostResolverProc(previous) {
155 }
156 
AddRule(const std::string & host_pattern,const std::string & replacement)157 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
158                                         const std::string& replacement) {
159   AddRuleForAddressFamily(host_pattern, ADDRESS_FAMILY_UNSPECIFIED,
160                           replacement);
161 }
162 
AddRuleForAddressFamily(const std::string & host_pattern,AddressFamily address_family,const std::string & replacement)163 void 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 
AddIPLiteralRule(const std::string & host_pattern,const std::string & ip_literal,const std::string & canonical_name)175 void 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 
AddRuleWithLatency(const std::string & host_pattern,const std::string & replacement,int latency_ms)193 void 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 
AllowDirectLookup(const std::string & host_pattern)205 void 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 
AddSimulatedFailure(const std::string & host_pattern)214 void 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 
Resolve(const std::string & host,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)223 int 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 
~RuleBasedHostResolverProc()271 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
272 }
273 
274 //-----------------------------------------------------------------------------
275 
WaitingHostResolverProc(HostResolverProc * previous)276 WaitingHostResolverProc::WaitingHostResolverProc(HostResolverProc* previous)
277     : HostResolverProc(previous), event_(false, false) {}
278 
Signal()279 void WaitingHostResolverProc::Signal() {
280   event_.Signal();
281 }
282 
Resolve(const std::string & host,AddressFamily address_family,HostResolverFlags host_resolver_flags,AddressList * addrlist,int * os_error)283 int 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 
~WaitingHostResolverProc()293 WaitingHostResolverProc::~WaitingHostResolverProc() {}
294 
295 //-----------------------------------------------------------------------------
296 
ScopedDefaultHostResolverProc()297 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
298 
ScopedDefaultHostResolverProc(HostResolverProc * proc)299 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
300     HostResolverProc* proc) {
301   Init(proc);
302 }
303 
~ScopedDefaultHostResolverProc()304 ScopedDefaultHostResolverProc::~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 
Init(HostResolverProc * proc)310 void 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