Home | History | Annotate | Download | only in base
      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 
     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.
     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 
     58 MockHostResolverBase::~MockHostResolverBase() {}
     59 
     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 
     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 
    103 void MockHostResolverBase::CancelRequest(RequestHandle req) {
    104   impl_->CancelRequest(req);
    105 }
    106 
    107 void MockHostResolverBase::AddObserver(Observer* observer) {
    108   impl_->AddObserver(observer);
    109 }
    110 
    111 void MockHostResolverBase::RemoveObserver(Observer* observer) {
    112   impl_->RemoveObserver(observer);
    113 }
    114 
    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 
    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 
    153 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous)
    154     : HostResolverProc(previous) {
    155 }
    156 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    271 RuleBasedHostResolverProc::~RuleBasedHostResolverProc() {
    272 }
    273 
    274 //-----------------------------------------------------------------------------
    275 
    276 WaitingHostResolverProc::WaitingHostResolverProc(HostResolverProc* previous)
    277     : HostResolverProc(previous), event_(false, false) {}
    278 
    279 void WaitingHostResolverProc::Signal() {
    280   event_.Signal();
    281 }
    282 
    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 
    293 WaitingHostResolverProc::~WaitingHostResolverProc() {}
    294 
    295 //-----------------------------------------------------------------------------
    296 
    297 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc() {}
    298 
    299 ScopedDefaultHostResolverProc::ScopedDefaultHostResolverProc(
    300     HostResolverProc* proc) {
    301   Init(proc);
    302 }
    303 
    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 
    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