| 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);
|
|
|