Index: net/quic/quic_packet_generator.cc |
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc |
index b91ccc65289f61fa2236df87774d19ed3ed4bff2..782fa355688e8984146b788d36315e3c2a8c9dc8 100644 |
--- a/net/quic/quic_packet_generator.cc |
+++ b/net/quic/quic_packet_generator.cc |
@@ -22,6 +22,7 @@ QuicPacketGenerator::QuicPacketGenerator(DelegateInterface* delegate, |
debug_delegate_(debug_delegate), |
packet_creator_(creator), |
batch_mode_(false), |
+ should_fec_protect_(false), |
should_send_ack_(false), |
should_send_feedback_(false), |
should_send_stop_waiting_(false) { |
@@ -143,15 +144,9 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id, |
} |
} |
- // Ensure the FEC group is closed at the end of this method if not in batch |
- // mode. |
- if (!InBatchMode() && packet_creator_->ShouldSendFec(true)) { |
- // TODO(jri): SerializeFec can return a NULL packet, and this should |
- // cause an early return, with a call to delegate_->OnPacketGenerationError. |
- SerializedPacket serialized_fec = packet_creator_->SerializeFec(); |
- DCHECK(serialized_fec.packet); |
- delegate_->OnSerializedPacket(serialized_fec); |
- } |
+ // Try to close FEC group since we've either run out of data to send or we're |
+ // blocked. If not in batch mode, force close the group. |
+ MaybeSendFecPacketAndCloseGroup(!InBatchMode()); |
DCHECK(InBatchMode() || !packet_creator_->HasPendingFrames()); |
return QuicConsumedData(total_bytes_consumed, fin_consumed); |
@@ -183,17 +178,62 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush) { |
if (packet_creator_->HasPendingFrames()) { |
SerializeAndSendPacket(); |
} |
- |
// Ensure the FEC group is closed at the end of this method unless other |
// writes are pending. |
- if (packet_creator_->ShouldSendFec(true)) { |
- // TODO(jri): SerializeFec can return a NULL packet, and this should |
- // cause an early return, with a call to |
- // delegate_->OnPacketGenerationError. |
- SerializedPacket serialized_fec = packet_creator_->SerializeFec(); |
- DCHECK(serialized_fec.packet); |
- delegate_->OnSerializedPacket(serialized_fec); |
- } |
+ MaybeSendFecPacketAndCloseGroup(true); |
+ } |
+} |
+ |
+void QuicPacketGenerator::MaybeStartFecProtection() { |
+ if (!packet_creator_->IsFecEnabled()) { |
+ return; |
+ } |
+ DVLOG(1) << "Turning FEC protection ON"; |
+ should_fec_protect_ = true; |
+ if (packet_creator_->IsFecProtected()) { |
+ // Only start creator's FEC protection if not already on. |
+ return; |
+ } |
+ if (HasQueuedFrames()) { |
+ // TODO(jri): This currently requires that the generator flush out any |
+ // pending frames when FEC protection is turned on. If current packet can be |
+ // converted to an FEC protected packet, do it. This will require the |
+ // generator to check if the resulting expansion still allows the incoming |
+ // frame to be added to the packet. |
+ SendQueuedFrames(true); |
+ } |
+ packet_creator_->StartFecProtectingPackets(); |
+ DCHECK(packet_creator_->IsFecProtected()); |
+} |
+ |
+void QuicPacketGenerator::MaybeStopFecProtection(bool force) { |
+ DVLOG(1) << "Turning FEC protection OFF"; |
+ // FEC protection will stop after the next FEC packet is transmitted. |
+ should_fec_protect_ = false; |
+ MaybeSendFecPacketAndCloseGroup(force); |
+} |
+ |
+void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force) { |
+ if (!packet_creator_->IsFecProtected() || |
+ packet_creator_->HasPendingFrames()) { |
+ return; |
+ } |
+ |
+ if (packet_creator_->ShouldSendFec(force)) { |
+ // TODO(jri): SerializeFec can return a NULL packet, and this should |
+ // cause an early return, with a call to |
+ // delegate_->OnPacketGenerationError. |
+ SerializedPacket serialized_fec = packet_creator_->SerializeFec(); |
+ DCHECK(serialized_fec.packet); |
+ delegate_->OnSerializedPacket(serialized_fec); |
+ } |
+ |
+ // Turn FEC protection off if the creator does not have an FEC group open. |
+ // Note: We only wait until the frames queued in the creator are flushed; |
+ // pending frames in the generator will not keep us from turning FEC off. |
+ if (!should_fec_protect_ && !packet_creator_->IsFecGroupOpen()) { |
+ packet_creator_->StopFecProtectingPackets(); |
+ DCHECK(!packet_creator_->IsFecProtected()); |
} |
} |
@@ -274,14 +314,7 @@ void QuicPacketGenerator::SerializeAndSendPacket() { |
SerializedPacket serialized_packet = packet_creator_->SerializePacket(); |
DCHECK(serialized_packet.packet); |
delegate_->OnSerializedPacket(serialized_packet); |
- |
- if (packet_creator_->ShouldSendFec(false)) { |
- // TODO(jri): SerializeFec can return a NULL packet, and this should |
- // cause an early return, with a call to delegate_->OnPacketGenerationError. |
- SerializedPacket serialized_fec = packet_creator_->SerializeFec(); |
- DCHECK(serialized_fec.packet); |
- delegate_->OnSerializedPacket(serialized_fec); |
- } |
+ MaybeSendFecPacketAndCloseGroup(false); |
} |
} // namespace net |