/src/mozilla-central/netwerk/protocol/http/Http2Session.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; 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/. */ |
5 | | |
6 | | #ifndef mozilla_net_Http2Session_h |
7 | | #define mozilla_net_Http2Session_h |
8 | | |
9 | | // HTTP/2 - RFC 7540 |
10 | | // https://www.rfc-editor.org/rfc/rfc7540.txt |
11 | | |
12 | | #include "ASpdySession.h" |
13 | | #include "mozilla/Attributes.h" |
14 | | #include "mozilla/UniquePtr.h" |
15 | | #include "mozilla/WeakPtr.h" |
16 | | #include "nsAHttpConnection.h" |
17 | | #include "nsClassHashtable.h" |
18 | | #include "nsDataHashtable.h" |
19 | | #include "nsDeque.h" |
20 | | #include "nsHashKeys.h" |
21 | | #include "nsHttpRequestHead.h" |
22 | | #include "nsICacheEntryOpenCallback.h" |
23 | | |
24 | | #include "Http2Compression.h" |
25 | | |
26 | | class nsISocketTransport; |
27 | | |
28 | | namespace mozilla { |
29 | | namespace net { |
30 | | |
31 | | class Http2PushedStream; |
32 | | class Http2Stream; |
33 | | class nsHttpTransaction; |
34 | | |
35 | | class Http2Session final : public ASpdySession |
36 | | , public nsAHttpConnection |
37 | | , public nsAHttpSegmentReader |
38 | | , public nsAHttpSegmentWriter |
39 | | { |
40 | | ~Http2Session(); |
41 | | |
42 | | public: |
43 | | NS_DECL_THREADSAFE_ISUPPORTS |
44 | | NS_DECL_NSAHTTPTRANSACTION |
45 | | NS_DECL_NSAHTTPCONNECTION(mConnection) |
46 | | NS_DECL_NSAHTTPSEGMENTREADER |
47 | | NS_DECL_NSAHTTPSEGMENTWRITER |
48 | | |
49 | | Http2Session(nsISocketTransport *, enum SpdyVersion version, bool attemptingEarlyData); |
50 | | |
51 | | MOZ_MUST_USE bool AddStream(nsAHttpTransaction *, int32_t, |
52 | | bool, nsIInterfaceRequestor *) override; |
53 | 0 | bool CanReuse() override { return !mShouldGoAway && !mClosed; } |
54 | | bool RoomForMoreStreams() override; |
55 | | enum SpdyVersion SpdyVersion() override; |
56 | | bool TestJoinConnection(const nsACString &hostname, int32_t port) override; |
57 | | bool JoinConnection(const nsACString &hostname, int32_t port) override; |
58 | | |
59 | | // When the connection is active this is called up to once every 1 second |
60 | | // return the interval (in seconds) that the connection next wants to |
61 | | // have this invoked. It might happen sooner depending on the needs of |
62 | | // other connections. |
63 | | uint32_t ReadTimeoutTick(PRIntervalTime now) override; |
64 | | |
65 | | // Idle time represents time since "goodput".. e.g. a data or header frame |
66 | | PRIntervalTime IdleTime() override; |
67 | | |
68 | | // Registering with a newID of 0 means pick the next available odd ID |
69 | | uint32_t RegisterStreamID(Http2Stream *, uint32_t aNewID = 0); |
70 | | |
71 | | /* |
72 | | HTTP/2 framing |
73 | | |
74 | | 0 1 2 3 |
75 | | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
76 | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
77 | | | Length (16) | Type (8) | Flags (8) | |
78 | | +-+-------------+---------------+-------------------------------+ |
79 | | |R| Stream Identifier (31) | |
80 | | +-+-------------------------------------------------------------+ |
81 | | | Frame Data (0...) ... |
82 | | +---------------------------------------------------------------+ |
83 | | */ |
84 | | |
85 | | enum FrameType { |
86 | | FRAME_TYPE_DATA = 0x0, |
87 | | FRAME_TYPE_HEADERS = 0x1, |
88 | | FRAME_TYPE_PRIORITY = 0x2, |
89 | | FRAME_TYPE_RST_STREAM = 0x3, |
90 | | FRAME_TYPE_SETTINGS = 0x4, |
91 | | FRAME_TYPE_PUSH_PROMISE = 0x5, |
92 | | FRAME_TYPE_PING = 0x6, |
93 | | FRAME_TYPE_GOAWAY = 0x7, |
94 | | FRAME_TYPE_WINDOW_UPDATE = 0x8, |
95 | | FRAME_TYPE_CONTINUATION = 0x9, |
96 | | FRAME_TYPE_ALTSVC = 0xA, |
97 | | FRAME_TYPE_UNUSED = 0xB, |
98 | | FRAME_TYPE_ORIGIN = 0xC, |
99 | | FRAME_TYPE_LAST = 0xD |
100 | | }; |
101 | | |
102 | | // NO_ERROR is a macro defined on windows, so we'll name the HTTP2 goaway |
103 | | // code NO_ERROR to be NO_HTTP_ERROR |
104 | | enum errorType { |
105 | | NO_HTTP_ERROR = 0, |
106 | | PROTOCOL_ERROR = 1, |
107 | | INTERNAL_ERROR = 2, |
108 | | FLOW_CONTROL_ERROR = 3, |
109 | | SETTINGS_TIMEOUT_ERROR = 4, |
110 | | STREAM_CLOSED_ERROR = 5, |
111 | | FRAME_SIZE_ERROR = 6, |
112 | | REFUSED_STREAM_ERROR = 7, |
113 | | CANCEL_ERROR = 8, |
114 | | COMPRESSION_ERROR = 9, |
115 | | CONNECT_ERROR = 10, |
116 | | ENHANCE_YOUR_CALM = 11, |
117 | | INADEQUATE_SECURITY = 12, |
118 | | HTTP_1_1_REQUIRED = 13, |
119 | | UNASSIGNED = 31 |
120 | | }; |
121 | | |
122 | | // These are frame flags. If they, or other undefined flags, are |
123 | | // used on frames other than the comments indicate they MUST be ignored. |
124 | | const static uint8_t kFlag_END_STREAM = 0x01; // data, headers |
125 | | const static uint8_t kFlag_END_HEADERS = 0x04; // headers, continuation |
126 | | const static uint8_t kFlag_END_PUSH_PROMISE = 0x04; // push promise |
127 | | const static uint8_t kFlag_ACK = 0x01; // ping and settings |
128 | | const static uint8_t kFlag_PADDED = 0x08; // data, headers, push promise, continuation |
129 | | const static uint8_t kFlag_PRIORITY = 0x20; // headers |
130 | | |
131 | | enum { |
132 | | SETTINGS_TYPE_HEADER_TABLE_SIZE = 1, // compression table size |
133 | | SETTINGS_TYPE_ENABLE_PUSH = 2, // can be used to disable push |
134 | | SETTINGS_TYPE_MAX_CONCURRENT = 3, // streams recvr allowed to initiate |
135 | | SETTINGS_TYPE_INITIAL_WINDOW = 4, // bytes for flow control default |
136 | | SETTINGS_TYPE_MAX_FRAME_SIZE = 5 // max frame size settings sender allows receipt of |
137 | | }; |
138 | | |
139 | | // This should be big enough to hold all of your control packets, |
140 | | // but if it needs to grow for huge headers it can do so dynamically. |
141 | | const static uint32_t kDefaultBufferSize = 2048; |
142 | | |
143 | | // kDefaultQueueSize must be >= other queue size constants |
144 | | const static uint32_t kDefaultQueueSize = 32768; |
145 | | const static uint32_t kQueueMinimumCleanup = 24576; |
146 | | const static uint32_t kQueueTailRoom = 4096; |
147 | | const static uint32_t kQueueReserved = 1024; |
148 | | |
149 | | const static uint32_t kMaxStreamID = 0x7800000; |
150 | | |
151 | | // This is a sentinel for a deleted stream. It is not a valid |
152 | | // 31 bit stream ID. |
153 | | const static uint32_t kDeadStreamID = 0xffffdead; |
154 | | |
155 | | // below the emergency threshold of local window we ack every received |
156 | | // byte. Above that we coalesce bytes into the MinimumToAck size. |
157 | | const static int32_t kEmergencyWindowThreshold = 96 * 1024; |
158 | | const static uint32_t kMinimumToAck = 4 * 1024 * 1024; |
159 | | |
160 | | // The default rwin is 64KB - 1 unless updated by a settings frame |
161 | | const static uint32_t kDefaultRwin = 65535; |
162 | | |
163 | | // We limit frames to 2^14 bytes of length in order to preserve responsiveness |
164 | | // This is the smallest allowed value for SETTINGS_MAX_FRAME_SIZE |
165 | | const static uint32_t kMaxFrameData = 0x4000; |
166 | | |
167 | | const static uint8_t kFrameLengthBytes = 3; |
168 | | const static uint8_t kFrameStreamIDBytes = 4; |
169 | | const static uint8_t kFrameFlagBytes = 1; |
170 | | const static uint8_t kFrameTypeBytes = 1; |
171 | | const static uint8_t kFrameHeaderBytes = kFrameLengthBytes + kFrameFlagBytes + |
172 | | kFrameTypeBytes + kFrameStreamIDBytes; |
173 | | |
174 | | enum { |
175 | | kLeaderGroupID = 0x3, |
176 | | kOtherGroupID = 0x5, |
177 | | kBackgroundGroupID = 0x7, |
178 | | kSpeculativeGroupID = 0x9, |
179 | | kFollowerGroupID = 0xB, |
180 | | kUrgentStartGroupID = 0xD |
181 | | // Hey, you! YES YOU! If you add/remove any groups here, you almost |
182 | | // certainly need to change the lookup of the stream/ID hash in |
183 | | // Http2Session::OnTransportStatus and |kPriorityGroupCount| below. |
184 | | // Yeah, that's right. YOU! |
185 | | }; |
186 | | const static uint8_t kPriorityGroupCount = 6; |
187 | | |
188 | | static nsresult RecvHeaders(Http2Session *); |
189 | | static nsresult RecvPriority(Http2Session *); |
190 | | static nsresult RecvRstStream(Http2Session *); |
191 | | static nsresult RecvSettings(Http2Session *); |
192 | | static nsresult RecvPushPromise(Http2Session *); |
193 | | static nsresult RecvPing(Http2Session *); |
194 | | static nsresult RecvGoAway(Http2Session *); |
195 | | static nsresult RecvWindowUpdate(Http2Session *); |
196 | | static nsresult RecvContinuation(Http2Session *); |
197 | | static nsresult RecvAltSvc(Http2Session *); |
198 | | static nsresult RecvUnused(Http2Session *); |
199 | | static nsresult RecvOrigin(Http2Session *); |
200 | | |
201 | | char *EnsureOutputBuffer(uint32_t needed); |
202 | | |
203 | | template<typename charType> |
204 | | void CreateFrameHeader(charType dest, uint16_t frameLength, |
205 | | uint8_t frameType, uint8_t frameFlags, |
206 | | uint32_t streamID); |
207 | | |
208 | | // For writing the data stream to LOG4 |
209 | | static void LogIO(Http2Session *, Http2Stream *, const char *, |
210 | | const char *, uint32_t); |
211 | | |
212 | | // overload of nsAHttpConnection |
213 | | void TransactionHasDataToWrite(nsAHttpTransaction *) override; |
214 | | void TransactionHasDataToRecv(nsAHttpTransaction *) override; |
215 | | |
216 | | // a similar version for Http2Stream |
217 | | void TransactionHasDataToWrite(Http2Stream *); |
218 | | |
219 | | // an overload of nsAHttpSegementReader |
220 | | virtual MOZ_MUST_USE nsresult CommitToSegmentSize(uint32_t size, |
221 | | bool forceCommitment) override; |
222 | | MOZ_MUST_USE nsresult BufferOutput(const char *, uint32_t, uint32_t *); |
223 | | void FlushOutputQueue(); |
224 | 0 | uint32_t AmountOfOutputBuffered() { return mOutputQueueUsed - mOutputQueueSent; } |
225 | | |
226 | 0 | uint32_t GetServerInitialStreamWindow() { return mServerInitialStreamWindow; } |
227 | | |
228 | | MOZ_MUST_USE bool TryToActivate(Http2Stream *stream); |
229 | | void ConnectPushedStream(Http2Stream *stream); |
230 | | void ConnectSlowConsumer(Http2Stream *stream); |
231 | | |
232 | | MOZ_MUST_USE nsresult ConfirmTLSProfile(); |
233 | | static MOZ_MUST_USE bool ALPNCallback(nsISupports *securityInfo); |
234 | | |
235 | 0 | uint64_t Serial() { return mSerial; } |
236 | | |
237 | | void PrintDiagnostics (nsCString &log) override; |
238 | | |
239 | | // Streams need access to these |
240 | 0 | uint32_t SendingChunkSize() { return mSendingChunkSize; } |
241 | 0 | uint32_t PushAllowance() { return mPushAllowance; } |
242 | 0 | Http2Compressor *Compressor() { return &mCompressor; } |
243 | 0 | nsISocketTransport *SocketTransport() { return mSocketTransport; } |
244 | 0 | int64_t ServerSessionWindow() { return mServerSessionWindow; } |
245 | 0 | void DecrementServerSessionWindow (uint32_t bytes) { mServerSessionWindow -= bytes; } |
246 | 0 | uint32_t InitialRwin() { return mInitialRwin; } |
247 | | |
248 | | void SendPing() override; |
249 | | MOZ_MUST_USE bool MaybeReTunnel(nsAHttpTransaction *) override; |
250 | 0 | bool UseH2Deps() { return mUseH2Deps; } |
251 | | |
252 | | // overload of nsAHttpTransaction |
253 | | MOZ_MUST_USE nsresult ReadSegmentsAgain(nsAHttpSegmentReader *, uint32_t, uint32_t *, bool *) final; |
254 | | MOZ_MUST_USE nsresult WriteSegmentsAgain(nsAHttpSegmentWriter *, uint32_t , uint32_t *, bool *) final; |
255 | 0 | MOZ_MUST_USE bool Do0RTT() final { return true; } |
256 | | MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged) final; |
257 | | void SetFastOpenStatus(uint8_t aStatus) final; |
258 | | |
259 | | // For use by an HTTP2Stream |
260 | | void Received421(nsHttpConnectionInfo *ci); |
261 | | |
262 | | void SendPriorityFrame(uint32_t streamID, uint32_t dependsOn, uint8_t weight); |
263 | 0 | void IncrementTrrCounter() { mTrrStreams++; } |
264 | | |
265 | | private: |
266 | | |
267 | | // These internal states do not correspond to the states of the HTTP/2 specification |
268 | | enum internalStateType { |
269 | | BUFFERING_OPENING_SETTINGS, |
270 | | BUFFERING_FRAME_HEADER, |
271 | | BUFFERING_CONTROL_FRAME, |
272 | | PROCESSING_DATA_FRAME_PADDING_CONTROL, |
273 | | PROCESSING_DATA_FRAME, |
274 | | DISCARDING_DATA_FRAME_PADDING, |
275 | | DISCARDING_DATA_FRAME, |
276 | | PROCESSING_COMPLETE_HEADERS, |
277 | | PROCESSING_CONTROL_RST_STREAM, |
278 | | NOT_USING_NETWORK |
279 | | }; |
280 | | |
281 | | static const uint8_t kMagicHello[24]; |
282 | | |
283 | | MOZ_MUST_USE nsresult ResponseHeadersComplete(); |
284 | | uint32_t GetWriteQueueSize(); |
285 | | void ChangeDownstreamState(enum internalStateType); |
286 | | void ResetDownstreamState(); |
287 | | MOZ_MUST_USE nsresult ReadyToProcessDataFrame(enum internalStateType); |
288 | | MOZ_MUST_USE nsresult UncompressAndDiscard(bool); |
289 | | void GeneratePing(bool); |
290 | | void GenerateSettingsAck(); |
291 | | void GeneratePriority(uint32_t, uint8_t); |
292 | | void GenerateRstStream(uint32_t, uint32_t); |
293 | | void GenerateGoAway(uint32_t); |
294 | | void CleanupStream(Http2Stream *, nsresult, errorType); |
295 | | void CleanupStream(uint32_t, nsresult, errorType); |
296 | | void CloseStream(Http2Stream *, nsresult); |
297 | | void SendHello(); |
298 | | void RemoveStreamFromQueues(Http2Stream *); |
299 | | MOZ_MUST_USE nsresult ParsePadding(uint8_t &, uint16_t &); |
300 | | |
301 | | void SetWriteCallbacks(); |
302 | | void RealignOutputQueue(); |
303 | | |
304 | | void ProcessPending(); |
305 | | MOZ_MUST_USE nsresult ProcessConnectedPush(Http2Stream *, |
306 | | nsAHttpSegmentWriter *, |
307 | | uint32_t, uint32_t *); |
308 | | MOZ_MUST_USE nsresult ProcessSlowConsumer(Http2Stream *, |
309 | | nsAHttpSegmentWriter *, |
310 | | uint32_t, uint32_t *); |
311 | | |
312 | | MOZ_MUST_USE nsresult SetInputFrameDataStream(uint32_t); |
313 | | void CreatePriorityNode(uint32_t, uint32_t, uint8_t, const char *); |
314 | | char *CreatePriorityFrame(uint32_t, uint32_t, uint8_t); |
315 | | bool VerifyStream(Http2Stream *, uint32_t); |
316 | | void SetNeedsCleanup(); |
317 | | |
318 | | void UpdateLocalRwin(Http2Stream *stream, uint32_t bytes); |
319 | | void UpdateLocalStreamWindow(Http2Stream *stream, uint32_t bytes); |
320 | | void UpdateLocalSessionWindow(uint32_t bytes); |
321 | | |
322 | | void MaybeDecrementConcurrent(Http2Stream *stream); |
323 | | bool RoomForMoreConcurrent(); |
324 | | void IncrementConcurrent(Http2Stream *stream); |
325 | | void QueueStream(Http2Stream *stream); |
326 | | |
327 | | // a wrapper for all calls to the nshttpconnection level segment writer. Used |
328 | | // to track network I/O for timeout purposes |
329 | | MOZ_MUST_USE nsresult NetworkRead(nsAHttpSegmentWriter *, char *, uint32_t, uint32_t *); |
330 | | |
331 | | void Shutdown(); |
332 | | |
333 | | // This is intended to be nsHttpConnectionMgr:nsConnectionHandle taken |
334 | | // from the first transaction on this session. That object contains the |
335 | | // pointer to the real network-level nsHttpConnection object. |
336 | | RefPtr<nsAHttpConnection> mConnection; |
337 | | |
338 | | // The underlying socket transport object is needed to propogate some events |
339 | | nsISocketTransport *mSocketTransport; |
340 | | |
341 | | // These are temporary state variables to hold the argument to |
342 | | // Read/WriteSegments so it can be accessed by On(read/write)segment |
343 | | // further up the stack. |
344 | | nsAHttpSegmentReader *mSegmentReader; |
345 | | nsAHttpSegmentWriter *mSegmentWriter; |
346 | | |
347 | | uint32_t mSendingChunkSize; /* the transmission chunk size */ |
348 | | uint32_t mNextStreamID; /* 24 bits */ |
349 | | uint32_t mLastPushedID; |
350 | | uint32_t mConcurrentHighWater; /* max parallelism on session */ |
351 | | uint32_t mPushAllowance; /* rwin for unmatched pushes */ |
352 | | |
353 | | internalStateType mDownstreamState; /* in frame, between frames, etc.. */ |
354 | | |
355 | | // Maintain 2 indexes - one by stream ID, one by transaction pointer. |
356 | | // There are also several lists of streams: ready to write, queued due to |
357 | | // max parallelism, streams that need to force a read for push, and the full |
358 | | // set of pushed streams. |
359 | | // The objects are not ref counted - they get destroyed |
360 | | // by the nsClassHashtable implementation when they are removed from |
361 | | // the transaction hash. |
362 | | nsDataHashtable<nsUint32HashKey, Http2Stream *> mStreamIDHash; |
363 | | nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>, |
364 | | Http2Stream> mStreamTransactionHash; |
365 | | |
366 | | nsDeque mReadyForWrite; |
367 | | nsDeque mQueuedStreams; |
368 | | nsDeque mPushesReadyForRead; |
369 | | nsDeque mSlowConsumersReadyForRead; |
370 | | nsTArray<Http2PushedStream *> mPushedStreams; |
371 | | |
372 | | // Compression contexts for header transport. |
373 | | // HTTP/2 compresses only HTTP headers and does not reset the context in between |
374 | | // frames. Even data that is not associated with a stream (e.g invalid |
375 | | // stream ID) is passed through these contexts to keep the compression |
376 | | // context correct. |
377 | | Http2Compressor mCompressor; |
378 | | Http2Decompressor mDecompressor; |
379 | | nsCString mDecompressBuffer; |
380 | | |
381 | | // mInputFrameBuffer is used to store received control packets and the 8 bytes |
382 | | // of header on data packets |
383 | | uint32_t mInputFrameBufferSize; // buffer allocation |
384 | | uint32_t mInputFrameBufferUsed; // amt of allocation used |
385 | | UniquePtr<char[]> mInputFrameBuffer; |
386 | | |
387 | | // mInputFrameDataSize/Read are used for tracking the amount of data consumed |
388 | | // in a frame after the 8 byte header. Control frames are always fully buffered |
389 | | // and the fixed 8 byte leading header is at mInputFrameBuffer + 0, the first |
390 | | // data byte (i.e. the first settings/goaway/etc.. specific byte) is at |
391 | | // mInputFrameBuffer + 8 |
392 | | // The frame size is mInputFrameDataSize + the constant 8 byte header |
393 | | uint32_t mInputFrameDataSize; |
394 | | uint32_t mInputFrameDataRead; |
395 | | bool mInputFrameFinal; // This frame was marked FIN |
396 | | uint8_t mInputFrameType; |
397 | | uint8_t mInputFrameFlags; |
398 | | uint32_t mInputFrameID; |
399 | | uint16_t mPaddingLength; |
400 | | |
401 | | // When a frame has been received that is addressed to a particular stream |
402 | | // (e.g. a data frame after the stream-id has been decoded), this points |
403 | | // to the stream. |
404 | | Http2Stream *mInputFrameDataStream; |
405 | | |
406 | | // mNeedsCleanup is a state variable to defer cleanup of a closed stream |
407 | | // If needed, It is set in session::OnWriteSegments() and acted on and |
408 | | // cleared when the stack returns to session::WriteSegments(). The stream |
409 | | // cannot be destroyed directly out of OnWriteSegments because |
410 | | // stream::writeSegments() is on the stack at that time. |
411 | | Http2Stream *mNeedsCleanup; |
412 | | |
413 | | // This reason code in the last processed RESET frame |
414 | | uint32_t mDownstreamRstReason; |
415 | | |
416 | | // When HEADERS/PROMISE are chained together, this is the expected ID of the next |
417 | | // recvd frame which must be the same type |
418 | | uint32_t mExpectedHeaderID; |
419 | | uint32_t mExpectedPushPromiseID; |
420 | | uint32_t mContinuedPromiseStream; |
421 | | |
422 | | // for the conversion of downstream http headers into http/2 formatted headers |
423 | | // The data here does not persist between frames |
424 | | nsCString mFlatHTTPResponseHeaders; |
425 | | uint32_t mFlatHTTPResponseHeadersOut; |
426 | | |
427 | | // when set, the session will go away when it reaches 0 streams. This flag |
428 | | // is set when: the stream IDs are running out (at either the client or the |
429 | | // server), when DontReuse() is called, a RST that is not specific to a |
430 | | // particular stream is received, a GOAWAY frame has been received from |
431 | | // the server. |
432 | | bool mShouldGoAway; |
433 | | |
434 | | // the session has received a nsAHttpTransaction::Close() call |
435 | | bool mClosed; |
436 | | |
437 | | // the session received a GoAway frame with a valid GoAwayID |
438 | | bool mCleanShutdown; |
439 | | |
440 | | // the session received the opening SETTINGS frame from the server |
441 | | bool mReceivedSettings; |
442 | | |
443 | | // The TLS comlpiance checks are not done in the ctor beacuse of bad |
444 | | // exception handling - so we do them at IO time and cache the result |
445 | | bool mTLSProfileConfirmed; |
446 | | |
447 | | // A specifc reason code for the eventual GoAway frame. If set to NO_HTTP_ERROR |
448 | | // only NO_HTTP_ERROR, PROTOCOL_ERROR, or INTERNAL_ERROR will be sent. |
449 | | errorType mGoAwayReason; |
450 | | |
451 | | // The error code sent/received on the session goaway frame. UNASSIGNED/31 |
452 | | // if not transmitted. |
453 | | int32_t mClientGoAwayReason; |
454 | | int32_t mPeerGoAwayReason; |
455 | | |
456 | | // If a GoAway message was received this is the ID of the last valid |
457 | | // stream. 0 otherwise. (0 is never a valid stream id.) |
458 | | uint32_t mGoAwayID; |
459 | | |
460 | | // The last stream processed ID we will send in our GoAway frame. |
461 | | uint32_t mOutgoingGoAwayID; |
462 | | |
463 | | // The limit on number of concurrent streams for this session. Normally it |
464 | | // is basically unlimited, but the SETTINGS control message from the |
465 | | // server might bring it down. |
466 | | uint32_t mMaxConcurrent; |
467 | | |
468 | | // The actual number of concurrent streams at this moment. Generally below |
469 | | // mMaxConcurrent, but the max can be lowered in real time to a value |
470 | | // below the current value |
471 | | uint32_t mConcurrent; |
472 | | |
473 | | // The number of server initiated promises, tracked for telemetry |
474 | | uint32_t mServerPushedResources; |
475 | | |
476 | | // The server rwin for new streams as determined from a SETTINGS frame |
477 | | uint32_t mServerInitialStreamWindow; |
478 | | |
479 | | // The Local Session window is how much data the server is allowed to send |
480 | | // (across all streams) without getting a window update to stream 0. It is |
481 | | // signed because asynchronous changes via SETTINGS can drive it negative. |
482 | | int64_t mLocalSessionWindow; |
483 | | |
484 | | // The Remote Session Window is how much data the client is allowed to send |
485 | | // (across all streams) without receiving a window update to stream 0. It is |
486 | | // signed because asynchronous changes via SETTINGS can drive it negative. |
487 | | int64_t mServerSessionWindow; |
488 | | |
489 | | // The initial value of the local stream and session window |
490 | | uint32_t mInitialRwin; |
491 | | |
492 | | // This is a output queue of bytes ready to be written to the SSL stream. |
493 | | // When that streams returns WOULD_BLOCK on direct write the bytes get |
494 | | // coalesced together here. This results in larger writes to the SSL layer. |
495 | | // The buffer is not dynamically grown to accomodate stream writes, but |
496 | | // does expand to accept infallible session wide frames like GoAway and RST. |
497 | | uint32_t mOutputQueueSize; |
498 | | uint32_t mOutputQueueUsed; |
499 | | uint32_t mOutputQueueSent; |
500 | | UniquePtr<char[]> mOutputQueueBuffer; |
501 | | |
502 | | PRIntervalTime mPingThreshold; |
503 | | PRIntervalTime mLastReadEpoch; // used for ping timeouts |
504 | | PRIntervalTime mLastDataReadEpoch; // used for IdleTime() |
505 | | PRIntervalTime mPingSentEpoch; |
506 | | |
507 | | PRIntervalTime mPreviousPingThreshold; // backup for the former value |
508 | | bool mPreviousUsed; // true when backup is used |
509 | | |
510 | | // used as a temporary buffer while enumerating the stream hash during GoAway |
511 | | nsDeque mGoAwayStreamsToRestart; |
512 | | |
513 | | // Each session gets a unique serial number because the push cache is correlated |
514 | | // by the load group and the serial number can be used as part of the cache key |
515 | | // to make sure streams aren't shared across sessions. |
516 | | uint64_t mSerial; |
517 | | |
518 | | // Telemetry for continued headers (pushed and pulled) for quic design |
519 | | uint32_t mAggregatedHeaderSize; |
520 | | |
521 | | // If push is disabled, we want to be able to send PROTOCOL_ERRORs if we |
522 | | // receive a PUSH_PROMISE, but we have to wait for the SETTINGS ACK before |
523 | | // we can actually tell the other end to go away. These help us keep track |
524 | | // of that state so we can behave appropriately. |
525 | | bool mWaitingForSettingsAck; |
526 | | bool mGoAwayOnPush; |
527 | | |
528 | | bool mUseH2Deps; |
529 | | |
530 | | bool mAttemptingEarlyData; |
531 | | // The ID(s) of the stream(s) that we are getting 0RTT data from. |
532 | | nsTArray<WeakPtr<Http2Stream>> m0RTTStreams; |
533 | | // The ID(s) of the stream(s) that are not able to send 0RTT data. We need to |
534 | | // remember them put them into mReadyForWrite queue when 0RTT finishes. |
535 | | nsTArray<WeakPtr<Http2Stream>> mCannotDo0RTTStreams; |
536 | | |
537 | | bool RealJoinConnection(const nsACString &hostname, int32_t port, bool jk); |
538 | | bool TestOriginFrame(const nsACString &name, int32_t port); |
539 | | bool mOriginFrameActivated; |
540 | | nsDataHashtable<nsCStringHashKey, bool> mOriginFrame; |
541 | | |
542 | | nsDataHashtable<nsCStringHashKey, bool> mJoinConnectionCache; |
543 | | |
544 | | uint64_t mCurrentForegroundTabOuterContentWindowId; |
545 | | |
546 | | class CachePushCheckCallback final : public nsICacheEntryOpenCallback |
547 | | { |
548 | | public: |
549 | | CachePushCheckCallback(Http2Session *session, uint32_t promisedID, const nsACString &requestString); |
550 | | |
551 | | NS_DECL_ISUPPORTS |
552 | | NS_DECL_NSICACHEENTRYOPENCALLBACK |
553 | | |
554 | | private: |
555 | 0 | ~CachePushCheckCallback() = default; |
556 | | |
557 | | RefPtr<Http2Session> mSession; |
558 | | uint32_t mPromisedID; |
559 | | nsHttpRequestHead mRequestHead; |
560 | | }; |
561 | | |
562 | | // A h2 session will be created before all socket events are trigered, |
563 | | // e.g. NS_NET_STATUS_TLS_HANDSHAKE_ENDED and for TFO many others. |
564 | | // We should propagate this events to the first nsHttpTransaction. |
565 | | RefPtr<nsHttpTransaction> mFirstHttpTransaction; |
566 | | bool mTlsHandshakeFinished; |
567 | | |
568 | | bool mCheckNetworkStallsWithTFO; |
569 | | PRIntervalTime mLastRequestBytesSentTime; |
570 | | private: |
571 | | /// connect tunnels |
572 | | void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *); |
573 | | void CreateTunnel(nsHttpTransaction *, nsHttpConnectionInfo *, nsIInterfaceRequestor *); |
574 | | void RegisterTunnel(Http2Stream *); |
575 | | void UnRegisterTunnel(Http2Stream *); |
576 | | uint32_t FindTunnelCount(nsHttpConnectionInfo *); |
577 | | nsDataHashtable<nsCStringHashKey, uint32_t> mTunnelHash; |
578 | | uint32_t mTrrStreams; |
579 | | }; |
580 | | |
581 | | } // namespace net |
582 | | } // namespace mozilla |
583 | | |
584 | | #endif // mozilla_net_Http2Session_h |