File: broken_alternative_services.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (240 lines) | stat: -rw-r--r-- 10,223 bytes parent folder | download | duplicates (6)
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
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_HTTP_BROKEN_ALTERNATIVE_SERVICES_H_
#define NET_HTTP_BROKEN_ALTERNATIVE_SERVICES_H_

#include <list>
#include <set>

#include "base/containers/lru_cache.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/network_anonymization_key.h"
#include "net/http/alternative_service.h"

namespace base {
class TickClock;
}

namespace net {

// Contains information about a broken alternative service, and the context in
// which it's known to be broken.
struct NET_EXPORT_PRIVATE BrokenAlternativeService {
  // If |use_network_anonymization_key| is false, |network_anonymization_key| is
  // ignored, and an empty NetworkAnonymizationKey is used instead.
  BrokenAlternativeService(
      const AlternativeService& alternative_service,
      const NetworkAnonymizationKey& network_anonymization_key,
      bool use_network_anonymization_key);

  ~BrokenAlternativeService();

  bool operator<(const BrokenAlternativeService& other) const;

  AlternativeService alternative_service;

  // The context in which the alternative service is known to be broken in. Used
  // to avoid cross-NetworkAnonymizationKey communication.
  NetworkAnonymizationKey network_anonymization_key;
};

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

// Stores how many times an alternative service has been marked broken.
class RecentlyBrokenAlternativeServices
    : public base::LRUCache<BrokenAlternativeService, int> {
 public:
  explicit RecentlyBrokenAlternativeServices(
      int max_recently_broken_alternative_service_entries)
      : base::LRUCache<BrokenAlternativeService, int>(
            max_recently_broken_alternative_service_entries) {}
};

// This class tracks HTTP alternative services that have been marked as broken.
// The brokenness of an alt-svc will expire after some time according to an
// exponential back-off formula: each time an alt-svc is marked broken, the
// expiration delay will be some constant multiple of its previous expiration
// delay. This prevents broken alt-svcs from being retried too often by the
// network stack.
//
// Intended solely for use by HttpServerProperties.
class NET_EXPORT_PRIVATE BrokenAlternativeServices {
 public:
  // Delegate to be used by owner so it can be notified when the brokenness of
  // an AlternativeService expires.
  class NET_EXPORT Delegate {
   public:
    // Called when a broken alternative service's expiration time is reached.
    virtual void OnExpireBrokenAlternativeService(
        const AlternativeService& expired_alternative_service,
        const NetworkAnonymizationKey& network_anonymization_key) = 0;
    virtual ~Delegate() = default;
  };

  // |delegate| will be notified when a broken alternative service expires. It
  // must not be null.
  // |clock| is used for setting expiration times and scheduling the
  // expiration of broken alternative services. It must not be null.
  // |delegate| and |clock| are both unowned and must outlive this.
  BrokenAlternativeServices(int max_recently_broken_alternative_service_entries,
                            Delegate* delegate,
                            const base::TickClock* clock);

  BrokenAlternativeServices(const BrokenAlternativeServices&) = delete;
  void operator=(const BrokenAlternativeServices&) = delete;

  ~BrokenAlternativeServices();

  // Clears all broken and recently-broken alternative services (i.e. mark all
  // as not broken nor recently-broken).
  void Clear();

  // Marks |broken_alternative_service| as broken until an expiration delay
  // (determined by how many consecutive times it's been marked broken before).
  // After the delay, it will be in the recently broken state. However, when the
  // default network changes, the service will immediately be in the working
  // state.
  void MarkBrokenUntilDefaultNetworkChanges(
      const BrokenAlternativeService& broken_alternative_service);

  // Marks |broken_alternative_service| as broken until an expiration delay
  // (determined by how many consecutive times it's been marked broken before).
  // After the delay, it will be in the recently broken state. When the default
  // network changes, the brokenness state of this service remains unchanged.
  void MarkBroken(const BrokenAlternativeService& broken_alternative_service);

  // Marks |broken_alternative_service| as recently broken. Being recently
  // broken will cause WasAlternativeServiceRecentlyBroken(alternative_service,
  // network_anonymization_key) to return true until
  // Confirm(alternative_service, network_anonymization_key) is called.
  void MarkRecentlyBroken(
      const BrokenAlternativeService& broken_alternative_service);

  // Returns true if the alternative service is considered broken.
  bool IsBroken(
      const BrokenAlternativeService& broken_alternative_service) const;

  // If the alternative service is considered broken, returns true and sets
  // |brokenness_expiration| to the expiration time for that service.
  // Returns false otherwise.
  bool IsBroken(const BrokenAlternativeService& broken_alternative_service,
                base::TimeTicks* brokenness_expiration) const;

  // Returns true if MarkRecentlyBroken(alternative_service)
  // or MarkBroken(alternative_service) has been called and
  // Confirm(alternative_service) has not been called
  // afterwards (even if brokenness of |alternative_service| has expired).
  bool WasRecentlyBroken(
      const BrokenAlternativeService& broken_alternative_service);

  // Changes the alternative service to be considered as working.
  void Confirm(const BrokenAlternativeService& broken_alternative_service);

  // Clears all alternative services which were marked as broken until the
  // default network changed, those services will now be considered working.
  // Returns true if there was any broken alternative service affected by this
  // network change.
  bool OnDefaultNetworkChanged();

  // Sets broken and recently broken alternative services.
  // |broken_alternative_service_list|, |recently_broken_alternative_services|
  // must not be nullptr.
  //
  // If a broken/recently-broken alt svc that's being added is already stored,
  // the stored expiration/broken-count for that alt svc will be overwritten
  // with the new value.
  void SetBrokenAndRecentlyBrokenAlternativeServices(
      std::unique_ptr<BrokenAlternativeServiceList>
          broken_alternative_service_list,
      std::unique_ptr<RecentlyBrokenAlternativeServices>
          recently_broken_alternative_services);

  // If values are present, sets initial_delay_ and
  // exponential_backoff_on_initial_delay_ which are used to calculate delay of
  // broken alternative services.
  void SetDelayParams(std::optional<base::TimeDelta> initial_delay,
                      std::optional<bool> exponential_backoff_on_initial_delay);

  const BrokenAlternativeServiceList& broken_alternative_service_list() const;

  const RecentlyBrokenAlternativeServices&
  recently_broken_alternative_services() const;

 private:
  // TODO (wangyix): modify HttpServerProperties unit tests so this friendness
  // is no longer required.
  friend class HttpServerPropertiesPeer;

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

  typedef std::map<BrokenAlternativeService,
                   BrokenAlternativeServiceList::iterator>
      BrokenMap;

  // Helper method that marks |broken_alternative_service| as broken until
  // an expiration delay (determined by how many consecutive times it's been
  // marked broken before). After the delay, it will be in the recently broken
  // state.
  void MarkBrokenImpl(
      const BrokenAlternativeService& broken_alternative_service);

  // Inserts |broken_alternative_service| and its |expiration| time into
  // |broken_alternative_service_list_| and |broken_alternative_service_map_|.
  // |it| is the position in |broken_alternative_service_list_| where it was
  // inserted.
  bool AddToBrokenListAndMap(
      const BrokenAlternativeService& broken_alternative_service,
      base::TimeTicks expiration,
      BrokenAlternativeServiceList::iterator* it);

  void ExpireBrokenAlternateProtocolMappings();
  void ScheduleBrokenAlternateProtocolMappingsExpiration();

  raw_ptr<Delegate> delegate_;            // Unowned
  raw_ptr<const base::TickClock> clock_;  // Unowned

  // List of <broken alt svc, expiration time> pairs sorted by expiration time.
  BrokenAlternativeServiceList broken_alternative_service_list_;
  // A map from broken alt-svcs to their iterator pointing to that alt-svc's
  // position in |broken_alternative_service_list_|.
  BrokenMap broken_alternative_service_map_;
  // A set of broken alternative services on the current default
  // network. This will be cleared every time the default network changes.
  std::set<BrokenAlternativeService>
      broken_alternative_services_on_default_network_;

  // Maps broken alternative services to how many times they've been marked
  // broken.
  RecentlyBrokenAlternativeServices recently_broken_alternative_services_;

  // Used for scheduling the task that expires the brokenness of alternative
  // services.
  base::OneShotTimer expiration_timer_;

  // Delay for the 1st time alternative service is marked broken.
  base::TimeDelta initial_delay_;

  // If true, the delay for broken alternative service =
  // initial_delay_for_broken_alternative_service * (1 << broken_count).
  // Otherwise, the delay would be initial_delay_for_broken_alternative_service,
  // 5min, 10min.. and so on.
  bool exponential_backoff_on_initial_delay_ = true;

  base::WeakPtrFactory<BrokenAlternativeServices> weak_ptr_factory_{this};
};

}  // namespace net

#endif  // NET_HTTP_BROKEN_ALTERNATIVE_SERVICES_H_