Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef NET_SPDY_SPDY_STREAM_H_ |
| 6 | #define NET_SPDY_SPDY_STREAM_H_ |
| 7 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 8 | #include <deque> |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 9 | #include <string> |
| 10 | #include <vector> |
| 11 | |
| 12 | #include "base/basictypes.h" |
| 13 | #include "base/memory/ref_counted.h" |
| 14 | #include "base/memory/scoped_ptr.h" |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 15 | #include "base/memory/scoped_vector.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 16 | #include "base/memory/weak_ptr.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 17 | #include "net/base/bandwidth_metrics.h" |
| 18 | #include "net/base/io_buffer.h" |
| 19 | #include "net/base/net_export.h" |
| 20 | #include "net/base/net_log.h" |
| 21 | #include "net/base/request_priority.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 22 | #include "net/socket/ssl_client_socket.h" |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 23 | #include "net/spdy/spdy_buffer.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 24 | #include "net/spdy/spdy_framer.h" |
| 25 | #include "net/spdy/spdy_header_block.h" |
| 26 | #include "net/spdy/spdy_protocol.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 27 | #include "net/ssl/server_bound_cert_service.h" |
| 28 | #include "net/ssl/ssl_client_cert_type.h" |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 29 | #include "url/gurl.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 30 | |
| 31 | namespace net { |
| 32 | |
| 33 | class AddressList; |
| 34 | class IPEndPoint; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 35 | struct LoadTimingInfo; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 36 | class SSLCertRequestInfo; |
| 37 | class SSLInfo; |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 38 | class SpdySession; |
| 39 | |
| 40 | enum SpdyStreamType { |
| 41 | // The most general type of stream; there are no restrictions on |
| 42 | // when data can be sent and received. |
| 43 | SPDY_BIDIRECTIONAL_STREAM, |
| 44 | // A stream where the client sends a request with possibly a body, |
| 45 | // and the server then sends a response with a body. |
| 46 | SPDY_REQUEST_RESPONSE_STREAM, |
| 47 | // A server-initiated stream where the server just sends a response |
| 48 | // with a body and the client does not send anything. |
| 49 | SPDY_PUSH_STREAM |
| 50 | }; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 51 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 52 | // Passed to some SpdyStream functions to indicate whether there's |
| 53 | // more data to send. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 54 | enum SpdySendStatus { |
| 55 | MORE_DATA_TO_SEND, |
| 56 | NO_MORE_DATA_TO_SEND |
| 57 | }; |
| 58 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 59 | // Returned by SpdyStream::OnResponseHeadersUpdated() to indicate |
| 60 | // whether the current response headers are complete or not. |
| 61 | enum SpdyResponseHeadersStatus { |
| 62 | RESPONSE_HEADERS_ARE_INCOMPLETE, |
| 63 | RESPONSE_HEADERS_ARE_COMPLETE |
| 64 | }; |
| 65 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 66 | // The SpdyStream is used by the SpdySession to represent each stream known |
| 67 | // on the SpdySession. This class provides interfaces for SpdySession to use. |
| 68 | // Streams can be created either by the client or by the server. When they |
| 69 | // are initiated by the client, both the SpdySession and client object (such as |
| 70 | // a SpdyNetworkTransaction) will maintain a reference to the stream. When |
| 71 | // initiated by the server, only the SpdySession will maintain any reference, |
| 72 | // until such a time as a client object requests a stream for the path. |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 73 | class NET_EXPORT_PRIVATE SpdyStream { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 74 | public: |
| 75 | // Delegate handles protocol specific behavior of spdy stream. |
| 76 | class NET_EXPORT_PRIVATE Delegate { |
| 77 | public: |
| 78 | Delegate() {} |
| 79 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 80 | // Called when the request headers have been sent. Never called |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 81 | // for push streams. Must not cause the stream to be closed. |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 82 | virtual void OnRequestHeadersSent() = 0; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 83 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 84 | // WARNING: This function is complicated! Be sure to read the |
| 85 | // whole comment below if you're working with code that implements |
| 86 | // or calls this function. |
| 87 | // |
| 88 | // Called when the response headers are updated from the |
| 89 | // server. |response_headers| contains the set of all headers |
| 90 | // received up to this point; delegates can assume that any |
| 91 | // headers previously received remain unchanged. |
| 92 | // |
| 93 | // This is called at least once before any data is received. If |
| 94 | // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this will be |
| 95 | // called again when more headers are received until |
| 96 | // RESPONSE_HEADERS_ARE_COMPLETE is returned, and any data |
| 97 | // received before then will be treated as a protocol error. |
| 98 | // |
| 99 | // If RESPONSE_HEADERS_ARE_INCOMPLETE is returned, the delegate |
| 100 | // must not have closed the stream. Otherwise, if |
| 101 | // RESPONSE_HEADERS_ARE_COMPLETE is returned, the delegate has |
| 102 | // processed the headers successfully. However, it still may have |
| 103 | // closed the stream, e.g. if the headers indicated an error |
| 104 | // condition. |
| 105 | // |
| 106 | // Some type-specific behavior: |
| 107 | // |
| 108 | // - For bidirectional streams, this may be called even after |
| 109 | // data is received, but it is expected that |
| 110 | // RESPONSE_HEADERS_ARE_COMPLETE is always returned. If |
| 111 | // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is |
| 112 | // treated as a protocol error. |
| 113 | // |
| 114 | // - For request/response streams, this function is called |
| 115 | // exactly once before data is received, and it is expected |
| 116 | // that RESPONSE_HEADERS_ARE_COMPLETE is returned. If |
| 117 | // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is |
| 118 | // treated as a protocol error. |
| 119 | // |
| 120 | // - For push streams, it is expected that this function will be |
| 121 | // called until RESPONSE_HEADERS_ARE_COMPLETE is returned |
| 122 | // before any data is received; any deviation from this is |
| 123 | // treated as a protocol error. |
| 124 | // |
| 125 | // TODO(akalin): Treat headers received after data has been |
| 126 | // received as a protocol error for non-bidirectional streams. |
| 127 | virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated( |
| 128 | const SpdyHeaderBlock& response_headers) = 0; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 129 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 130 | // Called when data is received after all required response |
| 131 | // headers have been received. |buffer| may be NULL, which signals |
| 132 | // EOF. Must return OK if the data was received successfully, or |
| 133 | // a network error code otherwise. |
| 134 | // |
| 135 | // May cause the stream to be closed. |
| 136 | virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) = 0; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 137 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 138 | // Called when data is sent. Must not cause the stream to be |
| 139 | // closed. |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 140 | virtual void OnDataSent() = 0; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 141 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 142 | // Called when SpdyStream is closed. No other delegate functions |
| 143 | // will be called after this is called, and the delegate must not |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 144 | // access the stream after this is called. Must not cause the |
| 145 | // stream to be be (re-)closed. |
| 146 | // |
| 147 | // TODO(akalin): Allow this function to re-close the stream and |
| 148 | // handle it gracefully. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 149 | virtual void OnClose(int status) = 0; |
| 150 | |
| 151 | protected: |
| 152 | virtual ~Delegate() {} |
| 153 | |
| 154 | private: |
| 155 | DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 156 | }; |
| 157 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 158 | // SpdyStream constructor |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 159 | SpdyStream(SpdyStreamType type, |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 160 | const base::WeakPtr<SpdySession>& session, |
| 161 | const GURL& url, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 162 | RequestPriority priority, |
| 163 | int32 initial_send_window_size, |
| 164 | int32 initial_recv_window_size, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 165 | const BoundNetLog& net_log); |
| 166 | |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 167 | ~SpdyStream(); |
| 168 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 169 | // Set the delegate, which must not be NULL. Must not be called more |
| 170 | // than once. For push streams, calling this may cause buffered data |
| 171 | // to be sent to the delegate (from a posted task). |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 172 | void SetDelegate(Delegate* delegate); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 173 | |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 174 | // Detach the delegate from the stream, which must not yet be |
| 175 | // closed, and cancel it. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 176 | void DetachDelegate(); |
| 177 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 178 | // The time at which the first bytes of the response were received |
| 179 | // from the server, or null if the response hasn't been received |
| 180 | // yet. |
| 181 | base::Time response_time() const { return response_time_; } |
| 182 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 183 | SpdyStreamType type() const { return type_; } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 184 | |
| 185 | SpdyStreamId stream_id() const { return stream_id_; } |
| 186 | void set_stream_id(SpdyStreamId stream_id) { stream_id_ = stream_id; } |
| 187 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 188 | const GURL& url() const { return url_; } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 189 | |
| 190 | RequestPriority priority() const { return priority_; } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 191 | |
| 192 | int32 send_window_size() const { return send_window_size_; } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 193 | |
| 194 | int32 recv_window_size() const { return recv_window_size_; } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 195 | |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 196 | bool send_stalled_by_flow_control() const { |
| 197 | return send_stalled_by_flow_control_; |
| 198 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 199 | |
| 200 | void set_send_stalled_by_flow_control(bool stalled) { |
| 201 | send_stalled_by_flow_control_ = stalled; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 202 | } |
| 203 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 204 | // Called by the session to adjust this stream's send window size by |
| 205 | // |delta_window_size|, which is the difference between the |
| 206 | // SETTINGS_INITIAL_WINDOW_SIZE in the most recent SETTINGS frame |
| 207 | // and the previous initial send window size, possibly unstalling |
| 208 | // this stream. Although |delta_window_size| may cause this stream's |
| 209 | // send window size to go negative, it must not cause it to wrap |
| 210 | // around in either direction. Does nothing if the stream is already |
| 211 | // closed. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 212 | // |
| 213 | // If stream flow control is turned off, this must not be called. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 214 | void AdjustSendWindowSize(int32 delta_window_size); |
| 215 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 216 | // Called when bytes are consumed from a SpdyBuffer for a DATA frame |
| 217 | // that is to be written or is being written. Increases the send |
| 218 | // window size accordingly if some or all of the SpdyBuffer is being |
| 219 | // discarded. |
| 220 | // |
| 221 | // If stream flow control is turned off, this must not be called. |
| 222 | void OnWriteBufferConsumed(size_t frame_payload_size, |
| 223 | size_t consume_size, |
| 224 | SpdyBuffer::ConsumeSource consume_source); |
| 225 | |
| 226 | // Called by the session to increase this stream's send window size |
| 227 | // by |delta_window_size| (which must be at least 1) from a received |
| 228 | // WINDOW_UPDATE frame or from a dropped DATA frame that was |
| 229 | // intended to be sent, possibly unstalling this stream. If |
| 230 | // |delta_window_size| would cause this stream's send window size to |
| 231 | // overflow, calls into the session to reset this stream. Does |
| 232 | // nothing if the stream is already closed. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 233 | // |
| 234 | // If stream flow control is turned off, this must not be called. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 235 | void IncreaseSendWindowSize(int32 delta_window_size); |
| 236 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 237 | // If stream flow control is turned on, called by the session to |
| 238 | // decrease this stream's send window size by |delta_window_size|, |
| 239 | // which must be at least 0 and at most kMaxSpdyFrameChunkSize. |
| 240 | // |delta_window_size| must not cause this stream's send window size |
| 241 | // to go negative. Does nothing if the stream is already closed. |
| 242 | // |
| 243 | // If stream flow control is turned off, this must not be called. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 244 | void DecreaseSendWindowSize(int32 delta_window_size); |
| 245 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 246 | // Called when bytes are consumed by the delegate from a SpdyBuffer |
| 247 | // containing received data. Increases the receive window size |
| 248 | // accordingly. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 249 | // |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 250 | // If stream flow control is turned off, this must not be called. |
| 251 | void OnReadBufferConsumed(size_t consume_size, |
| 252 | SpdyBuffer::ConsumeSource consume_source); |
| 253 | |
| 254 | // Called by OnReadBufferConsume to increase this stream's receive |
| 255 | // window size by |delta_window_size|, which must be at least 1 and |
| 256 | // must not cause this stream's receive window size to overflow, |
| 257 | // possibly also sending a WINDOW_UPDATE frame. Does nothing if the |
| 258 | // stream is not active. |
| 259 | // |
| 260 | // If stream flow control is turned off, this must not be called. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 261 | void IncreaseRecvWindowSize(int32 delta_window_size); |
| 262 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 263 | // Called by OnDataReceived (which is in turn called by the session) |
| 264 | // to decrease this stream's receive window size by |
| 265 | // |delta_window_size|, which must be at least 1 and must not cause |
| 266 | // this stream's receive window size to go negative. |
| 267 | // |
| 268 | // If stream flow control is turned off or the stream is not active, |
| 269 | // this must not be called. |
| 270 | void DecreaseRecvWindowSize(int32 delta_window_size); |
| 271 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 272 | int GetPeerAddress(IPEndPoint* address) const; |
| 273 | int GetLocalAddress(IPEndPoint* address) const; |
| 274 | |
| 275 | // Returns true if the underlying transport socket ever had any reads or |
| 276 | // writes. |
| 277 | bool WasEverUsed() const; |
| 278 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 279 | const BoundNetLog& net_log() const { return net_log_; } |
| 280 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 281 | base::Time GetRequestTime() const; |
| 282 | void SetRequestTime(base::Time t); |
| 283 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 284 | // Called at most once by the SpdySession when the initial response |
| 285 | // headers have been received for this stream, i.e., a SYN_REPLY (or |
| 286 | // SYN_STREAM for push streams) frame has been received. This is the |
| 287 | // entry point for a push stream. Returns a status code; if it is |
| 288 | // an error, the stream was closed by this function. |
| 289 | int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers, |
| 290 | base::Time response_time, |
| 291 | base::TimeTicks recv_first_byte_time); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 292 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 293 | // Called by the SpdySession (only after |
| 294 | // OnInitialResponseHeadersReceived() has been called) when |
| 295 | // late-bound headers are received for a stream. Returns a status |
| 296 | // code; if it is an error, the stream was closed by this function. |
| 297 | int OnAdditionalResponseHeadersReceived( |
| 298 | const SpdyHeaderBlock& additional_response_headers); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 299 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 300 | // Called by the SpdySession when response data has been received |
| 301 | // for this stream. This callback may be called multiple times as |
| 302 | // data arrives from the network, and will never be called prior to |
| 303 | // OnResponseHeadersReceived. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 304 | // |
| 305 | // |buffer| contains the data received, or NULL if the stream is |
| 306 | // being closed. The stream must copy any data from this |
| 307 | // buffer before returning from this callback. |
| 308 | // |
| 309 | // |length| is the number of bytes received (at most 2^24 - 1) or 0 if |
| 310 | // the stream is being closed. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 311 | void OnDataReceived(scoped_ptr<SpdyBuffer> buffer); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 312 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 313 | // Called by the SpdySession when a frame has been successfully and |
| 314 | // completely written. |frame_size| is the total size of the frame |
| 315 | // in bytes, including framing overhead. |
| 316 | void OnFrameWriteComplete(SpdyFrameType frame_type, size_t frame_size); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 317 | |
| 318 | // Called by the SpdySession when the request is finished. This callback |
| 319 | // will always be called at the end of the request and signals to the |
| 320 | // stream that the stream has no more network events. No further callbacks |
| 321 | // to the stream will be made after this call. |
| 322 | // |status| is an error code or OK. |
| 323 | void OnClose(int status); |
| 324 | |
| 325 | // Called by the SpdySession to log stream related errors. |
| 326 | void LogStreamError(int status, const std::string& description); |
| 327 | |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 328 | // If this stream is active, reset it, and close it otherwise. In |
| 329 | // either case the stream is deleted. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 330 | void Cancel(); |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 331 | |
| 332 | // Close this stream without sending a RST_STREAM and delete |
| 333 | // it. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 334 | void Close(); |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 335 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 336 | // Must be used only by |session_|. |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 337 | base::WeakPtr<SpdyStream> GetWeakPtr(); |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 338 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 339 | // Interface for the delegate to use. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 340 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 341 | // Only one send can be in flight at a time, except for push |
| 342 | // streams, which must not send anything. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 343 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 344 | // Sends the request headers. The delegate is called back via |
| 345 | // OnRequestHeadersSent() when the request headers have completed |
| 346 | // sending. |send_status| must be MORE_DATA_TO_SEND for |
| 347 | // bidirectional streams; for request/response streams, it must be |
| 348 | // MORE_DATA_TO_SEND if the request has data to upload, or |
| 349 | // NO_MORE_DATA_TO_SEND if not. |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 350 | int SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> request_headers, |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 351 | SpdySendStatus send_status); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 352 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 353 | // Sends a DATA frame. The delegate will be notified via |
| 354 | // OnDataSent() when the send is complete. |send_status| must be |
| 355 | // MORE_DATA_TO_SEND for bidirectional streams; for request/response |
| 356 | // streams, it must be MORE_DATA_TO_SEND if there is more data to |
| 357 | // upload, or NO_MORE_DATA_TO_SEND if not. |
| 358 | void SendData(IOBuffer* data, int length, SpdySendStatus send_status); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 359 | |
| 360 | // Fills SSL info in |ssl_info| and returns true when SSL is in use. |
| 361 | bool GetSSLInfo(SSLInfo* ssl_info, |
| 362 | bool* was_npn_negotiated, |
| 363 | NextProto* protocol_negotiated); |
| 364 | |
| 365 | // Fills SSL Certificate Request info |cert_request_info| and returns |
| 366 | // true when SSL is in use. |
| 367 | bool GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); |
| 368 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 369 | // If the stream is stalled on sending data, but the session is not |
| 370 | // stalled on sending data and |send_window_size_| is positive, then |
| 371 | // set |send_stalled_by_flow_control_| to false and unstall the data |
| 372 | // sending. Called by the session or by the stream itself. Must be |
| 373 | // called only when the stream is still open. |
| 374 | void PossiblyResumeIfSendStalled(); |
| 375 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 376 | // Returns whether or not this stream is closed. Note that the only |
| 377 | // time a stream is closed and not deleted is in its delegate's |
| 378 | // OnClose() method. |
| 379 | bool IsClosed() const; |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 380 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 381 | // Returns whether or not this stream has finished sending its |
| 382 | // request headers and is ready to send/receive more data. |
| 383 | bool IsIdle() const; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 384 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 385 | // Returns the protocol used by this stream. Always between |
| 386 | // kProtoSPDY2 and kProtoSPDYMaximumVersion. |
| 387 | // |
| 388 | // TODO(akalin): Change the lower bound to kProtoSPDYMinimumVersion |
| 389 | // once we stop supporting SPDY/1. |
| 390 | NextProto GetProtocol() const; |
| 391 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 392 | int response_status() const { return response_status_; } |
| 393 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 394 | bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 395 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 396 | // Get the URL from the appropriate stream headers, or the empty |
| 397 | // GURL() if it is unknown. |
| 398 | // |
| 399 | // TODO(akalin): Figure out if we really need this function, |
| 400 | // i.e. can we just use the URL this stream was created with and/or |
| 401 | // one we receive headers validate that the URL from them is the |
| 402 | // same. |
| 403 | GURL GetUrlFromHeaders() const; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 404 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 405 | // Returns whether the URL for this stream is known. |
| 406 | // |
| 407 | // TODO(akalin): Remove this, as it's only used in tests. |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 408 | bool HasUrlFromHeaders() const; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 409 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 410 | int GetProtocolVersion() const; |
| 411 | |
| 412 | private: |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 413 | class SynStreamBufferProducer; |
| 414 | class HeaderBufferProducer; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 415 | |
| 416 | enum State { |
| 417 | STATE_NONE, |
| 418 | STATE_GET_DOMAIN_BOUND_CERT, |
| 419 | STATE_GET_DOMAIN_BOUND_CERT_COMPLETE, |
| 420 | STATE_SEND_DOMAIN_BOUND_CERT, |
| 421 | STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE, |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 422 | STATE_SEND_REQUEST_HEADERS, |
| 423 | STATE_SEND_REQUEST_HEADERS_COMPLETE, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 424 | STATE_IDLE, |
| 425 | STATE_CLOSED |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 426 | }; |
| 427 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 428 | void OnGetDomainBoundCertComplete(int result); |
| 429 | |
| 430 | // Try to make progress sending/receiving the request/response. |
| 431 | int DoLoop(int result); |
| 432 | |
| 433 | // The implementations of each state of the state machine. |
| 434 | int DoGetDomainBoundCert(); |
| 435 | int DoGetDomainBoundCertComplete(int result); |
| 436 | int DoSendDomainBoundCert(); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 437 | int DoSendDomainBoundCertComplete(int result); |
| 438 | int DoSendRequestHeaders(); |
| 439 | int DoSendRequestHeadersComplete(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 440 | int DoReadHeaders(); |
| 441 | int DoReadHeadersComplete(int result); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 442 | int DoOpen(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 443 | |
| 444 | // Update the histograms. Can safely be called repeatedly, but should only |
| 445 | // be called after the stream has completed. |
| 446 | void UpdateHistograms(); |
| 447 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 448 | // When a server-pushed stream is first created, this function is |
| 449 | // posted on the current MessageLoop to replay the data that the |
| 450 | // server has already sent. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 451 | void PushedStreamReplayData(); |
| 452 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 453 | // Produces the SYN_STREAM frame for the stream. The stream must |
| 454 | // already be activated. |
| 455 | scoped_ptr<SpdyFrame> ProduceSynStreamFrame(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 456 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 457 | // Produce the initial HEADER frame for the stream with the given |
| 458 | // block. The stream must already be activated. |
| 459 | scoped_ptr<SpdyFrame> ProduceHeaderFrame( |
| 460 | scoped_ptr<SpdyHeaderBlock> header_block); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 461 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 462 | // Queues the send for next frame of the remaining data in |
| 463 | // |pending_send_data_|. Must be called only when |
| 464 | // |pending_send_data_| is set. |
| 465 | void QueueNextDataFrame(); |
| 466 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 467 | // Merge the given headers into |response_headers_| and calls |
| 468 | // OnResponseHeadersUpdated() on the delegate (if attached). |
| 469 | // Returns a status code; if it is an error, the stream was closed |
| 470 | // by this function. |
| 471 | int MergeWithResponseHeaders(const SpdyHeaderBlock& new_response_headers); |
| 472 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 473 | const SpdyStreamType type_; |
| 474 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 475 | base::WeakPtrFactory<SpdyStream> weak_ptr_factory_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 476 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 477 | // Sentinel variable used to make sure we don't get destroyed by a |
| 478 | // function called from DoLoop(). |
| 479 | bool in_do_loop_; |
| 480 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 481 | // There is a small period of time between when a server pushed stream is |
| 482 | // first created, and the pushed data is replayed. Any data received during |
| 483 | // this time should continue to be buffered. |
| 484 | bool continue_buffering_data_; |
| 485 | |
| 486 | SpdyStreamId stream_id_; |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 487 | const GURL url_; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 488 | const RequestPriority priority_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 489 | size_t slot_; |
| 490 | |
| 491 | // Flow control variables. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 492 | bool send_stalled_by_flow_control_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 493 | int32 send_window_size_; |
| 494 | int32 recv_window_size_; |
| 495 | int32 unacked_recv_window_bytes_; |
| 496 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 497 | ScopedBandwidthMetrics metrics_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 498 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 499 | const base::WeakPtr<SpdySession> session_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 500 | |
| 501 | // The transaction should own the delegate. |
| 502 | SpdyStream::Delegate* delegate_; |
| 503 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 504 | // Whether or not we have more data to send on this stream. |
| 505 | SpdySendStatus send_status_; |
| 506 | |
| 507 | // The headers for the request to send. |
| 508 | // |
| 509 | // TODO(akalin): Hang onto this only until we send it. This |
| 510 | // necessitates stashing the URL separately. |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 511 | scoped_ptr<SpdyHeaderBlock> request_headers_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 512 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 513 | // The data waiting to be sent. |
| 514 | scoped_refptr<DrainableIOBuffer> pending_send_data_; |
| 515 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 516 | // The time at which the request was made that resulted in this response. |
| 517 | // For cached responses, this time could be "far" in the past. |
| 518 | base::Time request_time_; |
| 519 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 520 | SpdyHeaderBlock response_headers_; |
| 521 | SpdyResponseHeadersStatus response_headers_status_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 522 | base::Time response_time_; |
| 523 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 524 | State io_state_; |
| 525 | |
| 526 | // Since we buffer the response, we also buffer the response status. |
| 527 | // Not valid until the stream is closed. |
| 528 | int response_status_; |
| 529 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 530 | BoundNetLog net_log_; |
| 531 | |
| 532 | base::TimeTicks send_time_; |
| 533 | base::TimeTicks recv_first_byte_time_; |
| 534 | base::TimeTicks recv_last_byte_time_; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 535 | |
| 536 | // Number of data bytes that have been sent/received on this stream, not |
| 537 | // including frame overhead. Note that this does not count headers. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 538 | int send_bytes_; |
| 539 | int recv_bytes_; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 540 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 541 | // Data received before delegate is attached. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 542 | ScopedVector<SpdyBuffer> pending_buffers_; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 543 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 544 | std::string domain_bound_private_key_; |
| 545 | std::string domain_bound_cert_; |
| 546 | ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_; |
| 547 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 548 | // When OnFrameWriteComplete() is called, these variables are set. |
| 549 | SpdyFrameType just_completed_frame_type_; |
| 550 | size_t just_completed_frame_size_; |
| 551 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 552 | DISALLOW_COPY_AND_ASSIGN(SpdyStream); |
| 553 | }; |
| 554 | |
| 555 | } // namespace net |
| 556 | |
| 557 | #endif // NET_SPDY_SPDY_STREAM_H_ |