| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/quic/congestion_control/fix_rate_sender.h" |
| |
| #include <math.h> |
| |
| #include "base/logging.h" |
| #include "base/time.h" |
| #include "net/quic/quic_protocol.h" |
| |
| namespace { |
| const int kInitialBitrate = 100000; // In bytes per second. |
| const uint64 kWindowSizeUs = 10000; // 10 ms. |
| } |
| |
| namespace net { |
| |
| FixRateSender::FixRateSender(const QuicClock* clock) |
| : bitrate_in_bytes_per_s_(kInitialBitrate), |
| fix_rate_leaky_bucket_(clock, kInitialBitrate), |
| paced_sender_(clock, kInitialBitrate), |
| bytes_in_flight_(0) { |
| DVLOG(1) << "FixRateSender"; |
| } |
| |
| void FixRateSender::OnIncomingQuicCongestionFeedbackFrame( |
| const QuicCongestionFeedbackFrame& feedback) { |
| DCHECK(feedback.type == kFixRate) << |
| "Invalid incoming CongestionFeedbackType:" << feedback.type; |
| if (feedback.type == kFixRate) { |
| bitrate_in_bytes_per_s_ = |
| feedback.fix_rate.bitrate_in_bytes_per_second; |
| fix_rate_leaky_bucket_.SetDrainingRate(bitrate_in_bytes_per_s_); |
| paced_sender_.UpdateBandwidthEstimate(bitrate_in_bytes_per_s_); |
| } |
| // Silently ignore invalid messages in release mode. |
| } |
| |
| void FixRateSender::OnIncomingAck( |
| QuicPacketSequenceNumber /*acked_sequence_number*/, |
| size_t bytes_acked, |
| QuicTime::Delta /*rtt*/) { |
| bytes_in_flight_ -= bytes_acked; |
| } |
| |
| void FixRateSender::OnIncomingLoss(int /*number_of_lost_packets*/) { |
| // Ignore losses for fix rate sender. |
| } |
| |
| void FixRateSender::SentPacket(QuicPacketSequenceNumber /*sequence_number*/, |
| size_t bytes, |
| bool retransmit) { |
| fix_rate_leaky_bucket_.Add(bytes); |
| paced_sender_.SentPacket(bytes); |
| if (!retransmit) { |
| bytes_in_flight_ += bytes; |
| } |
| } |
| |
| QuicTime::Delta FixRateSender::TimeUntilSend(bool /*retransmit*/) { |
| if (CongestionWindow() > fix_rate_leaky_bucket_.BytesPending()) { |
| if (CongestionWindow() <= bytes_in_flight_) { |
| // We need an ack before we send more. |
| return QuicTime::Delta::Infinite(); |
| } |
| QuicTime::Delta zero_time; |
| return paced_sender_.TimeUntilSend(zero_time); |
| } |
| QuicTime::Delta time_remaining = fix_rate_leaky_bucket_.TimeRemaining(); |
| if (time_remaining.IsZero()) { |
| // We need an ack before we send more. |
| return QuicTime::Delta::Infinite(); |
| } |
| return paced_sender_.TimeUntilSend(time_remaining); |
| } |
| |
| size_t FixRateSender::CongestionWindow() { |
| size_t window_size = bitrate_in_bytes_per_s_ * kWindowSizeUs / |
| base::Time::kMicrosecondsPerSecond; |
| // Make sure window size is not less than a packet. |
| return std::max(kMaxPacketSize, window_size); |
| } |
| |
| size_t FixRateSender::AvailableCongestionWindow() { |
| size_t congestion_window = CongestionWindow(); |
| if (bytes_in_flight_ >= congestion_window) { |
| return 0; |
| } |
| size_t available_congestion_window = congestion_window - bytes_in_flight_; |
| return paced_sender_.AvailableWindow(available_congestion_window); |
| } |
| |
| int FixRateSender::BandwidthEstimate() { |
| return bitrate_in_bytes_per_s_; |
| } |
| |
| } // namespace net |