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