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_flags.h" | 10 #include "net/quic/quic_flags.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 } // namespace | 33 } // namespace |
34 | 34 |
35 class QuicAckNotifier; | 35 class QuicAckNotifier; |
36 | 36 |
37 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, | 37 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, |
38 QuicFramer* framer, | 38 QuicFramer* framer, |
39 QuicRandom* random_generator, | 39 QuicRandom* random_generator, |
40 DelegateInterface* delegate) | 40 DelegateInterface* delegate) |
41 : delegate_(delegate), | 41 : delegate_(delegate), |
42 debug_delegate_(nullptr), | 42 debug_delegate_(nullptr), |
43 packet_creator_(connection_id, framer, random_generator), | 43 packet_creator_(connection_id, framer, random_generator, this), |
44 batch_mode_(false), | 44 batch_mode_(false), |
45 fec_timeout_(QuicTime::Delta::Zero()), | 45 fec_timeout_(QuicTime::Delta::Zero()), |
46 rtt_multiplier_for_fec_timeout_(kRttMultiplierForFecTimeout), | 46 rtt_multiplier_for_fec_timeout_(kRttMultiplierForFecTimeout), |
47 should_fec_protect_(false), | 47 should_fec_protect_(false), |
48 fec_send_policy_(FEC_ANY_TRIGGER), | 48 fec_send_policy_(FEC_ANY_TRIGGER), |
49 should_send_ack_(false), | 49 should_send_ack_(false), |
50 should_send_stop_waiting_(false), | 50 should_send_stop_waiting_(false), |
51 ack_queued_(false), | 51 ack_queued_(false), |
52 stop_waiting_queued_(false), | 52 stop_waiting_queued_(false), |
53 max_packet_length_(kDefaultMaxPacketSize) {} | 53 max_packet_length_(kDefaultMaxPacketSize) {} |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 // To make reasoning about crypto frames easier, we don't combine them with | 132 // To make reasoning about crypto frames easier, we don't combine them with |
133 // other retransmittable frames in a single packet. | 133 // other retransmittable frames in a single packet. |
134 const bool flush = | 134 const bool flush = |
135 has_handshake && packet_creator_.HasPendingRetransmittableFrames(); | 135 has_handshake && packet_creator_.HasPendingRetransmittableFrames(); |
136 SendQueuedFrames(flush, /*is_fec_timeout=*/false); | 136 SendQueuedFrames(flush, /*is_fec_timeout=*/false); |
137 | 137 |
138 size_t total_bytes_consumed = 0; | 138 size_t total_bytes_consumed = 0; |
139 bool fin_consumed = false; | 139 bool fin_consumed = false; |
140 | 140 |
141 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) { | 141 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) { |
142 SerializeAndSendPacket(); | 142 packet_creator_.Flush(); |
143 } | 143 } |
144 | 144 |
145 if (fec_protection == MUST_FEC_PROTECT) { | 145 if (fec_protection == MUST_FEC_PROTECT) { |
146 MaybeStartFecProtection(); | 146 MaybeStartFecProtection(); |
147 } | 147 } |
148 | 148 |
149 if (!fin && (iov.total_length == 0)) { | 149 if (!fin && (iov.total_length == 0)) { |
150 LOG(DFATAL) << "Attempt to consume empty data without FIN."; | 150 LOG(DFATAL) << "Attempt to consume empty data without FIN."; |
151 return QuicConsumedData(0, false); | 151 return QuicConsumedData(0, false); |
152 } | 152 } |
153 | 153 |
154 int frames_created = 0; | |
155 while (delegate_->ShouldGeneratePacket( | 154 while (delegate_->ShouldGeneratePacket( |
156 HAS_RETRANSMITTABLE_DATA, has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) { | 155 HAS_RETRANSMITTABLE_DATA, has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) { |
157 QuicFrame frame; | 156 QuicFrame frame; |
158 UniqueStreamBuffer buffer; | 157 if (!packet_creator_.ConsumeData(id, iov, total_bytes_consumed, |
159 size_t bytes_consumed = packet_creator_.CreateStreamFrame( | 158 offset + total_bytes_consumed, fin, |
160 id, iov, total_bytes_consumed, offset + total_bytes_consumed, fin, | 159 has_handshake, &frame)) { |
161 &frame, &buffer); | 160 // Current packet is full and flushed. |
162 ++frames_created; | 161 continue; |
| 162 } |
163 | 163 |
164 if (!AddFrame(frame, buffer.Pass(), has_handshake)) { | 164 // A stream frame is created and added. |
165 LOG(DFATAL) << "Failed to add stream frame."; | 165 size_t bytes_consumed = frame.stream_frame->data.length(); |
166 // Inability to add a STREAM frame creates an unrecoverable hole in a | 166 if (debug_delegate_ != nullptr) { |
167 // the stream, so it's best to close the connection. | 167 debug_delegate_->OnFrameAddedToPacket(frame); |
168 delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false); | |
169 return QuicConsumedData(0, false); | |
170 } | 168 } |
| 169 |
171 if (listener != nullptr) { | 170 if (listener != nullptr) { |
172 ack_listeners_.push_back(AckListenerWrapper(listener, bytes_consumed)); | 171 ack_listeners_.push_back(AckListenerWrapper(listener, bytes_consumed)); |
173 } | 172 } |
174 | 173 |
175 total_bytes_consumed += bytes_consumed; | 174 total_bytes_consumed += bytes_consumed; |
176 fin_consumed = fin && total_bytes_consumed == iov.total_length; | 175 fin_consumed = fin && total_bytes_consumed == iov.total_length; |
177 DCHECK(total_bytes_consumed == iov.total_length || | 176 DCHECK(total_bytes_consumed == iov.total_length || |
178 packet_creator_.BytesFree() == 0u); | 177 (bytes_consumed > 0 && packet_creator_.HasPendingFrames())); |
179 | 178 |
180 if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) { | 179 if (!InBatchMode()) { |
181 // TODO(rtenneti): remove MaybeSendFecPacketAndCloseGroup() from inside | 180 // TODO(rtenneti): remove MaybeSendFecPacketAndCloseGroup() from inside |
182 // SerializeAndSendPacket() and make it an explicit call here (and | 181 // SerializeAndSendPacket() and make it an explicit call here (and |
183 // elsewhere where we call SerializeAndSendPacket?). | 182 // elsewhere where we call SerializeAndSendPacket?). |
184 SerializeAndSendPacket(); | 183 packet_creator_.Flush(); |
185 } | 184 } |
186 | 185 |
187 if (total_bytes_consumed == iov.total_length) { | 186 if (total_bytes_consumed == iov.total_length) { |
188 // We're done writing the data. Exit the loop. | 187 // We're done writing the data. Exit the loop. |
189 // We don't make this a precondition because we could have 0 bytes of data | 188 // We don't make this a precondition because we could have 0 bytes of data |
190 // if we're simply writing a fin. | 189 // if we're simply writing a fin. |
191 if (fec_protection == MUST_FEC_PROTECT) { | 190 if (fec_protection == MUST_FEC_PROTECT) { |
192 // Turn off FEC protection when we're done writing protected data. | 191 // Turn off FEC protection when we're done writing protected data. |
193 DVLOG(1) << "Turning FEC protection OFF"; | 192 DVLOG(1) << "Turning FEC protection OFF"; |
194 should_fec_protect_ = false; | 193 should_fec_protect_ = false; |
(...skipping 26 matching lines...) Expand all Loading... |
221 // serialized within this function. | 220 // serialized within this function. |
222 QuicMtuDiscoveryFrame mtu_discovery_frame; | 221 QuicMtuDiscoveryFrame mtu_discovery_frame; |
223 QuicFrame frame(mtu_discovery_frame); | 222 QuicFrame frame(mtu_discovery_frame); |
224 | 223 |
225 // Send the probe packet with the new length. | 224 // Send the probe packet with the new length. |
226 SetMaxPacketLength(target_mtu, /*force=*/true); | 225 SetMaxPacketLength(target_mtu, /*force=*/true); |
227 const bool success = AddFrame(frame, nullptr, /*needs_padding=*/true); | 226 const bool success = AddFrame(frame, nullptr, /*needs_padding=*/true); |
228 if (listener != nullptr) { | 227 if (listener != nullptr) { |
229 ack_listeners_.push_back(AckListenerWrapper(listener, 0)); | 228 ack_listeners_.push_back(AckListenerWrapper(listener, 0)); |
230 } | 229 } |
231 SerializeAndSendPacket(); | 230 packet_creator_.Flush(); |
232 // The only reason AddFrame can fail is that the packet is too full to fit in | 231 // The only reason AddFrame can fail is that the packet is too full to fit in |
233 // a ping. This is not possible for any sane MTU. | 232 // a ping. This is not possible for any sane MTU. |
234 DCHECK(success); | 233 DCHECK(success); |
235 | 234 |
236 // Reset the packet length back. | 235 // Reset the packet length back. |
237 SetMaxPacketLength(current_mtu, /*force=*/true); | 236 SetMaxPacketLength(current_mtu, /*force=*/true); |
238 } | 237 } |
239 | 238 |
240 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { | 239 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const { |
241 DCHECK(HasPendingFrames()); | 240 DCHECK(HasPendingFrames()); |
242 HasRetransmittableData retransmittable = | 241 HasRetransmittableData retransmittable = |
243 (should_send_ack_ || should_send_stop_waiting_) | 242 (should_send_ack_ || should_send_stop_waiting_) |
244 ? NO_RETRANSMITTABLE_DATA | 243 ? NO_RETRANSMITTABLE_DATA |
245 : HAS_RETRANSMITTABLE_DATA; | 244 : HAS_RETRANSMITTABLE_DATA; |
246 if (retransmittable == HAS_RETRANSMITTABLE_DATA) { | 245 if (retransmittable == HAS_RETRANSMITTABLE_DATA) { |
247 DCHECK(!queued_control_frames_.empty()); // These are retransmittable. | 246 DCHECK(!queued_control_frames_.empty()); // These are retransmittable. |
248 } | 247 } |
249 return delegate_->ShouldGeneratePacket(retransmittable, NOT_HANDSHAKE); | 248 return delegate_->ShouldGeneratePacket(retransmittable, NOT_HANDSHAKE); |
250 } | 249 } |
251 | 250 |
252 void QuicPacketGenerator::SendQueuedFrames(bool flush, bool is_fec_timeout) { | 251 void QuicPacketGenerator::SendQueuedFrames(bool flush, bool is_fec_timeout) { |
253 // Only add pending frames if we are SURE we can then send the whole packet. | 252 // Only add pending frames if we are SURE we can then send the whole packet. |
254 while (HasPendingFrames() && | 253 while (HasPendingFrames() && |
255 (flush || CanSendWithNextPendingFrameAddition())) { | 254 (flush || CanSendWithNextPendingFrameAddition())) { |
256 if (!AddNextPendingFrame()) { | 255 AddNextPendingFrame(); |
257 // Packet was full, so serialize and send it. | |
258 SerializeAndSendPacket(); | |
259 } | |
260 } | 256 } |
261 if (packet_creator_.HasPendingFrames() && (flush || !InBatchMode())) { | 257 if (flush || !InBatchMode()) { |
262 SerializeAndSendPacket(); | 258 packet_creator_.Flush(); |
263 } | 259 } |
264 MaybeSendFecPacketAndCloseGroup(flush, is_fec_timeout); | 260 MaybeSendFecPacketAndCloseGroup(flush, is_fec_timeout); |
265 } | 261 } |
266 | 262 |
267 void QuicPacketGenerator::MaybeStartFecProtection() { | 263 void QuicPacketGenerator::MaybeStartFecProtection() { |
268 if (!packet_creator_.IsFecEnabled()) { | 264 if (!packet_creator_.IsFecEnabled()) { |
269 return; | 265 return; |
270 } | 266 } |
271 DVLOG(1) << "Turning FEC protection ON"; | 267 DVLOG(1) << "Turning FEC protection ON"; |
272 should_fec_protect_ = true; | 268 should_fec_protect_ = true; |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 bool needs_padding) { | 413 bool needs_padding) { |
418 bool success = needs_padding | 414 bool success = needs_padding |
419 ? packet_creator_.AddPaddedSavedFrame(frame, buffer.Pass()) | 415 ? packet_creator_.AddPaddedSavedFrame(frame, buffer.Pass()) |
420 : packet_creator_.AddSavedFrame(frame, buffer.Pass()); | 416 : packet_creator_.AddSavedFrame(frame, buffer.Pass()); |
421 if (success && debug_delegate_) { | 417 if (success && debug_delegate_) { |
422 debug_delegate_->OnFrameAddedToPacket(frame); | 418 debug_delegate_->OnFrameAddedToPacket(frame); |
423 } | 419 } |
424 return success; | 420 return success; |
425 } | 421 } |
426 | 422 |
427 void QuicPacketGenerator::SerializeAndSendPacket() { | |
428 // The optimized encryption algorithm implementations run faster when | |
429 // operating on aligned memory. | |
430 // | |
431 // TODO(rtenneti): Change the default 64 alignas value (used the default | |
432 // value from CACHELINE_SIZE). | |
433 ALIGNAS(64) char buffer[kMaxPacketSize]; | |
434 SerializedPacket serialized_packet = | |
435 packet_creator_.SerializePacket(buffer, kMaxPacketSize); | |
436 if (serialized_packet.packet == nullptr) { | |
437 LOG(DFATAL) << "Failed to SerializePacket. fec_policy:" << fec_send_policy_ | |
438 << " should_fec_protect_:" << should_fec_protect_; | |
439 delegate_->CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false); | |
440 return; | |
441 } | |
442 | |
443 // There may be AckListeners interested in this packet. | |
444 serialized_packet.listeners.swap(ack_listeners_); | |
445 ack_listeners_.clear(); | |
446 | |
447 delegate_->OnSerializedPacket(serialized_packet); | |
448 MaybeSendFecPacketAndCloseGroup(/*force=*/false, /*is_fec_timeout=*/false); | |
449 | |
450 // Maximum packet size may be only enacted while no packet is currently being | |
451 // constructed, so here we have a good opportunity to actually change it. | |
452 if (packet_creator_.CanSetMaxPacketLength()) { | |
453 packet_creator_.SetMaxPacketLength(max_packet_length_); | |
454 } | |
455 | |
456 // The packet has now been serialized, so the frames are no longer queued. | |
457 ack_queued_ = false; | |
458 stop_waiting_queued_ = false; | |
459 } | |
460 | |
461 void QuicPacketGenerator::StopSendingVersion() { | 423 void QuicPacketGenerator::StopSendingVersion() { |
462 packet_creator_.StopSendingVersion(); | 424 packet_creator_.StopSendingVersion(); |
463 } | 425 } |
464 | 426 |
465 QuicPacketNumber QuicPacketGenerator::packet_number() const { | 427 QuicPacketNumber QuicPacketGenerator::packet_number() const { |
466 return packet_creator_.packet_number(); | 428 return packet_creator_.packet_number(); |
467 } | 429 } |
468 | 430 |
469 QuicByteCount QuicPacketGenerator::GetMaxPacketLength() const { | 431 QuicByteCount QuicPacketGenerator::GetMaxPacketLength() const { |
470 return max_packet_length_; | 432 return max_packet_length_; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 | 487 |
526 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { | 488 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { |
527 packet_creator_.set_encryption_level(level); | 489 packet_creator_.set_encryption_level(level); |
528 } | 490 } |
529 | 491 |
530 void QuicPacketGenerator::SetEncrypter(EncryptionLevel level, | 492 void QuicPacketGenerator::SetEncrypter(EncryptionLevel level, |
531 QuicEncrypter* encrypter) { | 493 QuicEncrypter* encrypter) { |
532 packet_creator_.SetEncrypter(level, encrypter); | 494 packet_creator_.SetEncrypter(level, encrypter); |
533 } | 495 } |
534 | 496 |
| 497 void QuicPacketGenerator::OnSerializedPacket( |
| 498 SerializedPacket* serialized_packet) { |
| 499 if (serialized_packet->packet == nullptr) { |
| 500 LOG(DFATAL) << "Failed to SerializePacket. fec_policy:" << fec_send_policy_ |
| 501 << " should_fec_protect_:" << should_fec_protect_; |
| 502 delegate_->CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false); |
| 503 return; |
| 504 } |
| 505 |
| 506 // There may be AckListeners interested in this packet. |
| 507 serialized_packet->listeners.swap(ack_listeners_); |
| 508 ack_listeners_.clear(); |
| 509 |
| 510 delegate_->OnSerializedPacket(*serialized_packet); |
| 511 MaybeSendFecPacketAndCloseGroup(/*force=*/false, /*is_fec_timeout=*/false); |
| 512 |
| 513 // Maximum packet size may be only enacted while no packet is currently being |
| 514 // constructed, so here we have a good opportunity to actually change it. |
| 515 if (packet_creator_.CanSetMaxPacketLength()) { |
| 516 packet_creator_.SetMaxPacketLength(max_packet_length_); |
| 517 } |
| 518 |
| 519 // The packet has now been serialized, so the frames are no longer queued. |
| 520 ack_queued_ = false; |
| 521 stop_waiting_queued_ = false; |
| 522 } |
| 523 |
535 } // namespace net | 524 } // namespace net |
OLD | NEW |