• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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