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 |