1
#pragma once
2

            
3
#include <map>
4
#include <memory>
5
#include <string>
6
#include <tuple>
7
#include <vector>
8

            
9
#include "envoy/common/optref.h"
10
#include "envoy/common/time.h"
11
#include "envoy/config/core/v3/protocol.pb.h"
12
#include "envoy/event/dispatcher.h"
13

            
14
#include "absl/strings/string_view.h"
15

            
16
namespace Envoy {
17
namespace Http {
18

            
19
/**
20
 * Tracks information used to make an HTTP connection to an origin server.
21
 *
22
 * This includes Alternate protocols, SRTT, Quic brokenness, etc.
23
 *
24
 * See https://tools.ietf.org/html/rfc7838 for HTTP Alternative Services and
25
 * https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-04 for the
26
 * "HTTPS" DNS resource record.
27
 */
28
class HttpServerPropertiesCache {
29
public:
30
  /**
31
   * Represents an HTTP origin to be connected too.
32
   */
33
  struct Origin {
34
  public:
35
23
    Origin() = default;
36
1991
    Origin(const Origin& other) = default;
37
    Origin(absl::string_view scheme, absl::string_view hostname, uint32_t port)
38
1603
        : scheme_(scheme), hostname_(hostname), port_(port) {}
39
27
    Origin& operator=(const Origin&) = default;
40

            
41
1131
    bool operator==(const Origin& other) const {
42
1131
      return std::tie(scheme_, hostname_, port_) ==
43
1131
             std::tie(other.scheme_, other.hostname_, other.port_);
44
1131
    }
45

            
46
    bool operator!=(const Origin& other) const { return !this->operator==(other); }
47

            
48
    bool operator<(const Origin& other) const {
49
      return std::tie(scheme_, hostname_, port_) <
50
             std::tie(other.scheme_, other.hostname_, other.port_);
51
    }
52

            
53
    bool operator>(const Origin& other) const {
54
      return std::tie(scheme_, hostname_, port_) >
55
             std::tie(other.scheme_, other.hostname_, other.port_);
56
    }
57

            
58
    bool operator<=(const Origin& other) const {
59
      return std::tie(scheme_, hostname_, port_) <=
60
             std::tie(other.scheme_, other.hostname_, other.port_);
61
    }
62

            
63
    bool operator>=(const Origin& other) const {
64
      return std::tie(scheme_, hostname_, port_) >=
65
             std::tie(other.scheme_, other.hostname_, other.port_);
66
    }
67

            
68
    std::string scheme_;
69
    std::string hostname_;
70
    uint32_t port_{};
71
  };
72

            
73
  /**
74
   * Represents an alternative protocol that can be used to connect to an origin
75
   * with a specified expiration time.
76
   */
77
  struct AlternateProtocol {
78
  public:
79
    AlternateProtocol(absl::string_view alpn, absl::string_view hostname, uint32_t port,
80
                      MonotonicTime expiration)
81
225
        : alpn_(alpn), hostname_(hostname), port_(port), expiration_(expiration) {}
82

            
83
45
    bool operator==(const AlternateProtocol& other) const {
84
45
      return std::tie(alpn_, hostname_, port_, expiration_) ==
85
45
             std::tie(other.alpn_, other.hostname_, other.port_, other.expiration_);
86
45
    }
87

            
88
    bool operator!=(const AlternateProtocol& other) const { return !this->operator==(other); }
89

            
90
    std::string alpn_;
91
    std::string hostname_;
92
    uint32_t port_;
93
    MonotonicTime expiration_;
94
  };
95

            
96
  class Http3StatusTracker {
97
  public:
98
96
    virtual ~Http3StatusTracker() = default;
99

            
100
    // Returns true if HTTP/3 status is pending.
101
    virtual bool isHttp3Pending() const PURE;
102
    // Returns true if HTTP/3 is broken.
103
    virtual bool isHttp3Broken() const PURE;
104
    // Returns true if HTTP/3 is confirmed to be working.
105
    virtual bool isHttp3Confirmed() const PURE;
106
    // Returns true if HTTP/3 has failed recently.
107
    virtual bool hasHttp3FailedRecently() const PURE;
108
    // Marks HTTP/3 status as pending.
109
    virtual void markHttp3Pending() PURE;
110
    // Marks HTTP/3 broken for a period of time, subject to backoff.
111
    virtual void markHttp3Broken() PURE;
112
    // Marks HTTP/3 as confirmed to be working and resets the backoff timeout.
113
    virtual void markHttp3Confirmed() PURE;
114
    // Marks HTTP/3 as failed recently.
115
    virtual void markHttp3FailedRecently() PURE;
116
  };
117

            
118
5379
  virtual ~HttpServerPropertiesCache() = default;
119

            
120
  /**
121
   * Sets the possible alternative protocols which can be used to connect to the
122
   * specified origin. Expires after the specified expiration time.
123
   * @param origin The origin to set alternate protocols for.
124
   * @param protocols A list of alternate protocols. This list may be truncated
125
   * by the cache.
126
   */
127
  virtual void setAlternatives(const Origin& origin,
128
                               std::vector<AlternateProtocol>& protocols) PURE;
129

            
130
  /**
131
   * Sets the srtt estimate for an origin.
132
   * @param origin The origin to set network characteristics for.
133
   * @param srtt The smothed round trip time for the origin.
134
   */
135
  virtual void setSrtt(const Origin& origin, std::chrono::microseconds srtt) PURE;
136

            
137
  /**
138
   * Returns the srtt estimate for an origin, or zero, if no srtt is cached.
139
   * @param origin The origin to get network characteristics for.
140
   * @param use_canonical_suffix Whether to use canonical suffix for SRTT lookup.
141
   */
142
  virtual std::chrono::microseconds getSrtt(const Origin& origin,
143
                                            bool use_canonical_suffix) const PURE;
144

            
145
  /**
146
   * Sets the number of concurrent streams allowed by the last connection to this origin.
147
   * @param origin The origin to set network characteristics for.
148
   * @param srtt The number of concurrent streams allowed.
149
   */
150
  virtual void setConcurrentStreams(const Origin& origin, uint32_t concurrent_streams) PURE;
151

            
152
  /**
153
   * Returns the number of concurrent streams allowed by the last connection to this origin,
154
   * or zero if no limit was set.
155
   * Note that different servers serving a given origin may have different
156
   * characteristics, so this is a best guess estimate not a guarantee.
157
   * @param origin The origin to get network characteristics for.
158
   */
159
  virtual uint32_t getConcurrentStreams(const Origin& origin) const PURE;
160

            
161
  /**
162
   * Returns the possible alternative protocols which can be used to connect to the
163
   * specified origin, or nullptr if not alternatives are found. The returned reference
164
   * is owned by the HttpServerPropertiesCache and is valid until the next operation on the
165
   * HttpServerPropertiesCache.
166
   * @param origin The origin to find alternate protocols for.
167
   * @return An optional list of alternate protocols for the given origin.
168
   */
169
  virtual OptRef<const std::vector<AlternateProtocol>> findAlternatives(const Origin& origin) PURE;
170

            
171
  /**
172
   * Returns the number of entries in the map.
173
   * @return the number if entries in the map.
174
   */
175
  virtual size_t size() const PURE;
176

            
177
  /**
178
   * @param origin The origin to get HTTP/3 status tracker for.
179
   * @return the existing status tracker or creating a new one if there is none.
180
   */
181
  virtual HttpServerPropertiesCache::Http3StatusTracker&
182
  getOrCreateHttp3StatusTracker(const Origin& origin) PURE;
183

            
184
  /**
185
   * @param origin The origin to check h3 brokenness for.
186
   * @return true if it's broken.
187
   */
188
  virtual bool isHttp3Broken(const Origin& origin) PURE;
189

            
190
  /**
191
   * @ origin The origin to mark h3 broken.
192
   */
193
  virtual void markHttp3Broken(const Origin& origin) PURE;
194

            
195
  /**
196
   * Changes any origins with status "Broken" for HTTP/3 to "Failed Recently"
197
   */
198
  virtual void resetBrokenness() PURE;
199

            
200
  /**
201
   * Changes any origin status for HTTP/3 to "Pending".
202
   */
203
  virtual void resetStatus() PURE;
204
};
205

            
206
using HttpServerPropertiesCacheSharedPtr = std::shared_ptr<HttpServerPropertiesCache>;
207
using Http3StatusTrackerPtr = std::unique_ptr<HttpServerPropertiesCache::Http3StatusTracker>;
208

            
209
/**
210
 * A manager for multiple alternate protocols caches.
211
 */
212
class HttpServerPropertiesCacheManager {
213
public:
214
50692
  virtual ~HttpServerPropertiesCacheManager() = default;
215

            
216
  /**
217
   * Get an alternate protocols cache.
218
   * @param config supplies the cache parameters. If a cache exists with the same parameters it
219
   *               will be returned, otherwise a new one will be created.
220
   * @param dispatcher supplies the current thread's dispatcher, for cache creation.
221
   */
222
  virtual HttpServerPropertiesCacheSharedPtr
223
  getCache(const envoy::config::core::v3::AlternateProtocolsCacheOptions& config,
224
           Event::Dispatcher& dispatcher) PURE;
225

            
226
  using CacheFn = std::function<void(HttpServerPropertiesCache&)>;
227

            
228
  /**
229
   * Run the supplied function on each HttpServerPropertiesCache on this thread.
230
   * @param cache_fn supplies the function to run.
231
   */
232
  virtual void forEachThreadLocalCache(CacheFn cache_fn) PURE;
233
};
234

            
235
using HttpServerPropertiesCacheManagerSharedPtr = std::shared_ptr<HttpServerPropertiesCacheManager>;
236

            
237
} // namespace Http
238
} // namespace Envoy