xref: /aosp_15_r20/external/cronet/net/http/bidirectional_stream.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 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_HTTP_BIDIRECTIONAL_STREAM_H_
6 #define NET_HTTP_BIDIRECTIONAL_STREAM_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <vector>
12 
13 #include "base/compiler_specific.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/time/time.h"
18 #include "net/base/load_timing_info.h"
19 #include "net/base/net_export.h"
20 #include "net/http/bidirectional_stream_impl.h"
21 #include "net/http/http_stream_factory.h"
22 #include "net/http/http_stream_request.h"
23 #include "net/log/net_log_with_source.h"
24 #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h"
25 
26 namespace base {
27 class OneShotTimer;
28 }  // namespace base
29 
30 namespace net {
31 
32 class HttpAuthController;
33 class HttpNetworkSession;
34 class HttpStream;
35 class IOBuffer;
36 class ProxyInfo;
37 struct BidirectionalStreamRequestInfo;
38 struct NetErrorDetails;
39 
40 // A class to do HTTP/2 bidirectional streaming. Note that at most one each of
41 // ReadData or SendData/SendvData should be in flight until the operation
42 // completes. The BidirectionalStream must be torn down before the
43 // HttpNetworkSession.
44 class NET_EXPORT BidirectionalStream : public BidirectionalStreamImpl::Delegate,
45                                        public HttpStreamRequest::Delegate {
46  public:
47   // Delegate interface to get notified of success of failure. Callbacks will be
48   // invoked asynchronously.
49   class NET_EXPORT Delegate {
50    public:
51     Delegate();
52 
53     Delegate(const Delegate&) = delete;
54     Delegate& operator=(const Delegate&) = delete;
55 
56     // Called when the stream is ready for writing and reading. This is called
57     // at most once for the lifetime of a stream.
58     // The delegate may call BidirectionalStream::ReadData to start reading,
59     // or call BidirectionalStream::SendData to send data.
60     // The delegate should not call BidirectionalStream::Cancel
61     // during this callback.
62     // |request_headers_sent| if true, request headers have been sent. If false,
63     // SendRequestHeaders() needs to be explicitly called.
64     virtual void OnStreamReady(bool request_headers_sent) = 0;
65 
66     // Called when headers are received. This is called at most once for the
67     // lifetime of a stream.
68     // The delegate may call BidirectionalStream::ReadData to start reading,
69     // call BidirectionalStream::SendData to send data,
70     // or call BidirectionalStream::Cancel to cancel the stream.
71     virtual void OnHeadersReceived(
72         const spdy::Http2HeaderBlock& response_headers) = 0;
73 
74     // Called when a pending read is completed asynchronously.
75     // |bytes_read| specifies how much data is read.
76     // The delegate may call BidirectionalStream::ReadData to continue
77     // reading, call BidirectionalStream::SendData to send data,
78     // or call BidirectionalStream::Cancel to cancel the stream.
79     virtual void OnDataRead(int bytes_read) = 0;
80 
81     // Called when the entire buffer passed through SendData is sent.
82     // The delegate may call BidirectionalStream::ReadData to continue
83     // reading, call BidirectionalStream::SendData to send data,
84     // The delegate should not call BidirectionalStream::Cancel
85     // during this callback.
86     virtual void OnDataSent() = 0;
87 
88     // Called when trailers are received. This is called as soon as trailers
89     // are received, which can happen before a read completes.
90     // The delegate is able to continue reading if there is no pending read and
91     // EOF has not been received, or to send data if there is no pending send.
92     virtual void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) = 0;
93 
94     // Called when an error occurred. Do not call into the stream after this
95     // point. No other delegate functions will be called after this.
96     virtual void OnFailed(int error) = 0;
97 
98    protected:
99     virtual ~Delegate();
100   };
101 
102   // Constructs a BidirectionalStream. |request_info| contains information about
103   // the request, and must be non-NULL. |session| is the http network session
104   // with which this request will be made. |delegate| must be non-NULL.
105   // |session| and |delegate| must outlive |this|.
106   // |send_request_headers_automatically| if true, request headers will be sent
107   // automatically when stream is negotiated. If false, request headers will be
108   // sent only when SendRequestHeaders() is invoked or with
109   // next SendData/SendvData.
110   BidirectionalStream(
111       std::unique_ptr<BidirectionalStreamRequestInfo> request_info,
112       HttpNetworkSession* session,
113       bool send_request_headers_automatically,
114       Delegate* delegate);
115 
116   // Constructor that accepts a Timer, which can be used in tests to control
117   // the buffering of received data.
118   BidirectionalStream(
119       std::unique_ptr<BidirectionalStreamRequestInfo> request_info,
120       HttpNetworkSession* session,
121       bool send_request_headers_automatically,
122       Delegate* delegate,
123       std::unique_ptr<base::OneShotTimer> timer);
124 
125   BidirectionalStream(const BidirectionalStream&) = delete;
126   BidirectionalStream& operator=(const BidirectionalStream&) = delete;
127 
128   // Cancels |stream_request_| or |stream_impl_| if applicable.
129   // |this| should not be destroyed during Delegate::OnHeadersSent or
130   // Delegate::OnDataSent.
131   ~BidirectionalStream() override;
132 
133   // Sends request headers to server.
134   // When |send_request_headers_automatically_| is
135   // false and OnStreamReady() is invoked with request_headers_sent = false,
136   // headers will be combined with next SendData/SendvData unless this
137   // method is called first, in which case headers will be sent separately
138   // without delay.
139   // (This method cannot be called when |send_request_headers_automatically_| is
140   // true nor when OnStreamReady() is invoked with request_headers_sent = true,
141   // since headers have been sent by the stream when stream is negotiated
142   // successfully.)
143   void SendRequestHeaders();
144 
145   // Reads at most |buf_len| bytes into |buf|. Returns the number of bytes read,
146   // or ERR_IO_PENDING if the read is to be completed asynchronously, or an
147   // error code if any error occurred. If returns 0, there is no more data to
148   // read. This should not be called before Delegate::OnStreamReady is
149   // invoked, and should not be called again unless it returns with number
150   // greater than 0 or until Delegate::OnDataRead is invoked.
151   int ReadData(IOBuffer* buf, int buf_len);
152 
153   // Sends data. This should not be called before Delegate::OnStreamReady is
154   // invoked, and should not be called again until Delegate::OnDataSent is
155   // invoked. If |end_stream| is true, the DATA frame will have an END_STREAM
156   // flag.
157   void SendvData(const std::vector<scoped_refptr<IOBuffer>>& buffers,
158                  const std::vector<int>& lengths,
159                  bool end_stream);
160 
161   // Returns the protocol used by this stream. If stream has not been
162   // established, return kProtoUnknown.
163   NextProto GetProtocol() const;
164 
165   // Total number of bytes received over the network of SPDY data, headers, and
166   // push_promise frames associated with this stream, including the size of
167   // frame headers, after SSL decryption and not including proxy overhead.
168   // If stream has not been established, return 0.
169   int64_t GetTotalReceivedBytes() const;
170 
171   // Total number of bytes sent over the network of SPDY frames associated with
172   // this stream, including the size of frame headers, before SSL encryption and
173   // not including proxy overhead. Note that some SPDY frames such as pings are
174   // not associated with any stream, and are not included in this value.
175   int64_t GetTotalSentBytes() const;
176 
177   // Gets LoadTimingInfo of this stream.
178   void GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
179 
180   // Get the network error details this stream is encountering.
181   // Fills in |details| if it is available; leaves |details| unchanged if it
182   // is unavailable.
183   void PopulateNetErrorDetails(NetErrorDetails* details);
184 
185  private:
186   void StartRequest();
187   // BidirectionalStreamImpl::Delegate implementation:
188   void OnStreamReady(bool request_headers_sent) override;
189   void OnHeadersReceived(
190       const spdy::Http2HeaderBlock& response_headers) override;
191   void OnDataRead(int bytes_read) override;
192   void OnDataSent() override;
193   void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override;
194   void OnFailed(int error) override;
195 
196   // HttpStreamRequest::Delegate implementation:
197   void OnStreamReady(const ProxyInfo& used_proxy_info,
198                      std::unique_ptr<HttpStream> stream) override;
199   void OnBidirectionalStreamImplReady(
200       const ProxyInfo& used_proxy_info,
201       std::unique_ptr<BidirectionalStreamImpl> stream) override;
202   void OnWebSocketHandshakeStreamReady(
203       const ProxyInfo& used_proxy_info,
204       std::unique_ptr<WebSocketHandshakeStreamBase> stream) override;
205   void OnStreamFailed(int status,
206                       const NetErrorDetails& net_error_details,
207                       const ProxyInfo& used_proxy_info,
208                       ResolveErrorInfo resolve_error_info) override;
209   void OnCertificateError(int status, const SSLInfo& ssl_info) override;
210   void OnNeedsProxyAuth(const HttpResponseInfo& response_info,
211                         const ProxyInfo& used_proxy_info,
212                         HttpAuthController* auth_controller) override;
213   void OnNeedsClientAuth(SSLCertRequestInfo* cert_info) override;
214   void OnQuicBroken() override;
215 
216   // Helper method to notify delegate if there is an error.
217   void NotifyFailed(int error);
218 
219   // BidirectionalStreamRequestInfo used when requesting the stream.
220   std::unique_ptr<BidirectionalStreamRequestInfo> request_info_;
221   const NetLogWithSource net_log_;
222 
223   raw_ptr<HttpNetworkSession, DanglingUntriaged> session_;
224 
225   bool send_request_headers_automatically_;
226   // Whether request headers have been sent, as indicated in OnStreamReady()
227   // callback.
228   bool request_headers_sent_ = false;
229 
230   const raw_ptr<Delegate> delegate_;
231 
232   // Timer used to buffer data received in short time-spans and send a single
233   // read completion notification.
234   std::unique_ptr<base::OneShotTimer> timer_;
235   // HttpStreamRequest used to request a BidirectionalStreamImpl. This is NULL
236   // if the request has been canceled or completed.
237   std::unique_ptr<HttpStreamRequest> stream_request_;
238   // The underlying BidirectioanlStreamImpl used for this stream. It is
239   // non-NULL, if the |stream_request_| successfully finishes.
240   std::unique_ptr<BidirectionalStreamImpl> stream_impl_;
241 
242   // Buffer used for reading.
243   scoped_refptr<IOBuffer> read_buffer_;
244   // List of buffers used for writing.
245   std::vector<scoped_refptr<IOBuffer>> write_buffer_list_;
246   // List of buffer length.
247   std::vector<int> write_buffer_len_list_;
248 
249   // TODO(xunjieli): Remove this once LoadTimingInfo has response end.
250   base::TimeTicks read_end_time_;
251 
252   // Load timing info of this stream. |connect_timing| is obtained when headers
253   // are received. Other fields are populated at different stages of the request
254   LoadTimingInfo load_timing_info_;
255 
256   base::WeakPtrFactory<BidirectionalStream> weak_factory_{this};
257 };
258 
259 }  // namespace net
260 
261 #endif  // NET_HTTP_BIDIRECTIONAL_STREAM_H_
262