| #ifndef QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_ |
| #define QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <functional> |
| |
| #include "quiche/common/platform/api/quiche_export.h" |
| #include "quiche/common/quiche_callbacks.h" |
| |
| namespace http2 { |
| namespace adapter { |
| |
| namespace test { |
| class WindowManagerPeer; |
| } |
| |
| // This class keeps track of a HTTP/2 flow control window, notifying a listener |
| // when a window update needs to be sent. This class is not thread-safe. |
| class QUICHE_EXPORT WindowManager { |
| public: |
| // A WindowUpdateListener is invoked when it is time to send a window update. |
| using WindowUpdateListener = quiche::MultiUseCallback<void(int64_t)>; |
| |
| // Invoked to determine whether to call the listener based on the window |
| // limit, window size, and delta that would be sent. |
| using ShouldWindowUpdateFn = bool (*)(int64_t limit, int64_t size, |
| int64_t delta); |
| |
| WindowManager(int64_t window_size_limit, WindowUpdateListener listener, |
| ShouldWindowUpdateFn should_window_update_fn = {}, |
| bool update_window_on_notify = true); |
| |
| int64_t CurrentWindowSize() const { return window_; } |
| int64_t WindowSizeLimit() const { return limit_; } |
| |
| // Called when the window size limit is changed (typically via settings) but |
| // no window update should be sent. |
| void OnWindowSizeLimitChange(int64_t new_limit); |
| |
| // Sets the window size limit to |new_limit| and notifies the listener to |
| // update as necessary. |
| void SetWindowSizeLimit(int64_t new_limit); |
| |
| // Increments the running total of data bytes buffered. Returns true iff there |
| // is more window remaining. |
| bool MarkDataBuffered(int64_t bytes); |
| |
| // Increments the running total of data bytes that have been flushed or |
| // dropped. Invokes the listener if the current window is smaller than some |
| // threshold and there is quota available to send. |
| void MarkDataFlushed(int64_t bytes); |
| |
| // Convenience method, used when incoming data is immediately dropped or |
| // ignored. |
| void MarkWindowConsumed(int64_t bytes) { |
| MarkDataBuffered(bytes); |
| MarkDataFlushed(bytes); |
| } |
| |
| // Increments the window size without affecting the limit. Useful if this end |
| // of a stream or connection issues a one-time WINDOW_UPDATE. |
| void IncreaseWindow(int64_t delta) { window_ += delta; } |
| |
| private: |
| friend class test::WindowManagerPeer; |
| |
| void MaybeNotifyListener(); |
| |
| // The upper bound on the flow control window. The GFE attempts to maintain a |
| // window of this size at the peer as data is proxied through. |
| int64_t limit_; |
| |
| // The current flow control window that has not been advertised to the peer |
| // and not yet consumed. The peer can send this many bytes before becoming |
| // blocked. |
| int64_t window_; |
| |
| // The amount of data already buffered, which should count against the flow |
| // control window upper bound. |
| int64_t buffered_; |
| |
| WindowUpdateListener listener_; |
| |
| ShouldWindowUpdateFn should_window_update_fn_; |
| |
| bool update_window_on_notify_; |
| }; |
| |
| } // namespace adapter |
| } // namespace http2 |
| |
| #endif // QUICHE_HTTP2_ADAPTER_WINDOW_MANAGER_H_ |