summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/Http3Stream.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/protocol/http/Http3Stream.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/netwerk/protocol/http/Http3Stream.h b/netwerk/protocol/http/Http3Stream.h
new file mode 100644
index 0000000000..1048b20ef5
--- /dev/null
+++ b/netwerk/protocol/http/Http3Stream.h
@@ -0,0 +1,165 @@
+/* -*- 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 "Http3StreamBase.h"
+#include "mozilla/WeakPtr.h"
+#include "nsIClassOfService.h"
+
+namespace mozilla {
+namespace net {
+
+class Http3Session;
+
+class Http3Stream final : public nsAHttpSegmentReader,
+ public nsAHttpSegmentWriter,
+ public Http3StreamBase {
+ public:
+ NS_DECL_NSAHTTPSEGMENTREADER
+ NS_DECL_NSAHTTPSEGMENTWRITER
+ // for RefPtr
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Http3Stream, override)
+
+ Http3Stream(nsAHttpTransaction*, Http3Session*, const ClassOfService&,
+ uint64_t);
+
+ Http3WebTransportSession* GetHttp3WebTransportSession() override {
+ return nullptr;
+ }
+ Http3WebTransportStream* GetHttp3WebTransportStream() override {
+ return nullptr;
+ }
+ Http3Stream* GetHttp3Stream() override { return this; }
+
+ nsresult TryActivating();
+
+ void CurrentBrowserIdChanged(uint64_t id);
+
+ [[nodiscard]] nsresult ReadSegments() override;
+ [[nodiscard]] nsresult WriteSegments() override;
+
+ bool Done() const override { return mRecvState == RECV_DONE; }
+
+ void Close(nsresult aResult) override;
+ bool RecvdData() const { return mDataReceived; }
+
+ void StopSending();
+
+ void SetResponseHeaders(nsTArray<uint8_t>& aResponseHeaders, bool fin,
+ bool interim) override;
+
+ // Mirrors nsAHttpTransaction
+ bool Do0RTT() override;
+ nsresult Finish0RTT(bool aRestart) override;
+
+ uint8_t PriorityUrgency();
+ bool PriorityIncremental();
+
+ private:
+ ~Http3Stream() = default;
+
+ bool GetHeadersString(const char* buf, uint32_t avail, uint32_t* countUsed);
+ nsresult StartRequest();
+
+ void SetPriority(uint32_t aCos);
+ void SetIncremental(bool incremental);
+
+ /**
+ * 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{PREPARING_HEADERS};
+
+ /**
+ * RecvStreamState:
+ * - BEFORE_HEADERS:
+ * The stream has not received headers yet.
+ * - READING_HEADERS and READING_INTERIM_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 steam was in the READING_INTERIM_HEADERS state it will
+ * change back to the BEFORE_HEADERS state. If the stream has been
+ * in the READING_HEADERS state it will change to the READING_DATA
+ * state. If the stream was closed by the server after sending headers
+ * the stream will transit into RECEIVED_FIN state. neqo makes sure
+ * that response headers and data are received in the right order,
+ * e.g. 1xx cannot be received after a non-1xx response, fin cannot
+ * follow 1xx response, etc.
+ * - 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_INTERIM_HEADERS,
+ READING_DATA,
+ RECEIVED_FIN,
+ RECV_DONE
+ } mRecvState{BEFORE_HEADERS};
+
+ nsCString mFlatHttpRequestHeaders;
+ bool mDataReceived{false};
+ nsTArray<uint8_t> mFlatResponseHeaders;
+ uint64_t mTransactionBrowserId{0};
+ uint64_t mCurrentBrowserId;
+ uint8_t mPriorityUrgency{3}; // urgency field of http priority
+ bool mPriorityIncremental{false};
+
+ // For Progress Events
+ uint64_t mTotalSent{0};
+ uint64_t mTotalRead{0};
+
+ bool mAttempting0RTT = false;
+
+ uint32_t mSendingBlockedByFlowControlCount = 0;
+
+ nsresult mSocketInCondition = NS_ERROR_NOT_INITIALIZED;
+ nsresult mSocketOutCondition = NS_ERROR_NOT_INITIALIZED;
+
+#ifdef DEBUG
+ uint32_t mRequestBodyLenExpected{0};
+ uint32_t mRequestBodyLenSent{0};
+#endif
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_Http3Stream_h