OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/reliable_quic_stream.h" | 5 #include "net/quic/reliable_quic_stream.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/profiler/scoped_tracker.h" | 8 #include "base/profiler/scoped_tracker.h" |
9 #include "net/quic/iovector.h" | 9 #include "net/quic/iovector.h" |
10 #include "net/quic/quic_flow_controller.h" | 10 #include "net/quic/quic_flow_controller.h" |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed"; | 341 DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed"; |
342 return QuicConsumedData(0, false); | 342 return QuicConsumedData(0, false); |
343 } | 343 } |
344 | 344 |
345 // How much data we want to write. | 345 // How much data we want to write. |
346 size_t write_length = TotalIovecLength(iov, iov_count); | 346 size_t write_length = TotalIovecLength(iov, iov_count); |
347 | 347 |
348 // A FIN with zero data payload should not be flow control blocked. | 348 // A FIN with zero data payload should not be flow control blocked. |
349 bool fin_with_zero_data = (fin && write_length == 0); | 349 bool fin_with_zero_data = (fin && write_length == 0); |
350 | 350 |
351 if (flow_controller_.IsEnabled()) { | 351 // How much data we are allowed to write from flow control. |
352 // How much data we are allowed to write from flow control. | 352 QuicByteCount send_window = flow_controller_.SendWindowSize(); |
353 QuicByteCount send_window = flow_controller_.SendWindowSize(); | 353 if (stream_contributes_to_connection_flow_control_) { |
354 if (stream_contributes_to_connection_flow_control_) { | 354 send_window = |
355 send_window = | 355 min(send_window, connection_flow_controller_->SendWindowSize()); |
356 min(send_window, connection_flow_controller_->SendWindowSize()); | 356 } |
357 } | |
358 | 357 |
359 if (send_window == 0 && !fin_with_zero_data) { | 358 if (send_window == 0 && !fin_with_zero_data) { |
360 // Quick return if we can't send anything. | 359 // Quick return if we can't send anything. |
361 MaybeSendBlocked(); | 360 MaybeSendBlocked(); |
362 return QuicConsumedData(0, false); | 361 return QuicConsumedData(0, false); |
363 } | 362 } |
364 | 363 |
365 if (write_length > send_window) { | 364 if (write_length > send_window) { |
366 // Don't send the FIN if we aren't going to send all the data. | 365 // Don't send the FIN if we aren't going to send all the data. |
367 fin = false; | 366 fin = false; |
368 | 367 |
369 // Writing more data would be a violation of flow control. | 368 // Writing more data would be a violation of flow control. |
370 write_length = static_cast<size_t>(send_window); | 369 write_length = static_cast<size_t>(send_window); |
371 } | |
372 } | 370 } |
373 | 371 |
374 // Fill an IOVector with bytes from the iovec. | 372 // Fill an IOVector with bytes from the iovec. |
375 IOVector data; | 373 IOVector data; |
376 data.AppendIovecAtMostBytes(iov, iov_count, write_length); | 374 data.AppendIovecAtMostBytes(iov, iov_count, write_length); |
377 | 375 |
378 QuicConsumedData consumed_data = session()->WritevData( | 376 QuicConsumedData consumed_data = session()->WritevData( |
379 id(), data, stream_bytes_written_, fin, GetFecProtection(), | 377 id(), data, stream_bytes_written_, fin, GetFecProtection(), |
380 ack_notifier_delegate); | 378 ack_notifier_delegate); |
381 stream_bytes_written_ += consumed_data.bytes_consumed; | 379 stream_bytes_written_ += consumed_data.bytes_consumed; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 // endpoints have the same connection level flow control state, mark all | 449 // endpoints have the same connection level flow control state, mark all |
452 // unreceived or buffered bytes as consumed. | 450 // unreceived or buffered bytes as consumed. |
453 QuicByteCount bytes_to_consume = | 451 QuicByteCount bytes_to_consume = |
454 flow_controller_.highest_received_byte_offset() - | 452 flow_controller_.highest_received_byte_offset() - |
455 flow_controller_.bytes_consumed(); | 453 flow_controller_.bytes_consumed(); |
456 AddBytesConsumed(bytes_to_consume); | 454 AddBytesConsumed(bytes_to_consume); |
457 } | 455 } |
458 | 456 |
459 void ReliableQuicStream::OnWindowUpdateFrame( | 457 void ReliableQuicStream::OnWindowUpdateFrame( |
460 const QuicWindowUpdateFrame& frame) { | 458 const QuicWindowUpdateFrame& frame) { |
461 if (!flow_controller_.IsEnabled()) { | |
462 DLOG(DFATAL) << "Flow control not enabled! " << version(); | |
463 return; | |
464 } | |
465 if (flow_controller_.UpdateSendWindowOffset(frame.byte_offset)) { | 459 if (flow_controller_.UpdateSendWindowOffset(frame.byte_offset)) { |
466 // We can write again! | 460 // We can write again! |
467 // TODO(rjshade): This does not respect priorities (e.g. multiple | 461 // TODO(rjshade): This does not respect priorities (e.g. multiple |
468 // outstanding POSTs are unblocked on arrival of | 462 // outstanding POSTs are unblocked on arrival of |
469 // SHLO with initial window). | 463 // SHLO with initial window). |
470 // As long as the connection is not flow control blocked, we can write! | 464 // As long as the connection is not flow control blocked, we can write! |
471 OnCanWrite(); | 465 OnCanWrite(); |
472 } | 466 } |
473 } | 467 } |
474 | 468 |
475 bool ReliableQuicStream::MaybeIncreaseHighestReceivedOffset( | 469 bool ReliableQuicStream::MaybeIncreaseHighestReceivedOffset( |
476 QuicStreamOffset new_offset) { | 470 QuicStreamOffset new_offset) { |
477 if (!flow_controller_.IsEnabled()) { | |
478 return false; | |
479 } | |
480 uint64 increment = | 471 uint64 increment = |
481 new_offset - flow_controller_.highest_received_byte_offset(); | 472 new_offset - flow_controller_.highest_received_byte_offset(); |
482 if (!flow_controller_.UpdateHighestReceivedOffset(new_offset)) { | 473 if (!flow_controller_.UpdateHighestReceivedOffset(new_offset)) { |
483 return false; | 474 return false; |
484 } | 475 } |
485 | 476 |
486 // If |new_offset| increased the stream flow controller's highest received | 477 // If |new_offset| increased the stream flow controller's highest received |
487 // offset, then we need to increase the connection flow controller's value | 478 // offset, then we need to increase the connection flow controller's value |
488 // by the incremental difference. | 479 // by the incremental difference. |
489 if (stream_contributes_to_connection_flow_control_) { | 480 if (stream_contributes_to_connection_flow_control_) { |
490 connection_flow_controller_->UpdateHighestReceivedOffset( | 481 connection_flow_controller_->UpdateHighestReceivedOffset( |
491 connection_flow_controller_->highest_received_byte_offset() + | 482 connection_flow_controller_->highest_received_byte_offset() + |
492 increment); | 483 increment); |
493 } | 484 } |
494 return true; | 485 return true; |
495 } | 486 } |
496 | 487 |
497 void ReliableQuicStream::AddBytesSent(QuicByteCount bytes) { | 488 void ReliableQuicStream::AddBytesSent(QuicByteCount bytes) { |
498 if (flow_controller_.IsEnabled()) { | 489 flow_controller_.AddBytesSent(bytes); |
499 flow_controller_.AddBytesSent(bytes); | 490 if (stream_contributes_to_connection_flow_control_) { |
500 if (stream_contributes_to_connection_flow_control_) { | 491 connection_flow_controller_->AddBytesSent(bytes); |
501 connection_flow_controller_->AddBytesSent(bytes); | |
502 } | |
503 } | 492 } |
504 } | 493 } |
505 | 494 |
506 void ReliableQuicStream::AddBytesConsumed(QuicByteCount bytes) { | 495 void ReliableQuicStream::AddBytesConsumed(QuicByteCount bytes) { |
507 if (flow_controller_.IsEnabled()) { | 496 // Only adjust stream level flow controller if we are still reading. |
508 // Only adjust stream level flow controller if we are still reading. | 497 if (!read_side_closed_) { |
509 if (!read_side_closed_) { | 498 flow_controller_.AddBytesConsumed(bytes); |
510 flow_controller_.AddBytesConsumed(bytes); | 499 } |
511 } | |
512 | 500 |
513 if (stream_contributes_to_connection_flow_control_) { | 501 if (stream_contributes_to_connection_flow_control_) { |
514 connection_flow_controller_->AddBytesConsumed(bytes); | 502 connection_flow_controller_->AddBytesConsumed(bytes); |
515 } | |
516 } | 503 } |
517 } | 504 } |
518 | 505 |
519 void ReliableQuicStream::UpdateSendWindowOffset(QuicStreamOffset new_window) { | 506 void ReliableQuicStream::UpdateSendWindowOffset(QuicStreamOffset new_window) { |
520 if (flow_controller_.UpdateSendWindowOffset(new_window)) { | 507 if (flow_controller_.UpdateSendWindowOffset(new_window)) { |
521 OnCanWrite(); | 508 OnCanWrite(); |
522 } | 509 } |
523 } | 510 } |
524 | 511 |
525 bool ReliableQuicStream::IsFlowControlBlocked() { | 512 bool ReliableQuicStream::IsFlowControlBlocked() { |
526 if (flow_controller_.IsBlocked()) { | 513 if (flow_controller_.IsBlocked()) { |
527 return true; | 514 return true; |
528 } | 515 } |
529 return stream_contributes_to_connection_flow_control_ && | 516 return stream_contributes_to_connection_flow_control_ && |
530 connection_flow_controller_->IsBlocked(); | 517 connection_flow_controller_->IsBlocked(); |
531 } | 518 } |
532 | 519 |
533 } // namespace net | 520 } // namespace net |
OLD | NEW |