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