LCOV - app.info - netwerk/protocol/http/SpdySession.h

LCOV - code coverage report
| Current view: | directory - netwerk/protocol/http - SpdySession.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 1 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 1 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 :
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Mozilla Foundation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2011
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Patrick McManus <mcmanus@ducksong.com>
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #ifndef mozilla_net_SpdySession_h
          41                 : #define mozilla_net_SpdySession_h
          42                 :
          43                 : // SPDY as defined by
          44                 : // http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2
          45                 :
          46                 : #include "nsAHttpTransaction.h"
          47                 : #include "nsAHttpConnection.h"
          48                 : #include "nsClassHashtable.h"
          49                 : #include "nsDataHashtable.h"
          50                 : #include "nsDeque.h"
          51                 : #include "nsHashKeys.h"
          52                 : #include "zlib.h"
          53                 :
          54                 : class nsHttpConnection;
          55                 : class nsISocketTransport;
          56                 :
          57                 : namespace mozilla { namespace net {
          58                 :
          59                 : class SpdyStream;
          60                 :
          61                 : class SpdySession : public nsAHttpTransaction
          62                 :                   , public nsAHttpConnection
          63                 :                   , public nsAHttpSegmentReader
          64                 :                   , public nsAHttpSegmentWriter
          65                 : {
          66                 : public:
          67                 :   NS_DECL_ISUPPORTS
          68                 :   NS_DECL_NSAHTTPTRANSACTION
          69                 :   NS_DECL_NSAHTTPCONNECTION
          70                 :   NS_DECL_NSAHTTPSEGMENTREADER
          71                 :   NS_DECL_NSAHTTPSEGMENTWRITER
          72                 :
          73                 :   SpdySession(nsAHttpTransaction *, nsISocketTransport *, PRInt32);
          74                 :   ~SpdySession();
          75                 :
          76                 :   bool AddStream(nsAHttpTransaction *, PRInt32);
          77               0 :   bool CanReuse() { return !mShouldGoAway && !mClosed; }
          78                 :   void DontReuse();
          79                 :   bool RoomForMoreStreams();
          80                 :
          81                 :   // When the connection is active this is called every 15 seconds
          82                 :   void ReadTimeoutTick(PRIntervalTime now);
          83                 :
          84                 :   // Idle time represents time since "goodput".. e.g. a data or header frame
          85                 :   PRIntervalTime IdleTime();
          86                 :
          87                 :   PRUint32 RegisterStreamID(SpdyStream *);
          88                 :
          89                 :   const static PRUint8 kFlag_Control   = 0x80;
          90                 :
          91                 :   const static PRUint8 kFlag_Data_FIN  = 0x01;
          92                 :   const static PRUint8 kFlag_Data_UNI  = 0x02;
          93                 :   const static PRUint8 kFlag_Data_ZLIB = 0x02;
          94                 :
          95                 :   // The protocol document for v2 specifies that the
          96                 :   // highest value (3) is the highest priority, but in
          97                 :   // reality 0 is the highest priority.
          98                 :   //
          99                 :   // Draft 3 notes here https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/
         100                 :   // are the best guide to the mistake. Also see
         101                 :   // GetLowestPriority() and GetHighestPriority() in spdy_framer.h of
         102                 :   // chromium source.
         103                 :
         104                 :   const static PRUint8 kPri00   = 0 << 6; // highest
         105                 :   const static PRUint8 kPri01   = 1 << 6;
         106                 :   const static PRUint8 kPri02   = 2 << 6;
         107                 :   const static PRUint8 kPri03   = 3 << 6; // lowest
         108                 :
         109                 :   enum
         110                 :   {
         111                 :     CONTROL_TYPE_FIRST = 0,
         112                 :     CONTROL_TYPE_SYN_STREAM = 1,
         113                 :     CONTROL_TYPE_SYN_REPLY = 2,
         114                 :     CONTROL_TYPE_RST_STREAM = 3,
         115                 :     CONTROL_TYPE_SETTINGS = 4,
         116                 :     CONTROL_TYPE_NOOP = 5,
         117                 :     CONTROL_TYPE_PING = 6,
         118                 :     CONTROL_TYPE_GOAWAY = 7,
         119                 :     CONTROL_TYPE_HEADERS = 8,
         120                 :     CONTROL_TYPE_WINDOW_UPDATE = 9,               /* no longer in v2 */
         121                 :     CONTROL_TYPE_LAST = 10
         122                 :   };
         123                 :
         124                 :   enum rstReason
         125                 :   {
         126                 :     RST_PROTOCOL_ERROR = 1,
         127                 :     RST_INVALID_STREAM = 2,
         128                 :     RST_REFUSED_STREAM = 3,
         129                 :     RST_UNSUPPORTED_VERSION = 4,
         130                 :     RST_CANCEL = 5,
         131                 :     RST_INTERNAL_ERROR = 6,
         132                 :     RST_FLOW_CONTROL_ERROR = 7,
         133                 :     RST_BAD_ASSOC_STREAM = 8
         134                 :   };
         135                 :
         136                 :   enum
         137                 :   {
         138                 :     SETTINGS_TYPE_UPLOAD_BW = 1, // kb/s
         139                 :     SETTINGS_TYPE_DOWNLOAD_BW = 2, // kb/s
         140                 :     SETTINGS_TYPE_RTT = 3, // ms
         141                 :     SETTINGS_TYPE_MAX_CONCURRENT = 4, // streams
         142                 :     SETTINGS_TYPE_CWND = 5, // packets
         143                 :     SETTINGS_TYPE_DOWNLOAD_RETRANS_RATE = 6, // percentage
         144                 :     SETTINGS_TYPE_INITIAL_WINDOW = 7  // bytes. Not used in v2.
         145                 :   };
         146                 :
         147                 :   // This should be big enough to hold all of your control packets,
         148                 :   // but if it needs to grow for huge headers it can do so dynamically.
         149                 :   // About 1% of requests to SPDY google services seem to be > 1000
         150                 :   // with all less than 2000.
         151                 :   const static PRUint32 kDefaultBufferSize = 2048;
         152                 :
         153                 :   // kDefaultQueueSize must be >= other queue size constants
         154                 :   const static PRUint32 kDefaultQueueSize =  16384;
         155                 :   const static PRUint32 kQueueMinimumCleanup = 8192;
         156                 :   const static PRUint32 kQueueTailRoom    =  4096;
         157                 :   const static PRUint32 kQueueReserved    =  1024;
         158                 :
         159                 :   const static PRUint32 kSendingChunkSize = 4096;
         160                 :   const static PRUint32 kDefaultMaxConcurrent = 100;
         161                 :   const static PRUint32 kMaxStreamID = 0x7800000;
         162                 :
         163                 :   static nsresult HandleSynStream(SpdySession *);
         164                 :   static nsresult HandleSynReply(SpdySession *);
         165                 :   static nsresult HandleRstStream(SpdySession *);
         166                 :   static nsresult HandleSettings(SpdySession *);
         167                 :   static nsresult HandleNoop(SpdySession *);
         168                 :   static nsresult HandlePing(SpdySession *);
         169                 :   static nsresult HandleGoAway(SpdySession *);
         170                 :   static nsresult HandleHeaders(SpdySession *);
         171                 :   static nsresult HandleWindowUpdate(SpdySession *);
         172                 :
         173                 :   static void EnsureBuffer(nsAutoArrayPtr<char> &,
         174                 :                            PRUint32, PRUint32, PRUint32 &);
         175                 :
         176                 :   // For writing the SPDY data stream to LOG4
         177                 :   static void LogIO(SpdySession *, SpdyStream *, const char *,
         178                 :                     const char *, PRUint32);
         179                 :
         180                 :   // an overload of nsAHttpConnection
         181                 :   void TransactionHasDataToWrite(nsAHttpTransaction *);
         182                 :
         183                 :   // a similar version for SpdyStream
         184                 :   void TransactionHasDataToWrite(SpdyStream *);
         185                 :
         186                 :   // an overload of nsAHttpSegementReader
         187                 :   virtual nsresult CommitToSegmentSize(PRUint32 size);
         188                 :
         189                 : private:
         190                 :
         191                 :   enum stateType {
         192                 :     BUFFERING_FRAME_HEADER,
         193                 :     BUFFERING_CONTROL_FRAME,
         194                 :     PROCESSING_DATA_FRAME,
         195                 :     DISCARDING_DATA_FRAME,
         196                 :     PROCESSING_CONTROL_SYN_REPLY,
         197                 :     PROCESSING_CONTROL_RST_STREAM
         198                 :   };
         199                 :
         200                 :   void        DeterminePingThreshold();
         201                 :   nsresult    HandleSynReplyForValidStream();
         202                 :   PRUint32    GetWriteQueueSize();
         203                 :   void        ChangeDownstreamState(enum stateType);
         204                 :   void        ResetDownstreamState();
         205                 :   nsresult    DownstreamUncompress(char *, PRUint32);
         206                 :   void        zlibInit();
         207                 :   nsresult    FindHeader(nsCString, nsDependentCSubstring &);
         208                 :   nsresult    ConvertHeaders(nsDependentCSubstring &,
         209                 :                              nsDependentCSubstring &);
         210                 :   void        GeneratePing(PRUint32);
         211                 :   void        ClearPing(bool);
         212                 :   void        GenerateRstStream(PRUint32, PRUint32);
         213                 :   void        GenerateGoAway();
         214                 :   void        CleanupStream(SpdyStream *, nsresult, rstReason);
         215                 :
         216                 :   void        SetWriteCallbacks();
         217                 :   void        FlushOutputQueue();
         218                 :
         219                 :   bool        RoomForMoreConcurrent();
         220                 :   void        ActivateStream(SpdyStream *);
         221                 :   void        ProcessPending();
         222                 :
         223                 :   // a wrapper for all calls to the nshttpconnection level segment writer. Used
         224                 :   // to track network I/O for timeout purposes
         225                 :   nsresult   NetworkRead(nsAHttpSegmentWriter *, char *, PRUint32, PRUint32 *);
         226                 :
         227                 :   static PLDHashOperator ShutdownEnumerator(nsAHttpTransaction *,
         228                 :                                             nsAutoPtr<SpdyStream> &,
         229                 :                                             void *);
         230                 :
         231                 :   // This is intended to be nsHttpConnectionMgr:nsHttpConnectionHandle taken
         232                 :   // from the first transaction on this session. That object contains the
         233                 :   // pointer to the real network-level nsHttpConnection object.
         234                 :   nsRefPtr<nsAHttpConnection> mConnection;
         235                 :
         236                 :   // The underlying socket transport object is needed to propogate some events
         237                 :   nsISocketTransport         *mSocketTransport;
         238                 :
         239                 :   // These are temporary state variables to hold the argument to
         240                 :   // Read/WriteSegments so it can be accessed by On(read/write)segment
         241                 :   // further up the stack.
         242                 :   nsAHttpSegmentReader       *mSegmentReader;
         243                 :   nsAHttpSegmentWriter       *mSegmentWriter;
         244                 :
         245                 :   PRUint32          mSendingChunkSize;        /* the transmission chunk size */
         246                 :   PRUint32          mNextStreamID;            /* 24 bits */
         247                 :   PRUint32          mConcurrentHighWater;     /* max parallelism on session */
         248                 :
         249                 :   stateType         mDownstreamState; /* in frame, between frames, etc..  */
         250                 :
         251                 :   // Maintain 5 indexes - one by stream ID, one by transaction ptr,
         252                 :   // one list of streams ready to write, one list of streams that are queued
         253                 :   // due to max parallelism settings, and one list of streams
         254                 :   // that must be given priority to write for window updates. The objects
         255                 :   // are not ref counted - they get destroyed
         256                 :   // by the nsClassHashtable implementation when they are removed from
         257                 :   // there.
         258                 :   nsDataHashtable<nsUint32HashKey, SpdyStream *>      mStreamIDHash;
         259                 :   nsClassHashtable<nsPtrHashKey<nsAHttpTransaction>,
         260                 :                    SpdyStream>                        mStreamTransactionHash;
         261                 :   nsDeque                                             mReadyForWrite;
         262                 :   nsDeque                                             mQueuedStreams;
         263                 :
         264                 :   // UrgentForWrite is meant to carry window updates. They were defined in
         265                 :   // the v2 spec but apparently never implemented so are now scheduled to
         266                 :   // be removed. But they will be reintroduced for v3, so we will leave
         267                 :   // this queue in place to ease that transition.
         268                 :   nsDeque           mUrgentForWrite;
         269                 :
         270                 :   // Compression contexts for header transport using deflate.
         271                 :   // SPDY compresses only HTTP headers and does not reset zlib in between
         272                 :   // frames.
         273                 :   z_stream            mDownstreamZlib;
         274                 :   z_stream            mUpstreamZlib;
         275                 :
         276                 :   // mInputFrameBuffer is used to store received control packets and the 8 bytes
         277                 :   // of header on data packets
         278                 :   PRUint32             mInputFrameBufferSize;
         279                 :   PRUint32             mInputFrameBufferUsed;
         280                 :   nsAutoArrayPtr<char> mInputFrameBuffer;
         281                 :
         282                 :   // mInputFrameDataSize/Read are used for tracking the amount of data consumed
         283                 :   // in a data frame. the data itself is not buffered in spdy
         284                 :   // The frame size is mInputFrameDataSize + the constant 8 byte header
         285                 :   PRUint32             mInputFrameDataSize;
         286                 :   PRUint32             mInputFrameDataRead;
         287                 :   bool                 mInputFrameDataLast; // This frame was marked FIN
         288                 :
         289                 :   // When a frame has been received that is addressed to a particular stream
         290                 :   // (e.g. a data frame after the stream-id has been decoded), this points
         291                 :   // to the stream.
         292                 :   SpdyStream          *mInputFrameDataStream;
         293                 :
         294                 :   // mNeedsCleanup is a state variable to defer cleanup of a closed stream
         295                 :   // If needed, It is set in session::OnWriteSegments() and acted on and
         296                 :   // cleared when the stack returns to session::WriteSegments(). The stream
         297                 :   // cannot be destroyed directly out of OnWriteSegments because
         298                 :   // stream::writeSegments() is on the stack at that time.
         299                 :   SpdyStream          *mNeedsCleanup;
         300                 :
         301                 :   // The CONTROL_TYPE value for a control frame
         302                 :   PRUint32             mFrameControlType;
         303                 :
         304                 :   // This reason code in the last processed RESET frame
         305                 :   PRUint32             mDownstreamRstReason;
         306                 :
         307                 :   // These are used for decompressing downstream spdy response headers
         308                 :   // This is done at the session level because sometimes the stream
         309                 :   // has already been canceled but the decompression still must happen
         310                 :   // to keep the zlib state correct for the next state of headers.
         311                 :   PRUint32             mDecompressBufferSize;
         312                 :   PRUint32             mDecompressBufferUsed;
         313                 :   nsAutoArrayPtr<char> mDecompressBuffer;
         314                 :
         315                 :   // for the conversion of downstream http headers into spdy formatted headers
         316                 :   nsCString            mFlatHTTPResponseHeaders;
         317                 :   PRUint32             mFlatHTTPResponseHeadersOut;
         318                 :
         319                 :   // when set, the session will go away when it reaches 0 streams. This flag
         320                 :   // is set when: the stream IDs are running out (at either the client or the
         321                 :   // server), when DontReuse() is called, a RST that is not specific to a
         322                 :   // particular stream is received, a GOAWAY frame has been received from
         323                 :   // the server.
         324                 :   bool                 mShouldGoAway;
         325                 :
         326                 :   // the session has received a nsAHttpTransaction::Close()  call
         327                 :   bool                 mClosed;
         328                 :
         329                 :   // the session received a GoAway frame with a valid GoAwayID
         330                 :   bool                 mCleanShutdown;
         331                 :
         332                 :   // If a GoAway message was received this is the ID of the last valid
         333                 :   // stream. 0 otherwise. (0 is never a valid stream id.)
         334                 :   PRUint32             mGoAwayID;
         335                 :
         336                 :   // The limit on number of concurrent streams for this session. Normally it
         337                 :   // is basically unlimited, but the SETTINGS control message from the
         338                 :   // server might bring it down.
         339                 :   PRUint32             mMaxConcurrent;
         340                 :
         341                 :   // The actual number of concurrent streams at this moment. Generally below
         342                 :   // mMaxConcurrent, but the max can be lowered in real time to a value
         343                 :   // below the current value
         344                 :   PRUint32             mConcurrent;
         345                 :
         346                 :   // The number of server initiated SYN-STREAMS, tracked for telemetry
         347                 :   PRUint32             mServerPushedResources;
         348                 :
         349                 :   // This is a output queue of bytes ready to be written to the SSL stream.
         350                 :   // When that streams returns WOULD_BLOCK on direct write the bytes get
         351                 :   // coalesced together here. This results in larger writes to the SSL layer.
         352                 :   // The buffer is not dynamically grown to accomodate stream writes, but
         353                 :   // does expand to accept infallible session wide frames like GoAway and RST.
         354                 :   PRUint32             mOutputQueueSize;
         355                 :   PRUint32             mOutputQueueUsed;
         356                 :   PRUint32             mOutputQueueSent;
         357                 :   nsAutoArrayPtr<char> mOutputQueueBuffer;
         358                 :
         359                 :   PRIntervalTime       mPingThreshold;
         360                 :   PRIntervalTime       mLastReadEpoch;     // used for ping timeouts
         361                 :   PRIntervalTime       mLastDataReadEpoch; // used for IdleTime()
         362                 :   PRIntervalTime       mPingSentEpoch;
         363                 :   PRUint32             mNextPingID;
         364                 :   bool                 mPingThresholdExperiment;
         365                 : };
         366                 :
         367                 : }} // namespace mozilla::net
         368                 :
         369                 : #endif // mozilla_net_SpdySession_h

Generated by: LCOV version 1.7