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#ifndef NET_BASE_DNSRR_RESOLVER_H_
6#define NET_BASE_DNSRR_RESOLVER_H_
7#pragma once
8
9#include <map>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "base/basictypes.h"
15#include "base/memory/ref_counted.h"
16#include "base/threading/non_thread_safe.h"
17#include "base/time.h"
18#include "build/build_config.h"
19#include "net/base/completion_callback.h"
20#include "net/base/network_change_notifier.h"
21
22namespace net {
23
24// RRResponse contains the result of a successful request for a resource record.
25struct RRResponse {
26  RRResponse();
27  ~RRResponse();
28
29  // HasExpired returns true if |fetch_time| + |ttl| is less than
30  // |current_time|.
31  bool HasExpired(base::Time current_time) const;
32
33  // For testing only
34  bool ParseFromResponse(const uint8* data, unsigned len,
35                         uint16 rrtype_requested);
36
37  // name contains the canonical name of the resulting domain. If the queried
38  // name was a CNAME then this can differ.
39  std::string name;
40  // ttl contains the TTL of the resource records.
41  uint32 ttl;
42  // dnssec is true if the response was DNSSEC validated.
43  bool dnssec;
44  std::vector<std::string> rrdatas;
45  // sigs contains the RRSIG records returned.
46  std::vector<std::string> signatures;
47  // fetch_time is the time at which the response was received from the
48  // network.
49  base::Time fetch_time;
50  // negative is true if this is a negative cache entry, i.e. is a placeholder
51  // to remember that a given RR doesn't exist.
52  bool negative;
53};
54
55class BoundNetLog;
56class RRResolverWorker;
57class RRResolverJob;
58
59// DnsRRResolver resolves arbitary DNS resource record types. It should not be
60// confused with HostResolver and should not be used to resolve A/AAAA records.
61//
62// HostResolver exists to lookup addresses and there are many details about
63// address resolution over and above DNS (i.e. Bonjour, VPNs etc).
64//
65// DnsRRResolver should only be used when the data is specifically DNS data and
66// the name is a fully qualified DNS domain.
67//
68// A DnsRRResolver must be used from the MessageLoop which created it.
69class DnsRRResolver : public base::NonThreadSafe,
70                      public NetworkChangeNotifier::IPAddressObserver {
71 public:
72  typedef intptr_t Handle;
73
74  enum {
75    kInvalidHandle = 0,
76  };
77
78  enum {
79    // Try harder to get a DNSSEC signed response. This doesn't mean that the
80    // RRResponse will always have the dnssec bit set.
81    FLAG_WANT_DNSSEC = 1,
82  };
83
84  DnsRRResolver();
85  ~DnsRRResolver();
86
87  uint64 requests() const { return requests_; }
88  uint64 cache_hits() const { return cache_hits_; }
89  uint64 inflight_joins() const { return inflight_joins_; }
90
91  // Resolve starts the resolution process. When complete, |callback| is called
92  // with a result. If the result is |OK| then |response| is filled with the
93  // result of the resolution. Note that |callback| is called via the current
94  // MessageLoop.
95  //
96  // This returns a handle value which can be passed to |CancelResolve|. If
97  // this function returns kInvalidHandle then the resolution failed
98  // immediately because it was improperly formed.
99  Handle Resolve(const std::string& name, uint16 rrtype,
100                 uint16 flags, CompletionCallback* callback,
101                 RRResponse* response, int priority,
102                 const BoundNetLog& netlog);
103
104  // CancelResolve cancels an inflight lookup. The callback for this lookup
105  // must not have already been called.
106  void CancelResolve(Handle handle);
107
108  // Implementation of NetworkChangeNotifier::IPAddressObserver
109  virtual void OnIPAddressChanged();
110
111 private:
112  friend class RRResolverWorker;
113
114  void HandleResult(const std::string& name, uint16 rrtype, int result,
115                    const RRResponse& response);
116
117  // cache_ maps from a request to a cached response. The cached answer may
118  // have expired and the size of |cache_| must be <= kMaxCacheEntries.
119  //                < name      , rrtype>
120  std::map<std::pair<std::string, uint16>, RRResponse> cache_;
121  // inflight_ maps from a request to an active resolution which is taking
122  // place.
123  std::map<std::pair<std::string, uint16>, RRResolverJob*> inflight_;
124
125  uint64 requests_;
126  uint64 cache_hits_;
127  uint64 inflight_joins_;
128
129  bool in_destructor_;
130
131  DISALLOW_COPY_AND_ASSIGN(DnsRRResolver);
132};
133
134}  // namespace net
135
136#endif  // NET_BASE_DNSRR_RESOLVER_H_
137