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