1 // Copyright 2012 The Chromium Authors 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 <stddef.h> 9 #include <stdint.h> 10 11 #include <memory> 12 #include <string> 13 #include <vector> 14 15 #include "base/memory/raw_ptr.h" 16 #include "base/memory/scoped_refptr.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/time/time.h" 19 #include "net/base/io_buffer.h" 20 #include "net/base/net_export.h" 21 #include "net/base/request_priority.h" 22 #include "net/log/net_log_source.h" 23 #include "net/log/net_log_with_source.h" 24 #include "net/socket/next_proto.h" 25 #include "net/socket/ssl_client_socket.h" 26 #include "net/spdy/spdy_buffer.h" 27 #include "net/ssl/ssl_client_cert_type.h" 28 #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" 29 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" 30 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" 31 #include "net/traffic_annotation/network_traffic_annotation.h" 32 #include "url/gurl.h" 33 34 namespace net { 35 36 namespace test { 37 class SpdyStreamTest; 38 } 39 40 class IPEndPoint; 41 struct LoadTimingInfo; 42 class SSLInfo; 43 class SpdySession; 44 45 enum SpdyStreamType { 46 // The most general type of stream; there are no restrictions on 47 // when data can be sent and received. 48 SPDY_BIDIRECTIONAL_STREAM, 49 // A stream where the client sends a request with possibly a body, 50 // and the server then sends a response with a body. 51 SPDY_REQUEST_RESPONSE_STREAM, 52 // A server-initiated stream where the server just sends a response 53 // with a body and the client does not send anything. 54 SPDY_PUSH_STREAM 55 }; 56 57 // Passed to some SpdyStream functions to indicate whether there's 58 // more data to send. 59 enum SpdySendStatus { 60 MORE_DATA_TO_SEND, 61 NO_MORE_DATA_TO_SEND 62 }; 63 64 // SpdyStream is owned by SpdySession and is used to represent each stream known 65 // on the SpdySession. This class provides interfaces for SpdySession to use. 66 // Streams can be created either by the client or by the server. When they 67 // are initiated by the client, both the SpdySession and client object (such as 68 // a SpdyNetworkTransaction) will maintain a reference to the stream. When 69 // initiated by the server, only the SpdySession will maintain any reference, 70 // until such a time as a client object requests a stream for the path. 71 class NET_EXPORT_PRIVATE SpdyStream { 72 public: 73 // Delegate handles protocol specific behavior of spdy stream. 74 class NET_EXPORT_PRIVATE Delegate { 75 public: 76 Delegate() = default; 77 78 Delegate(const Delegate&) = delete; 79 Delegate& operator=(const Delegate&) = delete; 80 81 // Called when the request headers have been sent. Never called 82 // for push streams. Must not cause the stream to be closed. 83 virtual void OnHeadersSent() = 0; 84 85 // OnEarlyHintsReceived(), OnHeadersReceived(), OnDataReceived(), 86 // OnTrailers(), and OnClose() are guaranteed to be called in the following 87 // order: 88 // - OnEarlyHintsReceived() zero or more times; 89 // - OnHeadersReceived() exactly once; 90 // - OnDataReceived() zero or more times; 91 // - OnTrailers() zero or one times; 92 // - OnClose() exactly once. 93 94 // Called when a 103 Early Hints response is received. 95 virtual void OnEarlyHintsReceived( 96 const spdy::Http2HeaderBlock& headers) = 0; 97 98 // Called when response headers have been received. In case of a pushed 99 // stream, the pushed request headers are also passed. 100 virtual void OnHeadersReceived( 101 const spdy::Http2HeaderBlock& response_headers, 102 const spdy::Http2HeaderBlock* pushed_request_headers) = 0; 103 104 // Called when data is received. |buffer| may be NULL, which signals EOF. 105 // May cause the stream to be closed. 106 virtual void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) = 0; 107 108 // Called when data is sent. Must not cause the stream to be closed. 109 virtual void OnDataSent() = 0; 110 111 // Called when trailers are received. 112 virtual void OnTrailers(const spdy::Http2HeaderBlock& trailers) = 0; 113 114 // Called when SpdyStream is closed. No other delegate functions 115 // will be called after this is called, and the delegate must not 116 // access the stream after this is called. Must not cause the 117 // stream to be (re-)closed. 118 // 119 // TODO(akalin): Allow this function to re-close the stream and 120 // handle it gracefully. 121 virtual void OnClose(int status) = 0; 122 123 // Returns whether it is allowed to send greased (reserved type) frames on 124 // the HTTP/2 stream. 125 virtual bool CanGreaseFrameType() const = 0; 126 127 virtual NetLogSource source_dependency() const = 0; 128 129 protected: 130 virtual ~Delegate() = default; 131 }; 132 133 // SpdyStream constructor 134 SpdyStream(SpdyStreamType type, 135 const base::WeakPtr<SpdySession>& session, 136 const GURL& url, 137 RequestPriority priority, 138 int32_t initial_send_window_size, 139 int32_t max_recv_window_size, 140 const NetLogWithSource& net_log, 141 const NetworkTrafficAnnotationTag& traffic_annotation, 142 bool detect_broken_connection); 143 144 SpdyStream(const SpdyStream&) = delete; 145 SpdyStream& operator=(const SpdyStream&) = delete; 146 147 ~SpdyStream(); 148 149 // Set the delegate, which must not be NULL. Must not be called more 150 // than once. For push streams, calling this may cause buffered data 151 // to be sent to the delegate (from a posted task). 152 void SetDelegate(Delegate* delegate); 153 154 // Detach the delegate from the stream, which must not yet be 155 // closed, and cancel it. 156 void DetachDelegate(); 157 158 // The time at which the first bytes of the response were received 159 // from the server, or null if the response hasn't been received 160 // yet. response_time()161 base::Time response_time() const { return response_time_; } 162 type()163 SpdyStreamType type() const { return type_; } 164 stream_id()165 spdy::SpdyStreamId stream_id() const { return stream_id_; } set_stream_id(spdy::SpdyStreamId stream_id)166 void set_stream_id(spdy::SpdyStreamId stream_id) { stream_id_ = stream_id; } 167 url()168 const GURL& url() const { return url_; } 169 priority()170 RequestPriority priority() const { return priority_; } 171 172 // Update priority and send PRIORITY frames on the wire if necessary. 173 void SetPriority(RequestPriority priority); 174 send_window_size()175 int32_t send_window_size() const { return send_window_size_; } 176 recv_window_size()177 int32_t recv_window_size() const { return recv_window_size_; } 178 send_stalled_by_flow_control()179 bool send_stalled_by_flow_control() const { 180 return send_stalled_by_flow_control_; 181 } 182 set_send_stalled_by_flow_control(bool stalled)183 void set_send_stalled_by_flow_control(bool stalled) { 184 send_stalled_by_flow_control_ = stalled; 185 } 186 187 // Called by the session to adjust this stream's send window size by 188 // |delta_window_size|, which is the difference between the 189 // spdy::SETTINGS_INITIAL_WINDOW_SIZE in the most recent SETTINGS frame 190 // and the previous initial send window size, possibly unstalling 191 // this stream. Although |delta_window_size| may cause this stream's 192 // send window size to go negative, it must not cause it to wrap 193 // around in either direction. Does nothing if the stream is already 194 // closed. 195 // Returns true if successful. Returns false if |send_window_size_| 196 // would exceed 2^31-1 after the update, see RFC7540 Section 6.9.2. 197 // Note that |send_window_size_| should not possibly underflow. 198 [[nodiscard]] bool AdjustSendWindowSize(int32_t delta_window_size); 199 200 // Called when bytes are consumed from a SpdyBuffer for a DATA frame 201 // that is to be written or is being written. Increases the send 202 // window size accordingly if some or all of the SpdyBuffer is being 203 // discarded. 204 // 205 // If stream flow control is turned off, this must not be called. 206 void OnWriteBufferConsumed(size_t frame_payload_size, 207 size_t consume_size, 208 SpdyBuffer::ConsumeSource consume_source); 209 210 // Called by the session to increase this stream's send window size 211 // by |delta_window_size| (which must be at least 1) from a received 212 // WINDOW_UPDATE frame or from a dropped DATA frame that was 213 // intended to be sent, possibly unstalling this stream. If 214 // |delta_window_size| would cause this stream's send window size to 215 // overflow, calls into the session to reset this stream. Does 216 // nothing if the stream is already closed. 217 // 218 // If stream flow control is turned off, this must not be called. 219 void IncreaseSendWindowSize(int32_t delta_window_size); 220 221 // If stream flow control is turned on, called by the session to 222 // decrease this stream's send window size by |delta_window_size|, 223 // which must be at least 0 and at most kMaxSpdyFrameChunkSize. 224 // |delta_window_size| must not cause this stream's send window size 225 // to go negative. Does nothing if the stream is already closed. 226 // 227 // If stream flow control is turned off, this must not be called. 228 void DecreaseSendWindowSize(int32_t delta_window_size); 229 230 // Called when bytes are consumed by the delegate from a SpdyBuffer 231 // containing received data. Increases the receive window size 232 // accordingly. 233 // 234 // If stream flow control is turned off, this must not be called. 235 void OnReadBufferConsumed(size_t consume_size, 236 SpdyBuffer::ConsumeSource consume_source); 237 238 // Called by OnReadBufferConsume to increase this stream's receive 239 // window size by |delta_window_size|, which must be at least 1 and 240 // must not cause this stream's receive window size to overflow, 241 // possibly also sending a WINDOW_UPDATE frame. Does nothing if the 242 // stream is not active. 243 // 244 // If stream flow control is turned off, this must not be called. 245 void IncreaseRecvWindowSize(int32_t delta_window_size); 246 247 // Called by OnDataReceived or OnPaddingConsumed (which are in turn called by 248 // the session) to decrease this stream's receive window size by 249 // |delta_window_size|, which must be at least 1. May close the stream on 250 // flow control error. 251 // 252 // If stream flow control is turned off or the stream is not active, 253 // this must not be called. 254 void DecreaseRecvWindowSize(int32_t delta_window_size); 255 256 int GetPeerAddress(IPEndPoint* address) const; 257 int GetLocalAddress(IPEndPoint* address) const; 258 259 // Returns true if the underlying transport socket ever had any reads or 260 // writes. 261 bool WasEverUsed() const; 262 net_log()263 const NetLogWithSource& net_log() const { return net_log_; } 264 265 base::Time GetRequestTime() const; 266 void SetRequestTime(base::Time t); 267 268 // Called by SpdySession when headers are received for this stream. May close 269 // the stream. 270 void OnHeadersReceived(const spdy::Http2HeaderBlock& response_headers, 271 base::Time response_time, 272 base::TimeTicks recv_first_byte_time); 273 274 // Called by the SpdySession when a frame carrying request headers opening a 275 // push stream is received. Stream transits to STATE_RESERVED_REMOTE state. 276 void OnPushPromiseHeadersReceived(spdy::Http2HeaderBlock headers, GURL url); 277 278 // Called by the SpdySession when response data has been received 279 // for this stream. This callback may be called multiple times as 280 // data arrives from the network, and will never be called prior to 281 // OnResponseHeadersReceived. 282 // 283 // |buffer| contains the data received, or NULL if the stream is 284 // being closed. The stream must copy any data from this 285 // buffer before returning from this callback. 286 // 287 // |length| is the number of bytes received (at most 2^24 - 1) or 0 if 288 // the stream is being closed. 289 void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer); 290 291 // Called by the SpdySession when padding is consumed to allow for the stream 292 // receiving window to be updated. 293 void OnPaddingConsumed(size_t len); 294 295 // Called by the SpdySession when a frame has been successfully and completely 296 // written. |frame_size| is the total size of the logical frame in bytes, 297 // including framing overhead. For fragmented headers, this is the total size 298 // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames. 299 void OnFrameWriteComplete(spdy::SpdyFrameType frame_type, size_t frame_size); 300 301 // HEADERS-specific write handler invoked by OnFrameWriteComplete(). 302 int OnHeadersSent(); 303 304 // DATA-specific write handler invoked by OnFrameWriteComplete(). 305 // If more data is already available to be written, the next write is 306 // queued and ERR_IO_PENDING is returned. Returns OK otherwise. 307 int OnDataSent(size_t frame_size); 308 309 // Called by the SpdySession when the request is finished. This callback 310 // will always be called at the end of the request and signals to the 311 // stream that the stream has no more network events. No further callbacks 312 // to the stream will be made after this call. Must be called before 313 // SpdyStream is destroyed. 314 // |status| is an error code or OK. 315 void OnClose(int status); 316 317 // Called by the SpdySession to log stream related errors. 318 void LogStreamError(int error, base::StringPiece description); 319 320 // If this stream is active, reset it, and close it otherwise. In 321 // either case the stream is deleted. 322 void Cancel(int error); 323 324 // Close this stream without sending a RST_STREAM and delete 325 // it. 326 void Close(); 327 328 // Must be used only by |session_|. 329 base::WeakPtr<SpdyStream> GetWeakPtr(); 330 331 // Interface for the delegate to use. 332 333 // Only one send can be in flight at a time, except for push 334 // streams, which must not send anything. 335 336 // Sends the request headers. The delegate is called back via OnHeadersSent() 337 // when the request headers have completed sending. |send_status| must be 338 // MORE_DATA_TO_SEND for bidirectional streams; for request/response streams, 339 // it must be MORE_DATA_TO_SEND if the request has data to upload, or 340 // NO_MORE_DATA_TO_SEND if not. 341 int SendRequestHeaders(spdy::Http2HeaderBlock request_headers, 342 SpdySendStatus send_status); 343 344 // Sends a DATA frame. The delegate will be notified via 345 // OnDataSent() when the send is complete. |send_status| must be 346 // MORE_DATA_TO_SEND for bidirectional streams; for request/response 347 // streams, it must be MORE_DATA_TO_SEND if there is more data to 348 // upload, or NO_MORE_DATA_TO_SEND if not. 349 // Must not be called until Delegate::OnHeadersSent() is called. 350 void SendData(IOBuffer* data, int length, SpdySendStatus send_status); 351 352 // Fills SSL info in |ssl_info| and returns true when SSL is in use. 353 bool GetSSLInfo(SSLInfo* ssl_info) const; 354 355 // Returns true if ALPN was negotiated for the underlying socket. 356 bool WasAlpnNegotiated() const; 357 358 // Returns the protocol negotiated via ALPN for the underlying socket. 359 NextProto GetNegotiatedProtocol() const; 360 361 // If the stream is stalled on sending data, but the session is not 362 // stalled on sending data and |send_window_size_| is positive, then 363 // set |send_stalled_by_flow_control_| to false and unstall the data 364 // sending. Called by the session or by the stream itself. Must be 365 // called only when the stream is still open. 366 enum ShouldRequeueStream { Requeue, DoNotRequeue }; 367 ShouldRequeueStream PossiblyResumeIfSendStalled(); 368 369 // Returns whether or not this stream is closed. Note that the only 370 // time a stream is closed and not deleted is in its delegate's 371 // OnClose() method. 372 bool IsClosed() const; 373 374 // Returns whether the streams local endpoint is closed. 375 // The remote endpoint may still be active. 376 bool IsLocallyClosed() const; 377 378 // Returns whether this stream is IDLE: request and response headers 379 // have neither been sent nor receieved. 380 bool IsIdle() const; 381 382 // Returns whether or not this stream is fully open: that request and 383 // response headers are complete, and it is not in a half-closed state. 384 bool IsOpen() const; 385 386 // Returns whether the stream is reserved by remote endpoint: server has sent 387 // intended request headers for a pushed stream, but haven't started response 388 // yet. 389 bool IsReservedRemote() const; 390 391 void AddRawReceivedBytes(size_t received_bytes); 392 void AddRawSentBytes(size_t sent_bytes); 393 raw_received_bytes()394 int64_t raw_received_bytes() const { return raw_received_bytes_; } raw_sent_bytes()395 int64_t raw_sent_bytes() const { return raw_sent_bytes_; } recv_bytes()396 int recv_bytes() const { return recv_bytes_; } 397 bool ShouldRetryRSTPushStream() const; 398 399 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const; 400 request_headers()401 const spdy::Http2HeaderBlock& request_headers() const { 402 return request_headers_; 403 } response_headers()404 const spdy::Http2HeaderBlock& response_headers() const { 405 return response_headers_; 406 } 407 traffic_annotation()408 const NetworkTrafficAnnotationTag traffic_annotation() const { 409 return traffic_annotation_; 410 } 411 detect_broken_connection()412 bool detect_broken_connection() const { return detect_broken_connection_; } 413 414 private: 415 friend class test::SpdyStreamTest; 416 417 class HeadersBufferProducer; 418 419 // SpdyStream states and transitions are modeled 420 // on the HTTP/2 stream state machine. All states and transitions 421 // are modeled, with the exceptions of RESERVED_LOCAL (the client 422 // cannot initate push streams), and the transition to OPEN due to 423 // a remote HEADERS (the client can only initate streams). 424 enum State { 425 STATE_IDLE, 426 STATE_OPEN, 427 STATE_HALF_CLOSED_LOCAL_UNCLAIMED, 428 STATE_HALF_CLOSED_LOCAL, 429 STATE_HALF_CLOSED_REMOTE, 430 STATE_RESERVED_REMOTE, 431 STATE_CLOSED, 432 }; 433 434 // Per RFC 7540 Section 8.1, an HTTP response consists of: 435 // * zero or more header blocks with informational (1xx) HTTP status, 436 // * one header block, 437 // * zero or more DATA frames, 438 // * zero or one header block ("trailers"). 439 // Each header block must have a ":status" header field. SpdyStream enforces 440 // these requirements, and resets the stream if they are not met. 441 enum ResponseState { 442 READY_FOR_HEADERS, 443 READY_FOR_DATA_OR_TRAILERS, 444 TRAILERS_RECEIVED 445 }; 446 447 // When a server-push stream is claimed by SetDelegate(), this function is 448 // posted on the current MessageLoop to replay everything the server has sent. 449 // From the perspective of SpdyStream's state machine, headers, data, and 450 // FIN states received prior to the delegate being attached have not yet been 451 // read. While buffered by |pending_recv_data_| it's not until 452 // PushedStreamReplay() is invoked that reads are considered 453 // to have occurred, driving the state machine forward. 454 void PushedStreamReplay(); 455 456 // Produces the HEADERS frame for the stream. The stream must 457 // already be activated. 458 std::unique_ptr<spdy::SpdySerializedFrame> ProduceHeadersFrame(); 459 460 // Queues the send for next frame of the remaining data in 461 // |pending_send_data_|. Must be called only when 462 // |pending_send_data_| is set. 463 void QueueNextDataFrame(); 464 465 void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& response_headers, 466 base::TimeTicks recv_first_byte_time); 467 468 // Saves the given headers into |response_headers_| and calls 469 // OnHeadersReceived() on the delegate if attached. 470 void SaveResponseHeaders(const spdy::Http2HeaderBlock& response_headers, 471 int status); 472 473 static std::string DescribeState(State state); 474 475 const SpdyStreamType type_; 476 477 spdy::SpdyStreamId stream_id_ = 0; 478 const GURL url_; 479 RequestPriority priority_; 480 481 bool send_stalled_by_flow_control_ = false; 482 483 // Current send window size. 484 int32_t send_window_size_; 485 486 // Maximum receive window size. Each time a WINDOW_UPDATE is sent, it 487 // restores the receive window size to this value. 488 int32_t max_recv_window_size_; 489 490 // Sum of |session_unacked_recv_window_bytes_| and current receive window 491 // size. 492 // TODO(bnc): Rename or change semantics so that |window_size_| is actual 493 // window size. 494 int32_t recv_window_size_; 495 496 // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession, 497 // and this member keeps count of them until the corresponding WINDOW_UPDATEs 498 // are sent. 499 int32_t unacked_recv_window_bytes_ = 0; 500 501 // Time of the last WINDOW_UPDATE for the receive window 502 base::TimeTicks last_recv_window_update_; 503 504 const base::WeakPtr<SpdySession> session_; 505 506 // The transaction should own the delegate. 507 raw_ptr<SpdyStream::Delegate> delegate_ = nullptr; 508 509 // The headers for the request to send. 510 bool request_headers_valid_ = false; 511 spdy::Http2HeaderBlock request_headers_; 512 513 // Data waiting to be sent, and the close state of the local endpoint 514 // after the data is fully written. 515 scoped_refptr<DrainableIOBuffer> pending_send_data_; 516 SpdySendStatus pending_send_status_ = MORE_DATA_TO_SEND; 517 518 // Data waiting to be received, and the close state of the remote endpoint 519 // after the data is fully read. Specifically, data received before the 520 // delegate is attached must be buffered and later replayed. A remote FIN 521 // is represented by a final, zero-length buffer. 522 std::vector<std::unique_ptr<SpdyBuffer>> pending_recv_data_; 523 524 // The time at which the request was made that resulted in this response. 525 // For cached responses, this time could be "far" in the past. 526 base::Time request_time_; 527 528 spdy::Http2HeaderBlock response_headers_; 529 ResponseState response_state_ = READY_FOR_HEADERS; 530 base::Time response_time_; 531 532 State io_state_ = STATE_IDLE; 533 534 NetLogWithSource net_log_; 535 536 base::TimeTicks send_time_; 537 538 // The time at which the first / last byte of the HTTP headers were received. 539 // 540 // These correspond to |LoadTimingInfo::receive_headers_start| and 541 // |LoadTimingInfo::receive_headers_end|. See also comments there. 542 base::TimeTicks recv_first_byte_time_; 543 base::TimeTicks recv_last_byte_time_; 544 545 // The time at which the first byte of the HTTP headers for the 546 // non-informational response (non-1xx). This corresponds to 547 // |LoadTimingInfo::receive_non_informational_headers_start|. See also 548 // comments there. 549 base::TimeTicks recv_first_byte_time_for_non_informational_response_; 550 551 // The time at which the first 103 Early Hints response is received. 552 base::TimeTicks first_early_hints_time_; 553 554 // Number of bytes that have been received on this stream, including frame 555 // overhead and headers. 556 int64_t raw_received_bytes_ = 0; 557 // Number of bytes that have been sent on this stream, including frame 558 // overhead and headers. 559 int64_t raw_sent_bytes_ = 0; 560 561 // Number of data bytes that have been received on this stream, not including 562 // frame overhead. Note that this does not count headers. 563 int recv_bytes_ = 0; 564 565 // Guards calls of delegate write handlers ensuring |this| is not destroyed. 566 // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked 567 // down. 568 bool write_handler_guard_ = false; 569 570 const NetworkTrafficAnnotationTag traffic_annotation_; 571 572 // Used by SpdySession to remember if this stream requested broken connection 573 // detection. 574 bool detect_broken_connection_; 575 576 base::WeakPtrFactory<SpdyStream> weak_ptr_factory_{this}; 577 }; 578 579 } // namespace net 580 581 #endif // NET_SPDY_SPDY_STREAM_H_ 582