| // Copyright (c) 2013 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/pacing_sender.h" |
| |
| namespace net { |
| |
| PacingSender::PacingSender(SendAlgorithmInterface* sender, |
| QuicTime::Delta alarm_granularity) |
| : sender_(sender), |
| alarm_granularity_(alarm_granularity), |
| next_packet_send_time_(QuicTime::Zero()), |
| was_last_send_delayed_(false), |
| max_segment_size_(kDefaultMaxPacketSize) { |
| } |
| |
| PacingSender::~PacingSender() {} |
| |
| void PacingSender::SetMaxPacketSize(QuicByteCount max_packet_size) { |
| max_segment_size_ = max_packet_size; |
| sender_->SetMaxPacketSize(max_packet_size); |
| } |
| |
| void PacingSender::SetFromConfig(const QuicConfig& config, bool is_server) { |
| sender_->SetFromConfig(config, is_server); |
| } |
| |
| void PacingSender::OnIncomingQuicCongestionFeedbackFrame( |
| const QuicCongestionFeedbackFrame& feedback, |
| QuicTime feedback_receive_time, |
| const SendAlgorithmInterface::SentPacketsMap& sent_packets) { |
| sender_->OnIncomingQuicCongestionFeedbackFrame( |
| feedback, feedback_receive_time, sent_packets); |
| } |
| |
| void PacingSender::OnPacketAcked( |
| QuicPacketSequenceNumber acked_sequence_number, |
| QuicByteCount acked_bytes, |
| QuicTime::Delta rtt) { |
| sender_->OnPacketAcked(acked_sequence_number, acked_bytes, rtt); |
| } |
| |
| void PacingSender::OnPacketLost(QuicPacketSequenceNumber sequence_number, |
| QuicTime ack_receive_time) { |
| sender_->OnPacketLost(sequence_number, ack_receive_time); |
| } |
| |
| bool PacingSender::OnPacketSent( |
| QuicTime sent_time, |
| QuicPacketSequenceNumber sequence_number, |
| QuicByteCount bytes, |
| TransmissionType transmission_type, |
| HasRetransmittableData has_retransmittable_data) { |
| // Only pace data packets. |
| if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) { |
| // The next packet should be sent as soon as the current packets has |
| // been transferred. We pace at twice the rate of the underlying |
| // sender's bandwidth estimate to help ensure that pacing doesn't become |
| // a bottleneck. |
| const float kPacingAggression = 2; |
| QuicTime::Delta delay = |
| BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes); |
| next_packet_send_time_ = next_packet_send_time_.Add(delay); |
| } |
| return sender_->OnPacketSent(sent_time, sequence_number, bytes, |
| transmission_type, has_retransmittable_data); |
| } |
| |
| void PacingSender::OnRetransmissionTimeout() { |
| sender_->OnRetransmissionTimeout(); |
| } |
| |
| void PacingSender::OnPacketAbandoned(QuicPacketSequenceNumber sequence_number, |
| QuicByteCount abandoned_bytes) { |
| sender_->OnPacketAbandoned(sequence_number, abandoned_bytes); |
| } |
| |
| QuicTime::Delta PacingSender::TimeUntilSend( |
| QuicTime now, |
| TransmissionType transmission_type, |
| HasRetransmittableData has_retransmittable_data, |
| IsHandshake handshake) { |
| QuicTime::Delta time_until_send = |
| sender_->TimeUntilSend(now, transmission_type, |
| has_retransmittable_data, handshake); |
| if (!time_until_send.IsZero()) { |
| DCHECK(time_until_send.IsInfinite()); |
| // The underlying sender prevents sending. |
| return time_until_send; |
| } |
| |
| if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) { |
| // Don't pace ACK packets, since they do not count against CWND and do not |
| // cause CWND to grow. |
| return QuicTime::Delta::Zero(); |
| } |
| |
| if (!was_last_send_delayed_ && |
| (!next_packet_send_time_.IsInitialized() || |
| now > next_packet_send_time_.Add(alarm_granularity_))) { |
| // An alarm did not go off late, instead the application is "slow" |
| // delivering data. In this case, we restrict the amount of lost time |
| // that we can make up for. |
| next_packet_send_time_ = now.Subtract(alarm_granularity_); |
| } |
| |
| // If the end of the epoch is far enough in the future, delay the send. |
| if (next_packet_send_time_ > now.Add(alarm_granularity_)) { |
| was_last_send_delayed_ = true; |
| DVLOG(1) << "Delaying packet: " |
| << next_packet_send_time_.Subtract(now).ToMicroseconds(); |
| return next_packet_send_time_.Subtract(now); |
| } |
| |
| // Sent it immediately. The epoch end will be adjusted in OnPacketSent. |
| was_last_send_delayed_ = false; |
| DVLOG(1) << "Sending packet now"; |
| return QuicTime::Delta::Zero(); |
| } |
| |
| QuicBandwidth PacingSender::BandwidthEstimate() const { |
| return sender_->BandwidthEstimate(); |
| } |
| |
| QuicTime::Delta PacingSender::SmoothedRtt() const { |
| return sender_->SmoothedRtt(); |
| } |
| |
| QuicTime::Delta PacingSender::RetransmissionDelay() const { |
| return sender_->RetransmissionDelay(); |
| } |
| |
| QuicByteCount PacingSender::GetCongestionWindow() const { |
| return sender_->GetCongestionWindow(); |
| } |
| |
| } // namespace net |