diff options
Diffstat (limited to '')
-rw-r--r-- | netwerk/protocol/http/Http2Session.h | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/netwerk/protocol/http/Http2Session.h b/netwerk/protocol/http/Http2Session.h new file mode 100644 index 0000000000..767e5cf9f7 --- /dev/null +++ b/netwerk/protocol/http/Http2Session.h @@ -0,0 +1,626 @@ +/* -*- 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 "nsCOMArray.h" +#include "nsRefPtrHashtable.h" +#include "nsTHashMap.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 Http2StreamBase; +class Http2StreamTunnel; +class nsHttpTransaction; +class nsHttpConnection; + +enum Http2StreamBaseType { Normal, WebSocket, Tunnel, ServerPush }; + +// b23b147c-c4f8-4d6e-841a-09f29a010de7 +#define NS_HTTP2SESSION_IID \ + { \ + 0xb23b147c, 0xc4f8, 0x4d6e, { \ + 0x84, 0x1a, 0x09, 0xf2, 0x9a, 0x01, 0x0d, 0xe7 \ + } \ + } + +class Http2Session final : public ASpdySession, + public nsAHttpConnection, + public nsAHttpSegmentReader, + public nsAHttpSegmentWriter { + ~Http2Session(); + + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_HTTP2SESSION_IID) + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSAHTTPTRANSACTION + NS_DECL_NSAHTTPCONNECTION(mConnection) + NS_DECL_NSAHTTPSEGMENTREADER + NS_DECL_NSAHTTPSEGMENTWRITER + + static Http2Session* CreateSession(nsISocketTransport*, + enum SpdyVersion version, + bool attemptingEarlyData); + + [[nodiscard]] bool AddStream(nsAHttpTransaction*, int32_t, + nsIInterfaceRequestor*) override; + bool CanReuse() override { return !mShouldGoAway && !mClosed; } + bool RoomForMoreStreams() override; + enum SpdyVersion 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(Http2StreamBase*, 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 + // 6 is SETTINGS_TYPE_MAX_HEADER_LIST - advisory, we ignore it + // 7 is unassigned + SETTINGS_TYPE_ENABLE_CONNECT_PROTOCOL = + 8 // if sender implements extended CONNECT for websockets + }; + + // 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*, Http2StreamBase*, const char*, const char*, + uint32_t); + + // overload of nsAHttpConnection + void TransactionHasDataToWrite(nsAHttpTransaction*) override; + void TransactionHasDataToRecv(nsAHttpTransaction*) override; + + // a similar version for Http2StreamBase + void TransactionHasDataToWrite(Http2StreamBase*); + void TransactionHasDataToRecv(Http2StreamBase* caller); + + // an overload of nsAHttpSegementReader + [[nodiscard]] virtual nsresult CommitToSegmentSize( + uint32_t count, bool forceCommitment) override; + [[nodiscard]] nsresult BufferOutput(const char*, uint32_t, uint32_t*); + void FlushOutputQueue(); + uint32_t AmountOfOutputBuffered() { + return mOutputQueueUsed - mOutputQueueSent; + } + + uint32_t GetServerInitialStreamWindow() { return mServerInitialStreamWindow; } + + [[nodiscard]] bool TryToActivate(Http2StreamBase* stream); + void ConnectPushedStream(Http2StreamBase* stream); + void ConnectSlowConsumer(Http2StreamBase* stream); + + [[nodiscard]] nsresult ConfirmTLSProfile(); + [[nodiscard]] static bool ALPNCallback(nsITLSSocketControl* tlsSocketControl); + + 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; + bool UseH2Deps() { return mUseH2Deps; } + void SetCleanShutdown(bool) override; + + // overload of nsAHttpTransaction + [[nodiscard]] nsresult ReadSegmentsAgain(nsAHttpSegmentReader*, uint32_t, + uint32_t*, bool*) final; + [[nodiscard]] nsresult WriteSegmentsAgain(nsAHttpSegmentWriter*, uint32_t, + uint32_t*, bool*) final; + [[nodiscard]] bool Do0RTT() final { return true; } + [[nodiscard]] nsresult Finish0RTT(bool aRestart, bool aAlpnChanged) final; + + // For use by an HTTP2Stream + void Received421(nsHttpConnectionInfo* ci); + + void SendPriorityFrame(uint32_t streamID, uint32_t dependsOn, uint8_t weight); + void IncrementTrrCounter() { mTrrStreams++; } + + WebSocketSupport GetWebSocketSupport() override; + + already_AddRefed<nsHttpConnection> CreateTunnelStream( + nsAHttpTransaction* aHttpTransaction, nsIInterfaceRequestor* aCallbacks, + PRIntervalTime aRtt, bool aIsWebSocket = false) override; + + void CleanupStream(Http2StreamBase*, nsresult, errorType); + + private: + Http2Session(nsISocketTransport*, enum SpdyVersion version, + bool attemptingEarlyData); + + static Http2StreamTunnel* CreateTunnelStreamFromConnInfo( + Http2Session* session, uint64_t bcId, nsHttpConnectionInfo* connInfo, + bool isWebSocket); + + // 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]; + + void CreateStream(nsAHttpTransaction* aHttpTransaction, int32_t aPriority, + Http2StreamBaseType streamType); + + [[nodiscard]] nsresult ResponseHeadersComplete(); + uint32_t GetWriteQueueSize(); + void ChangeDownstreamState(enum internalStateType); + void ResetDownstreamState(); + [[nodiscard]] nsresult ReadyToProcessDataFrame(enum internalStateType); + [[nodiscard]] 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(uint32_t, nsresult, errorType); + void CloseStream(Http2StreamBase* aStream, nsresult aResult, + bool aRemoveFromQueue = true); + void SendHello(); + void RemoveStreamFromQueues(Http2StreamBase*); + [[nodiscard]] nsresult ParsePadding(uint8_t&, uint16_t&); + + void SetWriteCallbacks(); + void RealignOutputQueue(); + + void ProcessPending(); + [[nodiscard]] nsresult ProcessConnectedPush(Http2StreamBase*, + nsAHttpSegmentWriter*, uint32_t, + uint32_t*); + [[nodiscard]] nsresult ProcessSlowConsumer(Http2StreamBase*, + nsAHttpSegmentWriter*, uint32_t, + uint32_t*); + + [[nodiscard]] nsresult SetInputFrameDataStream(uint32_t); + void CreatePriorityNode(uint32_t, uint32_t, uint8_t, const char*); + char* CreatePriorityFrame(uint32_t, uint32_t, uint8_t); + bool VerifyStream(Http2StreamBase*, uint32_t); + void SetNeedsCleanup(); + + void UpdateLocalRwin(Http2StreamBase* stream, uint32_t bytes); + void UpdateLocalStreamWindow(Http2StreamBase* stream, uint32_t bytes); + void UpdateLocalSessionWindow(uint32_t bytes); + + void MaybeDecrementConcurrent(Http2StreamBase* stream); + bool RoomForMoreConcurrent(); + void IncrementConcurrent(Http2StreamBase* stream); + void QueueStream(Http2StreamBase* stream); + + // a wrapper for all calls to the nshttpconnection level segment writer. Used + // to track network I/O for timeout purposes + [[nodiscard]] nsresult NetworkRead(nsAHttpSegmentWriter*, char*, uint32_t, + uint32_t*); + + void Shutdown(nsresult aReason); + void ShutdownStream(Http2StreamBase* aStream, nsresult aResult); + + nsresult SessionError(enum errorType); + + // 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. + RefPtr<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. + nsTHashMap<nsUint32HashKey, Http2StreamBase*> mStreamIDHash; + nsRefPtrHashtable<nsPtrHashKey<nsAHttpTransaction>, Http2StreamBase> + mStreamTransactionHash; + nsTArray<RefPtr<Http2StreamTunnel>> mTunnelStreams; + + nsTArray<WeakPtr<Http2StreamBase>> mReadyForWrite; + nsTArray<WeakPtr<Http2StreamBase>> mQueuedStreams; + nsTArray<WeakPtr<Http2StreamBase>> mPushesReadyForRead; + nsTArray<WeakPtr<Http2StreamBase>> 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. + Http2StreamBase* 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. + Http2StreamBase* 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<Http2StreamBase> 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<Http2StreamBase>> 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<Http2StreamBase>> mCannotDo0RTTStreams; + + bool RealJoinConnection(const nsACString& hostname, int32_t port, + bool justKidding); + bool TestOriginFrame(const nsACString& name, int32_t port); + bool mOriginFrameActivated; + nsTHashMap<nsCStringHashKey, bool> mOriginFrame; + + nsTHashMap<nsCStringHashKey, bool> mJoinConnectionCache; + + uint64_t mCurrentBrowserId; + + uint32_t mCntActivated; + + // A h2 session will be created before all socket events are trigered, + // e.g. NS_NET_STATUS_TLS_HANDSHAKE_ENDED. + // We should propagate this events to the first nsHttpTransaction. + RefPtr<nsHttpTransaction> mFirstHttpTransaction; + bool mTlsHandshakeFinished; + + bool mPeerFailedHandshake; + + private: + uint32_t mTrrStreams; + + // websockets + bool mEnableWebsockets; // Whether we allow websockets, based on a pref + bool mPeerAllowsWebsockets; // Whether our peer allows websockets, based on + // SETTINGS + bool mProcessedWaitingWebsockets; // True once we've received at least one + // SETTINGS + // Setting this to true means there is a transaction waiting for the result of + // WebSocket support. We'll need to process the pending queue once we've + // received the settings. + bool mHasTransactionWaitingForWebsockets = false; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(Http2Session, NS_HTTP2SESSION_IID); + +} // namespace net +} // namespace mozilla + +#endif // mozilla_net_Http2Session_h |