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