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