• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/logging.h"
8 #include "net/quic/crypto/quic_random.h"
9 #include "net/quic/quic_ack_notifier.h"
10 #include "net/quic/quic_fec_group.h"
11 #include "net/quic/quic_utils.h"
12 
13 using base::StringPiece;
14 using std::make_pair;
15 using std::max;
16 using std::min;
17 using std::pair;
18 using std::vector;
19 
20 namespace net {
21 
22 // A QuicRandom wrapper that gets a bucket of entropy and distributes it
23 // bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this
24 // class if single bit randomness is needed elsewhere.
25 class QuicRandomBoolSource {
26  public:
27   // random: Source of entropy. Not owned.
QuicRandomBoolSource(QuicRandom * random)28   explicit QuicRandomBoolSource(QuicRandom* random)
29       : random_(random),
30         bit_bucket_(0),
31         bit_mask_(0) {}
32 
~QuicRandomBoolSource()33   ~QuicRandomBoolSource() {}
34 
35   // Returns the next random bit from the bucket.
RandBool()36   bool RandBool() {
37     if (bit_mask_ == 0) {
38       bit_bucket_ = random_->RandUint64();
39       bit_mask_ = 1;
40     }
41     bool result = ((bit_bucket_ & bit_mask_) != 0);
42     bit_mask_ <<= 1;
43     return result;
44   }
45 
46  private:
47   // Source of entropy.
48   QuicRandom* random_;
49   // Stored random bits.
50   uint64 bit_bucket_;
51   // The next available bit has "1" in the mask. Zero means empty bucket.
52   uint64 bit_mask_;
53 
54   DISALLOW_COPY_AND_ASSIGN(QuicRandomBoolSource);
55 };
56 
QuicPacketCreator(QuicGuid guid,QuicFramer * framer,QuicRandom * random_generator,bool is_server)57 QuicPacketCreator::QuicPacketCreator(QuicGuid guid,
58                                      QuicFramer* framer,
59                                      QuicRandom* random_generator,
60                                      bool is_server)
61     : guid_(guid),
62       framer_(framer),
63       random_bool_source_(new QuicRandomBoolSource(random_generator)),
64       sequence_number_(0),
65       fec_group_number_(0),
66       is_server_(is_server),
67       send_version_in_packet_(!is_server),
68       sequence_number_length_(options_.send_sequence_number_length),
69       packet_size_(0) {
70   framer_->set_fec_builder(this);
71 }
72 
~QuicPacketCreator()73 QuicPacketCreator::~QuicPacketCreator() {
74 }
75 
OnBuiltFecProtectedPayload(const QuicPacketHeader & header,StringPiece payload)76 void QuicPacketCreator::OnBuiltFecProtectedPayload(
77     const QuicPacketHeader& header, StringPiece payload) {
78   if (fec_group_.get()) {
79     DCHECK_NE(0u, header.fec_group);
80     fec_group_->Update(header, payload);
81   }
82 }
83 
ShouldSendFec(bool force_close) const84 bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
85   return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 &&
86       (force_close ||
87        fec_group_->NumReceivedPackets() >= options_.max_packets_per_fec_group);
88 }
89 
MaybeStartFEC()90 void QuicPacketCreator::MaybeStartFEC() {
91   if (options_.max_packets_per_fec_group > 0 && fec_group_.get() == NULL) {
92     DCHECK(queued_frames_.empty());
93     // Set the fec group number to the sequence number of the next packet.
94     fec_group_number_ = sequence_number() + 1;
95     fec_group_.reset(new QuicFecGroup());
96   }
97 }
98 
99 // Stops serializing version of the protocol in packets sent after this call.
100 // A packet that is already open might send kQuicVersionSize bytes less than the
101 // maximum packet size if we stop sending version before it is serialized.
StopSendingVersion()102 void QuicPacketCreator::StopSendingVersion() {
103   DCHECK(send_version_in_packet_);
104   send_version_in_packet_ = false;
105   if (packet_size_ > 0) {
106     DCHECK_LT(kQuicVersionSize, packet_size_);
107     packet_size_ -= kQuicVersionSize;
108   }
109 }
110 
UpdateSequenceNumberLength(QuicPacketSequenceNumber least_packet_awaited_by_peer,QuicByteCount bytes_per_second)111 void QuicPacketCreator::UpdateSequenceNumberLength(
112       QuicPacketSequenceNumber least_packet_awaited_by_peer,
113       QuicByteCount bytes_per_second) {
114   DCHECK_LE(least_packet_awaited_by_peer, sequence_number_ + 1);
115   // Since the packet creator will not change sequence number length mid FEC
116   // group, include the size of an FEC group to be safe.
117   const QuicPacketSequenceNumber current_delta =
118       options_.max_packets_per_fec_group + sequence_number_ + 1
119       - least_packet_awaited_by_peer;
120   const uint64 congestion_window =
121       bytes_per_second / options_.max_packet_length;
122   const uint64 delta = max(current_delta, congestion_window);
123 
124   options_.send_sequence_number_length =
125       QuicFramer::GetMinSequenceNumberLength(delta * 4);
126 }
127 
HasRoomForStreamFrame(QuicStreamId id,QuicStreamOffset offset) const128 bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
129                                               QuicStreamOffset offset) const {
130   return BytesFree() >
131       QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset, true);
132 }
133 
134 // static
StreamFramePacketOverhead(QuicVersion version,QuicGuidLength guid_length,bool include_version,QuicSequenceNumberLength sequence_number_length,InFecGroup is_in_fec_group)135 size_t QuicPacketCreator::StreamFramePacketOverhead(
136     QuicVersion version,
137     QuicGuidLength guid_length,
138     bool include_version,
139     QuicSequenceNumberLength sequence_number_length,
140     InFecGroup is_in_fec_group) {
141   return GetPacketHeaderSize(guid_length, include_version,
142                              sequence_number_length, is_in_fec_group) +
143       // Assumes this is a stream with a single lone packet.
144       QuicFramer::GetMinStreamFrameSize(version, 1u, 0u, true);
145 }
146 
CreateStreamFrame(QuicStreamId id,const IOVector & data,QuicStreamOffset offset,bool fin,QuicFrame * frame)147 size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
148                                             const IOVector& data,
149                                             QuicStreamOffset offset,
150                                             bool fin,
151                                             QuicFrame* frame) {
152   DCHECK_GT(options_.max_packet_length,
153             StreamFramePacketOverhead(
154                 framer_->version(), PACKET_8BYTE_GUID, kIncludeVersion,
155                 PACKET_6BYTE_SEQUENCE_NUMBER, IN_FEC_GROUP));
156   if (!HasRoomForStreamFrame(id, offset)) {
157     LOG(DFATAL) << "No room for Stream frame, BytesFree: " << BytesFree()
158                 << " MinStreamFrameSize: "
159                 << QuicFramer::GetMinStreamFrameSize(
160                     framer_->version(), id, offset, true);
161   }
162 
163   if (data.Empty()) {
164     if (!fin) {
165       LOG(DFATAL) << "Creating a stream frame with no data or fin.";
166     }
167     // Create a new packet for the fin, if necessary.
168     *frame = QuicFrame(new QuicStreamFrame(id, true, offset, data));
169     return 0;
170   }
171 
172   const size_t free_bytes = BytesFree();
173   size_t bytes_consumed = 0;
174   const size_t data_size = data.TotalBufferSize();
175 
176   // When a STREAM frame is the last frame in a packet, it consumes two fewer
177   // bytes of framing overhead.
178   // Anytime more data is available than fits in with the extra two bytes,
179   // the frame will be the last, and up to two extra bytes are consumed.
180   // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when
181   // 1 byte is available, because then the STREAM frame isn't the last.
182 
183   // The minimum frame size(0 bytes of data) if it's not the last frame.
184   size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
185       framer_->version(), id, offset, false);
186   // Check if it's the last frame in the packet.
187   if (data_size + min_frame_size > free_bytes) {
188     // The minimum frame size(0 bytes of data) if it is the last frame.
189     size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize(
190         framer_->version(), id, offset, true);
191     bytes_consumed =
192         min<size_t>(free_bytes - min_last_frame_size, data_size);
193   } else {
194     DCHECK_LT(data_size, BytesFree());
195     bytes_consumed = data_size;
196   }
197 
198   bool set_fin = fin && bytes_consumed == data_size;  // Last frame.
199   IOVector frame_data;
200   frame_data.AppendIovecAtMostBytes(data.iovec(), data.Size(),
201                                     bytes_consumed);
202   DCHECK_EQ(frame_data.TotalBufferSize(), bytes_consumed);
203   *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, frame_data));
204   return bytes_consumed;
205 }
206 
CreateStreamFrameWithNotifier(QuicStreamId id,const IOVector & data,QuicStreamOffset offset,bool fin,QuicAckNotifier * notifier,QuicFrame * frame)207 size_t QuicPacketCreator::CreateStreamFrameWithNotifier(
208     QuicStreamId id,
209     const IOVector& data,
210     QuicStreamOffset offset,
211     bool fin,
212     QuicAckNotifier* notifier,
213     QuicFrame* frame) {
214   size_t bytes_consumed = CreateStreamFrame(id, data, offset, fin, frame);
215 
216   // The frame keeps track of the QuicAckNotifier until it is serialized into
217   // a packet. At that point the notifier is informed of the sequence number
218   // of the packet that this frame was eventually sent in.
219   frame->stream_frame->notifier = notifier;
220 
221   return bytes_consumed;
222 }
223 
ReserializeAllFrames(const QuicFrames & frames,QuicSequenceNumberLength original_length)224 SerializedPacket QuicPacketCreator::ReserializeAllFrames(
225     const QuicFrames& frames,
226     QuicSequenceNumberLength original_length) {
227   const QuicSequenceNumberLength start_length = sequence_number_length_;
228   const QuicSequenceNumberLength start_options_length =
229       options_.send_sequence_number_length;
230   const QuicFecGroupNumber start_fec_group = fec_group_number_;
231   const size_t start_max_packets_per_fec_group =
232       options_.max_packets_per_fec_group;
233 
234   // Temporarily set the sequence number length and disable FEC.
235   sequence_number_length_ = original_length;
236   options_.send_sequence_number_length = original_length;
237   fec_group_number_ = 0;
238   options_.max_packets_per_fec_group = 0;
239 
240   // Serialize the packet and restore the fec and sequence number length state.
241   SerializedPacket serialized_packet = SerializeAllFrames(frames);
242   sequence_number_length_ = start_length;
243   options_.send_sequence_number_length = start_options_length;
244   fec_group_number_ = start_fec_group;
245   options_.max_packets_per_fec_group = start_max_packets_per_fec_group;
246 
247   return serialized_packet;
248 }
249 
SerializeAllFrames(const QuicFrames & frames)250 SerializedPacket QuicPacketCreator::SerializeAllFrames(
251     const QuicFrames& frames) {
252   // TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued
253   // frames from SendStreamData()[send_stream_should_flush_ == false &&
254   // data.empty() == true] and retransmit due to RTO.
255   DCHECK_EQ(0u, queued_frames_.size());
256   if (frames.empty()) {
257     LOG(DFATAL) << "Attempt to serialize empty packet";
258   }
259   for (size_t i = 0; i < frames.size(); ++i) {
260     bool success = AddFrame(frames[i], false);
261     DCHECK(success);
262   }
263   SerializedPacket packet = SerializePacket();
264   DCHECK(packet.retransmittable_frames == NULL);
265   return packet;
266 }
267 
HasPendingFrames()268 bool QuicPacketCreator::HasPendingFrames() {
269   return !queued_frames_.empty();
270 }
271 
BytesFree() const272 size_t QuicPacketCreator::BytesFree() const {
273   const size_t max_plaintext_size =
274       framer_->GetMaxPlaintextSize(options_.max_packet_length);
275   DCHECK_GE(max_plaintext_size, PacketSize());
276 
277   // If the last frame in the packet is a stream frame, then it can be
278   // two bytes smaller than if it were not the last.  So this means that
279   // there are two fewer bytes available to the next frame in this case.
280   bool has_trailing_stream_frame =
281       !queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME;
282   size_t expanded_packet_size = PacketSize() +
283       (has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0);
284 
285   if (expanded_packet_size  >= max_plaintext_size) {
286     return 0;
287   }
288   return max_plaintext_size - expanded_packet_size;
289 }
290 
PacketSize() const291 size_t QuicPacketCreator::PacketSize() const {
292   if (queued_frames_.empty()) {
293     // Only adjust the sequence number length when the FEC group is not open,
294     // to ensure no packets in a group are too large.
295     if (fec_group_.get() == NULL ||
296         fec_group_->NumReceivedPackets() == 0) {
297       sequence_number_length_ = options_.send_sequence_number_length;
298     }
299     packet_size_ = GetPacketHeaderSize(options_.send_guid_length,
300                                        send_version_in_packet_,
301                                        sequence_number_length_,
302                                        options_.max_packets_per_fec_group == 0 ?
303                                            NOT_IN_FEC_GROUP : IN_FEC_GROUP);
304   }
305   return packet_size_;
306 }
307 
AddSavedFrame(const QuicFrame & frame)308 bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) {
309   return AddFrame(frame, true);
310 }
311 
SerializePacket()312 SerializedPacket QuicPacketCreator::SerializePacket() {
313   if (queued_frames_.empty()) {
314     LOG(DFATAL) << "Attempt to serialize empty packet";
315   }
316   QuicPacketHeader header;
317   FillPacketHeader(fec_group_number_, false, false, &header);
318 
319   MaybeAddPadding();
320 
321   size_t max_plaintext_size =
322       framer_->GetMaxPlaintextSize(options_.max_packet_length);
323   DCHECK_GE(max_plaintext_size, packet_size_);
324   // ACK and CONNECTION_CLOSE Frames will be truncated only if they're
325   // the first frame in the packet.  If truncation is to occur, then
326   // GetSerializedFrameLength will have returned all bytes free.
327   bool possibly_truncated =
328       packet_size_ != max_plaintext_size ||
329       queued_frames_.size() != 1 ||
330       (queued_frames_.back().type == ACK_FRAME ||
331        queued_frames_.back().type == CONNECTION_CLOSE_FRAME);
332   SerializedPacket serialized =
333       framer_->BuildDataPacket(header, queued_frames_, packet_size_);
334   if (!serialized.packet) {
335     LOG(DFATAL) << "Failed to serialize " << queued_frames_.size()
336                 << " frames.";
337   }
338   // Because of possible truncation, we can't be confident that our
339   // packet size calculation worked correctly.
340   if (!possibly_truncated)
341     DCHECK_EQ(packet_size_, serialized.packet->length());
342 
343   packet_size_ = 0;
344   queued_frames_.clear();
345   serialized.retransmittable_frames = queued_retransmittable_frames_.release();
346   return serialized;
347 }
348 
SerializeFec()349 SerializedPacket QuicPacketCreator::SerializeFec() {
350   DCHECK_LT(0u, fec_group_->NumReceivedPackets());
351   DCHECK_EQ(0u, queued_frames_.size());
352   QuicPacketHeader header;
353   FillPacketHeader(fec_group_number_, true,
354                    fec_group_->entropy_parity(), &header);
355   QuicFecData fec_data;
356   fec_data.fec_group = fec_group_->min_protected_packet();
357   fec_data.redundancy = fec_group_->payload_parity();
358   SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data);
359   fec_group_.reset(NULL);
360   fec_group_number_ = 0;
361   packet_size_ = 0;
362   if (!serialized.packet) {
363     LOG(DFATAL) << "Failed to serialize fec packet for group:"
364                 << fec_data.fec_group;
365   }
366   DCHECK_GE(options_.max_packet_length, serialized.packet->length());
367   return serialized;
368 }
369 
SerializeConnectionClose(QuicConnectionCloseFrame * close_frame)370 SerializedPacket QuicPacketCreator::SerializeConnectionClose(
371     QuicConnectionCloseFrame* close_frame) {
372   QuicFrames frames;
373   frames.push_back(QuicFrame(close_frame));
374   return SerializeAllFrames(frames);
375 }
376 
SerializeVersionNegotiationPacket(const QuicVersionVector & supported_versions)377 QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
378     const QuicVersionVector& supported_versions) {
379   DCHECK(is_server_);
380   QuicPacketPublicHeader header;
381   header.guid = guid_;
382   header.reset_flag = false;
383   header.version_flag = true;
384   header.versions = supported_versions;
385   QuicEncryptedPacket* encrypted =
386       framer_->BuildVersionNegotiationPacket(header, supported_versions);
387   DCHECK(encrypted);
388   DCHECK_GE(options_.max_packet_length, encrypted->length());
389   return encrypted;
390 }
391 
FillPacketHeader(QuicFecGroupNumber fec_group,bool fec_flag,bool fec_entropy_flag,QuicPacketHeader * header)392 void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
393                                          bool fec_flag,
394                                          bool fec_entropy_flag,
395                                          QuicPacketHeader* header) {
396   header->public_header.guid = guid_;
397   header->public_header.reset_flag = false;
398   header->public_header.version_flag = send_version_in_packet_;
399   header->fec_flag = fec_flag;
400   header->packet_sequence_number = ++sequence_number_;
401   header->public_header.sequence_number_length = sequence_number_length_;
402 
403   bool entropy_flag;
404   if (fec_flag) {
405     // FEC packets don't have an entropy of their own. Entropy flag for FEC
406     // packets is the XOR of entropy of previous packets.
407     entropy_flag = fec_entropy_flag;
408   } else {
409     entropy_flag = random_bool_source_->RandBool();
410   }
411   header->entropy_flag = entropy_flag;
412   header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
413   header->fec_group = fec_group;
414 }
415 
ShouldRetransmit(const QuicFrame & frame)416 bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
417   return frame.type != ACK_FRAME && frame.type != CONGESTION_FEEDBACK_FRAME &&
418       frame.type != PADDING_FRAME;
419 }
420 
AddFrame(const QuicFrame & frame,bool save_retransmittable_frames)421 bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
422                                  bool save_retransmittable_frames) {
423   size_t frame_len = framer_->GetSerializedFrameLength(
424       frame, BytesFree(), queued_frames_.empty(), true,
425       options()->send_sequence_number_length);
426   if (frame_len == 0) {
427     return false;
428   }
429   DCHECK_LT(0u, packet_size_);
430   MaybeStartFEC();
431   packet_size_ += frame_len;
432   // If the last frame in the packet was a stream frame, then once we add the
433   // new frame it's serialization will be two bytes larger.
434   if (!queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME) {
435     packet_size_ += kQuicStreamPayloadLengthSize;
436   }
437   if (save_retransmittable_frames && ShouldRetransmit(frame)) {
438     if (queued_retransmittable_frames_.get() == NULL) {
439       queued_retransmittable_frames_.reset(new RetransmittableFrames());
440     }
441     if (frame.type == STREAM_FRAME) {
442       queued_frames_.push_back(
443           queued_retransmittable_frames_->AddStreamFrame(frame.stream_frame));
444     } else {
445       queued_frames_.push_back(
446           queued_retransmittable_frames_->AddNonStreamFrame(frame));
447     }
448   } else {
449     queued_frames_.push_back(frame);
450   }
451   return true;
452 }
453 
MaybeAddPadding()454 void QuicPacketCreator::MaybeAddPadding() {
455   if (BytesFree() == 0) {
456     // Don't pad full packets.
457     return;
458   }
459 
460   // If any of the frames in the current packet are on the crypto stream
461   // then they contain handshake messagses, and we should pad them.
462   bool is_handshake = false;
463   for (size_t i = 0; i < queued_frames_.size(); ++i) {
464     if (queued_frames_[i].type == STREAM_FRAME &&
465         queued_frames_[i].stream_frame->stream_id == kCryptoStreamId) {
466       is_handshake = true;
467       break;
468     }
469   }
470   if (!is_handshake) {
471     return;
472   }
473 
474   QuicPaddingFrame padding;
475   bool success = AddFrame(QuicFrame(&padding), false);
476   DCHECK(success);
477 }
478 
479 }  // namespace net
480