Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef mozilla_net_Http2Session_h |
michael@0 | 7 | #define mozilla_net_Http2Session_h |
michael@0 | 8 | |
michael@0 | 9 | // HTTP/2 |
michael@0 | 10 | |
michael@0 | 11 | #include "ASpdySession.h" |
michael@0 | 12 | #include "mozilla/Attributes.h" |
michael@0 | 13 | #include "nsAHttpConnection.h" |
michael@0 | 14 | #include "nsClassHashtable.h" |
michael@0 | 15 | #include "nsDataHashtable.h" |
michael@0 | 16 | #include "nsDeque.h" |
michael@0 | 17 | #include "nsHashKeys.h" |
michael@0 | 18 | |
michael@0 | 19 | #include "Http2Compression.h" |
michael@0 | 20 | |
michael@0 | 21 | class nsISocketTransport; |
michael@0 | 22 | |
michael@0 | 23 | namespace mozilla { |
michael@0 | 24 | namespace net { |
michael@0 | 25 | |
michael@0 | 26 | class Http2PushedStream; |
michael@0 | 27 | class Http2Stream; |
michael@0 | 28 | |
michael@0 | 29 | class Http2Session MOZ_FINAL : public ASpdySession |
michael@0 | 30 | , public nsAHttpConnection |
michael@0 | 31 | , public nsAHttpSegmentReader |
michael@0 | 32 | , public nsAHttpSegmentWriter |
michael@0 | 33 | { |
michael@0 | 34 | public: |
michael@0 | 35 | NS_DECL_ISUPPORTS |
michael@0 | 36 | NS_DECL_NSAHTTPTRANSACTION |
michael@0 | 37 | NS_DECL_NSAHTTPCONNECTION(mConnection) |
michael@0 | 38 | NS_DECL_NSAHTTPSEGMENTREADER |
michael@0 | 39 | NS_DECL_NSAHTTPSEGMENTWRITER |
michael@0 | 40 | |
michael@0 | 41 | Http2Session(nsAHttpTransaction *, nsISocketTransport *, int32_t); |
michael@0 | 42 | ~Http2Session(); |
michael@0 | 43 | |
michael@0 | 44 | bool AddStream(nsAHttpTransaction *, int32_t); |
michael@0 | 45 | bool CanReuse() { return !mShouldGoAway && !mClosed; } |
michael@0 | 46 | bool RoomForMoreStreams(); |
michael@0 | 47 | |
michael@0 | 48 | // When the connection is active this is called up to once every 1 second |
michael@0 | 49 | // return the interval (in seconds) that the connection next wants to |
michael@0 | 50 | // have this invoked. It might happen sooner depending on the needs of |
michael@0 | 51 | // other connections. |
michael@0 | 52 | uint32_t ReadTimeoutTick(PRIntervalTime now); |
michael@0 | 53 | |
michael@0 | 54 | // Idle time represents time since "goodput".. e.g. a data or header frame |
michael@0 | 55 | PRIntervalTime IdleTime(); |
michael@0 | 56 | |
michael@0 | 57 | // Registering with a newID of 0 means pick the next available odd ID |
michael@0 | 58 | uint32_t RegisterStreamID(Http2Stream *, uint32_t aNewID = 0); |
michael@0 | 59 | |
michael@0 | 60 | /* |
michael@0 | 61 | HTTP/2 framing |
michael@0 | 62 | |
michael@0 | 63 | 0 1 2 3 |
michael@0 | 64 | 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 |
michael@0 | 65 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
michael@0 | 66 | | Length (16) | Type (8) | Flags (8) | |
michael@0 | 67 | +-+-------------+---------------+-------------------------------+ |
michael@0 | 68 | |R| Stream Identifier (31) | |
michael@0 | 69 | +-+-------------------------------------------------------------+ |
michael@0 | 70 | | Frame Data (0...) ... |
michael@0 | 71 | +---------------------------------------------------------------+ |
michael@0 | 72 | */ |
michael@0 | 73 | |
michael@0 | 74 | enum frameType { |
michael@0 | 75 | FRAME_TYPE_DATA = 0, |
michael@0 | 76 | FRAME_TYPE_HEADERS = 1, |
michael@0 | 77 | FRAME_TYPE_PRIORITY = 2, |
michael@0 | 78 | FRAME_TYPE_RST_STREAM = 3, |
michael@0 | 79 | FRAME_TYPE_SETTINGS = 4, |
michael@0 | 80 | FRAME_TYPE_PUSH_PROMISE = 5, |
michael@0 | 81 | FRAME_TYPE_PING = 6, |
michael@0 | 82 | FRAME_TYPE_GOAWAY = 7, |
michael@0 | 83 | FRAME_TYPE_WINDOW_UPDATE = 8, |
michael@0 | 84 | FRAME_TYPE_CONTINUATION = 9, |
michael@0 | 85 | FRAME_TYPE_LAST = 10 |
michael@0 | 86 | }; |
michael@0 | 87 | |
michael@0 | 88 | // NO_ERROR is a macro defined on windows, so we'll name the HTTP2 goaway |
michael@0 | 89 | // code NO_ERROR to be NO_HTTP_ERROR |
michael@0 | 90 | enum errorType { |
michael@0 | 91 | NO_HTTP_ERROR = 0, |
michael@0 | 92 | PROTOCOL_ERROR = 1, |
michael@0 | 93 | INTERNAL_ERROR = 2, |
michael@0 | 94 | FLOW_CONTROL_ERROR = 3, |
michael@0 | 95 | SETTINGS_TIMEOUT_ERROR = 4, |
michael@0 | 96 | STREAM_CLOSED_ERROR = 5, |
michael@0 | 97 | FRAME_SIZE_ERROR = 6, |
michael@0 | 98 | REFUSED_STREAM_ERROR = 7, |
michael@0 | 99 | CANCEL_ERROR = 8, |
michael@0 | 100 | COMPRESSION_ERROR = 9, |
michael@0 | 101 | CONNECT_ERROR = 10, |
michael@0 | 102 | ENHANCE_YOUR_CALM = 11, |
michael@0 | 103 | INADEQUATE_SECURITY = 12 |
michael@0 | 104 | }; |
michael@0 | 105 | |
michael@0 | 106 | // These are frame flags. If they, or other undefined flags, are |
michael@0 | 107 | // used on frames other than the comments indicate they MUST be ignored. |
michael@0 | 108 | const static uint8_t kFlag_END_STREAM = 0x01; // data, headers |
michael@0 | 109 | const static uint8_t kFlag_END_HEADERS = 0x04; // headers, continuation |
michael@0 | 110 | const static uint8_t kFlag_PRIORITY = 0x08; //headers |
michael@0 | 111 | const static uint8_t kFlag_END_PUSH_PROMISE = 0x04; // push promise |
michael@0 | 112 | const static uint8_t kFlag_ACK = 0x01; // ping and settings |
michael@0 | 113 | const static uint8_t kFlag_END_SEGMENT = 0x02; // data |
michael@0 | 114 | const static uint8_t kFlag_PAD_LOW = 0x10; // data, headers, continuation |
michael@0 | 115 | const static uint8_t kFlag_PAD_HIGH = 0x20; // data, headers, continuation |
michael@0 | 116 | |
michael@0 | 117 | enum { |
michael@0 | 118 | SETTINGS_TYPE_HEADER_TABLE_SIZE = 1, // compression table size |
michael@0 | 119 | SETTINGS_TYPE_ENABLE_PUSH = 2, // can be used to disable push |
michael@0 | 120 | SETTINGS_TYPE_MAX_CONCURRENT = 3, // streams recvr allowed to initiate |
michael@0 | 121 | SETTINGS_TYPE_INITIAL_WINDOW = 4 // bytes for flow control default |
michael@0 | 122 | }; |
michael@0 | 123 | |
michael@0 | 124 | // This should be big enough to hold all of your control packets, |
michael@0 | 125 | // but if it needs to grow for huge headers it can do so dynamically. |
michael@0 | 126 | const static uint32_t kDefaultBufferSize = 2048; |
michael@0 | 127 | |
michael@0 | 128 | // kDefaultQueueSize must be >= other queue size constants |
michael@0 | 129 | const static uint32_t kDefaultQueueSize = 32768; |
michael@0 | 130 | const static uint32_t kQueueMinimumCleanup = 24576; |
michael@0 | 131 | const static uint32_t kQueueTailRoom = 4096; |
michael@0 | 132 | const static uint32_t kQueueReserved = 1024; |
michael@0 | 133 | |
michael@0 | 134 | const static uint32_t kDefaultMaxConcurrent = 100; |
michael@0 | 135 | const static uint32_t kMaxStreamID = 0x7800000; |
michael@0 | 136 | |
michael@0 | 137 | // This is a sentinel for a deleted stream. It is not a valid |
michael@0 | 138 | // 31 bit stream ID. |
michael@0 | 139 | const static uint32_t kDeadStreamID = 0xffffdead; |
michael@0 | 140 | |
michael@0 | 141 | // below the emergency threshold of local window we ack every received |
michael@0 | 142 | // byte. Above that we coalesce bytes into the MinimumToAck size. |
michael@0 | 143 | const static int32_t kEmergencyWindowThreshold = 256 * 1024; |
michael@0 | 144 | const static uint32_t kMinimumToAck = 4 * 1024 * 1024; |
michael@0 | 145 | |
michael@0 | 146 | // The default rwin is 64KB - 1 unless updated by a settings frame |
michael@0 | 147 | const static uint32_t kDefaultRwin = 65535; |
michael@0 | 148 | |
michael@0 | 149 | // Frames with HTTP semantics are limited to 2^14 - 1 bytes of length in |
michael@0 | 150 | // order to preserve responsiveness |
michael@0 | 151 | const static uint32_t kMaxFrameData = 16383; |
michael@0 | 152 | |
michael@0 | 153 | static nsresult RecvHeaders(Http2Session *); |
michael@0 | 154 | static nsresult RecvPriority(Http2Session *); |
michael@0 | 155 | static nsresult RecvRstStream(Http2Session *); |
michael@0 | 156 | static nsresult RecvSettings(Http2Session *); |
michael@0 | 157 | static nsresult RecvPushPromise(Http2Session *); |
michael@0 | 158 | static nsresult RecvPing(Http2Session *); |
michael@0 | 159 | static nsresult RecvGoAway(Http2Session *); |
michael@0 | 160 | static nsresult RecvWindowUpdate(Http2Session *); |
michael@0 | 161 | static nsresult RecvContinuation(Http2Session *); |
michael@0 | 162 | |
michael@0 | 163 | template<typename T> |
michael@0 | 164 | static void EnsureBuffer(nsAutoArrayPtr<T> &, |
michael@0 | 165 | uint32_t, uint32_t, uint32_t &); |
michael@0 | 166 | char *EnsureOutputBuffer(uint32_t needed); |
michael@0 | 167 | |
michael@0 | 168 | template<typename charType> |
michael@0 | 169 | void CreateFrameHeader(charType dest, uint16_t frameLength, |
michael@0 | 170 | uint8_t frameType, uint8_t frameFlags, |
michael@0 | 171 | uint32_t streamID); |
michael@0 | 172 | |
michael@0 | 173 | // For writing the data stream to LOG4 |
michael@0 | 174 | static void LogIO(Http2Session *, Http2Stream *, const char *, |
michael@0 | 175 | const char *, uint32_t); |
michael@0 | 176 | |
michael@0 | 177 | // an overload of nsAHttpConnection |
michael@0 | 178 | void TransactionHasDataToWrite(nsAHttpTransaction *); |
michael@0 | 179 | |
michael@0 | 180 | // a similar version for Http2Stream |
michael@0 | 181 | void TransactionHasDataToWrite(Http2Stream *); |
michael@0 | 182 | |
michael@0 | 183 | // an overload of nsAHttpSegementReader |
michael@0 | 184 | virtual nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment); |
michael@0 | 185 | nsresult BufferOutput(const char *, uint32_t, uint32_t *); |
michael@0 | 186 | void FlushOutputQueue(); |
michael@0 | 187 | uint32_t AmountOfOutputBuffered() { return mOutputQueueUsed - mOutputQueueSent; } |
michael@0 | 188 | |
michael@0 | 189 | uint32_t GetServerInitialStreamWindow() { return mServerInitialStreamWindow; } |
michael@0 | 190 | |
michael@0 | 191 | void ConnectPushedStream(Http2Stream *stream); |
michael@0 | 192 | void MaybeDecrementConcurrent(Http2Stream *stream); |
michael@0 | 193 | |
michael@0 | 194 | nsresult ConfirmTLSProfile(); |
michael@0 | 195 | |
michael@0 | 196 | uint64_t Serial() { return mSerial; } |
michael@0 | 197 | |
michael@0 | 198 | void PrintDiagnostics (nsCString &log); |
michael@0 | 199 | |
michael@0 | 200 | // Streams need access to these |
michael@0 | 201 | uint32_t SendingChunkSize() { return mSendingChunkSize; } |
michael@0 | 202 | uint32_t PushAllowance() { return mPushAllowance; } |
michael@0 | 203 | Http2Compressor *Compressor() { return &mCompressor; } |
michael@0 | 204 | nsISocketTransport *SocketTransport() { return mSocketTransport; } |
michael@0 | 205 | int64_t ServerSessionWindow() { return mServerSessionWindow; } |
michael@0 | 206 | void DecrementServerSessionWindow (uint32_t bytes) { mServerSessionWindow -= bytes; } |
michael@0 | 207 | |
michael@0 | 208 | private: |
michael@0 | 209 | |
michael@0 | 210 | // These internal states do not correspond to the states of the HTTP/2 specification |
michael@0 | 211 | enum internalStateType { |
michael@0 | 212 | BUFFERING_OPENING_SETTINGS, |
michael@0 | 213 | BUFFERING_FRAME_HEADER, |
michael@0 | 214 | BUFFERING_CONTROL_FRAME, |
michael@0 | 215 | PROCESSING_DATA_FRAME_PADDING_CONTROL, |
michael@0 | 216 | PROCESSING_DATA_FRAME, |
michael@0 | 217 | DISCARDING_DATA_FRAME_PADDING, |
michael@0 | 218 | DISCARDING_DATA_FRAME, |
michael@0 | 219 | PROCESSING_COMPLETE_HEADERS, |
michael@0 | 220 | PROCESSING_CONTROL_RST_STREAM |
michael@0 | 221 | }; |
michael@0 | 222 | |
michael@0 | 223 | static const uint8_t kMagicHello[24]; |
michael@0 | 224 | |
michael@0 | 225 | nsresult ResponseHeadersComplete(); |
michael@0 | 226 | uint32_t GetWriteQueueSize(); |
michael@0 | 227 | void ChangeDownstreamState(enum internalStateType); |
michael@0 | 228 | void ResetDownstreamState(); |
michael@0 | 229 | nsresult ReadyToProcessDataFrame(enum internalStateType); |
michael@0 | 230 | nsresult UncompressAndDiscard(); |
michael@0 | 231 | void GeneratePing(bool); |
michael@0 | 232 | void GenerateSettingsAck(); |
michael@0 | 233 | void GeneratePriority(uint32_t, uint32_t); |
michael@0 | 234 | void GenerateRstStream(uint32_t, uint32_t); |
michael@0 | 235 | void GenerateGoAway(uint32_t); |
michael@0 | 236 | void CleanupStream(Http2Stream *, nsresult, errorType); |
michael@0 | 237 | void CloseStream(Http2Stream *, nsresult); |
michael@0 | 238 | void SendHello(); |
michael@0 | 239 | void RemoveStreamFromQueues(Http2Stream *); |
michael@0 | 240 | nsresult ParsePadding(uint8_t &, uint16_t &); |
michael@0 | 241 | |
michael@0 | 242 | void SetWriteCallbacks(); |
michael@0 | 243 | void RealignOutputQueue(); |
michael@0 | 244 | |
michael@0 | 245 | bool RoomForMoreConcurrent(); |
michael@0 | 246 | void ActivateStream(Http2Stream *); |
michael@0 | 247 | void ProcessPending(); |
michael@0 | 248 | nsresult SetInputFrameDataStream(uint32_t); |
michael@0 | 249 | bool VerifyStream(Http2Stream *, uint32_t); |
michael@0 | 250 | void SetNeedsCleanup(); |
michael@0 | 251 | |
michael@0 | 252 | void UpdateLocalRwin(Http2Stream *stream, uint32_t bytes); |
michael@0 | 253 | void UpdateLocalStreamWindow(Http2Stream *stream, uint32_t bytes); |
michael@0 | 254 | void UpdateLocalSessionWindow(uint32_t bytes); |
michael@0 | 255 | |
michael@0 | 256 | // a wrapper for all calls to the nshttpconnection level segment writer. Used |
michael@0 | 257 | // to track network I/O for timeout purposes |
michael@0 | 258 | nsresult NetworkRead(nsAHttpSegmentWriter *, char *, uint32_t, uint32_t *); |
michael@0 | 259 | |
michael@0 | 260 | static PLDHashOperator ShutdownEnumerator(nsAHttpTransaction *, |
michael@0 | 261 | nsAutoPtr<Http2Stream> &, |
michael@0 | 262 | void *); |
michael@0 | 263 | |
michael@0 | 264 | static PLDHashOperator GoAwayEnumerator(nsAHttpTransaction *, |
michael@0 | 265 | nsAutoPtr<Http2Stream> &, |
michael@0 | 266 | void *); |
michael@0 | 267 | |
michael@0 | 268 | static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *, |
michael@0 | 269 | nsAutoPtr<Http2Stream> &, |
michael@0 | 270 | void *); |
michael@0 | 271 | |
michael@0 | 272 | static PLDHashOperator RestartBlockedOnRwinEnumerator(nsAHttpTransaction *, |
michael@0 | 273 | nsAutoPtr<Http2Stream> &, |
michael@0 | 274 | void *); |
michael@0 | 275 | |
michael@0 | 276 | // This is intended to be nsHttpConnectionMgr:nsConnectionHandle taken |
michael@0 | 277 | // from the first transaction on this session. That object contains the |
michael@0 | 278 | // pointer to the real network-level nsHttpConnection object. |
michael@0 | 279 | nsRefPtr<nsAHttpConnection> mConnection; |
michael@0 | 280 | |
michael@0 | 281 | // The underlying socket transport object is needed to propogate some events |
michael@0 | 282 | nsISocketTransport *mSocketTransport; |
michael@0 | 283 | |
michael@0 | 284 | // These are temporary state variables to hold the argument to |
michael@0 | 285 | // Read/WriteSegments so it can be accessed by On(read/write)segment |
michael@0 | 286 | // further up the stack. |
michael@0 | 287 | nsAHttpSegmentReader *mSegmentReader; |
michael@0 | 288 | nsAHttpSegmentWriter *mSegmentWriter; |
michael@0 | 289 | |
michael@0 | 290 | uint32_t mSendingChunkSize; /* the transmission chunk size */ |
michael@0 | 291 | uint32_t mNextStreamID; /* 24 bits */ |
michael@0 | 292 | uint32_t mConcurrentHighWater; /* max parallelism on session */ |
michael@0 | 293 | uint32_t mPushAllowance; /* rwin for unmatched pushes */ |
michael@0 | 294 | |
michael@0 | 295 | internalStateType mDownstreamState; /* in frame, between frames, etc.. */ |
michael@0 | 296 | |
michael@0 | 297 | // Maintain 2 indexes - one by stream ID, one by transaction pointer. |
michael@0 | 298 | // There are also several lists of streams: ready to write, queued due to |
michael@0 | 299 | // max parallelism, streams that need to force a read for push, and the full |
michael@0 | 300 | // set of pushed streams. |
michael@0 | 301 | // The objects are not ref counted - they get destroyed |
michael@0 | 302 | // by the nsClassHashtable implementation when they are removed from |
michael@0 | 303 | // the transaction hash. |
michael@0 | 304 | nsDataHashtable<nsUint32HashKey, Http2Stream *> mStreamIDHash; |
michael@0 | 305 | nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>, |
michael@0 | 306 | Http2Stream> mStreamTransactionHash; |
michael@0 | 307 | |
michael@0 | 308 | nsDeque mReadyForWrite; |
michael@0 | 309 | nsDeque mQueuedStreams; |
michael@0 | 310 | nsDeque mReadyForRead; |
michael@0 | 311 | nsTArray<Http2PushedStream *> mPushedStreams; |
michael@0 | 312 | |
michael@0 | 313 | // Compression contexts for header transport. |
michael@0 | 314 | // HTTP/2 compresses only HTTP headers and does not reset the context in between |
michael@0 | 315 | // frames. Even data that is not associated with a stream (e.g invalid |
michael@0 | 316 | // stream ID) is passed through these contexts to keep the compression |
michael@0 | 317 | // context correct. |
michael@0 | 318 | Http2Compressor mCompressor; |
michael@0 | 319 | Http2Decompressor mDecompressor; |
michael@0 | 320 | nsCString mDecompressBuffer; |
michael@0 | 321 | |
michael@0 | 322 | // mInputFrameBuffer is used to store received control packets and the 8 bytes |
michael@0 | 323 | // of header on data packets |
michael@0 | 324 | uint32_t mInputFrameBufferSize; // buffer allocation |
michael@0 | 325 | uint32_t mInputFrameBufferUsed; // amt of allocation used |
michael@0 | 326 | nsAutoArrayPtr<char> mInputFrameBuffer; |
michael@0 | 327 | |
michael@0 | 328 | // mInputFrameDataSize/Read are used for tracking the amount of data consumed |
michael@0 | 329 | // in a frame after the 8 byte header. Control frames are always fully buffered |
michael@0 | 330 | // and the fixed 8 byte leading header is at mInputFrameBuffer + 0, the first |
michael@0 | 331 | // data byte (i.e. the first settings/goaway/etc.. specific byte) is at |
michael@0 | 332 | // mInputFrameBuffer + 8 |
michael@0 | 333 | // The frame size is mInputFrameDataSize + the constant 8 byte header |
michael@0 | 334 | uint32_t mInputFrameDataSize; |
michael@0 | 335 | uint32_t mInputFrameDataRead; |
michael@0 | 336 | bool mInputFrameFinal; // This frame was marked FIN |
michael@0 | 337 | uint8_t mInputFrameType; |
michael@0 | 338 | uint8_t mInputFrameFlags; |
michael@0 | 339 | uint32_t mInputFrameID; |
michael@0 | 340 | uint16_t mPaddingLength; |
michael@0 | 341 | |
michael@0 | 342 | // When a frame has been received that is addressed to a particular stream |
michael@0 | 343 | // (e.g. a data frame after the stream-id has been decoded), this points |
michael@0 | 344 | // to the stream. |
michael@0 | 345 | Http2Stream *mInputFrameDataStream; |
michael@0 | 346 | |
michael@0 | 347 | // mNeedsCleanup is a state variable to defer cleanup of a closed stream |
michael@0 | 348 | // If needed, It is set in session::OnWriteSegments() and acted on and |
michael@0 | 349 | // cleared when the stack returns to session::WriteSegments(). The stream |
michael@0 | 350 | // cannot be destroyed directly out of OnWriteSegments because |
michael@0 | 351 | // stream::writeSegments() is on the stack at that time. |
michael@0 | 352 | Http2Stream *mNeedsCleanup; |
michael@0 | 353 | |
michael@0 | 354 | // This reason code in the last processed RESET frame |
michael@0 | 355 | uint32_t mDownstreamRstReason; |
michael@0 | 356 | |
michael@0 | 357 | // When HEADERS/PROMISE are chained together, this is the expected ID of the next |
michael@0 | 358 | // recvd frame which must be the same type |
michael@0 | 359 | uint32_t mExpectedHeaderID; |
michael@0 | 360 | uint32_t mExpectedPushPromiseID; |
michael@0 | 361 | uint32_t mContinuedPromiseStream; |
michael@0 | 362 | |
michael@0 | 363 | // for the conversion of downstream http headers into http/2 formatted headers |
michael@0 | 364 | // The data here does not persist between frames |
michael@0 | 365 | nsCString mFlatHTTPResponseHeaders; |
michael@0 | 366 | uint32_t mFlatHTTPResponseHeadersOut; |
michael@0 | 367 | |
michael@0 | 368 | // when set, the session will go away when it reaches 0 streams. This flag |
michael@0 | 369 | // is set when: the stream IDs are running out (at either the client or the |
michael@0 | 370 | // server), when DontReuse() is called, a RST that is not specific to a |
michael@0 | 371 | // particular stream is received, a GOAWAY frame has been received from |
michael@0 | 372 | // the server. |
michael@0 | 373 | bool mShouldGoAway; |
michael@0 | 374 | |
michael@0 | 375 | // the session has received a nsAHttpTransaction::Close() call |
michael@0 | 376 | bool mClosed; |
michael@0 | 377 | |
michael@0 | 378 | // the session received a GoAway frame with a valid GoAwayID |
michael@0 | 379 | bool mCleanShutdown; |
michael@0 | 380 | |
michael@0 | 381 | // The TLS comlpiance checks are not done in the ctor beacuse of bad |
michael@0 | 382 | // exception handling - so we do them at IO time and cache the result |
michael@0 | 383 | bool mTLSProfileConfirmed; |
michael@0 | 384 | |
michael@0 | 385 | // A specifc reason code for the eventual GoAway frame. If set to NO_HTTP_ERROR |
michael@0 | 386 | // only NO_HTTP_ERROR, PROTOCOL_ERROR, or INTERNAL_ERROR will be sent. |
michael@0 | 387 | errorType mGoAwayReason; |
michael@0 | 388 | |
michael@0 | 389 | // If a GoAway message was received this is the ID of the last valid |
michael@0 | 390 | // stream. 0 otherwise. (0 is never a valid stream id.) |
michael@0 | 391 | uint32_t mGoAwayID; |
michael@0 | 392 | |
michael@0 | 393 | // The last stream processed ID we will send in our GoAway frame. |
michael@0 | 394 | uint32_t mOutgoingGoAwayID; |
michael@0 | 395 | |
michael@0 | 396 | // The limit on number of concurrent streams for this session. Normally it |
michael@0 | 397 | // is basically unlimited, but the SETTINGS control message from the |
michael@0 | 398 | // server might bring it down. |
michael@0 | 399 | uint32_t mMaxConcurrent; |
michael@0 | 400 | |
michael@0 | 401 | // The actual number of concurrent streams at this moment. Generally below |
michael@0 | 402 | // mMaxConcurrent, but the max can be lowered in real time to a value |
michael@0 | 403 | // below the current value |
michael@0 | 404 | uint32_t mConcurrent; |
michael@0 | 405 | |
michael@0 | 406 | // The number of server initiated promises, tracked for telemetry |
michael@0 | 407 | uint32_t mServerPushedResources; |
michael@0 | 408 | |
michael@0 | 409 | // The server rwin for new streams as determined from a SETTINGS frame |
michael@0 | 410 | uint32_t mServerInitialStreamWindow; |
michael@0 | 411 | |
michael@0 | 412 | // The Local Session window is how much data the server is allowed to send |
michael@0 | 413 | // (across all streams) without getting a window update to stream 0. It is |
michael@0 | 414 | // signed because asynchronous changes via SETTINGS can drive it negative. |
michael@0 | 415 | int64_t mLocalSessionWindow; |
michael@0 | 416 | |
michael@0 | 417 | // The Remote Session Window is how much data the client is allowed to send |
michael@0 | 418 | // (across all streams) without receiving a window update to stream 0. It is |
michael@0 | 419 | // signed because asynchronous changes via SETTINGS can drive it negative. |
michael@0 | 420 | int64_t mServerSessionWindow; |
michael@0 | 421 | |
michael@0 | 422 | // This is a output queue of bytes ready to be written to the SSL stream. |
michael@0 | 423 | // When that streams returns WOULD_BLOCK on direct write the bytes get |
michael@0 | 424 | // coalesced together here. This results in larger writes to the SSL layer. |
michael@0 | 425 | // The buffer is not dynamically grown to accomodate stream writes, but |
michael@0 | 426 | // does expand to accept infallible session wide frames like GoAway and RST. |
michael@0 | 427 | uint32_t mOutputQueueSize; |
michael@0 | 428 | uint32_t mOutputQueueUsed; |
michael@0 | 429 | uint32_t mOutputQueueSent; |
michael@0 | 430 | nsAutoArrayPtr<char> mOutputQueueBuffer; |
michael@0 | 431 | |
michael@0 | 432 | PRIntervalTime mPingThreshold; |
michael@0 | 433 | PRIntervalTime mLastReadEpoch; // used for ping timeouts |
michael@0 | 434 | PRIntervalTime mLastDataReadEpoch; // used for IdleTime() |
michael@0 | 435 | PRIntervalTime mPingSentEpoch; |
michael@0 | 436 | |
michael@0 | 437 | // used as a temporary buffer while enumerating the stream hash during GoAway |
michael@0 | 438 | nsDeque mGoAwayStreamsToRestart; |
michael@0 | 439 | |
michael@0 | 440 | // Each session gets a unique serial number because the push cache is correlated |
michael@0 | 441 | // by the load group and the serial number can be used as part of the cache key |
michael@0 | 442 | // to make sure streams aren't shared across sessions. |
michael@0 | 443 | uint64_t mSerial; |
michael@0 | 444 | }; |
michael@0 | 445 | |
michael@0 | 446 | } // namespace mozilla::net |
michael@0 | 447 | } // namespace mozilla |
michael@0 | 448 | |
michael@0 | 449 | #endif // mozilla_net_Http2Session_h |