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