tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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