blob: 3d7f3b51cbf6c8ade4dc0bd9f1c20edb7a62bdde [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"
Eric Roman06bd9742019-07-13 15:19:1327#include "net/log/net_log_values.h"
Bence Béky94658bf2018-05-11 19:22:5828#include "net/spdy/spdy_http_utils.h"
29#include "net/spdy/spdy_log_util.h"
xunjieli11834f02015-12-22 04:27:0830#include "net/ssl/ssl_cert_request_info.h"
31#include "net/ssl/ssl_config.h"
Ryan Hamiltonea4fa192022-04-12 18:30:4932#include "net/third_party/quiche/src/quiche/spdy/core/spdy_header_block.h"
Ramin Halavati3c96c6d2018-03-11 13:29:4433#include "net/traffic_annotation/network_traffic_annotation.h"
xunjieli11834f02015-12-22 04:27:0834#include "url/gurl.h"
35
36namespace net {
37
xunjielid4c21ab2016-04-28 22:44:4738namespace {
39
Bence Béky4c325e52020-10-22 20:48:0140base::Value NetLogHeadersParams(const spdy::Http2HeaderBlock* headers,
Eric Roman06bd9742019-07-13 15:19:1341 NetLogCaptureMode capture_mode) {
Matt Menkec9a0b382022-05-27 22:31:4742 base::Value::Dict dict;
43 dict.Set("headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode));
44 return base::Value(std::move(dict));
xunjielid4c21ab2016-04-28 22:44:4745}
46
Eric Roman06bd9742019-07-13 15:19:1347base::Value NetLogParams(const GURL& url,
48 const std::string& method,
49 const HttpRequestHeaders* headers,
50 NetLogCaptureMode capture_mode) {
Matt Menkec9a0b382022-05-27 22:31:4751 base::Value::Dict dict;
52 dict.Set("url", url.possibly_invalid_spec());
53 dict.Set("method", method);
54 base::Value headers_param(
55 headers->NetLogParams(/*request_line=*/std::string(), capture_mode));
56 dict.Set("headers", std::move(headers_param));
57 return base::Value(std::move(dict));
xunjielid4c21ab2016-04-28 22:44:4758}
59
60} // namespace
61
Chris Watkins7a41d3552017-12-01 02:13:2762BidirectionalStream::Delegate::Delegate() = default;
xunjieli11834f02015-12-22 04:27:0863
Chris Watkins7a41d3552017-12-01 02:13:2764BidirectionalStream::Delegate::~Delegate() = default;
xunjieli11834f02015-12-22 04:27:0865
66BidirectionalStream::BidirectionalStream(
danakj1fd259a02016-04-16 03:17:0967 std::unique_ptr<BidirectionalStreamRequestInfo> request_info,
xunjieli11834f02015-12-22 04:27:0868 HttpNetworkSession* session,
xunjielibcb0f86e2016-06-03 00:49:2969 bool send_request_headers_automatically,
xunjieli11834f02015-12-22 04:27:0870 Delegate* delegate)
71 : BidirectionalStream(std::move(request_info),
72 session,
xunjielibcb0f86e2016-06-03 00:49:2973 send_request_headers_automatically,
xunjieli11834f02015-12-22 04:27:0874 delegate,
tzik08d8d6e2018-07-09 04:11:4775 std::make_unique<base::OneShotTimer>()) {}
xunjieli11834f02015-12-22 04:27:0876
77BidirectionalStream::BidirectionalStream(
danakj1fd259a02016-04-16 03:17:0978 std::unique_ptr<BidirectionalStreamRequestInfo> request_info,
xunjieli11834f02015-12-22 04:27:0879 HttpNetworkSession* session,
xunjielibcb0f86e2016-06-03 00:49:2980 bool send_request_headers_automatically,
xunjieli11834f02015-12-22 04:27:0881 Delegate* delegate,
tzik08d8d6e2018-07-09 04:11:4782 std::unique_ptr<base::OneShotTimer> timer)
xunjieli11834f02015-12-22 04:27:0883 : request_info_(std::move(request_info)),
tfarina42834112016-09-22 13:38:2084 net_log_(NetLogWithSource::Make(session->net_log(),
85 NetLogSourceType::BIDIRECTIONAL_STREAM)),
xunjielib3a648e2016-03-22 03:39:5186 session_(session),
xunjielibcb0f86e2016-06-03 00:49:2987 send_request_headers_automatically_(send_request_headers_automatically),
88 request_headers_sent_(false),
xunjieli11834f02015-12-22 04:27:0889 delegate_(delegate),
Jeremy Romand54000b22019-07-08 18:40:1690 timer_(std::move(timer)) {
xunjieli11834f02015-12-22 04:27:0891 DCHECK(delegate_);
92 DCHECK(request_info_);
93
xunjieli369d0922016-09-23 18:45:0694 // Start time should be measured before connect.
95 load_timing_info_.request_start_time = base::Time::Now();
96 load_timing_info_.request_start = base::TimeTicks::Now();
97
xunjielif88028e2016-06-01 19:27:1498 if (net_log_.IsCapturing()) {
Eric Roman06bd9742019-07-13 15:19:1399 net_log_.BeginEvent(NetLogEventType::BIDIRECTIONAL_STREAM_ALIVE,
100 [&](NetLogCaptureMode capture_mode) {
101 return NetLogParams(
102 request_info_->url, request_info_->method,
103 &request_info_->extra_headers, capture_mode);
104 });
xunjielif88028e2016-06-01 19:27:14105 }
106
xunjieli11834f02015-12-22 04:27:08107 if (!request_info_->url.SchemeIs(url::kHttpsScheme)) {
108 base::ThreadTaskRunnerHandle::Get()->PostTask(
109 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49110 base::BindOnce(&BidirectionalStream::NotifyFailed,
111 weak_factory_.GetWeakPtr(), ERR_DISALLOWED_URL_SCHEME));
xunjieli11834f02015-12-22 04:27:08112 return;
113 }
114
David Benjamin830c58c32022-01-19 22:23:23115 StartRequest(SSLConfig());
xunjieli11834f02015-12-22 04:27:08116}
117
118BidirectionalStream::~BidirectionalStream() {
xunjielid4c21ab2016-04-28 22:44:47119 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00120 net_log_.EndEvent(NetLogEventType::BIDIRECTIONAL_STREAM_ALIVE);
xunjielid4c21ab2016-04-28 22:44:47121 }
xunjieli11834f02015-12-22 04:27:08122}
123
xunjielibcb0f86e2016-06-03 00:49:29124void BidirectionalStream::SendRequestHeaders() {
125 DCHECK(stream_impl_);
126 DCHECK(!request_headers_sent_);
127 DCHECK(!send_request_headers_automatically_);
128
129 stream_impl_->SendRequestHeaders();
130}
131
xunjieli11834f02015-12-22 04:27:08132int BidirectionalStream::ReadData(IOBuffer* buf, int buf_len) {
xunjieli5749218c2016-03-22 16:43:06133 DCHECK(stream_impl_);
xunjieli11834f02015-12-22 04:27:08134
xunjielibe07785e2016-04-14 21:15:29135 int rv = stream_impl_->ReadData(buf, buf_len);
136 if (rv > 0) {
xunjielid58621f2016-08-12 18:33:00137 read_end_time_ = base::TimeTicks::Now();
xunjielibe07785e2016-04-14 21:15:29138 net_log_.AddByteTransferEvent(
mikecirone8b85c432016-09-08 19:11:00139 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_RECEIVED, rv, buf->data());
xunjielibe07785e2016-04-14 21:15:29140 } else if (rv == ERR_IO_PENDING) {
141 read_buffer_ = buf;
142 // Bytes will be logged in OnDataRead().
143 }
xunjielie1780482016-07-01 21:22:54144 if (net_log_.IsCapturing()) {
Eric Roman06bd9742019-07-13 15:19:13145 net_log_.AddEventWithIntParams(
146 NetLogEventType::BIDIRECTIONAL_STREAM_READ_DATA, "rv", rv);
xunjielie1780482016-07-01 21:22:54147 }
xunjielibe07785e2016-04-14 21:15:29148 return rv;
xunjieli11834f02015-12-22 04:27:08149}
150
xunjieli2328a2682016-05-16 19:38:25151void BidirectionalStream::SendvData(
152 const std::vector<scoped_refptr<IOBuffer>>& buffers,
153 const std::vector<int>& lengths,
154 bool end_stream) {
xunjieli07a42ce2016-04-26 20:05:31155 DCHECK(stream_impl_);
156 DCHECK_EQ(buffers.size(), lengths.size());
157 DCHECK(write_buffer_list_.empty());
158 DCHECK(write_buffer_len_list_.empty());
159
xunjielie1780482016-07-01 21:22:54160 if (net_log_.IsCapturing()) {
Eric Roman06bd9742019-07-13 15:19:13161 net_log_.AddEventWithIntParams(
162 NetLogEventType::BIDIRECTIONAL_STREAM_SENDV_DATA, "num_buffers",
163 buffers.size());
xunjielie1780482016-07-01 21:22:54164 }
xunjieli07a42ce2016-04-26 20:05:31165 stream_impl_->SendvData(buffers, lengths, end_stream);
166 for (size_t i = 0; i < buffers.size(); ++i) {
167 write_buffer_list_.push_back(buffers[i]);
168 write_buffer_len_list_.push_back(lengths[i]);
169 }
xunjieli11834f02015-12-22 04:27:08170}
171
xunjieli11834f02015-12-22 04:27:08172NextProto BidirectionalStream::GetProtocol() const {
xunjieli5749218c2016-03-22 16:43:06173 if (!stream_impl_)
xunjieli11834f02015-12-22 04:27:08174 return kProtoUnknown;
175
xunjieli5749218c2016-03-22 16:43:06176 return stream_impl_->GetProtocol();
xunjieli11834f02015-12-22 04:27:08177}
178
179int64_t BidirectionalStream::GetTotalReceivedBytes() const {
xunjieli5749218c2016-03-22 16:43:06180 if (!stream_impl_)
xunjieli11834f02015-12-22 04:27:08181 return 0;
182
xunjieli5749218c2016-03-22 16:43:06183 return stream_impl_->GetTotalReceivedBytes();
xunjieli11834f02015-12-22 04:27:08184}
185
186int64_t BidirectionalStream::GetTotalSentBytes() const {
xunjieli5749218c2016-03-22 16:43:06187 if (!stream_impl_)
xunjieli11834f02015-12-22 04:27:08188 return 0;
189
xunjieli5749218c2016-03-22 16:43:06190 return stream_impl_->GetTotalSentBytes();
xunjieli11834f02015-12-22 04:27:08191}
192
xunjieli369d0922016-09-23 18:45:06193void BidirectionalStream::GetLoadTimingInfo(
194 LoadTimingInfo* load_timing_info) const {
195 *load_timing_info = load_timing_info_;
196}
197
Brad Lassey5f488db42017-07-19 00:30:46198void BidirectionalStream::PopulateNetErrorDetails(NetErrorDetails* details) {
199 DCHECK(details);
200 if (stream_impl_)
201 stream_impl_->PopulateNetErrorDetails(details);
202}
203
Helen Li43e3bee2018-03-21 16:57:11204void BidirectionalStream::StartRequest(const SSLConfig& ssl_config) {
205 DCHECK(!stream_request_);
206 HttpRequestInfo http_request_info;
207 http_request_info.url = request_info_->url;
208 http_request_info.method = request_info_->method;
209 http_request_info.extra_headers = request_info_->extra_headers;
210 http_request_info.socket_tag = request_info_->socket_tag;
211 stream_request_ =
212 session_->http_stream_factory()->RequestBidirectionalStreamImpl(
213 http_request_info, request_info_->priority, ssl_config, ssl_config,
214 this,
215 /* enable_ip_based_pooling = */ true,
216 /* enable_alternative_services = */ true, net_log_);
217 // Check that this call does not fail.
218 DCHECK(stream_request_);
219 // Check that HttpStreamFactory does not invoke OnBidirectionalStreamImplReady
220 // synchronously.
221 DCHECK(!stream_impl_);
222}
223
xunjielibcb0f86e2016-06-03 00:49:29224void BidirectionalStream::OnStreamReady(bool request_headers_sent) {
225 request_headers_sent_ = request_headers_sent;
xunjieli2704f5d2016-06-10 16:02:23226 if (net_log_.IsCapturing()) {
Eric Roman06bd9742019-07-13 15:19:13227 net_log_.AddEntryWithBoolParams(
228 NetLogEventType::BIDIRECTIONAL_STREAM_READY, NetLogEventPhase::NONE,
229 "request_headers_sent", request_headers_sent);
xunjieli2704f5d2016-06-10 16:02:23230 }
xunjieli369d0922016-09-23 18:45:06231 load_timing_info_.send_start = base::TimeTicks::Now();
232 load_timing_info_.send_end = load_timing_info_.send_start;
xunjielibcb0f86e2016-06-03 00:49:29233 delegate_->OnStreamReady(request_headers_sent);
xunjieli11834f02015-12-22 04:27:08234}
235
236void BidirectionalStream::OnHeadersReceived(
Bence Béky4c325e52020-10-22 20:48:01237 const spdy::Http2HeaderBlock& response_headers) {
xunjielib3a648e2016-03-22 03:39:51238 HttpResponseInfo response_info;
Kenichi Ishibashie3708df2022-02-26 00:55:40239 if (SpdyHeadersToHttpResponse(response_headers, &response_info) != OK) {
xunjielib3a648e2016-03-22 03:39:51240 DLOG(WARNING) << "Invalid headers";
xunjieli3b6ac702016-06-06 21:36:28241 NotifyFailed(ERR_FAILED);
xunjielib3a648e2016-03-22 03:39:51242 return;
243 }
xunjielid4c21ab2016-04-28 22:44:47244 if (net_log_.IsCapturing()) {
mikecirone8b85c432016-09-08 19:11:00245 net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_RECV_HEADERS,
Eric Roman06bd9742019-07-13 15:19:13246 [&](NetLogCaptureMode capture_mode) {
247 return NetLogHeadersParams(&response_headers,
248 capture_mode);
249 });
xunjielid4c21ab2016-04-28 22:44:47250 }
xunjieli369d0922016-09-23 18:45:06251 // Impl should only provide |connect_timing| and |socket_reused| info,
252 // so use a copy to get these information only.
253 LoadTimingInfo impl_load_timing_info;
254 bool has_load_timing =
255 stream_impl_->GetLoadTimingInfo(&impl_load_timing_info);
256 if (has_load_timing) {
257 load_timing_info_.connect_timing = impl_load_timing_info.connect_timing;
258 load_timing_info_.socket_reused = impl_load_timing_info.socket_reused;
259 }
260 load_timing_info_.receive_headers_end = base::TimeTicks::Now();
261 read_end_time_ = load_timing_info_.receive_headers_end;
xunjielib3a648e2016-03-22 03:39:51262 session_->http_stream_factory()->ProcessAlternativeServices(
Matt Menke3233d8f22019-08-20 21:01:49263 session_, net::NetworkIsolationKey(), response_info.headers.get(),
zhongyi3d4a55e72016-04-22 20:36:46264 url::SchemeHostPort(request_info_->url));
xunjieli11834f02015-12-22 04:27:08265 delegate_->OnHeadersReceived(response_headers);
266}
267
268void BidirectionalStream::OnDataRead(int bytes_read) {
xunjielibe07785e2016-04-14 21:15:29269 DCHECK(read_buffer_);
270
xunjielid4c21ab2016-04-28 22:44:47271 if (net_log_.IsCapturing()) {
272 net_log_.AddByteTransferEvent(
mikecirone8b85c432016-09-08 19:11:00273 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_RECEIVED, bytes_read,
xunjielid4c21ab2016-04-28 22:44:47274 read_buffer_->data());
275 }
xunjielid58621f2016-08-12 18:33:00276 read_end_time_ = base::TimeTicks::Now();
xunjielibe07785e2016-04-14 21:15:29277 read_buffer_ = nullptr;
xunjieli11834f02015-12-22 04:27:08278 delegate_->OnDataRead(bytes_read);
279}
280
281void BidirectionalStream::OnDataSent() {
xunjieli07a42ce2016-04-26 20:05:31282 DCHECK(!write_buffer_list_.empty());
283 DCHECK_EQ(write_buffer_list_.size(), write_buffer_len_list_.size());
xunjielibe07785e2016-04-14 21:15:29284
xunjielid4c21ab2016-04-28 22:44:47285 if (net_log_.IsCapturing()) {
xunjieli2704f5d2016-06-10 16:02:23286 if (write_buffer_list_.size() > 1) {
287 net_log_.BeginEvent(
Eric Roman06bd9742019-07-13 15:19:13288 NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT_COALESCED, [&] {
289 return NetLogParamsWithInt("num_buffers_coalesced",
290 write_buffer_list_.size());
291 });
xunjieli2704f5d2016-06-10 16:02:23292 }
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(
Bence Béky4c325e52020-10-22 20:48:01310 const spdy::Http2HeaderBlock& 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,
Eric Roman06bd9742019-07-13 15:19:13313 [&](NetLogCaptureMode capture_mode) {
314 return NetLogHeadersParams(&trailers, capture_mode);
315 });
xunjielid4c21ab2016-04-28 22:44:47316 }
xunjielid58621f2016-08-12 18:33:00317 read_end_time_ = base::TimeTicks::Now();
xunjieli11834f02015-12-22 04:27:08318 delegate_->OnTrailersReceived(trailers);
319}
320
321void BidirectionalStream::OnFailed(int status) {
xunjieli2704f5d2016-06-10 16:02:23322 if (net_log_.IsCapturing()) {
Eric Roman06bd9742019-07-13 15:19:13323 net_log_.AddEventWithIntParams(NetLogEventType::BIDIRECTIONAL_STREAM_FAILED,
324 "net_error", status);
xunjieli2704f5d2016-06-10 16:02:23325 }
xunjieli3b6ac702016-06-06 21:36:28326 NotifyFailed(status);
xunjieli11834f02015-12-22 04:27:08327}
328
329void BidirectionalStream::OnStreamReady(const SSLConfig& used_ssl_config,
330 const ProxyInfo& used_proxy_info,
bnc5029f4632017-06-08 16:19:00331 std::unique_ptr<HttpStream> stream) {
xunjieli11834f02015-12-22 04:27:08332 NOTREACHED();
333}
334
xunjieli5749218c2016-03-22 16:43:06335void BidirectionalStream::OnBidirectionalStreamImplReady(
xunjieli11834f02015-12-22 04:27:08336 const SSLConfig& used_ssl_config,
337 const ProxyInfo& used_proxy_info,
bnc5029f4632017-06-08 16:19:00338 std::unique_ptr<BidirectionalStreamImpl> stream) {
xunjieli5749218c2016-03-22 16:43:06339 DCHECK(!stream_impl_);
xunjieli11834f02015-12-22 04:27:08340
Ramin Halavati3c96c6d2018-03-11 13:29:44341 net::NetworkTrafficAnnotationTag traffic_annotation =
342 net::DefineNetworkTrafficAnnotation("bidirectional_stream", R"(
343 semantics {
344 sender: "Bidirectional Stream"
345 description:
346 "Bidirectional stream is used to exchange data with a server on "
347 "behalf of an RPC API."
348 trigger:
349 "When an application makes an RPC to the server."
350 data:
351 "Any arbitrary data."
352 destination: OTHER
353 destination_other:
354 "Any destination that the application chooses."
355 }
356 policy {
357 cookies_allowed: NO
358 setting: "This feature is not used in Chrome."
359 policy_exception_justification:
360 "This feature is not used in Chrome."
361 }
362 )");
363
xunjieli11834f02015-12-22 04:27:08364 stream_request_.reset();
bnc5029f4632017-06-08 16:19:00365 stream_impl_ = std::move(stream);
xunjielibcb0f86e2016-06-03 00:49:29366 stream_impl_->Start(request_info_.get(), net_log_,
367 send_request_headers_automatically_, this,
Ramin Halavati3c96c6d2018-03-11 13:29:44368 std::move(timer_), traffic_annotation);
xunjieli11834f02015-12-22 04:27:08369}
370
371void BidirectionalStream::OnWebSocketHandshakeStreamReady(
372 const SSLConfig& used_ssl_config,
373 const ProxyInfo& used_proxy_info,
bnc5029f4632017-06-08 16:19:00374 std::unique_ptr<WebSocketHandshakeStreamBase> stream) {
xunjieli11834f02015-12-22 04:27:08375 NOTREACHED();
376}
377
Ryan Hamilton75f197262017-08-17 14:00:07378void BidirectionalStream::OnStreamFailed(
379 int result,
380 const NetErrorDetails& net_error_details,
Wojciech Dzierżanowskiabdeeaf2019-04-01 20:16:22381 const SSLConfig& used_ssl_config,
dalyk6d7a8c52019-12-18 21:43:01382 const ProxyInfo& used_proxy_info,
383 ResolveErrorInfo resolve_error_info) {
xunjieli11834f02015-12-22 04:27:08384 DCHECK_LT(result, 0);
385 DCHECK_NE(result, ERR_IO_PENDING);
386 DCHECK(stream_request_);
387
xunjieli3b6ac702016-06-06 21:36:28388 NotifyFailed(result);
xunjieli11834f02015-12-22 04:27:08389}
390
391void BidirectionalStream::OnCertificateError(int result,
392 const SSLConfig& used_ssl_config,
393 const SSLInfo& ssl_info) {
394 DCHECK_LT(result, 0);
395 DCHECK_NE(result, ERR_IO_PENDING);
396 DCHECK(stream_request_);
397
xunjieli3b6ac702016-06-06 21:36:28398 NotifyFailed(result);
xunjieli11834f02015-12-22 04:27:08399}
400
401void BidirectionalStream::OnNeedsProxyAuth(
402 const HttpResponseInfo& proxy_response,
403 const SSLConfig& used_ssl_config,
404 const ProxyInfo& used_proxy_info,
405 HttpAuthController* auth_controller) {
406 DCHECK(stream_request_);
407
xunjieli3b6ac702016-06-06 21:36:28408 NotifyFailed(ERR_PROXY_AUTH_REQUESTED);
xunjieli11834f02015-12-22 04:27:08409}
410
411void BidirectionalStream::OnNeedsClientAuth(const SSLConfig& used_ssl_config,
412 SSLCertRequestInfo* cert_info) {
413 DCHECK(stream_request_);
414
Helen Li43e3bee2018-03-21 16:57:11415 // BidirectionalStream doesn't support client auth. It ignores client auth
416 // requests with null client cert and key.
417 SSLConfig ssl_config = used_ssl_config;
David Benjaminbac8dff2019-08-07 01:30:41418 session_->ssl_client_context()->SetClientCertificate(cert_info->host_and_port,
419 nullptr, nullptr);
Helen Li43e3bee2018-03-21 16:57:11420 stream_request_ = nullptr;
421 StartRequest(ssl_config);
xunjieli11834f02015-12-22 04:27:08422}
423
xunjieli11834f02015-12-22 04:27:08424void BidirectionalStream::OnQuicBroken() {}
425
xunjieli3b6ac702016-06-06 21:36:28426void BidirectionalStream::NotifyFailed(int error) {
427 delegate_->OnFailed(error);
428}
429
xunjieli11834f02015-12-22 04:27:08430} // namespace net