blob: 11efae85892b38262e37eb2c834af41cd01f28c1 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2017 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/third_party/quiche/src/quic/core/quic_control_frame_manager.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/quic_constants.h"
10#include "net/third_party/quiche/src/quic/core/quic_session.h"
11#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014
15namespace quic {
16
fayang83d7e3e2019-07-31 14:45:19 -070017namespace {
18
19// The maximum number of buffered control frames which are waiting to be ACKed
20// or sent for the first time.
21const size_t kMaxNumControlFrames = 1000;
22
23} // namespace
24
QUICHE teama6ef0a62019-03-07 20:34:33 -050025QuicControlFrameManager::QuicControlFrameManager(QuicSession* session)
26 : last_control_frame_id_(kInvalidControlFrameId),
27 least_unacked_(1),
28 least_unsent_(1),
fayang83d7e3e2019-07-31 14:45:19 -070029 session_(session),
30 add_upper_limit_(GetQuicReloadableFlag(
fayangd85976f2019-09-27 05:59:14 -070031 quic_add_upper_limit_of_buffered_control_frames3)) {
fayang83d7e3e2019-07-31 14:45:19 -070032 if (add_upper_limit_) {
fayang2de46de2019-09-13 09:09:27 -070033 QUIC_RELOADABLE_FLAG_COUNT(
fayangd85976f2019-09-27 05:59:14 -070034 quic_add_upper_limit_of_buffered_control_frames3);
fayang83d7e3e2019-07-31 14:45:19 -070035 }
36}
QUICHE teama6ef0a62019-03-07 20:34:33 -050037
38QuicControlFrameManager::~QuicControlFrameManager() {
39 while (!control_frames_.empty()) {
40 DeleteFrame(&control_frames_.front());
41 control_frames_.pop_front();
42 }
43}
44
45void QuicControlFrameManager::WriteOrBufferQuicFrame(QuicFrame frame) {
46 const bool had_buffered_frames = HasBufferedFrames();
47 control_frames_.emplace_back(frame);
fayang83d7e3e2019-07-31 14:45:19 -070048 if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
49 session_->connection()->CloseConnection(
50 QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
51 QuicStrCat("More than ", kMaxNumControlFrames,
52 "buffered control frames, least_unacked: ", least_unacked_,
53 ", least_unsent_: ", least_unsent_),
54 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
55 return;
56 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050057 if (had_buffered_frames) {
58 return;
59 }
60 WriteBufferedFrames();
61}
62
63void QuicControlFrameManager::WriteOrBufferRstStream(
64 QuicStreamId id,
65 QuicRstStreamErrorCode error,
66 QuicStreamOffset bytes_written) {
67 QUIC_DVLOG(1) << "Writing RST_STREAM_FRAME";
68 WriteOrBufferQuicFrame((QuicFrame(new QuicRstStreamFrame(
69 ++last_control_frame_id_, id, error, bytes_written))));
70}
71
72void QuicControlFrameManager::WriteOrBufferGoAway(
73 QuicErrorCode error,
74 QuicStreamId last_good_stream_id,
vasilvvc48c8712019-03-11 13:38:16 -070075 const std::string& reason) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 QUIC_DVLOG(1) << "Writing GOAWAY_FRAME";
77 WriteOrBufferQuicFrame(QuicFrame(new QuicGoAwayFrame(
78 ++last_control_frame_id_, error, last_good_stream_id, reason)));
79}
80
81void QuicControlFrameManager::WriteOrBufferWindowUpdate(
82 QuicStreamId id,
83 QuicStreamOffset byte_offset) {
84 QUIC_DVLOG(1) << "Writing WINDOW_UPDATE_FRAME";
85 WriteOrBufferQuicFrame(QuicFrame(
86 new QuicWindowUpdateFrame(++last_control_frame_id_, id, byte_offset)));
87}
88
89void QuicControlFrameManager::WriteOrBufferBlocked(QuicStreamId id) {
90 QUIC_DVLOG(1) << "Writing BLOCKED_FRAME";
91 WriteOrBufferQuicFrame(
92 QuicFrame(new QuicBlockedFrame(++last_control_frame_id_, id)));
93}
94
fkastenholz3c4eabf2019-04-22 07:49:59 -070095void QuicControlFrameManager::WriteOrBufferStreamsBlocked(QuicStreamCount count,
96 bool unidirectional) {
97 QUIC_DVLOG(1) << "Writing STREAMS_BLOCKED Frame";
98 QUIC_CODE_COUNT(quic_streams_blocked_transmits);
99 WriteOrBufferQuicFrame(QuicFrame(QuicStreamsBlockedFrame(
100 ++last_control_frame_id_, count, unidirectional)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101}
102
fkastenholz3c4eabf2019-04-22 07:49:59 -0700103void QuicControlFrameManager::WriteOrBufferMaxStreams(QuicStreamCount count,
104 bool unidirectional) {
105 QUIC_DVLOG(1) << "Writing MAX_STREAMS Frame";
106 QUIC_CODE_COUNT(quic_max_streams_transmits);
107 WriteOrBufferQuicFrame(QuicFrame(
108 QuicMaxStreamsFrame(++last_control_frame_id_, count, unidirectional)));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500109}
110
111void QuicControlFrameManager::WriteOrBufferStopSending(uint16_t code,
112 QuicStreamId stream_id) {
113 QUIC_DVLOG(1) << "Writing STOP_SENDING_FRAME";
114 WriteOrBufferQuicFrame(QuicFrame(
115 new QuicStopSendingFrame(++last_control_frame_id_, stream_id, code)));
116}
117
118void QuicControlFrameManager::WritePing() {
119 QUIC_DVLOG(1) << "Writing PING_FRAME";
120 if (HasBufferedFrames()) {
121 // Do not send ping if there is buffered frames.
122 QUIC_LOG(WARNING)
123 << "Try to send PING when there is buffered control frames.";
124 return;
125 }
126 control_frames_.emplace_back(
127 QuicFrame(QuicPingFrame(++last_control_frame_id_)));
fayang83d7e3e2019-07-31 14:45:19 -0700128 if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
129 session_->connection()->CloseConnection(
130 QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
131 QuicStrCat("More than ", kMaxNumControlFrames,
132 "buffered control frames, least_unacked: ", least_unacked_,
133 ", least_unsent_: ", least_unsent_),
134 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
135 return;
136 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 WriteBufferedFrames();
138}
139
140void QuicControlFrameManager::OnControlFrameSent(const QuicFrame& frame) {
141 QuicControlFrameId id = GetControlFrameId(frame);
142 if (id == kInvalidControlFrameId) {
143 QUIC_BUG
144 << "Send or retransmit a control frame with invalid control frame id";
145 return;
146 }
147 if (frame.type == WINDOW_UPDATE_FRAME) {
148 QuicStreamId stream_id = frame.window_update_frame->stream_id;
149 if (QuicContainsKey(window_update_frames_, stream_id) &&
150 id > window_update_frames_[stream_id]) {
151 // Consider the older window update of the same stream as acked.
152 OnControlFrameIdAcked(window_update_frames_[stream_id]);
153 }
154 window_update_frames_[stream_id] = id;
155 }
156 if (QuicContainsKey(pending_retransmissions_, id)) {
157 // This is retransmitted control frame.
158 pending_retransmissions_.erase(id);
159 return;
160 }
161 if (id > least_unsent_) {
162 QUIC_BUG << "Try to send control frames out of order, id: " << id
163 << " least_unsent: " << least_unsent_;
164 session_->connection()->CloseConnection(
165 QUIC_INTERNAL_ERROR, "Try to send control frames out of order",
166 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
167 return;
168 }
169 ++least_unsent_;
170}
171
172bool QuicControlFrameManager::OnControlFrameAcked(const QuicFrame& frame) {
173 QuicControlFrameId id = GetControlFrameId(frame);
174 if (!OnControlFrameIdAcked(id)) {
175 return false;
176 }
177 if (frame.type == WINDOW_UPDATE_FRAME) {
178 QuicStreamId stream_id = frame.window_update_frame->stream_id;
179 if (QuicContainsKey(window_update_frames_, stream_id) &&
180 window_update_frames_[stream_id] == id) {
181 window_update_frames_.erase(stream_id);
182 }
183 }
184 return true;
185}
186
187void QuicControlFrameManager::OnControlFrameLost(const QuicFrame& frame) {
188 QuicControlFrameId id = GetControlFrameId(frame);
189 if (id == kInvalidControlFrameId) {
190 // Frame does not have a valid control frame ID, ignore it.
191 return;
192 }
193 if (id >= least_unsent_) {
194 QUIC_BUG << "Try to mark unsent control frame as lost";
195 session_->connection()->CloseConnection(
196 QUIC_INTERNAL_ERROR, "Try to mark unsent control frame as lost",
197 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
198 return;
199 }
200 if (id < least_unacked_ ||
201 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
202 kInvalidControlFrameId) {
203 // This frame has already been acked.
204 return;
205 }
206 if (!QuicContainsKey(pending_retransmissions_, id)) {
207 pending_retransmissions_[id] = true;
fayang83d7e3e2019-07-31 14:45:19 -0700208 QUIC_BUG_IF(pending_retransmissions_.size() > control_frames_.size())
209 << "least_unacked_: " << least_unacked_
210 << ", least_unsent_: " << least_unsent_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500211 }
212}
213
214bool QuicControlFrameManager::IsControlFrameOutstanding(
215 const QuicFrame& frame) const {
216 QuicControlFrameId id = GetControlFrameId(frame);
217 if (id == kInvalidControlFrameId) {
218 // Frame without a control frame ID should not be retransmitted.
219 return false;
220 }
221 // Consider this frame is outstanding if it does not get acked.
222 return id < least_unacked_ + control_frames_.size() && id >= least_unacked_ &&
223 GetControlFrameId(control_frames_.at(id - least_unacked_)) !=
224 kInvalidControlFrameId;
225}
226
227bool QuicControlFrameManager::HasPendingRetransmission() const {
228 return !pending_retransmissions_.empty();
229}
230
231bool QuicControlFrameManager::WillingToWrite() const {
232 return HasPendingRetransmission() || HasBufferedFrames();
233}
234
235QuicFrame QuicControlFrameManager::NextPendingRetransmission() const {
236 QUIC_BUG_IF(pending_retransmissions_.empty())
237 << "Unexpected call to NextPendingRetransmission() with empty pending "
238 << "retransmission list.";
239 QuicControlFrameId id = pending_retransmissions_.begin()->first;
240 return control_frames_.at(id - least_unacked_);
241}
242
243void QuicControlFrameManager::OnCanWrite() {
244 if (HasPendingRetransmission()) {
245 // Exit early to allow streams to write pending retransmissions if any.
246 WritePendingRetransmission();
247 return;
248 }
249 WriteBufferedFrames();
250}
251
252bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
253 QuicControlFrameId id = GetControlFrameId(frame);
254 if (id == kInvalidControlFrameId) {
255 // Frame does not have a valid control frame ID, ignore it. Returns true
256 // to allow writing following frames.
257 return true;
258 }
259 if (id >= least_unsent_) {
260 QUIC_BUG << "Try to retransmit unsent control frame";
261 session_->connection()->CloseConnection(
262 QUIC_INTERNAL_ERROR, "Try to retransmit unsent control frame",
263 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
264 return false;
265 }
266 if (id < least_unacked_ ||
267 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
268 kInvalidControlFrameId) {
269 // This frame has already been acked.
270 return true;
271 }
272 QuicFrame copy = CopyRetransmittableControlFrame(frame);
273 QUIC_DVLOG(1) << "control frame manager is forced to retransmit frame: "
274 << frame;
275 if (session_->WriteControlFrame(copy)) {
276 return true;
277 }
278 DeleteFrame(&copy);
279 return false;
280}
281
282void QuicControlFrameManager::WriteBufferedFrames() {
283 while (HasBufferedFrames()) {
284 if (session_->session_decides_what_to_write()) {
285 session_->SetTransmissionType(NOT_RETRANSMISSION);
286 }
287 QuicFrame frame_to_send =
288 control_frames_.at(least_unsent_ - least_unacked_);
289 QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
290 if (!session_->WriteControlFrame(copy)) {
291 // Connection is write blocked.
292 DeleteFrame(&copy);
293 break;
294 }
295 OnControlFrameSent(frame_to_send);
296 }
297}
298
299void QuicControlFrameManager::WritePendingRetransmission() {
300 while (HasPendingRetransmission()) {
301 QuicFrame pending = NextPendingRetransmission();
302 QuicFrame copy = CopyRetransmittableControlFrame(pending);
303 if (!session_->WriteControlFrame(copy)) {
304 // Connection is write blocked.
305 DeleteFrame(&copy);
306 break;
307 }
308 OnControlFrameSent(pending);
309 }
310}
311
312bool QuicControlFrameManager::OnControlFrameIdAcked(QuicControlFrameId id) {
313 if (id == kInvalidControlFrameId) {
314 // Frame does not have a valid control frame ID, ignore it.
315 return false;
316 }
317 if (id >= least_unsent_) {
318 QUIC_BUG << "Try to ack unsent control frame";
319 session_->connection()->CloseConnection(
320 QUIC_INTERNAL_ERROR, "Try to ack unsent control frame",
321 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
322 return false;
323 }
324 if (id < least_unacked_ ||
325 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
326 kInvalidControlFrameId) {
327 // This frame has already been acked.
328 return false;
329 }
330
331 // Set control frame ID of acked frames to 0.
332 SetControlFrameId(kInvalidControlFrameId,
333 &control_frames_.at(id - least_unacked_));
334 // Remove acked control frames from pending retransmissions.
335 pending_retransmissions_.erase(id);
336 // Clean up control frames queue and increment least_unacked_.
337 while (!control_frames_.empty() &&
338 GetControlFrameId(control_frames_.front()) == kInvalidControlFrameId) {
339 DeleteFrame(&control_frames_.front());
340 control_frames_.pop_front();
341 ++least_unacked_;
342 }
343 return true;
344}
345
346bool QuicControlFrameManager::HasBufferedFrames() const {
347 return least_unsent_ < least_unacked_ + control_frames_.size();
348}
349
350} // namespace quic