Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_packet_generator.cc
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/basictypes.h"
8 #include "base/logging.h"
9 #include "net/quic/quic_fec_group.h"
10 #include "net/quic/quic_utils.h"
11
12 using base::StringPiece;
13
14 namespace net {
15
16 class QuicAckNotifier;
17
18 QuicPacketGenerator::QuicPacketGenerator(DelegateInterface* delegate,
19                                          DebugDelegateInterface* debug_delegate,
20                                          QuicPacketCreator* creator)
21     : delegate_(delegate),
22       debug_delegate_(debug_delegate),
23       packet_creator_(creator),
24       batch_mode_(false),
25       should_send_ack_(false),
26       should_send_feedback_(false),
27       should_send_stop_waiting_(false) {
28 }
29
30 QuicPacketGenerator::~QuicPacketGenerator() {
31   for (QuicFrames::iterator it = queued_control_frames_.begin();
32        it != queued_control_frames_.end(); ++it) {
33     switch (it->type) {
34       case PADDING_FRAME:
35         delete it->padding_frame;
36         break;
37       case STREAM_FRAME:
38         delete it->stream_frame;
39         break;
40       case ACK_FRAME:
41         delete it->ack_frame;
42         break;
43       case CONGESTION_FEEDBACK_FRAME:
44         delete it->congestion_feedback_frame;
45         break;
46       case RST_STREAM_FRAME:
47         delete it->rst_stream_frame;
48         break;
49       case CONNECTION_CLOSE_FRAME:
50         delete it->connection_close_frame;
51         break;
52       case GOAWAY_FRAME:
53         delete it->goaway_frame;
54         break;
55       case WINDOW_UPDATE_FRAME:
56         delete it->window_update_frame;
57         break;
58       case BLOCKED_FRAME:
59         delete it->blocked_frame;
60         break;
61       case STOP_WAITING_FRAME:
62         delete it->stop_waiting_frame;
63         break;
64       case PING_FRAME:
65         delete it->ping_frame;
66         break;
67       case NUM_FRAME_TYPES:
68         DCHECK(false) << "Cannot delete type: " << it->type;
69     }
70   }
71 }
72
73 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback,
74                                            bool also_send_stop_waiting) {
75   should_send_ack_ = true;
76   should_send_feedback_ = also_send_feedback;
77   should_send_stop_waiting_ = also_send_stop_waiting;
78   SendQueuedFrames(false);
79 }
80
81 void QuicPacketGenerator::SetShouldSendStopWaiting() {
82   should_send_stop_waiting_ = true;
83   SendQueuedFrames(false);
84 }
85
86 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
87   queued_control_frames_.push_back(frame);
88   SendQueuedFrames(false);
89 }
90
91 QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
92                                                   const IOVector& data_to_write,
93                                                   QuicStreamOffset offset,
94                                                   bool fin,
95                                                   QuicAckNotifier* notifier) {
96   IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE;
97   SendQueuedFrames(false);
98
99   size_t total_bytes_consumed = 0;
100   bool fin_consumed = false;
101
102   if (!packet_creator_->HasRoomForStreamFrame(id, offset)) {
103     SerializeAndSendPacket();
104   }
105
106   IOVector data = data_to_write;
107   size_t data_size = data.TotalBufferSize();
108   while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION,
109                                          HAS_RETRANSMITTABLE_DATA, handshake)) {
110     QuicFrame frame;
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);
116     } else {
117       bytes_consumed = packet_creator_->CreateStreamFrame(
118           id, data, offset + total_bytes_consumed, fin, &frame);
119     }
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);
126     }
127
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);
132
133     // TODO(ianswett): Restore packet reordering.
134     if (!InBatchMode() || !packet_creator_->HasRoomForStreamFrame(id, offset)) {
135       SerializeAndSendPacket();
136     }
137
138     if (data.Empty()) {
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.
142       break;
143     }
144   }
145
146   // Ensure the FEC group is closed at the end of this method if not in batch
147   // mode.
148   if (!InBatchMode() && packet_creator_->ShouldSendFec(true)) {
149     // TODO(jri): SerializeFec can return a NULL packet, and this should
150     // cause an early return, with a call to delegate_->OnPacketGenerationError.
151     SerializedPacket serialized_fec = packet_creator_->SerializeFec();
152     DCHECK(serialized_fec.packet);
153     delegate_->OnSerializedPacket(serialized_fec);
154   }
155
156   DCHECK(InBatchMode() || !packet_creator_->HasPendingFrames());
157   return QuicConsumedData(total_bytes_consumed, fin_consumed);
158 }
159
160 bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
161   DCHECK(HasPendingFrames());
162   HasRetransmittableData retransmittable =
163       (should_send_ack_ || should_send_feedback_ || should_send_stop_waiting_)
164       ? NO_RETRANSMITTABLE_DATA : HAS_RETRANSMITTABLE_DATA;
165   if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
166       DCHECK(!queued_control_frames_.empty());  // These are retransmittable.
167   }
168   return delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, retransmittable,
169                                          NOT_HANDSHAKE);
170 }
171
172 void QuicPacketGenerator::SendQueuedFrames(bool flush) {
173   // Only add pending frames if we are SURE we can then send the whole packet.
174   while (HasPendingFrames() &&
175          (flush || CanSendWithNextPendingFrameAddition())) {
176     if (!AddNextPendingFrame()) {
177       // Packet was full, so serialize and send it.
178       SerializeAndSendPacket();
179     }
180   }
181
182   if (!InBatchMode() || flush) {
183     if (packet_creator_->HasPendingFrames()) {
184       SerializeAndSendPacket();
185     }
186
187     // Ensure the FEC group is closed at the end of this method unless other
188     // writes are pending.
189     if (packet_creator_->ShouldSendFec(true)) {
190       // TODO(jri): SerializeFec can return a NULL packet, and this should
191       // cause an early return, with a call to
192       // delegate_->OnPacketGenerationError.
193       SerializedPacket serialized_fec = packet_creator_->SerializeFec();
194       DCHECK(serialized_fec.packet);
195       delegate_->OnSerializedPacket(serialized_fec);
196     }
197   }
198 }
199
200 bool QuicPacketGenerator::InBatchMode() {
201   return batch_mode_;
202 }
203
204 void QuicPacketGenerator::StartBatchOperations() {
205   batch_mode_ = true;
206 }
207
208 void QuicPacketGenerator::FinishBatchOperations() {
209   batch_mode_ = false;
210   SendQueuedFrames(false);
211 }
212
213 void QuicPacketGenerator::FlushAllQueuedFrames() {
214   SendQueuedFrames(true);
215 }
216
217 bool QuicPacketGenerator::HasQueuedFrames() const {
218   return packet_creator_->HasPendingFrames() || HasPendingFrames();
219 }
220
221 bool QuicPacketGenerator::HasPendingFrames() const {
222   return should_send_ack_ || should_send_feedback_ ||
223       should_send_stop_waiting_ || !queued_control_frames_.empty();
224 }
225
226 bool QuicPacketGenerator::AddNextPendingFrame() {
227   if (should_send_ack_) {
228     pending_ack_frame_.reset(delegate_->CreateAckFrame());
229     // If we can't this add the frame now, then we still need to do so later.
230     should_send_ack_ = !AddFrame(QuicFrame(pending_ack_frame_.get()));
231     // Return success if we have cleared out this flag (i.e., added the frame).
232     // If we still need to send, then the frame is full, and we have failed.
233     return !should_send_ack_;
234   }
235
236   if (should_send_feedback_) {
237     pending_feedback_frame_.reset(delegate_->CreateFeedbackFrame());
238     // If we can't this add the frame now, then we still need to do so later.
239     should_send_feedback_ = !AddFrame(QuicFrame(pending_feedback_frame_.get()));
240     // Return success if we have cleared out this flag (i.e., added the frame).
241     // If we still need to send, then the frame is full, and we have failed.
242     return !should_send_feedback_;
243   }
244
245   if (should_send_stop_waiting_) {
246     pending_stop_waiting_frame_.reset(delegate_->CreateStopWaitingFrame());
247     // If we can't this add the frame now, then we still need to do so later.
248     should_send_stop_waiting_ =
249         !AddFrame(QuicFrame(pending_stop_waiting_frame_.get()));
250     // Return success if we have cleared out this flag (i.e., added the frame).
251     // If we still need to send, then the frame is full, and we have failed.
252     return !should_send_stop_waiting_;
253   }
254
255   LOG_IF(DFATAL, queued_control_frames_.empty())
256       << "AddNextPendingFrame called with no queued control frames.";
257   if (!AddFrame(queued_control_frames_.back())) {
258     // Packet was full.
259     return false;
260   }
261   queued_control_frames_.pop_back();
262   return true;
263 }
264
265 bool QuicPacketGenerator::AddFrame(const QuicFrame& frame) {
266   bool success = packet_creator_->AddSavedFrame(frame);
267   if (success && debug_delegate_) {
268     debug_delegate_->OnFrameAddedToPacket(frame);
269   }
270   return success;
271 }
272
273 void QuicPacketGenerator::SerializeAndSendPacket() {
274   SerializedPacket serialized_packet = packet_creator_->SerializePacket();
275   DCHECK(serialized_packet.packet);
276   delegate_->OnSerializedPacket(serialized_packet);
277
278   if (packet_creator_->ShouldSendFec(false)) {
279     // TODO(jri): SerializeFec can return a NULL packet, and this should
280     // cause an early return, with a call to delegate_->OnPacketGenerationError.
281     SerializedPacket serialized_fec = packet_creator_->SerializeFec();
282     DCHECK(serialized_fec.packet);
283     delegate_->OnSerializedPacket(serialized_fec);
284   }
285 }
286
287 }  // namespace net