Index: net/quic/quic_packet_generator.cc |
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc |
index 2262883e1ce9c9dc359722d1ecdc6e45e2563822..74617ef602e2855d79a455547655597f1f3dc627 100644 |
--- a/net/quic/quic_packet_generator.cc |
+++ b/net/quic/quic_packet_generator.cc |
@@ -6,6 +6,7 @@ |
#include "base/basictypes.h" |
#include "base/logging.h" |
+#include "net/quic/quic_ack_notifier.h" |
#include "net/quic/quic_fec_group.h" |
#include "net/quic/quic_flags.h" |
#include "net/quic/quic_utils.h" |
@@ -24,6 +25,7 @@ namespace { |
// protected packet. Since we don't want to delay an FEC packet past half an |
// RTT, we set the max FEC group size to be half the current congestion window. |
const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5; |
+const float kRttMultiplierForFecTimeout = 0.5; |
} // namespace |
@@ -37,10 +39,12 @@ QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, |
debug_delegate_(nullptr), |
packet_creator_(connection_id, framer, random_generator), |
batch_mode_(false), |
+ fec_timeout_(QuicTime::Delta::Zero()), |
should_fec_protect_(false), |
should_send_ack_(false), |
should_send_feedback_(false), |
- should_send_stop_waiting_(false) {} |
+ should_send_stop_waiting_(false) { |
+} |
QuicPacketGenerator::~QuicPacketGenerator() { |
for (QuicFrames::iterator it = queued_control_frames_.begin(); |
@@ -92,6 +96,10 @@ void QuicPacketGenerator::OnCongestionWindowChange( |
max_packets_in_flight)); |
} |
+void QuicPacketGenerator::OnRttChange(QuicTime::Delta rtt) { |
+ fec_timeout_ = rtt.Multiply(kRttMultiplierForFecTimeout); |
+} |
+ |
void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback, |
bool also_send_stop_waiting) { |
if (FLAGS_quic_disallow_multiple_pending_ack_frames) { |
@@ -127,12 +135,13 @@ void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) { |
SendQueuedFrames(false); |
} |
-QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id, |
- const IOVector& data_to_write, |
- QuicStreamOffset offset, |
- bool fin, |
- FecProtection fec_protection, |
- QuicAckNotifier* notifier) { |
+QuicConsumedData QuicPacketGenerator::ConsumeData( |
+ QuicStreamId id, |
+ const IOVector& data_to_write, |
+ QuicStreamOffset offset, |
+ bool fin, |
+ FecProtection fec_protection, |
+ QuicAckNotifier::DelegateInterface* delegate) { |
IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE; |
// To make reasoning about crypto frames easier, we don't combine them with |
// other retransmittable frames in a single packet. |
@@ -151,25 +160,37 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id, |
MaybeStartFecProtection(); |
} |
+ // This notifier will be owned by the AckNotifierManager (or deleted below) if |
+ // not attached to a packet. |
+ QuicAckNotifier* notifier = nullptr; |
+ if (delegate != nullptr) { |
+ notifier = new QuicAckNotifier(delegate); |
+ } |
+ |
IOVector data = data_to_write; |
size_t data_size = data.TotalBufferSize(); |
+ if (FLAGS_quic_empty_data_no_fin_early_return && !fin && (data_size == 0)) { |
+ LOG(DFATAL) << "Attempt to consume empty data without FIN."; |
+ return QuicConsumedData(0, false); |
+ } |
+ |
+ int frames_created = 0; |
while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, |
HAS_RETRANSMITTABLE_DATA, handshake)) { |
QuicFrame frame; |
- size_t bytes_consumed; |
- if (notifier != nullptr) { |
- // We want to track which packet this stream frame ends up in. |
- bytes_consumed = packet_creator_.CreateStreamFrameWithNotifier( |
- id, data, offset + total_bytes_consumed, fin, notifier, &frame); |
- } else { |
- bytes_consumed = packet_creator_.CreateStreamFrame( |
- id, data, offset + total_bytes_consumed, fin, &frame); |
- } |
+ size_t bytes_consumed = packet_creator_.CreateStreamFrame( |
+ id, data, offset + total_bytes_consumed, fin, &frame); |
+ ++frames_created; |
+ |
+ // We want to track which packet this stream frame ends up in. |
+ frame.stream_frame->notifier = notifier; |
+ |
if (!AddFrame(frame)) { |
LOG(DFATAL) << "Failed to add stream frame."; |
// Inability to add a STREAM frame creates an unrecoverable hole in a |
// the stream, so it's best to close the connection. |
delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false); |
+ delete notifier; |
return QuicConsumedData(0, false); |
} |
@@ -196,6 +217,11 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id, |
} |
} |
+ if (notifier != nullptr && frames_created == 0) { |
+ // Safe to delete the AckNotifer as it was never attached to a packet. |
+ delete notifier; |
+ } |
+ |
// Don't allow the handshake to be bundled with other retransmittable frames. |
if (handshake == IS_HANDSHAKE) { |
SendQueuedFrames(true); |