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

Unified Diff: net/quic/quic_connection.cc

Issue 11958018: Queueing QUIC frames to be resent instead of packets and packing RST frames with acks and congestio… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 11 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_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 2651433375e78d6875bae4317a93dc55342a83f7..8c19758ec76df340182d8f890e3ab37f0ff3db72 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -58,6 +58,21 @@ bool Near(QuicPacketSequenceNumber a, QuicPacketSequenceNumber b) {
return delta <= kMaxPacketGap;
}
+QuicConnection::UnackedPacket::UnackedPacket(QuicFrames unacked_frames)
+ : frames(unacked_frames),
+ number_nacks(0) {
+}
+
+QuicConnection::UnackedPacket::UnackedPacket(QuicFrames unacked_frames,
+ std::string data)
+ : frames(unacked_frames),
+ number_nacks(0),
+ data(data) {
+}
+
+QuicConnection::UnackedPacket::~UnackedPacket() {
+}
+
QuicConnection::QuicConnection(QuicGuid guid,
IPEndPoint address,
QuicConnectionHelperInterface* helper)
@@ -99,19 +114,53 @@ QuicConnection::QuicConnection(QuicGuid guid,
}
QuicConnection::~QuicConnection() {
- for (UnackedPacketMap::iterator it = unacked_packets_.begin();
- it != unacked_packets_.end(); ++it) {
- delete it->second.packet;
+ for (UnackedPacketMap::iterator u = unacked_packets_.begin();
jar (doing other things) 2013/01/16 23:59:11 nit: avoid single letter variable names. Use of "
Ian Swett 2013/01/17 15:33:27 Agreed, that is a terrible name. I have no idea w
+ u != unacked_packets_.end(); ++u) {
+ DeleteUnackedPacket(u->second);
}
+ STLDeleteValues(&unacked_packets_);
jar (doing other things) 2013/01/16 23:59:11 nit: It seems strange to iterate over the map star
Ian Swett 2013/01/17 15:33:27 I hated writing it. I actually made a destructor,
jar (doing other things) 2013/01/17 16:14:33 +1 That would certainly help IMO.
STLDeleteValues(&group_map_);
- // Queued packets that are not to be resent are owned
- // by the packet queue.
for (QueuedPacketList::iterator q = queued_packets_.begin();
jar (doing other things) 2013/01/16 23:59:11 nit: "q" should be a better name (...yeah... ya'
Ian Swett 2013/01/17 15:33:27 Done.
q != queued_packets_.end(); ++q) {
- if (!q->resend) delete q->packet;
+ delete q->packet;
}
}
+void QuicConnection::DeleteEnclosedFrame(QuicFrame* frame) {
+ switch (frame->type) {
+ case STREAM_FRAME:
+ delete frame->stream_frame;
+ break;
+ case ACK_FRAME:
+ delete frame->ack_frame;
+ break;
+ case CONGESTION_FEEDBACK_FRAME:
+ delete frame->congestion_feedback_frame;
+ break;
+ case RST_STREAM_FRAME:
+ delete frame->rst_stream_frame;
+ break;
+ 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;
+ }
+}
+
+void QuicConnection::DeleteUnackedPacket(UnackedPacket* unacked) {
+ for (QuicFrames::iterator it = unacked->frames.begin();
+ it != unacked->frames.end(); ++it) {
+ DCHECK(ShouldResend(*it));
+ DeleteEnclosedFrame(&(*it));
+ }
+}
+
+bool QuicConnection::ShouldResend(const QuicFrame& frame) {
+ return frame.type != ACK_FRAME && frame.type != CONGESTION_FEEDBACK_FRAME;
+}
+
void QuicConnection::OnError(QuicFramer* framer) {
SendConnectionClose(framer->error());
}
@@ -270,6 +319,10 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
// Packet was acked, so remove it from our unacked packet list.
DVLOG(1) << "Got an ack for " << it->first;
// TODO(rch): This is inefficient and should be sped up.
+ // TODO(ianswett): Ensure this inner loop is applicable now that we're
+ // 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).
for (QueuedPacketList::iterator q = queued_packets_.begin();
q != queued_packets_.end(); ++q) {
@@ -279,7 +332,8 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
}
}
acked_packets.insert(it->first);
- delete it->second.packet;
+ DeleteUnackedPacket(it->second);
+ delete it->second;
UnackedPacketMap::iterator it_tmp = it;
++it;
unacked_packets_.erase(it_tmp);
@@ -298,8 +352,8 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
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 &&
+ ++(it->second->number_nacks);
+ if (it->second->number_nacks >= kNumberOfNacksBeforeResend &&
resent_packets < kMaxResendPerAck) {
resend_number = it->first;
}
@@ -424,8 +478,9 @@ QuicConsumedData QuicConnection::SendStreamData(
while (queued_packets_.empty()) {
vector<PacketPair> packets;
+ QuicFrames frames;
size_t bytes_consumed =
- packet_creator_.DataToStream(id, data, offset, fin, &packets);
+ packet_creator_.DataToStream(id, data, offset, fin, &packets, &frames);
total_bytes_consumed += bytes_consumed;
offset += bytes_consumed;
fin_consumed = fin && bytes_consumed == data.size();
@@ -433,14 +488,24 @@ QuicConsumedData QuicConnection::SendStreamData(
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,
- // Resend is false for FEC packets.
- !packets[i].second->IsFecPacket(),
+ should_resend,
false,
false);
- unacked_packets_.insert(make_pair(packets[i].first,
- UnackedPacket(packets[i].second)));
+ 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) {
@@ -459,13 +524,13 @@ QuicConsumedData QuicConnection::SendStreamData(
void QuicConnection::SendRstStream(QuicStreamId id,
QuicErrorCode error,
QuicStreamOffset offset) {
- // TODO(ianswett): Queue the frame and use WriteData instead of SendPacket
- // once we support re-sending frames instead of packets.
- PacketPair packetpair = packet_creator_.ResetStream(id, offset, error);
+ queued_control_frames_.push_back(QuicFrame(
+ new QuicRstStreamFrame(id, offset, error)));
- SendPacket(packetpair.first, packetpair.second, true, false, false);
- unacked_packets_.insert(make_pair(packetpair.first,
- UnackedPacket(packetpair.second)));
+ // Try to write immediately if possible.
+ if (CanWrite(false)) {
+ WriteData();
+ }
}
void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
@@ -506,19 +571,33 @@ bool QuicConnection::OnCanWrite() {
bool QuicConnection::WriteData() {
DCHECK_EQ(false, write_blocked_);
// Serialize the ack and congestion frames before draining the pending queue.
- QuicFrames frames;
if (should_send_ack_) {
- frames.push_back(QuicFrame(&outgoing_ack_));
+ queued_control_frames_.push_back(QuicFrame(&outgoing_ack_));
}
if (should_send_congestion_feedback_) {
- frames.push_back(QuicFrame(&outgoing_congestion_feedback_));
+ queued_control_frames_.push_back(QuicFrame(&outgoing_congestion_feedback_));
}
- while (!frames.empty()) {
+ while (!queued_control_frames_.empty()) {
size_t num_serialized;
- PacketPair pair = packet_creator_.SerializeFrames(frames, &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.
+ QuicFrames unacked_frames;
+ for (QuicFrames::const_iterator iter = queued_control_frames_.begin();
+ iter != queued_control_frames_.begin() + num_serialized; ++iter) {
+ if (ShouldResend(*iter)) {
+ unacked_frames.push_back(*iter);
+ }
+ }
+ if (!unacked_frames.empty()) {
+ unacked_packets_.insert(make_pair(pair.first,
+ new UnackedPacket(unacked_frames)));
+ }
queued_packets_.push_back(QueuedPacket(
- pair.first, pair.second, false, false));
- frames.erase(frames.begin(), frames.begin() + num_serialized);
+ pair.first, pair.second, !unacked_frames.empty(), false));
+ queued_control_frames_.erase(
+ queued_control_frames_.begin(),
+ queued_control_frames_.begin() + num_serialized);
}
should_send_ack_ = false;
should_send_congestion_feedback_ = false;
@@ -566,22 +645,20 @@ void QuicConnection::MaybeResendPacket(
UnackedPacketMap::iterator it = unacked_packets_.find(sequence_number);
if (it != unacked_packets_.end()) {
- QuicPacket* packet = it->second.packet;
+ UnackedPacket* unacked = it->second;
+ // TODO(ianswett): Never change the sequence number of the connect packet.
unacked_packets_.erase(it);
- // Re-frame the packet with a new sequence number for resend.
- QuicPacketSequenceNumber new_sequence_number =
- packet_creator_.SetNewSequenceNumber(packet);
+ // Re-packetize the frames with a new sequence number for resend.
+ // Resent 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 "
- << new_sequence_number;
- // Clear the FEC group.
- framer_.WriteFecGroup(0u, packet);
- unacked_packets_.insert(make_pair(new_sequence_number,
- UnackedPacket(packet)));
+ << 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(new_sequence_number, packet, true, false, true);
+ SendPacket(packetpair.first, packetpair.second, true, false, true);
} else {
DVLOG(2) << "alarm fired for " << sequence_number
<< " but it has been acked";
@@ -658,7 +735,7 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
DVLOG(1) << "last packet: " << time_of_last_packet_.ToMicroseconds();
scheduler_->SentPacket(sequence_number, packet->length(), is_retransmit);
- if (!should_resend) delete packet;
+ delete packet;
return true;
}
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698