blob: 11c6a840c5d93e6b5bc4aa4dcf88e037b082c271 [file] [log] [blame]
xunjieli11834f02015-12-22 04:27:081// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/http/bidirectional_stream.h"
6
xunjielid4c21ab2016-04-28 22:44:477#include <string>
Bence Béky6d05ebd2017-05-16 00:09:018#include <utility>
danakj1fd259a02016-04-16 03:17:099
xunjieli11834f02015-12-22 04:27:0810#include "base/bind.h"
11#include "base/location.h"
12#include "base/logging.h"
xunjielid58621f2016-08-12 18:33:0013#include "base/metrics/histogram_macros.h"
gabf767595f2016-05-11 18:50:3514#include "base/threading/thread_task_runner_handle.h"
xunjieli11834f02015-12-22 04:27:0815#include "base/timer/timer.h"
xunjielid4c21ab2016-04-28 22:44:4716#include "base/values.h"
xunjieli11834f02015-12-22 04:27:0817#include "net/base/load_flags.h"
18#include "net/base/net_errors.h"
19#include "net/http/bidirectional_stream_request_info.h"
20#include "net/http/http_network_session.h"
xunjielib3a648e2016-03-22 03:39:5121#include "net/http/http_response_headers.h"
xunjieli11834f02015-12-22 04:27:0822#include "net/http/http_stream.h"
mikecironef22f9812016-10-04 03:40:1923#include "net/log/net_log.h"
xunjielid4c21ab2016-04-28 22:44:4724#include "net/log/net_log_capture_mode.h"
mikecirone8b85c432016-09-08 19:11:0025#include "net/log/net_log_event_type.h"
26#include "net/log/net_log_source_type.h"
Bence Béky94658bf2018-05-11 19:22:5827#include "net/spdy/spdy_http_utils.h"
28#include "net/spdy/spdy_log_util.h"
xunjieli11834f02015-12-22 04:27:0829#include "net/ssl/ssl_cert_request_info.h"
30#include "net/ssl/ssl_config.h"
Ryan Hamilton2e003eea2018-05-02 00:24:2931#include "net/third_party/spdy/core/spdy_header_block.h"
Ramin Halavati3c96c6d2018-03-11 13:29:4432#include "net/traffic_annotation/network_traffic_annotation.h"
xunjieli11834f02015-12-22 04:27:0833#include "url/gurl.h"
34
35namespace net {
36
xunjielid4c21ab2016-04-28 22:44:4737namespace {
38
39std::unique_ptr<base::Value> NetLogHeadersCallback(
Ryan Hamilton0239aac2018-05-19 00:03:1340 const spdy::SpdyHeaderBlock* headers,
xunjielid4c21ab2016-04-28 22:44:4741 NetLogCaptureMode capture_mode) {
Jeremy Roman0579ed62017-08-29 15:56:1942 auto dict = std::make_unique<base::DictionaryValue>();
xunjielid4c21ab2016-04-28 22:44:4743 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode));
44 return std::move(dict);
45}
46
47std::unique_ptr<base::Value> NetLogCallback(const GURL* url,
48 const std::string* method,
49 const HttpRequestHeaders* headers,
50 NetLogCaptureMode capture_mode) {
Jeremy Roman0579ed62017-08-29 15:56:1951 auto dict = std::make_unique<base::DictionaryValue>();
xunjielid4c21ab2016-04-28 22:44:4752 dict->SetString("url", url->possibly_invalid_spec());
53 dict->SetString("method", *method);
54 std::string empty;
55 std::unique_ptr<base::Value> headers_param(
56 headers->NetLogCallback(&empty, capture_mode));
57 dict->Set("headers", std::move(headers_param));
58 return std::move(dict);
59}
60
61} // namespace
62
Chris Watkins7a41d3552017-12-01 02:13:2763BidirectionalStream::Delegate::Delegate() = default;
xunjieli11834f02015-12-22 04:27:0864
Chris Watkins7a41d3552017-12-01 02:13:2765BidirectionalStream::Delegate::~Delegate() = default;
xunjieli11834f02015-12-22 04:27:0866
67BidirectionalStream::BidirectionalStream(
danakj1fd259a02016-04-16 03:17:0968 std::unique_ptr<BidirectionalStreamRequestInfo> request_info,
xunjieli11834f02015-12-22 04:27:0869 HttpNetworkSession* session,
xunjielibcb0f86e2016-06-03 00:49:2970 bool send_request_headers_automatically,
xunjieli11834f02015-12-22 04:27:0871 Delegate* delegate)
72 : BidirectionalStream(std::move(request_info),
73 session,
xunjielibcb0f86e2016-06-03 00:49:2974 send_request_headers_automatically,
xunjieli11834f02015-12-22 04:27:0875 delegate,
Jeremy Roman0579ed62017-08-29 15:56:1976 std::make_unique<base::Timer>(false, false)) {}
xunjieli11834f02015-12-22 04:27:0877
78BidirectionalStream::BidirectionalStream(
danakj1fd259a02016-04-16 03:17:0979 std::unique_ptr<BidirectionalStreamRequestInfo> request_info,
xunjieli11834f02015-12-22 04:27:0880 HttpNetworkSession* session,
xunjielibcb0f86e2016-06-03 00:49:2981 bool send_request_headers_automatically,
xunjieli11834f02015-12-22 04:27:0882 Delegate* delegate,
danakj1fd259a02016-04-16 03:17:0983 std::unique_ptr<base::Timer> timer)
xunjieli11834f02015-12-22 04:27:0884 : request_info_(std::move(request_info)),
tfarina428341112016-09-22 13:38:2085 net_log_(NetLogWithSource::Make(session->net_log(),
86 NetLogSourceType::BIDIRECTIONAL_STREAM)),
xunjielib3a648e2016-03-22 03:39:5187 session_(session),
xunjielibcb0f86e2016-06-03 00:49:2988 send_request_headers_automatically_(send_request_headers_automatically),
89 request_headers_sent_(false),
xunjieli11834f02015-12-22 04:27:0890 delegate_(delegate),
xunjieli3b6ac702016-06-06 21:36:2891 timer_(std::move(timer)),
92 weak_factory_(this) {
xunjieli11834f02015-12-22 04:27:0893 DCHECK(delegate_);
94 DCHECK(request_info_);
95
xunjieli369d0922016-09-23 18:45:0696 // Start time should be measured before connect.
97 load_timing_info_.request_start_time = base::Time::Now();
98 load_timing_info_.request_start = base::TimeTicks::Now();
99
xunjielif88028e2016-06-01 19:27:14100 if (net_log_.IsCapturing()) {
101 net_log_.BeginEvent(
mikecirone8b85c432016-09-08 19:11:00102 NetLogEventType::BIDIRECTIONAL_STREAM_ALIVE,
xunjielif88028e2016-06-01 19:27:14103 base::Bind(&NetLogCallback, &request_info_->url, &request_info_->method,
104 base::Unretained(&request_info_->extra_headers)));
105 }
106
xunjieli11834f02015-12-22 04:27:08107 if (!request_info_->url.SchemeIs(url::kHttpsScheme)) {
108 base::ThreadTaskRunnerHandle::Get()->PostTask(
109 FROM_HERE,
xunjieli3b6ac702016-06-06 21:36:28110 base::Bind(&BidirectionalStream::NotifyFailed,
111 weak_factory_.GetWeakPtr(), ERR_DISALLOWED_URL_SCHEME));
xunjieli11834f02015-12-22 04:27:08112 return;
113 }
114
Helen Li43e3bee2018-03-21 16:57:11115 SSLConfig ssl_config;
116 session->ssl_config_service()->GetSSLConfig(&ssl_config);
117 session->GetAlpnProtos(&ssl_config.alpn_protos);
118
119 StartRequest(ssl_config);
xunjieli11834f02015-12-22 04:27:08120}
121
122BidirectionalStream::~BidirectionalStream() {
xunjielid58621f2016-08-12 18:33:00123 UpdateHistograms();
xunjielid4c21ab2016-04-28 22:44:47124 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00125 net_log_.EndEvent(NetLogEventType::BIDIRECTIONAL_STREAM_ALIVE);
xunjielid4c21ab2016-04-28 22:44:47126 }
xunjieli11834f02015-12-22 04:27:08127}
128
xunjielibcb0f86e2016-06-03 00:49:29129void BidirectionalStream::SendRequestHeaders() {
130 DCHECK(stream_impl_);
131 DCHECK(!request_headers_sent_);
132 DCHECK(!send_request_headers_automatically_);
133
134 stream_impl_->SendRequestHeaders();
135}
136
xunjieli11834f02015-12-22 04:27:08137int BidirectionalStream::ReadData(IOBuffer* buf, int buf_len) {
xunjieli5749218c2016-03-22 16:43:06138 DCHECK(stream_impl_);
xunjieli11834f02015-12-22 04:27:08139
xunjielibe07785e2016-04-14 21:15:29140 int rv = stream_impl_->ReadData(buf, buf_len);
141 if (rv > 0) {
xunjielid58621f2016-08-12 18:33:00142 read_end_time_ = base::TimeTicks::Now();
xunjielibe07785e2016-04-14 21:15:29143 net_log_.AddByteTransferEvent(
mikecirone8b85c432016-09-08 19:11:00144 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_RECEIVED, rv, buf->data());
xunjielibe07785e2016-04-14 21:15:29145 } else if (rv == ERR_IO_PENDING) {
146 read_buffer_ = buf;
147 // Bytes will be logged in OnDataRead().
148 }
xunjielie1780482016-07-01 21:22:54149 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00150 net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_READ_DATA,
xunjielie1780482016-07-01 21:22:54151 NetLog::IntCallback("rv", rv));
152 }
xunjielibe07785e2016-04-14 21:15:29153 return rv;
xunjieli11834f02015-12-22 04:27:08154}
155
xunjieli2328a2682016-05-16 19:38:25156void BidirectionalStream::SendvData(
157 const std::vector<scoped_refptr<IOBuffer>>& buffers,
158 const std::vector<int>& lengths,
159 bool end_stream) {
xunjieli07a42ce2016-04-26 20:05:31160 DCHECK(stream_impl_);
161 DCHECK_EQ(buffers.size(), lengths.size());
162 DCHECK(write_buffer_list_.empty());
163 DCHECK(write_buffer_len_list_.empty());
164
xunjielie1780482016-07-01 21:22:54165 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00166 net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_SENDV_DATA,
xunjielie1780482016-07-01 21:22:54167 NetLog::IntCallback("num_buffers", buffers.size()));
168 }
xunjieli07a42ce2016-04-26 20:05:31169 stream_impl_->SendvData(buffers, lengths, end_stream);
170 for (size_t i = 0; i < buffers.size(); ++i) {
171 write_buffer_list_.push_back(buffers[i]);
172 write_buffer_len_list_.push_back(lengths[i]);
173 }
xunjieli11834f02015-12-22 04:27:08174}
175
xunjieli11834f02015-12-22 04:27:08176NextProto BidirectionalStream::GetProtocol() const {
xunjieli5749218c2016-03-22 16:43:06177 if (!stream_impl_)
xunjieli11834f02015-12-22 04:27:08178 return kProtoUnknown;
179
xunjieli5749218c2016-03-22 16:43:06180 return stream_impl_->GetProtocol();
xunjieli11834f02015-12-22 04:27:08181}
182
183int64_t BidirectionalStream::GetTotalReceivedBytes() const {
xunjieli5749218c2016-03-22 16:43:06184 if (!stream_impl_)
xunjieli11834f02015-12-22 04:27:08185 return 0;
186
xunjieli5749218c2016-03-22 16:43:06187 return stream_impl_->GetTotalReceivedBytes();
xunjieli11834f02015-12-22 04:27:08188}
189
190int64_t BidirectionalStream::GetTotalSentBytes() const {
xunjieli5749218c2016-03-22 16:43:06191 if (!stream_impl_)
xunjieli11834f02015-12-22 04:27:08192 return 0;
193
xunjieli5749218c2016-03-22 16:43:06194 return stream_impl_->GetTotalSentBytes();
xunjieli11834f02015-12-22 04:27:08195}
196
xunjieli369d0922016-09-23 18:45:06197void BidirectionalStream::GetLoadTimingInfo(
198 LoadTimingInfo* load_timing_info) const {
199 *load_timing_info = load_timing_info_;
200}
201
Brad Lassey5f488db42017-07-19 00:30:46202void BidirectionalStream::PopulateNetErrorDetails(NetErrorDetails* details) {
203 DCHECK(details);
204 if (stream_impl_)
205 stream_impl_->PopulateNetErrorDetails(details);
206}
207
Helen Li43e3bee2018-03-21 16:57:11208void BidirectionalStream::StartRequest(const SSLConfig& ssl_config) {
209 DCHECK(!stream_request_);
210 HttpRequestInfo http_request_info;
211 http_request_info.url = request_info_->url;
212 http_request_info.method = request_info_->method;
213 http_request_info.extra_headers = request_info_->extra_headers;
214 http_request_info.socket_tag = request_info_->socket_tag;
215 stream_request_ =
216 session_->http_stream_factory()->RequestBidirectionalStreamImpl(
217 http_request_info, request_info_->priority, ssl_config, ssl_config,
218 this,
219 /* enable_ip_based_pooling = */ true,
220 /* enable_alternative_services = */ true, net_log_);
221 // Check that this call does not fail.
222 DCHECK(stream_request_);
223 // Check that HttpStreamFactory does not invoke OnBidirectionalStreamImplReady
224 // synchronously.
225 DCHECK(!stream_impl_);
226}
227
xunjielibcb0f86e2016-06-03 00:49:29228void BidirectionalStream::OnStreamReady(bool request_headers_sent) {
229 request_headers_sent_ = request_headers_sent;
xunjieli2704f5d2016-06-10 16:02:23230 if (net_log_.IsCapturing()) {
231 net_log_.AddEvent(
mikecirone8b85c432016-09-08 19:11:00232 NetLogEventType::BIDIRECTIONAL_STREAM_READY,
xunjieli2704f5d2016-06-10 16:02:23233 NetLog::BoolCallback("request_headers_sent", request_headers_sent));
234 }
xunjieli369d0922016-09-23 18:45:06235 load_timing_info_.send_start = base::TimeTicks::Now();
236 load_timing_info_.send_end = load_timing_info_.send_start;
xunjielibcb0f86e2016-06-03 00:49:29237 delegate_->OnStreamReady(request_headers_sent);
xunjieli11834f02015-12-22 04:27:08238}
239
240void BidirectionalStream::OnHeadersReceived(
Ryan Hamilton0239aac2018-05-19 00:03:13241 const spdy::SpdyHeaderBlock& response_headers) {
xunjielib3a648e2016-03-22 03:39:51242 HttpResponseInfo response_info;
bncbca843ba2016-07-14 13:05:48243 if (!SpdyHeadersToHttpResponse(response_headers, &response_info)) {
xunjielib3a648e2016-03-22 03:39:51244 DLOG(WARNING) << "Invalid headers";
xunjieli3b6ac702016-06-06 21:36:28245 NotifyFailed(ERR_FAILED);
xunjielib3a648e2016-03-22 03:39:51246 return;
247 }
xunjielid4c21ab2016-04-28 22:44:47248 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00249 net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_RECV_HEADERS,
xunjielid4c21ab2016-04-28 22:44:47250 base::Bind(&NetLogHeadersCallback, &response_headers));
251 }
xunjieli369d0922016-09-23 18:45:06252 // Impl should only provide |connect_timing| and |socket_reused| info,
253 // so use a copy to get these information only.
254 LoadTimingInfo impl_load_timing_info;
255 bool has_load_timing =
256 stream_impl_->GetLoadTimingInfo(&impl_load_timing_info);
257 if (has_load_timing) {
258 load_timing_info_.connect_timing = impl_load_timing_info.connect_timing;
259 load_timing_info_.socket_reused = impl_load_timing_info.socket_reused;
260 }
261 load_timing_info_.receive_headers_end = base::TimeTicks::Now();
262 read_end_time_ = load_timing_info_.receive_headers_end;
xunjielib3a648e2016-03-22 03:39:51263 session_->http_stream_factory()->ProcessAlternativeServices(
264 session_, response_info.headers.get(),
zhongyi3d4a55e72016-04-22 20:36:46265 url::SchemeHostPort(request_info_->url));
xunjieli11834f02015-12-22 04:27:08266 delegate_->OnHeadersReceived(response_headers);
267}
268
269void BidirectionalStream::OnDataRead(int bytes_read) {
xunjielibe07785e2016-04-14 21:15:29270 DCHECK(read_buffer_);
271
xunjielid4c21ab2016-04-28 22:44:47272 if (net_log_.IsCapturing()) {
273 net_log_.AddByteTransferEvent(
mikecirone8b85c432016-09-08 19:11:00274 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_RECEIVED, bytes_read,
xunjielid4c21ab2016-04-28 22:44:47275 read_buffer_->data());
276 }
xunjielid58621f2016-08-12 18:33:00277 read_end_time_ = base::TimeTicks::Now();
xunjielibe07785e2016-04-14 21:15:29278 read_buffer_ = nullptr;
xunjieli11834f02015-12-22 04:27:08279 delegate_->OnDataRead(bytes_read);
280}
281
282void BidirectionalStream::OnDataSent() {
xunjieli07a42ce2016-04-26 20:05:31283 DCHECK(!write_buffer_list_.empty());
284 DCHECK_EQ(write_buffer_list_.size(), write_buffer_len_list_.size());
xunjielibe07785e2016-04-14 21:15:29285
xunjielid4c21ab2016-04-28 22:44:47286 if (net_log_.IsCapturing()) {
xunjieli2704f5d2016-06-10 16:02:23287 if (write_buffer_list_.size() > 1) {
288 net_log_.BeginEvent(
mikecirone8b85c432016-09-08 19:11:00289 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT_COALESCED,
xunjieli2704f5d2016-06-10 16:02:23290 NetLog::IntCallback("num_buffers_coalesced",
291 write_buffer_list_.size()));
292 }
xunjielid4c21ab2016-04-28 22:44:47293 for (size_t i = 0; i < write_buffer_list_.size(); ++i) {
294 net_log_.AddByteTransferEvent(
mikecirone8b85c432016-09-08 19:11:00295 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT,
xunjielid4c21ab2016-04-28 22:44:47296 write_buffer_len_list_[i], write_buffer_list_[i]->data());
297 }
xunjieli2704f5d2016-06-10 16:02:23298 if (write_buffer_list_.size() > 1) {
mikecirone8b85c432016-09-08 19:11:00299 net_log_.EndEvent(
300 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT_COALESCED);
xunjieli2704f5d2016-06-10 16:02:23301 }
xunjieli07a42ce2016-04-26 20:05:31302 }
xunjieli369d0922016-09-23 18:45:06303 load_timing_info_.send_end = base::TimeTicks::Now();
xunjieli07a42ce2016-04-26 20:05:31304 write_buffer_list_.clear();
305 write_buffer_len_list_.clear();
xunjieli11834f02015-12-22 04:27:08306 delegate_->OnDataSent();
307}
308
Ryan Hamilton0239aac2018-05-19 00:03:13309void BidirectionalStream::OnTrailersReceived(
310 const spdy::SpdyHeaderBlock& trailers) {
xunjielid4c21ab2016-04-28 22:44:47311 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00312 net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_RECV_TRAILERS,
xunjielid4c21ab2016-04-28 22:44:47313 base::Bind(&NetLogHeadersCallback, &trailers));
314 }
xunjielid58621f2016-08-12 18:33:00315 read_end_time_ = base::TimeTicks::Now();
xunjieli11834f02015-12-22 04:27:08316 delegate_->OnTrailersReceived(trailers);
317}
318
319void BidirectionalStream::OnFailed(int status) {
xunjieli2704f5d2016-06-10 16:02:23320 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00321 net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_FAILED,
xunjieli2704f5d2016-06-10 16:02:23322 NetLog::IntCallback("net_error", status));
323 }
xunjieli3b6ac702016-06-06 21:36:28324 NotifyFailed(status);
xunjieli11834f02015-12-22 04:27:08325}
326
327void BidirectionalStream::OnStreamReady(const SSLConfig& used_ssl_config,
328 const ProxyInfo& used_proxy_info,
bnc5029f4632017-06-08 16:19:00329 std::unique_ptr<HttpStream> stream) {
xunjieli11834f02015-12-22 04:27:08330 NOTREACHED();
331}
332
xunjieli5749218c2016-03-22 16:43:06333void BidirectionalStream::OnBidirectionalStreamImplReady(
xunjieli11834f02015-12-22 04:27:08334 const SSLConfig& used_ssl_config,
335 const ProxyInfo& used_proxy_info,
bnc5029f4632017-06-08 16:19:00336 std::unique_ptr<BidirectionalStreamImpl> stream) {
xunjieli5749218c2016-03-22 16:43:06337 DCHECK(!stream_impl_);
xunjieli11834f02015-12-22 04:27:08338
Ramin Halavati3c96c6d2018-03-11 13:29:44339 net::NetworkTrafficAnnotationTag traffic_annotation =
340 net::DefineNetworkTrafficAnnotation("bidirectional_stream", R"(
341 semantics {
342 sender: "Bidirectional Stream"
343 description:
344 "Bidirectional stream is used to exchange data with a server on "
345 "behalf of an RPC API."
346 trigger:
347 "When an application makes an RPC to the server."
348 data:
349 "Any arbitrary data."
350 destination: OTHER
351 destination_other:
352 "Any destination that the application chooses."
353 }
354 policy {
355 cookies_allowed: NO
356 setting: "This feature is not used in Chrome."
357 policy_exception_justification:
358 "This feature is not used in Chrome."
359 }
360 )");
361
xunjieli11834f02015-12-22 04:27:08362 stream_request_.reset();
bnc5029f4632017-06-08 16:19:00363 stream_impl_ = std::move(stream);
xunjielibcb0f86e2016-06-03 00:49:29364 stream_impl_->Start(request_info_.get(), net_log_,
365 send_request_headers_automatically_, this,
Ramin Halavati3c96c6d2018-03-11 13:29:44366 std::move(timer_), traffic_annotation);
xunjieli11834f02015-12-22 04:27:08367}
368
369void BidirectionalStream::OnWebSocketHandshakeStreamReady(
370 const SSLConfig& used_ssl_config,
371 const ProxyInfo& used_proxy_info,
bnc5029f4632017-06-08 16:19:00372 std::unique_ptr<WebSocketHandshakeStreamBase> stream) {
xunjieli11834f02015-12-22 04:27:08373 NOTREACHED();
374}
375
Ryan Hamilton75f197262017-08-17 14:00:07376void BidirectionalStream::OnStreamFailed(
377 int result,
378 const NetErrorDetails& net_error_details,
379 const SSLConfig& used_ssl_config) {
xunjieli11834f02015-12-22 04:27:08380 DCHECK_LT(result, 0);
381 DCHECK_NE(result, ERR_IO_PENDING);
382 DCHECK(stream_request_);
383
xunjieli3b6ac702016-06-06 21:36:28384 NotifyFailed(result);
xunjieli11834f02015-12-22 04:27:08385}
386
387void BidirectionalStream::OnCertificateError(int result,
388 const SSLConfig& used_ssl_config,
389 const SSLInfo& ssl_info) {
390 DCHECK_LT(result, 0);
391 DCHECK_NE(result, ERR_IO_PENDING);
392 DCHECK(stream_request_);
393
xunjieli3b6ac702016-06-06 21:36:28394 NotifyFailed(result);
xunjieli11834f02015-12-22 04:27:08395}
396
397void BidirectionalStream::OnNeedsProxyAuth(
398 const HttpResponseInfo& proxy_response,
399 const SSLConfig& used_ssl_config,
400 const ProxyInfo& used_proxy_info,
401 HttpAuthController* auth_controller) {
402 DCHECK(stream_request_);
403
xunjieli3b6ac702016-06-06 21:36:28404 NotifyFailed(ERR_PROXY_AUTH_REQUESTED);
xunjieli11834f02015-12-22 04:27:08405}
406
407void BidirectionalStream::OnNeedsClientAuth(const SSLConfig& used_ssl_config,
408 SSLCertRequestInfo* cert_info) {
409 DCHECK(stream_request_);
410
Helen Li43e3bee2018-03-21 16:57:11411 // BidirectionalStream doesn't support client auth. It ignores client auth
412 // requests with null client cert and key.
413 SSLConfig ssl_config = used_ssl_config;
414 ssl_config.send_client_cert = true;
415 ssl_config.client_cert = nullptr;
416 ssl_config.client_private_key = nullptr;
417 session_->ssl_client_auth_cache()->Add(cert_info->host_and_port, nullptr,
418 nullptr);
419 stream_request_ = nullptr;
420 StartRequest(ssl_config);
xunjieli11834f02015-12-22 04:27:08421}
422
423void BidirectionalStream::OnHttpsProxyTunnelResponse(
424 const HttpResponseInfo& response_info,
425 const SSLConfig& used_ssl_config,
426 const ProxyInfo& used_proxy_info,
Bence Béky6d05ebd2017-05-16 00:09:01427 std::unique_ptr<HttpStream> stream) {
xunjieli11834f02015-12-22 04:27:08428 DCHECK(stream_request_);
429
xunjieli3b6ac702016-06-06 21:36:28430 NotifyFailed(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
xunjieli11834f02015-12-22 04:27:08431}
432
433void BidirectionalStream::OnQuicBroken() {}
434
xunjieli3b6ac702016-06-06 21:36:28435void BidirectionalStream::NotifyFailed(int error) {
436 delegate_->OnFailed(error);
437}
438
xunjielid58621f2016-08-12 18:33:00439void BidirectionalStream::UpdateHistograms() {
440 // If the request failed before response is started, treat the metrics as
441 // bogus and skip logging.
xunjieli369d0922016-09-23 18:45:06442 if (load_timing_info_.request_start.is_null() ||
443 load_timing_info_.receive_headers_end.is_null() ||
444 read_end_time_.is_null() || load_timing_info_.send_start.is_null() ||
445 load_timing_info_.send_end.is_null()) {
xunjielid58621f2016-08-12 18:33:00446 return;
447 }
448 if (GetProtocol() == kProtoHTTP2) {
xunjielieef1d9c2016-09-02 22:00:58449 UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadStart.HTTP2",
xunjieli369d0922016-09-23 18:45:06450 load_timing_info_.receive_headers_end -
451 load_timing_info_.request_start);
xunjielieef1d9c2016-09-02 22:00:58452 UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadEnd.HTTP2",
xunjieli369d0922016-09-23 18:45:06453 read_end_time_ - load_timing_info_.request_start);
454 UMA_HISTOGRAM_TIMES(
455 "Net.BidirectionalStream.TimeToSendStart.HTTP2",
456 load_timing_info_.send_start - load_timing_info_.request_start);
457 UMA_HISTOGRAM_TIMES(
458 "Net.BidirectionalStream.TimeToSendEnd.HTTP2",
459 load_timing_info_.send_end - load_timing_info_.request_start);
Steven Holte6143e642017-06-28 19:47:38460 UMA_HISTOGRAM_COUNTS_1M("Net.BidirectionalStream.ReceivedBytes.HTTP2",
461 stream_impl_->GetTotalReceivedBytes());
462 UMA_HISTOGRAM_COUNTS_1M("Net.BidirectionalStream.SentBytes.HTTP2",
463 stream_impl_->GetTotalSentBytes());
bnc401eb922016-10-21 16:49:35464 } else if (GetProtocol() == kProtoQUIC) {
xunjielieef1d9c2016-09-02 22:00:58465 UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadStart.QUIC",
xunjieli369d0922016-09-23 18:45:06466 load_timing_info_.receive_headers_end -
467 load_timing_info_.request_start);
xunjielieef1d9c2016-09-02 22:00:58468 UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadEnd.QUIC",
xunjieli369d0922016-09-23 18:45:06469 read_end_time_ - load_timing_info_.request_start);
470 UMA_HISTOGRAM_TIMES(
471 "Net.BidirectionalStream.TimeToSendStart.QUIC",
472 load_timing_info_.send_start - load_timing_info_.request_start);
473 UMA_HISTOGRAM_TIMES(
474 "Net.BidirectionalStream.TimeToSendEnd.QUIC",
475 load_timing_info_.send_end - load_timing_info_.request_start);
Steven Holte6143e642017-06-28 19:47:38476 UMA_HISTOGRAM_COUNTS_1M("Net.BidirectionalStream.ReceivedBytes.QUIC",
477 stream_impl_->GetTotalReceivedBytes());
478 UMA_HISTOGRAM_COUNTS_1M("Net.BidirectionalStream.SentBytes.QUIC",
479 stream_impl_->GetTotalSentBytes());
xunjielid58621f2016-08-12 18:33:00480 }
481}
482
xunjieli11834f02015-12-22 04:27:08483} // namespace net