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_generator.h"
      6 
      7 #include "base/logging.h"
      8 #include "net/quic/quic_fec_group.h"
      9 #include "net/quic/quic_utils.h"
     10 
     11 using base::StringPiece;
     12 
     13 namespace net {
     14 
     15 class QuicAckNotifier;
     16 
     17 QuicPacketGenerator::QuicPacketGenerator(DelegateInterface* delegate,
     18                                          DebugDelegateInterface* debug_delegate,
     19                                          QuicPacketCreator* creator)
     20     : delegate_(delegate),
     21       debug_delegate_(debug_delegate),
     22       packet_creator_(creator),
     23       batch_mode_(false),
     24       should_send_ack_(false),
     25       should_send_feedback_(false) {
     26 }
     27 
     28 QuicPacketGenerator::~QuicPacketGenerator() {
     29   for (QuicFrames::iterator it = queued_control_frames_.begin();
     30        it != queued_control_frames_.end(); ++it) {
     31     switch (it->type) {
     32       case PADDING_FRAME:
     33         delete it->padding_frame;
     34         break;
     35       case STREAM_FRAME:
     36         delete it->stream_frame;
     37         break;
     38       case ACK_FRAME:
     39         delete it->ack_frame;
     40         break;
     41       case CONGESTION_FEEDBACK_FRAME:
     42         delete it->congestion_feedback_frame;
     43         break;
     44       case RST_STREAM_FRAME:
     45         delete it->rst_stream_frame;
     46         break;
     47       case CONNECTION_CLOSE_FRAME:
     48         delete it->connection_close_frame;
     49         break;
     50       case GOAWAY_FRAME:
     51         delete it->goaway_frame;
     52         break;
     53       case NUM_FRAME_TYPES:
     54         DCHECK(false) << "Cannot delete type: " << it->type;
     55     }
     56   }
     57 }
     58 
     59 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback) {
     60   should_send_ack_ = true;
     61   should_send_feedback_ = also_send_feedback;
     62   SendQueuedFrames(false);
     63 }
     64 
     65 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
     66   queued_control_frames_.push_back(frame);
     67   SendQueuedFrames(false);
     68 }
     69 
     70 QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
     71                                                   const IOVector& data_to_write,
     72                                                   QuicStreamOffset offset,
     73                                                   bool fin,
     74                                                   QuicAckNotifier* notifier) {
     75   IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE;
     76   // The caller should have flushed pending frames before sending handshake
     77   // messages.
     78   DCHECK(handshake == NOT_HANDSHAKE || !HasPendingFrames());
     79   SendQueuedFrames(false);
     80 
     81   size_t total_bytes_consumed = 0;
     82   bool fin_consumed = false;
     83 
     84   if (!packet_creator_->HasRoomForStreamFrame(id, offset)) {
     85     SerializeAndSendPacket();
     86   }
     87 
     88   IOVector data = data_to_write;
     89   size_t data_size = data.TotalBufferSize();
     90   while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION,
     91                                          HAS_RETRANSMITTABLE_DATA, handshake)) {
     92     QuicFrame frame;
     93     size_t bytes_consumed;
     94     if (notifier != NULL) {
     95       // We want to track which packet this stream frame ends up in.
     96       bytes_consumed = packet_creator_->CreateStreamFrameWithNotifier(
     97           id, data, offset + total_bytes_consumed, fin, notifier, &frame);
     98     } else {
     99       bytes_consumed = packet_creator_->CreateStreamFrame(
    100           id, data, offset + total_bytes_consumed, fin, &frame);
    101     }
    102     if (!AddFrame(frame)) {
    103       LOG(DFATAL) << "Failed to add stream frame.";
    104       // Inability to add a STREAM frame creates an unrecoverable hole in a
    105       // the stream, so it's best to close the connection.
    106       delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false);
    107       return QuicConsumedData(0, false);
    108     }
    109 
    110     total_bytes_consumed += bytes_consumed;
    111     fin_consumed = fin && total_bytes_consumed == data_size;
    112     data.Consume(bytes_consumed);
    113     DCHECK(data.Empty() || packet_creator_->BytesFree() == 0u);
    114 
    115     // TODO(ianswett): Restore packet reordering.
    116     if (!InBatchMode() || !packet_creator_->HasRoomForStreamFrame(id, offset)) {
    117       SerializeAndSendPacket();
    118     }
    119 
    120     if (data.Empty()) {
    121       // We're done writing the data. Exit the loop.
    122       // We don't make this a precondition because we could have 0 bytes of data
    123       // if we're simply writing a fin.
    124       break;
    125     }
    126   }
    127 
    128   // Ensure the FEC group is closed at the end of this method if not in batch
    129   // mode.
    130   if (!InBatchMode() && packet_creator_->ShouldSendFec(true)) {
    131     SerializedPacket serialized_fec = packet_creator_->SerializeFec();
    132     DCHECK(serialized_fec.packet);
    133     delegate_->OnSerializedPacket(serialized_fec);
    134   }
    135 
    136   DCHECK(InBatchMode() || !packet_creator_->HasPendingFrames());
    137   return QuicConsumedData(total_bytes_consumed, fin_consumed);
    138 }
    139 
    140 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
    141   DCHECK(HasPendingFrames());
    142   HasRetransmittableData retransmittable =
    143       (should_send_ack_ || should_send_feedback_) ? NO_RETRANSMITTABLE_DATA
    144                                                   : HAS_RETRANSMITTABLE_DATA;
    145   if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
    146       DCHECK(!queued_control_frames_.empty());  // These are retransmittable.
    147   }
    148   return delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, retransmittable,
    149                                          NOT_HANDSHAKE);
    150 }
    151 
    152 void QuicPacketGenerator::SendQueuedFrames(bool flush) {
    153   // Only add pending frames if we are SURE we can then send the whole packet.
    154   while (HasPendingFrames() &&
    155          (flush || CanSendWithNextPendingFrameAddition())) {
    156     if (!AddNextPendingFrame()) {
    157       // Packet was full, so serialize and send it.
    158       SerializeAndSendPacket();
    159     }
    160   }
    161 
    162   if (!InBatchMode() || flush) {
    163     if (packet_creator_->HasPendingFrames()) {
    164       SerializeAndSendPacket();
    165     }
    166 
    167     // Ensure the FEC group is closed at the end of this method unless other
    168     // writes are pending.
    169     if (packet_creator_->ShouldSendFec(true)) {
    170       SerializedPacket serialized_fec = packet_creator_->SerializeFec();
    171       DCHECK(serialized_fec.packet);
    172       delegate_->OnSerializedPacket(serialized_fec);
    173     }
    174   }
    175 }
    176 
    177 bool QuicPacketGenerator::InBatchMode() {
    178   return batch_mode_;
    179 }
    180 
    181 void QuicPacketGenerator::StartBatchOperations() {
    182   batch_mode_ = true;
    183 }
    184 
    185 void QuicPacketGenerator::FinishBatchOperations() {
    186   batch_mode_ = false;
    187   SendQueuedFrames(false);
    188 }
    189 
    190 void QuicPacketGenerator::FlushAllQueuedFrames() {
    191   SendQueuedFrames(true);
    192 }
    193 
    194 bool QuicPacketGenerator::HasQueuedFrames() const {
    195   return packet_creator_->HasPendingFrames() || HasPendingFrames();
    196 }
    197 
    198 bool QuicPacketGenerator::HasPendingFrames() const {
    199   return should_send_ack_ || should_send_feedback_ ||
    200       !queued_control_frames_.empty();
    201 }
    202 
    203 bool QuicPacketGenerator::AddNextPendingFrame() {
    204   if (should_send_ack_) {
    205     pending_ack_frame_.reset(delegate_->CreateAckFrame());
    206     // If we can't this add the frame now, then we still need to do so later.
    207     should_send_ack_ = !AddFrame(QuicFrame(pending_ack_frame_.get()));
    208     // Return success if we have cleared out this flag (i.e., added the frame).
    209     // If we still need to send, then the frame is full, and we have failed.
    210     return !should_send_ack_;
    211   }
    212 
    213   if (should_send_feedback_) {
    214     pending_feedback_frame_.reset(delegate_->CreateFeedbackFrame());
    215     // If we can't this add the frame now, then we still need to do so later.
    216     should_send_feedback_ = !AddFrame(QuicFrame(pending_feedback_frame_.get()));
    217     // Return success if we have cleared out this flag (i.e., added the frame).
    218     // If we still need to send, then the frame is full, and we have failed.
    219     return !should_send_feedback_;
    220   }
    221 
    222   if (queued_control_frames_.empty()) {
    223     LOG(DFATAL) << "AddNextPendingFrame called with no queued control frames.";
    224   }
    225   if (!AddFrame(queued_control_frames_.back())) {
    226     // Packet was full.
    227     return false;
    228   }
    229   queued_control_frames_.pop_back();
    230   return true;
    231 }
    232 
    233 bool QuicPacketGenerator::AddFrame(const QuicFrame& frame) {
    234   bool success = packet_creator_->AddSavedFrame(frame);
    235   if (success && debug_delegate_) {
    236     debug_delegate_->OnFrameAddedToPacket(frame);
    237   }
    238   return success;
    239 }
    240 
    241 void QuicPacketGenerator::SerializeAndSendPacket() {
    242   SerializedPacket serialized_packet = packet_creator_->SerializePacket();
    243   DCHECK(serialized_packet.packet);
    244   delegate_->OnSerializedPacket(serialized_packet);
    245 
    246   if (packet_creator_->ShouldSendFec(false)) {
    247     SerializedPacket serialized_fec = packet_creator_->SerializeFec();
    248     DCHECK(serialized_fec.packet);
    249     delegate_->OnSerializedPacket(serialized_fec);
    250   }
    251 }
    252 
    253 }  // namespace net
    254