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