blob: 22fa55635b6977d6657d2b84ec00d073fb915dd0 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2018 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/test_tools/simple_session_notifier.h"
6
7#include "net/third_party/quiche/src/quic/core/quic_utils.h"
bnc5de87052019-05-03 14:21:53 -07008#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
10#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
11
12namespace quic {
13
14namespace test {
15
16SimpleSessionNotifier::SimpleSessionNotifier(QuicConnection* connection)
17 : last_control_frame_id_(kInvalidControlFrameId),
18 least_unacked_(1),
19 least_unsent_(1),
20 connection_(connection) {}
21
22SimpleSessionNotifier::~SimpleSessionNotifier() {
23 while (!control_frames_.empty()) {
24 DeleteFrame(&control_frames_.front());
25 control_frames_.pop_front();
26 }
27}
28
29SimpleSessionNotifier::StreamState::StreamState()
30 : bytes_total(0),
31 bytes_sent(0),
32 fin_buffered(false),
33 fin_sent(false),
34 fin_outstanding(false),
35 fin_lost(false) {}
36
37SimpleSessionNotifier::StreamState::~StreamState() {}
38
39QuicConsumedData SimpleSessionNotifier::WriteOrBufferData(
40 QuicStreamId id,
41 QuicByteCount data_length,
42 StreamSendingState state) {
43 if (!QuicContainsKey(stream_map_, id)) {
44 stream_map_[id] = StreamState();
45 }
46 StreamState& stream_state = stream_map_.find(id)->second;
47 const bool had_buffered_data =
48 HasBufferedStreamData() || HasBufferedControlFrames();
QUICHE teama6ef0a62019-03-07 20:34:33 -050049 QuicStreamOffset offset = stream_state.bytes_sent;
50 QUIC_DVLOG(1) << "WriteOrBuffer stream_id: " << id << " [" << offset << ", "
51 << offset + data_length << "), fin: " << (state != NO_FIN);
52 stream_state.bytes_total += data_length;
53 stream_state.fin_buffered = state != NO_FIN;
54 if (had_buffered_data) {
55 QUIC_DLOG(WARNING) << "Connection is write blocked";
56 return {0, false};
57 }
58 const size_t length = stream_state.bytes_total - stream_state.bytes_sent;
59 connection_->SetTransmissionType(NOT_RETRANSMISSION);
60 QuicConsumedData consumed =
61 connection_->SendStreamData(id, length, stream_state.bytes_sent,
62 stream_state.fin_buffered ? FIN : NO_FIN);
63 QUIC_DVLOG(1) << "consumed: " << consumed;
64 OnStreamDataConsumed(id, stream_state.bytes_sent, consumed.bytes_consumed,
65 consumed.fin_consumed);
66 return consumed;
67}
68
69void SimpleSessionNotifier::OnStreamDataConsumed(QuicStreamId id,
70 QuicStreamOffset offset,
71 QuicByteCount data_length,
72 bool fin) {
73 StreamState& state = stream_map_.find(id)->second;
nharper46833c32019-05-15 21:33:05 -070074 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(), id) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 data_length > 0) {
76 crypto_bytes_transferred_[connection_->encryption_level()].Add(
77 offset, offset + data_length);
78 }
79 state.bytes_sent += data_length;
80 state.fin_sent = fin;
81 state.fin_outstanding = fin;
82}
83
84size_t SimpleSessionNotifier::WriteCryptoData(EncryptionLevel level,
85 QuicByteCount data_length,
86 QuicStreamOffset offset) {
87 crypto_state_[level].bytes_total += data_length;
88 size_t bytes_written =
89 connection_->SendCryptoData(level, data_length, offset);
90 crypto_state_[level].bytes_sent += bytes_written;
91 crypto_bytes_transferred_[level].Add(offset, offset + bytes_written);
92 return bytes_written;
93}
94
95void SimpleSessionNotifier::WriteOrBufferRstStream(
96 QuicStreamId id,
97 QuicRstStreamErrorCode error,
98 QuicStreamOffset bytes_written) {
99 QUIC_DVLOG(1) << "Writing RST_STREAM_FRAME";
100 const bool had_buffered_data =
101 HasBufferedStreamData() || HasBufferedControlFrames();
102 control_frames_.emplace_back((QuicFrame(new QuicRstStreamFrame(
103 ++last_control_frame_id_, id, error, bytes_written))));
104 if (error != QUIC_STREAM_NO_ERROR) {
105 // Delete stream to avoid retransmissions.
106 stream_map_.erase(id);
107 }
108 if (had_buffered_data) {
109 QUIC_DLOG(WARNING) << "Connection is write blocked";
110 return;
111 }
112 WriteBufferedControlFrames();
113}
114
zhongyifbb25772019-04-10 16:54:08 -0700115void SimpleSessionNotifier::WriteOrBufferPing() {
116 QUIC_DVLOG(1) << "Writing PING_FRAME";
117 const bool had_buffered_data =
118 HasBufferedStreamData() || HasBufferedControlFrames();
119 control_frames_.emplace_back(
120 (QuicFrame(QuicPingFrame(++last_control_frame_id_))));
121 if (had_buffered_data) {
122 QUIC_DLOG(WARNING) << "Connection is write blocked";
123 return;
124 }
125 WriteBufferedControlFrames();
126}
127
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128void SimpleSessionNotifier::NeuterUnencryptedData() {
nharper46833c32019-05-15 21:33:05 -0700129 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
fayang93c83942019-11-07 10:41:16 -0800130 for (const auto& interval : crypto_bytes_transferred_[ENCRYPTION_INITIAL]) {
131 QuicCryptoFrame crypto_frame(ENCRYPTION_INITIAL, interval.min(),
132 interval.max() - interval.min());
133 OnFrameAcked(QuicFrame(&crypto_frame), QuicTime::Delta::Zero(),
134 QuicTime::Zero());
135 }
nharper46833c32019-05-15 21:33:05 -0700136 return;
137 }
QUICHE team6987b4a2019-03-15 16:23:04 -0700138 for (const auto& interval : crypto_bytes_transferred_[ENCRYPTION_INITIAL]) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 QuicStreamFrame stream_frame(
140 QuicUtils::GetCryptoStreamId(connection_->transport_version()), false,
141 interval.min(), interval.max() - interval.min());
QUICHE team9467db02019-05-30 09:38:45 -0700142 OnFrameAcked(QuicFrame(stream_frame), QuicTime::Delta::Zero(),
143 QuicTime::Zero());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144 }
145}
146
147void SimpleSessionNotifier::OnCanWrite() {
148 if (!RetransmitLostCryptoData() || !RetransmitLostControlFrames() ||
149 !RetransmitLostStreamData()) {
150 return;
151 }
152 // Write buffered control frames.
153 if (!WriteBufferedControlFrames()) {
154 return;
155 }
156 // Write new data.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 for (const auto& pair : stream_map_) {
158 const auto& state = pair.second;
159 if (!StreamHasBufferedData(pair.first)) {
160 continue;
161 }
162
163 const size_t length = state.bytes_total - state.bytes_sent;
164 const bool can_bundle_fin =
165 state.fin_buffered && (state.bytes_sent + length == state.bytes_total);
166 connection_->SetTransmissionType(NOT_RETRANSMISSION);
167 QuicConsumedData consumed = connection_->SendStreamData(
168 pair.first, length, state.bytes_sent, can_bundle_fin ? FIN : NO_FIN);
169 QUIC_DVLOG(1) << "Tries to write stream_id: " << pair.first << " ["
170 << state.bytes_sent << ", " << state.bytes_sent + length
171 << "), fin: " << can_bundle_fin
172 << ", and consumed: " << consumed;
173 OnStreamDataConsumed(pair.first, state.bytes_sent, consumed.bytes_consumed,
174 consumed.fin_consumed);
175 if (length != consumed.bytes_consumed ||
176 (can_bundle_fin && !consumed.fin_consumed)) {
177 break;
178 }
179 }
180}
181
fayang0fcbf352019-08-30 11:15:58 -0700182void SimpleSessionNotifier::OnStreamReset(QuicStreamId id,
183 QuicRstStreamErrorCode error) {
184 if (error != QUIC_STREAM_NO_ERROR) {
185 // Delete stream to avoid retransmissions.
186 stream_map_.erase(id);
187 }
188}
189
QUICHE teama6ef0a62019-03-07 20:34:33 -0500190bool SimpleSessionNotifier::WillingToWrite() const {
191 QUIC_DVLOG(1) << "has_buffered_control_frames: " << HasBufferedControlFrames()
192 << " as_lost_control_frames: " << !lost_control_frames_.empty()
193 << " has_buffered_stream_data: " << HasBufferedStreamData()
194 << " has_lost_stream_data: " << HasLostStreamData();
195 return HasBufferedControlFrames() || !lost_control_frames_.empty() ||
196 HasBufferedStreamData() || HasLostStreamData();
197}
198
199QuicByteCount SimpleSessionNotifier::StreamBytesSent() const {
200 QuicByteCount bytes_sent = 0;
201 for (const auto& pair : stream_map_) {
202 const auto& state = pair.second;
203 bytes_sent += state.bytes_sent;
204 }
205 return bytes_sent;
206}
207
208QuicByteCount SimpleSessionNotifier::StreamBytesToSend() const {
209 QuicByteCount bytes_to_send = 0;
210 for (const auto& pair : stream_map_) {
211 const auto& state = pair.second;
212 bytes_to_send += (state.bytes_total - state.bytes_sent);
213 }
214 return bytes_to_send;
215}
216
217bool SimpleSessionNotifier::OnFrameAcked(const QuicFrame& frame,
QUICHE team9467db02019-05-30 09:38:45 -0700218 QuicTime::Delta /*ack_delay_time*/,
219 QuicTime /*receive_timestamp*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500220 QUIC_DVLOG(1) << "Acking " << frame;
221 if (frame.type == CRYPTO_FRAME) {
222 StreamState* state = &crypto_state_[frame.crypto_frame->level];
223 QuicStreamOffset offset = frame.crypto_frame->offset;
224 QuicByteCount data_length = frame.crypto_frame->data_length;
225 QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
226 newly_acked.Difference(state->bytes_acked);
227 if (newly_acked.Empty()) {
228 return false;
229 }
230 state->bytes_acked.Add(offset, offset + data_length);
231 state->pending_retransmissions.Difference(offset, offset + data_length);
232 return true;
233 }
234 if (frame.type != STREAM_FRAME) {
235 return OnControlFrameAcked(frame);
236 }
237 if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
238 return false;
239 }
240 auto* state = &stream_map_.find(frame.stream_frame.stream_id)->second;
241 QuicStreamOffset offset = frame.stream_frame.offset;
242 QuicByteCount data_length = frame.stream_frame.data_length;
243 QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
244 newly_acked.Difference(state->bytes_acked);
245 const bool fin_newly_acked = frame.stream_frame.fin && state->fin_outstanding;
246 if (newly_acked.Empty() && !fin_newly_acked) {
247 return false;
248 }
249 state->bytes_acked.Add(offset, offset + data_length);
250 if (fin_newly_acked) {
251 state->fin_outstanding = false;
252 state->fin_lost = false;
253 }
254 state->pending_retransmissions.Difference(offset, offset + data_length);
255 return true;
256}
257
258void SimpleSessionNotifier::OnFrameLost(const QuicFrame& frame) {
259 QUIC_DVLOG(1) << "Losting " << frame;
260 if (frame.type == CRYPTO_FRAME) {
261 StreamState* state = &crypto_state_[frame.crypto_frame->level];
262 QuicStreamOffset offset = frame.crypto_frame->offset;
263 QuicByteCount data_length = frame.crypto_frame->data_length;
264 QuicIntervalSet<QuicStreamOffset> bytes_lost(offset, offset + data_length);
265 bytes_lost.Difference(state->bytes_acked);
266 if (bytes_lost.Empty()) {
267 return;
268 }
269 for (const auto& lost : bytes_lost) {
270 state->pending_retransmissions.Add(lost.min(), lost.max());
271 }
272 return;
273 }
274 if (frame.type != STREAM_FRAME) {
275 OnControlFrameLost(frame);
276 return;
277 }
278 if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
279 return;
280 }
281 auto* state = &stream_map_.find(frame.stream_frame.stream_id)->second;
282 QuicStreamOffset offset = frame.stream_frame.offset;
283 QuicByteCount data_length = frame.stream_frame.data_length;
284 QuicIntervalSet<QuicStreamOffset> bytes_lost(offset, offset + data_length);
285 bytes_lost.Difference(state->bytes_acked);
286 const bool fin_lost = state->fin_outstanding && frame.stream_frame.fin;
287 if (bytes_lost.Empty() && !fin_lost) {
288 return;
289 }
290 for (const auto& lost : bytes_lost) {
291 state->pending_retransmissions.Add(lost.min(), lost.max());
292 }
293 state->fin_lost = fin_lost;
294}
295
296void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
297 TransmissionType type) {
fayanga4b37b22019-06-18 13:37:47 -0700298 QuicConnection::ScopedPacketFlusher retransmission_flusher(connection_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500299 connection_->SetTransmissionType(type);
300 for (const QuicFrame& frame : frames) {
301 if (frame.type == CRYPTO_FRAME) {
302 const StreamState& state = crypto_state_[frame.crypto_frame->level];
fayang18ff23b2020-01-28 09:19:00 -0800303 const EncryptionLevel current_encryption_level =
304 connection_->encryption_level();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305 QuicIntervalSet<QuicStreamOffset> retransmission(
306 frame.crypto_frame->offset,
307 frame.crypto_frame->offset + frame.crypto_frame->data_length);
308 retransmission.Difference(state.bytes_acked);
309 for (const auto& interval : retransmission) {
310 QuicStreamOffset offset = interval.min();
311 QuicByteCount length = interval.max() - interval.min();
fayang18ff23b2020-01-28 09:19:00 -0800312 connection_->SetDefaultEncryptionLevel(frame.crypto_frame->level);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 size_t consumed = connection_->SendCryptoData(frame.crypto_frame->level,
314 length, offset);
315 // CRYPTO frames should never be write blocked.
316 DCHECK_EQ(consumed, length);
317 }
fayang18ff23b2020-01-28 09:19:00 -0800318 connection_->SetDefaultEncryptionLevel(current_encryption_level);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500319 }
320 if (frame.type != STREAM_FRAME) {
321 if (GetControlFrameId(frame) == kInvalidControlFrameId) {
322 continue;
323 }
324 QuicFrame copy = CopyRetransmittableControlFrame(frame);
325 if (!connection_->SendControlFrame(copy)) {
326 // Connection is write blocked.
327 DeleteFrame(&copy);
328 return;
329 }
330 continue;
331 }
332 if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
333 continue;
334 }
335 const auto& state = stream_map_.find(frame.stream_frame.stream_id)->second;
336 QuicIntervalSet<QuicStreamOffset> retransmission(
337 frame.stream_frame.offset,
338 frame.stream_frame.offset + frame.stream_frame.data_length);
339 EncryptionLevel retransmission_encryption_level =
340 connection_->encryption_level();
341 EncryptionLevel current_encryption_level = connection_->encryption_level();
nharper46833c32019-05-15 21:33:05 -0700342 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
343 frame.stream_frame.stream_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500344 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
345 if (retransmission.Intersects(crypto_bytes_transferred_[i])) {
346 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
347 retransmission.Intersection(crypto_bytes_transferred_[i]);
348 break;
349 }
350 }
351 }
352 retransmission.Difference(state.bytes_acked);
353 bool retransmit_fin = frame.stream_frame.fin && state.fin_outstanding;
354 QuicConsumedData consumed(0, false);
355 for (const auto& interval : retransmission) {
356 QuicStreamOffset retransmission_offset = interval.min();
357 QuicByteCount retransmission_length = interval.max() - interval.min();
358 const bool can_bundle_fin =
359 retransmit_fin &&
360 (retransmission_offset + retransmission_length == state.bytes_sent);
nharper46833c32019-05-15 21:33:05 -0700361 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
362 frame.stream_frame.stream_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500363 // Set appropriate encryption level for crypto stream.
364 connection_->SetDefaultEncryptionLevel(retransmission_encryption_level);
365 }
366 consumed = connection_->SendStreamData(
367 frame.stream_frame.stream_id, retransmission_length,
368 retransmission_offset, can_bundle_fin ? FIN : NO_FIN);
369 QUIC_DVLOG(1) << "stream " << frame.stream_frame.stream_id
370 << " is forced to retransmit stream data ["
371 << retransmission_offset << ", "
372 << retransmission_offset + retransmission_length
373 << ") and fin: " << can_bundle_fin
374 << ", consumed: " << consumed;
375 if (can_bundle_fin) {
376 retransmit_fin = !consumed.fin_consumed;
377 }
nharper46833c32019-05-15 21:33:05 -0700378 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
379 frame.stream_frame.stream_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500380 // Restore encryption level.
381 connection_->SetDefaultEncryptionLevel(current_encryption_level);
382 }
383 if (consumed.bytes_consumed < retransmission_length ||
384 (can_bundle_fin && !consumed.fin_consumed)) {
385 // Connection is write blocked.
386 return;
387 }
388 }
389 if (retransmit_fin) {
390 QUIC_DVLOG(1) << "stream " << frame.stream_frame.stream_id
391 << " retransmits fin only frame.";
392 consumed = connection_->SendStreamData(frame.stream_frame.stream_id, 0,
393 state.bytes_sent, FIN);
394 }
395 }
396}
397
398bool SimpleSessionNotifier::IsFrameOutstanding(const QuicFrame& frame) const {
399 if (frame.type == CRYPTO_FRAME) {
400 QuicStreamOffset offset = frame.crypto_frame->offset;
401 QuicByteCount data_length = frame.crypto_frame->data_length;
402 bool ret = data_length > 0 &&
403 !crypto_state_[frame.crypto_frame->level].bytes_acked.Contains(
404 offset, offset + data_length);
405 return ret;
406 }
407 if (frame.type != STREAM_FRAME) {
408 return IsControlFrameOutstanding(frame);
409 }
410 if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
411 return false;
412 }
413 const auto& state = stream_map_.find(frame.stream_frame.stream_id)->second;
414 QuicStreamOffset offset = frame.stream_frame.offset;
415 QuicByteCount data_length = frame.stream_frame.data_length;
416 return (data_length > 0 &&
417 !state.bytes_acked.Contains(offset, offset + data_length)) ||
418 (frame.stream_frame.fin && state.fin_outstanding);
419}
420
421bool SimpleSessionNotifier::HasUnackedCryptoData() const {
QUICHE teamea740082019-03-11 17:58:43 -0700422 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500423 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
424 const StreamState& state = crypto_state_[i];
425 if (state.bytes_total > state.bytes_sent) {
426 return true;
427 }
428 QuicIntervalSet<QuicStreamOffset> bytes_to_ack(0, state.bytes_total);
429 bytes_to_ack.Difference(state.bytes_acked);
430 if (!bytes_to_ack.Empty()) {
431 return true;
432 }
433 }
434 return false;
435 }
436 if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
437 connection_->transport_version()))) {
438 return false;
439 }
440 const auto& state =
441 stream_map_
442 .find(QuicUtils::GetCryptoStreamId(connection_->transport_version()))
443 ->second;
444 if (state.bytes_total > state.bytes_sent) {
445 return true;
446 }
447 QuicIntervalSet<QuicStreamOffset> bytes_to_ack(0, state.bytes_total);
448 bytes_to_ack.Difference(state.bytes_acked);
449 return !bytes_to_ack.Empty();
450}
451
zhongyi1b2f7832019-06-14 13:31:34 -0700452bool SimpleSessionNotifier::HasUnackedStreamData() const {
453 for (auto it : stream_map_) {
454 if (StreamIsWaitingForAcks(it.first))
455 return true;
456 }
457 return false;
458}
459
QUICHE teama6ef0a62019-03-07 20:34:33 -0500460bool SimpleSessionNotifier::OnControlFrameAcked(const QuicFrame& frame) {
461 QuicControlFrameId id = GetControlFrameId(frame);
462 if (id == kInvalidControlFrameId) {
463 return false;
464 }
465 DCHECK(id < least_unacked_ + control_frames_.size());
466 if (id < least_unacked_ ||
467 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
468 kInvalidControlFrameId) {
469 return false;
470 }
471 SetControlFrameId(kInvalidControlFrameId,
472 &control_frames_.at(id - least_unacked_));
473 lost_control_frames_.erase(id);
474 while (!control_frames_.empty() &&
475 GetControlFrameId(control_frames_.front()) == kInvalidControlFrameId) {
476 DeleteFrame(&control_frames_.front());
477 control_frames_.pop_front();
478 ++least_unacked_;
479 }
480 return true;
481}
482
483void SimpleSessionNotifier::OnControlFrameLost(const QuicFrame& frame) {
484 QuicControlFrameId id = GetControlFrameId(frame);
485 if (id == kInvalidControlFrameId) {
486 return;
487 }
488 DCHECK(id < least_unacked_ + control_frames_.size());
489 if (id < least_unacked_ ||
490 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
491 kInvalidControlFrameId) {
492 return;
493 }
494 if (!QuicContainsKey(lost_control_frames_, id)) {
495 lost_control_frames_[id] = true;
496 }
497}
498
499bool SimpleSessionNotifier::IsControlFrameOutstanding(
500 const QuicFrame& frame) const {
501 QuicControlFrameId id = GetControlFrameId(frame);
502 if (id == kInvalidControlFrameId) {
503 return false;
504 }
505 return id < least_unacked_ + control_frames_.size() && id >= least_unacked_ &&
506 GetControlFrameId(control_frames_.at(id - least_unacked_)) !=
507 kInvalidControlFrameId;
508}
509
510bool SimpleSessionNotifier::RetransmitLostControlFrames() {
511 while (!lost_control_frames_.empty()) {
512 QuicFrame pending = control_frames_.at(lost_control_frames_.begin()->first -
513 least_unacked_);
514 QuicFrame copy = CopyRetransmittableControlFrame(pending);
515 connection_->SetTransmissionType(LOSS_RETRANSMISSION);
516 if (!connection_->SendControlFrame(copy)) {
517 // Connection is write blocked.
518 DeleteFrame(&copy);
519 break;
520 }
521 lost_control_frames_.pop_front();
522 }
523 return lost_control_frames_.empty();
524}
525
526bool SimpleSessionNotifier::RetransmitLostCryptoData() {
nharper46833c32019-05-15 21:33:05 -0700527 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
528 for (EncryptionLevel level :
529 {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT,
530 ENCRYPTION_FORWARD_SECURE}) {
531 auto& state = crypto_state_[level];
532 while (!state.pending_retransmissions.Empty()) {
533 connection_->SetTransmissionType(HANDSHAKE_RETRANSMISSION);
534 EncryptionLevel current_encryption_level =
535 connection_->encryption_level();
536 connection_->SetDefaultEncryptionLevel(level);
537 QuicIntervalSet<QuicStreamOffset> retransmission(
538 state.pending_retransmissions.begin()->min(),
539 state.pending_retransmissions.begin()->max());
540 retransmission.Intersection(crypto_bytes_transferred_[level]);
541 QuicStreamOffset retransmission_offset = retransmission.begin()->min();
542 QuicByteCount retransmission_length =
543 retransmission.begin()->max() - retransmission.begin()->min();
544 size_t bytes_consumed = connection_->SendCryptoData(
545 level, retransmission_length, retransmission_offset);
546 // Restore encryption level.
547 connection_->SetDefaultEncryptionLevel(current_encryption_level);
548 state.pending_retransmissions.Difference(
549 retransmission_offset, retransmission_offset + bytes_consumed);
550 if (bytes_consumed < retransmission_length) {
551 return false;
552 }
553 }
554 }
555 return true;
556 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500557 if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
558 connection_->transport_version()))) {
559 return true;
560 }
561 auto& state =
562 stream_map_
563 .find(QuicUtils::GetCryptoStreamId(connection_->transport_version()))
564 ->second;
565 while (!state.pending_retransmissions.Empty()) {
566 connection_->SetTransmissionType(HANDSHAKE_RETRANSMISSION);
567 QuicIntervalSet<QuicStreamOffset> retransmission(
568 state.pending_retransmissions.begin()->min(),
569 state.pending_retransmissions.begin()->max());
QUICHE team6987b4a2019-03-15 16:23:04 -0700570 EncryptionLevel retransmission_encryption_level = ENCRYPTION_INITIAL;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500571 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
572 if (retransmission.Intersects(crypto_bytes_transferred_[i])) {
573 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
574 retransmission.Intersection(crypto_bytes_transferred_[i]);
575 break;
576 }
577 }
578 QuicStreamOffset retransmission_offset = retransmission.begin()->min();
579 QuicByteCount retransmission_length =
580 retransmission.begin()->max() - retransmission.begin()->min();
581 EncryptionLevel current_encryption_level = connection_->encryption_level();
582 // Set appropriate encryption level.
583 connection_->SetDefaultEncryptionLevel(retransmission_encryption_level);
584 QuicConsumedData consumed = connection_->SendStreamData(
585 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
586 retransmission_length, retransmission_offset, NO_FIN);
587 // Restore encryption level.
588 connection_->SetDefaultEncryptionLevel(current_encryption_level);
589 state.pending_retransmissions.Difference(
590 retransmission_offset, retransmission_offset + consumed.bytes_consumed);
591 if (consumed.bytes_consumed < retransmission_length) {
592 break;
593 }
594 }
595 return state.pending_retransmissions.Empty();
596}
597
598bool SimpleSessionNotifier::RetransmitLostStreamData() {
599 for (auto& pair : stream_map_) {
600 StreamState& state = pair.second;
601 QuicConsumedData consumed(0, false);
602 while (!state.pending_retransmissions.Empty() || state.fin_lost) {
603 connection_->SetTransmissionType(LOSS_RETRANSMISSION);
604 if (state.pending_retransmissions.Empty()) {
605 QUIC_DVLOG(1) << "stream " << pair.first
606 << " retransmits fin only frame.";
607 consumed =
608 connection_->SendStreamData(pair.first, 0, state.bytes_sent, FIN);
609 state.fin_lost = !consumed.fin_consumed;
610 if (state.fin_lost) {
bnc5de87052019-05-03 14:21:53 -0700611 QUIC_DLOG(INFO) << "Connection is write blocked";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500612 return false;
613 }
614 } else {
615 QuicStreamOffset offset = state.pending_retransmissions.begin()->min();
616 QuicByteCount length = state.pending_retransmissions.begin()->max() -
617 state.pending_retransmissions.begin()->min();
618 const bool can_bundle_fin =
619 state.fin_lost && (offset + length == state.bytes_sent);
620 consumed = connection_->SendStreamData(pair.first, length, offset,
621 can_bundle_fin ? FIN : NO_FIN);
622 QUIC_DVLOG(1) << "stream " << pair.first
623 << " tries to retransmit stream data [" << offset << ", "
624 << offset + length << ") and fin: " << can_bundle_fin
625 << ", consumed: " << consumed;
626 state.pending_retransmissions.Difference(
627 offset, offset + consumed.bytes_consumed);
628 if (consumed.fin_consumed) {
629 state.fin_lost = false;
630 }
631 if (length > consumed.bytes_consumed ||
632 (can_bundle_fin && !consumed.fin_consumed)) {
bnc5de87052019-05-03 14:21:53 -0700633 QUIC_DVLOG(1) << "Connection is write blocked";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500634 break;
635 }
636 }
637 }
638 }
639 return !HasLostStreamData();
640}
641
642bool SimpleSessionNotifier::WriteBufferedControlFrames() {
643 while (HasBufferedControlFrames()) {
644 QuicFrame frame_to_send =
645 control_frames_.at(least_unsent_ - least_unacked_);
646 QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
647 connection_->SetTransmissionType(NOT_RETRANSMISSION);
648 if (!connection_->SendControlFrame(copy)) {
649 // Connection is write blocked.
650 DeleteFrame(&copy);
651 break;
652 }
653 ++least_unsent_;
654 }
655 return !HasBufferedControlFrames();
656}
657
658bool SimpleSessionNotifier::HasBufferedControlFrames() const {
659 return least_unsent_ < least_unacked_ + control_frames_.size();
660}
661
662bool SimpleSessionNotifier::HasBufferedStreamData() const {
663 for (const auto& pair : stream_map_) {
664 const auto& state = pair.second;
665 if (state.bytes_total > state.bytes_sent ||
666 (state.fin_buffered && !state.fin_sent)) {
667 return true;
668 }
669 }
670 return false;
671}
672
673bool SimpleSessionNotifier::StreamIsWaitingForAcks(QuicStreamId id) const {
674 if (!QuicContainsKey(stream_map_, id)) {
675 return false;
676 }
677 const StreamState& state = stream_map_.find(id)->second;
678 return !state.bytes_acked.Contains(0, state.bytes_sent) ||
679 state.fin_outstanding;
680}
681
682bool SimpleSessionNotifier::StreamHasBufferedData(QuicStreamId id) const {
683 if (!QuicContainsKey(stream_map_, id)) {
684 return false;
685 }
686 const StreamState& state = stream_map_.find(id)->second;
687 return state.bytes_total > state.bytes_sent ||
688 (state.fin_buffered && !state.fin_sent);
689}
690
691bool SimpleSessionNotifier::HasLostStreamData() const {
692 for (const auto& pair : stream_map_) {
693 const auto& state = pair.second;
694 if (!state.pending_retransmissions.Empty() || state.fin_lost) {
695 return true;
696 }
697 }
698 return false;
699}
700
701} // namespace test
702
703} // namespace quic