netwerk/protocol/http/SpdySession3.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #ifndef mozilla_net_SpdySession3_h
     7 #define mozilla_net_SpdySession3_h
     9 // SPDY as defined by
    10 // http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
    12 #include "ASpdySession.h"
    13 #include "mozilla/Attributes.h"
    14 #include "nsAHttpConnection.h"
    15 #include "nsClassHashtable.h"
    16 #include "nsDataHashtable.h"
    17 #include "nsDeque.h"
    18 #include "nsHashKeys.h"
    19 #include "zlib.h"
    21 class nsISocketTransport;
    23 namespace mozilla { namespace net {
    25 class SpdyPushedStream3;
    26 class SpdyStream3;
    28 class SpdySession3 MOZ_FINAL : public ASpdySession
    29                              , public nsAHttpConnection
    30                              , public nsAHttpSegmentReader
    31                              , public nsAHttpSegmentWriter
    32 {
    33 public:
    34   NS_DECL_THREADSAFE_ISUPPORTS
    35   NS_DECL_NSAHTTPTRANSACTION
    36   NS_DECL_NSAHTTPCONNECTION(mConnection)
    37   NS_DECL_NSAHTTPSEGMENTREADER
    38   NS_DECL_NSAHTTPSEGMENTWRITER
    40   SpdySession3(nsAHttpTransaction *, nsISocketTransport *, int32_t);
    41   ~SpdySession3();
    43   bool AddStream(nsAHttpTransaction *, int32_t);
    44   bool CanReuse() { return !mShouldGoAway && !mClosed; }
    45   bool RoomForMoreStreams();
    47   // When the connection is active this is called up to once every 1 second
    48   // return the interval (in seconds) that the connection next wants to
    49   // have this invoked. It might happen sooner depending on the needs of
    50   // other connections.
    51   uint32_t  ReadTimeoutTick(PRIntervalTime now);
    53   // Idle time represents time since "goodput".. e.g. a data or header frame
    54   PRIntervalTime IdleTime();
    56   // Registering with a newID of 0 means pick the next available odd ID
    57   uint32_t RegisterStreamID(SpdyStream3 *, uint32_t aNewID = 0);
    59   const static uint8_t kVersion        = 3;
    61   const static uint8_t kFlag_Control   = 0x80;
    63   const static uint8_t kFlag_Data_FIN  = 0x01;
    64   const static uint8_t kFlag_Data_UNI  = 0x02;
    66   enum
    67   {
    68     CONTROL_TYPE_FIRST = 0,
    69     CONTROL_TYPE_SYN_STREAM = 1,
    70     CONTROL_TYPE_SYN_REPLY = 2,
    71     CONTROL_TYPE_RST_STREAM = 3,
    72     CONTROL_TYPE_SETTINGS = 4,
    73     CONTROL_TYPE_NOOP = 5,                        /* deprecated */
    74     CONTROL_TYPE_PING = 6,
    75     CONTROL_TYPE_GOAWAY = 7,
    76     CONTROL_TYPE_HEADERS = 8,
    77     CONTROL_TYPE_WINDOW_UPDATE = 9,
    78     CONTROL_TYPE_CREDENTIAL = 10,
    79     CONTROL_TYPE_LAST = 11
    80   };
    82   enum rstReason
    83   {
    84     RST_PROTOCOL_ERROR = 1,
    85     RST_INVALID_STREAM = 2,
    86     RST_REFUSED_STREAM = 3,
    87     RST_UNSUPPORTED_VERSION = 4,
    88     RST_CANCEL = 5,
    89     RST_INTERNAL_ERROR = 6,
    90     RST_FLOW_CONTROL_ERROR = 7,
    91     RST_STREAM_IN_USE = 8,
    92     RST_STREAM_ALREADY_CLOSED = 9,
    93     RST_INVALID_CREDENTIALS = 10,
    94     RST_FRAME_TOO_LARGE = 11
    95   };
    97   enum goawayReason
    98   {
    99     OK = 0,
   100     PROTOCOL_ERROR = 1,
   101     INTERNAL_ERROR = 2,    // sometimes misdocumented as 11
   102     NUM_STATUS_CODES = 3   // reserved by chromium but undocumented
   103   };
   105   enum settingsFlags
   106   {
   107     PERSIST_VALUE = 1,
   108     PERSISTED_VALUE = 2
   109   };
   111   enum
   112   {
   113     SETTINGS_TYPE_UPLOAD_BW = 1, // kb/s
   114     SETTINGS_TYPE_DOWNLOAD_BW = 2, // kb/s
   115     SETTINGS_TYPE_RTT = 3, // ms
   116     SETTINGS_TYPE_MAX_CONCURRENT = 4, // streams
   117     SETTINGS_TYPE_CWND = 5, // packets
   118     SETTINGS_TYPE_DOWNLOAD_RETRANS_RATE = 6, // percentage
   119     SETTINGS_TYPE_INITIAL_WINDOW = 7,  // bytes for flow control
   120     SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8
   121   };
   123   // This should be big enough to hold all of your control packets,
   124   // but if it needs to grow for huge headers it can do so dynamically.
   125   // About 1% of responses from SPDY google services seem to be > 1000
   126   // with all less than 2000 when compression is enabled.
   127   const static uint32_t kDefaultBufferSize = 2048;
   129   // kDefaultQueueSize must be >= other queue size constants
   130   const static uint32_t kDefaultQueueSize =  32768;
   131   const static uint32_t kQueueMinimumCleanup = 24576;
   132   const static uint32_t kQueueTailRoom    =  4096;
   133   const static uint32_t kQueueReserved    =  1024;
   135   const static uint32_t kDefaultMaxConcurrent = 100;
   136   const static uint32_t kMaxStreamID = 0x7800000;
   138   // This is a sentinel for a deleted stream. It is not a valid
   139   // 31 bit stream ID.
   140   const static uint32_t kDeadStreamID = 0xffffdead;
   142   // below the emergency threshold of local window we ack every received
   143   // byte. Above that we coalesce bytes into the MinimumToAck size.
   144   const static int32_t  kEmergencyWindowThreshold = 1024 * 1024;
   145   const static uint32_t kMinimumToAck = 64 * 1024;
   147   // The default peer rwin is 64KB unless updated by a settings frame
   148   const static uint32_t kDefaultServerRwin = 64 * 1024;
   150   static nsresult HandleSynStream(SpdySession3 *);
   151   static nsresult HandleSynReply(SpdySession3 *);
   152   static nsresult HandleRstStream(SpdySession3 *);
   153   static nsresult HandleSettings(SpdySession3 *);
   154   static nsresult HandleNoop(SpdySession3 *);
   155   static nsresult HandlePing(SpdySession3 *);
   156   static nsresult HandleGoAway(SpdySession3 *);
   157   static nsresult HandleHeaders(SpdySession3 *);
   158   static nsresult HandleWindowUpdate(SpdySession3 *);
   159   static nsresult HandleCredential(SpdySession3 *);
   161   template<typename T>
   162   static void EnsureBuffer(nsAutoArrayPtr<T> &,
   163                            uint32_t, uint32_t, uint32_t &);
   165   // For writing the SPDY data stream to LOG4
   166   static void LogIO(SpdySession3 *, SpdyStream3 *, const char *,
   167                     const char *, uint32_t);
   169   // an overload of nsAHttpConnection
   170   void TransactionHasDataToWrite(nsAHttpTransaction *);
   172   // a similar version for SpdyStream3
   173   void TransactionHasDataToWrite(SpdyStream3 *);
   175   // an overload of nsAHttpSegementReader
   176   virtual nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment);
   178   uint32_t GetServerInitialWindow() { return mServerInitialWindow; }
   180   void ConnectPushedStream(SpdyStream3 *stream);
   181   void DecrementConcurrent(SpdyStream3 *stream);
   183   uint64_t Serial() { return mSerial; }
   185   void     PrintDiagnostics (nsCString &log);
   187   // Streams need access to these
   188   uint32_t SendingChunkSize() { return mSendingChunkSize; }
   189   uint32_t PushAllowance() { return mPushAllowance; }
   190   z_stream *UpstreamZlib() { return &mUpstreamZlib; }
   191   nsISocketTransport *SocketTransport() { return mSocketTransport; }
   193 private:
   195   enum stateType {
   196     BUFFERING_FRAME_HEADER,
   197     BUFFERING_CONTROL_FRAME,
   198     PROCESSING_DATA_FRAME,
   199     DISCARDING_DATA_FRAME,
   200     PROCESSING_COMPLETE_HEADERS,
   201     PROCESSING_CONTROL_RST_STREAM
   202   };
   204   nsresult    ResponseHeadersComplete();
   205   uint32_t    GetWriteQueueSize();
   206   void        ChangeDownstreamState(enum stateType);
   207   void        ResetDownstreamState();
   208   nsresult    UncompressAndDiscard(uint32_t, uint32_t);
   209   void        zlibInit();
   210   void        GeneratePing(uint32_t);
   211   void        GenerateRstStream(uint32_t, uint32_t);
   212   void        GenerateGoAway(uint32_t);
   213   void        CleanupStream(SpdyStream3 *, nsresult, rstReason);
   214   void        CloseStream(SpdyStream3 *, nsresult);
   215   void        GenerateSettings();
   216   void        RemoveStreamFromQueues(SpdyStream3 *);
   218   void        SetWriteCallbacks();
   219   void        FlushOutputQueue();
   220   void        RealignOutputQueue();
   222   bool        RoomForMoreConcurrent();
   223   void        ActivateStream(SpdyStream3 *);
   224   void        ProcessPending();
   225   nsresult    SetInputFrameDataStream(uint32_t);
   226   bool        VerifyStream(SpdyStream3 *, uint32_t);
   227   void        SetNeedsCleanup();
   229   void        UpdateLocalRwin(SpdyStream3 *stream, uint32_t bytes);
   231   // a wrapper for all calls to the nshttpconnection level segment writer. Used
   232   // to track network I/O for timeout purposes
   233   nsresult   NetworkRead(nsAHttpSegmentWriter *, char *, uint32_t, uint32_t *);
   235   static PLDHashOperator ShutdownEnumerator(nsAHttpTransaction *,
   236                                             nsAutoPtr<SpdyStream3> &,
   237                                             void *);
   239   static PLDHashOperator GoAwayEnumerator(nsAHttpTransaction *,
   240                                           nsAutoPtr<SpdyStream3> &,
   241                                           void *);
   243   static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *,
   244                                                     nsAutoPtr<SpdyStream3> &,
   245                                                     void *);
   247   // This is intended to be nsHttpConnectionMgr:nsConnectionHandle taken
   248   // from the first transaction on this session. That object contains the
   249   // pointer to the real network-level nsHttpConnection object.
   250   nsRefPtr<nsAHttpConnection> mConnection;
   252   // The underlying socket transport object is needed to propogate some events
   253   nsISocketTransport         *mSocketTransport;
   255   // These are temporary state variables to hold the argument to
   256   // Read/WriteSegments so it can be accessed by On(read/write)segment
   257   // further up the stack.
   258   nsAHttpSegmentReader       *mSegmentReader;
   259   nsAHttpSegmentWriter       *mSegmentWriter;
   261   uint32_t          mSendingChunkSize;        /* the transmission chunk size */
   262   uint32_t          mNextStreamID;            /* 24 bits */
   263   uint32_t          mConcurrentHighWater;     /* max parallelism on session */
   264   uint32_t          mPushAllowance;           /* rwin for unmatched pushes */
   266   stateType         mDownstreamState; /* in frame, between frames, etc..  */
   268   // Maintain 2 indexes - one by stream ID, one by transaction pointer.
   269   // There are also several lists of streams: ready to write, queued due to
   270   // max parallelism, streams that need to force a read for push, and the full
   271   // set of pushed streams.
   272   // The objects are not ref counted - they get destroyed
   273   // by the nsClassHashtable implementation when they are removed from
   274   // the transaction hash.
   275   nsDataHashtable<nsUint32HashKey, SpdyStream3 *>     mStreamIDHash;
   276   nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>,
   277                    SpdyStream3>                       mStreamTransactionHash;
   279   nsDeque                                             mReadyForWrite;
   280   nsDeque                                             mQueuedStreams;
   281   nsDeque                                             mReadyForRead;
   282   nsTArray<SpdyPushedStream3 *>                       mPushedStreams;
   284   // Compression contexts for header transport using deflate.
   285   // SPDY compresses only HTTP headers and does not reset zlib in between
   286   // frames. Even data that is not associated with a stream (e.g invalid
   287   // stream ID) is passed through these contexts to keep the compression
   288   // context correct.
   289   z_stream            mDownstreamZlib;
   290   z_stream            mUpstreamZlib;
   292   // mInputFrameBuffer is used to store received control packets and the 8 bytes
   293   // of header on data packets
   294   uint32_t             mInputFrameBufferSize;
   295   uint32_t             mInputFrameBufferUsed;
   296   nsAutoArrayPtr<char> mInputFrameBuffer;
   298   // mInputFrameDataSize/Read are used for tracking the amount of data consumed
   299   // in a data frame. the data itself is not buffered in spdy
   300   // The frame size is mInputFrameDataSize + the constant 8 byte header
   301   uint32_t             mInputFrameDataSize;
   302   uint32_t             mInputFrameDataRead;
   303   bool                 mInputFrameDataLast; // This frame was marked FIN
   305   // When a frame has been received that is addressed to a particular stream
   306   // (e.g. a data frame after the stream-id has been decoded), this points
   307   // to the stream.
   308   SpdyStream3          *mInputFrameDataStream;
   310   // mNeedsCleanup is a state variable to defer cleanup of a closed stream
   311   // If needed, It is set in session::OnWriteSegments() and acted on and
   312   // cleared when the stack returns to session::WriteSegments(). The stream
   313   // cannot be destroyed directly out of OnWriteSegments because
   314   // stream::writeSegments() is on the stack at that time.
   315   SpdyStream3          *mNeedsCleanup;
   317   // The CONTROL_TYPE value for a control frame
   318   uint32_t             mFrameControlType;
   320   // This reason code in the last processed RESET frame
   321   uint32_t             mDownstreamRstReason;
   323   // for the conversion of downstream http headers into spdy formatted headers
   324   // The data here does not persist between frames
   325   nsCString            mFlatHTTPResponseHeaders;
   326   uint32_t             mFlatHTTPResponseHeadersOut;
   328   // when set, the session will go away when it reaches 0 streams. This flag
   329   // is set when: the stream IDs are running out (at either the client or the
   330   // server), when DontReuse() is called, a RST that is not specific to a
   331   // particular stream is received, a GOAWAY frame has been received from
   332   // the server.
   333   bool                 mShouldGoAway;
   335   // the session has received a nsAHttpTransaction::Close()  call
   336   bool                 mClosed;
   338   // the session received a GoAway frame with a valid GoAwayID
   339   bool                 mCleanShutdown;
   341   // indicates PROCESSING_COMPLETE_HEADERS state was pushed onto the stack
   342   // over an active PROCESSING_DATA_FRAME, which should be restored when
   343   // the processed headers are written to the stream
   344   bool                 mDataPending;
   346   // If a GoAway message was received this is the ID of the last valid
   347   // stream. 0 otherwise. (0 is never a valid stream id.)
   348   uint32_t             mGoAwayID;
   350   // The limit on number of concurrent streams for this session. Normally it
   351   // is basically unlimited, but the SETTINGS control message from the
   352   // server might bring it down.
   353   uint32_t             mMaxConcurrent;
   355   // The actual number of concurrent streams at this moment. Generally below
   356   // mMaxConcurrent, but the max can be lowered in real time to a value
   357   // below the current value
   358   uint32_t             mConcurrent;
   360   // The number of server initiated SYN-STREAMS, tracked for telemetry
   361   uint32_t             mServerPushedResources;
   363   // The server rwin for new streams as determined from a SETTINGS frame
   364   uint32_t             mServerInitialWindow;
   366   // This is a output queue of bytes ready to be written to the SSL stream.
   367   // When that streams returns WOULD_BLOCK on direct write the bytes get
   368   // coalesced together here. This results in larger writes to the SSL layer.
   369   // The buffer is not dynamically grown to accomodate stream writes, but
   370   // does expand to accept infallible session wide frames like GoAway and RST.
   371   uint32_t             mOutputQueueSize;
   372   uint32_t             mOutputQueueUsed;
   373   uint32_t             mOutputQueueSent;
   374   nsAutoArrayPtr<char> mOutputQueueBuffer;
   376   PRIntervalTime       mPingThreshold;
   377   PRIntervalTime       mLastReadEpoch;     // used for ping timeouts
   378   PRIntervalTime       mLastDataReadEpoch; // used for IdleTime()
   379   PRIntervalTime       mPingSentEpoch;
   380   uint32_t             mNextPingID;
   382   // used as a temporary buffer while enumerating the stream hash during GoAway
   383   nsDeque  mGoAwayStreamsToRestart;
   385   // Each session gets a unique serial number because the push cache is correlated
   386   // by the load group and the serial number can be used as part of the cache key
   387   // to make sure streams aren't shared across sessions.
   388   uint64_t        mSerial;
   389 };
   391 }} // namespace mozilla::net
   393 #endif // mozilla_net_SpdySession3_h

mercurial