| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef NET_SPDY_SPDY_STREAM_H_ | 
 | #define NET_SPDY_SPDY_STREAM_H_ | 
 |  | 
 | #include <memory> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "base/compiler_specific.h" | 
 | #include "base/macros.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "net/base/io_buffer.h" | 
 | #include "net/base/net_export.h" | 
 | #include "net/base/request_priority.h" | 
 | #include "net/log/net_log_source.h" | 
 | #include "net/log/net_log_with_source.h" | 
 | #include "net/socket/next_proto.h" | 
 | #include "net/socket/ssl_client_socket.h" | 
 | #include "net/spdy/spdy_buffer.h" | 
 | #include "net/ssl/ssl_client_cert_type.h" | 
 | #include "net/third_party/quiche/src/spdy/core/spdy_framer.h" | 
 | #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" | 
 | #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" | 
 | #include "net/traffic_annotation/network_traffic_annotation.h" | 
 | #include "starboard/types.h" | 
 | #include "url/gurl.h" | 
 |  | 
 | namespace net { | 
 |  | 
 | class IPEndPoint; | 
 | struct LoadTimingInfo; | 
 | class SSLInfo; | 
 | class SpdySession; | 
 |  | 
 | enum SpdyStreamType { | 
 |   // The most general type of stream; there are no restrictions on | 
 |   // when data can be sent and received. | 
 |   SPDY_BIDIRECTIONAL_STREAM, | 
 |   // A stream where the client sends a request with possibly a body, | 
 |   // and the server then sends a response with a body. | 
 |   SPDY_REQUEST_RESPONSE_STREAM, | 
 |   // A server-initiated stream where the server just sends a response | 
 |   // with a body and the client does not send anything. | 
 |   SPDY_PUSH_STREAM | 
 | }; | 
 |  | 
 | // Passed to some SpdyStream functions to indicate whether there's | 
 | // more data to send. | 
 | enum SpdySendStatus { | 
 |   MORE_DATA_TO_SEND, | 
 |   NO_MORE_DATA_TO_SEND | 
 | }; | 
 |  | 
 | // SpdyStream is owned by SpdySession and is used to represent each stream known | 
 | // on the SpdySession.  This class provides interfaces for SpdySession to use. | 
 | // Streams can be created either by the client or by the server.  When they | 
 | // are initiated by the client, both the SpdySession and client object (such as | 
 | // a SpdyNetworkTransaction) will maintain a reference to the stream.  When | 
 | // initiated by the server, only the SpdySession will maintain any reference, | 
 | // until such a time as a client object requests a stream for the path. | 
 | class NET_EXPORT_PRIVATE SpdyStream { | 
 |  public: | 
 |   // Delegate handles protocol specific behavior of spdy stream. | 
 |   class NET_EXPORT_PRIVATE Delegate { | 
 |    public: | 
 |     Delegate() {} | 
 |  | 
 |     // Called when the request headers have been sent. Never called | 
 |     // for push streams. Must not cause the stream to be closed. | 
 |     virtual void OnHeadersSent() = 0; | 
 |  | 
 |     // OnHeadersReceived(), OnDataReceived(), OnTrailers(), and OnClose() | 
 |     // are guaranteed to be called in the following order: | 
 |     //   - OnHeadersReceived() exactly once; | 
 |     //   - OnDataReceived() zero or more times; | 
 |     //   - OnTrailers() zero or one times; | 
 |     //   - OnClose() exactly once. | 
 |  | 
 |     // Called when response headers have been received.  In case of a pushed | 
 |     // stream, the pushed request headers are also passed. | 
 |     virtual void OnHeadersReceived( | 
 |         const spdy::SpdyHeaderBlock& response_headers, | 
 |         const spdy::SpdyHeaderBlock* pushed_request_headers) = 0; | 
 |  | 
 |     // Called when data is received.  |buffer| may be NULL, which signals EOF. | 
 |     // May cause the stream to be closed. | 
 |     virtual void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) = 0; | 
 |  | 
 |     // Called when data is sent.  Must not cause the stream to be closed. | 
 |     virtual void OnDataSent() = 0; | 
 |  | 
 |     // Called when trailers are received. | 
 |     virtual void OnTrailers(const spdy::SpdyHeaderBlock& trailers) = 0; | 
 |  | 
 |     // Called when SpdyStream is closed. No other delegate functions | 
 |     // will be called after this is called, and the delegate must not | 
 |     // access the stream after this is called. Must not cause the | 
 |     // stream to be (re-)closed. | 
 |     // | 
 |     // TODO(akalin): Allow this function to re-close the stream and | 
 |     // handle it gracefully. | 
 |     virtual void OnClose(int status) = 0; | 
 |  | 
 |     virtual NetLogSource source_dependency() const = 0; | 
 |  | 
 |    protected: | 
 |     virtual ~Delegate() {} | 
 |  | 
 |    private: | 
 |     DISALLOW_COPY_AND_ASSIGN(Delegate); | 
 |   }; | 
 |  | 
 |   // SpdyStream constructor | 
 |   SpdyStream(SpdyStreamType type, | 
 |              const base::WeakPtr<SpdySession>& session, | 
 |              const GURL& url, | 
 |              RequestPriority priority, | 
 |              int32_t initial_send_window_size, | 
 |              int32_t max_recv_window_size, | 
 |              const NetLogWithSource& net_log, | 
 |              const NetworkTrafficAnnotationTag& traffic_annotation); | 
 |  | 
 |   ~SpdyStream(); | 
 |  | 
 |   // Set the delegate, which must not be NULL. Must not be called more | 
 |   // than once. For push streams, calling this may cause buffered data | 
 |   // to be sent to the delegate (from a posted task). | 
 |   void SetDelegate(Delegate* delegate); | 
 |  | 
 |   // Detach the delegate from the stream, which must not yet be | 
 |   // closed, and cancel it. | 
 |   void DetachDelegate(); | 
 |  | 
 |   // The time at which the first bytes of the response were received | 
 |   // from the server, or null if the response hasn't been received | 
 |   // yet. | 
 |   base::Time response_time() const { return response_time_; } | 
 |  | 
 |   SpdyStreamType type() const { return type_; } | 
 |  | 
 |   spdy::SpdyStreamId stream_id() const { return stream_id_; } | 
 |   void set_stream_id(spdy::SpdyStreamId stream_id) { stream_id_ = stream_id; } | 
 |  | 
 |   const GURL& url() const { return url_; } | 
 |  | 
 |   RequestPriority priority() const { return priority_; } | 
 |  | 
 |   // Update priority and send PRIORITY frames on the wire if necessary. | 
 |   void SetPriority(RequestPriority priority); | 
 |  | 
 |   int32_t send_window_size() const { return send_window_size_; } | 
 |  | 
 |   int32_t recv_window_size() const { return recv_window_size_; } | 
 |  | 
 |   bool send_stalled_by_flow_control() const { | 
 |     return send_stalled_by_flow_control_; | 
 |   } | 
 |  | 
 |   void set_send_stalled_by_flow_control(bool stalled) { | 
 |     send_stalled_by_flow_control_ = stalled; | 
 |   } | 
 |  | 
 |   // Called by the session to adjust this stream's send window size by | 
 |   // |delta_window_size|, which is the difference between the | 
 |   // spdy::SETTINGS_INITIAL_WINDOW_SIZE in the most recent SETTINGS frame | 
 |   // and the previous initial send window size, possibly unstalling | 
 |   // this stream. Although |delta_window_size| may cause this stream's | 
 |   // send window size to go negative, it must not cause it to wrap | 
 |   // around in either direction. Does nothing if the stream is already | 
 |   // closed. | 
 |   // Returns true if successful.  Returns false if |send_window_size_| | 
 |   // would exceed 2^31-1 after the update, see RFC7540 Section 6.9.2. | 
 |   // Note that |send_window_size_| should not possibly underflow. | 
 |   bool AdjustSendWindowSize(int32_t delta_window_size) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Called when bytes are consumed from a SpdyBuffer for a DATA frame | 
 |   // that is to be written or is being written. Increases the send | 
 |   // window size accordingly if some or all of the SpdyBuffer is being | 
 |   // discarded. | 
 |   // | 
 |   // If stream flow control is turned off, this must not be called. | 
 |   void OnWriteBufferConsumed(size_t frame_payload_size, | 
 |                              size_t consume_size, | 
 |                              SpdyBuffer::ConsumeSource consume_source); | 
 |  | 
 |   // Called by the session to increase this stream's send window size | 
 |   // by |delta_window_size| (which must be at least 1) from a received | 
 |   // WINDOW_UPDATE frame or from a dropped DATA frame that was | 
 |   // intended to be sent, possibly unstalling this stream. If | 
 |   // |delta_window_size| would cause this stream's send window size to | 
 |   // overflow, calls into the session to reset this stream. Does | 
 |   // nothing if the stream is already closed. | 
 |   // | 
 |   // If stream flow control is turned off, this must not be called. | 
 |   void IncreaseSendWindowSize(int32_t delta_window_size); | 
 |  | 
 |   // If stream flow control is turned on, called by the session to | 
 |   // decrease this stream's send window size by |delta_window_size|, | 
 |   // which must be at least 0 and at most kMaxSpdyFrameChunkSize. | 
 |   // |delta_window_size| must not cause this stream's send window size | 
 |   // to go negative. Does nothing if the stream is already closed. | 
 |   // | 
 |   // If stream flow control is turned off, this must not be called. | 
 |   void DecreaseSendWindowSize(int32_t delta_window_size); | 
 |  | 
 |   // Called when bytes are consumed by the delegate from a SpdyBuffer | 
 |   // containing received data. Increases the receive window size | 
 |   // accordingly. | 
 |   // | 
 |   // If stream flow control is turned off, this must not be called. | 
 |   void OnReadBufferConsumed(size_t consume_size, | 
 |                             SpdyBuffer::ConsumeSource consume_source); | 
 |  | 
 |   // Called by OnReadBufferConsume to increase this stream's receive | 
 |   // window size by |delta_window_size|, which must be at least 1 and | 
 |   // must not cause this stream's receive window size to overflow, | 
 |   // possibly also sending a WINDOW_UPDATE frame. Does nothing if the | 
 |   // stream is not active. | 
 |   // | 
 |   // If stream flow control is turned off, this must not be called. | 
 |   void IncreaseRecvWindowSize(int32_t delta_window_size); | 
 |  | 
 |   // Called by OnDataReceived or OnPaddingConsumed (which are in turn called by | 
 |   // the session) to decrease this stream's receive window size by | 
 |   // |delta_window_size|, which must be at least 1.  May close the stream on | 
 |   // flow control error. | 
 |   // | 
 |   // If stream flow control is turned off or the stream is not active, | 
 |   // this must not be called. | 
 |   void DecreaseRecvWindowSize(int32_t delta_window_size); | 
 |  | 
 |   int GetPeerAddress(IPEndPoint* address) const; | 
 |   int GetLocalAddress(IPEndPoint* address) const; | 
 |  | 
 |   // Returns true if the underlying transport socket ever had any reads or | 
 |   // writes. | 
 |   bool WasEverUsed() const; | 
 |  | 
 |   const NetLogWithSource& net_log() const { return net_log_; } | 
 |  | 
 |   base::Time GetRequestTime() const; | 
 |   void SetRequestTime(base::Time t); | 
 |  | 
 |   // Called by SpdySession when headers are received for this stream.  May close | 
 |   // the stream. | 
 |   void OnHeadersReceived(const spdy::SpdyHeaderBlock& response_headers, | 
 |                          base::Time response_time, | 
 |                          base::TimeTicks recv_first_byte_time); | 
 |  | 
 |   // Called by the SpdySession when a frame carrying request headers opening a | 
 |   // push stream is received. Stream transits to STATE_RESERVED_REMOTE state. | 
 |   void OnPushPromiseHeadersReceived(spdy::SpdyHeaderBlock headers, GURL url); | 
 |  | 
 |   // Called by the SpdySession when response data has been received | 
 |   // for this stream.  This callback may be called multiple times as | 
 |   // data arrives from the network, and will never be called prior to | 
 |   // OnResponseHeadersReceived. | 
 |   // | 
 |   // |buffer| contains the data received, or NULL if the stream is | 
 |   //          being closed.  The stream must copy any data from this | 
 |   //          buffer before returning from this callback. | 
 |   // | 
 |   // |length| is the number of bytes received (at most 2^24 - 1) or 0 if | 
 |   //          the stream is being closed. | 
 |   void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer); | 
 |  | 
 |   // Called by the SpdySession when padding is consumed to allow for the stream | 
 |   // receiving window to be updated. | 
 |   void OnPaddingConsumed(size_t len); | 
 |  | 
 |   // Called by the SpdySession when a frame has been successfully and completely | 
 |   // written. |frame_size| is the total size of the logical frame in bytes, | 
 |   // including framing overhead.  For fragmented headers, this is the total size | 
 |   // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames. | 
 |   void OnFrameWriteComplete(spdy::SpdyFrameType frame_type, size_t frame_size); | 
 |  | 
 |   // HEADERS-specific write handler invoked by OnFrameWriteComplete(). | 
 |   int OnHeadersSent(); | 
 |  | 
 |   // DATA-specific write handler invoked by OnFrameWriteComplete(). | 
 |   // If more data is already available to be written, the next write is | 
 |   // queued and ERR_IO_PENDING is returned. Returns OK otherwise. | 
 |   int OnDataSent(size_t frame_size); | 
 |  | 
 |   // Called by the SpdySession when the request is finished.  This callback | 
 |   // will always be called at the end of the request and signals to the | 
 |   // stream that the stream has no more network events.  No further callbacks | 
 |   // to the stream will be made after this call.  Must be called before | 
 |   // SpdyStream is destroyed. | 
 |   // |status| is an error code or OK. | 
 |   void OnClose(int status); | 
 |  | 
 |   // Called by the SpdySession to log stream related errors. | 
 |   void LogStreamError(int error, const std::string& description); | 
 |  | 
 |   // If this stream is active, reset it, and close it otherwise. In | 
 |   // either case the stream is deleted. | 
 |   void Cancel(int error); | 
 |  | 
 |   // Close this stream without sending a RST_STREAM and delete | 
 |   // it. | 
 |   void Close(); | 
 |  | 
 |   // Must be used only by |session_|. | 
 |   base::WeakPtr<SpdyStream> GetWeakPtr(); | 
 |  | 
 |   // Interface for the delegate to use. | 
 |  | 
 |   // Only one send can be in flight at a time, except for push | 
 |   // streams, which must not send anything. | 
 |  | 
 |   // Sends the request headers. The delegate is called back via OnHeadersSent() | 
 |   // when the request headers have completed sending. |send_status| must be | 
 |   // MORE_DATA_TO_SEND for bidirectional streams; for request/response streams, | 
 |   // it must be MORE_DATA_TO_SEND if the request has data to upload, or | 
 |   // NO_MORE_DATA_TO_SEND if not. | 
 |   int SendRequestHeaders(spdy::SpdyHeaderBlock request_headers, | 
 |                          SpdySendStatus send_status); | 
 |  | 
 |   // Sends a DATA frame. The delegate will be notified via | 
 |   // OnDataSent() when the send is complete. |send_status| must be | 
 |   // MORE_DATA_TO_SEND for bidirectional streams; for request/response | 
 |   // streams, it must be MORE_DATA_TO_SEND if there is more data to | 
 |   // upload, or NO_MORE_DATA_TO_SEND if not. | 
 |   // Must not be called until Delegate::OnHeadersSent() is called. | 
 |   void SendData(IOBuffer* data, int length, SpdySendStatus send_status); | 
 |  | 
 |   // Fills SSL info in |ssl_info| and returns true when SSL is in use. | 
 |   bool GetSSLInfo(SSLInfo* ssl_info) const; | 
 |  | 
 |   // Returns true if ALPN was negotiated for the underlying socket. | 
 |   bool WasAlpnNegotiated() const; | 
 |  | 
 |   // Returns the protocol negotiated via ALPN for the underlying socket. | 
 |   NextProto GetNegotiatedProtocol() const; | 
 |  | 
 |   // If the stream is stalled on sending data, but the session is not | 
 |   // stalled on sending data and |send_window_size_| is positive, then | 
 |   // set |send_stalled_by_flow_control_| to false and unstall the data | 
 |   // sending. Called by the session or by the stream itself. Must be | 
 |   // called only when the stream is still open. | 
 |   enum ShouldRequeueStream { Requeue, DoNotRequeue }; | 
 |   ShouldRequeueStream PossiblyResumeIfSendStalled(); | 
 |  | 
 |   // Returns whether or not this stream is closed. Note that the only | 
 |   // time a stream is closed and not deleted is in its delegate's | 
 |   // OnClose() method. | 
 |   bool IsClosed() const; | 
 |  | 
 |   // Returns whether the streams local endpoint is closed. | 
 |   // The remote endpoint may still be active. | 
 |   bool IsLocallyClosed() const; | 
 |  | 
 |   // Returns whether this stream is IDLE: request and response headers | 
 |   // have neither been sent nor receieved. | 
 |   bool IsIdle() const; | 
 |  | 
 |   // Returns whether or not this stream is fully open: that request and | 
 |   // response headers are complete, and it is not in a half-closed state. | 
 |   bool IsOpen() const; | 
 |  | 
 |   // Returns whether the stream is reserved by remote endpoint: server has sent | 
 |   // intended request headers for a pushed stream, but haven't started response | 
 |   // yet. | 
 |   bool IsReservedRemote() const; | 
 |  | 
 |   int response_status() const { return response_status_; } | 
 |  | 
 |   void AddRawReceivedBytes(size_t received_bytes); | 
 |   void AddRawSentBytes(size_t sent_bytes); | 
 |  | 
 |   int64_t raw_received_bytes() const { return raw_received_bytes_; } | 
 |   int64_t raw_sent_bytes() const { return raw_sent_bytes_; } | 
 |   int recv_bytes() const { return recv_bytes_; } | 
 |   bool ShouldRetryRSTPushStream() const; | 
 |  | 
 |   bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const; | 
 |  | 
 |   const spdy::SpdyHeaderBlock& request_headers() const { | 
 |     return request_headers_; | 
 |   } | 
 |   const spdy::SpdyHeaderBlock& response_headers() const { | 
 |     return response_headers_; | 
 |   } | 
 |  | 
 |   // Returns the estimate of dynamically allocated memory in bytes. | 
 |   size_t EstimateMemoryUsage() const; | 
 |  | 
 |   const NetworkTrafficAnnotationTag traffic_annotation() const { | 
 |     return traffic_annotation_; | 
 |   } | 
 |  | 
 |  private: | 
 |   class HeadersBufferProducer; | 
 |  | 
 |   // SpdyStream states and transitions are modeled | 
 |   // on the HTTP/2 stream state machine. All states and transitions | 
 |   // are modeled, with the exceptions of RESERVED_LOCAL (the client | 
 |   // cannot initate push streams), and the transition to OPEN due to | 
 |   // a remote HEADERS (the client can only initate streams). | 
 |   enum State { | 
 |     STATE_IDLE, | 
 |     STATE_OPEN, | 
 |     STATE_HALF_CLOSED_LOCAL_UNCLAIMED, | 
 |     STATE_HALF_CLOSED_LOCAL, | 
 |     STATE_HALF_CLOSED_REMOTE, | 
 |     STATE_RESERVED_REMOTE, | 
 |     STATE_CLOSED, | 
 |   }; | 
 |  | 
 |   // Per RFC 7540 Section 8.1, an HTTP response consists of: | 
 |   // * zero or more header blocks with informational (1xx) HTTP status, | 
 |   // * one header block, | 
 |   // * zero or more DATA frames, | 
 |   // * zero or one header block ("trailers"). | 
 |   // Each header block must have a ":status" header field.  SpdyStream enforces | 
 |   // these requirements, and resets the stream if they are not met. | 
 |   enum ResponseState { | 
 |     READY_FOR_HEADERS, | 
 |     READY_FOR_DATA_OR_TRAILERS, | 
 |     TRAILERS_RECEIVED | 
 |   }; | 
 |  | 
 |   // Update the histograms.  Can safely be called repeatedly, but should only | 
 |   // be called after the stream has completed. | 
 |   void UpdateHistograms(); | 
 |  | 
 |   // When a server-push stream is claimed by SetDelegate(), this function is | 
 |   // posted on the current MessageLoop to replay everything the server has sent. | 
 |   // From the perspective of SpdyStream's state machine, headers, data, and | 
 |   // FIN states received prior to the delegate being attached have not yet been | 
 |   // read. While buffered by |pending_recv_data_| it's not until | 
 |   // PushedStreamReplay() is invoked that reads are considered | 
 |   // to have occurred, driving the state machine forward. | 
 |   void PushedStreamReplay(); | 
 |  | 
 |   // Produces the HEADERS frame for the stream. The stream must | 
 |   // already be activated. | 
 |   std::unique_ptr<spdy::SpdySerializedFrame> ProduceHeadersFrame(); | 
 |  | 
 |   // Queues the send for next frame of the remaining data in | 
 |   // |pending_send_data_|. Must be called only when | 
 |   // |pending_send_data_| is set. | 
 |   void QueueNextDataFrame(); | 
 |  | 
 |   // Saves the given headers into |response_headers_| and calls | 
 |   // OnHeadersReceived() on the delegate if attached. | 
 |   void SaveResponseHeaders(const spdy::SpdyHeaderBlock& response_headers); | 
 |  | 
 |   static std::string DescribeState(State state); | 
 |  | 
 |   const SpdyStreamType type_; | 
 |  | 
 |   spdy::SpdyStreamId stream_id_; | 
 |   const GURL url_; | 
 |   RequestPriority priority_; | 
 |  | 
 |   bool send_stalled_by_flow_control_; | 
 |  | 
 |   // Current send window size. | 
 |   int32_t send_window_size_; | 
 |  | 
 |   // Maximum receive window size.  Each time a WINDOW_UPDATE is sent, it | 
 |   // restores the receive window size to this value. | 
 |   int32_t max_recv_window_size_; | 
 |  | 
 |   // Sum of |session_unacked_recv_window_bytes_| and current receive window | 
 |   // size. | 
 |   // TODO(bnc): Rename or change semantics so that |window_size_| is actual | 
 |   // window size. | 
 |   int32_t recv_window_size_; | 
 |  | 
 |   // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession, | 
 |   // and this member keeps count of them until the corresponding WINDOW_UPDATEs | 
 |   // are sent. | 
 |   int32_t unacked_recv_window_bytes_; | 
 |  | 
 |   const base::WeakPtr<SpdySession> session_; | 
 |  | 
 |   // The transaction should own the delegate. | 
 |   SpdyStream::Delegate* delegate_; | 
 |  | 
 |   // The headers for the request to send. | 
 |   bool request_headers_valid_; | 
 |   spdy::SpdyHeaderBlock request_headers_; | 
 |  | 
 |   // Data waiting to be sent, and the close state of the local endpoint | 
 |   // after the data is fully written. | 
 |   scoped_refptr<DrainableIOBuffer> pending_send_data_; | 
 |   SpdySendStatus pending_send_status_; | 
 |  | 
 |   // Data waiting to be received, and the close state of the remote endpoint | 
 |   // after the data is fully read. Specifically, data received before the | 
 |   // delegate is attached must be buffered and later replayed. A remote FIN | 
 |   // is represented by a final, zero-length buffer. | 
 |   std::vector<std::unique_ptr<SpdyBuffer>> pending_recv_data_; | 
 |  | 
 |   // The time at which the request was made that resulted in this response. | 
 |   // For cached responses, this time could be "far" in the past. | 
 |   base::Time request_time_; | 
 |  | 
 |   spdy::SpdyHeaderBlock response_headers_; | 
 |   ResponseState response_state_; | 
 |   base::Time response_time_; | 
 |  | 
 |   State io_state_; | 
 |  | 
 |   // Since we buffer the response, we also buffer the response status. | 
 |   // Not valid until the stream is closed. | 
 |   int response_status_; | 
 |  | 
 |   NetLogWithSource net_log_; | 
 |  | 
 |   base::TimeTicks send_time_; | 
 |   base::TimeTicks recv_first_byte_time_; | 
 |   base::TimeTicks recv_last_byte_time_; | 
 |  | 
 |   // Number of bytes that have been received on this stream, including frame | 
 |   // overhead and headers. | 
 |   int64_t raw_received_bytes_; | 
 |   // Number of bytes that have been sent on this stream, including frame | 
 |   // overhead and headers. | 
 |   int64_t raw_sent_bytes_; | 
 |  | 
 |   // Number of data bytes that have been sent/received on this stream, not | 
 |   // including frame overhead. Note that this does not count headers. | 
 |   int send_bytes_; | 
 |   int recv_bytes_; | 
 |  | 
 |   // Guards calls of delegate write handlers ensuring |this| is not destroyed. | 
 |   // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked | 
 |   // down. | 
 |   bool write_handler_guard_; | 
 |  | 
 |   const NetworkTrafficAnnotationTag traffic_annotation_; | 
 |  | 
 |   base::WeakPtrFactory<SpdyStream> weak_ptr_factory_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(SpdyStream); | 
 | }; | 
 |  | 
 | }  // namespace net | 
 |  | 
 | #endif  // NET_SPDY_SPDY_STREAM_H_ |