xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/adapter/window_manager.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 #ifndef QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_
2 #define QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_
3 
4 #include <stddef.h>
5 #include <stdint.h>
6 
7 #include <functional>
8 
9 #include "quiche/common/platform/api/quiche_export.h"
10 #include "quiche/common/quiche_callbacks.h"
11 
12 namespace http2 {
13 namespace adapter {
14 
15 namespace test {
16 class WindowManagerPeer;
17 }
18 
19 // This class keeps track of a HTTP/2 flow control window, notifying a listener
20 // when a window update needs to be sent. This class is not thread-safe.
21 class QUICHE_EXPORT WindowManager {
22  public:
23   // A WindowUpdateListener is invoked when it is time to send a window update.
24   using WindowUpdateListener = quiche::MultiUseCallback<void(int64_t)>;
25 
26   // Invoked to determine whether to call the listener based on the window
27   // limit, window size, and delta that would be sent.
28   using ShouldWindowUpdateFn = bool (*)(int64_t limit, int64_t size,
29                                         int64_t delta);
30 
31   WindowManager(int64_t window_size_limit, WindowUpdateListener listener,
32                 ShouldWindowUpdateFn should_window_update_fn = {},
33                 bool update_window_on_notify = true);
34 
CurrentWindowSize()35   int64_t CurrentWindowSize() const { return window_; }
WindowSizeLimit()36   int64_t WindowSizeLimit() const { return limit_; }
37 
38   // Called when the window size limit is changed (typically via settings) but
39   // no window update should be sent.
40   void OnWindowSizeLimitChange(int64_t new_limit);
41 
42   // Sets the window size limit to |new_limit| and notifies the listener to
43   // update as necessary.
44   void SetWindowSizeLimit(int64_t new_limit);
45 
46   // Increments the running total of data bytes buffered. Returns true iff there
47   // is more window remaining.
48   bool MarkDataBuffered(int64_t bytes);
49 
50   // Increments the running total of data bytes that have been flushed or
51   // dropped. Invokes the listener if the current window is smaller than some
52   // threshold and there is quota available to send.
53   void MarkDataFlushed(int64_t bytes);
54 
55   // Convenience method, used when incoming data is immediately dropped or
56   // ignored.
MarkWindowConsumed(int64_t bytes)57   void MarkWindowConsumed(int64_t bytes) {
58     MarkDataBuffered(bytes);
59     MarkDataFlushed(bytes);
60   }
61 
62   // Increments the window size without affecting the limit. Useful if this end
63   // of a stream or connection issues a one-time WINDOW_UPDATE.
IncreaseWindow(int64_t delta)64   void IncreaseWindow(int64_t delta) { window_ += delta; }
65 
66  private:
67   friend class test::WindowManagerPeer;
68 
69   void MaybeNotifyListener();
70 
71   // The upper bound on the flow control window. The GFE attempts to maintain a
72   // window of this size at the peer as data is proxied through.
73   int64_t limit_;
74 
75   // The current flow control window that has not been advertised to the peer
76   // and not yet consumed. The peer can send this many bytes before becoming
77   // blocked.
78   int64_t window_;
79 
80   // The amount of data already buffered, which should count against the flow
81   // control window upper bound.
82   int64_t buffered_;
83 
84   WindowUpdateListener listener_;
85 
86   ShouldWindowUpdateFn should_window_update_fn_;
87 
88   bool update_window_on_notify_;
89 };
90 
91 }  // namespace adapter
92 }  // namespace http2
93 
94 #endif  // QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_
95