Chromium Code Reviews| 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. |
|
Ryan Hamilton
2017/06/01 17:10:14
Since this CL no longer notifies the delegate sync
xunjieli
2017/06/01 21:24:02
Acknowledged. If the upcalls (OnClose and OnError)
Ryan Hamilton
2017/06/01 21:43:48
Yeah, either a bool, or an int. TODO added.
| |
| 103 auto guard = weak_factory_.GetWeakPtr(); | |
| 104 size_t headers_bytes_sent = stream_->WriteHeaders( | 107 size_t headers_bytes_sent = stream_->WriteHeaders( |
| 105 std::move(headers), request_info_->end_stream_on_headers, nullptr); | 108 std::move(headers), request_info_->end_stream_on_headers, nullptr); |
| 106 if (!guard.get()) | 109 if (!stream_) |
| 107 return; | 110 return false; |
|
xunjieli
2017/06/01 21:24:02
Could you add a comment here that NotifyError() wi
Ryan Hamilton
2017/06/01 21:43:48
In both places that this method returns false, a t
| |
| 111 | |
| 108 headers_bytes_sent_ += headers_bytes_sent; | 112 headers_bytes_sent_ += headers_bytes_sent; |
| 109 has_sent_headers_ = true; | 113 has_sent_headers_ = true; |
| 114 return true; | |
| 110 } | 115 } |
| 111 | 116 |
| 112 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { | 117 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| 113 DCHECK(buffer); | 118 DCHECK(buffer); |
| 114 DCHECK(buffer_len); | 119 DCHECK(buffer_len); |
| 115 | 120 |
| 116 if (!stream_) { | 121 if (!stream_) { |
| 117 // If the stream is already closed, there is no body to read. | 122 // If the stream is already closed, there is no body to read. |
| 118 return response_status_; | 123 return response_status_; |
| 119 } | 124 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 150 return; | 155 return; |
| 151 } | 156 } |
| 152 | 157 |
| 153 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; | 158 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler; |
| 154 if (!has_sent_headers_) { | 159 if (!has_sent_headers_) { |
| 155 DCHECK(!send_request_headers_automatically_); | 160 DCHECK(!send_request_headers_automatically_); |
| 156 // Creates a bundler only if there are headers to be sent along with the | 161 // Creates a bundler only if there are headers to be sent along with the |
| 157 // single data buffer. | 162 // single data buffer. |
| 158 bundler = | 163 bundler = |
| 159 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING); | 164 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING); |
| 160 SendRequestHeaders(); | 165 // Sending the request might result in the stream being closed. |
| 166 if (!WriteHeaders()) | |
| 167 return; | |
| 161 } | 168 } |
| 162 | 169 |
| 163 QuicStringPiece string_data(data->data(), length); | 170 QuicStringPiece string_data(data->data(), length); |
| 164 int rv = stream_->WriteStreamData( | 171 int rv = stream_->WriteStreamData( |
| 165 string_data, end_stream, | 172 string_data, end_stream, |
| 166 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 173 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 167 weak_factory_.GetWeakPtr())); | 174 weak_factory_.GetWeakPtr())); |
| 168 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 175 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 169 if (rv == OK) { | 176 if (rv == OK) { |
| 170 base::ThreadTaskRunnerHandle::Get()->PostTask( | 177 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 184 base::ThreadTaskRunnerHandle::Get()->PostTask( | 191 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 185 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | 192 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 186 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | 193 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| 187 return; | 194 return; |
| 188 } | 195 } |
| 189 | 196 |
| 190 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( | 197 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( |
| 191 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); | 198 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); |
| 192 if (!has_sent_headers_) { | 199 if (!has_sent_headers_) { |
| 193 DCHECK(!send_request_headers_automatically_); | 200 DCHECK(!send_request_headers_automatically_); |
| 194 SendRequestHeaders(); | 201 // Sending the request might result in the stream being closed. |
| 202 if (!WriteHeaders()) | |
| 203 return; | |
| 195 } | 204 } |
| 196 | 205 |
| 197 int rv = stream_->WritevStreamData( | 206 int rv = stream_->WritevStreamData( |
| 198 buffers, lengths, end_stream, | 207 buffers, lengths, end_stream, |
| 199 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 208 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 200 weak_factory_.GetWeakPtr())); | 209 weak_factory_.GetWeakPtr())); |
| 201 | 210 |
| 202 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 211 DCHECK(rv == OK || rv == ERR_IO_PENDING); |
| 203 if (rv == OK) { | 212 if (rv == OK) { |
| 204 base::ThreadTaskRunnerHandle::Get()->PostTask( | 213 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 235 load_timing_info->socket_reused = true; | 244 load_timing_info->socket_reused = true; |
| 236 } | 245 } |
| 237 return true; | 246 return true; |
| 238 } | 247 } |
| 239 | 248 |
| 240 void BidirectionalStreamQuicImpl::OnClose() { | 249 void BidirectionalStreamQuicImpl::OnClose() { |
| 241 DCHECK(stream_); | 250 DCHECK(stream_); |
| 242 | 251 |
| 243 if (stream_->connection_error() != QUIC_NO_ERROR || | 252 if (stream_->connection_error() != QUIC_NO_ERROR || |
| 244 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { | 253 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { |
| 245 NotifyError(session_->IsCryptoHandshakeConfirmed() | 254 OnError(session_->IsCryptoHandshakeConfirmed() ? ERR_QUIC_PROTOCOL_ERROR |
| 246 ? ERR_QUIC_PROTOCOL_ERROR | 255 : ERR_QUIC_HANDSHAKE_FAILED); |
| 247 : ERR_QUIC_HANDSHAKE_FAILED); | |
| 248 return; | 256 return; |
| 249 } | 257 } |
| 250 | 258 |
| 251 if (!stream_->fin_sent() || !stream_->fin_received()) { | 259 if (!stream_->fin_sent() || !stream_->fin_received()) { |
| 252 // The connection must have been closed by the peer with QUIC_NO_ERROR, | 260 // The connection must have been closed by the peer with QUIC_NO_ERROR, |
| 253 // which is improper. | 261 // which is improper. |
| 254 NotifyError(ERR_UNEXPECTED); | 262 OnError(ERR_UNEXPECTED); |
| 255 return; | 263 return; |
| 256 } | 264 } |
| 257 | 265 |
| 258 // The connection was closed normally so there is no need to notify | 266 // The connection was closed normally so there is no need to notify |
| 259 // the delegate. | 267 // the delegate. |
| 260 ResetStream(); | 268 ResetStream(); |
| 261 } | 269 } |
| 262 | 270 |
| 263 void BidirectionalStreamQuicImpl::OnError(int error) { | 271 void BidirectionalStreamQuicImpl::OnError(int error) { |
| 264 NotifyError(error); | 272 // Avoid reentrancy by notifying the delegate asynchronously. |
| 273 NotifyErrorImpl(error, /*notify_delegate_later*/ true); | |
| 265 } | 274 } |
| 266 | 275 |
| 267 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { | 276 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| 268 DCHECK_NE(ERR_IO_PENDING, rv); | 277 DCHECK_NE(ERR_IO_PENDING, rv); |
| 269 DCHECK(rv == OK || !stream_); | 278 DCHECK(rv == OK || !stream_); |
| 270 if (rv != OK) { | 279 if (rv != OK) { |
| 271 NotifyError(rv); | 280 NotifyError(rv); |
| 272 return; | 281 return; |
| 273 } | 282 } |
| 274 | 283 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 351 // If the write side is closed, OnFinRead() will call | 360 // If the write side is closed, OnFinRead() will call |
| 352 // BidirectionalStreamQuicImpl::OnClose(). | 361 // BidirectionalStreamQuicImpl::OnClose(). |
| 353 stream_->OnFinRead(); | 362 stream_->OnFinRead(); |
| 354 } | 363 } |
| 355 | 364 |
| 356 if (delegate_) | 365 if (delegate_) |
| 357 delegate_->OnDataRead(rv); | 366 delegate_->OnDataRead(rv); |
| 358 } | 367 } |
| 359 | 368 |
| 360 void BidirectionalStreamQuicImpl::NotifyError(int error) { | 369 void BidirectionalStreamQuicImpl::NotifyError(int error) { |
| 370 NotifyErrorImpl(error, /*notify_delegate_later*/ false); | |
| 371 } | |
| 372 | |
| 373 void BidirectionalStreamQuicImpl::NotifyErrorImpl(int error, | |
| 374 bool notify_delegate_later) { | |
| 361 DCHECK_NE(OK, error); | 375 DCHECK_NE(OK, error); |
| 362 DCHECK_NE(ERR_IO_PENDING, error); | 376 DCHECK_NE(ERR_IO_PENDING, error); |
| 363 | 377 |
| 364 ResetStream(); | 378 ResetStream(); |
| 365 if (delegate_) { | 379 if (delegate_) { |
| 366 response_status_ = error; | 380 response_status_ = error; |
| 367 BidirectionalStreamImpl::Delegate* delegate = delegate_; | 381 BidirectionalStreamImpl::Delegate* delegate = delegate_; |
| 368 delegate_ = nullptr; | 382 delegate_ = nullptr; |
| 369 // Cancel any pending callback. | 383 // Cancel any pending callback. |
| 370 weak_factory_.InvalidateWeakPtrs(); | 384 weak_factory_.InvalidateWeakPtrs(); |
| 371 delegate->OnFailed(error); | 385 if (notify_delegate_later) { |
| 372 // |this| might be destroyed at this point. | 386 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 387 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyFailure, | |
| 388 weak_factory_.GetWeakPtr(), delegate, error)); | |
| 389 } else { | |
| 390 NotifyFailure(delegate, error); | |
| 391 // |this| might be destroyed at this point. | |
| 392 } | |
| 373 } | 393 } |
| 374 } | 394 } |
| 375 | 395 |
| 396 void BidirectionalStreamQuicImpl::NotifyFailure( | |
| 397 BidirectionalStreamImpl::Delegate* delegate, | |
| 398 int error) { | |
| 399 delegate->OnFailed(error); | |
| 400 // |this| might be destroyed at this point. | |
| 401 } | |
| 402 | |
| 376 void BidirectionalStreamQuicImpl::NotifyStreamReady() { | 403 void BidirectionalStreamQuicImpl::NotifyStreamReady() { |
| 377 if (send_request_headers_automatically_) { | 404 // Sending the request might result in the stream being closed. |
| 378 // Sending the request might result in |this| being deleted. | 405 if (send_request_headers_automatically_ && !WriteHeaders()) |
| 379 auto guard = weak_factory_.GetWeakPtr(); | 406 return; |
| 380 SendRequestHeaders(); | 407 |
| 381 if (!guard.get()) | |
| 382 return; | |
| 383 } | |
| 384 if (delegate_) | 408 if (delegate_) |
| 385 delegate_->OnStreamReady(has_sent_headers_); | 409 delegate_->OnStreamReady(has_sent_headers_); |
| 386 } | 410 } |
| 387 | 411 |
| 388 void BidirectionalStreamQuicImpl::ResetStream() { | 412 void BidirectionalStreamQuicImpl::ResetStream() { |
| 389 if (!stream_) | 413 if (!stream_) |
| 390 return; | 414 return; |
| 391 closed_stream_received_bytes_ = stream_->stream_bytes_read(); | 415 closed_stream_received_bytes_ = stream_->stream_bytes_read(); |
| 392 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); | 416 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); |
| 393 closed_is_first_stream_ = stream_->IsFirstStream(); | 417 closed_is_first_stream_ = stream_->IsFirstStream(); |
| 394 stream_->ClearDelegate(); | 418 stream_->ClearDelegate(); |
| 395 stream_ = nullptr; | 419 stream_ = nullptr; |
| 396 } | 420 } |
| 397 | 421 |
| 398 } // namespace net | 422 } // namespace net |
| OLD | NEW |