summaryrefslogtreecommitdiff
path: root/chromium/net/http/http_server_properties.h
blob: 22f0a5db0f555547e93c1d5a33f95c8bf803357a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_HTTP_HTTP_SERVER_PROPERTIES_H_
#define NET_HTTP_HTTP_SERVER_PROPERTIES_H_

#include <stdint.h>

#include <map>
#include <ostream>
#include <string>
#include <tuple>
#include <vector>

#include "base/callback.h"
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_export.h"
#include "net/quic/core/quic_bandwidth.h"
#include "net/quic/core/quic_server_id.h"
#include "net/quic/core/quic_versions.h"
#include "net/socket/next_proto.h"
#include "net/spdy/core/spdy_framer.h"  // TODO(willchan): Reconsider this.
#include "net/spdy/core/spdy_protocol.h"
#include "url/scheme_host_port.h"

namespace base {
class Value;
}

namespace net {

class IPAddress;
struct SSLConfig;

enum AlternateProtocolUsage {
  // Alternate Protocol was used without racing a normal connection.
  ALTERNATE_PROTOCOL_USAGE_NO_RACE = 0,
  // Alternate Protocol was used by winning a race with a normal connection.
  ALTERNATE_PROTOCOL_USAGE_WON_RACE = 1,
  // Alternate Protocol was not used by losing a race with a normal connection.
  ALTERNATE_PROTOCOL_USAGE_LOST_RACE = 2,
  // Alternate Protocol was not used because no Alternate-Protocol information
  // was available when the request was issued, but an Alternate-Protocol header
  // was present in the response.
  ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING = 3,
  // Alternate Protocol was not used because it was marked broken.
  ALTERNATE_PROTOCOL_USAGE_BROKEN = 4,
  // Maximum value for the enum.
  ALTERNATE_PROTOCOL_USAGE_MAX,
};

// Log a histogram to reflect |usage|.
NET_EXPORT void HistogramAlternateProtocolUsage(AlternateProtocolUsage usage,
                                                bool proxy_server_used);

enum BrokenAlternateProtocolLocation {
  BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB = 0,
  BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY = 1,
  BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT = 2,
  BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN = 3,
  BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_HTTP_STREAM = 4,
  BROKEN_ALTERNATE_PROTOCOL_LOCATION_MAX,
};

// Log a histogram to reflect |location|.
NET_EXPORT void HistogramBrokenAlternateProtocolLocation(
    BrokenAlternateProtocolLocation location);

NET_EXPORT bool IsAlternateProtocolValid(NextProto protocol);

// (protocol, host, port) triple as defined in
// https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html
struct NET_EXPORT AlternativeService {
  AlternativeService() : protocol(kProtoUnknown), host(), port(0) {}

  AlternativeService(NextProto protocol, const std::string& host, uint16_t port)
      : protocol(protocol), host(host), port(port) {}

  AlternativeService(NextProto protocol, const HostPortPair& host_port_pair)
      : protocol(protocol),
        host(host_port_pair.host()),
        port(host_port_pair.port()) {}

  AlternativeService(const AlternativeService& alternative_service) = default;
  AlternativeService& operator=(const AlternativeService& alternative_service) =
      default;

  HostPortPair host_port_pair() const { return HostPortPair(host, port); }

  bool operator==(const AlternativeService& other) const {
    return protocol == other.protocol && host == other.host &&
           port == other.port;
  }

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

  bool operator<(const AlternativeService& other) const {
    return std::tie(protocol, host, port) <
           std::tie(other.protocol, other.host, other.port);
  }

  // Output format: "protocol host:port", e.g. "h2 www.google.com:1234".
  std::string ToString() const;

  NextProto protocol;
  std::string host;
  uint16_t port;
};

NET_EXPORT_PRIVATE std::ostream& operator<<(
    std::ostream& os,
    const AlternativeService& alternative_service);

struct AlternativeServiceHash {
  size_t operator()(const net::AlternativeService& entry) const {
    return entry.protocol ^ std::hash<std::string>()(entry.host) ^ entry.port;
  }
};

class NET_EXPORT_PRIVATE AlternativeServiceInfo {
 public:
  static AlternativeServiceInfo CreateHttp2AlternativeServiceInfo(
      const AlternativeService& alternative_service,
      base::Time expiration);

  static AlternativeServiceInfo CreateQuicAlternativeServiceInfo(
      const AlternativeService& alternative_service,
      base::Time expiration,
      const QuicTransportVersionVector& advertised_versions);

  AlternativeServiceInfo();
  ~AlternativeServiceInfo();

  AlternativeServiceInfo(
      const AlternativeServiceInfo& alternative_service_info);

  AlternativeServiceInfo& operator=(
      const AlternativeServiceInfo& alternative_service_info);

  bool operator==(const AlternativeServiceInfo& other) const {
    return alternative_service_ == other.alternative_service() &&
           expiration_ == other.expiration() &&
           advertised_versions_ == other.advertised_versions();
  }

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

  std::string ToString() const;

  void set_alternative_service(const AlternativeService& alternative_service) {
    alternative_service_ = alternative_service;
  }

  void set_protocol(const NextProto& protocol) {
    alternative_service_.protocol = protocol;
  }

  void set_host(const std::string& host) { alternative_service_.host = host; }

  void set_port(uint16_t port) { alternative_service_.port = port; }

  void set_expiration(const base::Time& expiration) {
    expiration_ = expiration;
  }

  void set_advertised_versions(
      const QuicTransportVersionVector& advertised_versions) {
    if (alternative_service_.protocol != kProtoQUIC)
      return;

    advertised_versions_ = advertised_versions;
    std::sort(advertised_versions_.begin(), advertised_versions_.end());
  }

  const AlternativeService& alternative_service() const {
    return alternative_service_;
  }

  NextProto protocol() const { return alternative_service_.protocol; }

  HostPortPair host_port_pair() const {
    return alternative_service_.host_port_pair();
  }

  base::Time expiration() const { return expiration_; }

  const QuicTransportVersionVector& advertised_versions() const {
    return advertised_versions_;
  }

 private:
  AlternativeServiceInfo(const AlternativeService& alternative_service,
                         base::Time expiration,
                         const QuicTransportVersionVector& advertised_versions);

  AlternativeService alternative_service_;
  base::Time expiration_;

  // Lists all the QUIC versions that are advertised by the server and supported
  // by Chrome. If empty, defaults to versions used by the current instance of
  // the netstack.
  // This list MUST be sorted in ascending order.
  QuicTransportVersionVector advertised_versions_;
};

struct NET_EXPORT SupportsQuic {
  SupportsQuic() : used_quic(false) {}
  SupportsQuic(bool used_quic, const std::string& address)
      : used_quic(used_quic),
        address(address) {}

  bool Equals(const SupportsQuic& other) const {
    return used_quic == other.used_quic && address == other.address;
  }

  bool used_quic;
  std::string address;
};

struct NET_EXPORT ServerNetworkStats {
  ServerNetworkStats() : bandwidth_estimate(QuicBandwidth::Zero()) {}

  bool operator==(const ServerNetworkStats& other) const {
    return srtt == other.srtt && bandwidth_estimate == other.bandwidth_estimate;
  }

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

  base::TimeDelta srtt;
  QuicBandwidth bandwidth_estimate;
};

typedef std::vector<AlternativeService> AlternativeServiceVector;
typedef std::vector<AlternativeServiceInfo> AlternativeServiceInfoVector;

// Stores broken alternative services and when their brokenness expires.
typedef std::list<std::pair<AlternativeService, base::TimeTicks>>
    BrokenAlternativeServiceList;

// Store at most 300 MRU SupportsSpdyServerHostPortPairs in memory and disk.
const int kMaxSupportsSpdyServerEntries = 300;

// Store at most 200 MRU AlternateProtocolHostPortPairs in memory and disk.
const int kMaxAlternateProtocolEntries = 200;

// Store at most 200 MRU ServerNetworkStats in memory and disk.
const int kMaxServerNetworkStatsEntries = 200;

// Store at most 200 MRU RecentlyBrokenAlternativeServices in memory and disk.
const int kMaxRecentlyBrokenAlternativeServiceEntries = 200;

// Store at most 5 MRU QUIC servers by default. This is mainly used by cronet.
const int kDefaultMaxQuicServerEntries = 5;

// Stores flattened representation of servers (scheme, host, port) and whether
// or not they support SPDY.
class SpdyServersMap : public base::MRUCache<std::string, bool> {
 public:
  SpdyServersMap()
      : base::MRUCache<std::string, bool>(kMaxSupportsSpdyServerEntries) {}
};

class AlternativeServiceMap
    : public base::MRUCache<url::SchemeHostPort, AlternativeServiceInfoVector> {
 public:
  AlternativeServiceMap()
      : base::MRUCache<url::SchemeHostPort, AlternativeServiceInfoVector>(
            kMaxAlternateProtocolEntries) {}
};

class ServerNetworkStatsMap
    : public base::MRUCache<url::SchemeHostPort, ServerNetworkStats> {
 public:
  ServerNetworkStatsMap()
      : base::MRUCache<url::SchemeHostPort, ServerNetworkStats>(
            kMaxServerNetworkStatsEntries) {}
};

// Stores how many times an alternative service has been marked broken.
class RecentlyBrokenAlternativeServices
    : public base::MRUCache<AlternativeService, int> {
 public:
  RecentlyBrokenAlternativeServices()
      : base::MRUCache<AlternativeService, int>(
            kMaxRecentlyBrokenAlternativeServiceEntries) {}
};

// Max number of quic servers to store is not hardcoded and can be set.
// Because of this, QuicServerInfoMap will not be a subclass of MRUCache.
typedef base::MRUCache<QuicServerId, std::string> QuicServerInfoMap;

extern const char kAlternativeServiceHeader[];

// The interface for setting/retrieving the HTTP server properties.
// Currently, this class manages servers':
// * HTTP/2 support;
// * Alternative Service support;
// * QUIC data (like ServerNetworkStats and QuicServerInfo).
//
// Embedders must ensure that HttpServerProperites is completely initialized
// before the first request is issued.
class NET_EXPORT HttpServerProperties {
 public:
  HttpServerProperties() {}
  virtual ~HttpServerProperties() {}

  // Deletes all data. If |callback| is non-null, flushes data to disk
  // and invokes the callback asynchronously once changes have been written to
  // disk.
  virtual void Clear(base::OnceClosure callback) = 0;

  // Returns true if |server| supports a network protocol which honors
  // request prioritization.
  // Note that this also implies that the server supports request
  // multiplexing, since priorities imply a relationship between
  // multiple requests.
  virtual bool SupportsRequestPriority(const url::SchemeHostPort& server) = 0;

  // Returns the value set by SetSupportsSpdy(). If not set, returns false.
  virtual bool GetSupportsSpdy(const url::SchemeHostPort& server) = 0;

  // Add |server| into the persistent store. Should only be called from IO
  // thread.
  virtual void SetSupportsSpdy(const url::SchemeHostPort& server,
                               bool support_spdy) = 0;

  // Returns true if |server| has required HTTP/1.1 via HTTP/2 error code.
  virtual bool RequiresHTTP11(const HostPortPair& server) = 0;

  // Require HTTP/1.1 on subsequent connections.  Not persisted.
  virtual void SetHTTP11Required(const HostPortPair& server) = 0;

  // Modify SSLConfig to force HTTP/1.1.
  static void ForceHTTP11(SSLConfig* ssl_config);

  // Modify SSLConfig to force HTTP/1.1 if necessary.
  virtual void MaybeForceHTTP11(const HostPortPair& server,
                                SSLConfig* ssl_config) = 0;

  // Return all alternative services for |origin|, including broken ones.
  // Returned alternative services never have empty hostnames.
  virtual AlternativeServiceInfoVector GetAlternativeServiceInfos(
      const url::SchemeHostPort& origin) = 0;

  // Set a single HTTP/2 alternative service for |origin|.  Previous
  // alternative services for |origin| are discarded.
  // |alternative_service.host| may be empty.
  // Return true if |alternative_service_map_| has changed significantly enough
  // that it should be persisted to disk.
  virtual bool SetHttp2AlternativeService(
      const url::SchemeHostPort& origin,
      const AlternativeService& alternative_service,
      base::Time expiration) = 0;

  // Set a single QUIC alternative service for |origin|.  Previous alternative
  // services for |origin| are discarded.
  // |alternative_service.host| may be empty.
  // Return true if |alternative_service_map_| has changed significantly enough
  // that it should be persisted to disk.
  virtual bool SetQuicAlternativeService(
      const url::SchemeHostPort& origin,
      const AlternativeService& alternative_service,
      base::Time expiration,
      const QuicTransportVersionVector& advertised_versions) = 0;

  // Set alternative services for |origin|.  Previous alternative services for
  // |origin| are discarded.
  // Hostnames in |alternative_service_info_vector| may be empty.
  // |alternative_service_info_vector| may be empty.
  // Return true if |alternative_service_map_| has changed significantly enough
  // that it should be persisted to disk.
  virtual bool SetAlternativeServices(
      const url::SchemeHostPort& origin,
      const AlternativeServiceInfoVector& alternative_service_info_vector) = 0;

  // Marks |alternative_service| as broken.
  // |alternative_service.host| must not be empty.
  virtual void MarkAlternativeServiceBroken(
      const AlternativeService& alternative_service) = 0;

  // Marks |alternative_service| as recently broken.
  // |alternative_service.host| must not be empty.
  virtual void MarkAlternativeServiceRecentlyBroken(
      const AlternativeService& alternative_service) = 0;

  // Returns true iff |alternative_service| is currently broken.
  // |alternative_service.host| must not be empty.
  virtual bool IsAlternativeServiceBroken(
      const AlternativeService& alternative_service) const = 0;

  // Returns true iff |alternative_service| was recently broken.
  // |alternative_service.host| must not be empty.
  virtual bool WasAlternativeServiceRecentlyBroken(
      const AlternativeService& alternative_service) = 0;

  // Confirms that |alternative_service| is working.
  // |alternative_service.host| must not be empty.
  virtual void ConfirmAlternativeService(
      const AlternativeService& alternative_service) = 0;

  // Returns all alternative service mappings.
  // Returned alternative services may have empty hostnames.
  virtual const AlternativeServiceMap& alternative_service_map() const = 0;

  // Returns all alternative service mappings as human readable strings.
  // Empty alternative service hostnames will be printed as such.
  virtual std::unique_ptr<base::Value> GetAlternativeServiceInfoAsValue()
      const = 0;

  virtual bool GetSupportsQuic(IPAddress* last_address) const = 0;

  virtual void SetSupportsQuic(bool used_quic,
                               const IPAddress& last_address) = 0;

  // Sets |stats| for |server|.
  virtual void SetServerNetworkStats(const url::SchemeHostPort& server,
                                     ServerNetworkStats stats) = 0;

  // Clears any stats for |server|.
  virtual void ClearServerNetworkStats(const url::SchemeHostPort& server) = 0;

  // Returns any stats for |server| or nullptr if there are none.
  virtual const ServerNetworkStats* GetServerNetworkStats(
      const url::SchemeHostPort& server) = 0;

  virtual const ServerNetworkStatsMap& server_network_stats_map() const = 0;

  // Save QuicServerInfo (in std::string form) for the given |server_id|.
  // Returns true if the value has changed otherwise it returns false.
  virtual bool SetQuicServerInfo(const QuicServerId& server_id,
                                 const std::string& server_info) = 0;

  // Get QuicServerInfo (in std::string form) for the given |server_id|.
  virtual const std::string* GetQuicServerInfo(
      const QuicServerId& server_id) = 0;

  // Returns all persistent QuicServerInfo objects.
  virtual const QuicServerInfoMap& quic_server_info_map() const = 0;

  // Returns the number of server configs (QuicServerInfo objects) persisted.
  virtual size_t max_server_configs_stored_in_properties() const = 0;

  // Sets the number of server configs (QuicServerInfo objects) to be persisted.
  virtual void SetMaxServerConfigsStoredInProperties(
      size_t max_server_configs_stored_in_properties) = 0;

  // Returns whether HttpServerProperties is initialized.
  virtual bool IsInitialized() const = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(HttpServerProperties);
};

}  // namespace net

#endif  // NET_HTTP_HTTP_SERVER_PROPERTIES_H_