summaryrefslogtreecommitdiffstats
path: root/net/quic/quic_connection.cc
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-18 05:43:20 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-18 05:43:20 +0000
commitc995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f (patch)
treeefdaf02c88a1809609cb65488c75e27f31bb3cf2 /net/quic/quic_connection.cc
parent736337679a839a57b9a39e2c0677d52a44e31dc6 (diff)
downloadchromium_src-c995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f.zip
chromium_src-c995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f.tar.gz
chromium_src-c995c57ac3cbf7c29c56dd4aba5ab8d1ed54c73f.tar.bz2
Cleaning up constructors for QuicData, QuicPacket and QuicEncryptedPacket to not take unnamed bool values.
Merge internal change: 41194576 Simplify the interface between the QuicConnection and the congestion control system. Add a QuicCongestionManager to wrap the the SendScheduler and ReceiptMetricsCollector in a single class for all congestion-related functionality. (Narrows the SendScheduler-specific interface to just those methods called by the QuicConnection.) This is a minor cleanup in advance of moving the RTO management out of QuicConnection (since it is algorithm specific). Merge internal change: 41188949 Refactor SendStreamData to frame one StreamFrame at once and send it, instea d of framing and serializing multiple in DataToStream. Merge internal change: 41155771 Expand the 48 bit on-the-wire packet sequence number into the full 64 bit se quence number. Merge internal change: 41147680 Enable encryption of private flags. Merge internal change: 41147034 Splitting flags into private and public and implementing framing for both. Merge internal change: 41145985 Add a zero length padding frame. Merge internal change: 41141396 Remove "support" for PDUs Merge internal change: 41133537 Remove the Clear method from QuicPacketCreator options, and explicitly initialize all field in the constructor. Merge internal change: 41128100 Cleanup from chrome cl 11820003 Merge internal change: 41118012 Refactor to pull out connection close so that connection can be closed without sending connection close frame. Merge internal change: 41026182 Keep a bool to check if a QuicPacket is an FEC packet instead of taking whol e packet flag as an input to the constructor. Merge internal change: 41026127 Remove default constructors for QuicTime and QuicTime::Delta and used static Zero() methods instead to make it clear what value is being used. One annoying side-effect is this means that maps which have these objects as keys can't not be accessed with []. Thankfully, this is not a huge problem. (It only affects us in one place). But I can add the default constructors back to support this use case, if necessary. (I'd prefer not to since I think Zero() is more clear, but can go either way). Merge internal change: 40993340 Replace boolean literals with named constants ini QuicConnection::SendPacket() calls. Merge internal change: 40991762 Consistently use Retransmit/Retransmission (instead of Resend) when talking about sending QUIC data a second time (in a new packet). Merge internal change: 40988697 Move the logic for RTO timeout handling from the Helper to the QuicConnection. Merge internal change: 40980852 Fixing a bug where a non-existant frame corresponding to an FEC was being deleted. Merge internal change: 40883214 Change the QUIC FEC group number from an ad-hoc id to the sequence number of the first packet in the group. Over the wire, however, send a 1 byte delta from the sequence number of the current packet to the sequence number of the first protected packet in the group. Merge internal change: 40881017 TBR=jar@chromium.org Review URL: https://chromiumcodereview.appspot.com/11959039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177612 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic/quic_connection.cc')
-rw-r--r--net/quic/quic_connection.cc253
1 files changed, 159 insertions, 94 deletions
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index debc017..bf09e91 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -27,6 +27,8 @@ namespace net {
// TODO(pwestin): kDefaultTimeoutUs is in int64.
int32 kNegotiatedTimeoutUs = kDefaultTimeoutUs;
+namespace {
+
// The largest gap in packets we'll accept without closing the connection.
// This will likely have to be tuned.
const QuicPacketSequenceNumber kMaxPacketGap = 5000;
@@ -35,29 +37,37 @@ const QuicPacketSequenceNumber kMaxPacketGap = 5000;
// without exceeding kMaxPacketSize.
const QuicPacketSequenceNumber kMaxUnackedPackets = 192u;
-// The amount of time we wait before resending a packet.
-const int64 kDefaultResendTimeMs = 500;
-
// 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 kMaxResendPerAck = 10;
+const int kMaxRetransmissionsPerAck = 10;
-// TCP resends after 2 nacks. We allow for a third in case of out-of-order
+// TCP retransmits after 2 nacks. We allow for a third in case of out-of-order
// delivery.
-// TODO(ianswett): Change to match TCP's rule of resending once an ack at least
-// 3 sequence numbers larger arrives.
-const int kNumberOfNacksBeforeResend = 3;
+// TODO(ianswett): Change to match TCP's rule of retransmitting once an ack
+// at least 3 sequence numbers larger arrives.
+const int kNumberOfNacksBeforeRetransmission = 3;
// The maxiumum number of packets we'd like to queue. We may end up queueing
// more in the case of many control frames.
// 6 is arbitrary.
const int kMaxPacketsToSerializeAtOnce = 6;
+// Limit the number of packets we send per retransmission-alarm so we
+// eventually cede. 10 is arbitrary.
+const int kMaxPacketsPerRetransmissionAlarm = 10;
+
+// Named constants for SendPacket options.
+const bool kForce = true;
+const bool kShouldRetransmit = true;
+const bool kIsRetransmission = true;
+
bool Near(QuicPacketSequenceNumber a, QuicPacketSequenceNumber b) {
QuicPacketSequenceNumber delta = (a > b) ? a - b : b - a;
return delta <= kMaxPacketGap;
}
+} // namespace
+
QuicConnection::UnackedPacket::UnackedPacket(QuicFrames unacked_frames)
: frames(unacked_frames),
number_nacks(0) {
@@ -87,16 +97,15 @@ QuicConnection::QuicConnection(QuicGuid guid,
largest_seen_packet_with_ack_(0),
peer_largest_observed_packet_(0),
peer_least_packet_awaiting_ack_(0),
+ handling_retransmission_timeout_(false),
write_blocked_(false),
packet_creator_(guid_, &framer_),
timeout_(QuicTime::Delta::FromMicroseconds(kDefaultTimeoutUs)),
time_of_last_packet_(clock_->Now()),
- collector_(new QuicReceiptMetricsCollector(clock_, kTCP)),
- scheduler_(new QuicSendScheduler(clock_, kTCP)),
+ congestion_manager_(clock_, kTCP),
connected_(true),
received_truncated_ack_(false),
send_ack_in_response_to_packet_(false) {
- options()->max_num_packets = kMaxPacketsToSerializeAtOnce;
helper_->SetConnection(this);
helper_->SetTimeoutAlarm(timeout_);
framer_.set_visitor(this);
@@ -128,6 +137,9 @@ QuicConnection::~QuicConnection() {
void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
switch (frame->type) {
+ case PADDING_FRAME:
+ delete frame->padding_frame;
+ break;
case STREAM_FRAME:
delete frame->stream_frame;
break;
@@ -143,7 +155,6 @@ void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
case CONNECTION_CLOSE_FRAME:
delete frame->connection_close_frame;
break;
- case PDU_FRAME: // Fall through.
case NUM_FRAME_TYPES:
DCHECK(false) << "Cannot delete type: " << frame->type;
}
@@ -152,12 +163,12 @@ void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
void QuicConnection::DeleteUnackedPacket(UnackedPacket* unacked) {
for (QuicFrames::iterator it = unacked->frames.begin();
it != unacked->frames.end(); ++it) {
- DCHECK(ShouldResend(*it));
+ DCHECK(ShouldRetransmit(*it));
DeleteEnclosedFrame(&(*it));
}
}
-bool QuicConnection::ShouldResend(const QuicFrame& frame) {
+bool QuicConnection::ShouldRetransmit(const QuicFrame& frame) {
return frame.type != ACK_FRAME && frame.type != CONGESTION_FEEDBACK_FRAME;
}
@@ -188,7 +199,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
}
// If this packet has already been seen, or that the sender
- // has told us will not be resent, then stop processing the packet.
+ // has told us will not be retransmitted, then stop processing the packet.
if (!outgoing_ack_.received_info.IsAwaitingPacket(
header.packet_sequence_number)) {
return false;
@@ -199,7 +210,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
}
void QuicConnection::OnFecProtectedPayload(StringPiece payload) {
- DCHECK_NE(0, last_header_.fec_group);
+ DCHECK_NE(0u, last_header_.fec_group);
QuicFecGroup* group = GetFecGroup();
group->Update(last_header_, payload);
}
@@ -227,14 +238,14 @@ void QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
UpdatePacketInformationReceivedByPeer(incoming_ack);
UpdatePacketInformationSentByPeer(incoming_ack);
- scheduler_->OnIncomingAckFrame(incoming_ack);
+ congestion_manager_.OnIncomingAckFrame(incoming_ack);
// Now the we have received an ack, we might be able to send queued packets.
if (queued_packets_.empty()) {
return;
}
- QuicTime::Delta delay = scheduler_->TimeUntilSend(false);
+ QuicTime::Delta delay = congestion_manager_.TimeUntilSend(false);
if (delay.IsZero()) {
helper_->UnregisterSendAlarmIfRegistered();
if (!write_blocked_) {
@@ -247,7 +258,7 @@ void QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
void QuicConnection::OnCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback) {
- scheduler_->OnIncomingQuicCongestionFeedbackFrame(feedback);
+ congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(feedback);
}
bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
@@ -309,7 +320,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
packet_creator_.sequence_number() + 1,
peer_largest_observed_packet_ + 1);
- int resent_packets = 0;
+ 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.
@@ -323,7 +334,8 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
// always sending packets with new sequence numbers. I believe it may
// only be relevant for the first crypto connect packet, which doesn't
// get a new packet sequence number.
- // The acked packet might be queued (if a resend had been attempted).
+ // The acked packet might be queued (if a retransmission had been
+ // attempted).
for (QueuedPacketList::iterator q = queued_packets_.begin();
q != queued_packets_.end(); ++q) {
if (q->sequence_number == it->first) {
@@ -338,7 +350,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
++it;
unacked_packets_.erase(it_tmp);
} else {
- // This is a packet which we planned on resending and has not been
+ // 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) << "still missing " << it->first;
@@ -347,24 +359,24 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
}
// Determine if this packet is being explicitly nacked and, if so, if it
- // is worth resending.
- QuicPacketSequenceNumber resend_number = 0;
+ // is worth retransmitting.
+ QuicPacketSequenceNumber retransmission_number = 0;
if (it->first < peer_largest_observed_packet_) {
// The peer got packets after this sequence number. This is an explicit
// nack.
++(it->second->number_nacks);
- if (it->second->number_nacks >= kNumberOfNacksBeforeResend &&
- resent_packets < kMaxResendPerAck) {
- resend_number = it->first;
+ if (it->second->number_nacks >= kNumberOfNacksBeforeRetransmission &&
+ retransmitted_packets < kMaxRetransmissionsPerAck) {
+ retransmission_number = it->first;
}
}
++it;
- if (resend_number > 0) {
- ++resent_packets;
- DVLOG(1) << "Trying to resend packet " << resend_number
+ if (retransmission_number > 0) {
+ ++retransmitted_packets;
+ DVLOG(1) << "Trying to retransmit packet " << retransmission_number
<< " as it has been nacked 3 or more times.";
- MaybeResendPacket(resend_number);
+ MaybeRetransmitPacket(retransmission_number);
}
}
}
@@ -376,7 +388,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
void QuicConnection::SetLeastUnacked(QuicPacketSequenceNumber lowest_unacked) {
// If we've gotten an ack for the lowest packet we were waiting on,
- // update that and the list of packets we advertise we will not resend.
+ // update that and the list of packets we advertise we will not retransmit.
if (lowest_unacked > outgoing_ack_.sent_info.least_unacked) {
outgoing_ack_.sent_info.least_unacked = lowest_unacked;
}
@@ -412,7 +424,7 @@ void QuicConnection::UpdatePacketInformationSentByPeer(
}
void QuicConnection::OnFecData(const QuicFecData& fec) {
- DCHECK_NE(0, last_header_.fec_group);
+ DCHECK_NE(0u, last_header_.fec_group);
QuicFecGroup* group = GetFecGroup();
group->UpdateFec(last_header_.packet_sequence_number, fec);
}
@@ -427,16 +439,15 @@ void QuicConnection::OnConnectionCloseFrame(
const QuicConnectionCloseFrame& frame) {
DLOG(INFO) << "Connection closed with error "
<< QuicUtils::ErrorToString(frame.error_code);
- connected_ = false;
- visitor_->ConnectionClose(frame.error_code, true);
+ CloseConnection(frame.error_code, true);
}
void QuicConnection::OnPacketComplete() {
if (!last_packet_revived_) {
DLOG(INFO) << "Got packet " << last_header_.packet_sequence_number
<< " with " << last_stream_frames_.size()
- << " stream frames for " << last_header_.guid;
- collector_->RecordIncomingPacket(last_size_,
+ << " stream frames for " << last_header_.public_header.guid;
+ congestion_manager_.RecordIncomingPacket(last_size_,
last_header_.packet_sequence_number,
clock_->Now(),
last_packet_revived_);
@@ -461,8 +472,7 @@ void QuicConnection::MaybeSendAckInResponseToPacket() {
} else if (!last_stream_frames_.empty()) {
// TODO(alyssar) this case should really be "if the packet contained any
// non-ack frame", rather than "if the packet contained a stream frame"
- helper_->SetAckAlarm(
- QuicTime::Delta::FromMicroseconds(kDefaultResendTimeMs));
+ helper_->SetAckAlarm(DefaultRetransmissionTime());
}
send_ack_in_response_to_packet_ = !send_ack_in_response_to_packet_;
}
@@ -471,46 +481,37 @@ QuicConsumedData QuicConnection::SendStreamData(
QuicStreamId id,
StringPiece data,
QuicStreamOffset offset,
- bool fin,
- QuicPacketSequenceNumber* last_packet) {
+ bool fin) {
size_t total_bytes_consumed = 0;
bool fin_consumed = false;
+ packet_creator_.MaybeStartFEC();
while (queued_packets_.empty()) {
- vector<PacketPair> packets;
QuicFrames frames;
size_t bytes_consumed =
- packet_creator_.DataToStream(id, data, offset, fin, &packets, &frames);
+ packet_creator_.CreateStreamFrame(id, data, offset, fin, &frames);
total_bytes_consumed += bytes_consumed;
offset += bytes_consumed;
fin_consumed = fin && bytes_consumed == data.size();
data.remove_prefix(bytes_consumed);
- DCHECK_LT(0u, packets.size());
-
- for (size_t i = 0; i < packets.size(); ++i) {
- // Resend is false for FEC packets.
- bool should_resend = !packets[i].second->IsFecPacket();
- SendPacket(packets[i].first,
- packets[i].second,
- should_resend,
- false,
- false);
- if (should_resend) {
- QuicFrames unacked_frames;
- unacked_frames.push_back(frames[i]);
- UnackedPacket* unacked = new UnackedPacket(
- unacked_frames, frames[i].stream_frame->data.as_string());
- // Ensure the string piece points to the owned copy of the data.
- unacked->frames[0].stream_frame->data = StringPiece(unacked->data);
- unacked_packets_.insert(make_pair(packets[i].first, unacked));
- } else {
- DeleteEnclosedFrame(&frames[i]);
- }
- }
- if (last_packet != NULL) {
- *last_packet = packets[packets.size() - 1].first;
+ PacketPair pair = packet_creator_.SerializeAllFrames(frames);
+ // TODO(ianswett): Restore packet reordering.
+ SendPacket(pair.first, pair.second, kShouldRetransmit, !kForce,
+ !kIsRetransmission);
+ UnackedPacket* unacked = new UnackedPacket(
+ frames, frames[0].stream_frame->data.as_string());
+ // Ensure the string piece points to the owned copy of the data.
+ unacked->frames[0].stream_frame->data = StringPiece(unacked->data);
+ unacked_packets_.insert(make_pair(pair.first, unacked));
+
+ if (packet_creator_.ShouldSendFec(data.size() == 0)) {
+ PacketPair fec_pair = packet_creator_.SerializeFec();
+ // Never resend FEC packets.
+ SendPacket(fec_pair.first, fec_pair.second, !kShouldRetransmit, !kForce,
+ !kIsRetransmission);
}
+
if (data.size() == 0) {
// We're done writing the data. Exit the loop.
// We don't make this a precondition beacuse we could have 0 bytes of data
@@ -561,7 +562,7 @@ bool QuicConnection::OnCanWrite() {
// 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.
- helper_->SetSendAlarm(QuicTime::Delta());
+ helper_->SetSendAlarm(QuicTime::Delta::Zero());
}
}
@@ -581,11 +582,12 @@ bool QuicConnection::WriteData() {
size_t num_serialized;
PacketPair pair = packet_creator_.SerializeFrames(
queued_control_frames_, &num_serialized);
- // If any serialized frames need to be resent, add them to unacked_packets.
+ // If any serialized frames need to be retransmitted, add them to
+ // unacked_packets.
QuicFrames unacked_frames;
for (QuicFrames::const_iterator iter = queued_control_frames_.begin();
iter != queued_control_frames_.begin() + num_serialized; ++iter) {
- if (ShouldResend(*iter)) {
+ if (ShouldRetransmit(*iter)) {
unacked_frames.push_back(*iter);
}
}
@@ -612,7 +614,8 @@ bool QuicConnection::WriteData() {
num_queued_packets = queued_packets_.size();
QueuedPacket p = queued_packets_.front();
queued_packets_.pop_front();
- SendPacket(p.sequence_number, p.packet, p.resend, false, p.retransmit);
+ SendPacket(p.sequence_number, p.packet, p.should_retransmit, !kForce,
+ p.is_retransmission);
}
return !write_blocked_;
@@ -624,7 +627,7 @@ void QuicConnection::RecordPacketReceived(const QuicPacketHeader& header) {
outgoing_ack_.received_info.RecordReceived(sequence_number);
}
-bool QuicConnection::MaybeResendPacketForRTO(
+bool QuicConnection::MaybeRetransmitPacketForRTO(
QuicPacketSequenceNumber 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
@@ -635,12 +638,12 @@ bool QuicConnection::MaybeResendPacketForRTO(
ContainsKey(unacked_packets_, sequence_number)) {
return false;
} else {
- MaybeResendPacket(sequence_number);
+ MaybeRetransmitPacket(sequence_number);
return true;
}
}
-void QuicConnection::MaybeResendPacket(
+void QuicConnection::MaybeRetransmitPacket(
QuicPacketSequenceNumber sequence_number) {
UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
@@ -648,30 +651,31 @@ void QuicConnection::MaybeResendPacket(
UnackedPacket* unacked = it->second;
// TODO(ianswett): Never change the sequence number of the connect packet.
unacked_packets_.erase(it);
- // Re-packetize the frames with a new sequence number for resend.
- // Resent data packets do not use FEC, even when it's enabled.
+ // Re-packetize the frames with a new sequence number for retransmission.
+ // Retransmitted data packets do not use FEC, even when it's enabled.
PacketPair packetpair = packet_creator_.SerializeAllFrames(unacked->frames);
- DVLOG(1) << "Resending unacked packet " << sequence_number << " as "
+ DVLOG(1) << "Retransmitting unacked packet " << sequence_number << " as "
<< packetpair.first;
unacked_packets_.insert(make_pair(packetpair.first, unacked));
// Make sure if this was our least unacked packet, that we update our
// outgoing ack. If this wasn't the least unacked, this is a no-op.
UpdateLeastUnacked(sequence_number);
- SendPacket(packetpair.first, packetpair.second, true, false, true);
+ SendPacket(packetpair.first, packetpair.second, kShouldRetransmit,
+ !kForce, kIsRetransmission);
} else {
DVLOG(2) << "alarm fired for " << sequence_number
<< " but it has been acked";
}
}
-bool QuicConnection::CanWrite(bool is_retransmit) {
+bool QuicConnection::CanWrite(bool is_retransmission) {
// TODO(ianswett): If the packet is a retransmit, the current send alarm may
// be too long.
if (write_blocked_ || helper_->IsSendAlarmSet()) {
return false;
}
- QuicTime::Delta delay = scheduler_->TimeUntilSend(is_retransmit);
+ QuicTime::Delta delay = congestion_manager_.TimeUntilSend(is_retransmission);
// If the scheduler requires a delay, then we can not send this packet now.
if (!delay.IsZero() && !delay.IsInfinite()) {
// TODO(pwestin): we need to handle delay.IsInfinite() seperately.
@@ -683,21 +687,31 @@ bool QuicConnection::CanWrite(bool is_retransmit) {
bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
- bool should_resend,
+ bool should_retransmit,
bool force,
- bool is_retransmit) {
+ bool is_retransmission) {
// If this packet is being forced, don't bother checking to see if we should
// write, just write.
if (!force) {
// If we can't write, then simply queue the packet.
- if (!CanWrite(is_retransmit)) {
+ if (!CanWrite(is_retransmission)) {
queued_packets_.push_back(
- QueuedPacket(sequence_number, packet, should_resend, is_retransmit));
+ QueuedPacket(sequence_number, packet, should_retransmit,
+ is_retransmission));
return false;
}
}
- if (should_resend) {
- helper_->SetResendAlarm(sequence_number, DefaultResendTime());
+ if (should_retransmit) {
+ // Do not set the retransmisson alarm if we're already handling the
+ // retransmission alarm because the retransmission alarm will be reset when
+ // OnRetransmissionTimeout completes.
+ if (!handling_retransmission_timeout_) {
+ helper_->SetRetransmissionAlarm(DefaultRetransmissionTime());
+ }
+ retransmission_timeouts_.push_back(
+ make_pair(sequence_number, clock_->Now().Add(
+ DefaultRetransmissionTime())));
+
// The second case should never happen in the real world, but does here
// because we sometimes send out of order to validate corner cases.
if (outgoing_ack_.sent_info.least_unacked == 0 ||
@@ -709,7 +723,8 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*packet));
int error;
DLOG(INFO) << "Sending packet : "
- << (should_resend ? "data bearing " : " ack only ")
+ << (packet->is_fec_packet() ? "FEC " :
+ (should_retransmit ? "data bearing " : " ack only "))
<< "packet " << sequence_number;
DCHECK(encrypted->length() <= kMaxPacketSize)
<< "Packet " << sequence_number << " will not be read; too large: "
@@ -724,7 +739,8 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
// UDP sockets.
/*
queued_packets_.push_front(
- QueuedPacket(sequence_number, packet, should_resend, is_retransmit));
+ QueuedPacket(sequence_number, packet, should_retransmit,
+ is_retransmission));
*/
return false;
}
@@ -734,7 +750,8 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
time_of_last_packet_ = clock_->Now();
DVLOG(1) << "last packet: " << time_of_last_packet_.ToMicroseconds();
- scheduler_->SentPacket(sequence_number, packet->length(), is_retransmit);
+ congestion_manager_.SentPacket(sequence_number, packet->length(),
+ is_retransmission);
delete packet;
return true;
}
@@ -753,7 +770,7 @@ void QuicConnection::SendAck() {
if (!ContainsKey(unacked_packets_, outgoing_ack_.sent_info.least_unacked)) {
// At some point, all packets were acked, and we set least_unacked to a
- // packet we will not resend. Make sure we update it.
+ // packet we will not retransmit. Make sure we update it.
UpdateLeastUnacked(outgoing_ack_.sent_info.least_unacked);
}
@@ -761,7 +778,8 @@ void QuicConnection::SendAck() {
should_send_ack_ = true;
- if (collector_->GenerateCongestionFeedback(&outgoing_congestion_feedback_)) {
+ if (congestion_manager_.GenerateCongestionFeedback(
+ &outgoing_congestion_feedback_)) {
DVLOG(1) << "Sending feedback " << outgoing_congestion_feedback_;
should_send_congestion_feedback_ = true;
}
@@ -771,6 +789,46 @@ void QuicConnection::SendAck() {
}
}
+QuicTime QuicConnection::OnRetransmissionTimeout() {
+ // This guards against registering the alarm later than we should.
+ //
+ // If we have packet A and B in the list and we call
+ // MaybeRetransmitPacketForRTO on A, that may trigger a call to
+ // SetRetransmissionAlarm if A is retransmitted as C. In that case we
+ // don't want to register the alarm under SetRetransmissionAlarm; we
+ // want to set it to the RTO of B when we return from this function.
+ handling_retransmission_timeout_ = true;
+
+ for (int i = 0; i < kMaxPacketsPerRetransmissionAlarm; ++i) {
+ if (retransmission_timeouts_.empty() ||
+ retransmission_timeouts_.front().second > clock_->Now()) {
+ break;
+ }
+ if (!MaybeRetransmitPacketForRTO(retransmission_timeouts_.front().first)) {
+ DLOG(INFO) << "MaybeRetransmitPacketForRTO failed: "
+ << "adding an extra delay.";
+ // This implicitly delays the RTO for all subsequent packets, since
+ // MaybeRetransmitPacketForRTO will return false for all packets with
+ // a larger sequence number anyway.
+ retransmission_timeouts_.front().second =
+ retransmission_timeouts_.front().second.Add(
+ DefaultRetransmissionTime());
+ break;
+ }
+ retransmission_timeouts_.pop_front();
+ }
+
+ handling_retransmission_timeout_ = false;
+
+ if (retransmission_timeouts_.empty()) {
+ return QuicTime::FromMilliseconds(0);
+ }
+
+ // We have packets remaining. Return the absolute RTO of the oldest packet
+ // on the list.
+ return retransmission_timeouts_.front().second;
+}
+
void QuicConnection::MaybeProcessRevivedPacket() {
QuicFecGroup* group = GetFecGroup();
if (group == NULL || !group->CanRevive()) {
@@ -809,10 +867,17 @@ void QuicConnection::SendConnectionClose(QuicErrorCode error) {
frame.ack_frame = outgoing_ack_;
PacketPair packetpair = packet_creator_.CloseConnection(&frame);
- // There's no point in resending this: we're closing the connection.
- SendPacket(packetpair.first, packetpair.second, false, true, false);
+ // There's no point in retransmitting this: we're closing the connection.
+ SendPacket(packetpair.first, packetpair.second, !kShouldRetransmit, kForce,
+ !kIsRetransmission);
+ CloseConnection(error, false);
+}
+
+void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
+ // TODO(satyamshekhar): Ask the dispatcher to delete visitor and hence self
+ // if the visitor will always be deleted by closing the connection.
connected_ = false;
- visitor_->ConnectionClose(error, false);
+ visitor_->ConnectionClose(error, from_peer);
}
void QuicConnection::CloseFecGroupsBefore(