Chromium Code Reviews| Index: net/quic/chromium/bidirectional_stream_quic_impl.cc |
| diff --git a/net/quic/chromium/bidirectional_stream_quic_impl.cc b/net/quic/chromium/bidirectional_stream_quic_impl.cc |
| index b776e1ded53239f172364761f5f472877e9e4409..3198bd077cc4c50ac103bfda43838693f7068004 100644 |
| --- a/net/quic/chromium/bidirectional_stream_quic_impl.cc |
| +++ b/net/quic/chromium/bidirectional_stream_quic_impl.cc |
| @@ -44,6 +44,7 @@ BidirectionalStreamQuicImpl::BidirectionalStreamQuicImpl( |
| delegate_(nullptr), |
| response_status_(OK), |
| negotiated_protocol_(kProtoUnknown), |
| + expect_trailers_(true), |
| read_buffer_len_(0), |
| headers_bytes_received_(0), |
| headers_bytes_sent_(0), |
| @@ -102,21 +103,16 @@ void BidirectionalStreamQuicImpl::Start( |
| void BidirectionalStreamQuicImpl::SendRequestHeaders() { |
| ScopedBoolSaver saver(&may_invoke_callbacks_, false); |
| - // If this fails, a task will have been posted to notify the delegate |
| - // asynchronously. |
| - WriteHeaders(); |
| -} |
| - |
| -bool BidirectionalStreamQuicImpl::WriteHeaders() { |
| - DCHECK(!has_sent_headers_); |
| - if (!stream_) { |
| - LOG(ERROR) |
| - << "Trying to send request headers after stream has been destroyed."; |
| + int rv = WriteHeaders(); |
| + if (rv < 0) { |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| - weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| - return false; |
| + weak_factory_.GetWeakPtr(), rv)); |
| } |
| +} |
| + |
| +int BidirectionalStreamQuicImpl::WriteHeaders() { |
| + DCHECK(!has_sent_headers_); |
| SpdyHeaderBlock headers; |
| HttpRequestInfo http_request_info; |
| @@ -126,17 +122,13 @@ bool BidirectionalStreamQuicImpl::WriteHeaders() { |
| CreateSpdyHeadersFromHttpRequest( |
| http_request_info, http_request_info.extra_headers, true, &headers); |
| - // Sending the request might result in the stream being closed via OnClose |
| - // which will post a task to notify the delegate asynchronously. |
| - // TODO(rch): Clean up this interface when OnClose and OnError are removed. |
| - size_t headers_bytes_sent = stream_->WriteHeaders( |
| - std::move(headers), request_info_->end_stream_on_headers, nullptr); |
| - if (!stream_) |
| - return false; |
| - |
| - headers_bytes_sent_ += headers_bytes_sent; |
| - has_sent_headers_ = true; |
| - return true; |
| + int rv = stream_->WriteHeaders(std::move(headers), |
| + request_info_->end_stream_on_headers, nullptr); |
| + if (rv >= 0) { |
| + headers_bytes_sent_ += rv; |
| + has_sent_headers_ = true; |
| + } |
| + return rv; |
| } |
| int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| @@ -144,10 +136,6 @@ int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| DCHECK(buffer); |
| DCHECK(buffer_len); |
| - if (!stream_) { |
| - // If the stream is already closed, there is no body to read. |
| - return response_status_; |
| - } |
| int rv = stream_->ReadBody( |
| buffer, buffer_len, |
| base::Bind(&BidirectionalStreamQuicImpl::OnReadDataComplete, |
| @@ -164,6 +152,7 @@ int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| if (stream_->IsDoneReading()) { |
| // If the write side is closed, OnFinRead() will call |
| // BidirectionalStreamQuicImpl::OnClose(). |
| + expect_trailers_ = false; |
| stream_->OnFinRead(); |
| } |
| return rv; |
| @@ -174,8 +163,8 @@ void BidirectionalStreamQuicImpl::SendData(const scoped_refptr<IOBuffer>& data, |
| bool end_stream) { |
| ScopedBoolSaver saver(&may_invoke_callbacks_, false); |
| DCHECK(length > 0 || (length == 0 && end_stream)); |
| - if (!stream_) { |
| - LOG(ERROR) << "Trying to send data after stream has been destroyed."; |
| + if (!stream_->IsOpen()) { |
| + LOG(ERROR) << "Trying to send data after stream has been closed."; |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| @@ -190,8 +179,13 @@ void BidirectionalStreamQuicImpl::SendData(const scoped_refptr<IOBuffer>& data, |
| bundler = |
| session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING); |
| // Sending the request might result in the stream being closed. |
| - if (!WriteHeaders()) |
| + int rv = WriteHeaders(); |
| + if (rv < 0) { |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| + weak_factory_.GetWeakPtr(), rv)); |
| return; |
| + } |
| } |
| QuicStringPiece string_data(data->data(), length); |
| @@ -199,11 +193,10 @@ void BidirectionalStreamQuicImpl::SendData(const scoped_refptr<IOBuffer>& data, |
| string_data, end_stream, |
| base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| weak_factory_.GetWeakPtr())); |
| - DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| - if (rv == OK) { |
| + if (rv != ERR_IO_PENDING) { |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| - weak_factory_.GetWeakPtr(), OK)); |
| + weak_factory_.GetWeakPtr(), rv)); |
| } |
| } |
| @@ -214,8 +207,8 @@ void BidirectionalStreamQuicImpl::SendvData( |
| ScopedBoolSaver saver(&may_invoke_callbacks_, false); |
| DCHECK_EQ(buffers.size(), lengths.size()); |
| - if (!stream_) { |
| - LOG(ERROR) << "Trying to send data after stream has been destroyed."; |
| + if (!stream_->IsOpen()) { |
| + LOG(ERROR) << "Trying to send data after stream has been closed."; |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| @@ -226,9 +219,13 @@ void BidirectionalStreamQuicImpl::SendvData( |
| session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); |
| if (!has_sent_headers_) { |
| DCHECK(!send_request_headers_automatically_); |
| - // Sending the request might result in the stream being closed. |
| - if (!WriteHeaders()) |
| + int rv = WriteHeaders(); |
| + if (rv < 0) { |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| + weak_factory_.GetWeakPtr(), rv)); |
|
Ryan Hamilton
2017/06/01 23:20:30
Since we do this same thing every time we call Wri
|
| return; |
| + } |
| } |
| int rv = stream_->WritevStreamData( |
| @@ -236,11 +233,10 @@ void BidirectionalStreamQuicImpl::SendvData( |
| base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| weak_factory_.GetWeakPtr())); |
| - DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| - if (rv == OK) { |
| + if (rv != ERR_IO_PENDING) { |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| - weak_factory_.GetWeakPtr(), OK)); |
| + weak_factory_.GetWeakPtr(), rv)); |
| } |
| } |
| @@ -274,42 +270,15 @@ bool BidirectionalStreamQuicImpl::GetLoadTimingInfo( |
| return true; |
| } |
| -void BidirectionalStreamQuicImpl::OnClose() { |
| - DCHECK(stream_); |
| - |
| - if (stream_->connection_error() != QUIC_NO_ERROR || |
| - stream_->stream_error() != QUIC_STREAM_NO_ERROR) { |
| - OnError(session_->IsCryptoHandshakeConfirmed() ? ERR_QUIC_PROTOCOL_ERROR |
| - : ERR_QUIC_HANDSHAKE_FAILED); |
| - return; |
| - } |
| - |
| - if (!stream_->fin_sent() || !stream_->fin_received()) { |
| - // The connection must have been closed by the peer with QUIC_NO_ERROR, |
| - // which is improper. |
| - OnError(ERR_UNEXPECTED); |
| - return; |
| - } |
| - |
| - // The connection was closed normally so there is no need to notify |
| - // the delegate. |
| - ResetStream(); |
| -} |
| - |
| -void BidirectionalStreamQuicImpl::OnError(int error) { |
| - // Avoid reentrancy by notifying the delegate asynchronously. |
| - NotifyErrorImpl(error, /*notify_delegate_later*/ true); |
| -} |
| - |
| void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| DCHECK_NE(ERR_IO_PENDING, rv); |
| - DCHECK(rv == OK || !stream_); |
| + DCHECK(!stream_); |
| if (rv != OK) { |
| NotifyError(rv); |
| return; |
| } |
| - stream_ = session_->ReleaseStream(this); |
| + stream_ = session_->ReleaseStream(); |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::ReadInitialHeaders, |
| @@ -320,8 +289,8 @@ void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { |
| CHECK(may_invoke_callbacks_); |
| - DCHECK(rv == OK || !stream_); |
| - if (rv != 0) { |
| + DCHECK_NE(ERR_IO_PENDING, rv); |
| + if (rv < 0) { |
| NotifyError(rv); |
| return; |
| } |
| @@ -372,7 +341,8 @@ void BidirectionalStreamQuicImpl::OnReadTrailingHeadersComplete(int rv) { |
| CHECK(may_invoke_callbacks_); |
| DCHECK_NE(ERR_IO_PENDING, rv); |
| if (rv < 0) { |
| - NotifyError(rv); |
| + if (expect_trailers_) |
| + NotifyError(rv); |
| return; |
| } |
| @@ -384,7 +354,7 @@ void BidirectionalStreamQuicImpl::OnReadTrailingHeadersComplete(int rv) { |
| void BidirectionalStreamQuicImpl::OnReadDataComplete(int rv) { |
| CHECK(may_invoke_callbacks_); |
| - DCHECK_GE(rv, 0); |
| + |
| read_buffer_ = nullptr; |
| read_buffer_len_ = 0; |
| @@ -394,7 +364,12 @@ void BidirectionalStreamQuicImpl::OnReadDataComplete(int rv) { |
| stream_->OnFinRead(); |
| } |
| - if (delegate_) |
| + if (!delegate_) |
| + return; |
| + |
| + if (rv < 0) |
| + NotifyError(rv); |
| + else |
| delegate_->OnDataRead(rv); |
| } |
| @@ -435,9 +410,15 @@ void BidirectionalStreamQuicImpl::NotifyFailure( |
| void BidirectionalStreamQuicImpl::NotifyStreamReady() { |
| CHECK(may_invoke_callbacks_); |
| - // Sending the request might result in the stream being closed. |
| - if (send_request_headers_automatically_ && !WriteHeaders()) |
| - return; |
| + if (send_request_headers_automatically_) { |
| + int rv = WriteHeaders(); |
| + if (rv < 0) { |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| + weak_factory_.GetWeakPtr(), rv)); |
| + return; |
| + } |
| + } |
| if (delegate_) |
| delegate_->OnStreamReady(has_sent_headers_); |
| @@ -449,8 +430,6 @@ void BidirectionalStreamQuicImpl::ResetStream() { |
| closed_stream_received_bytes_ = stream_->stream_bytes_read(); |
| closed_stream_sent_bytes_ = stream_->stream_bytes_written(); |
| closed_is_first_stream_ = stream_->IsFirstStream(); |
| - stream_->ClearDelegate(); |
| - stream_ = nullptr; |
| } |
| } // namespace net |