| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_packet_generator.h" | 5 #include "net/quic/quic_packet_generator.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "net/quic/quic_ack_notifier.h" |
| 9 #include "net/quic/quic_fec_group.h" | 10 #include "net/quic/quic_fec_group.h" |
| 10 #include "net/quic/quic_flags.h" | 11 #include "net/quic/quic_flags.h" |
| 11 #include "net/quic/quic_utils.h" | 12 #include "net/quic/quic_utils.h" |
| 12 | 13 |
| 13 using base::StringPiece; | 14 using base::StringPiece; |
| 14 | 15 |
| 15 namespace net { | 16 namespace net { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 // We want to put some space between a protected packet and the FEC packet to | 20 // We want to put some space between a protected packet and the FEC packet to |
| 20 // avoid losing them both within the same loss episode. On the other hand, | 21 // avoid losing them both within the same loss episode. On the other hand, |
| 21 // we expect to be able to recover from any loss in about an RTT. | 22 // we expect to be able to recover from any loss in about an RTT. |
| 22 // We resolve this tradeoff by sending an FEC packet atmost half an RTT, | 23 // We resolve this tradeoff by sending an FEC packet atmost half an RTT, |
| 23 // or equivalently, half the max number of in-flight packets, the first | 24 // or equivalently, half the max number of in-flight packets, the first |
| 24 // protected packet. Since we don't want to delay an FEC packet past half an | 25 // protected packet. Since we don't want to delay an FEC packet past half an |
| 25 // RTT, we set the max FEC group size to be half the current congestion window. | 26 // RTT, we set the max FEC group size to be half the current congestion window. |
| 26 const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5; | 27 const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5; |
| 28 const float kRttMultiplierForFecTimeout = 0.5; |
| 27 | 29 |
| 28 } // namespace | 30 } // namespace |
| 29 | 31 |
| 30 class QuicAckNotifier; | 32 class QuicAckNotifier; |
| 31 | 33 |
| 32 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, | 34 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, |
| 33 QuicFramer* framer, | 35 QuicFramer* framer, |
| 34 QuicRandom* random_generator, | 36 QuicRandom* random_generator, |
| 35 DelegateInterface* delegate) | 37 DelegateInterface* delegate) |
| 36 : delegate_(delegate), | 38 : delegate_(delegate), |
| 37 debug_delegate_(nullptr), | 39 debug_delegate_(nullptr), |
| 38 packet_creator_(connection_id, framer, random_generator), | 40 packet_creator_(connection_id, framer, random_generator), |
| 39 batch_mode_(false), | 41 batch_mode_(false), |
| 42 fec_timeout_(QuicTime::Delta::Zero()), |
| 40 should_fec_protect_(false), | 43 should_fec_protect_(false), |
| 41 should_send_ack_(false), | 44 should_send_ack_(false), |
| 42 should_send_feedback_(false), | 45 should_send_feedback_(false), |
| 43 should_send_stop_waiting_(false) {} | 46 should_send_stop_waiting_(false) { |
| 47 } |
| 44 | 48 |
| 45 QuicPacketGenerator::~QuicPacketGenerator() { | 49 QuicPacketGenerator::~QuicPacketGenerator() { |
| 46 for (QuicFrames::iterator it = queued_control_frames_.begin(); | 50 for (QuicFrames::iterator it = queued_control_frames_.begin(); |
| 47 it != queued_control_frames_.end(); ++it) { | 51 it != queued_control_frames_.end(); ++it) { |
| 48 switch (it->type) { | 52 switch (it->type) { |
| 49 case PADDING_FRAME: | 53 case PADDING_FRAME: |
| 50 delete it->padding_frame; | 54 delete it->padding_frame; |
| 51 break; | 55 break; |
| 52 case STREAM_FRAME: | 56 case STREAM_FRAME: |
| 53 delete it->stream_frame; | 57 delete it->stream_frame; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 } | 89 } |
| 86 } | 90 } |
| 87 | 91 |
| 88 void QuicPacketGenerator::OnCongestionWindowChange( | 92 void QuicPacketGenerator::OnCongestionWindowChange( |
| 89 QuicPacketCount max_packets_in_flight) { | 93 QuicPacketCount max_packets_in_flight) { |
| 90 packet_creator_.set_max_packets_per_fec_group( | 94 packet_creator_.set_max_packets_per_fec_group( |
| 91 static_cast<size_t>(kMaxPacketsInFlightMultiplierForFecGroupSize * | 95 static_cast<size_t>(kMaxPacketsInFlightMultiplierForFecGroupSize * |
| 92 max_packets_in_flight)); | 96 max_packets_in_flight)); |
| 93 } | 97 } |
| 94 | 98 |
| 99 void QuicPacketGenerator::OnRttChange(QuicTime::Delta rtt) { |
| 100 fec_timeout_ = rtt.Multiply(kRttMultiplierForFecTimeout); |
| 101 } |
| 102 |
| 95 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback, | 103 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback, |
| 96 bool also_send_stop_waiting) { | 104 bool also_send_stop_waiting) { |
| 97 if (FLAGS_quic_disallow_multiple_pending_ack_frames) { | 105 if (FLAGS_quic_disallow_multiple_pending_ack_frames) { |
| 98 if (pending_ack_frame_ != nullptr) { | 106 if (pending_ack_frame_ != nullptr) { |
| 99 // Ack already queued, nothing to do. | 107 // Ack already queued, nothing to do. |
| 100 return; | 108 return; |
| 101 } | 109 } |
| 102 | 110 |
| 103 if (also_send_feedback && pending_feedback_frame_ != nullptr) { | 111 if (also_send_feedback && pending_feedback_frame_ != nullptr) { |
| 104 LOG(DFATAL) << "Should only ever be one pending feedback frame."; | 112 LOG(DFATAL) << "Should only ever be one pending feedback frame."; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 120 void QuicPacketGenerator::SetShouldSendStopWaiting() { | 128 void QuicPacketGenerator::SetShouldSendStopWaiting() { |
| 121 should_send_stop_waiting_ = true; | 129 should_send_stop_waiting_ = true; |
| 122 SendQueuedFrames(false); | 130 SendQueuedFrames(false); |
| 123 } | 131 } |
| 124 | 132 |
| 125 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) { | 133 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) { |
| 126 queued_control_frames_.push_back(frame); | 134 queued_control_frames_.push_back(frame); |
| 127 SendQueuedFrames(false); | 135 SendQueuedFrames(false); |
| 128 } | 136 } |
| 129 | 137 |
| 130 QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id, | 138 QuicConsumedData QuicPacketGenerator::ConsumeData( |
| 131 const IOVector& data_to_write, | 139 QuicStreamId id, |
| 132 QuicStreamOffset offset, | 140 const IOVector& data_to_write, |
| 133 bool fin, | 141 QuicStreamOffset offset, |
| 134 FecProtection fec_protection, | 142 bool fin, |
| 135 QuicAckNotifier* notifier) { | 143 FecProtection fec_protection, |
| 144 QuicAckNotifier::DelegateInterface* delegate) { |
| 136 IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE; | 145 IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE; |
| 137 // To make reasoning about crypto frames easier, we don't combine them with | 146 // To make reasoning about crypto frames easier, we don't combine them with |
| 138 // other retransmittable frames in a single packet. | 147 // other retransmittable frames in a single packet. |
| 139 const bool flush = handshake == IS_HANDSHAKE && | 148 const bool flush = handshake == IS_HANDSHAKE && |
| 140 packet_creator_.HasPendingRetransmittableFrames(); | 149 packet_creator_.HasPendingRetransmittableFrames(); |
| 141 SendQueuedFrames(flush); | 150 SendQueuedFrames(flush); |
| 142 | 151 |
| 143 size_t total_bytes_consumed = 0; | 152 size_t total_bytes_consumed = 0; |
| 144 bool fin_consumed = false; | 153 bool fin_consumed = false; |
| 145 | 154 |
| 146 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) { | 155 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) { |
| 147 SerializeAndSendPacket(); | 156 SerializeAndSendPacket(); |
| 148 } | 157 } |
| 149 | 158 |
| 150 if (fec_protection == MUST_FEC_PROTECT) { | 159 if (fec_protection == MUST_FEC_PROTECT) { |
| 151 MaybeStartFecProtection(); | 160 MaybeStartFecProtection(); |
| 152 } | 161 } |
| 153 | 162 |
| 163 // This notifier will be owned by the AckNotifierManager (or deleted below) if |
| 164 // not attached to a packet. |
| 165 QuicAckNotifier* notifier = nullptr; |
| 166 if (delegate != nullptr) { |
| 167 notifier = new QuicAckNotifier(delegate); |
| 168 } |
| 169 |
| 154 IOVector data = data_to_write; | 170 IOVector data = data_to_write; |
| 155 size_t data_size = data.TotalBufferSize(); | 171 size_t data_size = data.TotalBufferSize(); |
| 172 if (FLAGS_quic_empty_data_no_fin_early_return && !fin && (data_size == 0)) { |
| 173 LOG(DFATAL) << "Attempt to consume empty data without FIN."; |
| 174 return QuicConsumedData(0, false); |
| 175 } |
| 176 |
| 177 int frames_created = 0; |
| 156 while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, | 178 while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, |
| 157 HAS_RETRANSMITTABLE_DATA, handshake)) { | 179 HAS_RETRANSMITTABLE_DATA, handshake)) { |
| 158 QuicFrame frame; | 180 QuicFrame frame; |
| 159 size_t bytes_consumed; | 181 size_t bytes_consumed = packet_creator_.CreateStreamFrame( |
| 160 if (notifier != nullptr) { | 182 id, data, offset + total_bytes_consumed, fin, &frame); |
| 161 // We want to track which packet this stream frame ends up in. | 183 ++frames_created; |
| 162 bytes_consumed = packet_creator_.CreateStreamFrameWithNotifier( | 184 |
| 163 id, data, offset + total_bytes_consumed, fin, notifier, &frame); | 185 // We want to track which packet this stream frame ends up in. |
| 164 } else { | 186 frame.stream_frame->notifier = notifier; |
| 165 bytes_consumed = packet_creator_.CreateStreamFrame( | 187 |
| 166 id, data, offset + total_bytes_consumed, fin, &frame); | |
| 167 } | |
| 168 if (!AddFrame(frame)) { | 188 if (!AddFrame(frame)) { |
| 169 LOG(DFATAL) << "Failed to add stream frame."; | 189 LOG(DFATAL) << "Failed to add stream frame."; |
| 170 // Inability to add a STREAM frame creates an unrecoverable hole in a | 190 // Inability to add a STREAM frame creates an unrecoverable hole in a |
| 171 // the stream, so it's best to close the connection. | 191 // the stream, so it's best to close the connection. |
| 172 delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false); | 192 delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false); |
| 193 delete notifier; |
| 173 return QuicConsumedData(0, false); | 194 return QuicConsumedData(0, false); |
| 174 } | 195 } |
| 175 | 196 |
| 176 total_bytes_consumed += bytes_consumed; | 197 total_bytes_consumed += bytes_consumed; |
| 177 fin_consumed = fin && total_bytes_consumed == data_size; | 198 fin_consumed = fin && total_bytes_consumed == data_size; |
| 178 data.Consume(bytes_consumed); | 199 data.Consume(bytes_consumed); |
| 179 DCHECK(data.Empty() || packet_creator_.BytesFree() == 0u); | 200 DCHECK(data.Empty() || packet_creator_.BytesFree() == 0u); |
| 180 | 201 |
| 181 // TODO(ianswett): Restore packet reordering. | 202 // TODO(ianswett): Restore packet reordering. |
| 182 if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) { | 203 if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) { |
| 183 SerializeAndSendPacket(); | 204 SerializeAndSendPacket(); |
| 184 } | 205 } |
| 185 | 206 |
| 186 if (data.Empty()) { | 207 if (data.Empty()) { |
| 187 // We're done writing the data. Exit the loop. | 208 // We're done writing the data. Exit the loop. |
| 188 // We don't make this a precondition because we could have 0 bytes of data | 209 // We don't make this a precondition because we could have 0 bytes of data |
| 189 // if we're simply writing a fin. | 210 // if we're simply writing a fin. |
| 190 if (fec_protection == MUST_FEC_PROTECT) { | 211 if (fec_protection == MUST_FEC_PROTECT) { |
| 191 // Turn off FEC protection when we're done writing protected data. | 212 // Turn off FEC protection when we're done writing protected data. |
| 192 DVLOG(1) << "Turning FEC protection OFF"; | 213 DVLOG(1) << "Turning FEC protection OFF"; |
| 193 should_fec_protect_ = false; | 214 should_fec_protect_ = false; |
| 194 } | 215 } |
| 195 break; | 216 break; |
| 196 } | 217 } |
| 197 } | 218 } |
| 198 | 219 |
| 220 if (notifier != nullptr && frames_created == 0) { |
| 221 // Safe to delete the AckNotifer as it was never attached to a packet. |
| 222 delete notifier; |
| 223 } |
| 224 |
| 199 // Don't allow the handshake to be bundled with other retransmittable frames. | 225 // Don't allow the handshake to be bundled with other retransmittable frames. |
| 200 if (handshake == IS_HANDSHAKE) { | 226 if (handshake == IS_HANDSHAKE) { |
| 201 SendQueuedFrames(true); | 227 SendQueuedFrames(true); |
| 202 } | 228 } |
| 203 | 229 |
| 204 // Try to close FEC group since we've either run out of data to send or we're | 230 // Try to close FEC group since we've either run out of data to send or we're |
| 205 // blocked. If not in batch mode, force close the group. | 231 // blocked. If not in batch mode, force close the group. |
| 206 // TODO(jri): This method should be called with flush=false here | 232 // TODO(jri): This method should be called with flush=false here |
| 207 // once the timer-based FEC sending is done, to separate FEC sending from | 233 // once the timer-based FEC sending is done, to separate FEC sending from |
| 208 // the end of batch operations. | 234 // the end of batch operations. |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 packet_creator_.set_connection_id_length(PACKET_8BYTE_CONNECTION_ID); | 445 packet_creator_.set_connection_id_length(PACKET_8BYTE_CONNECTION_ID); |
| 420 } | 446 } |
| 421 } | 447 } |
| 422 | 448 |
| 423 | 449 |
| 424 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { | 450 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { |
| 425 packet_creator_.set_encryption_level(level); | 451 packet_creator_.set_encryption_level(level); |
| 426 } | 452 } |
| 427 | 453 |
| 428 } // namespace net | 454 } // namespace net |
| OLD | NEW |