| 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" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 session_->IsCryptoHandshakeConfirmed() | 74 session_->IsCryptoHandshakeConfirmed() |
| 75 ? rv | 75 ? rv |
| 76 : ERR_QUIC_HANDSHAKE_FAILED)); | 76 : ERR_QUIC_HANDSHAKE_FAILED)); |
| 77 return; | 77 return; |
| 78 } | 78 } |
| 79 | 79 |
| 80 OnStreamReady(rv); | 80 OnStreamReady(rv); |
| 81 } | 81 } |
| 82 | 82 |
| 83 void BidirectionalStreamQuicImpl::SendRequestHeaders() { | 83 void BidirectionalStreamQuicImpl::SendRequestHeaders() { |
| 84 WriteHeaders(); |
| 85 } |
| 86 |
| 87 bool BidirectionalStreamQuicImpl::WriteHeaders() { |
| 84 DCHECK(!has_sent_headers_); | 88 DCHECK(!has_sent_headers_); |
| 85 if (!stream_) { | 89 if (!stream_) { |
| 86 LOG(ERROR) | 90 LOG(ERROR) |
| 87 << "Trying to send request headers after stream has been destroyed."; | 91 << "Trying to send request headers after stream has been destroyed."; |
| 88 base::ThreadTaskRunnerHandle::Get()->PostTask( | 92 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 89 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | 93 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 90 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | 94 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| 91 return; | 95 return false; |
| 92 } | 96 } |
| 93 | 97 |
| 94 SpdyHeaderBlock headers; | 98 SpdyHeaderBlock headers; |
| 95 HttpRequestInfo http_request_info; | 99 HttpRequestInfo http_request_info; |
| 96 http_request_info.url = request_info_->url; | 100 http_request_info.url = request_info_->url; |
| 97 http_request_info.method = request_info_->method; | 101 http_request_info.method = request_info_->method; |
| 98 http_request_info.extra_headers = request_info_->extra_headers; | 102 http_request_info.extra_headers = request_info_->extra_headers; |
| 99 | 103 |
| 100 CreateSpdyHeadersFromHttpRequest( | 104 CreateSpdyHeadersFromHttpRequest( |
| 101 http_request_info, http_request_info.extra_headers, true, &headers); | 105 http_request_info, http_request_info.extra_headers, true, &headers); |
| 102 // Sending the request might result in |this| being deleted. | 106 // Sending the request might result in the stream being closed via OnClose |
| 103 auto guard = weak_factory_.GetWeakPtr(); | 107 // which will post a task to notify the delegate asynchronously. |
| 108 // TODO(rch): Clean up this interface when OnClose and OnError are removed. |
| 104 size_t headers_bytes_sent = stream_->WriteHeaders( | 109 size_t headers_bytes_sent = stream_->WriteHeaders( |
| 105 std::move(headers), request_info_->end_stream_on_headers, nullptr); | 110 std::move(headers), request_info_->end_stream_on_headers, nullptr); |
| 106 if (!guard.get()) | 111 if (!stream_) |
| 107 return; | 112 return false; |
| 113 |
| 108 headers_bytes_sent_ += headers_bytes_sent; | 114 headers_bytes_sent_ += headers_bytes_sent; |
| 109 has_sent_headers_ = true; | 115 has_sent_headers_ = true; |
| 116 return true; |
| 110 } | 117 } |
| 111 | 118 |
| 112 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { | 119 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| 113 DCHECK(buffer); | 120 DCHECK(buffer); |
| 114 DCHECK(buffer_len); | 121 DCHECK(buffer_len); |
| 115 | 122 |
| 116 if (!stream_) { | 123 if (!stream_) { |
| 117 // If the stream is already closed, there is no body to read. | 124 // If the stream is already closed, there is no body to read. |
| 118 return response_status_; | 125 return response_status_; |
| 119 } | 126 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 150 return; | 157 return; |
| 151 } | 158 } |
| 152 | 159 |
| 153 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; | 160 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; |
| 154 if (!has_sent_headers_) { | 161 if (!has_sent_headers_) { |
| 155 DCHECK(!send_request_headers_automatically_); | 162 DCHECK(!send_request_headers_automatically_); |
| 156 // Creates a bundler only if there are headers to be sent along with the | 163 // Creates a bundler only if there are headers to be sent along with the |
| 157 // single data buffer. | 164 // single data buffer. |
| 158 bundler = | 165 bundler = |
| 159 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING); | 166 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING); |
| 160 SendRequestHeaders(); | 167 // Sending the request might result in the stream being closed. |
| 168 if (!WriteHeaders()) |
| 169 return; |
| 161 } | 170 } |
| 162 | 171 |
| 163 QuicStringPiece string_data(data->data(), length); | 172 QuicStringPiece string_data(data->data(), length); |
| 164 int rv = stream_->WriteStreamData( | 173 int rv = stream_->WriteStreamData( |
| 165 string_data, end_stream, | 174 string_data, end_stream, |
| 166 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 175 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 167 weak_factory_.GetWeakPtr())); | 176 weak_factory_.GetWeakPtr())); |
| 168 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 177 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 169 if (rv == OK) { | 178 if (rv == OK) { |
| 170 base::ThreadTaskRunnerHandle::Get()->PostTask( | 179 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 184 base::ThreadTaskRunnerHandle::Get()->PostTask( | 193 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 185 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | 194 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 186 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | 195 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| 187 return; | 196 return; |
| 188 } | 197 } |
| 189 | 198 |
| 190 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( | 199 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( |
| 191 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); | 200 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); |
| 192 if (!has_sent_headers_) { | 201 if (!has_sent_headers_) { |
| 193 DCHECK(!send_request_headers_automatically_); | 202 DCHECK(!send_request_headers_automatically_); |
| 194 SendRequestHeaders(); | 203 // Sending the request might result in the stream being closed. |
| 204 if (!WriteHeaders()) |
| 205 return; |
| 195 } | 206 } |
| 196 | 207 |
| 197 int rv = stream_->WritevStreamData( | 208 int rv = stream_->WritevStreamData( |
| 198 buffers, lengths, end_stream, | 209 buffers, lengths, end_stream, |
| 199 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 210 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 200 weak_factory_.GetWeakPtr())); | 211 weak_factory_.GetWeakPtr())); |
| 201 | 212 |
| 202 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 213 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 203 if (rv == OK) { | 214 if (rv == OK) { |
| 204 base::ThreadTaskRunnerHandle::Get()->PostTask( | 215 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| (...skipping 30 matching lines...) Expand all Loading... |
| 235 load_timing_info->socket_reused = true; | 246 load_timing_info->socket_reused = true; |
| 236 } | 247 } |
| 237 return true; | 248 return true; |
| 238 } | 249 } |
| 239 | 250 |
| 240 void BidirectionalStreamQuicImpl::OnClose() { | 251 void BidirectionalStreamQuicImpl::OnClose() { |
| 241 DCHECK(stream_); | 252 DCHECK(stream_); |
| 242 | 253 |
| 243 if (stream_->connection_error() != QUIC_NO_ERROR || | 254 if (stream_->connection_error() != QUIC_NO_ERROR || |
| 244 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { | 255 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { |
| 245 NotifyError(session_->IsCryptoHandshakeConfirmed() | 256 OnError(session_->IsCryptoHandshakeConfirmed() ? ERR_QUIC_PROTOCOL_ERROR |
| 246 ? ERR_QUIC_PROTOCOL_ERROR | 257 : ERR_QUIC_HANDSHAKE_FAILED); |
| 247 : ERR_QUIC_HANDSHAKE_FAILED); | |
| 248 return; | 258 return; |
| 249 } | 259 } |
| 250 | 260 |
| 251 if (!stream_->fin_sent() || !stream_->fin_received()) { | 261 if (!stream_->fin_sent() || !stream_->fin_received()) { |
| 252 // The connection must have been closed by the peer with QUIC_NO_ERROR, | 262 // The connection must have been closed by the peer with QUIC_NO_ERROR, |
| 253 // which is improper. | 263 // which is improper. |
| 254 NotifyError(ERR_UNEXPECTED); | 264 OnError(ERR_UNEXPECTED); |
| 255 return; | 265 return; |
| 256 } | 266 } |
| 257 | 267 |
| 258 // The connection was closed normally so there is no need to notify | 268 // The connection was closed normally so there is no need to notify |
| 259 // the delegate. | 269 // the delegate. |
| 260 ResetStream(); | 270 ResetStream(); |
| 261 } | 271 } |
| 262 | 272 |
| 263 void BidirectionalStreamQuicImpl::OnError(int error) { | 273 void BidirectionalStreamQuicImpl::OnError(int error) { |
| 264 NotifyError(error); | 274 // Avoid reentrancy by notifying the delegate asynchronously. |
| 275 NotifyErrorImpl(error, /*notify_delegate_later*/ true); |
| 265 } | 276 } |
| 266 | 277 |
| 267 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { | 278 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| 268 DCHECK_NE(ERR_IO_PENDING, rv); | 279 DCHECK_NE(ERR_IO_PENDING, rv); |
| 269 DCHECK(rv == OK || !stream_); | 280 DCHECK(rv == OK || !stream_); |
| 270 if (rv != OK) { | 281 if (rv != OK) { |
| 271 NotifyError(rv); | 282 NotifyError(rv); |
| 272 return; | 283 return; |
| 273 } | 284 } |
| 274 | 285 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 // If the write side is closed, OnFinRead() will call | 362 // If the write side is closed, OnFinRead() will call |
| 352 // BidirectionalStreamQuicImpl::OnClose(). | 363 // BidirectionalStreamQuicImpl::OnClose(). |
| 353 stream_->OnFinRead(); | 364 stream_->OnFinRead(); |
| 354 } | 365 } |
| 355 | 366 |
| 356 if (delegate_) | 367 if (delegate_) |
| 357 delegate_->OnDataRead(rv); | 368 delegate_->OnDataRead(rv); |
| 358 } | 369 } |
| 359 | 370 |
| 360 void BidirectionalStreamQuicImpl::NotifyError(int error) { | 371 void BidirectionalStreamQuicImpl::NotifyError(int error) { |
| 372 NotifyErrorImpl(error, /*notify_delegate_later*/ false); |
| 373 } |
| 374 |
| 375 void BidirectionalStreamQuicImpl::NotifyErrorImpl(int error, |
| 376 bool notify_delegate_later) { |
| 361 DCHECK_NE(OK, error); | 377 DCHECK_NE(OK, error); |
| 362 DCHECK_NE(ERR_IO_PENDING, error); | 378 DCHECK_NE(ERR_IO_PENDING, error); |
| 363 | 379 |
| 364 ResetStream(); | 380 ResetStream(); |
| 365 if (delegate_) { | 381 if (delegate_) { |
| 366 response_status_ = error; | 382 response_status_ = error; |
| 367 BidirectionalStreamImpl::Delegate* delegate = delegate_; | 383 BidirectionalStreamImpl::Delegate* delegate = delegate_; |
| 368 delegate_ = nullptr; | 384 delegate_ = nullptr; |
| 369 // Cancel any pending callback. | 385 // Cancel any pending callback. |
| 370 weak_factory_.InvalidateWeakPtrs(); | 386 weak_factory_.InvalidateWeakPtrs(); |
| 371 delegate->OnFailed(error); | 387 if (notify_delegate_later) { |
| 372 // |this| might be destroyed at this point. | 388 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 389 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyFailure, |
| 390 weak_factory_.GetWeakPtr(), delegate, error)); |
| 391 } else { |
| 392 NotifyFailure(delegate, error); |
| 393 // |this| might be destroyed at this point. |
| 394 } |
| 373 } | 395 } |
| 374 } | 396 } |
| 375 | 397 |
| 398 void BidirectionalStreamQuicImpl::NotifyFailure( |
| 399 BidirectionalStreamImpl::Delegate* delegate, |
| 400 int error) { |
| 401 delegate->OnFailed(error); |
| 402 // |this| might be destroyed at this point. |
| 403 } |
| 404 |
| 376 void BidirectionalStreamQuicImpl::NotifyStreamReady() { | 405 void BidirectionalStreamQuicImpl::NotifyStreamReady() { |
| 377 if (send_request_headers_automatically_) { | 406 // Sending the request might result in the stream being closed. |
| 378 // Sending the request might result in |this| being deleted. | 407 if (send_request_headers_automatically_ && !WriteHeaders()) |
| 379 auto guard = weak_factory_.GetWeakPtr(); | 408 return; |
| 380 SendRequestHeaders(); | 409 |
| 381 if (!guard.get()) | |
| 382 return; | |
| 383 } | |
| 384 if (delegate_) | 410 if (delegate_) |
| 385 delegate_->OnStreamReady(has_sent_headers_); | 411 delegate_->OnStreamReady(has_sent_headers_); |
| 386 } | 412 } |
| 387 | 413 |
| 388 void BidirectionalStreamQuicImpl::ResetStream() { | 414 void BidirectionalStreamQuicImpl::ResetStream() { |
| 389 if (!stream_) | 415 if (!stream_) |
| 390 return; | 416 return; |
| 391 closed_stream_received_bytes_ = stream_->stream_bytes_read(); | 417 closed_stream_received_bytes_ = stream_->stream_bytes_read(); |
| 392 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); | 418 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); |
| 393 closed_is_first_stream_ = stream_->IsFirstStream(); | 419 closed_is_first_stream_ = stream_->IsFirstStream(); |
| 394 stream_->ClearDelegate(); | 420 stream_->ClearDelegate(); |
| 395 stream_ = nullptr; | 421 stream_ = nullptr; |
| 396 } | 422 } |
| 397 | 423 |
| 398 } // namespace net | 424 } // namespace net |
| OLD | NEW |