blob: 66eea780f135d8f52a015d6f5d3fa6bce678e430 [file] [log] [blame]
// Copyright 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/quic_sent_packet_manager.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "net/quic/quic_ack_notifier_manager.h"
using std::make_pair;
// TODO(rtenneti): Remove this.
// Do not flip this flag until the flakiness of the
// net/tools/quic/end_to_end_test is fixed.
// If true, then QUIC connections will track the retransmission history of a
// packet so that an ack of a previous transmission will ack the data of all
// other transmissions.
bool FLAGS_track_retransmission_history = false;
namespace net {
#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
QuicSentPacketManager::HelperInterface::~HelperInterface() {
}
QuicSentPacketManager::QuicSentPacketManager(bool is_server,
HelperInterface* helper)
: is_server_(is_server),
helper_(helper) {
}
QuicSentPacketManager::~QuicSentPacketManager() {
STLDeleteValues(&unacked_packets_);
while (!previous_transmissions_map_.empty()) {
SequenceNumberSet* previous_transmissions =
previous_transmissions_map_.begin()->second;
for (SequenceNumberSet::const_iterator it = previous_transmissions->begin();
it != previous_transmissions->end(); ++it) {
DCHECK(ContainsKey(previous_transmissions_map_, *it));
previous_transmissions_map_.erase(*it);
}
delete previous_transmissions;
}
}
void QuicSentPacketManager::OnSerializedPacket(
const SerializedPacket& serialized_packet, QuicTime serialized_time) {
if (serialized_packet.packet->is_fec_packet()) {
DCHECK(!serialized_packet.retransmittable_frames);
unacked_fec_packets_.insert(make_pair(
serialized_packet.sequence_number, serialized_time));
return;
}
if (serialized_packet.retransmittable_frames == NULL) {
// Don't track ack/congestion feedback packets.
return;
}
ack_notifier_manager_.OnSerializedPacket(serialized_packet);
DCHECK(unacked_packets_.empty() ||
unacked_packets_.rbegin()->first <
serialized_packet.sequence_number);
unacked_packets_[serialized_packet.sequence_number] =
serialized_packet.retransmittable_frames;
retransmission_map_[serialized_packet.sequence_number] =
RetransmissionInfo(serialized_packet.sequence_number,
serialized_packet.sequence_number_length);
}
void QuicSentPacketManager::OnRetransmittedPacket(
QuicPacketSequenceNumber old_sequence_number,
QuicPacketSequenceNumber new_sequence_number) {
DCHECK(ContainsKey(unacked_packets_, old_sequence_number));
DCHECK(ContainsKey(retransmission_map_, old_sequence_number));
DCHECK(ContainsKey(pending_retransmissions_, old_sequence_number));
DCHECK(unacked_packets_.empty() ||
unacked_packets_.rbegin()->first < new_sequence_number);
pending_retransmissions_.erase(old_sequence_number);
RetransmissionInfo retransmission_info(
new_sequence_number, GetSequenceNumberLength(old_sequence_number));
retransmission_info.number_retransmissions =
retransmission_map_[old_sequence_number].number_retransmissions + 1;
retransmission_map_.erase(old_sequence_number);
retransmission_map_[new_sequence_number] = retransmission_info;
RetransmittableFrames* frames = unacked_packets_[old_sequence_number];
DCHECK(frames);
// A notifier may be waiting to hear about ACKs for the original sequence
// number. Inform them that the sequence number has changed.
ack_notifier_manager_.UpdateSequenceNumber(old_sequence_number,
new_sequence_number);
if (FLAGS_track_retransmission_history) {
// We keep the old packet in the unacked packet list until it, or one of
// the retransmissions of it are acked.
unacked_packets_[old_sequence_number] = NULL;
} else {
unacked_packets_.erase(old_sequence_number);
}
unacked_packets_[new_sequence_number] = frames;
if (!FLAGS_track_retransmission_history) {
return;
}
// Keep track of all sequence numbers that this packet
// has been transmitted as.
SequenceNumberSet* previous_transmissions;
PreviousTransmissionMap::iterator it =
previous_transmissions_map_.find(old_sequence_number);
if (it == previous_transmissions_map_.end()) {
// This is the first retransmission of this packet, so create a new entry.
previous_transmissions = new SequenceNumberSet;
previous_transmissions_map_[old_sequence_number] = previous_transmissions;
previous_transmissions->insert(old_sequence_number);
} else {
// Otherwise, use the existing entry.
previous_transmissions = it->second;
}
previous_transmissions->insert(new_sequence_number);
previous_transmissions_map_[new_sequence_number] = previous_transmissions;
DCHECK(HasRetransmittableFrames(new_sequence_number));
}
void QuicSentPacketManager::OnIncomingAck(
const ReceivedPacketInfo& received_info,
bool is_truncated_ack) {
HandleAckForSentPackets(received_info, is_truncated_ack);
HandleAckForSentFecPackets(received_info);
}
void QuicSentPacketManager::DiscardUnackedPacket(
QuicPacketSequenceNumber sequence_number) {
MarkPacketReceivedByPeer(sequence_number);
}
void QuicSentPacketManager::HandleAckForSentPackets(
const ReceivedPacketInfo& received_info,
bool is_truncated_ack) {
// Go through the packets we have not received an ack for and see if this
// incoming_ack shows they've been seen by the peer.
UnackedPacketMap::iterator it = unacked_packets_.begin();
while (it != unacked_packets_.end()) {
QuicPacketSequenceNumber sequence_number = it->first;
if (sequence_number > received_info.largest_observed) {
// These are very new sequence_numbers.
break;
}
if (!IsAwaitingPacket(received_info, sequence_number)) {
// Packet was acked, so remove it from our unacked packet list.
DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
// If data is associated with the most recent transmission of this
// packet, then inform the caller.
it = MarkPacketReceivedByPeer(sequence_number);
// The AckNotifierManager is informed of every ACKed sequence number.
ack_notifier_manager_.OnPacketAcked(sequence_number);
continue;
}
// The peer got packets after this sequence number. This is an explicit
// nack.
// TODO(rch): move this to the congestion manager, and fix the logic.
// This is a packet which we planned on retransmitting and has not been
// seen at the time of this ack being sent out. See if it's our new
// lowest unacked packet.
DVLOG(1) << ENDPOINT << "still missing packet " << sequence_number;
++it;
RetransmissionMap::iterator retransmission_it =
retransmission_map_.find(sequence_number);
if (retransmission_it == retransmission_map_.end()) {
continue;
}
size_t nack_count = ++(retransmission_it->second.number_nacks);
helper_->OnPacketNacked(sequence_number, nack_count);
}
// If we have received a trunacted ack, then we need to
// clear out some previous transmissions to allow the peer
// to actually ACK new packets.
if (is_truncated_ack) {
size_t num_to_clear = received_info.missing_packets.size() / 2;
UnackedPacketMap::iterator it = unacked_packets_.begin();
while (it != unacked_packets_.end() && num_to_clear > 0) {
QuicPacketSequenceNumber sequence_number = it->first;
++it;
// If this is not a previous transmission then there is no point
// in clearing out any further packets, because it will not
// affect the high water mark.
if (!IsPreviousTransmission(sequence_number)) {
break;
}
DCHECK(ContainsKey(previous_transmissions_map_, sequence_number));
DCHECK(!ContainsKey(retransmission_map_, sequence_number));
DCHECK(!HasRetransmittableFrames(sequence_number));
unacked_packets_.erase(sequence_number);
SequenceNumberSet* previous_transmissions =
previous_transmissions_map_[sequence_number];
previous_transmissions_map_.erase(sequence_number);
previous_transmissions->erase(sequence_number);
if (previous_transmissions->size() == 1) {
previous_transmissions_map_.erase(*previous_transmissions->begin());
delete previous_transmissions;
}
--num_to_clear;
}
}
}
bool QuicSentPacketManager::HasRetransmittableFrames(
QuicPacketSequenceNumber sequence_number) const {
if (!ContainsKey(unacked_packets_, sequence_number)) {
return false;
}
return unacked_packets_.find(sequence_number)->second != NULL;
}
bool QuicSentPacketManager::MarkForRetransmission(
QuicPacketSequenceNumber sequence_number,
TransmissionType transmission_type) {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
if (!HasRetransmittableFrames(sequence_number)) {
return false;
}
// If it's already in the retransmission map, don't add it again, just let
// the prior retransmission request win out.
if (ContainsKey(pending_retransmissions_, sequence_number)) {
return true;
}
pending_retransmissions_[sequence_number] = transmission_type;
return true;
}
bool QuicSentPacketManager::HasPendingRetransmissions() const {
return !pending_retransmissions_.empty();
}
QuicSentPacketManager::PendingRetransmission
QuicSentPacketManager::NextPendingRetransmission() {
DCHECK(!pending_retransmissions_.empty());
QuicPacketSequenceNumber sequence_number =
pending_retransmissions_.begin()->first;
DCHECK(ContainsKey(unacked_packets_, sequence_number));
DCHECK(unacked_packets_[sequence_number]);
return PendingRetransmission(sequence_number,
pending_retransmissions_.begin()->second,
GetRetransmittableFrames(sequence_number),
GetSequenceNumberLength(sequence_number));
}
bool QuicSentPacketManager::IsPreviousTransmission(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
PreviousTransmissionMap::const_iterator it =
previous_transmissions_map_.find(sequence_number);
if (it == previous_transmissions_map_.end()) {
return false;
}
SequenceNumberSet* previous_transmissions = it->second;
DCHECK(!previous_transmissions->empty());
return *previous_transmissions->rbegin() != sequence_number;
}
QuicPacketSequenceNumber QuicSentPacketManager::GetMostRecentTransmission(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
PreviousTransmissionMap::const_iterator it =
previous_transmissions_map_.find(sequence_number);
if (it == previous_transmissions_map_.end()) {
return sequence_number;
}
SequenceNumberSet* previous_transmissions =
previous_transmissions_map_.find(sequence_number)->second;
DCHECK(!previous_transmissions->empty());
return *previous_transmissions->rbegin();
}
QuicSentPacketManager::UnackedPacketMap::iterator
QuicSentPacketManager::MarkPacketReceivedByPeer(
QuicPacketSequenceNumber sequence_number) {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
UnackedPacketMap::iterator next_unacked =
unacked_packets_.find(sequence_number);
++next_unacked;
// If this packet has never been retransmitted, then simply drop it.
if (!ContainsKey(previous_transmissions_map_, sequence_number)) {
DiscardPacket(sequence_number);
return next_unacked;
}
SequenceNumberSet* previous_transmissions =
previous_transmissions_map_.find(sequence_number)->second;
SequenceNumberSet::reverse_iterator previous_transmissions_it
= previous_transmissions->rbegin();
DCHECK(previous_transmissions_it != previous_transmissions->rend());
QuicPacketSequenceNumber new_packet = *previous_transmissions_it;
bool is_new_packet = new_packet == sequence_number;
if (is_new_packet) {
DiscardPacket(new_packet);
} else {
if (next_unacked->first == new_packet) {
++next_unacked;
}
// If we have received an ack for a previous transmission of a packet,
// we want to keep the "new" transmission of the packet unacked,
// but prevent the data from being retransmitted.
delete unacked_packets_[new_packet];
unacked_packets_[new_packet] = NULL;
pending_retransmissions_.erase(new_packet);
}
previous_transmissions_map_.erase(new_packet);
// Clear out information all previous transmissions.
++previous_transmissions_it;
while (previous_transmissions_it != previous_transmissions->rend()) {
QuicPacketSequenceNumber previous_transmission = *previous_transmissions_it;
++previous_transmissions_it;
DCHECK(ContainsKey(previous_transmissions_map_, previous_transmission));
previous_transmissions_map_.erase(previous_transmission);
if (next_unacked != unacked_packets_.end() &&
next_unacked->first == previous_transmission) {
++next_unacked;
}
DiscardPacket(previous_transmission);
}
delete previous_transmissions;
next_unacked = unacked_packets_.begin();
while (next_unacked != unacked_packets_.end() &&
next_unacked->first < sequence_number) {
++next_unacked;
}
return next_unacked;
}
void QuicSentPacketManager::DiscardPacket(
QuicPacketSequenceNumber sequence_number) {
UnackedPacketMap::iterator unacked_it =
unacked_packets_.find(sequence_number);
// Packet was not meant to be retransmitted.
if (unacked_it == unacked_packets_.end()) {
DCHECK(!ContainsKey(retransmission_map_, sequence_number));
return;
}
// Delete the unacked packet.
delete unacked_it->second;
unacked_packets_.erase(unacked_it);
retransmission_map_.erase(sequence_number);
pending_retransmissions_.erase(sequence_number);
return;
}
void QuicSentPacketManager::HandleAckForSentFecPackets(
const ReceivedPacketInfo& received_info) {
UnackedFecPacketMap::iterator it = unacked_fec_packets_.begin();
while (it != unacked_fec_packets_.end()) {
QuicPacketSequenceNumber sequence_number = it->first;
if (sequence_number > received_info.largest_observed) {
break;
}
if (!IsAwaitingPacket(received_info, sequence_number)) {
DVLOG(1) << ENDPOINT << "Got an ack for fec packet: " << sequence_number;
unacked_fec_packets_.erase(it++);
} else {
// TODO(rch): treat these packets more consistently. They should
// be subject to NACK and RTO based loss. (Thought obviously, they
// should not be retransmitted.)
DVLOG(1) << ENDPOINT << "Still missing ack for fec packet: "
<< sequence_number;
++it;
}
}
}
void QuicSentPacketManager::DiscardFecPacket(
QuicPacketSequenceNumber sequence_number) {
DCHECK(ContainsKey(unacked_fec_packets_, sequence_number));
unacked_fec_packets_.erase(sequence_number);
}
bool QuicSentPacketManager::IsRetransmission(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(HasRetransmittableFrames(sequence_number));
RetransmissionMap::const_iterator it =
retransmission_map_.find(sequence_number);
return it != retransmission_map_.end() &&
it->second.number_retransmissions > 0;
}
size_t QuicSentPacketManager::GetRetransmissionCount(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(HasRetransmittableFrames(sequence_number));
DCHECK(ContainsKey(retransmission_map_, sequence_number));
RetransmissionMap::const_iterator it =
retransmission_map_.find(sequence_number);
return it->second.number_retransmissions;
}
bool QuicSentPacketManager::IsUnacked(
QuicPacketSequenceNumber sequence_number) const {
return ContainsKey(unacked_packets_, sequence_number);
}
bool QuicSentPacketManager::IsFecUnacked(
QuicPacketSequenceNumber sequence_number) const {
return ContainsKey(unacked_fec_packets_, sequence_number);
}
const RetransmittableFrames& QuicSentPacketManager::GetRetransmittableFrames(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
DCHECK(ContainsKey(retransmission_map_, sequence_number));
return *unacked_packets_.find(sequence_number)->second;
}
QuicSequenceNumberLength QuicSentPacketManager::GetSequenceNumberLength(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
DCHECK(ContainsKey(retransmission_map_, sequence_number));
return retransmission_map_.find(
sequence_number)->second.sequence_number_length;
}
QuicTime QuicSentPacketManager::GetFecSentTime(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_fec_packets_, sequence_number));
return unacked_fec_packets_.find(sequence_number)->second;
}
bool QuicSentPacketManager::HasUnackedPackets() const {
return !unacked_packets_.empty();
}
size_t QuicSentPacketManager::GetNumUnackedPackets() const {
return unacked_packets_.size();
}
bool QuicSentPacketManager::HasUnackedFecPackets() const {
return !unacked_fec_packets_.empty();
}
QuicPacketSequenceNumber
QuicSentPacketManager::GetLeastUnackedSentPacket() const {
if (unacked_packets_.empty()) {
// If there are no unacked packets, set the least unacked packet to
// the sequence number of the next packet sent.
return helper_->GetNextPacketSequenceNumber();
}
return unacked_packets_.begin()->first;
}
QuicPacketSequenceNumber
QuicSentPacketManager::GetLeastUnackedFecPacket() const {
if (unacked_fec_packets_.empty()) {
// If there are no unacked packets, set the least unacked packet to
// the sequence number of the next packet sent.
return helper_->GetNextPacketSequenceNumber();
}
return unacked_fec_packets_.begin()->first;
}
SequenceNumberSet QuicSentPacketManager::GetUnackedPackets() const {
SequenceNumberSet unacked_packets;
for (UnackedPacketMap::const_iterator it = unacked_packets_.begin();
it != unacked_packets_.end(); ++it) {
unacked_packets.insert(it->first);
}
return unacked_packets;
}
} // namespace net