Bug 1909986 - For sidebar revamp, only show chatbot entrypoints (context menu, shortc...
[gecko.git] / netwerk / protocol / http / Http2StreamBase.h
blobae0b8c1a78638fdd884cb21b4d5725a8ba59c4f3
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_net_Http2StreamBase_h
7 #define mozilla_net_Http2StreamBase_h
9 // HTTP/2 - RFC7540
10 // https://www.rfc-editor.org/rfc/rfc7540.txt
12 #include "mozilla/Attributes.h"
13 #include "mozilla/UniquePtr.h"
14 #include "mozilla/WeakPtr.h"
15 #include "nsAHttpTransaction.h"
16 #include "nsISupportsPriority.h"
17 #include "SimpleBuffer.h"
18 #include "nsISupportsImpl.h"
19 #include "nsIURI.h"
21 class nsISocketTransport;
22 class nsIInputStream;
23 class nsIOutputStream;
25 namespace mozilla {
26 class OriginAttributes;
29 namespace mozilla::net {
31 class nsStandardURL;
32 class Http2Session;
33 class Http2Stream;
34 class Http2PushedStream;
35 class Http2Decompressor;
37 class Http2StreamBase : public nsAHttpSegmentReader,
38 public nsAHttpSegmentWriter,
39 public SupportsWeakPtr {
40 public:
41 NS_DECL_NSAHTTPSEGMENTREADER
43 enum stateType {
44 IDLE,
45 RESERVED_BY_REMOTE,
46 OPEN,
47 CLOSED_BY_LOCAL,
48 CLOSED_BY_REMOTE,
49 CLOSED
52 const static int32_t kNormalPriority = 0x1000;
53 const static int32_t kWorstPriority =
54 kNormalPriority + nsISupportsPriority::PRIORITY_LOWEST;
55 const static int32_t kBestPriority =
56 kNormalPriority + nsISupportsPriority::PRIORITY_HIGHEST;
58 Http2StreamBase(uint64_t, Http2Session*, int32_t, uint64_t);
60 uint32_t StreamID() { return mStreamID; }
62 stateType HTTPState() { return mState; }
63 void SetHTTPState(stateType val) { mState = val; }
65 [[nodiscard]] virtual nsresult ReadSegments(nsAHttpSegmentReader*, uint32_t,
66 uint32_t*);
67 [[nodiscard]] virtual nsresult WriteSegments(nsAHttpSegmentWriter*, uint32_t,
68 uint32_t*);
69 virtual bool DeferCleanup(nsresult status);
71 const nsCString& Origin() const { return mOrigin; }
72 const nsCString& Host() const { return mHeaderHost; }
73 const nsCString& Path() const { return mHeaderPath; }
75 bool RequestBlockedOnRead() {
76 return static_cast<bool>(mRequestBlockedOnRead);
79 bool HasRegisteredID() { return mStreamID != 0; }
81 virtual nsAHttpTransaction* Transaction() { return nullptr; }
82 nsHttpTransaction* HttpTransaction();
83 virtual nsIRequestContext* RequestContext() { return nullptr; }
85 virtual void CloseStream(nsresult reason) = 0;
86 void SetResponseIsComplete();
88 void SetRecvdFin(bool aStatus);
89 bool RecvdFin() { return mRecvdFin; }
91 void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; }
92 bool RecvdData() { return mReceivedData; }
94 void SetSentFin(bool aStatus);
95 bool SentFin() { return mSentFin; }
97 void SetRecvdReset(bool aStatus);
98 bool RecvdReset() { return mRecvdReset; }
100 void SetSentReset(bool aStatus);
101 bool SentReset() { return mSentReset; }
103 void SetQueued(bool aStatus) { mQueued = aStatus ? 1 : 0; }
104 bool Queued() { return mQueued; }
106 void SetCountAsActive(bool aStatus) { mCountAsActive = aStatus ? 1 : 0; }
107 bool CountAsActive() { return mCountAsActive; }
109 void SetAllHeadersReceived();
110 void UnsetAllHeadersReceived() { mAllHeadersReceived = 0; }
111 bool AllHeadersReceived() { return mAllHeadersReceived; }
113 void UpdateTransportSendEvents(uint32_t count);
114 void UpdateTransportReadEvents(uint32_t count);
116 // NS_ERROR_ABORT terminates stream, other failure terminates session
117 [[nodiscard]] nsresult ConvertResponseHeaders(Http2Decompressor*, nsACString&,
118 nsACString&, int32_t&);
119 [[nodiscard]] nsresult ConvertResponseTrailers(Http2Decompressor*,
120 nsACString&);
122 bool AllowFlowControlledWrite();
123 void UpdateServerReceiveWindow(int32_t delta);
124 int64_t ServerReceiveWindow() { return mServerReceiveWindow; }
126 void DecrementClientReceiveWindow(uint32_t delta) {
127 mClientReceiveWindow -= delta;
128 mLocalUnacked += delta;
131 void IncrementClientReceiveWindow(uint32_t delta) {
132 mClientReceiveWindow += delta;
133 mLocalUnacked -= delta;
136 uint64_t LocalUnAcked();
137 int64_t ClientReceiveWindow() { return mClientReceiveWindow; }
139 bool BlockedOnRwin() { return mBlockedOnRwin; }
141 uint32_t RFC7540Priority() { return mRFC7540Priority; }
142 uint32_t PriorityDependency() { return mPriorityDependency; }
143 uint8_t PriorityWeight() { return mPriorityWeight; }
144 void SetPriority(uint32_t);
145 void SetPriorityDependency(uint32_t, uint32_t);
146 void UpdatePriorityDependency();
148 uint64_t TransactionBrowserId() { return mTransactionBrowserId; }
150 // A pull stream has an implicit sink, a pushed stream has a sink
151 // once it is matched to a pull stream.
152 virtual bool HasSink() { return true; }
154 already_AddRefed<Http2Session> Session();
156 // Mirrors nsAHttpTransaction
157 bool Do0RTT();
158 nsresult Finish0RTT(bool aRestart, bool aAlpnChanged);
160 nsresult GetOriginAttributes(mozilla::OriginAttributes* oa);
162 virtual void CurrentBrowserIdChanged(uint64_t id);
163 // For use by pushed streams only
164 void CurrentBrowserIdChangedInternal(uint64_t id);
166 virtual void UpdatePriorityRFC7540(Http2Session* session);
167 virtual void UpdatePriority(Http2Session* session);
169 virtual bool IsTunnel() { return false; }
171 virtual uint32_t GetWireStreamId() { return mStreamID; }
172 virtual Http2Stream* GetHttp2Stream() { return nullptr; }
173 virtual Http2PushedStream* GetHttp2PushedStream() { return nullptr; }
175 [[nodiscard]] virtual nsresult OnWriteSegment(char*, uint32_t,
176 uint32_t*) override;
178 virtual nsHttpConnectionInfo* ConnectionInfo();
180 bool DataBuffered() { return mSimpleBuffer.Available(); }
182 virtual nsresult Condition() { return NS_OK; }
184 virtual void DisableSpdy() {
185 if (Transaction()) {
186 Transaction()->DisableSpdy();
189 virtual void ReuseConnectionOnRestartOK(bool aReuse) {
190 if (Transaction()) {
191 Transaction()->ReuseConnectionOnRestartOK(aReuse);
194 virtual void MakeNonSticky() {
195 if (Transaction()) {
196 Transaction()->MakeNonSticky();
200 protected:
201 virtual ~Http2StreamBase();
203 virtual void HandleResponseHeaders(nsACString& aHeadersOut,
204 int32_t httpResponseCode) {}
205 virtual nsresult CallToWriteData(uint32_t count, uint32_t* countRead) = 0;
206 virtual nsresult CallToReadData(uint32_t count, uint32_t* countWritten) = 0;
207 virtual bool CloseSendStreamWhenDone() { return true; }
209 // These internal states track request generation
210 enum upstreamStateType {
211 GENERATING_HEADERS,
212 GENERATING_BODY,
213 SENDING_BODY,
214 SENDING_FIN_STREAM,
215 UPSTREAM_COMPLETE
218 uint32_t mStreamID{0};
220 // The session that this stream is a subset of
221 nsWeakPtr mSession;
223 // These are temporary state variables to hold the argument to
224 // Read/WriteSegments so it can be accessed by On(read/write)segment
225 // further up the stack.
226 RefPtr<nsAHttpSegmentReader> mSegmentReader;
227 nsAHttpSegmentWriter* mSegmentWriter{nullptr};
229 nsCString mOrigin;
230 nsCString mHeaderHost;
231 nsCString mHeaderScheme;
232 nsCString mHeaderPath;
234 // Each stream goes from generating_headers to upstream_complete, perhaps
235 // looping on multiple instances of generating_body and
236 // sending_body for each frame in the upload.
237 enum upstreamStateType mUpstreamState { GENERATING_HEADERS };
239 // The HTTP/2 state for the stream from section 5.1
240 enum stateType mState { IDLE };
242 // Flag is set when all http request headers have been read ID is not stable
243 uint32_t mRequestHeadersDone : 1;
245 // Flag is set when ID is stable and concurrency limits are met
246 uint32_t mOpenGenerated : 1;
248 // Flag is set when all http response headers have been read
249 uint32_t mAllHeadersReceived : 1;
251 // Flag is set when stream is queued inside the session due to
252 // concurrency limits being exceeded
253 uint32_t mQueued : 1;
255 void ChangeState(enum upstreamStateType);
257 virtual void AdjustInitialWindow();
258 [[nodiscard]] nsresult TransmitFrame(const char*, uint32_t*,
259 bool forceCommitment);
261 // The underlying socket transport object is needed to propogate some events
262 nsCOMPtr<nsISocketTransport> mSocketTransport;
264 uint8_t mPriorityWeight = 0; // h2 weight
265 uint32_t mPriorityDependency = 0; // h2 stream id this one depends on
266 uint64_t mCurrentBrowserId;
267 uint64_t mTransactionBrowserId{0};
269 // The InlineFrame and associated data is used for composing control
270 // frames and data frame headers.
271 UniquePtr<uint8_t[]> mTxInlineFrame;
272 uint32_t mTxInlineFrameSize{0};
273 uint32_t mTxInlineFrameUsed{0};
275 uint32_t mRFC7540Priority = 0; // geckoish weight
277 // Buffer for request header compression.
278 nsCString mFlatHttpRequestHeaders;
280 // Track the content-length of a request body so that we can
281 // place the fin flag on the last data packet instead of waiting
282 // for a stream closed indication. Relying on stream close results
283 // in an extra 0-length runt packet and seems to have some interop
284 // problems with the google servers. Connect does rely on stream
285 // close by setting this to the max value.
286 int64_t mRequestBodyLenRemaining{0};
288 private:
289 friend class mozilla::DefaultDelete<Http2StreamBase>;
291 [[nodiscard]] nsresult ParseHttpRequestHeaders(const char*, uint32_t,
292 uint32_t*);
293 [[nodiscard]] nsresult GenerateOpen();
295 virtual nsresult GenerateHeaders(nsCString& aCompressedData,
296 uint8_t& firstFrameFlags) = 0;
298 void GenerateDataFrameHeader(uint32_t, bool);
300 [[nodiscard]] nsresult BufferInput(uint32_t, uint32_t*);
302 // The quanta upstream data frames are chopped into
303 uint32_t mChunkSize;
305 // Flag is set when the HTTP processor has more data to send
306 // but has blocked in doing so.
307 uint32_t mRequestBlockedOnRead : 1;
309 // Flag is set after the response frame bearing the fin bit has
310 // been processed. (i.e. after the server has closed).
311 uint32_t mRecvdFin : 1;
313 // Flag is set after 1st DATA frame has been passed to stream
314 uint32_t mReceivedData : 1;
316 // Flag is set after RST_STREAM has been received for this stream
317 uint32_t mRecvdReset : 1;
319 // Flag is set after RST_STREAM has been generated for this stream
320 uint32_t mSentReset : 1;
322 // Flag is set when stream is counted towards MAX_CONCURRENT streams in
323 // session
324 uint32_t mCountAsActive : 1;
326 // Flag is set when a FIN has been placed on a data or header frame
327 // (i.e after the client has closed)
328 uint32_t mSentFin : 1;
330 // Flag is set after the WAITING_FOR Transport event has been generated
331 uint32_t mSentWaitingFor : 1;
333 // Flag is set after TCP send autotuning has been disabled
334 uint32_t mSetTCPSocketBuffer : 1;
336 // Flag is set when OnWriteSegment is being called directly from stream
337 // instead of transaction
338 uint32_t mBypassInputBuffer : 1;
340 // mTxStreamFrameSize tracks the progress of
341 // transmitting a request body data frame. The data frame itself
342 // is never copied into the spdy layer.
343 uint32_t mTxStreamFrameSize{0};
345 // mClientReceiveWindow, mServerReceiveWindow, and mLocalUnacked are for flow
346 // control. *window are signed because the race conditions in asynchronous
347 // SETTINGS messages can force them temporarily negative.
349 // mClientReceiveWindow is how much data the server will send without getting
350 // a
351 // window update
352 int64_t mClientReceiveWindow;
354 // mServerReceiveWindow is how much data the client is allowed to send without
355 // getting a window update
356 int64_t mServerReceiveWindow;
358 // LocalUnacked is the number of bytes received by the client but not
359 // yet reflected in a window update. Sending that update will increment
360 // ClientReceiveWindow
361 uint64_t mLocalUnacked{0};
363 // True when sending is suspended becuase the server receive window is
364 // <= 0
365 bool mBlockedOnRwin{false};
367 // For Progress Events
368 uint64_t mTotalSent{0};
369 uint64_t mTotalRead{0};
371 // Used to store stream data when the transaction channel cannot keep up
372 // and flow control has not yet kicked in.
373 SimpleBuffer mSimpleBuffer;
375 bool mAttempting0RTT{false};
378 } // namespace mozilla::net
380 #endif // mozilla_net_Http2StreamBase_h