xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 1 | // 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 | |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 7 | #include <string> |
Bence Béky | 6d05ebd | 2017-05-16 00:09:01 | [diff] [blame] | 8 | #include <utility> |
danakj | 1fd259a0 | 2016-04-16 03:17:09 | [diff] [blame] | 9 | |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 10 | #include "base/bind.h" |
| 11 | #include "base/location.h" |
| 12 | #include "base/logging.h" |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 13 | #include "base/metrics/histogram_macros.h" |
gab | f767595f | 2016-05-11 18:50:35 | [diff] [blame] | 14 | #include "base/threading/thread_task_runner_handle.h" |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 15 | #include "base/timer/timer.h" |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 16 | #include "base/values.h" |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 17 | #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" |
xunjieli | b3a648e | 2016-03-22 03:39:51 | [diff] [blame] | 21 | #include "net/http/http_response_headers.h" |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 22 | #include "net/http/http_stream.h" |
mikecirone | f22f981 | 2016-10-04 03:40:19 | [diff] [blame] | 23 | #include "net/log/net_log.h" |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 24 | #include "net/log/net_log_capture_mode.h" |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 25 | #include "net/log/net_log_event_type.h" |
| 26 | #include "net/log/net_log_source_type.h" |
Bence Béky | 94658bf | 2018-05-11 19:22:58 | [diff] [blame] | 27 | #include "net/spdy/spdy_http_utils.h" |
| 28 | #include "net/spdy/spdy_log_util.h" |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 29 | #include "net/ssl/ssl_cert_request_info.h" |
| 30 | #include "net/ssl/ssl_config.h" |
Ryan Hamilton | 2e003eea | 2018-05-02 00:24:29 | [diff] [blame] | 31 | #include "net/third_party/spdy/core/spdy_header_block.h" |
Ramin Halavati | 3c96c6d | 2018-03-11 13:29:44 | [diff] [blame] | 32 | #include "net/traffic_annotation/network_traffic_annotation.h" |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 33 | #include "url/gurl.h" |
| 34 | |
| 35 | namespace net { |
| 36 | |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 37 | namespace { |
| 38 | |
| 39 | std::unique_ptr<base::Value> NetLogHeadersCallback( |
Ryan Hamilton | 0239aac | 2018-05-19 00:03:13 | [diff] [blame] | 40 | const spdy::SpdyHeaderBlock* headers, |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 41 | NetLogCaptureMode capture_mode) { |
Jeremy Roman | 0579ed6 | 2017-08-29 15:56:19 | [diff] [blame] | 42 | auto dict = std::make_unique<base::DictionaryValue>(); |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 43 | dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); |
| 44 | return std::move(dict); |
| 45 | } |
| 46 | |
| 47 | std::unique_ptr<base::Value> NetLogCallback(const GURL* url, |
| 48 | const std::string* method, |
| 49 | const HttpRequestHeaders* headers, |
| 50 | NetLogCaptureMode capture_mode) { |
Jeremy Roman | 0579ed6 | 2017-08-29 15:56:19 | [diff] [blame] | 51 | auto dict = std::make_unique<base::DictionaryValue>(); |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 52 | 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 Watkins | 7a41d355 | 2017-12-01 02:13:27 | [diff] [blame] | 63 | BidirectionalStream::Delegate::Delegate() = default; |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 64 | |
Chris Watkins | 7a41d355 | 2017-12-01 02:13:27 | [diff] [blame] | 65 | BidirectionalStream::Delegate::~Delegate() = default; |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 66 | |
| 67 | BidirectionalStream::BidirectionalStream( |
danakj | 1fd259a0 | 2016-04-16 03:17:09 | [diff] [blame] | 68 | std::unique_ptr<BidirectionalStreamRequestInfo> request_info, |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 69 | HttpNetworkSession* session, |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 70 | bool send_request_headers_automatically, |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 71 | Delegate* delegate) |
| 72 | : BidirectionalStream(std::move(request_info), |
| 73 | session, |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 74 | send_request_headers_automatically, |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 75 | delegate, |
Jeremy Roman | 0579ed6 | 2017-08-29 15:56:19 | [diff] [blame] | 76 | std::make_unique<base::Timer>(false, false)) {} |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 77 | |
| 78 | BidirectionalStream::BidirectionalStream( |
danakj | 1fd259a0 | 2016-04-16 03:17:09 | [diff] [blame] | 79 | std::unique_ptr<BidirectionalStreamRequestInfo> request_info, |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 80 | HttpNetworkSession* session, |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 81 | bool send_request_headers_automatically, |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 82 | Delegate* delegate, |
danakj | 1fd259a0 | 2016-04-16 03:17:09 | [diff] [blame] | 83 | std::unique_ptr<base::Timer> timer) |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 84 | : request_info_(std::move(request_info)), |
tfarina | 42834111 | 2016-09-22 13:38:20 | [diff] [blame] | 85 | net_log_(NetLogWithSource::Make(session->net_log(), |
| 86 | NetLogSourceType::BIDIRECTIONAL_STREAM)), |
xunjieli | b3a648e | 2016-03-22 03:39:51 | [diff] [blame] | 87 | session_(session), |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 88 | send_request_headers_automatically_(send_request_headers_automatically), |
| 89 | request_headers_sent_(false), |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 90 | delegate_(delegate), |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 91 | timer_(std::move(timer)), |
| 92 | weak_factory_(this) { |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 93 | DCHECK(delegate_); |
| 94 | DCHECK(request_info_); |
| 95 | |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 96 | // 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 | |
xunjieli | f88028e | 2016-06-01 19:27:14 | [diff] [blame] | 100 | if (net_log_.IsCapturing()) { |
| 101 | net_log_.BeginEvent( |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 102 | NetLogEventType::BIDIRECTIONAL_STREAM_ALIVE, |
xunjieli | f88028e | 2016-06-01 19:27:14 | [diff] [blame] | 103 | base::Bind(&NetLogCallback, &request_info_->url, &request_info_->method, |
| 104 | base::Unretained(&request_info_->extra_headers))); |
| 105 | } |
| 106 | |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 107 | if (!request_info_->url.SchemeIs(url::kHttpsScheme)) { |
| 108 | base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 109 | FROM_HERE, |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 110 | base::Bind(&BidirectionalStream::NotifyFailed, |
| 111 | weak_factory_.GetWeakPtr(), ERR_DISALLOWED_URL_SCHEME)); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 112 | return; |
| 113 | } |
| 114 | |
Helen Li | 43e3bee | 2018-03-21 16:57:11 | [diff] [blame] | 115 | SSLConfig ssl_config; |
| 116 | session->ssl_config_service()->GetSSLConfig(&ssl_config); |
| 117 | session->GetAlpnProtos(&ssl_config.alpn_protos); |
| 118 | |
| 119 | StartRequest(ssl_config); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | BidirectionalStream::~BidirectionalStream() { |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 123 | UpdateHistograms(); |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 124 | if (net_log_.IsCapturing()) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 125 | net_log_.EndEvent(NetLogEventType::BIDIRECTIONAL_STREAM_ALIVE); |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 126 | } |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 127 | } |
| 128 | |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 129 | void BidirectionalStream::SendRequestHeaders() { |
| 130 | DCHECK(stream_impl_); |
| 131 | DCHECK(!request_headers_sent_); |
| 132 | DCHECK(!send_request_headers_automatically_); |
| 133 | |
| 134 | stream_impl_->SendRequestHeaders(); |
| 135 | } |
| 136 | |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 137 | int BidirectionalStream::ReadData(IOBuffer* buf, int buf_len) { |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 138 | DCHECK(stream_impl_); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 139 | |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 140 | int rv = stream_impl_->ReadData(buf, buf_len); |
| 141 | if (rv > 0) { |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 142 | read_end_time_ = base::TimeTicks::Now(); |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 143 | net_log_.AddByteTransferEvent( |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 144 | NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_RECEIVED, rv, buf->data()); |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 145 | } else if (rv == ERR_IO_PENDING) { |
| 146 | read_buffer_ = buf; |
| 147 | // Bytes will be logged in OnDataRead(). |
| 148 | } |
xunjieli | e178048 | 2016-07-01 21:22:54 | [diff] [blame] | 149 | if (net_log_.IsCapturing()) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 150 | net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_READ_DATA, |
xunjieli | e178048 | 2016-07-01 21:22:54 | [diff] [blame] | 151 | NetLog::IntCallback("rv", rv)); |
| 152 | } |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 153 | return rv; |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 154 | } |
| 155 | |
xunjieli | 2328a268 | 2016-05-16 19:38:25 | [diff] [blame] | 156 | void BidirectionalStream::SendvData( |
| 157 | const std::vector<scoped_refptr<IOBuffer>>& buffers, |
| 158 | const std::vector<int>& lengths, |
| 159 | bool end_stream) { |
xunjieli | 07a42ce | 2016-04-26 20:05:31 | [diff] [blame] | 160 | DCHECK(stream_impl_); |
| 161 | DCHECK_EQ(buffers.size(), lengths.size()); |
| 162 | DCHECK(write_buffer_list_.empty()); |
| 163 | DCHECK(write_buffer_len_list_.empty()); |
| 164 | |
xunjieli | e178048 | 2016-07-01 21:22:54 | [diff] [blame] | 165 | if (net_log_.IsCapturing()) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 166 | net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_SENDV_DATA, |
xunjieli | e178048 | 2016-07-01 21:22:54 | [diff] [blame] | 167 | NetLog::IntCallback("num_buffers", buffers.size())); |
| 168 | } |
xunjieli | 07a42ce | 2016-04-26 20:05:31 | [diff] [blame] | 169 | 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 | } |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 174 | } |
| 175 | |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 176 | NextProto BidirectionalStream::GetProtocol() const { |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 177 | if (!stream_impl_) |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 178 | return kProtoUnknown; |
| 179 | |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 180 | return stream_impl_->GetProtocol(); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | int64_t BidirectionalStream::GetTotalReceivedBytes() const { |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 184 | if (!stream_impl_) |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 185 | return 0; |
| 186 | |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 187 | return stream_impl_->GetTotalReceivedBytes(); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | int64_t BidirectionalStream::GetTotalSentBytes() const { |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 191 | if (!stream_impl_) |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 192 | return 0; |
| 193 | |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 194 | return stream_impl_->GetTotalSentBytes(); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 195 | } |
| 196 | |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 197 | void BidirectionalStream::GetLoadTimingInfo( |
| 198 | LoadTimingInfo* load_timing_info) const { |
| 199 | *load_timing_info = load_timing_info_; |
| 200 | } |
| 201 | |
Brad Lassey | 5f488db4 | 2017-07-19 00:30:46 | [diff] [blame] | 202 | void BidirectionalStream::PopulateNetErrorDetails(NetErrorDetails* details) { |
| 203 | DCHECK(details); |
| 204 | if (stream_impl_) |
| 205 | stream_impl_->PopulateNetErrorDetails(details); |
| 206 | } |
| 207 | |
Helen Li | 43e3bee | 2018-03-21 16:57:11 | [diff] [blame] | 208 | void 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 | |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 228 | void BidirectionalStream::OnStreamReady(bool request_headers_sent) { |
| 229 | request_headers_sent_ = request_headers_sent; |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 230 | if (net_log_.IsCapturing()) { |
| 231 | net_log_.AddEvent( |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 232 | NetLogEventType::BIDIRECTIONAL_STREAM_READY, |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 233 | NetLog::BoolCallback("request_headers_sent", request_headers_sent)); |
| 234 | } |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 235 | load_timing_info_.send_start = base::TimeTicks::Now(); |
| 236 | load_timing_info_.send_end = load_timing_info_.send_start; |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 237 | delegate_->OnStreamReady(request_headers_sent); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 238 | } |
| 239 | |
| 240 | void BidirectionalStream::OnHeadersReceived( |
Ryan Hamilton | 0239aac | 2018-05-19 00:03:13 | [diff] [blame] | 241 | const spdy::SpdyHeaderBlock& response_headers) { |
xunjieli | b3a648e | 2016-03-22 03:39:51 | [diff] [blame] | 242 | HttpResponseInfo response_info; |
bnc | bca843ba | 2016-07-14 13:05:48 | [diff] [blame] | 243 | if (!SpdyHeadersToHttpResponse(response_headers, &response_info)) { |
xunjieli | b3a648e | 2016-03-22 03:39:51 | [diff] [blame] | 244 | DLOG(WARNING) << "Invalid headers"; |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 245 | NotifyFailed(ERR_FAILED); |
xunjieli | b3a648e | 2016-03-22 03:39:51 | [diff] [blame] | 246 | return; |
| 247 | } |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 248 | if (net_log_.IsCapturing()) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 249 | net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_RECV_HEADERS, |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 250 | base::Bind(&NetLogHeadersCallback, &response_headers)); |
| 251 | } |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 252 | // 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; |
xunjieli | b3a648e | 2016-03-22 03:39:51 | [diff] [blame] | 263 | session_->http_stream_factory()->ProcessAlternativeServices( |
| 264 | session_, response_info.headers.get(), |
zhongyi | 3d4a55e7 | 2016-04-22 20:36:46 | [diff] [blame] | 265 | url::SchemeHostPort(request_info_->url)); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 266 | delegate_->OnHeadersReceived(response_headers); |
| 267 | } |
| 268 | |
| 269 | void BidirectionalStream::OnDataRead(int bytes_read) { |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 270 | DCHECK(read_buffer_); |
| 271 | |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 272 | if (net_log_.IsCapturing()) { |
| 273 | net_log_.AddByteTransferEvent( |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 274 | NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_RECEIVED, bytes_read, |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 275 | read_buffer_->data()); |
| 276 | } |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 277 | read_end_time_ = base::TimeTicks::Now(); |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 278 | read_buffer_ = nullptr; |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 279 | delegate_->OnDataRead(bytes_read); |
| 280 | } |
| 281 | |
| 282 | void BidirectionalStream::OnDataSent() { |
xunjieli | 07a42ce | 2016-04-26 20:05:31 | [diff] [blame] | 283 | DCHECK(!write_buffer_list_.empty()); |
| 284 | DCHECK_EQ(write_buffer_list_.size(), write_buffer_len_list_.size()); |
xunjieli | be07785e | 2016-04-14 21:15:29 | [diff] [blame] | 285 | |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 286 | if (net_log_.IsCapturing()) { |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 287 | if (write_buffer_list_.size() > 1) { |
| 288 | net_log_.BeginEvent( |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 289 | NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT_COALESCED, |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 290 | NetLog::IntCallback("num_buffers_coalesced", |
| 291 | write_buffer_list_.size())); |
| 292 | } |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 293 | for (size_t i = 0; i < write_buffer_list_.size(); ++i) { |
| 294 | net_log_.AddByteTransferEvent( |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 295 | NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT, |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 296 | write_buffer_len_list_[i], write_buffer_list_[i]->data()); |
| 297 | } |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 298 | if (write_buffer_list_.size() > 1) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 299 | net_log_.EndEvent( |
| 300 | NetLogEventType::BIDIRECTIONAL_STREAM_BYTES_SENT_COALESCED); |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 301 | } |
xunjieli | 07a42ce | 2016-04-26 20:05:31 | [diff] [blame] | 302 | } |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 303 | load_timing_info_.send_end = base::TimeTicks::Now(); |
xunjieli | 07a42ce | 2016-04-26 20:05:31 | [diff] [blame] | 304 | write_buffer_list_.clear(); |
| 305 | write_buffer_len_list_.clear(); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 306 | delegate_->OnDataSent(); |
| 307 | } |
| 308 | |
Ryan Hamilton | 0239aac | 2018-05-19 00:03:13 | [diff] [blame] | 309 | void BidirectionalStream::OnTrailersReceived( |
| 310 | const spdy::SpdyHeaderBlock& trailers) { |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 311 | if (net_log_.IsCapturing()) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 312 | net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_RECV_TRAILERS, |
xunjieli | d4c21ab | 2016-04-28 22:44:47 | [diff] [blame] | 313 | base::Bind(&NetLogHeadersCallback, &trailers)); |
| 314 | } |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 315 | read_end_time_ = base::TimeTicks::Now(); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 316 | delegate_->OnTrailersReceived(trailers); |
| 317 | } |
| 318 | |
| 319 | void BidirectionalStream::OnFailed(int status) { |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 320 | if (net_log_.IsCapturing()) { |
mikecirone | 8b85c43 | 2016-09-08 19:11:00 | [diff] [blame] | 321 | net_log_.AddEvent(NetLogEventType::BIDIRECTIONAL_STREAM_FAILED, |
xunjieli | 2704f5d | 2016-06-10 16:02:23 | [diff] [blame] | 322 | NetLog::IntCallback("net_error", status)); |
| 323 | } |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 324 | NotifyFailed(status); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | void BidirectionalStream::OnStreamReady(const SSLConfig& used_ssl_config, |
| 328 | const ProxyInfo& used_proxy_info, |
bnc | 5029f463 | 2017-06-08 16:19:00 | [diff] [blame] | 329 | std::unique_ptr<HttpStream> stream) { |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 330 | NOTREACHED(); |
| 331 | } |
| 332 | |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 333 | void BidirectionalStream::OnBidirectionalStreamImplReady( |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 334 | const SSLConfig& used_ssl_config, |
| 335 | const ProxyInfo& used_proxy_info, |
bnc | 5029f463 | 2017-06-08 16:19:00 | [diff] [blame] | 336 | std::unique_ptr<BidirectionalStreamImpl> stream) { |
xunjieli | 5749218c | 2016-03-22 16:43:06 | [diff] [blame] | 337 | DCHECK(!stream_impl_); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 338 | |
Ramin Halavati | 3c96c6d | 2018-03-11 13:29:44 | [diff] [blame] | 339 | 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 | |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 362 | stream_request_.reset(); |
bnc | 5029f463 | 2017-06-08 16:19:00 | [diff] [blame] | 363 | stream_impl_ = std::move(stream); |
xunjieli | bcb0f86e | 2016-06-03 00:49:29 | [diff] [blame] | 364 | stream_impl_->Start(request_info_.get(), net_log_, |
| 365 | send_request_headers_automatically_, this, |
Ramin Halavati | 3c96c6d | 2018-03-11 13:29:44 | [diff] [blame] | 366 | std::move(timer_), traffic_annotation); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 367 | } |
| 368 | |
| 369 | void BidirectionalStream::OnWebSocketHandshakeStreamReady( |
| 370 | const SSLConfig& used_ssl_config, |
| 371 | const ProxyInfo& used_proxy_info, |
bnc | 5029f463 | 2017-06-08 16:19:00 | [diff] [blame] | 372 | std::unique_ptr<WebSocketHandshakeStreamBase> stream) { |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 373 | NOTREACHED(); |
| 374 | } |
| 375 | |
Ryan Hamilton | 75f19726 | 2017-08-17 14:00:07 | [diff] [blame] | 376 | void BidirectionalStream::OnStreamFailed( |
| 377 | int result, |
| 378 | const NetErrorDetails& net_error_details, |
| 379 | const SSLConfig& used_ssl_config) { |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 380 | DCHECK_LT(result, 0); |
| 381 | DCHECK_NE(result, ERR_IO_PENDING); |
| 382 | DCHECK(stream_request_); |
| 383 | |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 384 | NotifyFailed(result); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 385 | } |
| 386 | |
| 387 | void 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 | |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 394 | NotifyFailed(result); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 395 | } |
| 396 | |
| 397 | void 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 | |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 404 | NotifyFailed(ERR_PROXY_AUTH_REQUESTED); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 405 | } |
| 406 | |
| 407 | void BidirectionalStream::OnNeedsClientAuth(const SSLConfig& used_ssl_config, |
| 408 | SSLCertRequestInfo* cert_info) { |
| 409 | DCHECK(stream_request_); |
| 410 | |
Helen Li | 43e3bee | 2018-03-21 16:57:11 | [diff] [blame] | 411 | // 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); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 421 | } |
| 422 | |
| 423 | void BidirectionalStream::OnHttpsProxyTunnelResponse( |
| 424 | const HttpResponseInfo& response_info, |
| 425 | const SSLConfig& used_ssl_config, |
| 426 | const ProxyInfo& used_proxy_info, |
Bence Béky | 6d05ebd | 2017-05-16 00:09:01 | [diff] [blame] | 427 | std::unique_ptr<HttpStream> stream) { |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 428 | DCHECK(stream_request_); |
| 429 | |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 430 | NotifyFailed(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 431 | } |
| 432 | |
| 433 | void BidirectionalStream::OnQuicBroken() {} |
| 434 | |
xunjieli | 3b6ac70 | 2016-06-06 21:36:28 | [diff] [blame] | 435 | void BidirectionalStream::NotifyFailed(int error) { |
| 436 | delegate_->OnFailed(error); |
| 437 | } |
| 438 | |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 439 | void BidirectionalStream::UpdateHistograms() { |
| 440 | // If the request failed before response is started, treat the metrics as |
| 441 | // bogus and skip logging. |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 442 | 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()) { |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 446 | return; |
| 447 | } |
| 448 | if (GetProtocol() == kProtoHTTP2) { |
xunjieli | eef1d9c | 2016-09-02 22:00:58 | [diff] [blame] | 449 | UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadStart.HTTP2", |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 450 | load_timing_info_.receive_headers_end - |
| 451 | load_timing_info_.request_start); |
xunjieli | eef1d9c | 2016-09-02 22:00:58 | [diff] [blame] | 452 | UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadEnd.HTTP2", |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 453 | 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 Holte | 6143e64 | 2017-06-28 19:47:38 | [diff] [blame] | 460 | 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()); |
bnc | 401eb92 | 2016-10-21 16:49:35 | [diff] [blame] | 464 | } else if (GetProtocol() == kProtoQUIC) { |
xunjieli | eef1d9c | 2016-09-02 22:00:58 | [diff] [blame] | 465 | UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadStart.QUIC", |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 466 | load_timing_info_.receive_headers_end - |
| 467 | load_timing_info_.request_start); |
xunjieli | eef1d9c | 2016-09-02 22:00:58 | [diff] [blame] | 468 | UMA_HISTOGRAM_TIMES("Net.BidirectionalStream.TimeToReadEnd.QUIC", |
xunjieli | 369d092 | 2016-09-23 18:45:06 | [diff] [blame] | 469 | 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 Holte | 6143e64 | 2017-06-28 19:47:38 | [diff] [blame] | 476 | 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()); |
xunjieli | d58621f | 2016-08-12 18:33:00 | [diff] [blame] | 480 | } |
| 481 | } |
| 482 | |
xunjieli | 11834f0 | 2015-12-22 04:27:08 | [diff] [blame] | 483 | } // namespace net |