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.
5 #include "net/quic/quic_packet_generator.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "net/quic/quic_fec_group.h"
10 #include "net/quic/quic_utils.h"
12 using base::StringPiece
;
16 class QuicAckNotifier
;
18 QuicPacketGenerator::QuicPacketGenerator(DelegateInterface
* delegate
,
19 DebugDelegateInterface
* debug_delegate
,
20 QuicPacketCreator
* creator
)
21 : delegate_(delegate
),
22 debug_delegate_(debug_delegate
),
23 packet_creator_(creator
),
25 should_send_ack_(false),
26 should_send_feedback_(false),
27 should_send_stop_waiting_(false) {
30 QuicPacketGenerator::~QuicPacketGenerator() {
31 for (QuicFrames::iterator it
= queued_control_frames_
.begin();
32 it
!= queued_control_frames_
.end(); ++it
) {
35 delete it
->padding_frame
;
38 delete it
->stream_frame
;
43 case CONGESTION_FEEDBACK_FRAME
:
44 delete it
->congestion_feedback_frame
;
46 case RST_STREAM_FRAME
:
47 delete it
->rst_stream_frame
;
49 case CONNECTION_CLOSE_FRAME
:
50 delete it
->connection_close_frame
;
53 delete it
->goaway_frame
;
55 case WINDOW_UPDATE_FRAME
:
56 delete it
->window_update_frame
;
59 delete it
->blocked_frame
;
61 case STOP_WAITING_FRAME
:
62 delete it
->stop_waiting_frame
;
65 DCHECK(false) << "Cannot delete type: " << it
->type
;
70 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback
,
71 bool also_send_stop_waiting
) {
72 should_send_ack_
= true;
73 should_send_feedback_
= also_send_feedback
;
74 should_send_stop_waiting_
= also_send_stop_waiting
;
75 SendQueuedFrames(false);
78 void QuicPacketGenerator::SetShouldSendStopWaiting() {
79 should_send_stop_waiting_
= true;
80 SendQueuedFrames(false);
83 void QuicPacketGenerator::AddControlFrame(const QuicFrame
& frame
) {
84 queued_control_frames_
.push_back(frame
);
85 SendQueuedFrames(false);
88 QuicConsumedData
QuicPacketGenerator::ConsumeData(QuicStreamId id
,
89 const IOVector
& data_to_write
,
90 QuicStreamOffset offset
,
92 QuicAckNotifier
* notifier
) {
93 IsHandshake handshake
= id
== kCryptoStreamId
? IS_HANDSHAKE
: NOT_HANDSHAKE
;
94 // The caller should have flushed pending frames before sending handshake
96 DCHECK(handshake
== NOT_HANDSHAKE
|| !HasPendingFrames());
97 SendQueuedFrames(false);
99 size_t total_bytes_consumed
= 0;
100 bool fin_consumed
= false;
102 if (!packet_creator_
->HasRoomForStreamFrame(id
, offset
)) {
103 SerializeAndSendPacket();
106 IOVector data
= data_to_write
;
107 size_t data_size
= data
.TotalBufferSize();
108 while (delegate_
->ShouldGeneratePacket(NOT_RETRANSMISSION
,
109 HAS_RETRANSMITTABLE_DATA
, handshake
)) {
111 size_t bytes_consumed
;
112 if (notifier
!= NULL
) {
113 // We want to track which packet this stream frame ends up in.
114 bytes_consumed
= packet_creator_
->CreateStreamFrameWithNotifier(
115 id
, data
, offset
+ total_bytes_consumed
, fin
, notifier
, &frame
);
117 bytes_consumed
= packet_creator_
->CreateStreamFrame(
118 id
, data
, offset
+ total_bytes_consumed
, fin
, &frame
);
120 if (!AddFrame(frame
)) {
121 LOG(DFATAL
) << "Failed to add stream frame.";
122 // Inability to add a STREAM frame creates an unrecoverable hole in a
123 // the stream, so it's best to close the connection.
124 delegate_
->CloseConnection(QUIC_INTERNAL_ERROR
, false);
125 return QuicConsumedData(0, false);
128 total_bytes_consumed
+= bytes_consumed
;
129 fin_consumed
= fin
&& total_bytes_consumed
== data_size
;
130 data
.Consume(bytes_consumed
);
131 DCHECK(data
.Empty() || packet_creator_
->BytesFree() == 0u);
133 // TODO(ianswett): Restore packet reordering.
134 if (!InBatchMode() || !packet_creator_
->HasRoomForStreamFrame(id
, offset
)) {
135 SerializeAndSendPacket();
139 // We're done writing the data. Exit the loop.
140 // We don't make this a precondition because we could have 0 bytes of data
141 // if we're simply writing a fin.
146 // Ensure the FEC group is closed at the end of this method if not in batch
148 if (!InBatchMode() && packet_creator_
->ShouldSendFec(true)) {
149 SerializedPacket serialized_fec
= packet_creator_
->SerializeFec();
150 DCHECK(serialized_fec
.packet
);
151 delegate_
->OnSerializedPacket(serialized_fec
);
154 DCHECK(InBatchMode() || !packet_creator_
->HasPendingFrames());
155 return QuicConsumedData(total_bytes_consumed
, fin_consumed
);
158 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
159 DCHECK(HasPendingFrames());
160 HasRetransmittableData retransmittable
=
161 (should_send_ack_
|| should_send_feedback_
|| should_send_stop_waiting_
)
162 ? NO_RETRANSMITTABLE_DATA
: HAS_RETRANSMITTABLE_DATA
;
163 if (retransmittable
== HAS_RETRANSMITTABLE_DATA
) {
164 DCHECK(!queued_control_frames_
.empty()); // These are retransmittable.
166 return delegate_
->ShouldGeneratePacket(NOT_RETRANSMISSION
, retransmittable
,
170 void QuicPacketGenerator::SendQueuedFrames(bool flush
) {
171 // Only add pending frames if we are SURE we can then send the whole packet.
172 while (HasPendingFrames() &&
173 (flush
|| CanSendWithNextPendingFrameAddition())) {
174 if (!AddNextPendingFrame()) {
175 // Packet was full, so serialize and send it.
176 SerializeAndSendPacket();
180 if (!InBatchMode() || flush
) {
181 if (packet_creator_
->HasPendingFrames()) {
182 SerializeAndSendPacket();
185 // Ensure the FEC group is closed at the end of this method unless other
186 // writes are pending.
187 if (packet_creator_
->ShouldSendFec(true)) {
188 SerializedPacket serialized_fec
= packet_creator_
->SerializeFec();
189 DCHECK(serialized_fec
.packet
);
190 delegate_
->OnSerializedPacket(serialized_fec
);
195 bool QuicPacketGenerator::InBatchMode() {
199 void QuicPacketGenerator::StartBatchOperations() {
203 void QuicPacketGenerator::FinishBatchOperations() {
205 SendQueuedFrames(false);
208 void QuicPacketGenerator::FlushAllQueuedFrames() {
209 SendQueuedFrames(true);
212 bool QuicPacketGenerator::HasQueuedFrames() const {
213 return packet_creator_
->HasPendingFrames() || HasPendingFrames();
216 bool QuicPacketGenerator::HasPendingFrames() const {
217 return should_send_ack_
|| should_send_feedback_
||
218 should_send_stop_waiting_
|| !queued_control_frames_
.empty();
221 bool QuicPacketGenerator::AddNextPendingFrame() {
222 if (should_send_ack_
) {
223 pending_ack_frame_
.reset(delegate_
->CreateAckFrame());
224 // If we can't this add the frame now, then we still need to do so later.
225 should_send_ack_
= !AddFrame(QuicFrame(pending_ack_frame_
.get()));
226 // Return success if we have cleared out this flag (i.e., added the frame).
227 // If we still need to send, then the frame is full, and we have failed.
228 return !should_send_ack_
;
231 if (should_send_feedback_
) {
232 pending_feedback_frame_
.reset(delegate_
->CreateFeedbackFrame());
233 // If we can't this add the frame now, then we still need to do so later.
234 should_send_feedback_
= !AddFrame(QuicFrame(pending_feedback_frame_
.get()));
235 // Return success if we have cleared out this flag (i.e., added the frame).
236 // If we still need to send, then the frame is full, and we have failed.
237 return !should_send_feedback_
;
240 if (should_send_stop_waiting_
) {
241 pending_stop_waiting_frame_
.reset(delegate_
->CreateStopWaitingFrame());
242 // If we can't this add the frame now, then we still need to do so later.
243 should_send_stop_waiting_
=
244 !AddFrame(QuicFrame(pending_stop_waiting_frame_
.get()));
245 // Return success if we have cleared out this flag (i.e., added the frame).
246 // If we still need to send, then the frame is full, and we have failed.
247 return !should_send_stop_waiting_
;
250 LOG_IF(DFATAL
, queued_control_frames_
.empty())
251 << "AddNextPendingFrame called with no queued control frames.";
252 if (!AddFrame(queued_control_frames_
.back())) {
256 queued_control_frames_
.pop_back();
260 bool QuicPacketGenerator::AddFrame(const QuicFrame
& frame
) {
261 bool success
= packet_creator_
->AddSavedFrame(frame
);
262 if (success
&& debug_delegate_
) {
263 debug_delegate_
->OnFrameAddedToPacket(frame
);
268 void QuicPacketGenerator::SerializeAndSendPacket() {
269 SerializedPacket serialized_packet
= packet_creator_
->SerializePacket();
270 DCHECK(serialized_packet
.packet
);
271 delegate_
->OnSerializedPacket(serialized_packet
);
273 if (packet_creator_
->ShouldSendFec(false)) {
274 SerializedPacket serialized_fec
= packet_creator_
->SerializeFec();
275 DCHECK(serialized_fec
.packet
);
276 delegate_
->OnSerializedPacket(serialized_fec
);