Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(702)

Side by Side Diff: net/quic/quic_packet_generator.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_packet_generator.h ('k') | net/quic/quic_packet_generator_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/quic/quic_packet_generator.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "net/quic/quic_ack_notifier.h"
10 #include "net/quic/quic_fec_group.h"
11 #include "net/quic/quic_flags.h"
12 #include "net/quic/quic_utils.h"
13
14 using base::StringPiece;
15
16 namespace net {
17
18 namespace {
19
20 // We want to put some space between a protected packet and the FEC packet to
21 // avoid losing them both within the same loss episode. On the other hand, we
22 // expect to be able to recover from any loss in about an RTT. We resolve this
23 // tradeoff by sending an FEC packet atmost half an RTT, or equivalently, half
24 // the max number of in-flight packets, the first protected packet. Since we
25 // don't want to delay an FEC packet past half an RTT, we set the max FEC group
26 // size to be half the current congestion window.
27 const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5;
28 const float kRttMultiplierForFecTimeout = 0.5;
29
30 // Minimum timeout for FEC alarm, set to half the minimum Tail Loss Probe
31 // timeout of 10ms.
32 const int64 kMinFecTimeoutMs = 5u;
33
34 } // namespace
35
36 class QuicAckNotifier;
37
38 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
39 QuicFramer* framer,
40 QuicRandom* random_generator,
41 DelegateInterface* delegate)
42 : delegate_(delegate),
43 debug_delegate_(nullptr),
44 packet_creator_(connection_id, framer, random_generator),
45 batch_mode_(false),
46 fec_timeout_(QuicTime::Delta::Zero()),
47 should_fec_protect_(false),
48 should_send_ack_(false),
49 should_send_stop_waiting_(false),
50 ack_queued_(false),
51 stop_waiting_queued_(false) {
52 }
53
54 QuicPacketGenerator::~QuicPacketGenerator() {
55 for (QuicFrames::iterator it = queued_control_frames_.begin();
56 it != queued_control_frames_.end(); ++it) {
57 switch (it->type) {
58 case PADDING_FRAME:
59 delete it->padding_frame;
60 break;
61 case STREAM_FRAME:
62 delete it->stream_frame;
63 break;
64 case ACK_FRAME:
65 delete it->ack_frame;
66 break;
67 case RST_STREAM_FRAME:
68 delete it->rst_stream_frame;
69 break;
70 case CONNECTION_CLOSE_FRAME:
71 delete it->connection_close_frame;
72 break;
73 case GOAWAY_FRAME:
74 delete it->goaway_frame;
75 break;
76 case WINDOW_UPDATE_FRAME:
77 delete it->window_update_frame;
78 break;
79 case BLOCKED_FRAME:
80 delete it->blocked_frame;
81 break;
82 case STOP_WAITING_FRAME:
83 delete it->stop_waiting_frame;
84 break;
85 case PING_FRAME:
86 delete it->ping_frame;
87 break;
88 case NUM_FRAME_TYPES:
89 DCHECK(false) << "Cannot delete type: " << it->type;
90 }
91 }
92 }
93
94 void QuicPacketGenerator::OnCongestionWindowChange(
95 QuicPacketCount max_packets_in_flight) {
96 packet_creator_.set_max_packets_per_fec_group(
97 static_cast<size_t>(kMaxPacketsInFlightMultiplierForFecGroupSize *
98 max_packets_in_flight));
99 }
100
101 void QuicPacketGenerator::OnRttChange(QuicTime::Delta rtt) {
102 fec_timeout_ = rtt.Multiply(kRttMultiplierForFecTimeout);
103 }
104
105 void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
106 if (ack_queued_) {
107 // Ack already queued, nothing to do.
108 return;
109 }
110
111 if (also_send_stop_waiting && stop_waiting_queued_) {
112 LOG(DFATAL) << "Should only ever be one pending stop waiting frame.";
113 return;
114 }
115
116 should_send_ack_ = true;
117 should_send_stop_waiting_ = also_send_stop_waiting;
118 SendQueuedFrames(false);
119 }
120
121 void QuicPacketGenerator::SetShouldSendStopWaiting() {
122 should_send_stop_waiting_ = true;
123 SendQueuedFrames(false);
124 }
125
126 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
127 queued_control_frames_.push_back(frame);
128 SendQueuedFrames(false);
129 }
130
131 QuicConsumedData QuicPacketGenerator::ConsumeData(
132 QuicStreamId id,
133 const IOVector& data_to_write,
134 QuicStreamOffset offset,
135 bool fin,
136 FecProtection fec_protection,
137 QuicAckNotifier::DelegateInterface* delegate) {
138 bool has_handshake = id == kCryptoStreamId;
139 // To make reasoning about crypto frames easier, we don't combine them with
140 // other retransmittable frames in a single packet.
141 const bool flush =
142 has_handshake && packet_creator_.HasPendingRetransmittableFrames();
143 SendQueuedFrames(flush);
144
145 size_t total_bytes_consumed = 0;
146 bool fin_consumed = false;
147
148 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) {
149 SerializeAndSendPacket();
150 }
151
152 if (fec_protection == MUST_FEC_PROTECT) {
153 MaybeStartFecProtection();
154 }
155
156 // This notifier will be owned by the AckNotifierManager (or deleted below) if
157 // not attached to a packet.
158 QuicAckNotifier* notifier = nullptr;
159 if (delegate != nullptr) {
160 notifier = new QuicAckNotifier(delegate);
161 }
162
163 IOVector data = data_to_write;
164 size_t data_size = data.TotalBufferSize();
165 if (!fin && (data_size == 0)) {
166 LOG(DFATAL) << "Attempt to consume empty data without FIN.";
167 return QuicConsumedData(0, false);
168 }
169
170 int frames_created = 0;
171 while (delegate_->ShouldGeneratePacket(
172 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
173 has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) {
174 QuicFrame frame;
175 size_t bytes_consumed = packet_creator_.CreateStreamFrame(
176 id, data, offset + total_bytes_consumed, fin, &frame);
177 ++frames_created;
178
179 // We want to track which packet this stream frame ends up in.
180 if (FLAGS_quic_attach_ack_notifiers_to_packets) {
181 if (notifier != nullptr) {
182 ack_notifiers_.push_back(notifier);
183 }
184 } else {
185 frame.stream_frame->notifier = notifier;
186 }
187
188 if (!AddFrame(frame)) {
189 LOG(DFATAL) << "Failed to add stream frame.";
190 // Inability to add a STREAM frame creates an unrecoverable hole in a
191 // the stream, so it's best to close the connection.
192 delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false);
193 delete notifier;
194 return QuicConsumedData(0, false);
195 }
196
197 total_bytes_consumed += bytes_consumed;
198 fin_consumed = fin && total_bytes_consumed == data_size;
199 data.Consume(bytes_consumed);
200 DCHECK(data.Empty() || packet_creator_.BytesFree() == 0u);
201
202 // TODO(ianswett): Restore packet reordering.
203 if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) {
204 SerializeAndSendPacket();
205 }
206
207 if (data.Empty()) {
208 // We're done writing the data. Exit the loop.
209 // We don't make this a precondition because we could have 0 bytes of data
210 // if we're simply writing a fin.
211 if (fec_protection == MUST_FEC_PROTECT) {
212 // Turn off FEC protection when we're done writing protected data.
213 DVLOG(1) << "Turning FEC protection OFF";
214 should_fec_protect_ = false;
215 }
216 break;
217 }
218 }
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
225 // Don't allow the handshake to be bundled with other retransmittable frames.
226 if (has_handshake) {
227 SendQueuedFrames(true);
228 }
229
230 // Try to close FEC group since we've either run out of data to send or we're
231 // blocked. If not in batch mode, force close the group.
232 MaybeSendFecPacketAndCloseGroup(/*force=*/false);
233
234 DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames());
235 return QuicConsumedData(total_bytes_consumed, fin_consumed);
236 }
237
238 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
239 DCHECK(HasPendingFrames());
240 HasRetransmittableData retransmittable =
241 (should_send_ack_ || should_send_stop_waiting_)
242 ? NO_RETRANSMITTABLE_DATA
243 : HAS_RETRANSMITTABLE_DATA;
244 if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
245 DCHECK(!queued_control_frames_.empty()); // These are retransmittable.
246 }
247 return delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, retransmittable,
248 NOT_HANDSHAKE);
249 }
250
251 void QuicPacketGenerator::SendQueuedFrames(bool flush) {
252 // Only add pending frames if we are SURE we can then send the whole packet.
253 while (HasPendingFrames() &&
254 (flush || CanSendWithNextPendingFrameAddition())) {
255 if (!AddNextPendingFrame()) {
256 // Packet was full, so serialize and send it.
257 SerializeAndSendPacket();
258 }
259 }
260 if (packet_creator_.HasPendingFrames() && (flush || !InBatchMode())) {
261 SerializeAndSendPacket();
262 }
263 MaybeSendFecPacketAndCloseGroup(flush);
264 }
265
266 void QuicPacketGenerator::MaybeStartFecProtection() {
267 if (!packet_creator_.IsFecEnabled()) {
268 return;
269 }
270 DVLOG(1) << "Turning FEC protection ON";
271 should_fec_protect_ = true;
272 if (packet_creator_.IsFecProtected()) {
273 // Only start creator's FEC protection if not already on.
274 return;
275 }
276 if (HasQueuedFrames()) {
277 // TODO(jri): This currently requires that the generator flush out any
278 // pending frames when FEC protection is turned on. If current packet can be
279 // converted to an FEC protected packet, do it. This will require the
280 // generator to check if the resulting expansion still allows the incoming
281 // frame to be added to the packet.
282 SendQueuedFrames(true);
283 }
284 packet_creator_.StartFecProtectingPackets();
285 DCHECK(packet_creator_.IsFecProtected());
286 }
287
288 void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force) {
289 if (!ShouldSendFecPacket(force)) {
290 return;
291 }
292 // TODO(jri): SerializeFec can return a NULL packet, and this should
293 // cause an early return, with a call to delegate_->OnPacketGenerationError.
294 SerializedPacket serialized_fec = packet_creator_.SerializeFec();
295 DCHECK(serialized_fec.packet);
296 delegate_->OnSerializedPacket(serialized_fec);
297 // Turn FEC protection off if creator's protection is on and the creator
298 // does not have an open FEC group.
299 // Note: We only wait until the frames queued in the creator are flushed;
300 // pending frames in the generator will not keep us from turning FEC off.
301 if (!should_fec_protect_ && !packet_creator_.IsFecGroupOpen()) {
302 packet_creator_.StopFecProtectingPackets();
303 DCHECK(!packet_creator_.IsFecProtected());
304 }
305 }
306
307 bool QuicPacketGenerator::ShouldSendFecPacket(bool force) {
308 return packet_creator_.IsFecProtected() &&
309 !packet_creator_.HasPendingFrames() &&
310 packet_creator_.ShouldSendFec(force);
311 }
312
313 void QuicPacketGenerator::OnFecTimeout() {
314 DCHECK(!InBatchMode());
315 if (!ShouldSendFecPacket(true)) {
316 LOG(DFATAL) << "No FEC packet to send on FEC timeout.";
317 return;
318 }
319 // Flush out any pending frames in the generator and the creator, and then
320 // send out FEC packet.
321 SendQueuedFrames(true);
322 MaybeSendFecPacketAndCloseGroup(/*force=*/true);
323 }
324
325 QuicTime::Delta QuicPacketGenerator::GetFecTimeout(
326 QuicPacketSequenceNumber sequence_number) {
327 // Do not set up FEC alarm for |sequence_number| it is not the first packet in
328 // the current group.
329 if (packet_creator_.IsFecGroupOpen() &&
330 (sequence_number == packet_creator_.fec_group_number())) {
331 return QuicTime::Delta::Max(
332 fec_timeout_, QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs));
333 }
334 return QuicTime::Delta::Infinite();
335 }
336
337 bool QuicPacketGenerator::InBatchMode() {
338 return batch_mode_;
339 }
340
341 void QuicPacketGenerator::StartBatchOperations() {
342 batch_mode_ = true;
343 }
344
345 void QuicPacketGenerator::FinishBatchOperations() {
346 batch_mode_ = false;
347 SendQueuedFrames(false);
348 }
349
350 void QuicPacketGenerator::FlushAllQueuedFrames() {
351 SendQueuedFrames(true);
352 }
353
354 bool QuicPacketGenerator::HasQueuedFrames() const {
355 return packet_creator_.HasPendingFrames() || HasPendingFrames();
356 }
357
358 bool QuicPacketGenerator::HasPendingFrames() const {
359 return should_send_ack_ || should_send_stop_waiting_ ||
360 !queued_control_frames_.empty();
361 }
362
363 bool QuicPacketGenerator::AddNextPendingFrame() {
364 if (should_send_ack_) {
365 delegate_->PopulateAckFrame(&pending_ack_frame_);
366 ack_queued_ = true;
367 // If we can't this add the frame now, then we still need to do so later.
368 should_send_ack_ = !AddFrame(QuicFrame(&pending_ack_frame_));
369 // Return success if we have cleared out this flag (i.e., added the frame).
370 // If we still need to send, then the frame is full, and we have failed.
371 return !should_send_ack_;
372 }
373
374 if (should_send_stop_waiting_) {
375 delegate_->PopulateStopWaitingFrame(&pending_stop_waiting_frame_);
376 stop_waiting_queued_ = true;
377 // If we can't this add the frame now, then we still need to do so later.
378 should_send_stop_waiting_ =
379 !AddFrame(QuicFrame(&pending_stop_waiting_frame_));
380 // Return success if we have cleared out this flag (i.e., added the frame).
381 // If we still need to send, then the frame is full, and we have failed.
382 return !should_send_stop_waiting_;
383 }
384
385 LOG_IF(DFATAL, queued_control_frames_.empty())
386 << "AddNextPendingFrame called with no queued control frames.";
387 if (!AddFrame(queued_control_frames_.back())) {
388 // Packet was full.
389 return false;
390 }
391 queued_control_frames_.pop_back();
392 return true;
393 }
394
395 bool QuicPacketGenerator::AddFrame(const QuicFrame& frame) {
396 bool success = packet_creator_.AddSavedFrame(frame);
397 if (success && debug_delegate_) {
398 debug_delegate_->OnFrameAddedToPacket(frame);
399 }
400 return success;
401 }
402
403 void QuicPacketGenerator::SerializeAndSendPacket() {
404 SerializedPacket serialized_packet = packet_creator_.SerializePacket();
405 DCHECK(serialized_packet.packet);
406
407 // There may be AckNotifiers interested in this packet.
408 if (FLAGS_quic_attach_ack_notifiers_to_packets) {
409 serialized_packet.notifiers.swap(ack_notifiers_);
410 ack_notifiers_.clear();
411 }
412
413 delegate_->OnSerializedPacket(serialized_packet);
414 MaybeSendFecPacketAndCloseGroup(/*force=*/false);
415
416 // The packet has now been serialized, so the frames are no longer queued.
417 ack_queued_ = false;
418 stop_waiting_queued_ = false;
419 }
420
421 void QuicPacketGenerator::StopSendingVersion() {
422 packet_creator_.StopSendingVersion();
423 }
424
425 QuicPacketSequenceNumber QuicPacketGenerator::sequence_number() const {
426 return packet_creator_.sequence_number();
427 }
428
429 QuicByteCount QuicPacketGenerator::max_packet_length() const {
430 return packet_creator_.max_packet_length();
431 }
432
433 void QuicPacketGenerator::set_max_packet_length(QuicByteCount length) {
434 packet_creator_.set_max_packet_length(length);
435 }
436
437 QuicEncryptedPacket* QuicPacketGenerator::SerializeVersionNegotiationPacket(
438 const QuicVersionVector& supported_versions) {
439 return packet_creator_.SerializeVersionNegotiationPacket(supported_versions);
440 }
441
442 SerializedPacket QuicPacketGenerator::ReserializeAllFrames(
443 const RetransmittableFrames& frames,
444 QuicSequenceNumberLength original_length) {
445 return packet_creator_.ReserializeAllFrames(frames, original_length);
446 }
447
448 void QuicPacketGenerator::UpdateSequenceNumberLength(
449 QuicPacketSequenceNumber least_packet_awaited_by_peer,
450 QuicPacketCount max_packets_in_flight) {
451 return packet_creator_.UpdateSequenceNumberLength(
452 least_packet_awaited_by_peer, max_packets_in_flight);
453 }
454
455 void QuicPacketGenerator::SetConnectionIdLength(uint32 length) {
456 if (length == 0) {
457 packet_creator_.set_connection_id_length(PACKET_0BYTE_CONNECTION_ID);
458 } else if (length == 1) {
459 packet_creator_.set_connection_id_length(PACKET_1BYTE_CONNECTION_ID);
460 } else if (length <= 4) {
461 packet_creator_.set_connection_id_length(PACKET_4BYTE_CONNECTION_ID);
462 } else {
463 packet_creator_.set_connection_id_length(PACKET_8BYTE_CONNECTION_ID);
464 }
465 }
466
467
468 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) {
469 packet_creator_.set_encryption_level(level);
470 }
471
472 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_packet_generator.h ('k') | net/quic/quic_packet_generator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698