| 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_fec_group.h" | 9 #include "net/quic/quic_fec_group.h" |
| 10 #include "net/quic/quic_utils.h" | 10 #include "net/quic/quic_utils.h" |
| 11 | 11 |
| 12 using base::StringPiece; | 12 using base::StringPiece; |
| 13 | 13 |
| 14 namespace net { | 14 namespace net { |
| 15 | 15 |
| 16 namespace { |
| 17 |
| 18 // We want to put some space between a protected packet and the FEC packet to |
| 19 // avoid losing them both within the same loss episode. On the other hand, |
| 20 // we expect to be able to recover from any loss in about an RTT. |
| 21 // We resolve this tradeoff by sending an FEC packet atmost half an RTT, |
| 22 // or equivalently, half a cwnd, after the first protected packet. Since we |
| 23 // don't want to delay an FEC packet past half an RTT, we set the max FEC |
| 24 // group size to be half the current congestion window. |
| 25 const float kCongestionWindowMultiplierForFecGroupSize = 0.5; |
| 26 |
| 27 } // namespace |
| 28 |
| 16 class QuicAckNotifier; | 29 class QuicAckNotifier; |
| 17 | 30 |
| 18 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, | 31 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, |
| 19 QuicFramer* framer, | 32 QuicFramer* framer, |
| 20 QuicRandom* random_generator, | 33 QuicRandom* random_generator, |
| 21 DelegateInterface* delegate) | 34 DelegateInterface* delegate) |
| 22 : delegate_(delegate), | 35 : delegate_(delegate), |
| 23 debug_delegate_(NULL), | 36 debug_delegate_(NULL), |
| 24 packet_creator_(connection_id, framer, random_generator), | 37 packet_creator_(connection_id, framer, random_generator), |
| 25 batch_mode_(false), | 38 batch_mode_(false), |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 break; | 78 break; |
| 66 case PING_FRAME: | 79 case PING_FRAME: |
| 67 delete it->ping_frame; | 80 delete it->ping_frame; |
| 68 break; | 81 break; |
| 69 case NUM_FRAME_TYPES: | 82 case NUM_FRAME_TYPES: |
| 70 DCHECK(false) << "Cannot delete type: " << it->type; | 83 DCHECK(false) << "Cannot delete type: " << it->type; |
| 71 } | 84 } |
| 72 } | 85 } |
| 73 } | 86 } |
| 74 | 87 |
| 88 // NetworkChangeVisitor method. |
| 89 void QuicPacketGenerator::OnCongestionWindowChange( |
| 90 QuicByteCount congestion_window) { |
| 91 packet_creator_.set_max_packets_per_fec_group( |
| 92 static_cast<size_t>(kCongestionWindowMultiplierForFecGroupSize * |
| 93 congestion_window / kDefaultTCPMSS)); |
| 94 } |
| 95 |
| 75 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback, | 96 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback, |
| 76 bool also_send_stop_waiting) { | 97 bool also_send_stop_waiting) { |
| 77 should_send_ack_ = true; | 98 should_send_ack_ = true; |
| 78 should_send_feedback_ = also_send_feedback; | 99 should_send_feedback_ = also_send_feedback; |
| 79 should_send_stop_waiting_ = also_send_stop_waiting; | 100 should_send_stop_waiting_ = also_send_stop_waiting; |
| 80 SendQueuedFrames(false); | 101 SendQueuedFrames(false); |
| 81 } | 102 } |
| 82 | 103 |
| 83 void QuicPacketGenerator::SetShouldSendStopWaiting() { | 104 void QuicPacketGenerator::SetShouldSendStopWaiting() { |
| 84 should_send_stop_waiting_ = true; | 105 should_send_stop_waiting_ = true; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 } | 180 } |
| 160 } | 181 } |
| 161 | 182 |
| 162 // Don't allow the handshake to be bundled with other retransmittable frames. | 183 // Don't allow the handshake to be bundled with other retransmittable frames. |
| 163 if (handshake == IS_HANDSHAKE) { | 184 if (handshake == IS_HANDSHAKE) { |
| 164 SendQueuedFrames(true); | 185 SendQueuedFrames(true); |
| 165 } | 186 } |
| 166 | 187 |
| 167 // Try to close FEC group since we've either run out of data to send or we're | 188 // Try to close FEC group since we've either run out of data to send or we're |
| 168 // blocked. If not in batch mode, force close the group. | 189 // blocked. If not in batch mode, force close the group. |
| 190 // TODO(jri): This method should be called with flush=false here |
| 191 // once the timer-based FEC sending is done, to separate FEC sending from |
| 192 // the end of batch operations. |
| 169 MaybeSendFecPacketAndCloseGroup(!InBatchMode()); | 193 MaybeSendFecPacketAndCloseGroup(!InBatchMode()); |
| 170 | 194 |
| 171 DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames()); | 195 DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames()); |
| 172 return QuicConsumedData(total_bytes_consumed, fin_consumed); | 196 return QuicConsumedData(total_bytes_consumed, fin_consumed); |
| 173 } | 197 } |
| 174 | 198 |
| 175 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { | 199 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { |
| 176 DCHECK(HasPendingFrames()); | 200 DCHECK(HasPendingFrames()); |
| 177 HasRetransmittableData retransmittable = | 201 HasRetransmittableData retransmittable = |
| 178 (should_send_ack_ || should_send_feedback_ || should_send_stop_waiting_) | 202 (should_send_ack_ || should_send_feedback_ || should_send_stop_waiting_) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 // generator to check if the resulting expansion still allows the incoming | 245 // generator to check if the resulting expansion still allows the incoming |
| 222 // frame to be added to the packet. | 246 // frame to be added to the packet. |
| 223 SendQueuedFrames(true); | 247 SendQueuedFrames(true); |
| 224 } | 248 } |
| 225 packet_creator_.StartFecProtectingPackets(); | 249 packet_creator_.StartFecProtectingPackets(); |
| 226 DCHECK(packet_creator_.IsFecProtected()); | 250 DCHECK(packet_creator_.IsFecProtected()); |
| 227 } | 251 } |
| 228 | 252 |
| 229 void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force) { | 253 void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force) { |
| 230 if (!packet_creator_.IsFecProtected() || | 254 if (!packet_creator_.IsFecProtected() || |
| 231 packet_creator_.HasPendingFrames()) { | 255 packet_creator_.HasPendingFrames() || |
| 256 !packet_creator_.ShouldSendFec(force)) { |
| 232 return; | 257 return; |
| 233 } | 258 } |
| 234 | 259 // TODO(jri): SerializeFec can return a NULL packet, and this should |
| 235 if (packet_creator_.ShouldSendFec(force)) { | 260 // cause an early return, with a call to delegate_->OnPacketGenerationError. |
| 236 // TODO(jri): SerializeFec can return a NULL packet, and this should | 261 SerializedPacket serialized_fec = packet_creator_.SerializeFec(); |
| 237 // cause an early return, with a call to | 262 DCHECK(serialized_fec.packet); |
| 238 // delegate_->OnPacketGenerationError. | 263 delegate_->OnSerializedPacket(serialized_fec); |
| 239 SerializedPacket serialized_fec = packet_creator_.SerializeFec(); | 264 // Turn FEC protection off if creator's protection is on and the creator |
| 240 DCHECK(serialized_fec.packet); | 265 // does not have an open FEC group. |
| 241 delegate_->OnSerializedPacket(serialized_fec); | |
| 242 } | |
| 243 | |
| 244 // Turn FEC protection off if the creator does not have an FEC group open. | |
| 245 // Note: We only wait until the frames queued in the creator are flushed; | 266 // Note: We only wait until the frames queued in the creator are flushed; |
| 246 // pending frames in the generator will not keep us from turning FEC off. | 267 // pending frames in the generator will not keep us from turning FEC off. |
| 247 if (!should_fec_protect_ && !packet_creator_.IsFecGroupOpen()) { | 268 if (!should_fec_protect_ && !packet_creator_.IsFecGroupOpen()) { |
| 248 packet_creator_.StopFecProtectingPackets(); | 269 packet_creator_.StopFecProtectingPackets(); |
| 249 DCHECK(!packet_creator_.IsFecProtected()); | 270 DCHECK(!packet_creator_.IsFecProtected()); |
| 250 } | 271 } |
| 251 } | 272 } |
| 252 | 273 |
| 253 bool QuicPacketGenerator::InBatchMode() { | 274 bool QuicPacketGenerator::InBatchMode() { |
| 254 return batch_mode_; | 275 return batch_mode_; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 QuicByteCount congestion_window) { | 383 QuicByteCount congestion_window) { |
| 363 return packet_creator_.UpdateSequenceNumberLength( | 384 return packet_creator_.UpdateSequenceNumberLength( |
| 364 least_packet_awaited_by_peer, congestion_window); | 385 least_packet_awaited_by_peer, congestion_window); |
| 365 } | 386 } |
| 366 | 387 |
| 367 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { | 388 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { |
| 368 packet_creator_.set_encryption_level(level); | 389 packet_creator_.set_encryption_level(level); |
| 369 } | 390 } |
| 370 | 391 |
| 371 } // namespace net | 392 } // namespace net |
| OLD | NEW |