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
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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 "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/http/bidirectional_stream_job.h"
#include "net/http/http_stream_factory.h"
#include "net/log/net_log.h"
class GURL;
namespace net {
class HttpAuthController;
class HttpNetworkSession;
class HttpStream;
class HttpStreamRequest;
class IOBuffer;
class ProxyInfo;
class SpdyHeaderBlock;
struct BidirectionalStreamRequestInfo;
struct SSLConfig;
// A class to do HTTP/2 bidirectional streaming. Note that at most one each of
// ReadData or SendData should be in flight until the operation completes.
// The BidirectionalStream must be torn down before the HttpNetworkSession.
class NET_EXPORT BidirectionalStream
: public NON_EXPORTED_BASE(BidirectionalStreamJob::Delegate),
public NON_EXPORTED_BASE(HttpStreamRequest::Delegate) {
public:
// Delegate interface to get notified of success of failure. Callbacks will be
// invoked asynchronously.
class NET_EXPORT Delegate {
public:
Delegate();
// Called when headers have been sent. 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.
virtual void OnHeadersSent() = 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 SpdyHeaderBlock& 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 SpdyHeaderBlock& trailers) = 0;
// Called when the stream is closed or an error occurred.
// No other delegate functions will be called after this.
virtual void OnFailed(int error) = 0;
protected:
virtual ~Delegate();
private:
DISALLOW_COPY_AND_ASSIGN(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|.
BidirectionalStream(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
HttpNetworkSession* session,
Delegate* delegate);
// Constructor that accepts a Timer, which can be used in tests to control
// the buffering of received data.
BidirectionalStream(scoped_ptr<BidirectionalStreamRequestInfo> request_info,
HttpNetworkSession* session,
Delegate* delegate,
scoped_ptr<base::Timer> timer);
// Cancels |stream_request_| or |stream_job_| if applicable.
// |this| should not be destroyed during Delegate::OnHeadersSent or
// Delegate::OnDataSent.
~BidirectionalStream() override;
// 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::OnHeadersReceived 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::OnHeadersSent 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 SendData(IOBuffer* data, int length, bool end_stream);
// If |stream_request_| is non-NULL, cancel it. If |stream_job_| is
// established, cancel it. No delegate method will be called after Cancel().
// Any pending operations may or may not succeed.
void Cancel();
// 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;
// TODO(xunjieli): Implement a method to do flow control and a method to ping
// remote end point.
private:
// BidirectionalStreamJob::Delegate implementation:
void OnHeadersSent() override;
void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override;
void OnDataRead(int bytes_read) override;
void OnDataSent() override;
void OnTrailersReceived(const SpdyHeaderBlock& trailers) override;
void OnFailed(int error) override;
// HttpStreamRequest::Delegate implementation:
void OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override;
void OnBidirectionalStreamJobReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
BidirectionalStreamJob* stream) override;
void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
WebSocketHandshakeStreamBase* stream) override;
void OnStreamFailed(int status,
const SSLConfig& used_ssl_config,
SSLFailureState ssl_failure_state) override;
void OnCertificateError(int status,
const SSLConfig& used_ssl_config,
const SSLInfo& ssl_info) override;
void OnNeedsProxyAuth(const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpAuthController* auth_controller) override;
void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) override;
void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStream* stream) override;
void OnQuicBroken() override;
// BidirectionalStreamRequestInfo used when requesting the stream.
scoped_ptr<BidirectionalStreamRequestInfo> request_info_;
const BoundNetLog net_log_;
HttpNetworkSession* session_;
Delegate* const delegate_;
// Timer used to buffer data received in short time-spans and send a single
// read completion notification.
scoped_ptr<base::Timer> timer_;
// HttpStreamRequest used to request a BidirectionalStreamJob. This is NULL if
// the request has been canceled or completed.
scoped_ptr<HttpStreamRequest> stream_request_;
// The underlying BidirectioanlStreamJob used for this stream. It is non-NULL,
// if the |stream_request_| successfully finishes.
scoped_ptr<BidirectionalStreamJob> stream_job_;
DISALLOW_COPY_AND_ASSIGN(BidirectionalStream);
};
} // namespace net
#endif // NET_HTTP_BIDIRECTIONAL_STREAM_H_
|