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/logging.h"
8 #include "net/quic/quic_fec_group.h"
9 #include "net/quic/quic_utils.h"
11 using base::StringPiece
;
15 QuicPacketGenerator::QuicPacketGenerator(DelegateInterface
* delegate
,
16 DebugDelegateInterface
* debug_delegate
,
17 QuicPacketCreator
* creator
)
18 : delegate_(delegate
),
19 debug_delegate_(debug_delegate
),
20 packet_creator_(creator
),
22 should_send_ack_(false),
23 should_send_feedback_(false) {
26 QuicPacketGenerator::~QuicPacketGenerator() {
27 for (QuicFrames::iterator it
= queued_control_frames_
.begin();
28 it
!= queued_control_frames_
.end(); ++it
) {
31 delete it
->padding_frame
;
34 delete it
->stream_frame
;
39 case CONGESTION_FEEDBACK_FRAME
:
40 delete it
->congestion_feedback_frame
;
42 case RST_STREAM_FRAME
:
43 delete it
->rst_stream_frame
;
45 case CONNECTION_CLOSE_FRAME
:
46 delete it
->connection_close_frame
;
49 delete it
->goaway_frame
;
52 DCHECK(false) << "Cannot delete type: " << it
->type
;
57 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback
) {
58 should_send_ack_
= true;
59 should_send_feedback_
= also_send_feedback
;
64 void QuicPacketGenerator::AddControlFrame(const QuicFrame
& frame
) {
65 queued_control_frames_
.push_back(frame
);
69 QuicConsumedData
QuicPacketGenerator::ConsumeData(QuicStreamId id
,
71 QuicStreamOffset offset
,
75 size_t total_bytes_consumed
= 0;
76 bool fin_consumed
= false;
78 while (delegate_
->CanWrite(NOT_RETRANSMISSION
, HAS_RETRANSMITTABLE_DATA
)) {
80 size_t bytes_consumed
= packet_creator_
->CreateStreamFrame(
81 id
, data
, offset
+ total_bytes_consumed
, fin
, &frame
);
82 bool success
= AddFrame(frame
);
85 total_bytes_consumed
+= bytes_consumed
;
86 fin_consumed
= fin
&& bytes_consumed
== data
.size();
87 data
.remove_prefix(bytes_consumed
);
88 DCHECK(data
.empty() || packet_creator_
->BytesFree() == 0u);
90 // TODO(ianswett): Restore packet reordering.
91 if (should_flush_
|| !packet_creator_
->HasRoomForStreamFrame()) {
92 SerializeAndSendPacket();
96 // We're done writing the data. Exit the loop.
97 // We don't make this a precondition because we could have 0 bytes of data
98 // if we're simply writing a fin.
103 // Ensure the FEC group is closed at the end of this method unless other
104 // writes are pending.
105 if (should_flush_
&& packet_creator_
->ShouldSendFec(true)) {
106 SerializedPacket serialized_fec
= packet_creator_
->SerializeFec();
107 DCHECK(serialized_fec
.packet
);
108 delegate_
->OnSerializedPacket(serialized_fec
);
111 DCHECK(!should_flush_
|| !packet_creator_
->HasPendingFrames());
112 return QuicConsumedData(total_bytes_consumed
, fin_consumed
);
115 void QuicPacketGenerator::SendQueuedFrames() {
116 packet_creator_
->MaybeStartFEC();
117 while (HasPendingFrames() && delegate_
->CanWrite(NOT_RETRANSMISSION
,
118 packet_creator_
->HasPendingFrames() ?
119 HAS_RETRANSMITTABLE_DATA
: NO_RETRANSMITTABLE_DATA
)) {
120 if (!AddNextPendingFrame()) {
121 // Packet was full, so serialize and send it.
122 SerializeAndSendPacket();
127 if (packet_creator_
->HasPendingFrames()) {
128 SerializeAndSendPacket();
131 // Ensure the FEC group is closed at the end of this method unless other
132 // writes are pending.
133 if (packet_creator_
->ShouldSendFec(true)) {
134 SerializedPacket serialized_fec
= packet_creator_
->SerializeFec();
135 DCHECK(serialized_fec
.packet
);
136 delegate_
->OnSerializedPacket(serialized_fec
);
137 packet_creator_
->MaybeStartFEC();
142 void QuicPacketGenerator::StartBatchOperations() {
143 should_flush_
= false;
146 void QuicPacketGenerator::FinishBatchOperations() {
147 should_flush_
= true;
151 bool QuicPacketGenerator::HasQueuedFrames() const {
152 return packet_creator_
->HasPendingFrames() || HasPendingFrames();
155 bool QuicPacketGenerator::HasPendingFrames() const {
156 return should_send_ack_
|| should_send_feedback_
||
157 !queued_control_frames_
.empty();
160 bool QuicPacketGenerator::AddNextPendingFrame() {
161 if (should_send_ack_
) {
162 pending_ack_frame_
.reset(delegate_
->CreateAckFrame());
163 if (!AddFrame(QuicFrame(pending_ack_frame_
.get()))) {
167 should_send_ack_
= false;
171 if (should_send_feedback_
) {
172 pending_feedback_frame_
.reset(delegate_
->CreateFeedbackFrame());
173 if (!AddFrame(QuicFrame(pending_feedback_frame_
.get()))) {
177 should_send_feedback_
= false;
181 DCHECK(!queued_control_frames_
.empty());
182 if (!AddFrame(queued_control_frames_
.back())) {
186 queued_control_frames_
.pop_back();
190 bool QuicPacketGenerator::AddFrame(const QuicFrame
& frame
) {
191 bool success
= packet_creator_
->AddSavedFrame(frame
);
192 if (success
&& debug_delegate_
) {
193 debug_delegate_
->OnFrameAddedToPacket(frame
);
198 void QuicPacketGenerator::SerializeAndSendPacket() {
199 SerializedPacket serialized_packet
= packet_creator_
->SerializePacket();
200 DCHECK(serialized_packet
.packet
);
201 delegate_
->OnSerializedPacket(serialized_packet
);
203 if (packet_creator_
->ShouldSendFec(false)) {
204 SerializedPacket serialized_fec
= packet_creator_
->SerializeFec();
205 DCHECK(serialized_fec
.packet
);
206 delegate_
->OnSerializedPacket(serialized_fec
);
207 packet_creator_
->MaybeStartFEC();