| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/bidirectional_stream_quic_impl.h" | 5 #include "net/quic/bidirectional_stream_quic_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/timer/timer.h" | 10 #include "base/timer/timer.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 delegate_(nullptr), | 25 delegate_(nullptr), |
| 26 response_status_(OK), | 26 response_status_(OK), |
| 27 negotiated_protocol_(kProtoUnknown), | 27 negotiated_protocol_(kProtoUnknown), |
| 28 read_buffer_len_(0), | 28 read_buffer_len_(0), |
| 29 headers_bytes_received_(0), | 29 headers_bytes_received_(0), |
| 30 headers_bytes_sent_(0), | 30 headers_bytes_sent_(0), |
| 31 closed_stream_received_bytes_(0), | 31 closed_stream_received_bytes_(0), |
| 32 closed_stream_sent_bytes_(0), | 32 closed_stream_sent_bytes_(0), |
| 33 has_sent_headers_(false), | 33 has_sent_headers_(false), |
| 34 has_received_headers_(false), | 34 has_received_headers_(false), |
| 35 disable_auto_flush_(false), | 35 send_request_headers_automatically_(true), |
| 36 weak_factory_(this) { | 36 weak_factory_(this) { |
| 37 DCHECK(session_); | 37 DCHECK(session_); |
| 38 session_->AddObserver(this); | 38 session_->AddObserver(this); |
| 39 } | 39 } |
| 40 | 40 |
| 41 BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() { | 41 BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() { |
| 42 Cancel(); | 42 Cancel(); |
| 43 if (session_) | 43 if (session_) |
| 44 session_->RemoveObserver(this); | 44 session_->RemoveObserver(this); |
| 45 } | 45 } |
| 46 | 46 |
| 47 void BidirectionalStreamQuicImpl::Start( | 47 void BidirectionalStreamQuicImpl::Start( |
| 48 const BidirectionalStreamRequestInfo* request_info, | 48 const BidirectionalStreamRequestInfo* request_info, |
| 49 const BoundNetLog& net_log, | 49 const BoundNetLog& net_log, |
| 50 bool disable_auto_flush, | 50 bool send_request_headers_automatically, |
| 51 BidirectionalStreamImpl::Delegate* delegate, | 51 BidirectionalStreamImpl::Delegate* delegate, |
| 52 std::unique_ptr<base::Timer> /* timer */) { | 52 std::unique_ptr<base::Timer> /* timer */) { |
| 53 DCHECK(!stream_); | 53 DCHECK(!stream_); |
| 54 | 54 |
| 55 disable_auto_flush_ = disable_auto_flush; | 55 send_request_headers_automatically_ = send_request_headers_automatically; |
| 56 if (!session_) { | 56 if (!session_) { |
| 57 NotifyError(was_handshake_confirmed_ ? ERR_QUIC_PROTOCOL_ERROR | 57 NotifyError(was_handshake_confirmed_ ? ERR_QUIC_PROTOCOL_ERROR |
| 58 : ERR_QUIC_HANDSHAKE_FAILED); | 58 : ERR_QUIC_HANDSHAKE_FAILED); |
| 59 return; | 59 return; |
| 60 } | 60 } |
| 61 | 61 |
| 62 delegate_ = delegate; | 62 delegate_ = delegate; |
| 63 request_info_ = request_info; | 63 request_info_ = request_info; |
| 64 | 64 |
| 65 int rv = stream_request_.StartRequest( | 65 int rv = stream_request_.StartRequest( |
| 66 session_, &stream_, | 66 session_, &stream_, |
| 67 base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady, | 67 base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady, |
| 68 weak_factory_.GetWeakPtr())); | 68 weak_factory_.GetWeakPtr())); |
| 69 if (rv == OK) { | 69 if (rv == OK) { |
| 70 OnStreamReady(rv); | 70 OnStreamReady(rv); |
| 71 } else if (!was_handshake_confirmed_) { | 71 } else if (!was_handshake_confirmed_) { |
| 72 NotifyError(ERR_QUIC_HANDSHAKE_FAILED); | 72 NotifyError(ERR_QUIC_HANDSHAKE_FAILED); |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 | 75 |
| 76 void BidirectionalStreamQuicImpl::SendRequestHeaders() { |
| 77 DCHECK(!has_sent_headers_); |
| 78 DCHECK(stream_); |
| 79 |
| 80 SpdyHeaderBlock headers; |
| 81 HttpRequestInfo http_request_info; |
| 82 http_request_info.url = request_info_->url; |
| 83 http_request_info.method = request_info_->method; |
| 84 http_request_info.extra_headers = request_info_->extra_headers; |
| 85 |
| 86 CreateSpdyHeadersFromHttpRequest(http_request_info, |
| 87 http_request_info.extra_headers, HTTP2, true, |
| 88 &headers); |
| 89 size_t headers_bytes_sent = stream_->WriteHeaders( |
| 90 headers, request_info_->end_stream_on_headers, nullptr); |
| 91 headers_bytes_sent_ += headers_bytes_sent; |
| 92 has_sent_headers_ = true; |
| 93 } |
| 94 |
| 76 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { | 95 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| 77 DCHECK(buffer); | 96 DCHECK(buffer); |
| 78 DCHECK(buffer_len); | 97 DCHECK(buffer_len); |
| 79 | 98 |
| 80 if (!stream_) { | 99 if (!stream_) { |
| 81 // If the stream is already closed, there is no body to read. | 100 // If the stream is already closed, there is no body to read. |
| 82 return response_status_; | 101 return response_status_; |
| 83 } | 102 } |
| 84 int rv = stream_->Read(buffer, buffer_len); | 103 int rv = stream_->Read(buffer, buffer_len); |
| 85 if (rv != ERR_IO_PENDING) { | 104 if (rv != ERR_IO_PENDING) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 96 read_buffer_len_ = buffer_len; | 115 read_buffer_len_ = buffer_len; |
| 97 return ERR_IO_PENDING; | 116 return ERR_IO_PENDING; |
| 98 } | 117 } |
| 99 | 118 |
| 100 void BidirectionalStreamQuicImpl::SendData(const scoped_refptr<IOBuffer>& data, | 119 void BidirectionalStreamQuicImpl::SendData(const scoped_refptr<IOBuffer>& data, |
| 101 int length, | 120 int length, |
| 102 bool end_stream) { | 121 bool end_stream) { |
| 103 DCHECK(stream_); | 122 DCHECK(stream_); |
| 104 DCHECK(length > 0 || (length == 0 && end_stream)); | 123 DCHECK(length > 0 || (length == 0 && end_stream)); |
| 105 | 124 |
| 125 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; |
| 126 if (!has_sent_headers_) { |
| 127 DCHECK(!send_request_headers_automatically_); |
| 128 // Creates a bundler only if there are headers to be sent along with the |
| 129 // single data buffer. |
| 130 bundler.reset(new QuicConnection::ScopedPacketBundler( |
| 131 session_->connection(), QuicConnection::SEND_ACK_IF_PENDING)); |
| 132 SendRequestHeaders(); |
| 133 } |
| 134 |
| 106 base::StringPiece string_data(data->data(), length); | 135 base::StringPiece string_data(data->data(), length); |
| 107 int rv = stream_->WriteStreamData( | 136 int rv = stream_->WriteStreamData( |
| 108 string_data, end_stream, | 137 string_data, end_stream, |
| 109 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 138 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 110 weak_factory_.GetWeakPtr())); | 139 weak_factory_.GetWeakPtr())); |
| 111 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 140 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 112 if (rv == OK) { | 141 if (rv == OK) { |
| 113 base::ThreadTaskRunnerHandle::Get()->PostTask( | 142 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 114 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 143 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 115 weak_factory_.GetWeakPtr(), OK)); | 144 weak_factory_.GetWeakPtr(), OK)); |
| 116 } | 145 } |
| 117 } | 146 } |
| 118 | 147 |
| 119 void BidirectionalStreamQuicImpl::SendvData( | 148 void BidirectionalStreamQuicImpl::SendvData( |
| 120 const std::vector<scoped_refptr<IOBuffer>>& buffers, | 149 const std::vector<scoped_refptr<IOBuffer>>& buffers, |
| 121 const std::vector<int>& lengths, | 150 const std::vector<int>& lengths, |
| 122 bool end_stream) { | 151 bool end_stream) { |
| 123 DCHECK(stream_); | 152 DCHECK(stream_); |
| 124 DCHECK_EQ(buffers.size(), lengths.size()); | 153 DCHECK_EQ(buffers.size(), lengths.size()); |
| 125 | 154 |
| 126 QuicConnection::ScopedPacketBundler bundler( | 155 QuicConnection::ScopedPacketBundler bundler( |
| 127 session_->connection(), QuicConnection::SEND_ACK_IF_PENDING); | 156 session_->connection(), QuicConnection::SEND_ACK_IF_PENDING); |
| 128 if (!has_sent_headers_) { | 157 if (!has_sent_headers_) { |
| 158 DCHECK(!send_request_headers_automatically_); |
| 129 SendRequestHeaders(); | 159 SendRequestHeaders(); |
| 130 } | 160 } |
| 131 | 161 |
| 132 int rv = stream_->WritevStreamData( | 162 int rv = stream_->WritevStreamData( |
| 133 buffers, lengths, end_stream, | 163 buffers, lengths, end_stream, |
| 134 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 164 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 135 weak_factory_.GetWeakPtr())); | 165 weak_factory_.GetWeakPtr())); |
| 136 | 166 |
| 137 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 167 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 138 if (rv == OK) { | 168 if (rv == OK) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 DCHECK_NE(OK, error); | 261 DCHECK_NE(OK, error); |
| 232 session_.reset(); | 262 session_.reset(); |
| 233 NotifyError(error); | 263 NotifyError(error); |
| 234 } | 264 } |
| 235 | 265 |
| 236 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { | 266 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| 237 DCHECK_NE(ERR_IO_PENDING, rv); | 267 DCHECK_NE(ERR_IO_PENDING, rv); |
| 238 DCHECK(rv == OK || !stream_); | 268 DCHECK(rv == OK || !stream_); |
| 239 if (rv == OK) { | 269 if (rv == OK) { |
| 240 stream_->SetDelegate(this); | 270 stream_->SetDelegate(this); |
| 241 if (!disable_auto_flush_) { | 271 if (send_request_headers_automatically_) { |
| 242 SendRequestHeaders(); | 272 SendRequestHeaders(); |
| 243 } | 273 } |
| 244 delegate_->OnStreamReady(); | 274 delegate_->OnStreamReady(has_sent_headers_); |
| 245 } else { | 275 } else { |
| 246 NotifyError(rv); | 276 NotifyError(rv); |
| 247 } | 277 } |
| 248 } | 278 } |
| 249 | 279 |
| 250 void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { | 280 void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { |
| 251 DCHECK(rv == OK || !stream_); | 281 DCHECK(rv == OK || !stream_); |
| 252 if (rv == OK) { | 282 if (rv == OK) { |
| 253 delegate_->OnDataSent(); | 283 delegate_->OnDataSent(); |
| 254 } else { | 284 } else { |
| 255 NotifyError(rv); | 285 NotifyError(rv); |
| 256 } | 286 } |
| 257 } | 287 } |
| 258 | 288 |
| 259 void BidirectionalStreamQuicImpl::SendRequestHeaders() { | |
| 260 DCHECK(!has_sent_headers_); | |
| 261 DCHECK(stream_); | |
| 262 | |
| 263 SpdyHeaderBlock headers; | |
| 264 HttpRequestInfo http_request_info; | |
| 265 http_request_info.url = request_info_->url; | |
| 266 http_request_info.method = request_info_->method; | |
| 267 http_request_info.extra_headers = request_info_->extra_headers; | |
| 268 | |
| 269 CreateSpdyHeadersFromHttpRequest(http_request_info, | |
| 270 http_request_info.extra_headers, HTTP2, true, | |
| 271 &headers); | |
| 272 size_t frame_len = stream_->WriteHeaders( | |
| 273 headers, request_info_->end_stream_on_headers, nullptr); | |
| 274 headers_bytes_sent_ += frame_len; | |
| 275 has_sent_headers_ = true; | |
| 276 } | |
| 277 | |
| 278 void BidirectionalStreamQuicImpl::NotifyError(int error) { | 289 void BidirectionalStreamQuicImpl::NotifyError(int error) { |
| 279 DCHECK_NE(OK, error); | 290 DCHECK_NE(OK, error); |
| 280 DCHECK_NE(ERR_IO_PENDING, error); | 291 DCHECK_NE(ERR_IO_PENDING, error); |
| 281 | 292 |
| 282 response_status_ = error; | 293 response_status_ = error; |
| 283 ResetStream(); | 294 ResetStream(); |
| 284 delegate_->OnFailed(error); | 295 delegate_->OnFailed(error); |
| 285 } | 296 } |
| 286 | 297 |
| 287 void BidirectionalStreamQuicImpl::ResetStream() { | 298 void BidirectionalStreamQuicImpl::ResetStream() { |
| 288 if (!stream_) | 299 if (!stream_) |
| 289 return; | 300 return; |
| 290 closed_stream_received_bytes_ = stream_->stream_bytes_read(); | 301 closed_stream_received_bytes_ = stream_->stream_bytes_read(); |
| 291 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); | 302 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); |
| 292 stream_->SetDelegate(nullptr); | 303 stream_->SetDelegate(nullptr); |
| 293 stream_ = nullptr; | 304 stream_ = nullptr; |
| 294 } | 305 } |
| 295 | 306 |
| 296 } // namespace net | 307 } // namespace net |
| OLD | NEW |