| Index: net/spdy/spdy_stream.h
|
| diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
|
| index b410226eea581816f40755abc344bec2321bd06d..cb5da04f96950edfd2ae8fff1a9f6154511395f2 100644
|
| --- a/net/spdy/spdy_stream.h
|
| +++ b/net/spdy/spdy_stream.h
|
| @@ -49,13 +49,20 @@ enum SpdyStreamType {
|
| SPDY_PUSH_STREAM
|
| };
|
|
|
| -// Returned by some SpdyStream::Delegate functions to indicate whether
|
| -// there's more data to send.
|
| +// 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
|
| };
|
|
|
| +// Returned by SpdyStream::OnResponseHeadersUpdated() to indicate
|
| +// whether the current response headers are complete or not.
|
| +enum SpdyResponseHeadersStatus {
|
| + RESPONSE_HEADERS_ARE_INCOMPLETE,
|
| + RESPONSE_HEADERS_ARE_COMPLETE
|
| +};
|
| +
|
| // The SpdyStream is used by the SpdySession 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
|
| @@ -71,30 +78,74 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| Delegate() {}
|
|
|
| // Called when the request headers have been sent. Never called
|
| - // for push streams.
|
| + // for push streams. Must not cause the stream to be closed.
|
| virtual void OnRequestHeadersSent() = 0;
|
|
|
| - // Called when the SYN_STREAM, SYN_REPLY, or HEADERS frames are received.
|
| - // Normal streams will receive a SYN_REPLY and optional HEADERS frames.
|
| - // Pushed streams will receive a SYN_STREAM and optional HEADERS frames.
|
| - // Because a stream may have a SYN_* frame and multiple HEADERS frames,
|
| - // this callback may be called multiple times.
|
| - // |status| indicates network error. Returns network error code.
|
| - virtual int OnResponseHeadersReceived(const SpdyHeaderBlock& response,
|
| - base::Time response_time,
|
| - int status) = 0;
|
| -
|
| - // Called when data is received. |buffer| may be NULL, which
|
| - // signals EOF. Must return OK if the data was received
|
| - // successfully, or a network error code otherwise.
|
| - virtual int OnDataReceived(scoped_ptr<SpdyBuffer> buffer) = 0;
|
| -
|
| - // Called when data is sent.
|
| + // WARNING: This function is complicated! Be sure to read the
|
| + // whole comment below if you're working with code that implements
|
| + // or calls this function.
|
| + //
|
| + // Called when the response headers are updated from the
|
| + // server. |response_headers| contains the set of all headers
|
| + // received up to this point; delegates can assume that any
|
| + // headers previously received remain unchanged.
|
| + //
|
| + // This is called at least once before any data is received. If
|
| + // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this will be
|
| + // called again when more headers are received until
|
| + // RESPONSE_HEADERS_ARE_COMPLETE is returned, and any data
|
| + // received before then will be treated as a protocol error.
|
| + //
|
| + // If RESPONSE_HEADERS_ARE_INCOMPLETE is returned, the delegate
|
| + // must not have closed the stream. Otherwise, if
|
| + // RESPONSE_HEADERS_ARE_COMPLETE is returned, the delegate has
|
| + // processed the headers successfully. However, it still may have
|
| + // closed the stream, e.g. if the headers indicated an error
|
| + // condition.
|
| + //
|
| + // Some type-specific behavior:
|
| + //
|
| + // - For bidirectional streams, this may be called even after
|
| + // data is received, but it is expected that
|
| + // RESPONSE_HEADERS_ARE_COMPLETE is always returned. If
|
| + // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
|
| + // treated as a protocol error.
|
| + //
|
| + // - For request/response streams, this function is called
|
| + // exactly once before data is received, and it is expected
|
| + // that RESPONSE_HEADERS_ARE_COMPLETE is returned. If
|
| + // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
|
| + // treated as a protocol error.
|
| + //
|
| + // - For push streams, it is expected that this function will be
|
| + // called until RESPONSE_HEADERS_ARE_COMPLETE is returned
|
| + // before any data is received; any deviation from this is
|
| + // treated as a protocol error.
|
| + //
|
| + // TODO(akalin): Treat headers received after data has been
|
| + // received as a protocol error for non-bidirectional streams.
|
| + virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated(
|
| + const SpdyHeaderBlock& response_headers) = 0;
|
| +
|
| + // Called when data is received after all required response
|
| + // headers have been received. |buffer| may be NULL, which signals
|
| + // EOF. Must return OK if the data was received successfully, or
|
| + // a network error code otherwise.
|
| + //
|
| + // May cause the stream to be closed.
|
| + virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) = 0;
|
| +
|
| + // Called when data is sent. Must not cause the stream to be
|
| + // closed.
|
| virtual void OnDataSent() = 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.
|
| + // access the stream after this is called. Must not cause the
|
| + // stream to be be (re-)closed.
|
| + //
|
| + // TODO(akalin): Allow this function to re-close the stream and
|
| + // handle it gracefully.
|
| virtual void OnClose(int status) = 0;
|
|
|
| protected:
|
| @@ -115,25 +166,26 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
|
|
| ~SpdyStream();
|
|
|
| - // Set new |delegate|. |delegate| must not be NULL. If it already
|
| - // received SYN_REPLY or data, OnResponseHeadersReceived() or
|
| - // OnDataReceived() will be called.
|
| + // 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);
|
| - Delegate* GetDelegate() { return delegate_; }
|
| + Delegate* GetDelegate();
|
|
|
| // 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_; }
|
|
|
| SpdyStreamId stream_id() const { return stream_id_; }
|
| void set_stream_id(SpdyStreamId stream_id) { stream_id_ = stream_id; }
|
|
|
| - // TODO(akalin): Remove these two functions.
|
| - bool response_received() const { return response_received_; }
|
| - void set_response_received() { response_received_ = true; }
|
| -
|
| const std::string& path() const { return path_; }
|
|
|
| RequestPriority priority() const { return priority_; }
|
| @@ -230,14 +282,27 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| base::Time GetRequestTime() const;
|
| void SetRequestTime(base::Time t);
|
|
|
| - // Called by the SpdySession when a response (e.g. a SYN_STREAM or
|
| - // SYN_REPLY) has been received for this stream. This is the entry
|
| - // point for a push stream. Returns a status code.
|
| - int OnResponseHeadersReceived(const SpdyHeaderBlock& response);
|
| -
|
| - // Called by the SpdySession when late-bound headers are received for a
|
| - // stream. Returns a status code.
|
| - int OnHeaders(const SpdyHeaderBlock& headers);
|
| + // Called at most once by the SpdySession when the initial response
|
| + // headers have been received for this stream, i.e., a SYN_REPLY (or
|
| + // SYN_STREAM for push streams) frame has been received. This is the
|
| + // entry point for a push stream. Returns a status code; if it is an
|
| + // error, the stream may have already been closed.
|
| + //
|
| + // TODO(akalin): Guarantee that the stream is already closed if an
|
| + // error is returned.
|
| + int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers,
|
| + base::Time response_time,
|
| + base::TimeTicks recv_first_byte_time);
|
| +
|
| + // Called by the SpdySession (only after
|
| + // OnInitialResponseHeadersReceived() has been called) when
|
| + // late-bound headers are received for a stream. Returns a status
|
| + // code; if it is an error, ths stream may have already been closed.
|
| + //
|
| + // TODO(akalin): Guarantee that the stream is already closed if an
|
| + // error is returned.
|
| + int OnAdditionalResponseHeadersReceived(
|
| + const SpdyHeaderBlock& additional_response_headers);
|
|
|
| // Called by the SpdySession when response data has been received
|
| // for this stream. This callback may be called multiple times as
|
| @@ -291,7 +356,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| // 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(scoped_ptr<SpdyHeaderBlock> headers,
|
| + int SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> request_headers,
|
| SpdySendStatus send_status);
|
|
|
| // Sends a DATA frame. The delegate will be notified via
|
| @@ -328,13 +393,15 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
|
|
| bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
|
|
|
| - // Returns true if the URL for this stream is known.
|
| - bool HasUrl() const;
|
| -
|
| - // Get the URL associated with this stream. Only valid when has_url() is
|
| - // true.
|
| + // Get the URL associated with this stream, or the empty GURL() if
|
| + // it is unknown.
|
| GURL GetUrl() const;
|
|
|
| + // Returns whether the URL for this stream is known.
|
| + //
|
| + // TODO(akalin): Remove this, as it's only used in tests.
|
| + bool HasUrl() const;
|
| +
|
| int GetProtocolVersion() const;
|
|
|
| private:
|
| @@ -373,8 +440,9 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| // be called after the stream has completed.
|
| void UpdateHistograms();
|
|
|
| - // When a server pushed stream is first created, this function is posted on
|
| - // the MessageLoop to replay all the data that the server has already sent.
|
| + // When a server-pushed stream is first created, this function is
|
| + // posted on the current MessageLoop to replay the data that the
|
| + // server has already sent.
|
| void PushedStreamReplayData();
|
|
|
| // Produces the SYN_STREAM frame for the stream. The stream must
|
| @@ -391,6 +459,15 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| // |pending_send_data_| is set.
|
| void QueueNextDataFrame();
|
|
|
| + // Merge the given headers into |response_headers_| and calls
|
| + // OnResponseHeadersUpdated() on the delegate (if attached).
|
| + // Returns a status code; if it is an error, the stream may have
|
| + // already been closed.
|
| + //
|
| + // TODO(akalin): Guarantee that the stream is already closed if an
|
| + // error is returned.
|
| + int MergeWithResponseHeaders(const SpdyHeaderBlock& new_response_headers);
|
| +
|
| const SpdyStreamType type_;
|
|
|
| base::WeakPtrFactory<SpdyStream> weak_ptr_factory_;
|
| @@ -416,7 +493,6 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| int32 unacked_recv_window_bytes_;
|
|
|
| ScopedBandwidthMetrics metrics_;
|
| - bool response_received_;
|
|
|
| scoped_refptr<SpdySession> session_;
|
|
|
| @@ -430,7 +506,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| //
|
| // TODO(akalin): Hang onto this only until we send it. This
|
| // necessitates stashing the URL separately.
|
| - scoped_ptr<SpdyHeaderBlock> request_;
|
| + scoped_ptr<SpdyHeaderBlock> request_headers_;
|
|
|
| // The data waiting to be sent.
|
| scoped_refptr<DrainableIOBuffer> pending_send_data_;
|
| @@ -439,7 +515,8 @@ class NET_EXPORT_PRIVATE SpdyStream {
|
| // For cached responses, this time could be "far" in the past.
|
| base::Time request_time_;
|
|
|
| - scoped_ptr<SpdyHeaderBlock> response_;
|
| + SpdyHeaderBlock response_headers_;
|
| + SpdyResponseHeadersStatus response_headers_status_;
|
| base::Time response_time_;
|
|
|
| State io_state_;
|
|
|