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 // NOTE: This code is not shared between Google and Chrome. 6 7 #ifndef NET_QUIC_QUIC_CHROMIUM_CLIENT_STREAM_H_ 8 #define NET_QUIC_QUIC_CHROMIUM_CLIENT_STREAM_H_ 9 10 #include <stddef.h> 11 12 #include <memory> 13 #include <string_view> 14 #include <vector> 15 16 #include "base/containers/circular_deque.h" 17 #include "base/functional/callback_forward.h" 18 #include "base/memory/raw_ptr.h" 19 #include "base/memory/scoped_refptr.h" 20 #include "base/time/time.h" 21 #include "net/base/completion_once_callback.h" 22 #include "net/base/idempotency.h" 23 #include "net/base/ip_endpoint.h" 24 #include "net/base/net_export.h" 25 #include "net/base/upload_data_stream.h" 26 #include "net/http/http_request_info.h" 27 #include "net/http/http_response_info.h" 28 #include "net/http/http_stream.h" 29 #include "net/log/net_log_with_source.h" 30 #include "net/third_party/quiche/src/quiche/common/http/http_header_block.h" 31 #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.h" 32 #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" 33 #include "net/traffic_annotation/network_traffic_annotation.h" 34 35 namespace quic { 36 class QuicSpdyClientSessionBase; 37 } // namespace quic 38 namespace net { 39 40 // A client-initiated ReliableQuicStream. Instances of this class 41 // are owned by the QuicClientSession which created them. 42 class NET_EXPORT_PRIVATE QuicChromiumClientStream 43 : public quic::QuicSpdyStream { 44 public: 45 // Wrapper for interacting with the session in a restricted fashion. 46 class NET_EXPORT_PRIVATE Handle { 47 public: 48 Handle(const Handle&) = delete; 49 Handle& operator=(const Handle&) = delete; 50 51 ~Handle(); 52 53 // Returns true if the stream is still connected. IsOpen()54 bool IsOpen() { return stream_ != nullptr; } 55 56 // Reads initial or 103 Early Hints headers into |header_block| and returns 57 // the length of the HEADERS frame which contained them. If headers are not 58 // available, returns ERR_IO_PENDING and will invoke |callback| 59 // asynchronously when the headers arrive. 60 // TODO(rch): Invoke |callback| when there is a stream or connection error 61 // instead of calling OnClose() or OnError(). 62 int ReadInitialHeaders(quiche::HttpHeaderBlock* header_block, 63 CompletionOnceCallback callback); 64 65 // Reads at most |buffer_len| bytes of body into |buffer| and returns the 66 // number of bytes read. If body is not available, returns ERR_IO_PENDING 67 // and will invoke |callback| asynchronously when data arrive. 68 // TODO(rch): Invoke |callback| when there is a stream or connection error 69 // instead of calling OnClose() or OnError(). 70 int ReadBody(IOBuffer* buffer, 71 int buffer_len, 72 CompletionOnceCallback callback); 73 74 // Reads trailing headers into |header_block| and returns the length of 75 // the HEADERS frame which contained them. If headers are not available, 76 // returns ERR_IO_PENDING and will invoke |callback| asynchronously when 77 // the headers arrive. 78 // TODO(rch): Invoke |callback| when there is a stream or connection error 79 // instead of calling OnClose() or OnError(). 80 int ReadTrailingHeaders(quiche::HttpHeaderBlock* header_block, 81 CompletionOnceCallback callback); 82 83 // Writes |header_block| to the peer. Closes the write side if |fin| is 84 // true. If non-null, |ack_notifier_delegate| will be notified when the 85 // headers are ACK'd by the peer. Returns a net error code if there is 86 // an error writing the headers, or the number of bytes written on 87 // success. Will not return ERR_IO_PENDING. 88 int WriteHeaders( 89 quiche::HttpHeaderBlock header_block, 90 bool fin, 91 quiche::QuicheReferenceCountedPointer<quic::QuicAckListenerInterface> 92 ack_notifier_delegate); 93 94 // Writes |data| to the peer. Closes the write side if |fin| is true. 95 // If the data could not be written immediately, returns ERR_IO_PENDING 96 // and invokes |callback| asynchronously when the write completes. 97 int WriteStreamData(std::string_view data, 98 bool fin, 99 CompletionOnceCallback callback); 100 101 // Same as WriteStreamData except it writes data from a vector of IOBuffers, 102 // with the length of each buffer at the corresponding index in |lengths|. 103 int WritevStreamData(const std::vector<scoped_refptr<IOBuffer>>& buffers, 104 const std::vector<int>& lengths, 105 bool fin, 106 CompletionOnceCallback callback); 107 108 // Writes |packet| to server by constructing a UDP payload from 109 // packet and sending the datagram on the stream. 110 int WriteConnectUdpPayload(std::string_view packet); 111 112 // Reads at most |buf_len| bytes into |buf|. Returns the number of bytes 113 // read. 114 int Read(IOBuffer* buf, int buf_len); 115 116 // Called to notify the stream when the final incoming data is read. 117 void OnFinRead(); 118 119 // Prevents the connection from migrating to a cellular network while this 120 // stream is open. 121 void DisableConnectionMigrationToCellularNetwork(); 122 123 // Sets the precedence of the stream to |priority|. 124 void SetPriority(const quic::QuicStreamPriority& priority); 125 126 // Sends a RST_STREAM frame to the peer and closes the streams. 127 void Reset(quic::QuicRstStreamErrorCode error_code); 128 129 // Registers |visitor| to receive HTTP/3 datagrams on the stream. 130 void RegisterHttp3DatagramVisitor(Http3DatagramVisitor* visitor); 131 132 // Unregisters an HTTP/3 datagram visitor. 133 void UnregisterHttp3DatagramVisitor(); 134 135 quic::QuicStreamId id() const; 136 quic::QuicErrorCode connection_error() const; 137 quic::QuicRstStreamErrorCode stream_error() const; 138 uint64_t connection_wire_error() const; 139 uint64_t ietf_application_error() const; 140 bool fin_sent() const; 141 bool fin_received() const; 142 uint64_t stream_bytes_read() const; 143 uint64_t stream_bytes_written() const; 144 size_t NumBytesConsumed() const; 145 bool HasBytesToRead() const; 146 bool IsDoneReading() const; 147 bool IsFirstStream() const; 148 first_early_hints_time()149 base::TimeTicks first_early_hints_time() const { 150 return first_early_hints_time_; 151 } 152 headers_received_start_time()153 base::TimeTicks headers_received_start_time() const { 154 return headers_received_start_time_; 155 } 156 157 // TODO(rch): Move this test-only method to a peer, or else remove. 158 bool can_migrate_to_cellular_network(); 159 160 const NetLogWithSource& net_log() const; 161 162 // Sets the idempotency of the request. 163 void SetRequestIdempotency(Idempotency idempotency); 164 // Returns the idempotency of the request. 165 Idempotency GetRequestIdempotency() const; 166 167 // Returns the largest payload that will fit into a single MESSAGE frame at 168 // any point during the connection. This assumes the version and 169 // connection ID lengths do not change. Returns zero if the stream or 170 // session are closed. 171 quic::QuicPacketLength GetGuaranteedLargestMessagePayload() const; 172 173 private: 174 friend class QuicChromiumClientStream; 175 176 // Constucts a new Handle for |stream|. 177 explicit Handle(QuicChromiumClientStream* stream); 178 179 // Methods invoked by the stream. 180 void OnEarlyHintsAvailable(); 181 void OnInitialHeadersAvailable(); 182 void OnTrailingHeadersAvailable(); 183 void OnDataAvailable(); 184 void OnCanWrite(); 185 void OnClose(); 186 void OnError(int error); 187 188 // Invokes async IO callbacks because of |error|. 189 void InvokeCallbacksOnClose(int error); 190 191 // Saves various fields from the stream before the stream goes away. 192 void SaveState(); 193 194 void SetCallback(CompletionOnceCallback new_callback, 195 CompletionOnceCallback* callback); 196 197 void ResetAndRun(CompletionOnceCallback callback, int rv); 198 199 int HandleIOComplete(int rv); 200 201 raw_ptr<QuicChromiumClientStream> stream_; // Unowned. 202 203 bool may_invoke_callbacks_ = true; // True when callbacks may be invoked. 204 205 // Callback to be invoked when ReadInitialHeaders completes asynchronously. 206 CompletionOnceCallback read_headers_callback_; 207 // Provided by the owner of this handle when ReadInitialHeaders is called. 208 raw_ptr<quiche::HttpHeaderBlock> read_headers_buffer_ = nullptr; 209 210 // Callback to be invoked when ReadBody completes asynchronously. 211 CompletionOnceCallback read_body_callback_; 212 scoped_refptr<IOBuffer> read_body_buffer_; 213 int read_body_buffer_len_ = 0; 214 215 // Callback to be invoked when WriteStreamData or WritevStreamData completes 216 // asynchronously. 217 CompletionOnceCallback write_callback_; 218 219 quic::QuicStreamId id_; 220 quic::QuicErrorCode connection_error_; 221 quic::QuicRstStreamErrorCode stream_error_; 222 uint64_t connection_wire_error_ = 0; 223 uint64_t ietf_application_error_ = 0; 224 bool fin_sent_; 225 bool fin_received_; 226 uint64_t stream_bytes_read_; 227 uint64_t stream_bytes_written_; 228 bool is_done_reading_; 229 bool is_first_stream_; 230 size_t num_bytes_consumed_; 231 Idempotency idempotency_ = DEFAULT_IDEMPOTENCY; 232 233 int net_error_ = ERR_UNEXPECTED; 234 235 NetLogWithSource net_log_; 236 237 // The time at which the first 103 Early Hints response is received. 238 base::TimeTicks first_early_hints_time_; 239 240 base::TimeTicks headers_received_start_time_; 241 242 base::WeakPtrFactory<Handle> weak_factory_{this}; 243 }; 244 245 QuicChromiumClientStream( 246 quic::QuicStreamId id, 247 quic::QuicSpdyClientSessionBase* session, 248 quic::QuicServerId server_id, 249 quic::StreamType type, 250 const NetLogWithSource& net_log, 251 const NetworkTrafficAnnotationTag& traffic_annotation); 252 QuicChromiumClientStream( 253 quic::PendingStream* pending, 254 quic::QuicSpdyClientSessionBase* session, 255 quic::QuicServerId server_id, 256 const NetLogWithSource& net_log, 257 const NetworkTrafficAnnotationTag& traffic_annotation); 258 259 QuicChromiumClientStream(const QuicChromiumClientStream&) = delete; 260 QuicChromiumClientStream& operator=(const QuicChromiumClientStream&) = delete; 261 262 ~QuicChromiumClientStream() override; 263 264 // quic::QuicSpdyStream 265 void OnInitialHeadersComplete( 266 bool fin, 267 size_t frame_len, 268 const quic::QuicHeaderList& header_list) override; 269 void OnTrailingHeadersComplete( 270 bool fin, 271 size_t frame_len, 272 const quic::QuicHeaderList& header_list) override; 273 void OnBodyAvailable() override; 274 void OnClose() override; 275 void OnCanWrite() override; 276 size_t WriteHeaders( 277 quiche::HttpHeaderBlock header_block, 278 bool fin, 279 quiche::QuicheReferenceCountedPointer<quic::QuicAckListenerInterface> 280 ack_listener) override; 281 282 // While the server's set_priority shouldn't be called externally, the creator 283 // of client-side streams should be able to set the priority. 284 using quic::QuicSpdyStream::SetPriority; 285 286 // Writes |data| to the peer and closes the write side if |fin| is true. 287 // Returns true if the data have been fully written. If the data was not fully 288 // written, returns false and OnCanWrite() will be invoked later. 289 bool WriteStreamData(std::string_view data, bool fin); 290 // Same as WriteStreamData except it writes data from a vector of IOBuffers, 291 // with the length of each buffer at the corresponding index in |lengths|. 292 bool WritevStreamData(const std::vector<scoped_refptr<IOBuffer>>& buffers, 293 const std::vector<int>& lengths, 294 bool fin); 295 296 // Creates a new Handle for this stream. Must only be called once. 297 std::unique_ptr<QuicChromiumClientStream::Handle> CreateHandle(); 298 299 // Clears |handle_| from this stream. 300 void ClearHandle(); 301 302 // Notifies the stream handle of error, but doesn't close the stream. 303 void OnError(int error); 304 305 // Reads at most |buf_len| bytes into |buf|. Returns the number of bytes read. 306 int Read(IOBuffer* buf, int buf_len); 307 net_log()308 const NetLogWithSource& net_log() const { return net_log_; } 309 310 // Prevents this stream from migrating to a cellular network. May be reset 311 // when connection migrates to a cellular network. 312 void DisableConnectionMigrationToCellularNetwork(); 313 can_migrate_to_cellular_network()314 bool can_migrate_to_cellular_network() { 315 return can_migrate_to_cellular_network_; 316 } 317 318 // True if the underlying QUIC session supports HTTP/3 Datagrams. 319 bool SupportsH3Datagram() const; 320 321 // Returns the largest payload that will fit into a single MESSAGE frame at 322 // any point during the connection. This assumes the version and 323 // connection ID lengths do not change. Returns zero if the stream or 324 // session are closed. 325 quic::QuicPacketLength GetGuaranteedLargestMessagePayload() const; 326 327 // True if this stream is the first data stream created on this session. 328 bool IsFirstStream(); 329 330 int DeliverEarlyHints(quiche::HttpHeaderBlock* header_block); 331 332 int DeliverInitialHeaders(quiche::HttpHeaderBlock* header_block); 333 334 bool DeliverTrailingHeaders(quiche::HttpHeaderBlock* header_block, 335 int* frame_len); 336 337 static constexpr char kHttp3DatagramDroppedHistogram[] = 338 "Net.QuicChromiumClientStream." 339 "Http3DatagramDroppedOnWriteConnectUdpPayload"; 340 341 using quic::QuicSpdyStream::HasBufferedData; 342 using quic::QuicStream::sequencer; 343 344 private: 345 void NotifyHandleOfInitialHeadersAvailableLater(); 346 void NotifyHandleOfInitialHeadersAvailable(); 347 void NotifyHandleOfTrailingHeadersAvailableLater(); 348 void NotifyHandleOfTrailingHeadersAvailable(); 349 void NotifyHandleOfDataAvailableLater(); 350 void NotifyHandleOfDataAvailable(); 351 352 NetLogWithSource net_log_; 353 raw_ptr<Handle> handle_ = nullptr; 354 355 // True when initial headers have been sent. 356 bool initial_headers_sent_ = false; 357 358 raw_ptr<quic::QuicSpdyClientSessionBase> session_; 359 const quic::QuicServerId server_id_; 360 quic::QuicTransportVersion quic_version_; 361 362 // Set to false if this stream should not be migrated to a cellular network 363 // during connection migration. 364 bool can_migrate_to_cellular_network_ = true; 365 366 // True if non-informational (non-1xx) initial headers have arrived. 367 bool initial_headers_arrived_ = false; 368 // True if non-informational (non-1xx) initial headers have been delivered to 369 // the handle. 370 bool headers_delivered_ = false; 371 // Stores the initial header until they are delivered to the handle. 372 quiche::HttpHeaderBlock initial_headers_; 373 // Length of the HEADERS frame containing initial headers. 374 size_t initial_headers_frame_len_ = 0; 375 376 // Length of the HEADERS frame containing trailing headers. 377 size_t trailing_headers_frame_len_ = 0; 378 379 struct EarlyHints { EarlyHintsEarlyHints380 EarlyHints(quiche::HttpHeaderBlock headers, size_t frame_len) 381 : headers(std::move(headers)), frame_len(frame_len) {} 382 EarlyHints(EarlyHints&& other) = default; 383 EarlyHints& operator=(EarlyHints&& other) = default; 384 EarlyHints(const EarlyHints& other) = delete; 385 EarlyHints& operator=(const EarlyHints& other) = delete; 386 387 quiche::HttpHeaderBlock headers; 388 size_t frame_len = 0; 389 }; 390 base::circular_deque<EarlyHints> early_hints_; 391 392 base::WeakPtrFactory<QuicChromiumClientStream> weak_factory_{this}; 393 }; 394 395 } // namespace net 396 397 #endif // NET_QUIC_QUIC_CHROMIUM_CLIENT_STREAM_H_ 398