Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(624)

Unified Diff: net/quic/quic_connection.cc

Issue 23691073: Land Recent QUIC changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Compiler/unittests fix Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_helper_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_connection.cc
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 0633f90fa034ca87c60ab25754099d482b7db811..7417bd435a19cdfd47d6d3f54567a1cc13e9de13 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -33,7 +33,7 @@ const QuicPacketSequenceNumber kMaxPacketGap = 5000;
// We want to make sure if we get a large nack packet, we don't queue up too
// many packets at once. 10 is arbitrary.
-const int kMaxRetransmissionsPerAck = 10;
+const size_t kMaxRetransmissionsPerAck = 10;
// TCP retransmits after 2 nacks. We allow for a third in case of out-of-order
// delivery.
@@ -126,6 +126,21 @@ class TimeoutAlarm : public QuicAlarm::Delegate {
QuicConnection* connection_;
};
+// Indicates if any of the frames are intended to be sent with FORCE.
+// Returns true when one of the frames is a CONNECTION_CLOSE_FRAME.
+net::QuicConnection::Force HasForcedFrames(
+ const RetransmittableFrames* retransmittable_frames) {
+ if (!retransmittable_frames) {
+ return net::QuicConnection::NO_FORCE;
+ }
+ for (size_t i = 0; i < retransmittable_frames->frames().size(); ++i) {
+ if (retransmittable_frames->frames()[i].type == CONNECTION_CLOSE_FRAME) {
+ return net::QuicConnection::FORCE;
+ }
+ }
+ return net::QuicConnection::NO_FORCE;
+}
+
} // namespace
// TODO(rch): Remove this.
@@ -169,6 +184,7 @@ QuicConnection::QuicConnection(QuicGuid guid,
time_of_last_received_packet_(clock_->ApproximateNow()),
time_of_last_sent_packet_(clock_->ApproximateNow()),
congestion_manager_(clock_, kTCP),
+ sent_packet_manager_(is_server, this),
version_negotiation_state_(START_NEGOTIATION),
max_packets_per_retransmission_alarm_(kMaxPacketsPerRetransmissionAlarm),
is_server_(is_server),
@@ -193,7 +209,6 @@ QuicConnection::QuicConnection(QuicGuid guid,
QuicConnection::~QuicConnection() {
STLDeleteElements(&ack_notifiers_);
STLDeleteElements(&undecryptable_packets_);
- STLDeleteValues(&unacked_packets_);
STLDeleteValues(&group_map_);
for (QueuedPacketList::iterator it = queued_packets_.begin();
it != queued_packets_.end(); ++it) {
@@ -437,6 +452,17 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
SendConnectionClose(QUIC_INVALID_ACK_DATA);
return false;
}
+
+ // Reset the RTO timeout for each packet when an ack is received.
+ if (retransmission_alarm_->IsSet()) {
+ retransmission_alarm_->Cancel();
+ QuicTime::Delta retransmission_delay =
+ congestion_manager_.GetRetransmissionDelay(
+ sent_packet_manager_.GetNumUnackedPackets(), 0);
+ retransmission_alarm_->Set(clock_->ApproximateNow().Add(
+ retransmission_delay));
+ }
+
last_ack_frames_.push_back(incoming_ack);
return connected_;
}
@@ -456,12 +482,11 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
sent_entropy_manager_.ClearEntropyBefore(
received_packet_manager_.least_packet_awaited_by_peer() - 1);
+ retransmitted_nacked_packet_count_ = 0;
SequenceNumberSet acked_packets;
- HandleAckForSentPackets(incoming_ack, &acked_packets);
- HandleAckForSentFecPackets(incoming_ack, &acked_packets);
+ sent_packet_manager_.HandleAckForSentPackets(incoming_ack, &acked_packets);
+ sent_packet_manager_.HandleAckForSentFecPackets(incoming_ack, &acked_packets);
if (acked_packets.size() > 0) {
- visitor_->OnAck(acked_packets);
-
// Inform all the registered AckNotifiers of the new ACKs.
// TODO(rjshade): Make this more efficient by maintaining a mapping of
// <sequence number, set<AckNotifierList>> so that OnAck
@@ -479,6 +504,13 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
}
}
}
+ // Clear the earliest retransmission timeouts that are no longer unacked to
+ // ensure the priority queue doesn't become too large.
+ while (!retransmission_timeouts_.empty() &&
+ !sent_packet_manager_.IsUnacked(
+ retransmission_timeouts_.top().sequence_number)) {
+ retransmission_timeouts_.pop();
+ }
congestion_manager_.OnIncomingAckFrame(incoming_ack,
time_of_last_received_packet_);
}
@@ -567,73 +599,6 @@ bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
return true;
}
-void QuicConnection::HandleAckForSentPackets(const QuicAckFrame& incoming_ack,
- SequenceNumberSet* acked_packets) {
- int retransmitted_packets = 0;
- // 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_packet_manager_.peer_largest_observed_packet()) {
- // These are very new sequence_numbers.
- break;
- }
- RetransmittableFrames* unacked = it->second;
- if (!IsAwaitingPacket(incoming_ack.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;
- acked_packets->insert(sequence_number);
- delete unacked;
- unacked_packets_.erase(it++);
- retransmission_map_.erase(sequence_number);
- } else {
- // 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;
- // The peer got packets after this sequence number. This is an explicit
- // nack.
- RetransmissionMap::iterator retransmission_it =
- retransmission_map_.find(sequence_number);
- ++(retransmission_it->second.number_nacks);
- if (retransmission_it->second.number_nacks >=
- kNumberOfNacksBeforeRetransmission &&
- retransmitted_packets < kMaxRetransmissionsPerAck) {
- ++retransmitted_packets;
- DVLOG(1) << ENDPOINT << "Trying to retransmit packet "
- << sequence_number
- << " as it has been nacked 3 or more times.";
- // RetransmitPacket will retransmit with a new sequence_number.
- RetransmitPacket(sequence_number);
- }
- }
- }
-}
-
-void QuicConnection::HandleAckForSentFecPackets(
- const QuicAckFrame& incoming_ack, SequenceNumberSet* acked_packets) {
- UnackedPacketMap::iterator it = unacked_fec_packets_.begin();
- while (it != unacked_fec_packets_.end()) {
- QuicPacketSequenceNumber sequence_number = it->first;
- if (sequence_number >
- received_packet_manager_.peer_largest_observed_packet()) {
- break;
- }
- if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
- DVLOG(1) << ENDPOINT << "Got an ack for fec packet: " << sequence_number;
- acked_packets->insert(sequence_number);
- unacked_fec_packets_.erase(it++);
- } else {
- DVLOG(1) << ENDPOINT << "Still missing ack for fec packet: "
- << sequence_number;
- ++it;
- }
- }
-}
-
void QuicConnection::OnFecData(const QuicFecData& fec) {
DCHECK_EQ(IN_FEC_GROUP, last_header_.is_in_fec_group);
DCHECK_NE(0u, last_header_.fec_group);
@@ -703,9 +668,8 @@ void QuicConnection::OnPacketComplete() {
// from unacket_packets_, increasing the least_unacked.
const bool last_packet_should_instigate_ack = ShouldLastPacketInstigateAck();
- if ((last_stream_frames_.empty() ||
- visitor_->OnPacket(self_address_, peer_address_,
- last_header_, last_stream_frames_))) {
+ if (last_stream_frames_.empty() ||
+ visitor_->OnStreamFrames(last_stream_frames_)) {
received_packet_manager_.RecordPacketReceived(
last_header_, time_of_last_received_packet_);
}
@@ -763,13 +727,10 @@ bool QuicConnection::ShouldLastPacketInstigateAck() {
// the high water mark.
if (!last_ack_frames_.empty() &&
!last_ack_frames_.back().received_info.missing_packets.empty() &&
- !unacked_packets_.empty()) {
- if (unacked_packets_.begin()->first >
- *last_ack_frames_.back().received_info.missing_packets.begin()) {
- return true;
- }
+ sent_packet_manager_.HasUnackedPackets()) {
+ return sent_packet_manager_.GetLeastUnackedSentPacket() >
+ *last_ack_frames_.back().received_info.missing_packets.begin();
}
-
return false;
}
@@ -821,11 +782,13 @@ void QuicConnection::SendVersionNegotiationPacket() {
delete encrypted;
}
-QuicConsumedData QuicConnection::SendvStreamData(QuicStreamId id,
- const struct iovec* iov,
- int count,
- QuicStreamOffset offset,
- bool fin) {
+QuicConsumedData QuicConnection::SendvStreamDataInner(
+ QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckNotifier* notifier) {
// TODO(ianswett): Further improve sending by passing the iovec down
// instead of batching into multiple stream frames in a single packet.
const bool already_in_batch_mode = packet_generator_.InBatchMode();
@@ -833,31 +796,37 @@ QuicConsumedData QuicConnection::SendvStreamData(QuicStreamId id,
size_t bytes_written = 0;
bool fin_consumed = false;
- for (int i = 0; i < count; ++i) {
- bool send_fin = fin && (i == count - 1);
+
+ for (int i = 0; i < iov_count; ++i) {
+ bool send_fin = fin && (i == iov_count - 1);
if (!send_fin && iov[i].iov_len == 0) {
LOG(DFATAL) << "Attempt to send empty stream frame";
}
- QuicConsumedData data_consumed = packet_generator_.ConsumeData(
- id,
- StringPiece(static_cast<char*>(iov[i].iov_base), iov[i].iov_len),
- offset + bytes_written,
- send_fin);
- DCHECK_LE(data_consumed.bytes_consumed, numeric_limits<uint32>::max());
- bytes_written += data_consumed.bytes_consumed;
- fin_consumed = data_consumed.fin_consumed;
+
+ StringPiece data(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
+ int currentOffset = offset + bytes_written;
+ QuicConsumedData consumed_data =
+ packet_generator_.ConsumeData(id,
+ data,
+ currentOffset,
+ send_fin,
+ notifier);
+
+ DCHECK_LE(consumed_data.bytes_consumed, numeric_limits<uint32>::max());
+ bytes_written += consumed_data.bytes_consumed;
+ fin_consumed = consumed_data.fin_consumed;
// If no bytes were consumed, bail now, because the stream can not write
// more data.
- if (data_consumed.bytes_consumed < iov[i].iov_len) {
+ if (consumed_data.bytes_consumed < iov[i].iov_len) {
break;
}
}
// Handle the 0 byte write properly.
- if (count == 0) {
+ if (iov_count == 0) {
DCHECK(fin);
- QuicConsumedData data_consumed = packet_generator_.ConsumeData(
- id, StringPiece(), offset, fin);
- fin_consumed = data_consumed.fin_consumed;
+ QuicConsumedData consumed_data = packet_generator_.ConsumeData(
+ id, StringPiece(), offset, fin, NULL);
+ fin_consumed = consumed_data.fin_consumed;
}
// Leave the generator in the original batch state.
@@ -865,23 +834,33 @@ QuicConsumedData QuicConnection::SendvStreamData(QuicStreamId id,
packet_generator_.FinishBatchOperations();
}
DCHECK_EQ(already_in_batch_mode, packet_generator_.InBatchMode());
+
return QuicConsumedData(bytes_written, fin_consumed);
}
-QuicConsumedData QuicConnection::SendStreamDataAndNotifyWhenAcked(
+QuicConsumedData QuicConnection::SendvStreamData(QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ QuicStreamOffset offset,
+ bool fin) {
+ return SendvStreamDataInner(id, iov, iov_count, offset, fin, NULL);
+}
+
+QuicConsumedData QuicConnection::SendvStreamDataAndNotifyWhenAcked(
QuicStreamId id,
- StringPiece data,
+ const struct iovec* iov,
+ int iov_count,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier::DelegateInterface* delegate) {
- if (!fin && data.empty()) {
+ if (!fin && iov_count == 0) {
LOG(DFATAL) << "Attempt to send empty stream frame";
}
// This notifier will be deleted in ProcessAckFrame once it has seen ACKs for
// all the consumed data (or below if no data was consumed).
QuicAckNotifier* notifier = new QuicAckNotifier(delegate);
QuicConsumedData consumed_data =
- packet_generator_.ConsumeData(id, data, offset, fin, notifier);
+ SendvStreamDataInner(id, iov, iov_count, offset, fin, notifier);
if (consumed_data.bytes_consumed > 0) {
// If some data was consumed, then the delegate should be registered for
@@ -970,21 +949,14 @@ bool QuicConnection::DoWrite() {
DCHECK(!write_blocked_);
WriteQueuedPackets();
- // We are postulating if we are not yet forward secure, the visitor may have
- // handshake messages to send.
- // TODO(jar): add a new visitor_ method that returns whether it has handshake
- // messages to send, and call it and pass the return value to each CanWrite
- // call.
- const IsHandshake maybe_handshake =
- encryption_level_ == ENCRYPTION_FORWARD_SECURE ? NOT_HANDSHAKE
- : IS_HANDSHAKE;
-
+ IsHandshake pending_handshake = visitor_->HasPendingHandshake() ?
+ IS_HANDSHAKE : NOT_HANDSHAKE;
// Sending queued packets may have caused the socket to become write blocked,
// or the congestion manager to prohibit sending. If we've sent everything
// we had queued and we're still not blocked, let the visitor know it can
// write more.
if (CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
- maybe_handshake)) {
+ pending_handshake)) {
const bool already_in_batch_mode = packet_generator_.InBatchMode();
if (!already_in_batch_mode) {
packet_generator_.StartBatchOperations();
@@ -996,12 +968,11 @@ bool QuicConnection::DoWrite() {
// After the visitor writes, it may have caused the socket to become write
// blocked or the congestion manager to prohibit sending, so check again.
- // TODO(jar): we need to pass NOT_HANDSHAKE instead of maybe_handshake to
- // this CanWrite call to avoid getting into an infinite loop calling
- // DoWrite.
+ pending_handshake = visitor_->HasPendingHandshake() ? IS_HANDSHAKE
+ : NOT_HANDSHAKE;
if (!write_blocked_ && !all_bytes_written &&
CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
+ pending_handshake)) {
// We're not write blocked, but some stream didn't write out all of its
// bytes. Register for 'immediate' resumption so we'll keep writing after
// other quic connections have had a chance to use the socket.
@@ -1035,7 +1006,7 @@ bool QuicConnection::WriteQueuedPackets() {
packet_iterator->sequence_number,
packet_iterator->packet,
packet_iterator->retransmittable,
- NO_FORCE)) {
+ packet_iterator->forced)) {
packet_iterator = queued_packets_.erase(packet_iterator);
} else {
// Continue, because some queued packets may still be writable.
@@ -1049,101 +1020,72 @@ bool QuicConnection::WriteQueuedPackets() {
bool QuicConnection::MaybeRetransmitPacketForRTO(
QuicPacketSequenceNumber sequence_number) {
- DCHECK_EQ(ContainsKey(unacked_packets_, sequence_number),
- ContainsKey(retransmission_map_, sequence_number));
-
- if (!ContainsKey(unacked_packets_, sequence_number)) {
+ if (!sent_packet_manager_.IsUnacked(sequence_number)) {
DVLOG(2) << ENDPOINT << "alarm fired for " << sequence_number
<< " but it has been acked or already retransmitted with"
- << " different sequence number.";
+ << " a different sequence number.";
// So no extra delay is added for this packet.
return true;
}
- RetransmissionMap::iterator retransmission_it =
- retransmission_map_.find(sequence_number);
// If the packet hasn't been acked and we're getting truncated acks, ignore
// any RTO for packets larger than the peer's largest observed packet; it may
// have been received by the peer and just wasn't acked due to the ack frame
// running out of space.
- if (received_truncated_ack_ && sequence_number >
- received_packet_manager_.peer_largest_observed_packet() &&
+ if (received_truncated_ack_ &&
+ sequence_number > GetPeerLargestObservedPacket() &&
// We allow retransmission of already retransmitted packets so that we
// retransmit packets that were retransmissions of the packet with
// sequence number < the largest observed field of the truncated ack.
- retransmission_it->second.number_retransmissions == 0) {
+ !sent_packet_manager_.IsRetransmission(sequence_number)) {
return false;
- } else {
- ++stats_.rto_count;
- RetransmitPacket(sequence_number);
- return true;
}
+
+ ++stats_.rto_count;
+ RetransmitPacket(sequence_number);
+ return true;
}
void QuicConnection::RetransmitUnackedPackets(
RetransmissionType retransmission_type) {
- if (unacked_packets_.empty()) {
+ SequenceNumberSet unacked_packets = sent_packet_manager_.GetUnackedPackets();
+ if (unacked_packets.empty()) {
return;
}
- UnackedPacketMap::iterator next_it = unacked_packets_.begin();
- QuicPacketSequenceNumber end_sequence_number =
- unacked_packets_.rbegin()->first;
- do {
- UnackedPacketMap::iterator current_it = next_it;
- ++next_it;
+ for (SequenceNumberSet::const_iterator unacked_it = unacked_packets.begin();
+ unacked_it != unacked_packets.end(); ++unacked_it) {
+ const RetransmittableFrames& frames =
+ sent_packet_manager_.GetRetransmittableFrames(*unacked_it);
if (retransmission_type == ALL_PACKETS ||
- current_it->second->encryption_level() == ENCRYPTION_INITIAL) {
+ frames.encryption_level() == ENCRYPTION_INITIAL) {
// TODO(satyamshekhar): Think about congestion control here.
// Specifically, about the retransmission count of packets being sent
// proactively to achieve 0 (minimal) RTT.
- RetransmitPacket(current_it->first);
+ RetransmitPacket(*unacked_it);
}
- } while (next_it != unacked_packets_.end() &&
- next_it->first <= end_sequence_number);
+ }
}
void QuicConnection::RetransmitPacket(
QuicPacketSequenceNumber sequence_number) {
- UnackedPacketMap::iterator unacked_it =
- unacked_packets_.find(sequence_number);
- RetransmissionMap::iterator retransmission_it =
- retransmission_map_.find(sequence_number);
- // There should always be an entry corresponding to |sequence_number| in
- // both |retransmission_map_| and |unacked_packets_|. Retransmissions due to
- // RTO for sequence numbers that are already acked or retransmitted are
- // ignored by MaybeRetransmitPacketForRTO.
- DCHECK(unacked_it != unacked_packets_.end());
- DCHECK(retransmission_it != retransmission_map_.end());
- RetransmittableFrames* unacked = unacked_it->second;
+ DCHECK(sent_packet_manager_.IsUnacked(sequence_number));
+
// TODO(pwestin): Need to fix potential issue with FEC and a 1 packet
// congestion window see b/8331807 for details.
congestion_manager_.AbandoningPacket(sequence_number);
+ const RetransmittableFrames& retransmittable_frames =
+ sent_packet_manager_.GetRetransmittableFrames(sequence_number);
+
// Re-packetize the frames with a new sequence number for retransmission.
// Retransmitted data packets do not use FEC, even when it's enabled.
// Retransmitted packets use the same sequence number length as the original.
QuicSequenceNumberLength original_sequence_number_length =
- retransmission_it->second.sequence_number_length;
+ sent_packet_manager_.GetSequenceNumberLength(sequence_number);
SerializedPacket serialized_packet =
- packet_creator_.ReserializeAllFrames(unacked->frames(),
+ packet_creator_.ReserializeAllFrames(retransmittable_frames.frames(),
original_sequence_number_length);
- RetransmissionInfo retransmission_info(
- serialized_packet.sequence_number,
- serialized_packet.sequence_number_length);
- retransmission_info.number_retransmissions =
- retransmission_it->second.number_retransmissions + 1;
- // Remove info with old sequence number.
- unacked_packets_.erase(unacked_it);
- retransmission_map_.erase(retransmission_it);
- DLOG(INFO) << ENDPOINT << "Retransmitting unacked packet " << sequence_number
- << " as " << serialized_packet.sequence_number;
- DCHECK(unacked_packets_.empty() ||
- unacked_packets_.rbegin()->first < serialized_packet.sequence_number);
- unacked_packets_.insert(make_pair(serialized_packet.sequence_number,
- unacked));
- retransmission_map_.insert(make_pair(serialized_packet.sequence_number,
- retransmission_info));
// A notifier may be waiting to hear about ACKs for the original sequence
// number. Inform them that the sequence number has changed.
@@ -1153,15 +1095,21 @@ void QuicConnection::RetransmitPacket(
serialized_packet.sequence_number);
}
+ DLOG(INFO) << ENDPOINT << "Retransmitting " << sequence_number << " as "
+ << serialized_packet.sequence_number;
if (debug_visitor_) {
debug_visitor_->OnPacketRetransmitted(sequence_number,
serialized_packet.sequence_number);
}
- SendOrQueuePacket(unacked->encryption_level(),
+ sent_packet_manager_.OnRetransmittedPacket(sequence_number,
+ serialized_packet.sequence_number);
+
+ SendOrQueuePacket(retransmittable_frames.encryption_level(),
serialized_packet.sequence_number,
serialized_packet.packet,
serialized_packet.entropy_hash,
- HAS_RETRANSMITTABLE_DATA);
+ HAS_RETRANSMITTABLE_DATA,
+ HasForcedFrames(serialized_packet.retransmittable_frames));
}
bool QuicConnection::CanWrite(Retransmission retransmission,
@@ -1189,30 +1137,22 @@ bool QuicConnection::CanWrite(Retransmission retransmission,
return true;
}
-bool QuicConnection::IsRetransmission(
- QuicPacketSequenceNumber sequence_number) {
- RetransmissionMap::iterator it = retransmission_map_.find(sequence_number);
- return it != retransmission_map_.end() &&
- it->second.number_retransmissions > 0;
-}
-
void QuicConnection::SetupRetransmission(
QuicPacketSequenceNumber sequence_number,
EncryptionLevel level) {
- RetransmissionMap::iterator it = retransmission_map_.find(sequence_number);
- if (it == retransmission_map_.end()) {
+ if (!sent_packet_manager_.IsUnacked(sequence_number)) {
DVLOG(1) << ENDPOINT << "Will not retransmit packet " << sequence_number;
return;
}
-
- RetransmissionInfo retransmission_info = it->second;
+ size_t retransmission_count =
+ sent_packet_manager_.GetRetransmissionCount(sequence_number);
// TODO(rch): consider using a much smaller retransmisison_delay
// for the ENCRYPTION_NONE packets.
size_t effective_retransmission_count =
- level == ENCRYPTION_NONE ? 0 : retransmission_info.number_retransmissions;
+ level == ENCRYPTION_NONE ? 0 : retransmission_count;
QuicTime::Delta retransmission_delay =
congestion_manager_.GetRetransmissionDelay(
- unacked_packets_.size(),
+ sent_packet_manager_.GetNumUnackedPackets(),
effective_retransmission_count);
retransmission_timeouts_.push(RetransmissionTime(
@@ -1233,7 +1173,6 @@ void QuicConnection::SetupRetransmission(
void QuicConnection::SetupAbandonFecTimer(
QuicPacketSequenceNumber sequence_number) {
- DCHECK(ContainsKey(unacked_fec_packets_, sequence_number));
QuicTime::Delta retransmission_delay =
QuicTime::Delta::FromMilliseconds(
congestion_manager_.DefaultRetransmissionTime().ToMilliseconds() * 3);
@@ -1243,21 +1182,6 @@ void QuicConnection::SetupAbandonFecTimer(
true));
}
-void QuicConnection::DropPacket(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);
- return;
-}
-
bool QuicConnection::WritePacket(EncryptionLevel level,
QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
@@ -1276,14 +1200,15 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
level == ENCRYPTION_NONE) {
// Drop packets that are NULL encrypted since the peer won't accept them
// anymore.
- DLOG(INFO) << ENDPOINT << "Dropped packet: " << sequence_number
+ DLOG(INFO) << ENDPOINT << "Dropping packet: " << sequence_number
<< " since the packet is NULL encrypted.";
- DropPacket(sequence_number);
+ sent_packet_manager_.DiscardPacket(sequence_number);
delete packet;
return true;
}
- Retransmission retransmission = IsRetransmission(sequence_number) ?
+ Retransmission retransmission =
+ sent_packet_manager_.IsRetransmission(sequence_number) ?
IS_RETRANSMISSION : NOT_RETRANSMISSION;
// TODO(wtc): use the same logic that is used in the packet generator.
// Namely, a packet is a handshake if it contains a stream frame for the
@@ -1395,46 +1320,49 @@ int QuicConnection::WritePacketToWire(QuicPacketSequenceNumber sequence_number,
bool QuicConnection::OnSerializedPacket(
const SerializedPacket& serialized_packet) {
- if (serialized_packet.retransmittable_frames != NULL) {
- DCHECK(unacked_packets_.empty() ||
- unacked_packets_.rbegin()->first <
- serialized_packet.sequence_number);
- // Retransmitted frames will be sent with the same encryption level as the
- // original.
+ if (serialized_packet.retransmittable_frames) {
serialized_packet.retransmittable_frames->set_encryption_level(
encryption_level_);
- unacked_packets_.insert(
- make_pair(serialized_packet.sequence_number,
- serialized_packet.retransmittable_frames));
- // All unacked packets might be retransmitted.
- retransmission_map_.insert(
- make_pair(serialized_packet.sequence_number,
- RetransmissionInfo(
- serialized_packet.sequence_number,
- serialized_packet.sequence_number_length)));
- } else if (serialized_packet.packet->is_fec_packet()) {
- unacked_fec_packets_.insert(make_pair(
- serialized_packet.sequence_number,
- serialized_packet.retransmittable_frames));
}
+ sent_packet_manager_.OnSerializedPacket(serialized_packet);
return SendOrQueuePacket(encryption_level_,
serialized_packet.sequence_number,
serialized_packet.packet,
serialized_packet.entropy_hash,
serialized_packet.retransmittable_frames != NULL ?
HAS_RETRANSMITTABLE_DATA :
- NO_RETRANSMITTABLE_DATA);
+ NO_RETRANSMITTABLE_DATA,
+ HasForcedFrames(
+ serialized_packet.retransmittable_frames));
+}
+
+QuicPacketSequenceNumber QuicConnection::GetPeerLargestObservedPacket() {
+ return received_packet_manager_.peer_largest_observed_packet();
+}
+
+QuicPacketSequenceNumber QuicConnection::GetNextPacketSequenceNumber() {
+ return packet_creator_.sequence_number() + 1;
+}
+
+void QuicConnection::OnPacketNacked(QuicPacketSequenceNumber sequence_number,
+ size_t nack_count) {
+ if (nack_count >= kNumberOfNacksBeforeRetransmission &&
+ retransmitted_nacked_packet_count_ < kMaxRetransmissionsPerAck) {
+ ++retransmitted_nacked_packet_count_;
+ RetransmitPacket(sequence_number);
+ }
}
bool QuicConnection::SendOrQueuePacket(EncryptionLevel level,
QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
QuicPacketEntropyHash entropy_hash,
- HasRetransmittableData retransmittable) {
+ HasRetransmittableData retransmittable,
+ Force forced) {
sent_entropy_manager_.RecordPacketEntropyHash(sequence_number, entropy_hash);
- if (!WritePacket(level, sequence_number, packet, retransmittable, NO_FORCE)) {
+ if (!WritePacket(level, sequence_number, packet, retransmittable, forced)) {
queued_packets_.push_back(QueuedPacket(sequence_number, packet, level,
- retransmittable));
+ retransmittable, forced));
return false;
}
return true;
@@ -1450,14 +1378,7 @@ bool QuicConnection::ShouldSimulateLostPacket() {
}
void QuicConnection::UpdateSentPacketInfo(SentPacketInfo* sent_info) {
- if (!unacked_packets_.empty()) {
- sent_info->least_unacked = unacked_packets_.begin()->first;
- } else {
- // If there are no unacked packets, set the least unacked packet to
- // sequence_number() + 1 since that will be the sequence number of this
- // ack packet whenever it is sent.
- sent_info->least_unacked = packet_creator_.sequence_number() + 1;
- }
+ sent_info->least_unacked = sent_packet_manager_.GetLeastUnackedSentPacket();
sent_info->entropy_hash = sent_entropy_manager_.EntropyHash(
sent_info->least_unacked - 1);
}
@@ -1481,13 +1402,12 @@ void QuicConnection::SendAck() {
void QuicConnection::MaybeAbandonFecPacket(
QuicPacketSequenceNumber sequence_number) {
- if (!ContainsKey(unacked_fec_packets_, sequence_number)) {
+ if (!sent_packet_manager_.IsFecUnacked(sequence_number)) {
DVLOG(2) << ENDPOINT << "no need to abandon fec packet: "
<< sequence_number << "; it's already acked'";
return;
}
congestion_manager_.AbandoningPacket(sequence_number);
- // TODO(satyashekhar): Should this decrease the congestion window?
}
QuicTime QuicConnection::OnRetransmissionTimeout() {
@@ -1654,36 +1574,6 @@ void QuicConnection::SendConnectionClose(QuicErrorCode error) {
SendConnectionCloseWithDetails(error, string());
}
-void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
- const string& details) {
- DLOG(INFO) << ENDPOINT << "Force closing with error "
- << QuicUtils::ErrorToString(error) << " (" << error << ") "
- << details;
- QuicConnectionCloseFrame frame;
- frame.error_code = error;
- frame.error_details = details;
- UpdateSentPacketInfo(&frame.ack_frame.sent_info);
- received_packet_manager_.UpdateReceivedPacketInfo(
- &frame.ack_frame.received_info, clock_->ApproximateNow());
-
- SerializedPacket serialized_packet =
- packet_creator_.SerializeConnectionClose(&frame);
-
- // We need to update the sent entropy hash for all sent packets.
- sent_entropy_manager_.RecordPacketEntropyHash(
- serialized_packet.sequence_number,
- serialized_packet.entropy_hash);
-
- if (!WritePacket(encryption_level_,
- serialized_packet.sequence_number,
- serialized_packet.packet,
- serialized_packet.retransmittable_frames != NULL ?
- HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA,
- FORCE)) {
- delete serialized_packet.packet;
- }
-}
-
void QuicConnection::SendConnectionCloseWithDetails(QuicErrorCode error,
const string& details) {
if (!write_blocked_) {
@@ -1692,6 +1582,21 @@ void QuicConnection::SendConnectionCloseWithDetails(QuicErrorCode error,
CloseConnection(error, false);
}
+void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
+ const string& details) {
+ DLOG(INFO) << ENDPOINT << "Force closing with error "
+ << QuicUtils::ErrorToString(error) << " (" << error << ") "
+ << details;
+ QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame();
+ frame->error_code = error;
+ frame->error_details = details;
+ UpdateSentPacketInfo(&frame->ack_frame.sent_info);
+ received_packet_manager_.UpdateReceivedPacketInfo(
+ &frame->ack_frame.received_info, clock_->ApproximateNow());
+ packet_generator_.AddControlFrame(QuicFrame(frame));
+ Flush();
+}
+
void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
DCHECK(connected_);
connected_ = false;
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_helper_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698