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