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