| 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/chromium/bidirectional_stream_quic_impl.h" | 5 #include "net/quic/chromium/bidirectional_stream_quic_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 13 #include "base/timer/timer.h" | 13 #include "base/timer/timer.h" |
| 14 #include "net/http/bidirectional_stream_request_info.h" | 14 #include "net/http/bidirectional_stream_request_info.h" |
| 15 #include "net/quic/core/quic_connection.h" | 15 #include "net/quic/core/quic_connection.h" |
| 16 #include "net/quic/platform/api/quic_string_piece.h" | 16 #include "net/quic/platform/api/quic_string_piece.h" |
| 17 #include "net/socket/next_proto.h" | 17 #include "net/socket/next_proto.h" |
| 18 #include "net/spdy/chromium/spdy_http_utils.h" | 18 #include "net/spdy/chromium/spdy_http_utils.h" |
| 19 #include "net/spdy/core/spdy_header_block.h" | 19 #include "net/spdy/core/spdy_header_block.h" |
| 20 | 20 |
| 21 namespace net { | 21 namespace net { |
| 22 | 22 |
| 23 BidirectionalStreamQuicImpl::BidirectionalStreamQuicImpl( | 23 BidirectionalStreamQuicImpl::BidirectionalStreamQuicImpl( |
| 24 const base::WeakPtr<QuicChromiumClientSession>& session) | 24 std::unique_ptr<QuicChromiumClientSession::Handle> session) |
| 25 : session_(session), | 25 : session_(std::move(session)), |
| 26 was_handshake_confirmed_(session->IsCryptoHandshakeConfirmed()), | |
| 27 stream_(nullptr), | 26 stream_(nullptr), |
| 28 request_info_(nullptr), | 27 request_info_(nullptr), |
| 29 delegate_(nullptr), | 28 delegate_(nullptr), |
| 30 response_status_(OK), | 29 response_status_(OK), |
| 31 negotiated_protocol_(kProtoUnknown), | 30 negotiated_protocol_(kProtoUnknown), |
| 32 read_buffer_len_(0), | 31 read_buffer_len_(0), |
| 33 headers_bytes_received_(0), | 32 headers_bytes_received_(0), |
| 34 headers_bytes_sent_(0), | 33 headers_bytes_sent_(0), |
| 35 closed_stream_received_bytes_(0), | 34 closed_stream_received_bytes_(0), |
| 36 closed_stream_sent_bytes_(0), | 35 closed_stream_sent_bytes_(0), |
| 37 closed_is_first_stream_(false), | 36 closed_is_first_stream_(false), |
| 38 has_sent_headers_(false), | 37 has_sent_headers_(false), |
| 39 has_received_headers_(false), | 38 has_received_headers_(false), |
| 40 send_request_headers_automatically_(true), | 39 send_request_headers_automatically_(true), |
| 41 weak_factory_(this) { | 40 weak_factory_(this) {} |
| 42 DCHECK(session_); | |
| 43 session_->AddObserver(this); | |
| 44 } | |
| 45 | 41 |
| 46 BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() { | 42 BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() { |
| 47 if (stream_) { | 43 if (stream_) { |
| 48 delegate_ = nullptr; | 44 delegate_ = nullptr; |
| 49 stream_->Reset(QUIC_STREAM_CANCELLED); | 45 stream_->Reset(QUIC_STREAM_CANCELLED); |
| 50 } | 46 } |
| 51 | |
| 52 if (session_) | |
| 53 session_->RemoveObserver(this); | |
| 54 } | 47 } |
| 55 | 48 |
| 56 void BidirectionalStreamQuicImpl::Start( | 49 void BidirectionalStreamQuicImpl::Start( |
| 57 const BidirectionalStreamRequestInfo* request_info, | 50 const BidirectionalStreamRequestInfo* request_info, |
| 58 const NetLogWithSource& net_log, | 51 const NetLogWithSource& net_log, |
| 59 bool send_request_headers_automatically, | 52 bool send_request_headers_automatically, |
| 60 BidirectionalStreamImpl::Delegate* delegate, | 53 BidirectionalStreamImpl::Delegate* delegate, |
| 61 std::unique_ptr<base::Timer> /* timer */) { | 54 std::unique_ptr<base::Timer> /* timer */) { |
| 62 DCHECK(!stream_); | 55 DCHECK(!stream_); |
| 63 CHECK(delegate); | 56 CHECK(delegate); |
| 64 | 57 |
| 65 send_request_headers_automatically_ = send_request_headers_automatically; | 58 send_request_headers_automatically_ = send_request_headers_automatically; |
| 66 if (!session_) { | 59 if (!session_->IsConnected()) { |
| 67 NotifyError(was_handshake_confirmed_ ? ERR_QUIC_PROTOCOL_ERROR | 60 NotifyError(session_->IsCryptoHandshakeConfirmed() |
| 68 : ERR_QUIC_HANDSHAKE_FAILED); | 61 ? ERR_QUIC_PROTOCOL_ERROR |
| 62 : ERR_QUIC_HANDSHAKE_FAILED); |
| 69 return; | 63 return; |
| 70 } | 64 } |
| 71 | 65 |
| 72 delegate_ = delegate; | 66 delegate_ = delegate; |
| 73 request_info_ = request_info; | 67 request_info_ = request_info; |
| 74 | 68 |
| 75 stream_request_ = | 69 int rv = session_->RequestStream( |
| 76 session_->CreateStreamRequest(request_info_->method == "POST"); | 70 request_info_->method == "POST", |
| 77 int rv = stream_request_->StartRequest(base::Bind( | 71 base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady, |
| 78 &BidirectionalStreamQuicImpl::OnStreamReady, weak_factory_.GetWeakPtr())); | 72 weak_factory_.GetWeakPtr())); |
| 79 if (rv == ERR_IO_PENDING) | 73 if (rv == ERR_IO_PENDING) |
| 80 return; | 74 return; |
| 81 | 75 |
| 82 if (rv == OK) { | 76 if (rv == OK) { |
| 83 OnStreamReady(rv); | 77 OnStreamReady(rv); |
| 84 } else if (!was_handshake_confirmed_) { | 78 } else if (!session_->IsCryptoHandshakeConfirmed()) { |
| 85 NotifyError(ERR_QUIC_HANDSHAKE_FAILED); | 79 NotifyError(ERR_QUIC_HANDSHAKE_FAILED); |
| 86 } | 80 } |
| 87 } | 81 } |
| 88 | 82 |
| 89 void BidirectionalStreamQuicImpl::SendRequestHeaders() { | 83 void BidirectionalStreamQuicImpl::SendRequestHeaders() { |
| 90 DCHECK(!has_sent_headers_); | 84 DCHECK(!has_sent_headers_); |
| 91 if (!stream_) { | 85 if (!stream_) { |
| 92 LOG(ERROR) | 86 LOG(ERROR) |
| 93 << "Trying to send request headers after stream has been destroyed."; | 87 << "Trying to send request headers after stream has been destroyed."; |
| 94 base::ThreadTaskRunnerHandle::Get()->PostTask( | 88 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | 139 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 146 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | 140 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| 147 return; | 141 return; |
| 148 } | 142 } |
| 149 | 143 |
| 150 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; | 144 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; |
| 151 if (!has_sent_headers_) { | 145 if (!has_sent_headers_) { |
| 152 DCHECK(!send_request_headers_automatically_); | 146 DCHECK(!send_request_headers_automatically_); |
| 153 // Creates a bundler only if there are headers to be sent along with the | 147 // Creates a bundler only if there are headers to be sent along with the |
| 154 // single data buffer. | 148 // single data buffer. |
| 155 bundler.reset(new QuicConnection::ScopedPacketBundler( | 149 bundler = |
| 156 session_->connection(), QuicConnection::SEND_ACK_IF_PENDING)); | 150 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING); |
| 157 SendRequestHeaders(); | 151 SendRequestHeaders(); |
| 158 } | 152 } |
| 159 | 153 |
| 160 QuicStringPiece string_data(data->data(), length); | 154 QuicStringPiece string_data(data->data(), length); |
| 161 int rv = stream_->WriteStreamData( | 155 int rv = stream_->WriteStreamData( |
| 162 string_data, end_stream, | 156 string_data, end_stream, |
| 163 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 157 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 164 weak_factory_.GetWeakPtr())); | 158 weak_factory_.GetWeakPtr())); |
| 165 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 159 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 166 if (rv == OK) { | 160 if (rv == OK) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 177 DCHECK_EQ(buffers.size(), lengths.size()); | 171 DCHECK_EQ(buffers.size(), lengths.size()); |
| 178 | 172 |
| 179 if (!stream_) { | 173 if (!stream_) { |
| 180 LOG(ERROR) << "Trying to send data after stream has been destroyed."; | 174 LOG(ERROR) << "Trying to send data after stream has been destroyed."; |
| 181 base::ThreadTaskRunnerHandle::Get()->PostTask( | 175 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 182 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | 176 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 183 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | 177 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| 184 return; | 178 return; |
| 185 } | 179 } |
| 186 | 180 |
| 187 QuicConnection::ScopedPacketBundler bundler( | 181 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( |
| 188 session_->connection(), QuicConnection::SEND_ACK_IF_PENDING); | 182 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); |
| 189 if (!has_sent_headers_) { | 183 if (!has_sent_headers_) { |
| 190 DCHECK(!send_request_headers_automatically_); | 184 DCHECK(!send_request_headers_automatically_); |
| 191 SendRequestHeaders(); | 185 SendRequestHeaders(); |
| 192 } | 186 } |
| 193 | 187 |
| 194 int rv = stream_->WritevStreamData( | 188 int rv = stream_->WritevStreamData( |
| 195 buffers, lengths, end_stream, | 189 buffers, lengths, end_stream, |
| 196 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 190 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 197 weak_factory_.GetWeakPtr())); | 191 weak_factory_.GetWeakPtr())); |
| 198 | 192 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 // Spurrious notification. Wait for the next one. | 255 // Spurrious notification. Wait for the next one. |
| 262 return; | 256 return; |
| 263 } | 257 } |
| 264 read_buffer_ = nullptr; | 258 read_buffer_ = nullptr; |
| 265 read_buffer_len_ = 0; | 259 read_buffer_len_ = 0; |
| 266 if (delegate_) | 260 if (delegate_) |
| 267 delegate_->OnDataRead(rv); | 261 delegate_->OnDataRead(rv); |
| 268 } | 262 } |
| 269 | 263 |
| 270 void BidirectionalStreamQuicImpl::OnClose() { | 264 void BidirectionalStreamQuicImpl::OnClose() { |
| 271 DCHECK(session_); | |
| 272 DCHECK(stream_); | 265 DCHECK(stream_); |
| 273 | 266 |
| 274 if (stream_->connection_error() != QUIC_NO_ERROR || | 267 if (stream_->connection_error() != QUIC_NO_ERROR || |
| 275 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { | 268 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { |
| 276 NotifyError(was_handshake_confirmed_ ? ERR_QUIC_PROTOCOL_ERROR | 269 NotifyError(session_->IsCryptoHandshakeConfirmed() |
| 277 : ERR_QUIC_HANDSHAKE_FAILED); | 270 ? ERR_QUIC_PROTOCOL_ERROR |
| 271 : ERR_QUIC_HANDSHAKE_FAILED); |
| 278 return; | 272 return; |
| 279 } | 273 } |
| 280 | 274 |
| 281 if (!stream_->fin_sent() || !stream_->fin_received()) { | 275 if (!stream_->fin_sent() || !stream_->fin_received()) { |
| 282 // The connection must have been closed by the peer with QUIC_NO_ERROR, | 276 // The connection must have been closed by the peer with QUIC_NO_ERROR, |
| 283 // which is improper. | 277 // which is improper. |
| 284 NotifyError(ERR_UNEXPECTED); | 278 NotifyError(ERR_UNEXPECTED); |
| 285 return; | 279 return; |
| 286 } | 280 } |
| 287 | 281 |
| 288 // The connection was closed normally so there is no need to notify | 282 // The connection was closed normally so there is no need to notify |
| 289 // the delegate. | 283 // the delegate. |
| 290 ResetStream(); | 284 ResetStream(); |
| 291 } | 285 } |
| 292 | 286 |
| 293 void BidirectionalStreamQuicImpl::OnError(int error) { | 287 void BidirectionalStreamQuicImpl::OnError(int error) { |
| 294 NotifyError(error); | 288 NotifyError(error); |
| 295 } | 289 } |
| 296 | 290 |
| 297 void BidirectionalStreamQuicImpl::OnCryptoHandshakeConfirmed() { | |
| 298 was_handshake_confirmed_ = true; | |
| 299 } | |
| 300 | |
| 301 void BidirectionalStreamQuicImpl::OnSuccessfulVersionNegotiation( | |
| 302 const QuicVersion& version) {} | |
| 303 | |
| 304 void BidirectionalStreamQuicImpl::OnSessionClosed( | |
| 305 int error, | |
| 306 bool /*port_migration_detected*/) { | |
| 307 DCHECK_NE(OK, error); | |
| 308 session_.reset(); | |
| 309 NotifyError(error); | |
| 310 } | |
| 311 | |
| 312 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { | 291 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| 313 DCHECK_NE(ERR_IO_PENDING, rv); | 292 DCHECK_NE(ERR_IO_PENDING, rv); |
| 314 DCHECK(rv == OK || !stream_); | 293 DCHECK(rv == OK || !stream_); |
| 315 if (rv == OK) { | 294 if (rv == OK) { |
| 316 stream_ = stream_request_->ReleaseStream(); | 295 stream_ = session_->ReleaseStream(); |
| 317 stream_request_.reset(); | |
| 318 stream_->SetDelegate(this); | 296 stream_->SetDelegate(this); |
| 319 NotifyStreamReady(); | 297 NotifyStreamReady(); |
| 320 } else { | 298 } else { |
| 321 NotifyError(rv); | 299 NotifyError(rv); |
| 322 } | 300 } |
| 323 } | 301 } |
| 324 | 302 |
| 325 void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { | 303 void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { |
| 326 DCHECK(rv == OK || !stream_); | 304 DCHECK(rv == OK || !stream_); |
| 327 if (rv == OK) { | 305 if (rv == OK) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 350 | 328 |
| 351 void BidirectionalStreamQuicImpl::NotifyStreamReady() { | 329 void BidirectionalStreamQuicImpl::NotifyStreamReady() { |
| 352 if (send_request_headers_automatically_) { | 330 if (send_request_headers_automatically_) { |
| 353 SendRequestHeaders(); | 331 SendRequestHeaders(); |
| 354 } | 332 } |
| 355 if (delegate_) | 333 if (delegate_) |
| 356 delegate_->OnStreamReady(has_sent_headers_); | 334 delegate_->OnStreamReady(has_sent_headers_); |
| 357 } | 335 } |
| 358 | 336 |
| 359 void BidirectionalStreamQuicImpl::ResetStream() { | 337 void BidirectionalStreamQuicImpl::ResetStream() { |
| 360 if (session_) { | |
| 361 session_->RemoveObserver(this); | |
| 362 session_ = nullptr; | |
| 363 } | |
| 364 | |
| 365 if (!stream_) | 338 if (!stream_) |
| 366 return; | 339 return; |
| 367 closed_stream_received_bytes_ = stream_->stream_bytes_read(); | 340 closed_stream_received_bytes_ = stream_->stream_bytes_read(); |
| 368 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); | 341 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); |
| 369 closed_is_first_stream_ = stream_->IsFirstStream(); | 342 closed_is_first_stream_ = stream_->IsFirstStream(); |
| 370 stream_->SetDelegate(nullptr); | 343 stream_->SetDelegate(nullptr); |
| 371 stream_ = nullptr; | 344 stream_ = nullptr; |
| 372 } | 345 } |
| 373 | 346 |
| 374 } // namespace net | 347 } // namespace net |
| OLD | NEW |