Skip to content

Commit 11cbf9e

Browse files
hanidamlajmeta-codesync[bot]
authored andcommitted
document WtStreamManager.cpp & WtStreamManager.h
Summary: add some documentation around how things behave (api in .h file) and how things work (implementation details in .cpp) Reviewed By: afrind Differential Revision: D84727476 fbshipit-source-id: d5ea77742c823e89d2747b3f1b493dd7fb62a55c
1 parent 1ba5d00 commit 11cbf9e

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

proxygen/lib/http/coro/util/WtStreamManager.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,63 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9+
/**
10+
* This comment block documents the implementation details of WtStreamManager
11+
* (i.e. the how).
12+
*
13+
* WriteHandle & ReadHandle (concrete implementations of
14+
* WebTransport::WriteHandle and WebTransport::ReadHandle respsectively, defined
15+
* below) are anonymous and strictly scoped to this TU. This requires
16+
* downcasting in all apis that receive a pointer to those pure virtual classes.
17+
* To prevent leaking implementation details by marking methods in
18+
* WtStreamManager public just for internal use by WriteHandle & ReadHandle, we
19+
* utilize a friend struct Accessor (also anonymously defined and strictly
20+
* scoped to this TU).
21+
*
22+
* First thing to note is that we always allocate both a WriteHandle and
23+
* ReadHandle regardless of the underlying properities of the stream (e.g. if
24+
* it's a unidirectional stream). This makes things extremely easier to reason
25+
* about, as there's a single map from [id]->[bidi_handle]. The public api in
26+
* WtStreamManager is extremely restrictive, and we do not hand out a pointer to
27+
* an invalid handle. For example, if a client WtStreamManager attempts to
28+
* retrieve a EgressHandle for a server-initiated unidirectional stream (e.g.
29+
* id=0x03), the state for such a handle exists but we return nullptr – it's
30+
* effectively invisible to the user.
31+
*
32+
* A note about flow control:
33+
* – Ingress flow control is strict, as a peer exceeding the advertised max
34+
* offset is a connection- or stream-level flow control.
35+
*
36+
* – Egress flow control is not strict, as an application can enqueue too much
37+
* data for any number of reasons (large write, ignoring backpressure, etc.).
38+
* We buffer this data in WriteHandle and is subsequently dequeued by the
39+
* transport whenever the stream is writable (hence the need for
40+
* WtEgressContainer to manage this small complexity). Applications should
41+
* respect backpressure signalled by returning FcState::BLOCKED from
42+
* WriteHandle::writeStreamData
43+
*
44+
* A note about stream states:
45+
* – An egress handle transitions from [HandleState::Open] ->
46+
* [HandleState::Closed] in three cases: fin is dequeued from WriteHandle via
47+
* ::dequeue, the application resets the stream (i.e.
48+
* WebTransport::WriteHandle::resetStream), or the transport receives a
49+
* stop_sending and WtStreamManager::onStopSending is invoked.
50+
*
51+
* – An ingress handle transitions from [HandleState::Open] ->
52+
* [HandleState::Closed] in three cases: fin is read via ::readStreamData(),
53+
* the application is no longer interested in ingress (i.e.
54+
* WebTransport::ReadHandle::stopSending), or the transport receives a
55+
* reset_stream and WtStreamManager::onResetStream is invoked.
56+
*
57+
* – An invalid handle (e.g. client egress handle for a
58+
* server-initiated unidirectional stream) starts in the HandleState::Closed.
59+
*
60+
* – Once both the ingress & egress handles have reached the HandleState::Closed
61+
* state, we deallocate the state. Since we always allocate both a ReadHandle
62+
* and WriteHandle, they're both unconditionally linked together for
63+
* simplicity.
64+
*/
65+
966
#include <proxygen/lib/http/coro/util/WtStreamManager.h>
1067

1168
#include <folly/logging/xlog.h>

proxygen/lib/http/coro/util/WtStreamManager.h

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,48 @@
2121
#include <proxygen/lib/http/coro/util/WtEgressContainer.h>
2222
#include <proxygen/lib/http/webtransport/WebTransport.h>
2323

24+
/**
25+
* This comment block documents the api of WtStreamManager (i.e. its behaviour).
26+
* Please refer to the documentation in WtStreamManager.cpp for the
27+
* implementation details (i.e. the how).
28+
*
29+
* WtStreamManager, as the name suggestions, simply manages the stream state of
30+
* WebTransport streams. Following good design philosophy, as much as possible
31+
* is hidden from the user of this class.
32+
*
33+
* There are two channels to interact with this class:
34+
*
35+
* – The application via the handles (StreamWriteHandle & StreamReadHandle) and
36+
* their respective methods (e.g. WriteHandle::writeStreamData,
37+
* ReadHandle::stopSending, etc.).
38+
*
39+
* – The backing transport (http/2, quic, etc.) via the methods in this class
40+
* (e.g. onMaxStreams, onMaxData, ::enqueue(ReadHandle&),
41+
* ::dequeue(WriteHandle&), etc.)
42+
*
43+
* As of now, there's a single channel to communicate events to the backing
44+
* transport –via WtStreamManager::Callback. This simply lets the backing
45+
* transport know that there is an event available for the write loop to action
46+
* on – there are two main events:
47+
*
48+
* – Control frames that need to be serialized/sent by the transport (e.g.
49+
* reset_stream, stop_sending, etc.). The transport should invoke ::moveEvents
50+
* and install a visitor to ensure all control-frames are handled
51+
* appropriately.
52+
*
53+
* – A stream that is now writable (e.g. ::nextWritable will return
54+
* non-nullptr). The transport should query the nextWritable stream and
55+
* dequeue data from the handle.
56+
*
57+
*
58+
* A note about stream handles – everything is dervied from WtDir (the role of
59+
* the endpoint, e.g. client or server) and stream id. Any attempt to
60+
* access/create a handle for an invalid direction will return nullptr. For
61+
* example, a client invoking ::getEgressHandle for a stream id that is
62+
* logically a server-initiated unidirectional stream (e.g. id=0x03) will return
63+
* nullptr.
64+
*/
65+
2466
namespace proxygen::coro::detail {
2567

2668
enum WtDir : uint8_t { Client = 0, Server = 1 };
@@ -30,7 +72,7 @@ constexpr uint64_t kMaxVarint = (1ull << 62) - 1;
3072

3173
struct WtStreamManager {
3274
/**
33-
* This level-triggered callback (::eventsAvailable) is invoked once control
75+
* This edge-triggered callback (::eventsAvailable) is invoked once control
3476
* events are available to be dequeued by the backing transport – (e.g.
3577
* connection- and stream-level flow control, reset_stream, stop_sending,
3678
* etc.)

0 commit comments

Comments
 (0)