1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 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 "nsIClassOfService.h"
namespace mozilla {
namespace net {
class Http3Session;
class Http3Stream : 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; }
Http3ConnectUDPStream* GetHttp3ConnectUDPStream() override { return nullptr; }
Http3StreamTunnel* GetHttp3StreamTunnel() override { return nullptr; }
virtual 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();
protected:
~Http3Stream() = default;
bool GetHeadersString(const char* buf, uint32_t avail, uint32_t* countUsed);
nsresult StartRequest();
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
|