// 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