| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 return; | 95 return; |
| 96 } | 96 } |
| 97 | 97 |
| 98 base::ThreadTaskRunnerHandle::Get()->PostTask( | 98 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 99 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady, | 99 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnStreamReady, |
| 100 weak_factory_.GetWeakPtr(), rv)); | 100 weak_factory_.GetWeakPtr(), rv)); |
| 101 } | 101 } |
| 102 | 102 |
| 103 void BidirectionalStreamQuicImpl::SendRequestHeaders() { | 103 void BidirectionalStreamQuicImpl::SendRequestHeaders() { |
| 104 ScopedBoolSaver saver(&may_invoke_callbacks_, false); | 104 ScopedBoolSaver saver(&may_invoke_callbacks_, false); |
| 105 // If this fails, a task will have been posted to notify the delegate | 105 int rv = WriteHeaders(); |
| 106 // asynchronously. | 106 if (rv < 0) { |
| 107 WriteHeaders(); | 107 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 108 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 109 weak_factory_.GetWeakPtr(), rv)); |
| 110 } |
| 108 } | 111 } |
| 109 | 112 |
| 110 bool BidirectionalStreamQuicImpl::WriteHeaders() { | 113 int BidirectionalStreamQuicImpl::WriteHeaders() { |
| 111 DCHECK(!has_sent_headers_); | 114 DCHECK(!has_sent_headers_); |
| 112 if (!stream_) { | |
| 113 LOG(ERROR) | |
| 114 << "Trying to send request headers after stream has been destroyed."; | |
| 115 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 116 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | |
| 117 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | |
| 118 return false; | |
| 119 } | |
| 120 | 115 |
| 121 SpdyHeaderBlock headers; | 116 SpdyHeaderBlock headers; |
| 122 HttpRequestInfo http_request_info; | 117 HttpRequestInfo http_request_info; |
| 123 http_request_info.url = request_info_->url; | 118 http_request_info.url = request_info_->url; |
| 124 http_request_info.method = request_info_->method; | 119 http_request_info.method = request_info_->method; |
| 125 http_request_info.extra_headers = request_info_->extra_headers; | 120 http_request_info.extra_headers = request_info_->extra_headers; |
| 126 | 121 |
| 127 CreateSpdyHeadersFromHttpRequest( | 122 CreateSpdyHeadersFromHttpRequest( |
| 128 http_request_info, http_request_info.extra_headers, true, &headers); | 123 http_request_info, http_request_info.extra_headers, true, &headers); |
| 129 // Sending the request might result in the stream being closed via OnClose | 124 int rv = stream_->WriteHeaders(std::move(headers), |
| 130 // which will post a task to notify the delegate asynchronously. | 125 request_info_->end_stream_on_headers, nullptr); |
| 131 // TODO(rch): Clean up this interface when OnClose and OnError are removed. | 126 if (rv >= 0) { |
| 132 size_t headers_bytes_sent = stream_->WriteHeaders( | 127 headers_bytes_sent_ += rv; |
| 133 std::move(headers), request_info_->end_stream_on_headers, nullptr); | 128 has_sent_headers_ = true; |
| 134 if (!stream_) | 129 } |
| 135 return false; | 130 return rv; |
| 136 | |
| 137 headers_bytes_sent_ += headers_bytes_sent; | |
| 138 has_sent_headers_ = true; | |
| 139 return true; | |
| 140 } | 131 } |
| 141 | 132 |
| 142 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { | 133 int BidirectionalStreamQuicImpl::ReadData(IOBuffer* buffer, int buffer_len) { |
| 143 ScopedBoolSaver saver(&may_invoke_callbacks_, false); | 134 ScopedBoolSaver saver(&may_invoke_callbacks_, false); |
| 144 DCHECK(buffer); | 135 DCHECK(buffer); |
| 145 DCHECK(buffer_len); | 136 DCHECK(buffer_len); |
| 146 | 137 |
| 147 if (!stream_) { | |
| 148 // If the stream is already closed, there is no body to read. | |
| 149 return response_status_; | |
| 150 } | |
| 151 int rv = stream_->ReadBody( | 138 int rv = stream_->ReadBody( |
| 152 buffer, buffer_len, | 139 buffer, buffer_len, |
| 153 base::Bind(&BidirectionalStreamQuicImpl::OnReadDataComplete, | 140 base::Bind(&BidirectionalStreamQuicImpl::OnReadDataComplete, |
| 154 weak_factory_.GetWeakPtr())); | 141 weak_factory_.GetWeakPtr())); |
| 155 if (rv == ERR_IO_PENDING) { | 142 if (rv == ERR_IO_PENDING) { |
| 156 read_buffer_ = buffer; | 143 read_buffer_ = buffer; |
| 157 read_buffer_len_ = buffer_len; | 144 read_buffer_len_ = buffer_len; |
| 158 return ERR_IO_PENDING; | 145 return ERR_IO_PENDING; |
| 159 } | 146 } |
| 160 | 147 |
| 161 if (rv < 0) | 148 if (rv < 0) |
| 162 return rv; | 149 return rv; |
| 163 | 150 |
| 164 if (stream_->IsDoneReading()) { | 151 // If the write side is closed, OnFinRead() will call |
| 165 // If the write side is closed, OnFinRead() will call | 152 // BidirectionalStreamQuicImpl::OnClose(). |
| 166 // BidirectionalStreamQuicImpl::OnClose(). | 153 if (stream_->IsDoneReading()) |
| 167 stream_->OnFinRead(); | 154 stream_->OnFinRead(); |
| 168 } | 155 |
| 169 return rv; | 156 return rv; |
| 170 } | 157 } |
| 171 | 158 |
| 172 void BidirectionalStreamQuicImpl::SendvData( | 159 void BidirectionalStreamQuicImpl::SendvData( |
| 173 const std::vector<scoped_refptr<IOBuffer>>& buffers, | 160 const std::vector<scoped_refptr<IOBuffer>>& buffers, |
| 174 const std::vector<int>& lengths, | 161 const std::vector<int>& lengths, |
| 175 bool end_stream) { | 162 bool end_stream) { |
| 176 ScopedBoolSaver saver(&may_invoke_callbacks_, false); | 163 ScopedBoolSaver saver(&may_invoke_callbacks_, false); |
| 177 DCHECK_EQ(buffers.size(), lengths.size()); | 164 DCHECK_EQ(buffers.size(), lengths.size()); |
| 178 | 165 |
| 179 if (!stream_) { | 166 if (!stream_->IsOpen()) { |
| 180 LOG(ERROR) << "Trying to send data after stream has been destroyed."; | 167 LOG(ERROR) << "Trying to send data after stream has been closed."; |
| 181 base::ThreadTaskRunnerHandle::Get()->PostTask( | 168 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 182 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, | 169 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 183 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); | 170 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED)); |
| 184 return; | 171 return; |
| 185 } | 172 } |
| 186 | 173 |
| 187 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( | 174 std::unique_ptr<QuicConnection::ScopedPacketBundler> bundler( |
| 188 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); | 175 session_->CreatePacketBundler(QuicConnection::SEND_ACK_IF_PENDING)); |
| 189 if (!has_sent_headers_) { | 176 if (!has_sent_headers_) { |
| 190 DCHECK(!send_request_headers_automatically_); | 177 DCHECK(!send_request_headers_automatically_); |
| 191 // Sending the request might result in the stream being closed. | 178 int rv = WriteHeaders(); |
| 192 if (!WriteHeaders()) | 179 if (rv < 0) { |
| 180 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 181 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 182 weak_factory_.GetWeakPtr(), rv)); |
| 193 return; | 183 return; |
| 184 } |
| 194 } | 185 } |
| 195 | 186 |
| 196 int rv = stream_->WritevStreamData( | 187 int rv = stream_->WritevStreamData( |
| 197 buffers, lengths, end_stream, | 188 buffers, lengths, end_stream, |
| 198 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 189 base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 199 weak_factory_.GetWeakPtr())); | 190 weak_factory_.GetWeakPtr())); |
| 200 | 191 |
| 201 DCHECK(rv == OK || rv == ERR_IO_PENDING); | 192 if (rv != ERR_IO_PENDING) { |
| 202 if (rv == OK) { | |
| 203 base::ThreadTaskRunnerHandle::Get()->PostTask( | 193 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 204 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, | 194 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::OnSendDataComplete, |
| 205 weak_factory_.GetWeakPtr(), OK)); | 195 weak_factory_.GetWeakPtr(), rv)); |
| 206 } | 196 } |
| 207 } | 197 } |
| 208 | 198 |
| 209 NextProto BidirectionalStreamQuicImpl::GetProtocol() const { | 199 NextProto BidirectionalStreamQuicImpl::GetProtocol() const { |
| 210 return negotiated_protocol_; | 200 return negotiated_protocol_; |
| 211 } | 201 } |
| 212 | 202 |
| 213 int64_t BidirectionalStreamQuicImpl::GetTotalReceivedBytes() const { | 203 int64_t BidirectionalStreamQuicImpl::GetTotalReceivedBytes() const { |
| 214 if (stream_) | 204 if (stream_) |
| 215 return headers_bytes_received_ + stream_->stream_bytes_read(); | 205 return headers_bytes_received_ + stream_->stream_bytes_read(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 229 is_first_stream = stream_->IsFirstStream(); | 219 is_first_stream = stream_->IsFirstStream(); |
| 230 if (is_first_stream) { | 220 if (is_first_stream) { |
| 231 load_timing_info->socket_reused = false; | 221 load_timing_info->socket_reused = false; |
| 232 load_timing_info->connect_timing = connect_timing_; | 222 load_timing_info->connect_timing = connect_timing_; |
| 233 } else { | 223 } else { |
| 234 load_timing_info->socket_reused = true; | 224 load_timing_info->socket_reused = true; |
| 235 } | 225 } |
| 236 return true; | 226 return true; |
| 237 } | 227 } |
| 238 | 228 |
| 239 void BidirectionalStreamQuicImpl::OnClose() { | |
| 240 DCHECK(stream_); | |
| 241 | |
| 242 if (stream_->connection_error() != QUIC_NO_ERROR || | |
| 243 stream_->stream_error() != QUIC_STREAM_NO_ERROR) { | |
| 244 OnError(session_->IsCryptoHandshakeConfirmed() ? ERR_QUIC_PROTOCOL_ERROR | |
| 245 : ERR_QUIC_HANDSHAKE_FAILED); | |
| 246 return; | |
| 247 } | |
| 248 | |
| 249 if (!stream_->fin_sent() || !stream_->fin_received()) { | |
| 250 // The connection must have been closed by the peer with QUIC_NO_ERROR, | |
| 251 // which is improper. | |
| 252 OnError(ERR_UNEXPECTED); | |
| 253 return; | |
| 254 } | |
| 255 | |
| 256 // The connection was closed normally so there is no need to notify | |
| 257 // the delegate. | |
| 258 ResetStream(); | |
| 259 } | |
| 260 | |
| 261 void BidirectionalStreamQuicImpl::OnError(int error) { | |
| 262 // Avoid reentrancy by notifying the delegate asynchronously. | |
| 263 NotifyErrorImpl(error, /*notify_delegate_later*/ true); | |
| 264 } | |
| 265 | |
| 266 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { | 229 void BidirectionalStreamQuicImpl::OnStreamReady(int rv) { |
| 267 DCHECK_NE(ERR_IO_PENDING, rv); | 230 DCHECK_NE(ERR_IO_PENDING, rv); |
| 268 DCHECK(rv == OK || !stream_); | 231 DCHECK(!stream_); |
| 269 if (rv != OK) { | 232 if (rv != OK) { |
| 270 NotifyError(rv); | 233 NotifyError(rv); |
| 271 return; | 234 return; |
| 272 } | 235 } |
| 273 | 236 |
| 274 stream_ = session_->ReleaseStream(this); | 237 stream_ = session_->ReleaseStream(); |
| 275 | 238 |
| 276 base::ThreadTaskRunnerHandle::Get()->PostTask( | 239 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 277 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::ReadInitialHeaders, | 240 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::ReadInitialHeaders, |
| 278 weak_factory_.GetWeakPtr())); | 241 weak_factory_.GetWeakPtr())); |
| 279 | 242 |
| 280 NotifyStreamReady(); | 243 NotifyStreamReady(); |
| 281 } | 244 } |
| 282 | 245 |
| 283 void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { | 246 void BidirectionalStreamQuicImpl::OnSendDataComplete(int rv) { |
| 284 CHECK(may_invoke_callbacks_); | 247 CHECK(may_invoke_callbacks_); |
| 285 DCHECK(rv == OK || !stream_); | 248 DCHECK_NE(ERR_IO_PENDING, rv); |
| 286 if (rv != 0) { | 249 if (rv < 0) { |
| 287 NotifyError(rv); | 250 NotifyError(rv); |
| 288 return; | 251 return; |
| 289 } | 252 } |
| 290 | 253 |
| 291 if (delegate_) | 254 if (delegate_) |
| 292 delegate_->OnDataSent(); | 255 delegate_->OnDataSent(); |
| 293 } | 256 } |
| 294 | 257 |
| 295 void BidirectionalStreamQuicImpl::OnReadInitialHeadersComplete(int rv) { | 258 void BidirectionalStreamQuicImpl::OnReadInitialHeadersComplete(int rv) { |
| 296 CHECK(may_invoke_callbacks_); | 259 CHECK(may_invoke_callbacks_); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 302 } |
| 340 | 303 |
| 341 headers_bytes_received_ += rv; | 304 headers_bytes_received_ += rv; |
| 342 | 305 |
| 343 if (delegate_) | 306 if (delegate_) |
| 344 delegate_->OnTrailersReceived(trailing_headers_); | 307 delegate_->OnTrailersReceived(trailing_headers_); |
| 345 } | 308 } |
| 346 | 309 |
| 347 void BidirectionalStreamQuicImpl::OnReadDataComplete(int rv) { | 310 void BidirectionalStreamQuicImpl::OnReadDataComplete(int rv) { |
| 348 CHECK(may_invoke_callbacks_); | 311 CHECK(may_invoke_callbacks_); |
| 349 DCHECK_GE(rv, 0); | 312 |
| 350 read_buffer_ = nullptr; | 313 read_buffer_ = nullptr; |
| 351 read_buffer_len_ = 0; | 314 read_buffer_len_ = 0; |
| 352 | 315 |
| 353 if (stream_->IsDoneReading()) { | 316 // If the write side is closed, OnFinRead() will call |
| 354 // If the write side is closed, OnFinRead() will call | 317 // BidirectionalStreamQuicImpl::OnClose(). |
| 355 // BidirectionalStreamQuicImpl::OnClose(). | 318 if (stream_->IsDoneReading()) |
| 356 stream_->OnFinRead(); | 319 stream_->OnFinRead(); |
| 357 } | |
| 358 | 320 |
| 359 if (delegate_) | 321 if (!delegate_) |
| 322 return; |
| 323 |
| 324 if (rv < 0) |
| 325 NotifyError(rv); |
| 326 else |
| 360 delegate_->OnDataRead(rv); | 327 delegate_->OnDataRead(rv); |
| 361 } | 328 } |
| 362 | 329 |
| 363 void BidirectionalStreamQuicImpl::NotifyError(int error) { | 330 void BidirectionalStreamQuicImpl::NotifyError(int error) { |
| 364 NotifyErrorImpl(error, /*notify_delegate_later*/ false); | 331 NotifyErrorImpl(error, /*notify_delegate_later*/ false); |
| 365 } | 332 } |
| 366 | 333 |
| 367 void BidirectionalStreamQuicImpl::NotifyErrorImpl(int error, | 334 void BidirectionalStreamQuicImpl::NotifyErrorImpl(int error, |
| 368 bool notify_delegate_later) { | 335 bool notify_delegate_later) { |
| 369 DCHECK_NE(OK, error); | 336 DCHECK_NE(OK, error); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 390 void BidirectionalStreamQuicImpl::NotifyFailure( | 357 void BidirectionalStreamQuicImpl::NotifyFailure( |
| 391 BidirectionalStreamImpl::Delegate* delegate, | 358 BidirectionalStreamImpl::Delegate* delegate, |
| 392 int error) { | 359 int error) { |
| 393 CHECK(may_invoke_callbacks_); | 360 CHECK(may_invoke_callbacks_); |
| 394 delegate->OnFailed(error); | 361 delegate->OnFailed(error); |
| 395 // |this| might be destroyed at this point. | 362 // |this| might be destroyed at this point. |
| 396 } | 363 } |
| 397 | 364 |
| 398 void BidirectionalStreamQuicImpl::NotifyStreamReady() { | 365 void BidirectionalStreamQuicImpl::NotifyStreamReady() { |
| 399 CHECK(may_invoke_callbacks_); | 366 CHECK(may_invoke_callbacks_); |
| 400 // Sending the request might result in the stream being closed. | 367 if (send_request_headers_automatically_) { |
| 401 if (send_request_headers_automatically_ && !WriteHeaders()) | 368 int rv = WriteHeaders(); |
| 402 return; | 369 if (rv < 0) { |
| 370 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 371 FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError, |
| 372 weak_factory_.GetWeakPtr(), rv)); |
| 373 return; |
| 374 } |
| 375 } |
| 403 | 376 |
| 404 if (delegate_) | 377 if (delegate_) |
| 405 delegate_->OnStreamReady(has_sent_headers_); | 378 delegate_->OnStreamReady(has_sent_headers_); |
| 406 } | 379 } |
| 407 | 380 |
| 408 void BidirectionalStreamQuicImpl::ResetStream() { | 381 void BidirectionalStreamQuicImpl::ResetStream() { |
| 409 if (!stream_) | 382 if (!stream_) |
| 410 return; | 383 return; |
| 411 closed_stream_received_bytes_ = stream_->stream_bytes_read(); | 384 closed_stream_received_bytes_ = stream_->stream_bytes_read(); |
| 412 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); | 385 closed_stream_sent_bytes_ = stream_->stream_bytes_written(); |
| 413 closed_is_first_stream_ = stream_->IsFirstStream(); | 386 closed_is_first_stream_ = stream_->IsFirstStream(); |
| 414 stream_->ClearDelegate(); | |
| 415 stream_ = nullptr; | |
| 416 } | 387 } |
| 417 | 388 |
| 418 } // namespace net | 389 } // namespace net |
| OLD | NEW |