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