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