1
#pragma once
2

            
3
#include <chrono>
4
#include <functional>
5
#include <list>
6
#include <memory>
7
#include <string>
8

            
9
#include "envoy/common/pure.h"
10
#include "envoy/common/time.h"
11
#include "envoy/network/address.h"
12

            
13
#include "absl/types/optional.h"
14
#include "absl/types/variant.h"
15

            
16
namespace Envoy {
17
namespace Network {
18

            
19
/**
20
 * An active async DNS query.
21
 */
22
class ActiveDnsQuery {
23
public:
24
2034
  virtual ~ActiveDnsQuery() = default;
25

            
26
  enum class CancelReason {
27
    // The caller no longer needs the answer to the query.
28
    QueryAbandoned,
29
    // The query timed out from the perspective of the caller. The DNS implementation may take
30
    // a different action in this case (e.g., destroying existing DNS connections) in an effort
31
    // to get an answer to future queries.
32
    Timeout
33
  };
34

            
35
  /** Store the trace information. */
36
  struct Trace {
37
    /**
38
     * An identifier to store the trace information. The trace is `uint8_t` because the value can
39
     * vary depending on the DNS resolver implementation.
40
     */
41
    uint8_t trace_;
42
    /** Store the current time of this trace. */
43
    MonotonicTime time_;
44
  };
45

            
46
  /**
47
   * Cancel an outstanding DNS request.
48
   * @param reason supplies the cancel reason.
49
   */
50
  virtual void cancel(CancelReason reason) PURE;
51

            
52
  /**
53
   * Add a trace for the DNS query. The trace lifetime is tied to the lifetime of `ActiveQuery` and
54
   * `ActiveQuery` will be destroyed upon query completion or cancellation.
55
   */
56
  virtual void addTrace(uint8_t trace) PURE;
57

            
58
  /** Return the DNS query traces. */
59
  virtual std::string getTraces() PURE;
60
};
61

            
62
/**
63
 * DNS A/AAAA record response.
64
 */
65
struct AddrInfoResponse {
66
  const Address::InstanceConstSharedPtr address_;
67
  const std::chrono::seconds ttl_;
68
};
69

            
70
/**
71
 * DNS SRV record response.
72
 */
73
struct SrvResponse {
74
  const std::string host_;
75
  const uint16_t port_;
76
  const uint16_t priority_;
77
  const uint16_t weight_;
78
};
79

            
80
enum class RecordType { A, AAAA, SRV };
81

            
82
enum class DnsLookupFamily { V4Only, V6Only, Auto, V4Preferred, All };
83

            
84
class DnsResponse {
85
public:
86
  DnsResponse(const Address::InstanceConstSharedPtr& address, const std::chrono::seconds ttl)
87
1368
      : response_(AddrInfoResponse{
88
1368
            address,
89
1368
            std::chrono::seconds(std::min(std::chrono::seconds::rep(INT_MAX),
90
1368
                                          std::max(ttl.count(), std::chrono::seconds::rep(0))))}) {}
91
  DnsResponse(const std::string& host, uint16_t port, uint16_t priority, uint16_t weight)
92
      : response_(SrvResponse{host, port, priority, weight}) {}
93

            
94
1943
  const AddrInfoResponse& addrInfo() const { return absl::get<AddrInfoResponse>(response_); }
95

            
96
  const SrvResponse& srv() const { return absl::get<SrvResponse>(response_); }
97

            
98
private:
99
  absl::variant<AddrInfoResponse, SrvResponse> response_;
100
};
101

            
102
/**
103
 * An asynchronous DNS resolver.
104
 */
105
class DnsResolver {
106
public:
107
1911
  virtual ~DnsResolver() = default;
108

            
109
  /**
110
   * Final status for a DNS resolution.
111
   * DNS resolution can return result statuses like NODATA、SERVFAIL and NONAME,
112
   * which indicate successful completion of the query but
113
   * no results, and `Completed` is a more accurate way of reflecting that.
114
   */
115
  enum class ResolutionStatus { Completed, Failure };
116

            
117
  /**
118
   * Called when a resolution attempt is complete.
119
   * @param status supplies the final status of the resolution.
120
   * @param details supplies the details for the current address' resolution.
121
   * @param response supplies the list of resolved IP addresses and TTLs.
122
   */
123
  using ResolveCb = std::function<void(ResolutionStatus status, absl::string_view details,
124
                                       std::list<DnsResponse>&& response)>;
125

            
126
  /**
127
   * Initiate an async DNS resolution.
128
   * @param dns_name supplies the DNS name to lookup.
129
   * @param dns_lookup_family the DNS IP version lookup policy.
130
   * @param callback supplies the callback to invoke when the resolution is complete.
131
   * @return if non-null, a handle that can be used to cancel the resolution.
132
   *         This is only valid until the invocation of callback or ~DnsResolver().
133
   */
134
  virtual ActiveDnsQuery* resolve(const std::string& dns_name, DnsLookupFamily dns_lookup_family,
135
                                  ResolveCb callback) PURE;
136

            
137
  /**
138
   * Tell the resolver to reset networking, typically in response to a network switch (e.g., from
139
   * WiFi to cellular). What the resolver does is resolver dependent but might involve creating
140
   * new resolver connections, re-reading resolver targets, etc.
141
   */
142
  virtual void resetNetworking() PURE;
143
};
144

            
145
using DnsResolverSharedPtr = std::shared_ptr<DnsResolver>;
146

            
147
} // namespace Network
148
} // namespace Envoy