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_creator.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "net/quic/crypto/quic_random.h"
10 #include "net/quic/quic_ack_notifier.h"
11 #include "net/quic/quic_fec_group.h"
12 #include "net/quic/quic_utils.h"
13
14 using base::StringPiece;
15 using std::make_pair;
16 using std::max;
17 using std::min;
18 using std::pair;
19 using std::vector;
20
21 namespace net {
22
23 namespace {
24
25 // Default max packets in an FEC group.
26 static const size_t kDefaultMaxPacketsPerFecGroup = 10;
27 // Lowest max packets in an FEC group.
28 static const size_t kLowestMaxPacketsPerFecGroup = 2;
29
30 } // namespace
31
32 // A QuicRandom wrapper that gets a bucket of entropy and distributes it
33 // bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this
34 // class if single bit randomness is needed elsewhere.
35 class QuicRandomBoolSource {
36 public:
37 // random: Source of entropy. Not owned.
QuicRandomBoolSource(QuicRandom * random)38 explicit QuicRandomBoolSource(QuicRandom* random)
39 : random_(random),
40 bit_bucket_(0),
41 bit_mask_(0) {}
42
~QuicRandomBoolSource()43 ~QuicRandomBoolSource() {}
44
45 // Returns the next random bit from the bucket.
RandBool()46 bool RandBool() {
47 if (bit_mask_ == 0) {
48 bit_bucket_ = random_->RandUint64();
49 bit_mask_ = 1;
50 }
51 bool result = ((bit_bucket_ & bit_mask_) != 0);
52 bit_mask_ <<= 1;
53 return result;
54 }
55
56 private:
57 // Source of entropy.
58 QuicRandom* random_;
59 // Stored random bits.
60 uint64 bit_bucket_;
61 // The next available bit has "1" in the mask. Zero means empty bucket.
62 uint64 bit_mask_;
63
64 DISALLOW_COPY_AND_ASSIGN(QuicRandomBoolSource);
65 };
66
QuicPacketCreator(QuicConnectionId connection_id,QuicFramer * framer,QuicRandom * random_generator)67 QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
68 QuicFramer* framer,
69 QuicRandom* random_generator)
70 : connection_id_(connection_id),
71 encryption_level_(ENCRYPTION_NONE),
72 framer_(framer),
73 random_bool_source_(new QuicRandomBoolSource(random_generator)),
74 sequence_number_(0),
75 should_fec_protect_(false),
76 fec_group_number_(0),
77 send_version_in_packet_(!framer->is_server()),
78 max_packet_length_(kDefaultMaxPacketSize),
79 max_packets_per_fec_group_(kDefaultMaxPacketsPerFecGroup),
80 connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
81 next_sequence_number_length_(PACKET_1BYTE_SEQUENCE_NUMBER),
82 sequence_number_length_(next_sequence_number_length_),
83 packet_size_(0) {
84 framer_->set_fec_builder(this);
85 }
86
~QuicPacketCreator()87 QuicPacketCreator::~QuicPacketCreator() {
88 }
89
OnBuiltFecProtectedPayload(const QuicPacketHeader & header,StringPiece payload)90 void QuicPacketCreator::OnBuiltFecProtectedPayload(
91 const QuicPacketHeader& header, StringPiece payload) {
92 if (fec_group_.get()) {
93 DCHECK_NE(0u, header.fec_group);
94 fec_group_->Update(encryption_level_, header, payload);
95 }
96 }
97
set_max_packets_per_fec_group(size_t max_packets_per_fec_group)98 void QuicPacketCreator::set_max_packets_per_fec_group(
99 size_t max_packets_per_fec_group) {
100 max_packets_per_fec_group_ = max(kLowestMaxPacketsPerFecGroup,
101 max_packets_per_fec_group);
102 DCHECK_LT(0u, max_packets_per_fec_group_);
103 }
104
ShouldSendFec(bool force_close) const105 bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
106 DCHECK(!HasPendingFrames());
107 return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 &&
108 (force_close || fec_group_->NumReceivedPackets() >=
109 max_packets_per_fec_group_);
110 }
111
IsFecGroupOpen() const112 bool QuicPacketCreator::IsFecGroupOpen() const {
113 return fec_group_.get() != NULL;
114 }
115
StartFecProtectingPackets()116 void QuicPacketCreator::StartFecProtectingPackets() {
117 if (!IsFecEnabled()) {
118 LOG(DFATAL) << "Cannot start FEC protection when FEC is not enabled.";
119 return;
120 }
121 // TODO(jri): This currently requires that the generator flush out any
122 // pending frames when FEC protection is turned on. If current packet can be
123 // converted to an FEC protected packet, do it. This will require the
124 // generator to check if the resulting expansion still allows the incoming
125 // frame to be added to the packet.
126 if (HasPendingFrames()) {
127 LOG(DFATAL) << "Cannot start FEC protection with pending frames.";
128 return;
129 }
130 DCHECK(!should_fec_protect_);
131 should_fec_protect_ = true;
132 }
133
StopFecProtectingPackets()134 void QuicPacketCreator::StopFecProtectingPackets() {
135 if (fec_group_.get() != NULL) {
136 LOG(DFATAL) << "Cannot stop FEC protection with open FEC group.";
137 return;
138 }
139 DCHECK(should_fec_protect_);
140 should_fec_protect_ = false;
141 fec_group_number_ = 0;
142 }
143
IsFecProtected() const144 bool QuicPacketCreator::IsFecProtected() const {
145 return should_fec_protect_;
146 }
147
IsFecEnabled() const148 bool QuicPacketCreator::IsFecEnabled() const {
149 return max_packets_per_fec_group_ > 0;
150 }
151
MaybeUpdateLengthsAndStartFec()152 InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() {
153 if (fec_group_.get() != NULL) {
154 // Don't update any lengths when an FEC group is open, to ensure same
155 // packet header size in all packets within a group.
156 return IN_FEC_GROUP;
157 }
158 if (!queued_frames_.empty()) {
159 // Don't change creator state if there are frames queued.
160 return fec_group_.get() == NULL ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
161 }
162
163 // Update sequence number length only on packet and FEC group boundaries.
164 sequence_number_length_ = next_sequence_number_length_;
165
166 if (!should_fec_protect_) {
167 return NOT_IN_FEC_GROUP;
168 }
169 // Start a new FEC group since protection is on. Set the fec group number to
170 // the sequence number of the next packet.
171 fec_group_number_ = sequence_number() + 1;
172 fec_group_.reset(new QuicFecGroup());
173 return IN_FEC_GROUP;
174 }
175
176 // Stops serializing version of the protocol in packets sent after this call.
177 // A packet that is already open might send kQuicVersionSize bytes less than the
178 // maximum packet size if we stop sending version before it is serialized.
StopSendingVersion()179 void QuicPacketCreator::StopSendingVersion() {
180 DCHECK(send_version_in_packet_);
181 send_version_in_packet_ = false;
182 if (packet_size_ > 0) {
183 DCHECK_LT(kQuicVersionSize, packet_size_);
184 packet_size_ -= kQuicVersionSize;
185 }
186 }
187
UpdateSequenceNumberLength(QuicPacketSequenceNumber least_packet_awaited_by_peer,QuicByteCount congestion_window)188 void QuicPacketCreator::UpdateSequenceNumberLength(
189 QuicPacketSequenceNumber least_packet_awaited_by_peer,
190 QuicByteCount congestion_window) {
191 DCHECK_LE(least_packet_awaited_by_peer, sequence_number_ + 1);
192 // Since the packet creator will not change sequence number length mid FEC
193 // group, include the size of an FEC group to be safe.
194 const QuicPacketSequenceNumber current_delta =
195 max_packets_per_fec_group_ + sequence_number_ + 1
196 - least_packet_awaited_by_peer;
197 const uint64 congestion_window_packets =
198 congestion_window / max_packet_length_;
199 const uint64 delta = max(current_delta, congestion_window_packets);
200 next_sequence_number_length_ =
201 QuicFramer::GetMinSequenceNumberLength(delta * 4);
202 }
203
HasRoomForStreamFrame(QuicStreamId id,QuicStreamOffset offset) const204 bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
205 QuicStreamOffset offset) const {
206 // TODO(jri): This is a simple safe decision for now, but make
207 // is_in_fec_group a parameter. Same as with all public methods in
208 // QuicPacketCreator.
209 return BytesFree() >
210 QuicFramer::GetMinStreamFrameSize(id, offset, true,
211 should_fec_protect_ ? IN_FEC_GROUP :
212 NOT_IN_FEC_GROUP);
213 }
214
215 // static
StreamFramePacketOverhead(QuicConnectionIdLength connection_id_length,bool include_version,QuicSequenceNumberLength sequence_number_length,QuicStreamOffset offset,InFecGroup is_in_fec_group)216 size_t QuicPacketCreator::StreamFramePacketOverhead(
217 QuicConnectionIdLength connection_id_length,
218 bool include_version,
219 QuicSequenceNumberLength sequence_number_length,
220 QuicStreamOffset offset,
221 InFecGroup is_in_fec_group) {
222 return GetPacketHeaderSize(connection_id_length, include_version,
223 sequence_number_length, is_in_fec_group) +
224 // Assumes this is a stream with a single lone packet.
225 QuicFramer::GetMinStreamFrameSize(1u, offset, true, is_in_fec_group);
226 }
227
CreateStreamFrame(QuicStreamId id,const IOVector & data,QuicStreamOffset offset,bool fin,QuicFrame * frame)228 size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
229 const IOVector& data,
230 QuicStreamOffset offset,
231 bool fin,
232 QuicFrame* frame) {
233 DCHECK_GT(max_packet_length_, StreamFramePacketOverhead(
234 PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
235 PACKET_6BYTE_SEQUENCE_NUMBER, offset, IN_FEC_GROUP));
236
237 InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec();
238
239 LOG_IF(DFATAL, !HasRoomForStreamFrame(id, offset))
240 << "No room for Stream frame, BytesFree: " << BytesFree()
241 << " MinStreamFrameSize: "
242 << QuicFramer::GetMinStreamFrameSize(id, offset, true, is_in_fec_group);
243
244 if (data.Empty()) {
245 LOG_IF(DFATAL, !fin)
246 << "Creating a stream frame with no data or fin.";
247 // Create a new packet for the fin, if necessary.
248 *frame = QuicFrame(new QuicStreamFrame(id, true, offset, data));
249 return 0;
250 }
251
252 const size_t data_size = data.TotalBufferSize();
253 size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
254 id, offset, /* last_frame_in_packet= */ true, is_in_fec_group);
255 size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size);
256
257 bool set_fin = fin && bytes_consumed == data_size; // Last frame.
258 IOVector frame_data;
259 frame_data.AppendIovecAtMostBytes(data.iovec(), data.Size(),
260 bytes_consumed);
261 DCHECK_EQ(frame_data.TotalBufferSize(), bytes_consumed);
262 *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, frame_data));
263 return bytes_consumed;
264 }
265
CreateStreamFrameWithNotifier(QuicStreamId id,const IOVector & data,QuicStreamOffset offset,bool fin,QuicAckNotifier * notifier,QuicFrame * frame)266 size_t QuicPacketCreator::CreateStreamFrameWithNotifier(
267 QuicStreamId id,
268 const IOVector& data,
269 QuicStreamOffset offset,
270 bool fin,
271 QuicAckNotifier* notifier,
272 QuicFrame* frame) {
273 size_t bytes_consumed = CreateStreamFrame(id, data, offset, fin, frame);
274
275 // The frame keeps track of the QuicAckNotifier until it is serialized into
276 // a packet. At that point the notifier is informed of the sequence number
277 // of the packet that this frame was eventually sent in.
278 frame->stream_frame->notifier = notifier;
279
280 return bytes_consumed;
281 }
282
ReserializeAllFrames(const QuicFrames & frames,QuicSequenceNumberLength original_length)283 SerializedPacket QuicPacketCreator::ReserializeAllFrames(
284 const QuicFrames& frames,
285 QuicSequenceNumberLength original_length) {
286 DCHECK(fec_group_.get() == NULL);
287 const QuicSequenceNumberLength saved_length = sequence_number_length_;
288 const QuicSequenceNumberLength saved_next_length =
289 next_sequence_number_length_;
290 const bool saved_should_fec_protect = should_fec_protect_;
291
292 // Temporarily set the sequence number length and stop FEC protection.
293 sequence_number_length_ = original_length;
294 next_sequence_number_length_ = original_length;
295 should_fec_protect_ = false;
296
297 // Serialize the packet and restore the FEC and sequence number length state.
298 SerializedPacket serialized_packet = SerializeAllFrames(frames);
299 sequence_number_length_ = saved_length;
300 next_sequence_number_length_ = saved_next_length;
301 should_fec_protect_ = saved_should_fec_protect;
302
303 return serialized_packet;
304 }
305
SerializeAllFrames(const QuicFrames & frames)306 SerializedPacket QuicPacketCreator::SerializeAllFrames(
307 const QuicFrames& frames) {
308 // TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued
309 // frames from SendStreamData()[send_stream_should_flush_ == false &&
310 // data.empty() == true] and retransmit due to RTO.
311 DCHECK_EQ(0u, queued_frames_.size());
312 LOG_IF(DFATAL, frames.empty())
313 << "Attempt to serialize empty packet";
314 for (size_t i = 0; i < frames.size(); ++i) {
315 bool success = AddFrame(frames[i], false);
316 DCHECK(success);
317 }
318 SerializedPacket packet = SerializePacket();
319 DCHECK(packet.retransmittable_frames == NULL);
320 return packet;
321 }
322
HasPendingFrames() const323 bool QuicPacketCreator::HasPendingFrames() const {
324 return !queued_frames_.empty();
325 }
326
HasPendingRetransmittableFrames() const327 bool QuicPacketCreator::HasPendingRetransmittableFrames() const {
328 return queued_retransmittable_frames_.get() != NULL &&
329 !queued_retransmittable_frames_->frames().empty();
330 }
331
ExpansionOnNewFrame() const332 size_t QuicPacketCreator::ExpansionOnNewFrame() const {
333 // If packet is FEC protected, there's no expansion.
334 if (should_fec_protect_) {
335 return 0;
336 }
337 // If the last frame in the packet is a stream frame, then it will expand to
338 // include the stream_length field when a new frame is added.
339 bool has_trailing_stream_frame =
340 !queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME;
341 return has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0;
342 }
343
BytesFree() const344 size_t QuicPacketCreator::BytesFree() const {
345 const size_t max_plaintext_size =
346 framer_->GetMaxPlaintextSize(max_packet_length_);
347 DCHECK_GE(max_plaintext_size, PacketSize());
348 return max_plaintext_size - min(max_plaintext_size, PacketSize()
349 + ExpansionOnNewFrame());
350 }
351
PacketSize() const352 size_t QuicPacketCreator::PacketSize() const {
353 if (!queued_frames_.empty()) {
354 return packet_size_;
355 }
356 if (fec_group_.get() == NULL) {
357 // Update sequence number length on packet and FEC boundary.
358 sequence_number_length_ = next_sequence_number_length_;
359 }
360 packet_size_ = GetPacketHeaderSize(
361 connection_id_length_, send_version_in_packet_, sequence_number_length_,
362 should_fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP);
363 return packet_size_;
364 }
365
AddSavedFrame(const QuicFrame & frame)366 bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) {
367 return AddFrame(frame, true);
368 }
369
SerializePacket()370 SerializedPacket QuicPacketCreator::SerializePacket() {
371 LOG_IF(DFATAL, queued_frames_.empty())
372 << "Attempt to serialize empty packet";
373 DCHECK_GE(sequence_number_ + 1, fec_group_number_);
374 QuicPacketHeader header;
375 FillPacketHeader(should_fec_protect_ ? fec_group_number_ : 0, false, &header);
376
377 MaybeAddPadding();
378
379 size_t max_plaintext_size =
380 framer_->GetMaxPlaintextSize(max_packet_length_);
381 DCHECK_GE(max_plaintext_size, packet_size_);
382 // ACK Frames will be truncated due to length only if they're the only frame
383 // in the packet, and if packet_size_ was set to max_plaintext_size. If
384 // truncation due to length occurred, then GetSerializedFrameLength will have
385 // returned all bytes free.
386 bool possibly_truncated_by_length = packet_size_ == max_plaintext_size &&
387 queued_frames_.size() == 1 &&
388 queued_frames_.back().type == ACK_FRAME;
389 SerializedPacket serialized =
390 framer_->BuildDataPacket(header, queued_frames_, packet_size_);
391 LOG_IF(DFATAL, !serialized.packet)
392 << "Failed to serialize " << queued_frames_.size() << " frames.";
393 // Because of possible truncation, we can't be confident that our
394 // packet size calculation worked correctly.
395 if (!possibly_truncated_by_length) {
396 DCHECK_EQ(packet_size_, serialized.packet->length());
397 }
398 packet_size_ = 0;
399 queued_frames_.clear();
400 serialized.retransmittable_frames = queued_retransmittable_frames_.release();
401 return serialized;
402 }
403
SerializeFec()404 SerializedPacket QuicPacketCreator::SerializeFec() {
405 if (fec_group_.get() == NULL || fec_group_->NumReceivedPackets() <= 0) {
406 LOG(DFATAL) << "SerializeFEC called but no group or zero packets in group.";
407 // TODO(jri): Make this a public method of framer?
408 SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL);
409 return kNoPacket;
410 }
411 DCHECK_EQ(0u, queued_frames_.size());
412 QuicPacketHeader header;
413 FillPacketHeader(fec_group_number_, true, &header);
414 QuicFecData fec_data;
415 fec_data.fec_group = fec_group_->min_protected_packet();
416 fec_data.redundancy = fec_group_->payload_parity();
417 SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data);
418 fec_group_.reset(NULL);
419 packet_size_ = 0;
420 LOG_IF(DFATAL, !serialized.packet)
421 << "Failed to serialize fec packet for group:" << fec_data.fec_group;
422 DCHECK_GE(max_packet_length_, serialized.packet->length());
423 return serialized;
424 }
425
SerializeConnectionClose(QuicConnectionCloseFrame * close_frame)426 SerializedPacket QuicPacketCreator::SerializeConnectionClose(
427 QuicConnectionCloseFrame* close_frame) {
428 QuicFrames frames;
429 frames.push_back(QuicFrame(close_frame));
430 return SerializeAllFrames(frames);
431 }
432
SerializeVersionNegotiationPacket(const QuicVersionVector & supported_versions)433 QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
434 const QuicVersionVector& supported_versions) {
435 DCHECK(framer_->is_server());
436 QuicPacketPublicHeader header;
437 header.connection_id = connection_id_;
438 header.reset_flag = false;
439 header.version_flag = true;
440 header.versions = supported_versions;
441 QuicEncryptedPacket* encrypted =
442 framer_->BuildVersionNegotiationPacket(header, supported_versions);
443 DCHECK(encrypted);
444 DCHECK_GE(max_packet_length_, encrypted->length());
445 return encrypted;
446 }
447
FillPacketHeader(QuicFecGroupNumber fec_group,bool fec_flag,QuicPacketHeader * header)448 void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
449 bool fec_flag,
450 QuicPacketHeader* header) {
451 header->public_header.connection_id = connection_id_;
452 header->public_header.reset_flag = false;
453 header->public_header.version_flag = send_version_in_packet_;
454 header->fec_flag = fec_flag;
455 header->packet_sequence_number = ++sequence_number_;
456 header->public_header.sequence_number_length = sequence_number_length_;
457 header->entropy_flag = random_bool_source_->RandBool();
458 header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
459 header->fec_group = fec_group;
460 }
461
ShouldRetransmit(const QuicFrame & frame)462 bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
463 switch (frame.type) {
464 case ACK_FRAME:
465 case CONGESTION_FEEDBACK_FRAME:
466 case PADDING_FRAME:
467 case STOP_WAITING_FRAME:
468 return false;
469 default:
470 return true;
471 }
472 }
473
AddFrame(const QuicFrame & frame,bool save_retransmittable_frames)474 bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
475 bool save_retransmittable_frames) {
476 DVLOG(1) << "Adding frame: " << frame;
477 InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec();
478
479 size_t frame_len = framer_->GetSerializedFrameLength(
480 frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group,
481 sequence_number_length_);
482 if (frame_len == 0) {
483 return false;
484 }
485 DCHECK_LT(0u, packet_size_);
486 packet_size_ += ExpansionOnNewFrame() + frame_len;
487
488 if (save_retransmittable_frames && ShouldRetransmit(frame)) {
489 if (queued_retransmittable_frames_.get() == NULL) {
490 queued_retransmittable_frames_.reset(new RetransmittableFrames());
491 }
492 if (frame.type == STREAM_FRAME) {
493 queued_frames_.push_back(
494 queued_retransmittable_frames_->AddStreamFrame(frame.stream_frame));
495 } else {
496 queued_frames_.push_back(
497 queued_retransmittable_frames_->AddNonStreamFrame(frame));
498 }
499 } else {
500 queued_frames_.push_back(frame);
501 }
502 return true;
503 }
504
MaybeAddPadding()505 void QuicPacketCreator::MaybeAddPadding() {
506 if (BytesFree() == 0) {
507 // Don't pad full packets.
508 return;
509 }
510
511 // Since ReserializeAllFrames does not populate queued_retransmittable_frames_
512 // it's not sufficient to simply call
513 // queued_retransmittable_frames_->HasCryptoHandshake().
514 // TODO(rch): we should really make ReserializeAllFrames not be a special
515 // case!
516
517 // If any of the frames in the current packet are on the crypto stream
518 // then they contain handshake messagses, and we should pad them.
519 bool is_handshake = false;
520 for (const QuicFrame& frame : queued_frames_) {
521 if (frame.type == STREAM_FRAME &&
522 frame.stream_frame->stream_id == kCryptoStreamId) {
523 is_handshake = true;
524 break;
525 }
526 }
527 if (!is_handshake) {
528 return;
529 }
530
531 QuicPaddingFrame padding;
532 bool success = AddFrame(QuicFrame(&padding), false);
533 DCHECK(success);
534 }
535
536 } // namespace net
537