Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_session.h
index 73f8cd4..bf64cec 100644 (file)
@@ -61,10 +61,16 @@ const int kMaxReadBytesWithoutYielding = 32 * 1024;
 // The initial receive window size for both streams and sessions.
 const int32 kDefaultInitialRecvWindowSize = 10 * 1024 * 1024;  // 10MB
 
+// First and last valid stream IDs. As we always act as the client,
+// start at 1 for the first stream id.
+const SpdyStreamId kFirstStreamId = 1;
+const SpdyStreamId kLastStreamId = 0x7fffffff;
+
 class BoundNetLog;
 struct LoadTimingInfo;
 class SpdyStream;
 class SSLInfo;
+class TransportSecurityState;
 
 // NOTE: There's an enum of the same name (also with numeric suffixes)
 // in histograms.xml. Be sure to add new values there also.
@@ -82,6 +88,7 @@ enum SpdyProtocolErrorDetails {
   SPDY_ERROR_RST_STREAM_FRAME_CORRUPT = 30,
   SPDY_ERROR_INVALID_DATA_FRAME_FLAGS = 8,
   SPDY_ERROR_INVALID_CONTROL_FRAME_FLAGS = 9,
+  SPDY_ERROR_UNEXPECTED_FRAME = 31,
   // SpdyRstStreamStatus mappings.
   // RST_STREAM_INVALID not mapped.
   STATUS_CODE_PROTOCOL_ERROR = 11,
@@ -94,7 +101,11 @@ enum SpdyProtocolErrorDetails {
   STATUS_CODE_STREAM_IN_USE = 18,
   STATUS_CODE_STREAM_ALREADY_CLOSED = 19,
   STATUS_CODE_INVALID_CREDENTIALS = 20,
-  STATUS_CODE_FRAME_TOO_LARGE = 21,
+  STATUS_CODE_FRAME_SIZE_ERROR = 21,
+  STATUS_CODE_SETTINGS_TIMEOUT = 32,
+  STATUS_CODE_CONNECT_ERROR = 33,
+  STATUS_CODE_ENHANCE_YOUR_CALM = 34,
+
   // SpdySession errors
   PROTOCOL_ERROR_UNEXPECTED_PING = 22,
   PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM = 23,
@@ -105,20 +116,30 @@ enum SpdyProtocolErrorDetails {
   PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION = 28,
 
   // Next free value.
-  NUM_SPDY_PROTOCOL_ERROR_DETAILS = 31,
+  NUM_SPDY_PROTOCOL_ERROR_DETAILS = 35,
 };
-SpdyProtocolErrorDetails NET_EXPORT_PRIVATE MapFramerErrorToProtocolError(
-    SpdyFramer::SpdyError);
-SpdyProtocolErrorDetails NET_EXPORT_PRIVATE MapRstStreamStatusToProtocolError(
-    SpdyRstStreamStatus);
+SpdyProtocolErrorDetails NET_EXPORT_PRIVATE
+    MapFramerErrorToProtocolError(SpdyFramer::SpdyError error);
+Error NET_EXPORT_PRIVATE MapFramerErrorToNetError(SpdyFramer::SpdyError error);
+SpdyProtocolErrorDetails NET_EXPORT_PRIVATE
+    MapRstStreamStatusToProtocolError(SpdyRstStreamStatus status);
+SpdyGoAwayStatus NET_EXPORT_PRIVATE MapNetErrorToGoAwayStatus(Error err);
 
 // If these compile asserts fail then SpdyProtocolErrorDetails needs
 // to be updated with new values, as do the mapping functions above.
-COMPILE_ASSERT(11 == SpdyFramer::LAST_ERROR,
+COMPILE_ASSERT(12 == SpdyFramer::LAST_ERROR,
                SpdyProtocolErrorDetails_SpdyErrors_mismatch);
-COMPILE_ASSERT(12 == RST_STREAM_NUM_STATUS_CODES,
+COMPILE_ASSERT(15 == RST_STREAM_NUM_STATUS_CODES,
                SpdyProtocolErrorDetails_RstStreamStatus_mismatch);
 
+// Splits pushed |headers| into request and response parts. Request headers are
+// the headers specifying resource URL.
+void NET_EXPORT_PRIVATE
+    SplitPushedHeadersToRequestAndResponse(const SpdyHeaderBlock& headers,
+                                           SpdyMajorVersion protocol_version,
+                                           SpdyHeaderBlock* request_headers,
+                                           SpdyHeaderBlock* response_headers);
+
 // A helper class used to manage a request to create a stream.
 class NET_EXPORT_PRIVATE SpdyStreamRequest {
  public:
@@ -175,7 +196,6 @@ class NET_EXPORT_PRIVATE SpdyStreamRequest {
 
   void Reset();
 
-  base::WeakPtrFactory<SpdyStreamRequest> weak_ptr_factory_;
   SpdyStreamType type_;
   base::WeakPtr<SpdySession> session_;
   base::WeakPtr<SpdyStream> stream_;
@@ -184,6 +204,8 @@ class NET_EXPORT_PRIVATE SpdyStreamRequest {
   BoundNetLog net_log_;
   CompletionCallback callback_;
 
+  base::WeakPtrFactory<SpdyStreamRequest> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(SpdyStreamRequest);
 };
 
@@ -201,6 +223,13 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
     FLOW_CONTROL_STREAM_AND_SESSION
   };
 
+  // Returns true if |hostname| can be pooled into an existing connection
+  // associated with |ssl_info|.
+  static bool CanPool(TransportSecurityState* transport_security_state,
+                      const SSLInfo& ssl_info,
+                      const std::string& old_hostname,
+                      const std::string& new_hostname);
+
   // Create a new SpdySession.
   // |spdy_session_key| is the host/port that this session connects to, privacy
   // and proxy configuration settings that it's using.
@@ -208,6 +237,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // network events to.
   SpdySession(const SpdySessionKey& spdy_session_key,
               const base::WeakPtr<HttpServerProperties>& http_server_properties,
+              TransportSecurityState* transport_security_state,
               bool verify_domain_authentication,
               bool enable_sending_initial_data,
               bool enable_compression,
@@ -220,7 +250,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
               const HostPortPair& trusted_spdy_proxy,
               NetLog* net_log);
 
-  virtual ~SpdySession();
+  ~SpdySession() override;
 
   const HostPortPair& host_port_pair() const {
     return spdy_session_key_.host_port_proxy_pair().first;
@@ -255,13 +285,13 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // |certificate_error_code| must either be OK or less than
   // ERR_IO_PENDING.
   //
-  // Returns OK on success, or an error on failure. Never returns
-  // ERR_IO_PENDING. If an error is returned, the session must be
-  // destroyed immediately.
-  Error InitializeWithSocket(scoped_ptr<ClientSocketHandle> connection,
-                             SpdySessionPool* pool,
-                             bool is_secure,
-                             int certificate_error_code);
+  // The session begins reading from |connection| on a subsequent event loop
+  // iteration, so the SpdySession may close immediately afterwards if the first
+  // read of |connection| fails.
+  void InitializeWithSocket(scoped_ptr<ClientSocketHandle> connection,
+                            SpdySessionPool* pool,
+                            bool is_secure,
+                            int certificate_error_code);
 
   // Returns the protocol used by this session. Always between
   // kProtoSPDYMinimumVersion and kProtoSPDYMaximumVersion.
@@ -338,12 +368,10 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   void SendStreamWindowUpdate(SpdyStreamId stream_id,
                               uint32 delta_window_size);
 
-  // Whether the stream is closed, i.e. it has stopped processing data
-  // and is about to be destroyed.
-  //
-  // TODO(akalin): This is only used in tests. Remove this function
-  // and have tests test the WeakPtr instead.
-  bool IsClosed() const { return availability_state_ == STATE_CLOSED; }
+  // Accessors for the session's availability state.
+  bool IsAvailable() const { return availability_state_ == STATE_AVAILABLE; }
+  bool IsGoingAway() const { return availability_state_ == STATE_GOING_AWAY; }
+  bool IsDraining() const { return availability_state_ == STATE_DRAINING; }
 
   // Closes this session. This will close all active streams and mark
   // the session as permanently closed. Callers must assume that the
@@ -361,12 +389,25 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // will not close any streams.
   void MakeUnavailable();
 
+  // Closes all active streams with stream id's greater than
+  // |last_good_stream_id|, as well as any created or pending
+  // streams. Must be called only when |availability_state_| >=
+  // STATE_GOING_AWAY. After this function, DcheckGoingAway() will
+  // pass. May be called multiple times.
+  void StartGoingAway(SpdyStreamId last_good_stream_id, Error status);
+
+  // Must be called only when going away (i.e., DcheckGoingAway()
+  // passes). If there are no more active streams and the session
+  // isn't closed yet, close it.
+  void MaybeFinishGoingAway();
+
   // Retrieves information on the current state of the SPDY session as a
   // Value.  Caller takes possession of the returned value.
   base::Value* GetInfoAsValue() const;
 
   // Indicates whether the session is being reused after having successfully
-  // used to send/receive data in the past.
+  // used to send/receive data in the past or if the underlying socket was idle
+  // before being used for a SPDY session.
   bool IsReused() const;
 
   // Returns true if the underlying transport socket ever had any reads or
@@ -395,10 +436,15 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // available for testing and diagnostics.
   size_t num_active_streams() const { return active_streams_.size(); }
   size_t num_unclaimed_pushed_streams() const {
-      return unclaimed_pushed_streams_.size();
+    return unclaimed_pushed_streams_.size();
   }
   size_t num_created_streams() const { return created_streams_.size(); }
 
+  size_t num_pushed_streams() const { return num_pushed_streams_; }
+  size_t num_active_pushed_streams() const {
+    return num_active_pushed_streams_;
+  }
+
   size_t pending_create_stream_queue_size(RequestPriority priority) const {
     DCHECK_GE(priority, MINIMUM_PRIORITY);
     DCHECK_LE(priority, MAXIMUM_PRIORITY);
@@ -463,11 +509,15 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
     return buffered_spdy_framer_->GetDataFrameMaximumPayload();
   }
 
+  // https://http2.github.io/http2-spec/#TLSUsage mandates minimum security
+  // standards for TLS.
+  bool HasAcceptableTransportSecurity() const;
+
   // Must be used only by |pool_|.
   base::WeakPtr<SpdySession> GetWeakPtr();
 
   // HigherLayeredPool implementation:
-  virtual bool CloseOneIdleConnection() OVERRIDE;
+  bool CloseOneIdleConnection() override;
 
  private:
   friend class base::RefCounted<SpdySession>;
@@ -487,6 +537,15 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoReceiveLeaks);
   FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlNoSendLeaks);
   FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, SessionFlowControlEndToEnd);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, StreamIdSpaceExhausted);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, UnstallRacesWithStreamCreation);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, GoAwayOnSessionFlowControlError);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest,
+                           RejectPushedStreamExceedingConcurrencyLimit);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, IgnoreReservedRemoteStreamsCount);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest,
+                           CancelReservedStreamOnHeadersReceived);
+  FRIEND_TEST_ALL_PREFIXES(SpdySessionTest, RejectInvalidUnknownFrames);
 
   typedef std::deque<base::WeakPtr<SpdyStreamRequest> >
       PendingStreamRequestQueue;
@@ -520,9 +579,11 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
     // The session can process data on existing streams but will
     // refuse to create new ones.
     STATE_GOING_AWAY,
-    // The session has been closed, is waiting to be deleted, and will
-    // refuse to process any more data.
-    STATE_CLOSED
+    // The session is draining its write queue in preparation of closing.
+    // Further writes will not be queued, and further reads will not be issued
+    // (though the remainder of a current read may be processed). The session
+    // will be destroyed by its write loop once the write queue is drained.
+    STATE_DRAINING,
   };
 
   enum ReadState {
@@ -537,18 +598,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
     WRITE_STATE_DO_WRITE_COMPLETE,
   };
 
-  // The return value of DoCloseSession() describing what was done.
-  enum CloseSessionResult {
-    // The session was already closed so nothing was done.
-    SESSION_ALREADY_CLOSED,
-    // The session was moved into the closed state but was not removed
-    // from |pool_| (because we're in an IO loop).
-    SESSION_CLOSED_BUT_NOT_REMOVED,
-    // The session was moved into the closed state and removed from
-    // |pool_|.
-    SESSION_CLOSED_AND_REMOVED,
-  };
-
   // Checks whether a stream for the given |url| can be created or
   // retrieved from the set of unclaimed push streams. Returns OK if
   // so. Otherwise, the session is closed and an error <
@@ -582,6 +631,11 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // possible.
   void ProcessPendingStreamRequests();
 
+  bool TryCreatePushStream(SpdyStreamId stream_id,
+                           SpdyStreamId associated_stream_id,
+                           SpdyPriority priority,
+                           const SpdyHeaderBlock& headers);
+
   // Close the stream pointed to by the given iterator. Note that that
   // stream may hold the last reference to the session.
   void CloseActiveStreamIterator(ActiveStreamMap::iterator it, int status);
@@ -606,30 +660,31 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
                                SpdyRstStreamStatus status,
                                const std::string& description);
 
-  // Calls DoReadLoop and then if |availability_state_| is
-  // STATE_CLOSED, calls RemoveFromPool().
-  //
-  // Use this function instead of DoReadLoop when posting a task to
-  // pump the read loop.
+  // Calls DoReadLoop. Use this function instead of DoReadLoop when
+  // posting a task to pump the read loop.
   void PumpReadLoop(ReadState expected_read_state, int result);
 
   // Advance the ReadState state machine. |expected_read_state| is the
   // expected starting read state.
   //
-  // This function must always be called via PumpReadLoop() except for
-  // from InitializeWithSocket().
+  // This function must always be called via PumpReadLoop().
   int DoReadLoop(ReadState expected_read_state, int result);
   // The implementations of the states of the ReadState state machine.
   int DoRead();
   int DoReadComplete(int result);
 
-  // Calls DoWriteLoop and then if |availability_state_| is
-  // STATE_CLOSED, calls RemoveFromPool().
+  // Calls DoWriteLoop. If |availability_state_| is STATE_DRAINING and no
+  // writes remain, the session is removed from the session pool and
+  // destroyed.
   //
   // Use this function instead of DoWriteLoop when posting a task to
   // pump the write loop.
   void PumpWriteLoop(WriteState expected_write_state, int result);
 
+  // Iff the write loop is not currently active, posts a callback into
+  // PumpWriteLoop().
+  void MaybePostWriteLoop();
+
   // Advance the WriteState state machine. |expected_write_state| is
   // the expected starting write state.
   //
@@ -668,7 +723,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
                              RequestPriority priority);
 
   // Send the PING frame.
-  void WritePingFrame(uint32 unique_id);
+  void WritePingFrame(uint32 unique_id, bool is_ack);
 
   // Post a CheckPingStatus call after delay. Don't post if there is already
   // CheckPingStatus running.
@@ -679,7 +734,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   void CheckPingStatus(base::TimeTicks last_check_time);
 
   // Get a new stream id.
-  int GetNewStreamId();
+  SpdyStreamId GetNewStreamId();
 
   // Pushes the given frame with the given priority into the write
   // queue for the session.
@@ -732,36 +787,13 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   void DcheckGoingAway() const;
 
   // Calls DcheckGoingAway(), then DCHECKs that |availability_state_|
-  // == STATE_CLOSED, |error_on_close_| has a valid value, that there
-  // are no active streams or unclaimed pushed streams, and that the
-  // write queue is empty.
-  void DcheckClosed() const;
-
-  // Closes all active streams with stream id's greater than
-  // |last_good_stream_id|, as well as any created or pending
-  // streams. Must be called only when |availability_state_| >=
-  // STATE_GOING_AWAY. After this function, DcheckGoingAway() will
-  // pass. May be called multiple times.
-  void StartGoingAway(SpdyStreamId last_good_stream_id, Error status);
+  // == STATE_DRAINING, |error_on_close_| has a valid value, and that there
+  // are no active streams or unclaimed pushed streams.
+  void DcheckDraining() const;
 
-  // Must be called only when going away (i.e., DcheckGoingAway()
-  // passes). If there are no more active streams and the session
-  // isn't closed yet, close it.
-  void MaybeFinishGoingAway();
-
-  // If the stream is already closed, does nothing. Otherwise, moves
-  // the session to a closed state. Then, if we're in an IO loop,
-  // returns (as the IO loop will do the pool removal itself when its
-  // done). Otherwise, also removes |this| from |pool_|. The returned
-  // result describes what was done.
-  CloseSessionResult DoCloseSession(Error err, const std::string& description);
-
-  // Remove this session from its pool, which must exist. Must be
-  // called only when the session is closed.
-  //
-  // Must be called only via Pump{Read,Write}Loop() or
-  // DoCloseSession().
-  void RemoveFromPool();
+  // If the session is already draining, does nothing. Otherwise, moves
+  // the session to the draining state.
+  void DoDrainSession(Error err, const std::string& description);
 
   // Called right before closing a (possibly-inactive) stream for a
   // reason other than being requested to by the stream.
@@ -781,53 +813,51 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   void DeleteExpiredPushedStreams();
 
   // BufferedSpdyFramerVisitorInterface:
-  virtual void OnError(SpdyFramer::SpdyError error_code) OVERRIDE;
-  virtual void OnStreamError(SpdyStreamId stream_id,
-                             const std::string& description) OVERRIDE;
-  virtual void OnPing(SpdyPingId unique_id) OVERRIDE;
-  virtual void OnRstStream(SpdyStreamId stream_id,
-                           SpdyRstStreamStatus status) OVERRIDE;
-  virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
-                        SpdyGoAwayStatus status) OVERRIDE;
-  virtual void OnDataFrameHeader(SpdyStreamId stream_id,
-                                 size_t length,
-                                 bool fin) OVERRIDE;
-  virtual void OnStreamFrameData(SpdyStreamId stream_id,
-                                 const char* data,
-                                 size_t len,
-                                 bool fin) OVERRIDE;
-  virtual void OnSettings(bool clear_persisted) OVERRIDE;
-  virtual void OnSetting(
-      SpdySettingsIds id, uint8 flags, uint32 value) OVERRIDE;
-  virtual void OnWindowUpdate(SpdyStreamId stream_id,
-                              uint32 delta_window_size) OVERRIDE;
-  virtual void OnPushPromise(SpdyStreamId stream_id,
-                             SpdyStreamId promised_stream_id) OVERRIDE;
-  virtual void OnSynStream(SpdyStreamId stream_id,
-                           SpdyStreamId associated_stream_id,
-                           SpdyPriority priority,
-                           bool fin,
-                           bool unidirectional,
-                           const SpdyHeaderBlock& headers) OVERRIDE;
-  virtual void OnSynReply(
-      SpdyStreamId stream_id,
-      bool fin,
-      const SpdyHeaderBlock& headers) OVERRIDE;
-  virtual void OnHeaders(
-      SpdyStreamId stream_id,
-      bool fin,
-      const SpdyHeaderBlock& headers) OVERRIDE;
+  void OnError(SpdyFramer::SpdyError error_code) override;
+  void OnStreamError(SpdyStreamId stream_id,
+                     const std::string& description) override;
+  void OnPing(SpdyPingId unique_id, bool is_ack) override;
+  void OnRstStream(SpdyStreamId stream_id, SpdyRstStreamStatus status) override;
+  void OnGoAway(SpdyStreamId last_accepted_stream_id,
+                SpdyGoAwayStatus status) override;
+  void OnDataFrameHeader(SpdyStreamId stream_id,
+                         size_t length,
+                         bool fin) override;
+  void OnStreamFrameData(SpdyStreamId stream_id,
+                         const char* data,
+                         size_t len,
+                         bool fin) override;
+  void OnSettings(bool clear_persisted) override;
+  void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override;
+  void OnWindowUpdate(SpdyStreamId stream_id,
+                      uint32 delta_window_size) override;
+  void OnPushPromise(SpdyStreamId stream_id,
+                     SpdyStreamId promised_stream_id,
+                     const SpdyHeaderBlock& headers) override;
+  void OnSynStream(SpdyStreamId stream_id,
+                   SpdyStreamId associated_stream_id,
+                   SpdyPriority priority,
+                   bool fin,
+                   bool unidirectional,
+                   const SpdyHeaderBlock& headers) override;
+  void OnSynReply(SpdyStreamId stream_id,
+                  bool fin,
+                  const SpdyHeaderBlock& headers) override;
+  void OnHeaders(SpdyStreamId stream_id,
+                 bool has_priority,
+                 SpdyPriority priority,
+                 bool fin,
+                 const SpdyHeaderBlock& headers) override;
+  bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override;
 
   // SpdyFramerDebugVisitorInterface
-  virtual void OnSendCompressedFrame(
-      SpdyStreamId stream_id,
-      SpdyFrameType type,
-      size_t payload_len,
-      size_t frame_len) OVERRIDE;
-  virtual void OnReceiveCompressedFrame(
-      SpdyStreamId stream_id,
-      SpdyFrameType type,
-      size_t frame_len) OVERRIDE;
+  void OnSendCompressedFrame(SpdyStreamId stream_id,
+                             SpdyFrameType type,
+                             size_t payload_len,
+                             size_t frame_len) override;
+  void OnReceiveCompressedFrame(SpdyStreamId stream_id,
+                                SpdyFrameType type,
+                                size_t frame_len) override;
 
   // Called when bytes are consumed from a SpdyBuffer for a DATA frame
   // that is to be written or is being written. Increases the send
@@ -906,6 +936,10 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
     hung_interval_ = duration;
   }
 
+  void set_max_concurrent_pushed_streams(size_t value) {
+    max_concurrent_pushed_streams_ = value;
+  }
+
   int64 pings_in_flight() const { return pings_in_flight_; }
 
   uint32 next_ping_id() const { return next_ping_id_; }
@@ -920,12 +954,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // or NULL, if the transport is not SSL.
   SSLClientSocket* GetSSLClientSocket() const;
 
-  // Used for posting asynchronous IO tasks.  We use this even though
-  // SpdySession is refcounted because we don't need to keep the SpdySession
-  // alive if the last reference is within a RunnableMethod.  Just revoke the
-  // method.
-  base::WeakPtrFactory<SpdySession> weak_factory_;
-
   // Whether Do{Read,Write}Loop() is in the call stack. Useful for
   // making sure we don't destroy ourselves prematurely in that case.
   bool in_io_loop_;
@@ -942,13 +970,18 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   SpdySessionPool* pool_;
   const base::WeakPtr<HttpServerProperties> http_server_properties_;
 
+  TransportSecurityState* transport_security_state_;
+
   // The socket handle for this session.
   scoped_ptr<ClientSocketHandle> connection_;
 
   // The read buffer used to read data from the socket.
   scoped_refptr<IOBuffer> read_buffer_;
 
-  int stream_hi_water_mark_;  // The next stream id to use.
+  SpdyStreamId stream_hi_water_mark_;  // The next stream id to use.
+
+  // Used to ensure the server increments push stream ids correctly.
+  SpdyStreamId last_accepted_push_stream_id_;
 
   // Queue, for each priority, of pending stream requests that have
   // not yet been satisfied.
@@ -977,6 +1010,16 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   // |created_streams_| owns all its SpdyStream objects.
   CreatedStreamSet created_streams_;
 
+  // Number of pushed streams. All active streams are stored in
+  // |active_streams_|, but it's better to know the number of push streams
+  // without traversing the whole collection.
+  size_t num_pushed_streams_;
+
+  // Number of active pushed streams in |active_streams_|, i.e. not in reserved
+  // remote state. Streams in reserved state are not counted towards any
+  // concurrency limits.
+  size_t num_active_pushed_streams_;
+
   // The write queue.
   SpdyWriteQueue write_queue_;
 
@@ -1006,15 +1049,16 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   ReadState read_state_;
   WriteState write_state_;
 
-  // If the session was closed (i.e., |availability_state_| is
-  // STATE_CLOSED), then |error_on_close_| holds the error with which
-  // it was closed, which is < ERR_IO_PENDING. Otherwise, it is set to
-  // OK.
+  // If the session is closing (i.e., |availability_state_| is STATE_DRAINING),
+  // then |error_on_close_| holds the error with which it was closed, which
+  // may be OK (upon a polite GOAWAY) or an error < ERR_IO_PENDING otherwise.
+  // Initialized to OK.
   Error error_on_close_;
 
   // Limits
   size_t max_concurrent_streams_;  // 0 if no limit
   size_t max_concurrent_streams_limit_;
+  size_t max_concurrent_pushed_streams_;
 
   // Some statistics counters for the session.
   int streams_initiated_count_;
@@ -1121,6 +1165,12 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
   HostPortPair trusted_spdy_proxy_;
 
   TimeFunc time_func_;
+
+  // Used for posting asynchronous IO tasks.  We use this even though
+  // SpdySession is refcounted because we don't need to keep the SpdySession
+  // alive if the last reference is within a RunnableMethod.  Just revoke the
+  // method.
+  base::WeakPtrFactory<SpdySession> weak_factory_;
 };
 
 }  // namespace net