Home | History | Annotate | Download | only in quic
      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_fec_group.h"
     10 #include "net/quic/quic_utils.h"
     11 
     12 using base::StringPiece;
     13 using std::make_pair;
     14 using std::min;
     15 using std::pair;
     16 using std::vector;
     17 
     18 namespace net {
     19 
     20 QuicPacketCreator::QuicPacketCreator(QuicGuid guid,
     21                                      QuicFramer* framer,
     22                                      QuicRandom* random_generator,
     23                                      bool is_server)
     24     : guid_(guid),
     25       framer_(framer),
     26       random_generator_(random_generator),
     27       sequence_number_(0),
     28       fec_group_number_(0),
     29       is_server_(is_server),
     30       send_version_in_packet_(!is_server),
     31       packet_size_(GetPacketHeaderSize(options_.send_guid_length,
     32                                        send_version_in_packet_,
     33                                        options_.send_sequence_number_length,
     34                                        NOT_IN_FEC_GROUP)) {
     35   framer_->set_fec_builder(this);
     36 }
     37 
     38 QuicPacketCreator::~QuicPacketCreator() {
     39 }
     40 
     41 void QuicPacketCreator::OnBuiltFecProtectedPayload(
     42     const QuicPacketHeader& header, StringPiece payload) {
     43   if (fec_group_.get()) {
     44     fec_group_->Update(header, payload);
     45   }
     46 }
     47 
     48 bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
     49   return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 &&
     50       (force_close ||
     51        fec_group_->NumReceivedPackets() >= options_.max_packets_per_fec_group);
     52 }
     53 
     54 void QuicPacketCreator::MaybeStartFEC() {
     55   if (options_.max_packets_per_fec_group > 0 && fec_group_.get() == NULL) {
     56     DCHECK(queued_frames_.empty());
     57     // Set the fec group number to the sequence number of the next packet.
     58     fec_group_number_ = sequence_number() + 1;
     59     fec_group_.reset(new QuicFecGroup());
     60     packet_size_ = GetPacketHeaderSize(options_.send_guid_length,
     61                                        send_version_in_packet_,
     62                                        options_.send_sequence_number_length,
     63                                        IN_FEC_GROUP);
     64     DCHECK_LE(packet_size_, options_.max_packet_length);
     65   }
     66 }
     67 
     68 // Stops serializing version of the protocol in packets sent after this call.
     69 // A packet that is already open might send kQuicVersionSize bytes less than the
     70 // maximum packet size if we stop sending version before it is serialized.
     71 void QuicPacketCreator::StopSendingVersion() {
     72   DCHECK(send_version_in_packet_);
     73   send_version_in_packet_ = false;
     74   if (packet_size_ > 0) {
     75     DCHECK_LT(kQuicVersionSize, packet_size_);
     76     packet_size_ -= kQuicVersionSize;
     77   }
     78 }
     79 
     80 bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
     81                                               QuicStreamOffset offset) const {
     82   return BytesFree() >
     83       QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset, true);
     84 }
     85 
     86 // static
     87 size_t QuicPacketCreator::StreamFramePacketOverhead(
     88     QuicVersion version,
     89     QuicGuidLength guid_length,
     90     bool include_version,
     91     QuicSequenceNumberLength sequence_number_length,
     92     InFecGroup is_in_fec_group) {
     93   return GetPacketHeaderSize(guid_length, include_version,
     94                              sequence_number_length, is_in_fec_group) +
     95       // Assumes this is a stream with a single lone packet.
     96       QuicFramer::GetMinStreamFrameSize(version, 1u, 0u, true);
     97 }
     98 
     99 size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
    100                                             StringPiece data,
    101                                             QuicStreamOffset offset,
    102                                             bool fin,
    103                                             QuicFrame* frame) {
    104   DCHECK_GT(options_.max_packet_length,
    105             StreamFramePacketOverhead(
    106                 framer_->version(), PACKET_8BYTE_GUID, kIncludeVersion,
    107                 PACKET_6BYTE_SEQUENCE_NUMBER, IN_FEC_GROUP));
    108   DCHECK(HasRoomForStreamFrame(id, offset));
    109 
    110   const size_t free_bytes = BytesFree();
    111   size_t bytes_consumed = 0;
    112 
    113   if (data.size() != 0) {
    114     // When a STREAM frame is the last frame in a packet, it consumes two fewer
    115     // bytes of framing overhead.
    116     // Anytime more data is available than fits in with the extra two bytes,
    117     // the frame will be the last, and up to two extra bytes are consumed.
    118     // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when
    119     // 1 byte is available, because then the STREAM frame isn't the last.
    120 
    121     // The minimum frame size(0 bytes of data) if it's not the last frame.
    122     size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
    123         framer_->version(), id, offset, false);
    124     // Check if it's the last frame in the packet.
    125     if (data.size() + min_frame_size > free_bytes) {
    126       // The minimum frame size(0 bytes of data) if it is the last frame.
    127       size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize(
    128           framer_->version(), id, offset, true);
    129       bytes_consumed =
    130           min<size_t>(free_bytes - min_last_frame_size, data.size());
    131     } else {
    132       DCHECK_LT(data.size(), BytesFree());
    133       bytes_consumed = data.size();
    134     }
    135 
    136     bool set_fin = fin && bytes_consumed == data.size();  // Last frame.
    137     StringPiece data_frame(data.data(), bytes_consumed);
    138     *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, data_frame));
    139   } else {
    140     DCHECK(fin);
    141     // Create a new packet for the fin, if necessary.
    142     *frame = QuicFrame(new QuicStreamFrame(id, true, offset, ""));
    143   }
    144 
    145   return bytes_consumed;
    146 }
    147 
    148 SerializedPacket QuicPacketCreator::SerializeAllFrames(
    149     const QuicFrames& frames) {
    150   // TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued
    151   // frames from SendStreamData()[send_stream_should_flush_ == false &&
    152   // data.empty() == true] and retransmit due to RTO.
    153   DCHECK_EQ(0u, queued_frames_.size());
    154   for (size_t i = 0; i < frames.size(); ++i) {
    155     bool success = AddFrame(frames[i], false);
    156     DCHECK(success);
    157   }
    158   SerializedPacket packet = SerializePacket();
    159   DCHECK(packet.retransmittable_frames == NULL);
    160   return packet;
    161 }
    162 
    163 bool QuicPacketCreator::HasPendingFrames() {
    164   return !queued_frames_.empty();
    165 }
    166 
    167 size_t QuicPacketCreator::BytesFree() const {
    168   const size_t max_plaintext_size =
    169       framer_->GetMaxPlaintextSize(options_.max_packet_length);
    170   if (packet_size_ > max_plaintext_size) {
    171     return 0;
    172   }
    173   return max_plaintext_size - packet_size_;
    174 }
    175 
    176 bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) {
    177   return AddFrame(frame, true);
    178 }
    179 
    180 SerializedPacket QuicPacketCreator::SerializePacket() {
    181   DCHECK_EQ(false, queued_frames_.empty());
    182   QuicPacketHeader header;
    183   FillPacketHeader(fec_group_number_, false, false, &header);
    184 
    185   SerializedPacket serialized = framer_->BuildDataPacket(
    186       header, queued_frames_, packet_size_);
    187   queued_frames_.clear();
    188   packet_size_ = GetPacketHeaderSize(options_.send_guid_length,
    189                                      send_version_in_packet_,
    190                                      options_.send_sequence_number_length,
    191                                      fec_group_.get() != NULL ?
    192                                          IN_FEC_GROUP : NOT_IN_FEC_GROUP);
    193   serialized.retransmittable_frames = queued_retransmittable_frames_.release();
    194   return serialized;
    195 }
    196 
    197 SerializedPacket QuicPacketCreator::SerializeFec() {
    198   DCHECK_LT(0u, fec_group_->NumReceivedPackets());
    199   DCHECK_EQ(0u, queued_frames_.size());
    200   QuicPacketHeader header;
    201   FillPacketHeader(fec_group_number_, true,
    202                    fec_group_->entropy_parity(), &header);
    203   QuicFecData fec_data;
    204   fec_data.fec_group = fec_group_->min_protected_packet();
    205   fec_data.redundancy = fec_group_->payload_parity();
    206   SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data);
    207   fec_group_.reset(NULL);
    208   fec_group_number_ = 0;
    209   // Reset packet_size_, since the next packet may not have an FEC group.
    210   packet_size_ = GetPacketHeaderSize(options_.send_guid_length,
    211                                      send_version_in_packet_,
    212                                      options_.send_sequence_number_length,
    213                                      NOT_IN_FEC_GROUP);
    214   DCHECK(serialized.packet);
    215   DCHECK_GE(options_.max_packet_length, serialized.packet->length());
    216   return serialized;
    217 }
    218 
    219 SerializedPacket QuicPacketCreator::SerializeConnectionClose(
    220     QuicConnectionCloseFrame* close_frame) {
    221   QuicFrames frames;
    222   frames.push_back(QuicFrame(close_frame));
    223   return SerializeAllFrames(frames);
    224 }
    225 
    226 QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
    227     const QuicVersionVector& supported_versions) {
    228   DCHECK(is_server_);
    229   QuicPacketPublicHeader header;
    230   header.guid = guid_;
    231   header.reset_flag = false;
    232   header.version_flag = true;
    233   header.versions = supported_versions;
    234   QuicEncryptedPacket* encrypted =
    235       framer_->BuildVersionNegotiationPacket(header, supported_versions);
    236   DCHECK(encrypted);
    237   DCHECK_GE(options_.max_packet_length, encrypted->length());
    238   return encrypted;
    239 }
    240 
    241 void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
    242                                          bool fec_flag,
    243                                          bool fec_entropy_flag,
    244                                          QuicPacketHeader* header) {
    245   header->public_header.guid = guid_;
    246   header->public_header.reset_flag = false;
    247   header->public_header.version_flag = send_version_in_packet_;
    248   header->fec_flag = fec_flag;
    249   header->packet_sequence_number = ++sequence_number_;
    250 
    251   bool entropy_flag;
    252   if (header->packet_sequence_number == 1) {
    253     DCHECK(!fec_flag);
    254     // TODO(satyamshekhar): No entropy in the first message.
    255     // For crypto tests to pass. Fix this by using deterministic QuicRandom.
    256     entropy_flag = 0;
    257   } else if (fec_flag) {
    258     // FEC packets don't have an entropy of their own. Entropy flag for FEC
    259     // packets is the XOR of entropy of previous packets.
    260     entropy_flag = fec_entropy_flag;
    261   } else {
    262     entropy_flag = random_generator_->RandBool();
    263   }
    264   header->entropy_flag = entropy_flag;
    265   header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
    266   header->fec_group = fec_group;
    267 }
    268 
    269 bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
    270   return frame.type != ACK_FRAME && frame.type != CONGESTION_FEEDBACK_FRAME &&
    271       frame.type != PADDING_FRAME;
    272 }
    273 
    274 bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
    275                                  bool save_retransmittable_frames) {
    276   size_t frame_len = framer_->GetSerializedFrameLength(
    277       frame, BytesFree(), queued_frames_.empty());
    278   if (frame_len == 0) {
    279     return false;
    280   }
    281   packet_size_ += frame_len;
    282 
    283   if (save_retransmittable_frames && ShouldRetransmit(frame)) {
    284     if (queued_retransmittable_frames_.get() == NULL) {
    285       queued_retransmittable_frames_.reset(new RetransmittableFrames());
    286     }
    287     if (frame.type == STREAM_FRAME) {
    288       queued_frames_.push_back(
    289           queued_retransmittable_frames_->AddStreamFrame(frame.stream_frame));
    290     } else {
    291       queued_frames_.push_back(
    292           queued_retransmittable_frames_->AddNonStreamFrame(frame));
    293     }
    294   } else {
    295     queued_frames_.push_back(frame);
    296   }
    297   return true;
    298 }
    299 
    300 }  // namespace net
    301