forked from mirrors/gecko-dev
		
	 0129d900f3
			
		
	
	
		0129d900f3
		
	
	
	
	
		
			
			MozReview-Commit-ID: 70gt5SUu4Dv --HG-- extra : rebase_source : 71912c6bde22aaed01e70615a4ee794a36e70d0e extra : source : 1c22d4c65d70b797ee3e963ec426c90e1f89b5e3
		
			
				
	
	
		
			582 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			582 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef mozilla_net_Http2Session_h
 | |
| #define mozilla_net_Http2Session_h
 | |
| 
 | |
| // HTTP/2 - RFC 7540
 | |
| // https://www.rfc-editor.org/rfc/rfc7540.txt
 | |
| 
 | |
| #include "ASpdySession.h"
 | |
| #include "mozilla/Attributes.h"
 | |
| #include "mozilla/UniquePtr.h"
 | |
| #include "mozilla/WeakPtr.h"
 | |
| #include "nsAHttpConnection.h"
 | |
| #include "nsClassHashtable.h"
 | |
| #include "nsDataHashtable.h"
 | |
| #include "nsDeque.h"
 | |
| #include "nsHashKeys.h"
 | |
| #include "nsHttpRequestHead.h"
 | |
| #include "nsICacheEntryOpenCallback.h"
 | |
| 
 | |
| #include "Http2Compression.h"
 | |
| 
 | |
| class nsISocketTransport;
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace net {
 | |
| 
 | |
| class Http2PushedStream;
 | |
| class Http2Stream;
 | |
| class nsHttpTransaction;
 | |
| 
 | |
| class Http2Session final : public ASpdySession
 | |
|                          , public nsAHttpConnection
 | |
|                          , public nsAHttpSegmentReader
 | |
|                          , public nsAHttpSegmentWriter
 | |
| {
 | |
|   ~Http2Session();
 | |
| 
 | |
| public:
 | |
|   NS_DECL_THREADSAFE_ISUPPORTS
 | |
|   NS_DECL_NSAHTTPTRANSACTION
 | |
|   NS_DECL_NSAHTTPCONNECTION(mConnection)
 | |
|   NS_DECL_NSAHTTPSEGMENTREADER
 | |
|   NS_DECL_NSAHTTPSEGMENTWRITER
 | |
| 
 | |
|   Http2Session(nsISocketTransport *, uint32_t version, bool attemptingEarlyData);
 | |
| 
 | |
|   MOZ_MUST_USE bool AddStream(nsAHttpTransaction *, int32_t,
 | |
|                               bool, nsIInterfaceRequestor *) override;
 | |
|   bool CanReuse() override { return !mShouldGoAway && !mClosed; }
 | |
|   bool RoomForMoreStreams() override;
 | |
|   uint32_t SpdyVersion() override;
 | |
|   bool TestJoinConnection(const nsACString &hostname, int32_t port) override;
 | |
|   bool JoinConnection(const nsACString &hostname, int32_t port) override;
 | |
| 
 | |
|   // When the connection is active this is called up to once every 1 second
 | |
|   // return the interval (in seconds) that the connection next wants to
 | |
|   // have this invoked. It might happen sooner depending on the needs of
 | |
|   // other connections.
 | |
|   uint32_t  ReadTimeoutTick(PRIntervalTime now) override;
 | |
| 
 | |
|   // Idle time represents time since "goodput".. e.g. a data or header frame
 | |
|   PRIntervalTime IdleTime() override;
 | |
| 
 | |
|   // Registering with a newID of 0 means pick the next available odd ID
 | |
|   uint32_t RegisterStreamID(Http2Stream *, uint32_t aNewID = 0);
 | |
| 
 | |
| /*
 | |
|   HTTP/2 framing
 | |
| 
 | |
|   0                   1                   2                   3
 | |
|   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
 | |
|   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | |
|   |         Length (16)           |   Type (8)    |   Flags (8)   |
 | |
|   +-+-------------+---------------+-------------------------------+
 | |
|   |R|                 Stream Identifier (31)                      |
 | |
|   +-+-------------------------------------------------------------+
 | |
|   |                     Frame Data (0...)                       ...
 | |
|   +---------------------------------------------------------------+
 | |
| */
 | |
| 
 | |
|   enum FrameType {
 | |
|     FRAME_TYPE_DATA          = 0x0,
 | |
|     FRAME_TYPE_HEADERS       = 0x1,
 | |
|     FRAME_TYPE_PRIORITY      = 0x2,
 | |
|     FRAME_TYPE_RST_STREAM    = 0x3,
 | |
|     FRAME_TYPE_SETTINGS      = 0x4,
 | |
|     FRAME_TYPE_PUSH_PROMISE  = 0x5,
 | |
|     FRAME_TYPE_PING          = 0x6,
 | |
|     FRAME_TYPE_GOAWAY        = 0x7,
 | |
|     FRAME_TYPE_WINDOW_UPDATE = 0x8,
 | |
|     FRAME_TYPE_CONTINUATION  = 0x9,
 | |
|     FRAME_TYPE_ALTSVC        = 0xA,
 | |
|     FRAME_TYPE_UNUSED        = 0xB,
 | |
|     FRAME_TYPE_ORIGIN        = 0xC,
 | |
|     FRAME_TYPE_LAST          = 0xD
 | |
|   };
 | |
| 
 | |
|   // NO_ERROR is a macro defined on windows, so we'll name the HTTP2 goaway
 | |
|   // code NO_ERROR to be NO_HTTP_ERROR
 | |
|   enum errorType {
 | |
|     NO_HTTP_ERROR = 0,
 | |
|     PROTOCOL_ERROR = 1,
 | |
|     INTERNAL_ERROR = 2,
 | |
|     FLOW_CONTROL_ERROR = 3,
 | |
|     SETTINGS_TIMEOUT_ERROR = 4,
 | |
|     STREAM_CLOSED_ERROR = 5,
 | |
|     FRAME_SIZE_ERROR = 6,
 | |
|     REFUSED_STREAM_ERROR = 7,
 | |
|     CANCEL_ERROR = 8,
 | |
|     COMPRESSION_ERROR = 9,
 | |
|     CONNECT_ERROR = 10,
 | |
|     ENHANCE_YOUR_CALM = 11,
 | |
|     INADEQUATE_SECURITY = 12,
 | |
|     HTTP_1_1_REQUIRED = 13,
 | |
|     UNASSIGNED = 31
 | |
|   };
 | |
| 
 | |
|   // These are frame flags. If they, or other undefined flags, are
 | |
|   // used on frames other than the comments indicate they MUST be ignored.
 | |
|   const static uint8_t kFlag_END_STREAM = 0x01; // data, headers
 | |
|   const static uint8_t kFlag_END_HEADERS = 0x04; // headers, continuation
 | |
|   const static uint8_t kFlag_END_PUSH_PROMISE = 0x04; // push promise
 | |
|   const static uint8_t kFlag_ACK = 0x01; // ping and settings
 | |
|   const static uint8_t kFlag_PADDED = 0x08; // data, headers, push promise, continuation
 | |
|   const static uint8_t kFlag_PRIORITY = 0x20; // headers
 | |
| 
 | |
|   enum {
 | |
|     SETTINGS_TYPE_HEADER_TABLE_SIZE = 1, // compression table size
 | |
|     SETTINGS_TYPE_ENABLE_PUSH = 2,     // can be used to disable push
 | |
|     SETTINGS_TYPE_MAX_CONCURRENT = 3,  // streams recvr allowed to initiate
 | |
|     SETTINGS_TYPE_INITIAL_WINDOW = 4,  // bytes for flow control default
 | |
|     SETTINGS_TYPE_MAX_FRAME_SIZE = 5   // max frame size settings sender allows receipt of
 | |
|   };
 | |
| 
 | |
|   // This should be big enough to hold all of your control packets,
 | |
|   // but if it needs to grow for huge headers it can do so dynamically.
 | |
|   const static uint32_t kDefaultBufferSize = 2048;
 | |
| 
 | |
|   // kDefaultQueueSize must be >= other queue size constants
 | |
|   const static uint32_t kDefaultQueueSize =  32768;
 | |
|   const static uint32_t kQueueMinimumCleanup = 24576;
 | |
|   const static uint32_t kQueueTailRoom    =  4096;
 | |
|   const static uint32_t kQueueReserved    =  1024;
 | |
| 
 | |
|   const static uint32_t kMaxStreamID = 0x7800000;
 | |
| 
 | |
|   // This is a sentinel for a deleted stream. It is not a valid
 | |
|   // 31 bit stream ID.
 | |
|   const static uint32_t kDeadStreamID = 0xffffdead;
 | |
| 
 | |
|   // below the emergency threshold of local window we ack every received
 | |
|   // byte. Above that we coalesce bytes into the MinimumToAck size.
 | |
|   const static int32_t  kEmergencyWindowThreshold = 96 * 1024;
 | |
|   const static uint32_t kMinimumToAck = 4 * 1024 * 1024;
 | |
| 
 | |
|   // The default rwin is 64KB - 1 unless updated by a settings frame
 | |
|   const static uint32_t kDefaultRwin = 65535;
 | |
| 
 | |
|   // We limit frames to 2^14 bytes of length in order to preserve responsiveness
 | |
|   // This is the smallest allowed value for SETTINGS_MAX_FRAME_SIZE
 | |
|   const static uint32_t kMaxFrameData = 0x4000;
 | |
| 
 | |
|   const static uint8_t kFrameLengthBytes = 3;
 | |
|   const static uint8_t kFrameStreamIDBytes = 4;
 | |
|   const static uint8_t kFrameFlagBytes = 1;
 | |
|   const static uint8_t kFrameTypeBytes = 1;
 | |
|   const static uint8_t kFrameHeaderBytes = kFrameLengthBytes + kFrameFlagBytes +
 | |
|     kFrameTypeBytes + kFrameStreamIDBytes;
 | |
| 
 | |
|   enum {
 | |
|     kLeaderGroupID =      0x3,
 | |
|     kOtherGroupID =       0x5,
 | |
|     kBackgroundGroupID =  0x7,
 | |
|     kSpeculativeGroupID = 0x9,
 | |
|     kFollowerGroupID =    0xB,
 | |
|     kUrgentStartGroupID = 0xD
 | |
|     // Hey, you! YES YOU! If you add/remove any groups here, you almost
 | |
|     // certainly need to change the lookup of the stream/ID hash in
 | |
|     // Http2Session::OnTransportStatus and |kPriorityGroupCount| below.
 | |
|     // Yeah, that's right. YOU!
 | |
|   };
 | |
|   const static uint8_t kPriorityGroupCount = 6;
 | |
| 
 | |
|   static nsresult RecvHeaders(Http2Session *);
 | |
|   static nsresult RecvPriority(Http2Session *);
 | |
|   static nsresult RecvRstStream(Http2Session *);
 | |
|   static nsresult RecvSettings(Http2Session *);
 | |
|   static nsresult RecvPushPromise(Http2Session *);
 | |
|   static nsresult RecvPing(Http2Session *);
 | |
|   static nsresult RecvGoAway(Http2Session *);
 | |
|   static nsresult RecvWindowUpdate(Http2Session *);
 | |
|   static nsresult RecvContinuation(Http2Session *);
 | |
|   static nsresult RecvAltSvc(Http2Session *);
 | |
|   static nsresult RecvUnused(Http2Session *);
 | |
|   static nsresult RecvOrigin(Http2Session *);
 | |
| 
 | |
|   char       *EnsureOutputBuffer(uint32_t needed);
 | |
| 
 | |
|   template<typename charType>
 | |
|   void CreateFrameHeader(charType dest, uint16_t frameLength,
 | |
|                          uint8_t frameType, uint8_t frameFlags,
 | |
|                          uint32_t streamID);
 | |
| 
 | |
|   // For writing the data stream to LOG4
 | |
|   static void LogIO(Http2Session *, Http2Stream *, const char *,
 | |
|                     const char *, uint32_t);
 | |
| 
 | |
|   // overload of nsAHttpConnection
 | |
|   void TransactionHasDataToWrite(nsAHttpTransaction *) override;
 | |
|   void TransactionHasDataToRecv(nsAHttpTransaction *) override;
 | |
| 
 | |
|   // a similar version for Http2Stream
 | |
|   void TransactionHasDataToWrite(Http2Stream *);
 | |
| 
 | |
|   // an overload of nsAHttpSegementReader
 | |
|   virtual MOZ_MUST_USE nsresult CommitToSegmentSize(uint32_t size,
 | |
|                                                     bool forceCommitment) override;
 | |
|   MOZ_MUST_USE nsresult BufferOutput(const char *, uint32_t, uint32_t *);
 | |
|   void     FlushOutputQueue();
 | |
|   uint32_t AmountOfOutputBuffered() { return mOutputQueueUsed - mOutputQueueSent; }
 | |
| 
 | |
|   uint32_t GetServerInitialStreamWindow() { return mServerInitialStreamWindow; }
 | |
| 
 | |
|   MOZ_MUST_USE bool TryToActivate(Http2Stream *stream);
 | |
|   void ConnectPushedStream(Http2Stream *stream);
 | |
|   void ConnectSlowConsumer(Http2Stream *stream);
 | |
| 
 | |
|   MOZ_MUST_USE nsresult ConfirmTLSProfile();
 | |
|   static MOZ_MUST_USE bool ALPNCallback(nsISupports *securityInfo);
 | |
| 
 | |
|   uint64_t Serial() { return mSerial; }
 | |
| 
 | |
|   void PrintDiagnostics (nsCString &log) override;
 | |
| 
 | |
|   // Streams need access to these
 | |
|   uint32_t SendingChunkSize() { return mSendingChunkSize; }
 | |
|   uint32_t PushAllowance() { return mPushAllowance; }
 | |
|   Http2Compressor *Compressor() { return &mCompressor; }
 | |
|   nsISocketTransport *SocketTransport() { return mSocketTransport; }
 | |
|   int64_t ServerSessionWindow() { return mServerSessionWindow; }
 | |
|   void DecrementServerSessionWindow (uint32_t bytes) { mServerSessionWindow -= bytes; }
 | |
|   uint32_t InitialRwin() { return mInitialRwin; }
 | |
| 
 | |
|   void SendPing() override;
 | |
|   MOZ_MUST_USE bool MaybeReTunnel(nsAHttpTransaction *) override;
 | |
|   bool UseH2Deps() { return mUseH2Deps; }
 | |
| 
 | |
|   // overload of nsAHttpTransaction
 | |
|   MOZ_MUST_USE nsresult ReadSegmentsAgain(nsAHttpSegmentReader *, uint32_t, uint32_t *, bool *) final;
 | |
|   MOZ_MUST_USE nsresult WriteSegmentsAgain(nsAHttpSegmentWriter *, uint32_t , uint32_t *, bool *) final;
 | |
|   MOZ_MUST_USE bool Do0RTT() final { return true; }
 | |
|   MOZ_MUST_USE nsresult Finish0RTT(bool aRestart, bool aAlpnChanged) final;
 | |
|   void SetFastOpenStatus(uint8_t aStatus) final;
 | |
| 
 | |
|   // For use by an HTTP2Stream
 | |
|   void Received421(nsHttpConnectionInfo *ci);
 | |
| 
 | |
|   void SendPriorityFrame(uint32_t streamID, uint32_t dependsOn, uint8_t weight);
 | |
| 
 | |
| private:
 | |
| 
 | |
|   // These internal states do not correspond to the states of the HTTP/2 specification
 | |
|   enum internalStateType {
 | |
|     BUFFERING_OPENING_SETTINGS,
 | |
|     BUFFERING_FRAME_HEADER,
 | |
|     BUFFERING_CONTROL_FRAME,
 | |
|     PROCESSING_DATA_FRAME_PADDING_CONTROL,
 | |
|     PROCESSING_DATA_FRAME,
 | |
|     DISCARDING_DATA_FRAME_PADDING,
 | |
|     DISCARDING_DATA_FRAME,
 | |
|     PROCESSING_COMPLETE_HEADERS,
 | |
|     PROCESSING_CONTROL_RST_STREAM,
 | |
|     NOT_USING_NETWORK
 | |
|   };
 | |
| 
 | |
|   static const uint8_t kMagicHello[24];
 | |
| 
 | |
|   MOZ_MUST_USE nsresult ResponseHeadersComplete();
 | |
|   uint32_t    GetWriteQueueSize();
 | |
|   void        ChangeDownstreamState(enum internalStateType);
 | |
|   void        ResetDownstreamState();
 | |
|   MOZ_MUST_USE nsresult ReadyToProcessDataFrame(enum internalStateType);
 | |
|   MOZ_MUST_USE nsresult UncompressAndDiscard(bool);
 | |
|   void        GeneratePing(bool);
 | |
|   void        GenerateSettingsAck();
 | |
|   void        GeneratePriority(uint32_t, uint8_t);
 | |
|   void        GenerateRstStream(uint32_t, uint32_t);
 | |
|   void        GenerateGoAway(uint32_t);
 | |
|   void        CleanupStream(Http2Stream *, nsresult, errorType);
 | |
|   void        CleanupStream(uint32_t, nsresult, errorType);
 | |
|   void        CloseStream(Http2Stream *, nsresult);
 | |
|   void        SendHello();
 | |
|   void        RemoveStreamFromQueues(Http2Stream *);
 | |
|   MOZ_MUST_USE nsresult ParsePadding(uint8_t &, uint16_t &);
 | |
| 
 | |
|   void        SetWriteCallbacks();
 | |
|   void        RealignOutputQueue();
 | |
| 
 | |
|   void        ProcessPending();
 | |
|   MOZ_MUST_USE nsresult ProcessConnectedPush(Http2Stream *,
 | |
|                                              nsAHttpSegmentWriter *,
 | |
|                                              uint32_t, uint32_t *);
 | |
|   MOZ_MUST_USE nsresult ProcessSlowConsumer(Http2Stream *,
 | |
|                                             nsAHttpSegmentWriter *,
 | |
|                                             uint32_t, uint32_t *);
 | |
| 
 | |
|   MOZ_MUST_USE nsresult SetInputFrameDataStream(uint32_t);
 | |
|   void        CreatePriorityNode(uint32_t, uint32_t, uint8_t, const char *);
 | |
|   char        *CreatePriorityFrame(uint32_t, uint32_t, uint8_t);
 | |
|   bool        VerifyStream(Http2Stream *, uint32_t);
 | |
|   void        SetNeedsCleanup();
 | |
| 
 | |
|   void        UpdateLocalRwin(Http2Stream *stream, uint32_t bytes);
 | |
|   void        UpdateLocalStreamWindow(Http2Stream *stream, uint32_t bytes);
 | |
|   void        UpdateLocalSessionWindow(uint32_t bytes);
 | |
| 
 | |
|   void        MaybeDecrementConcurrent(Http2Stream *stream);
 | |
|   bool        RoomForMoreConcurrent();
 | |
|   void        IncrementConcurrent(Http2Stream *stream);
 | |
|   void        QueueStream(Http2Stream *stream);
 | |
| 
 | |
|   // a wrapper for all calls to the nshttpconnection level segment writer. Used
 | |
|   // to track network I/O for timeout purposes
 | |
|   MOZ_MUST_USE nsresult NetworkRead(nsAHttpSegmentWriter *, char *, uint32_t, uint32_t *);
 | |
| 
 | |
|   void Shutdown();
 | |
| 
 | |
|   // This is intended to be nsHttpConnectionMgr:nsConnectionHandle taken
 | |
|   // from the first transaction on this session. That object contains the
 | |
|   // pointer to the real network-level nsHttpConnection object.
 | |
|   RefPtr<nsAHttpConnection> mConnection;
 | |
| 
 | |
|   // The underlying socket transport object is needed to propogate some events
 | |
|   nsISocketTransport         *mSocketTransport;
 | |
| 
 | |
|   // These are temporary state variables to hold the argument to
 | |
|   // Read/WriteSegments so it can be accessed by On(read/write)segment
 | |
|   // further up the stack.
 | |
|   nsAHttpSegmentReader       *mSegmentReader;
 | |
|   nsAHttpSegmentWriter       *mSegmentWriter;
 | |
| 
 | |
|   uint32_t          mSendingChunkSize;        /* the transmission chunk size */
 | |
|   uint32_t          mNextStreamID;            /* 24 bits */
 | |
|   uint32_t          mLastPushedID;
 | |
|   uint32_t          mConcurrentHighWater;     /* max parallelism on session */
 | |
|   uint32_t          mPushAllowance;           /* rwin for unmatched pushes */
 | |
| 
 | |
|   internalStateType mDownstreamState; /* in frame, between frames, etc..  */
 | |
| 
 | |
|   // Maintain 2 indexes - one by stream ID, one by transaction pointer.
 | |
|   // There are also several lists of streams: ready to write, queued due to
 | |
|   // max parallelism, streams that need to force a read for push, and the full
 | |
|   // set of pushed streams.
 | |
|   // The objects are not ref counted - they get destroyed
 | |
|   // by the nsClassHashtable implementation when they are removed from
 | |
|   // the transaction hash.
 | |
|   nsDataHashtable<nsUint32HashKey, Http2Stream *>     mStreamIDHash;
 | |
|   nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>,
 | |
|     Http2Stream>                                      mStreamTransactionHash;
 | |
| 
 | |
|   nsDeque                                             mReadyForWrite;
 | |
|   nsDeque                                             mQueuedStreams;
 | |
|   nsDeque                                             mPushesReadyForRead;
 | |
|   nsDeque                                             mSlowConsumersReadyForRead;
 | |
|   nsTArray<Http2PushedStream *>                       mPushedStreams;
 | |
| 
 | |
|   // Compression contexts for header transport.
 | |
|   // HTTP/2 compresses only HTTP headers and does not reset the context in between
 | |
|   // frames. Even data that is not associated with a stream (e.g invalid
 | |
|   // stream ID) is passed through these contexts to keep the compression
 | |
|   // context correct.
 | |
|   Http2Compressor     mCompressor;
 | |
|   Http2Decompressor   mDecompressor;
 | |
|   nsCString           mDecompressBuffer;
 | |
| 
 | |
|   // mInputFrameBuffer is used to store received control packets and the 8 bytes
 | |
|   // of header on data packets
 | |
|   uint32_t             mInputFrameBufferSize; // buffer allocation
 | |
|   uint32_t             mInputFrameBufferUsed; // amt of allocation used
 | |
|   UniquePtr<char[]>    mInputFrameBuffer;
 | |
| 
 | |
|   // mInputFrameDataSize/Read are used for tracking the amount of data consumed
 | |
|   // in a frame after the 8 byte header. Control frames are always fully buffered
 | |
|   // and the fixed 8 byte leading header is at mInputFrameBuffer + 0, the first
 | |
|   // data byte (i.e. the first settings/goaway/etc.. specific byte) is at
 | |
|   // mInputFrameBuffer + 8
 | |
|   // The frame size is mInputFrameDataSize + the constant 8 byte header
 | |
|   uint32_t             mInputFrameDataSize;
 | |
|   uint32_t             mInputFrameDataRead;
 | |
|   bool                 mInputFrameFinal; // This frame was marked FIN
 | |
|   uint8_t              mInputFrameType;
 | |
|   uint8_t              mInputFrameFlags;
 | |
|   uint32_t             mInputFrameID;
 | |
|   uint16_t             mPaddingLength;
 | |
| 
 | |
|   // When a frame has been received that is addressed to a particular stream
 | |
|   // (e.g. a data frame after the stream-id has been decoded), this points
 | |
|   // to the stream.
 | |
|   Http2Stream          *mInputFrameDataStream;
 | |
| 
 | |
|   // mNeedsCleanup is a state variable to defer cleanup of a closed stream
 | |
|   // If needed, It is set in session::OnWriteSegments() and acted on and
 | |
|   // cleared when the stack returns to session::WriteSegments(). The stream
 | |
|   // cannot be destroyed directly out of OnWriteSegments because
 | |
|   // stream::writeSegments() is on the stack at that time.
 | |
|   Http2Stream          *mNeedsCleanup;
 | |
| 
 | |
|   // This reason code in the last processed RESET frame
 | |
|   uint32_t             mDownstreamRstReason;
 | |
| 
 | |
|   // When HEADERS/PROMISE are chained together, this is the expected ID of the next
 | |
|   // recvd frame which must be the same type
 | |
|   uint32_t             mExpectedHeaderID;
 | |
|   uint32_t             mExpectedPushPromiseID;
 | |
|   uint32_t             mContinuedPromiseStream;
 | |
| 
 | |
|   // for the conversion of downstream http headers into http/2 formatted headers
 | |
|   // The data here does not persist between frames
 | |
|   nsCString            mFlatHTTPResponseHeaders;
 | |
|   uint32_t             mFlatHTTPResponseHeadersOut;
 | |
| 
 | |
|   // when set, the session will go away when it reaches 0 streams. This flag
 | |
|   // is set when: the stream IDs are running out (at either the client or the
 | |
|   // server), when DontReuse() is called, a RST that is not specific to a
 | |
|   // particular stream is received, a GOAWAY frame has been received from
 | |
|   // the server.
 | |
|   bool                 mShouldGoAway;
 | |
| 
 | |
|   // the session has received a nsAHttpTransaction::Close()  call
 | |
|   bool                 mClosed;
 | |
| 
 | |
|   // the session received a GoAway frame with a valid GoAwayID
 | |
|   bool                 mCleanShutdown;
 | |
| 
 | |
|   // the session received the opening SETTINGS frame from the server
 | |
|   bool                 mReceivedSettings;
 | |
| 
 | |
|   // The TLS comlpiance checks are not done in the ctor beacuse of bad
 | |
|   // exception handling - so we do them at IO time and cache the result
 | |
|   bool                 mTLSProfileConfirmed;
 | |
| 
 | |
|   // A specifc reason code for the eventual GoAway frame. If set to NO_HTTP_ERROR
 | |
|   // only NO_HTTP_ERROR, PROTOCOL_ERROR, or INTERNAL_ERROR will be sent.
 | |
|   errorType            mGoAwayReason;
 | |
| 
 | |
|   // The error code sent/received on the session goaway frame. UNASSIGNED/31
 | |
|   // if not transmitted.
 | |
|   int32_t             mClientGoAwayReason;
 | |
|   int32_t             mPeerGoAwayReason;
 | |
| 
 | |
|   // If a GoAway message was received this is the ID of the last valid
 | |
|   // stream. 0 otherwise. (0 is never a valid stream id.)
 | |
|   uint32_t             mGoAwayID;
 | |
| 
 | |
|   // The last stream processed ID we will send in our GoAway frame.
 | |
|   uint32_t             mOutgoingGoAwayID;
 | |
| 
 | |
|   // The limit on number of concurrent streams for this session. Normally it
 | |
|   // is basically unlimited, but the SETTINGS control message from the
 | |
|   // server might bring it down.
 | |
|   uint32_t             mMaxConcurrent;
 | |
| 
 | |
|   // The actual number of concurrent streams at this moment. Generally below
 | |
|   // mMaxConcurrent, but the max can be lowered in real time to a value
 | |
|   // below the current value
 | |
|   uint32_t             mConcurrent;
 | |
| 
 | |
|   // The number of server initiated promises, tracked for telemetry
 | |
|   uint32_t             mServerPushedResources;
 | |
| 
 | |
|   // The server rwin for new streams as determined from a SETTINGS frame
 | |
|   uint32_t             mServerInitialStreamWindow;
 | |
| 
 | |
|   // The Local Session window is how much data the server is allowed to send
 | |
|   // (across all streams) without getting a window update to stream 0. It is
 | |
|   // signed because asynchronous changes via SETTINGS can drive it negative.
 | |
|   int64_t              mLocalSessionWindow;
 | |
| 
 | |
|   // The Remote Session Window is how much data the client is allowed to send
 | |
|   // (across all streams) without receiving a window update to stream 0. It is
 | |
|   // signed because asynchronous changes via SETTINGS can drive it negative.
 | |
|   int64_t              mServerSessionWindow;
 | |
| 
 | |
|   // The initial value of the local stream and session window
 | |
|   uint32_t             mInitialRwin;
 | |
| 
 | |
|   // This is a output queue of bytes ready to be written to the SSL stream.
 | |
|   // When that streams returns WOULD_BLOCK on direct write the bytes get
 | |
|   // coalesced together here. This results in larger writes to the SSL layer.
 | |
|   // The buffer is not dynamically grown to accomodate stream writes, but
 | |
|   // does expand to accept infallible session wide frames like GoAway and RST.
 | |
|   uint32_t             mOutputQueueSize;
 | |
|   uint32_t             mOutputQueueUsed;
 | |
|   uint32_t             mOutputQueueSent;
 | |
|   UniquePtr<char[]>    mOutputQueueBuffer;
 | |
| 
 | |
|   PRIntervalTime       mPingThreshold;
 | |
|   PRIntervalTime       mLastReadEpoch;     // used for ping timeouts
 | |
|   PRIntervalTime       mLastDataReadEpoch; // used for IdleTime()
 | |
|   PRIntervalTime       mPingSentEpoch;
 | |
| 
 | |
|   PRIntervalTime       mPreviousPingThreshold; // backup for the former value
 | |
|   bool                 mPreviousUsed;          // true when backup is used
 | |
| 
 | |
|   // used as a temporary buffer while enumerating the stream hash during GoAway
 | |
|   nsDeque  mGoAwayStreamsToRestart;
 | |
| 
 | |
|   // Each session gets a unique serial number because the push cache is correlated
 | |
|   // by the load group and the serial number can be used as part of the cache key
 | |
|   // to make sure streams aren't shared across sessions.
 | |
|   uint64_t        mSerial;
 | |
| 
 | |
|   // Telemetry for continued headers (pushed and pulled) for quic design
 | |
|   uint32_t        mAggregatedHeaderSize;
 | |
| 
 | |
|   // If push is disabled, we want to be able to send PROTOCOL_ERRORs if we
 | |
|   // receive a PUSH_PROMISE, but we have to wait for the SETTINGS ACK before
 | |
|   // we can actually tell the other end to go away. These help us keep track
 | |
|   // of that state so we can behave appropriately.
 | |
|   bool mWaitingForSettingsAck;
 | |
|   bool mGoAwayOnPush;
 | |
| 
 | |
|   bool mUseH2Deps;
 | |
| 
 | |
|   bool mAttemptingEarlyData;
 | |
|   // The ID(s) of the stream(s) that we are getting 0RTT data from.
 | |
|   nsTArray<WeakPtr<Http2Stream>> m0RTTStreams;
 | |
|   // The ID(s) of the stream(s) that are not able to send 0RTT data. We need to
 | |
|   // remember them put them into mReadyForWrite queue when 0RTT finishes.
 | |
|   nsTArray<WeakPtr<Http2Stream>> mCannotDo0RTTStreams;
 | |
| 
 | |
|   bool RealJoinConnection(const nsACString &hostname, int32_t port, bool jk);
 | |
|   bool TestOriginFrame(const nsACString &name, int32_t port);
 | |
|   bool mOriginFrameActivated;
 | |
|   nsDataHashtable<nsCStringHashKey, bool> mOriginFrame;
 | |
| 
 | |
|   nsDataHashtable<nsCStringHashKey, bool> mJoinConnectionCache;
 | |
| 
 | |
|   uint64_t mCurrentForegroundTabOuterContentWindowId;
 | |
| 
 | |
|   class CachePushCheckCallback final : public nsICacheEntryOpenCallback
 | |
|   {
 | |
|   public:
 | |
|     CachePushCheckCallback(Http2Session *session, uint32_t promisedID, const nsACString &requestString);
 | |
| 
 | |
|     NS_DECL_ISUPPORTS
 | |
|     NS_DECL_NSICACHEENTRYOPENCALLBACK
 | |
| 
 | |
|   private:
 | |
|     ~CachePushCheckCallback() { }
 | |
| 
 | |
|     RefPtr<Http2Session> mSession;
 | |
|     uint32_t mPromisedID;
 | |
|     nsHttpRequestHead mRequestHead;
 | |
|   };
 | |
| 
 | |
|   // A h2 session will be created before all socket events are trigered,
 | |
|   // e.g. NS_NET_STATUS_TLS_HANDSHAKE_ENDED and for TFO many others.
 | |
|   // We should propagate this events to the first nsHttpTransaction.
 | |
|   RefPtr<nsHttpTransaction> mFirstHttpTransaction;
 | |
|   bool mTlsHandshakeFinished;
 | |
| 
 | |
|   bool mCheckNetworkStallsWithTFO;
 | |
|   PRIntervalTime mLastRequestBytesSentTime;
 | |
| private:
 | |
| /// connect tunnels
 | |
|   void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);
 | |
|   void CreateTunnel(nsHttpTransaction *, nsHttpConnectionInfo *, nsIInterfaceRequestor *);
 | |
|   void RegisterTunnel(Http2Stream *);
 | |
|   void UnRegisterTunnel(Http2Stream *);
 | |
|   uint32_t FindTunnelCount(nsHttpConnectionInfo *);
 | |
|   nsDataHashtable<nsCStringHashKey, uint32_t> mTunnelHash;
 | |
| };
 | |
| 
 | |
| } // namespace net
 | |
| } // namespace mozilla
 | |
| 
 | |
| #endif // mozilla_net_Http2Session_h
 |