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