xref: /aosp_15_r20/external/cronet/net/http/broken_alternative_services.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_HTTP_BROKEN_ALTERNATIVE_SERVICES_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_HTTP_BROKEN_ALTERNATIVE_SERVICES_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <list>
9*6777b538SAndroid Build Coastguard Worker #include <set>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/containers/lru_cache.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/network_anonymization_key.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/http/alternative_service.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace base {
20*6777b538SAndroid Build Coastguard Worker class TickClock;
21*6777b538SAndroid Build Coastguard Worker }
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker namespace net {
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker // Contains information about a broken alternative service, and the context in
26*6777b538SAndroid Build Coastguard Worker // which it's known to be broken.
27*6777b538SAndroid Build Coastguard Worker struct NET_EXPORT_PRIVATE BrokenAlternativeService {
28*6777b538SAndroid Build Coastguard Worker   // If |use_network_anonymization_key| is false, |network_anonymization_key| is
29*6777b538SAndroid Build Coastguard Worker   // ignored, and an empty NetworkAnonymizationKey is used instead.
30*6777b538SAndroid Build Coastguard Worker   BrokenAlternativeService(
31*6777b538SAndroid Build Coastguard Worker       const AlternativeService& alternative_service,
32*6777b538SAndroid Build Coastguard Worker       const NetworkAnonymizationKey& network_anonymization_key,
33*6777b538SAndroid Build Coastguard Worker       bool use_network_anonymization_key);
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker   ~BrokenAlternativeService();
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker   bool operator<(const BrokenAlternativeService& other) const;
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker   AlternativeService alternative_service;
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker   // The context in which the alternative service is known to be broken in. Used
42*6777b538SAndroid Build Coastguard Worker   // to avoid cross-NetworkAnonymizationKey communication.
43*6777b538SAndroid Build Coastguard Worker   NetworkAnonymizationKey network_anonymization_key;
44*6777b538SAndroid Build Coastguard Worker };
45*6777b538SAndroid Build Coastguard Worker 
46*6777b538SAndroid Build Coastguard Worker // Stores broken alternative services and when their brokenness expires.
47*6777b538SAndroid Build Coastguard Worker typedef std::list<std::pair<BrokenAlternativeService, base::TimeTicks>>
48*6777b538SAndroid Build Coastguard Worker     BrokenAlternativeServiceList;
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker // Stores how many times an alternative service has been marked broken.
51*6777b538SAndroid Build Coastguard Worker class RecentlyBrokenAlternativeServices
52*6777b538SAndroid Build Coastguard Worker     : public base::LRUCache<BrokenAlternativeService, int> {
53*6777b538SAndroid Build Coastguard Worker  public:
RecentlyBrokenAlternativeServices(int max_recently_broken_alternative_service_entries)54*6777b538SAndroid Build Coastguard Worker   explicit RecentlyBrokenAlternativeServices(
55*6777b538SAndroid Build Coastguard Worker       int max_recently_broken_alternative_service_entries)
56*6777b538SAndroid Build Coastguard Worker       : base::LRUCache<BrokenAlternativeService, int>(
57*6777b538SAndroid Build Coastguard Worker             max_recently_broken_alternative_service_entries) {}
58*6777b538SAndroid Build Coastguard Worker };
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker // This class tracks HTTP alternative services that have been marked as broken.
61*6777b538SAndroid Build Coastguard Worker // The brokenness of an alt-svc will expire after some time according to an
62*6777b538SAndroid Build Coastguard Worker // exponential back-off formula: each time an alt-svc is marked broken, the
63*6777b538SAndroid Build Coastguard Worker // expiration delay will be some constant multiple of its previous expiration
64*6777b538SAndroid Build Coastguard Worker // delay. This prevents broken alt-svcs from being retried too often by the
65*6777b538SAndroid Build Coastguard Worker // network stack.
66*6777b538SAndroid Build Coastguard Worker //
67*6777b538SAndroid Build Coastguard Worker // Intended solely for use by HttpServerProperties.
68*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE BrokenAlternativeServices {
69*6777b538SAndroid Build Coastguard Worker  public:
70*6777b538SAndroid Build Coastguard Worker   // Delegate to be used by owner so it can be notified when the brokenness of
71*6777b538SAndroid Build Coastguard Worker   // an AlternativeService expires.
72*6777b538SAndroid Build Coastguard Worker   class NET_EXPORT Delegate {
73*6777b538SAndroid Build Coastguard Worker    public:
74*6777b538SAndroid Build Coastguard Worker     // Called when a broken alternative service's expiration time is reached.
75*6777b538SAndroid Build Coastguard Worker     virtual void OnExpireBrokenAlternativeService(
76*6777b538SAndroid Build Coastguard Worker         const AlternativeService& expired_alternative_service,
77*6777b538SAndroid Build Coastguard Worker         const NetworkAnonymizationKey& network_anonymization_key) = 0;
78*6777b538SAndroid Build Coastguard Worker     virtual ~Delegate() = default;
79*6777b538SAndroid Build Coastguard Worker   };
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   // |delegate| will be notified when a broken alternative service expires. It
82*6777b538SAndroid Build Coastguard Worker   // must not be null.
83*6777b538SAndroid Build Coastguard Worker   // |clock| is used for setting expiration times and scheduling the
84*6777b538SAndroid Build Coastguard Worker   // expiration of broken alternative services. It must not be null.
85*6777b538SAndroid Build Coastguard Worker   // |delegate| and |clock| are both unowned and must outlive this.
86*6777b538SAndroid Build Coastguard Worker   BrokenAlternativeServices(int max_recently_broken_alternative_service_entries,
87*6777b538SAndroid Build Coastguard Worker                             Delegate* delegate,
88*6777b538SAndroid Build Coastguard Worker                             const base::TickClock* clock);
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker   BrokenAlternativeServices(const BrokenAlternativeServices&) = delete;
91*6777b538SAndroid Build Coastguard Worker   void operator=(const BrokenAlternativeServices&) = delete;
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   ~BrokenAlternativeServices();
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker   // Clears all broken and recently-broken alternative services (i.e. mark all
96*6777b538SAndroid Build Coastguard Worker   // as not broken nor recently-broken).
97*6777b538SAndroid Build Coastguard Worker   void Clear();
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   // Marks |broken_alternative_service| as broken until an expiration delay
100*6777b538SAndroid Build Coastguard Worker   // (determined by how many consecutive times it's been marked broken before).
101*6777b538SAndroid Build Coastguard Worker   // After the delay, it will be in the recently broken state. However, when the
102*6777b538SAndroid Build Coastguard Worker   // default network changes, the service will immediately be in the working
103*6777b538SAndroid Build Coastguard Worker   // state.
104*6777b538SAndroid Build Coastguard Worker   void MarkBrokenUntilDefaultNetworkChanges(
105*6777b538SAndroid Build Coastguard Worker       const BrokenAlternativeService& broken_alternative_service);
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   // Marks |broken_alternative_service| as broken until an expiration delay
108*6777b538SAndroid Build Coastguard Worker   // (determined by how many consecutive times it's been marked broken before).
109*6777b538SAndroid Build Coastguard Worker   // After the delay, it will be in the recently broken state. When the default
110*6777b538SAndroid Build Coastguard Worker   // network changes, the brokenness state of this service remains unchanged.
111*6777b538SAndroid Build Coastguard Worker   void MarkBroken(const BrokenAlternativeService& broken_alternative_service);
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   // Marks |broken_alternative_service| as recently broken. Being recently
114*6777b538SAndroid Build Coastguard Worker   // broken will cause WasAlternativeServiceRecentlyBroken(alternative_service,
115*6777b538SAndroid Build Coastguard Worker   // network_anonymization_key) to return true until
116*6777b538SAndroid Build Coastguard Worker   // Confirm(alternative_service, network_anonymization_key) is called.
117*6777b538SAndroid Build Coastguard Worker   void MarkRecentlyBroken(
118*6777b538SAndroid Build Coastguard Worker       const BrokenAlternativeService& broken_alternative_service);
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker   // Returns true if the alternative service is considered broken.
121*6777b538SAndroid Build Coastguard Worker   bool IsBroken(
122*6777b538SAndroid Build Coastguard Worker       const BrokenAlternativeService& broken_alternative_service) const;
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   // If the alternative service is considered broken, returns true and sets
125*6777b538SAndroid Build Coastguard Worker   // |brokenness_expiration| to the expiration time for that service.
126*6777b538SAndroid Build Coastguard Worker   // Returns false otherwise.
127*6777b538SAndroid Build Coastguard Worker   bool IsBroken(const BrokenAlternativeService& broken_alternative_service,
128*6777b538SAndroid Build Coastguard Worker                 base::TimeTicks* brokenness_expiration) const;
129*6777b538SAndroid Build Coastguard Worker 
130*6777b538SAndroid Build Coastguard Worker   // Returns true if MarkRecentlyBroken(alternative_service)
131*6777b538SAndroid Build Coastguard Worker   // or MarkBroken(alternative_service) has been called and
132*6777b538SAndroid Build Coastguard Worker   // Confirm(alternative_service) has not been called
133*6777b538SAndroid Build Coastguard Worker   // afterwards (even if brokenness of |alternative_service| has expired).
134*6777b538SAndroid Build Coastguard Worker   bool WasRecentlyBroken(
135*6777b538SAndroid Build Coastguard Worker       const BrokenAlternativeService& broken_alternative_service);
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker   // Changes the alternative service to be considered as working.
138*6777b538SAndroid Build Coastguard Worker   void Confirm(const BrokenAlternativeService& broken_alternative_service);
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker   // Clears all alternative services which were marked as broken until the
141*6777b538SAndroid Build Coastguard Worker   // default network changed, those services will now be considered working.
142*6777b538SAndroid Build Coastguard Worker   // Returns true if there was any broken alternative service affected by this
143*6777b538SAndroid Build Coastguard Worker   // network change.
144*6777b538SAndroid Build Coastguard Worker   bool OnDefaultNetworkChanged();
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   // Sets broken and recently broken alternative services.
147*6777b538SAndroid Build Coastguard Worker   // |broken_alternative_service_list|, |recently_broken_alternative_services|
148*6777b538SAndroid Build Coastguard Worker   // must not be nullptr.
149*6777b538SAndroid Build Coastguard Worker   //
150*6777b538SAndroid Build Coastguard Worker   // If a broken/recently-broken alt svc that's being added is already stored,
151*6777b538SAndroid Build Coastguard Worker   // the stored expiration/broken-count for that alt svc will be overwritten
152*6777b538SAndroid Build Coastguard Worker   // with the new value.
153*6777b538SAndroid Build Coastguard Worker   void SetBrokenAndRecentlyBrokenAlternativeServices(
154*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<BrokenAlternativeServiceList>
155*6777b538SAndroid Build Coastguard Worker           broken_alternative_service_list,
156*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<RecentlyBrokenAlternativeServices>
157*6777b538SAndroid Build Coastguard Worker           recently_broken_alternative_services);
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   // If values are present, sets initial_delay_ and
160*6777b538SAndroid Build Coastguard Worker   // exponential_backoff_on_initial_delay_ which are used to calculate delay of
161*6777b538SAndroid Build Coastguard Worker   // broken alternative services.
162*6777b538SAndroid Build Coastguard Worker   void SetDelayParams(std::optional<base::TimeDelta> initial_delay,
163*6777b538SAndroid Build Coastguard Worker                       std::optional<bool> exponential_backoff_on_initial_delay);
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker   const BrokenAlternativeServiceList& broken_alternative_service_list() const;
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker   const RecentlyBrokenAlternativeServices&
168*6777b538SAndroid Build Coastguard Worker   recently_broken_alternative_services() const;
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker  private:
171*6777b538SAndroid Build Coastguard Worker   // TODO (wangyix): modify HttpServerProperties unit tests so this friendness
172*6777b538SAndroid Build Coastguard Worker   // is no longer required.
173*6777b538SAndroid Build Coastguard Worker   friend class HttpServerPropertiesPeer;
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   struct AlternativeServiceHash {
operatorAlternativeServiceHash176*6777b538SAndroid Build Coastguard Worker     size_t operator()(const net::AlternativeService& entry) const {
177*6777b538SAndroid Build Coastguard Worker       return entry.protocol ^ std::hash<std::string>()(entry.host) ^ entry.port;
178*6777b538SAndroid Build Coastguard Worker     }
179*6777b538SAndroid Build Coastguard Worker   };
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker   typedef std::map<BrokenAlternativeService,
182*6777b538SAndroid Build Coastguard Worker                    BrokenAlternativeServiceList::iterator>
183*6777b538SAndroid Build Coastguard Worker       BrokenMap;
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   // Helper method that marks |broken_alternative_service| as broken until
186*6777b538SAndroid Build Coastguard Worker   // an expiration delay (determined by how many consecutive times it's been
187*6777b538SAndroid Build Coastguard Worker   // marked broken before). After the delay, it will be in the recently broken
188*6777b538SAndroid Build Coastguard Worker   // state.
189*6777b538SAndroid Build Coastguard Worker   void MarkBrokenImpl(
190*6777b538SAndroid Build Coastguard Worker       const BrokenAlternativeService& broken_alternative_service);
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker   // Inserts |broken_alternative_service| and its |expiration| time into
193*6777b538SAndroid Build Coastguard Worker   // |broken_alternative_service_list_| and |broken_alternative_service_map_|.
194*6777b538SAndroid Build Coastguard Worker   // |it| is the position in |broken_alternative_service_list_| where it was
195*6777b538SAndroid Build Coastguard Worker   // inserted.
196*6777b538SAndroid Build Coastguard Worker   bool AddToBrokenListAndMap(
197*6777b538SAndroid Build Coastguard Worker       const BrokenAlternativeService& broken_alternative_service,
198*6777b538SAndroid Build Coastguard Worker       base::TimeTicks expiration,
199*6777b538SAndroid Build Coastguard Worker       BrokenAlternativeServiceList::iterator* it);
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker   void ExpireBrokenAlternateProtocolMappings();
202*6777b538SAndroid Build Coastguard Worker   void ScheduleBrokenAlternateProtocolMappingsExpiration();
203*6777b538SAndroid Build Coastguard Worker 
204*6777b538SAndroid Build Coastguard Worker   raw_ptr<Delegate> delegate_;            // Unowned
205*6777b538SAndroid Build Coastguard Worker   raw_ptr<const base::TickClock> clock_;  // Unowned
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker   // List of <broken alt svc, expiration time> pairs sorted by expiration time.
208*6777b538SAndroid Build Coastguard Worker   BrokenAlternativeServiceList broken_alternative_service_list_;
209*6777b538SAndroid Build Coastguard Worker   // A map from broken alt-svcs to their iterator pointing to that alt-svc's
210*6777b538SAndroid Build Coastguard Worker   // position in |broken_alternative_service_list_|.
211*6777b538SAndroid Build Coastguard Worker   BrokenMap broken_alternative_service_map_;
212*6777b538SAndroid Build Coastguard Worker   // A set of broken alternative services on the current default
213*6777b538SAndroid Build Coastguard Worker   // network. This will be cleared every time the default network changes.
214*6777b538SAndroid Build Coastguard Worker   std::set<BrokenAlternativeService>
215*6777b538SAndroid Build Coastguard Worker       broken_alternative_services_on_default_network_;
216*6777b538SAndroid Build Coastguard Worker 
217*6777b538SAndroid Build Coastguard Worker   // Maps broken alternative services to how many times they've been marked
218*6777b538SAndroid Build Coastguard Worker   // broken.
219*6777b538SAndroid Build Coastguard Worker   RecentlyBrokenAlternativeServices recently_broken_alternative_services_;
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker   // Used for scheduling the task that expires the brokenness of alternative
222*6777b538SAndroid Build Coastguard Worker   // services.
223*6777b538SAndroid Build Coastguard Worker   base::OneShotTimer expiration_timer_;
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker   // Delay for the 1st time alternative service is marked broken.
226*6777b538SAndroid Build Coastguard Worker   base::TimeDelta initial_delay_;
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker   // If true, the delay for broken alternative service =
229*6777b538SAndroid Build Coastguard Worker   // initial_delay_for_broken_alternative_service * (1 << broken_count).
230*6777b538SAndroid Build Coastguard Worker   // Otherwise, the delay would be initial_delay_for_broken_alternative_service,
231*6777b538SAndroid Build Coastguard Worker   // 5min, 10min.. and so on.
232*6777b538SAndroid Build Coastguard Worker   bool exponential_backoff_on_initial_delay_ = true;
233*6777b538SAndroid Build Coastguard Worker 
234*6777b538SAndroid Build Coastguard Worker   base::WeakPtrFactory<BrokenAlternativeServices> weak_ptr_factory_{this};
235*6777b538SAndroid Build Coastguard Worker };
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker }  // namespace net
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker #endif  // NET_HTTP_BROKEN_ALTERNATIVE_SERVICES_H_
240