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