summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/Http3Stream.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/protocol/http/Http3Stream.h158
1 files changed, 158 insertions, 0 deletions
diff --git a/netwerk/protocol/http/Http3Stream.h b/netwerk/protocol/http/Http3Stream.h
new file mode 100644
index 0000000000..8463a3f860
--- /dev/null
+++ b/netwerk/protocol/http/Http3Stream.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_Http3Stream_h
+#define mozilla_net_Http3Stream_h
+
+#include "nsAHttpTransaction.h"
+#include "ARefBase.h"
+#include "mozilla/WeakPtr.h"
+
+namespace mozilla {
+namespace net {
+
+class Http3Session;
+
+class Http3Stream final : public nsAHttpSegmentReader,
+ public nsAHttpSegmentWriter,
+ public SupportsWeakPtr,
+ public ARefBase {
+ public:
+ NS_DECL_NSAHTTPSEGMENTREADER
+ NS_DECL_NSAHTTPSEGMENTWRITER
+ // for RefPtr
+ NS_INLINE_DECL_REFCOUNTING(Http3Stream, override)
+
+ Http3Stream(nsAHttpTransaction* httpTransaction, Http3Session* session);
+
+ bool HasStreamId() const { return mStreamId != UINT64_MAX; }
+ uint64_t StreamId() const { return mStreamId; }
+
+ nsresult TryActivating();
+
+ // TODO priorities
+ void TopLevelOuterContentWindowIdChanged(uint64_t windowId){};
+
+ [[nodiscard]] nsresult ReadSegments(nsAHttpSegmentReader*);
+ [[nodiscard]] nsresult WriteSegments(nsAHttpSegmentWriter*, uint32_t,
+ uint32_t*);
+
+ void SetQueued(bool aStatus) { mQueued = aStatus; }
+ bool Queued() const { return mQueued; }
+
+ bool Done() const { return mRecvState == RECV_DONE; }
+
+ void Close(nsresult aResult);
+ bool RecvdData() const { return mDataReceived; }
+
+ nsAHttpTransaction* Transaction() { return mTransaction; }
+ bool RecvdFin() const { return mFin; }
+ bool RecvdReset() const { return mResetRecv; }
+ void SetRecvdReset() { mResetRecv = true; }
+
+ void StopSending();
+
+ void SetResponseHeaders(nsTArray<uint8_t>& aResponseHeaders, bool fin);
+
+ // Mirrors nsAHttpTransaction
+ bool Do0RTT();
+ nsresult Finish0RTT(bool aRestart);
+
+ private:
+ ~Http3Stream() = default;
+
+ bool GetHeadersString(const char* buf, uint32_t avail, uint32_t* countUsed);
+ nsresult StartRequest();
+ void FindRequestContentLength();
+
+ /**
+ * SendStreamState:
+ * While sending request:
+ * - PREPARING_HEADERS:
+ * In this state we are collecting the headers and in some cases also
+ * waiting to be able to create a new stream.
+ * We need to read all headers into a buffer before calling
+ * Http3Session::TryActivating. Neqo may not have place for a new
+ * stream if it hits MAX_STREAMS limit. In that case the steam will be
+ * queued and dequeue when neqo can again create new stream
+ * (RequestsCreatable will be called).
+ * If transaction has data to send state changes to SENDING_BODY,
+ * otherwise the state transfers to READING_HEADERS.
+ * - SENDING_BODY:
+ * The stream will be in this state while the transaction is sending
+ * request body. Http3Session::SendRequestBody will be call to give
+ * the data to neqo.
+ * After SENDING_BODY, the state transfers to READING_HEADERS.
+ * - EARLY_RESPONSE:
+ * The server may send STOP_SENDING frame with error HTTP_NO_ERROR.
+ * That error means that the server is not interested in the request
+ * body. In this state the server will just ignore the request body.
+ **/
+ enum SendStreamState {
+ PREPARING_HEADERS,
+ WAITING_TO_ACTIVATE,
+ SENDING_BODY,
+ EARLY_RESPONSE,
+ SEND_DONE
+ } mSendState;
+
+ /**
+ * RecvStreamState:
+ * - BEFORE_HEADERS:
+ * The stream has not received headers yet.
+ * - READING_HEADERS:
+ * In this state Http3Session::ReadResponseHeaders will be called to read
+ * the response headers. All headers will be read at once into
+ * mFlatResponseHeaders. The stream will be in this state until all
+ * headers are given to the transaction.
+ * If the stream has been closed by the server after sending headers the
+ * stream will transit into RECEIVED_FIN state, otherwise it transits to
+ * READING_DATA state.
+ * - READING_DATA:
+ * In this state Http3Session::ReadResponseData will be called and the
+ * response body will be given to the transaction.
+ * This state may transfer to RECEIVED_FIN or DONE state.
+ * - DONE:
+ * The transaction is done.
+ **/
+ enum RecvStreamState {
+ BEFORE_HEADERS,
+ READING_HEADERS,
+ READING_DATA,
+ RECEIVED_FIN,
+ RECV_DONE
+ } mRecvState;
+
+ uint64_t mStreamId;
+ Http3Session* mSession;
+ RefPtr<nsAHttpTransaction> mTransaction;
+ nsCString mFlatHttpRequestHeaders;
+ bool mQueued;
+ bool mDataReceived;
+ bool mResetRecv;
+ nsTArray<uint8_t> mFlatResponseHeaders;
+ uint32_t mRequestBodyLenRemaining;
+
+ // The underlying socket transport object is needed to propogate some events
+ RefPtr<nsISocketTransport> mSocketTransport;
+
+ // For Progress Events
+ uint64_t mTotalSent;
+ uint64_t mTotalRead;
+
+ bool mFin;
+
+ bool mAttempting0RTT = false;
+
+ uint32_t mSendingBlockedByFlowControlCount = 0;
+
+ nsresult mSocketInCondition = NS_ERROR_NOT_INITIALIZED;
+ nsresult mSocketOutCondition = NS_ERROR_NOT_INITIALIZED;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_Http3Stream_h