blob: 9e67c899f51b1e12780a75f51f44cf4c9e6a36f5 [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];
303 QuicIntervalSet<QuicStreamOffset> retransmission(
304 frame.crypto_frame->offset,
305 frame.crypto_frame->offset + frame.crypto_frame->data_length);
306 retransmission.Difference(state.bytes_acked);
307 for (const auto& interval : retransmission) {
308 QuicStreamOffset offset = interval.min();
309 QuicByteCount length = interval.max() - interval.min();
310 size_t consumed = connection_->SendCryptoData(frame.crypto_frame->level,
311 length, offset);
312 // CRYPTO frames should never be write blocked.
313 DCHECK_EQ(consumed, length);
314 }
315 }
316 if (frame.type != STREAM_FRAME) {
317 if (GetControlFrameId(frame) == kInvalidControlFrameId) {
318 continue;
319 }
320 QuicFrame copy = CopyRetransmittableControlFrame(frame);
321 if (!connection_->SendControlFrame(copy)) {
322 // Connection is write blocked.
323 DeleteFrame(&copy);
324 return;
325 }
326 continue;
327 }
328 if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
329 continue;
330 }
331 const auto& state = stream_map_.find(frame.stream_frame.stream_id)->second;
332 QuicIntervalSet<QuicStreamOffset> retransmission(
333 frame.stream_frame.offset,
334 frame.stream_frame.offset + frame.stream_frame.data_length);
335 EncryptionLevel retransmission_encryption_level =
336 connection_->encryption_level();
337 EncryptionLevel current_encryption_level = connection_->encryption_level();
nharper46833c32019-05-15 21:33:05 -0700338 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
339 frame.stream_frame.stream_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500340 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
341 if (retransmission.Intersects(crypto_bytes_transferred_[i])) {
342 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
343 retransmission.Intersection(crypto_bytes_transferred_[i]);
344 break;
345 }
346 }
347 }
348 retransmission.Difference(state.bytes_acked);
349 bool retransmit_fin = frame.stream_frame.fin && state.fin_outstanding;
350 QuicConsumedData consumed(0, false);
351 for (const auto& interval : retransmission) {
352 QuicStreamOffset retransmission_offset = interval.min();
353 QuicByteCount retransmission_length = interval.max() - interval.min();
354 const bool can_bundle_fin =
355 retransmit_fin &&
356 (retransmission_offset + retransmission_length == state.bytes_sent);
nharper46833c32019-05-15 21:33:05 -0700357 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
358 frame.stream_frame.stream_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500359 // Set appropriate encryption level for crypto stream.
360 connection_->SetDefaultEncryptionLevel(retransmission_encryption_level);
361 }
362 consumed = connection_->SendStreamData(
363 frame.stream_frame.stream_id, retransmission_length,
364 retransmission_offset, can_bundle_fin ? FIN : NO_FIN);
365 QUIC_DVLOG(1) << "stream " << frame.stream_frame.stream_id
366 << " is forced to retransmit stream data ["
367 << retransmission_offset << ", "
368 << retransmission_offset + retransmission_length
369 << ") and fin: " << can_bundle_fin
370 << ", consumed: " << consumed;
371 if (can_bundle_fin) {
372 retransmit_fin = !consumed.fin_consumed;
373 }
nharper46833c32019-05-15 21:33:05 -0700374 if (QuicUtils::IsCryptoStreamId(connection_->transport_version(),
375 frame.stream_frame.stream_id)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500376 // Restore encryption level.
377 connection_->SetDefaultEncryptionLevel(current_encryption_level);
378 }
379 if (consumed.bytes_consumed < retransmission_length ||
380 (can_bundle_fin && !consumed.fin_consumed)) {
381 // Connection is write blocked.
382 return;
383 }
384 }
385 if (retransmit_fin) {
386 QUIC_DVLOG(1) << "stream " << frame.stream_frame.stream_id
387 << " retransmits fin only frame.";
388 consumed = connection_->SendStreamData(frame.stream_frame.stream_id, 0,
389 state.bytes_sent, FIN);
390 }
391 }
392}
393
394bool SimpleSessionNotifier::IsFrameOutstanding(const QuicFrame& frame) const {
395 if (frame.type == CRYPTO_FRAME) {
396 QuicStreamOffset offset = frame.crypto_frame->offset;
397 QuicByteCount data_length = frame.crypto_frame->data_length;
398 bool ret = data_length > 0 &&
399 !crypto_state_[frame.crypto_frame->level].bytes_acked.Contains(
400 offset, offset + data_length);
401 return ret;
402 }
403 if (frame.type != STREAM_FRAME) {
404 return IsControlFrameOutstanding(frame);
405 }
406 if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
407 return false;
408 }
409 const auto& state = stream_map_.find(frame.stream_frame.stream_id)->second;
410 QuicStreamOffset offset = frame.stream_frame.offset;
411 QuicByteCount data_length = frame.stream_frame.data_length;
412 return (data_length > 0 &&
413 !state.bytes_acked.Contains(offset, offset + data_length)) ||
414 (frame.stream_frame.fin && state.fin_outstanding);
415}
416
417bool SimpleSessionNotifier::HasUnackedCryptoData() const {
QUICHE teamea740082019-03-11 17:58:43 -0700418 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
420 const StreamState& state = crypto_state_[i];
421 if (state.bytes_total > state.bytes_sent) {
422 return true;
423 }
424 QuicIntervalSet<QuicStreamOffset> bytes_to_ack(0, state.bytes_total);
425 bytes_to_ack.Difference(state.bytes_acked);
426 if (!bytes_to_ack.Empty()) {
427 return true;
428 }
429 }
430 return false;
431 }
432 if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
433 connection_->transport_version()))) {
434 return false;
435 }
436 const auto& state =
437 stream_map_
438 .find(QuicUtils::GetCryptoStreamId(connection_->transport_version()))
439 ->second;
440 if (state.bytes_total > state.bytes_sent) {
441 return true;
442 }
443 QuicIntervalSet<QuicStreamOffset> bytes_to_ack(0, state.bytes_total);
444 bytes_to_ack.Difference(state.bytes_acked);
445 return !bytes_to_ack.Empty();
446}
447
zhongyi1b2f7832019-06-14 13:31:34 -0700448bool SimpleSessionNotifier::HasUnackedStreamData() const {
449 for (auto it : stream_map_) {
450 if (StreamIsWaitingForAcks(it.first))
451 return true;
452 }
453 return false;
454}
455
QUICHE teama6ef0a62019-03-07 20:34:33 -0500456bool SimpleSessionNotifier::OnControlFrameAcked(const QuicFrame& frame) {
457 QuicControlFrameId id = GetControlFrameId(frame);
458 if (id == kInvalidControlFrameId) {
459 return false;
460 }
461 DCHECK(id < least_unacked_ + control_frames_.size());
462 if (id < least_unacked_ ||
463 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
464 kInvalidControlFrameId) {
465 return false;
466 }
467 SetControlFrameId(kInvalidControlFrameId,
468 &control_frames_.at(id - least_unacked_));
469 lost_control_frames_.erase(id);
470 while (!control_frames_.empty() &&
471 GetControlFrameId(control_frames_.front()) == kInvalidControlFrameId) {
472 DeleteFrame(&control_frames_.front());
473 control_frames_.pop_front();
474 ++least_unacked_;
475 }
476 return true;
477}
478
479void SimpleSessionNotifier::OnControlFrameLost(const QuicFrame& frame) {
480 QuicControlFrameId id = GetControlFrameId(frame);
481 if (id == kInvalidControlFrameId) {
482 return;
483 }
484 DCHECK(id < least_unacked_ + control_frames_.size());
485 if (id < least_unacked_ ||
486 GetControlFrameId(control_frames_.at(id - least_unacked_)) ==
487 kInvalidControlFrameId) {
488 return;
489 }
490 if (!QuicContainsKey(lost_control_frames_, id)) {
491 lost_control_frames_[id] = true;
492 }
493}
494
495bool SimpleSessionNotifier::IsControlFrameOutstanding(
496 const QuicFrame& frame) const {
497 QuicControlFrameId id = GetControlFrameId(frame);
498 if (id == kInvalidControlFrameId) {
499 return false;
500 }
501 return id < least_unacked_ + control_frames_.size() && id >= least_unacked_ &&
502 GetControlFrameId(control_frames_.at(id - least_unacked_)) !=
503 kInvalidControlFrameId;
504}
505
506bool SimpleSessionNotifier::RetransmitLostControlFrames() {
507 while (!lost_control_frames_.empty()) {
508 QuicFrame pending = control_frames_.at(lost_control_frames_.begin()->first -
509 least_unacked_);
510 QuicFrame copy = CopyRetransmittableControlFrame(pending);
511 connection_->SetTransmissionType(LOSS_RETRANSMISSION);
512 if (!connection_->SendControlFrame(copy)) {
513 // Connection is write blocked.
514 DeleteFrame(&copy);
515 break;
516 }
517 lost_control_frames_.pop_front();
518 }
519 return lost_control_frames_.empty();
520}
521
522bool SimpleSessionNotifier::RetransmitLostCryptoData() {
nharper46833c32019-05-15 21:33:05 -0700523 if (QuicVersionUsesCryptoFrames(connection_->transport_version())) {
524 for (EncryptionLevel level :
525 {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT,
526 ENCRYPTION_FORWARD_SECURE}) {
527 auto& state = crypto_state_[level];
528 while (!state.pending_retransmissions.Empty()) {
529 connection_->SetTransmissionType(HANDSHAKE_RETRANSMISSION);
530 EncryptionLevel current_encryption_level =
531 connection_->encryption_level();
532 connection_->SetDefaultEncryptionLevel(level);
533 QuicIntervalSet<QuicStreamOffset> retransmission(
534 state.pending_retransmissions.begin()->min(),
535 state.pending_retransmissions.begin()->max());
536 retransmission.Intersection(crypto_bytes_transferred_[level]);
537 QuicStreamOffset retransmission_offset = retransmission.begin()->min();
538 QuicByteCount retransmission_length =
539 retransmission.begin()->max() - retransmission.begin()->min();
540 size_t bytes_consumed = connection_->SendCryptoData(
541 level, retransmission_length, retransmission_offset);
542 // Restore encryption level.
543 connection_->SetDefaultEncryptionLevel(current_encryption_level);
544 state.pending_retransmissions.Difference(
545 retransmission_offset, retransmission_offset + bytes_consumed);
546 if (bytes_consumed < retransmission_length) {
547 return false;
548 }
549 }
550 }
551 return true;
552 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500553 if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
554 connection_->transport_version()))) {
555 return true;
556 }
557 auto& state =
558 stream_map_
559 .find(QuicUtils::GetCryptoStreamId(connection_->transport_version()))
560 ->second;
561 while (!state.pending_retransmissions.Empty()) {
562 connection_->SetTransmissionType(HANDSHAKE_RETRANSMISSION);
563 QuicIntervalSet<QuicStreamOffset> retransmission(
564 state.pending_retransmissions.begin()->min(),
565 state.pending_retransmissions.begin()->max());
QUICHE team6987b4a2019-03-15 16:23:04 -0700566 EncryptionLevel retransmission_encryption_level = ENCRYPTION_INITIAL;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500567 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
568 if (retransmission.Intersects(crypto_bytes_transferred_[i])) {
569 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
570 retransmission.Intersection(crypto_bytes_transferred_[i]);
571 break;
572 }
573 }
574 QuicStreamOffset retransmission_offset = retransmission.begin()->min();
575 QuicByteCount retransmission_length =
576 retransmission.begin()->max() - retransmission.begin()->min();
577 EncryptionLevel current_encryption_level = connection_->encryption_level();
578 // Set appropriate encryption level.
579 connection_->SetDefaultEncryptionLevel(retransmission_encryption_level);
580 QuicConsumedData consumed = connection_->SendStreamData(
581 QuicUtils::GetCryptoStreamId(connection_->transport_version()),
582 retransmission_length, retransmission_offset, NO_FIN);
583 // Restore encryption level.
584 connection_->SetDefaultEncryptionLevel(current_encryption_level);
585 state.pending_retransmissions.Difference(
586 retransmission_offset, retransmission_offset + consumed.bytes_consumed);
587 if (consumed.bytes_consumed < retransmission_length) {
588 break;
589 }
590 }
591 return state.pending_retransmissions.Empty();
592}
593
594bool SimpleSessionNotifier::RetransmitLostStreamData() {
595 for (auto& pair : stream_map_) {
596 StreamState& state = pair.second;
597 QuicConsumedData consumed(0, false);
598 while (!state.pending_retransmissions.Empty() || state.fin_lost) {
599 connection_->SetTransmissionType(LOSS_RETRANSMISSION);
600 if (state.pending_retransmissions.Empty()) {
601 QUIC_DVLOG(1) << "stream " << pair.first
602 << " retransmits fin only frame.";
603 consumed =
604 connection_->SendStreamData(pair.first, 0, state.bytes_sent, FIN);
605 state.fin_lost = !consumed.fin_consumed;
606 if (state.fin_lost) {
bnc5de87052019-05-03 14:21:53 -0700607 QUIC_DLOG(INFO) << "Connection is write blocked";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500608 return false;
609 }
610 } else {
611 QuicStreamOffset offset = state.pending_retransmissions.begin()->min();
612 QuicByteCount length = state.pending_retransmissions.begin()->max() -
613 state.pending_retransmissions.begin()->min();
614 const bool can_bundle_fin =
615 state.fin_lost && (offset + length == state.bytes_sent);
616 consumed = connection_->SendStreamData(pair.first, length, offset,
617 can_bundle_fin ? FIN : NO_FIN);
618 QUIC_DVLOG(1) << "stream " << pair.first
619 << " tries to retransmit stream data [" << offset << ", "
620 << offset + length << ") and fin: " << can_bundle_fin
621 << ", consumed: " << consumed;
622 state.pending_retransmissions.Difference(
623 offset, offset + consumed.bytes_consumed);
624 if (consumed.fin_consumed) {
625 state.fin_lost = false;
626 }
627 if (length > consumed.bytes_consumed ||
628 (can_bundle_fin && !consumed.fin_consumed)) {
bnc5de87052019-05-03 14:21:53 -0700629 QUIC_DVLOG(1) << "Connection is write blocked";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500630 break;
631 }
632 }
633 }
634 }
635 return !HasLostStreamData();
636}
637
638bool SimpleSessionNotifier::WriteBufferedControlFrames() {
639 while (HasBufferedControlFrames()) {
640 QuicFrame frame_to_send =
641 control_frames_.at(least_unsent_ - least_unacked_);
642 QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
643 connection_->SetTransmissionType(NOT_RETRANSMISSION);
644 if (!connection_->SendControlFrame(copy)) {
645 // Connection is write blocked.
646 DeleteFrame(&copy);
647 break;
648 }
649 ++least_unsent_;
650 }
651 return !HasBufferedControlFrames();
652}
653
654bool SimpleSessionNotifier::HasBufferedControlFrames() const {
655 return least_unsent_ < least_unacked_ + control_frames_.size();
656}
657
658bool SimpleSessionNotifier::HasBufferedStreamData() const {
659 for (const auto& pair : stream_map_) {
660 const auto& state = pair.second;
661 if (state.bytes_total > state.bytes_sent ||
662 (state.fin_buffered && !state.fin_sent)) {
663 return true;
664 }
665 }
666 return false;
667}
668
669bool SimpleSessionNotifier::StreamIsWaitingForAcks(QuicStreamId id) const {
670 if (!QuicContainsKey(stream_map_, id)) {
671 return false;
672 }
673 const StreamState& state = stream_map_.find(id)->second;
674 return !state.bytes_acked.Contains(0, state.bytes_sent) ||
675 state.fin_outstanding;
676}
677
678bool SimpleSessionNotifier::StreamHasBufferedData(QuicStreamId id) const {
679 if (!QuicContainsKey(stream_map_, id)) {
680 return false;
681 }
682 const StreamState& state = stream_map_.find(id)->second;
683 return state.bytes_total > state.bytes_sent ||
684 (state.fin_buffered && !state.fin_sent);
685}
686
687bool SimpleSessionNotifier::HasLostStreamData() const {
688 for (const auto& pair : stream_map_) {
689 const auto& state = pair.second;
690 if (!state.pending_retransmissions.Empty() || state.fin_lost) {
691 return true;
692 }
693 }
694 return false;
695}
696
697} // namespace test
698
699} // namespace quic