1 // Copyright 2014 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 "quiche/quic/core/quic_unacked_packet_map.h"
6
7 #include <cstddef>
8 #include <limits>
9 #include <type_traits>
10
11 #include "absl/container/inlined_vector.h"
12 #include "quiche/quic/core/quic_connection_stats.h"
13 #include "quiche/quic/core/quic_packet_number.h"
14 #include "quiche/quic/core/quic_types.h"
15 #include "quiche/quic/core/quic_utils.h"
16 #include "quiche/quic/platform/api/quic_bug_tracker.h"
17 #include "quiche/quic/platform/api/quic_flag_utils.h"
18
19 namespace quic {
20
21 namespace {
WillStreamFrameLengthSumWrapAround(QuicPacketLength lhs,QuicPacketLength rhs)22 bool WillStreamFrameLengthSumWrapAround(QuicPacketLength lhs,
23 QuicPacketLength rhs) {
24 static_assert(
25 std::is_unsigned<QuicPacketLength>::value,
26 "This function assumes QuicPacketLength is an unsigned integer type.");
27 return std::numeric_limits<QuicPacketLength>::max() - lhs < rhs;
28 }
29
30 enum QuicFrameTypeBitfield : uint32_t {
31 kInvalidFrameBitfield = 0,
32 kPaddingFrameBitfield = 1,
33 kRstStreamFrameBitfield = 1 << 1,
34 kConnectionCloseFrameBitfield = 1 << 2,
35 kGoawayFrameBitfield = 1 << 3,
36 kWindowUpdateFrameBitfield = 1 << 4,
37 kBlockedFrameBitfield = 1 << 5,
38 kStopWaitingFrameBitfield = 1 << 6,
39 kPingFrameBitfield = 1 << 7,
40 kCryptoFrameBitfield = 1 << 8,
41 kHandshakeDoneFrameBitfield = 1 << 9,
42 kStreamFrameBitfield = 1 << 10,
43 kAckFrameBitfield = 1 << 11,
44 kMtuDiscoveryFrameBitfield = 1 << 12,
45 kNewConnectionIdFrameBitfield = 1 << 13,
46 kMaxStreamsFrameBitfield = 1 << 14,
47 kStreamsBlockedFrameBitfield = 1 << 15,
48 kPathResponseFrameBitfield = 1 << 16,
49 kPathChallengeFrameBitfield = 1 << 17,
50 kStopSendingFrameBitfield = 1 << 18,
51 kMessageFrameBitfield = 1 << 19,
52 kNewTokenFrameBitfield = 1 << 20,
53 kRetireConnectionIdFrameBitfield = 1 << 21,
54 kAckFrequencyFrameBitfield = 1 << 22,
55 kResetStreamAtFrameBitfield = 1 << 23,
56 };
57
GetFrameTypeBitfield(QuicFrameType type)58 QuicFrameTypeBitfield GetFrameTypeBitfield(QuicFrameType type) {
59 switch (type) {
60 case PADDING_FRAME:
61 return kPaddingFrameBitfield;
62 case RST_STREAM_FRAME:
63 return kRstStreamFrameBitfield;
64 case CONNECTION_CLOSE_FRAME:
65 return kConnectionCloseFrameBitfield;
66 case GOAWAY_FRAME:
67 return kGoawayFrameBitfield;
68 case WINDOW_UPDATE_FRAME:
69 return kWindowUpdateFrameBitfield;
70 case BLOCKED_FRAME:
71 return kBlockedFrameBitfield;
72 case STOP_WAITING_FRAME:
73 return kStopWaitingFrameBitfield;
74 case PING_FRAME:
75 return kPingFrameBitfield;
76 case CRYPTO_FRAME:
77 return kCryptoFrameBitfield;
78 case HANDSHAKE_DONE_FRAME:
79 return kHandshakeDoneFrameBitfield;
80 case STREAM_FRAME:
81 return kStreamFrameBitfield;
82 case ACK_FRAME:
83 return kAckFrameBitfield;
84 case MTU_DISCOVERY_FRAME:
85 return kMtuDiscoveryFrameBitfield;
86 case NEW_CONNECTION_ID_FRAME:
87 return kNewConnectionIdFrameBitfield;
88 case MAX_STREAMS_FRAME:
89 return kMaxStreamsFrameBitfield;
90 case STREAMS_BLOCKED_FRAME:
91 return kStreamsBlockedFrameBitfield;
92 case PATH_RESPONSE_FRAME:
93 return kPathResponseFrameBitfield;
94 case PATH_CHALLENGE_FRAME:
95 return kPathChallengeFrameBitfield;
96 case STOP_SENDING_FRAME:
97 return kStopSendingFrameBitfield;
98 case MESSAGE_FRAME:
99 return kMessageFrameBitfield;
100 case NEW_TOKEN_FRAME:
101 return kNewTokenFrameBitfield;
102 case RETIRE_CONNECTION_ID_FRAME:
103 return kRetireConnectionIdFrameBitfield;
104 case ACK_FREQUENCY_FRAME:
105 return kAckFrequencyFrameBitfield;
106 case RESET_STREAM_AT_FRAME:
107 return kResetStreamAtFrameBitfield;
108 case NUM_FRAME_TYPES:
109 QUIC_BUG(quic_bug_10518_1) << "Unexpected frame type";
110 return kInvalidFrameBitfield;
111 }
112 QUIC_BUG(quic_bug_10518_2) << "Unexpected frame type";
113 return kInvalidFrameBitfield;
114 }
115
116 } // namespace
117
QuicUnackedPacketMap(Perspective perspective)118 QuicUnackedPacketMap::QuicUnackedPacketMap(Perspective perspective)
119 : perspective_(perspective),
120 least_unacked_(FirstSendingPacketNumber()),
121 bytes_in_flight_(0),
122 bytes_in_flight_per_packet_number_space_{0, 0, 0},
123 packets_in_flight_(0),
124 last_inflight_packet_sent_time_(QuicTime::Zero()),
125 last_inflight_packets_sent_time_{
126 {QuicTime::Zero()}, {QuicTime::Zero()}, {QuicTime::Zero()}},
127 last_crypto_packet_sent_time_(QuicTime::Zero()),
128 session_notifier_(nullptr),
129 supports_multiple_packet_number_spaces_(false) {}
130
~QuicUnackedPacketMap()131 QuicUnackedPacketMap::~QuicUnackedPacketMap() {
132 for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
133 DeleteFrames(&(transmission_info.retransmittable_frames));
134 }
135 }
136
AddSentPacket(SerializedPacket * mutable_packet,TransmissionType transmission_type,QuicTime sent_time,bool set_in_flight,bool measure_rtt,QuicEcnCodepoint ecn_codepoint)137 void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* mutable_packet,
138 TransmissionType transmission_type,
139 QuicTime sent_time, bool set_in_flight,
140 bool measure_rtt,
141 QuicEcnCodepoint ecn_codepoint) {
142 const SerializedPacket& packet = *mutable_packet;
143 QuicPacketNumber packet_number = packet.packet_number;
144 QuicPacketLength bytes_sent = packet.encrypted_length;
145 QUIC_BUG_IF(quic_bug_12645_1, largest_sent_packet_.IsInitialized() &&
146 largest_sent_packet_ >= packet_number)
147 << "largest_sent_packet_: " << largest_sent_packet_
148 << ", packet_number: " << packet_number;
149 QUICHE_DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
150 while (least_unacked_ + unacked_packets_.size() < packet_number) {
151 unacked_packets_.push_back(QuicTransmissionInfo());
152 unacked_packets_.back().state = NEVER_SENT;
153 }
154
155 const bool has_crypto_handshake = packet.has_crypto_handshake == IS_HANDSHAKE;
156 QuicTransmissionInfo info(packet.encryption_level, transmission_type,
157 sent_time, bytes_sent, has_crypto_handshake,
158 packet.has_ack_frequency, ecn_codepoint);
159 info.largest_acked = packet.largest_acked;
160 largest_sent_largest_acked_.UpdateMax(packet.largest_acked);
161
162 if (!measure_rtt) {
163 QUIC_BUG_IF(quic_bug_12645_2, set_in_flight)
164 << "Packet " << mutable_packet->packet_number << ", transmission type "
165 << TransmissionTypeToString(mutable_packet->transmission_type)
166 << ", retransmittable frames: "
167 << QuicFramesToString(mutable_packet->retransmittable_frames)
168 << ", nonretransmittable_frames: "
169 << QuicFramesToString(mutable_packet->nonretransmittable_frames);
170 info.state = NOT_CONTRIBUTING_RTT;
171 }
172
173 largest_sent_packet_ = packet_number;
174 if (set_in_flight) {
175 const PacketNumberSpace packet_number_space =
176 GetPacketNumberSpace(info.encryption_level);
177 bytes_in_flight_ += bytes_sent;
178 bytes_in_flight_per_packet_number_space_[packet_number_space] += bytes_sent;
179 ++packets_in_flight_;
180 info.in_flight = true;
181 largest_sent_retransmittable_packets_[packet_number_space] = packet_number;
182 last_inflight_packet_sent_time_ = sent_time;
183 last_inflight_packets_sent_time_[packet_number_space] = sent_time;
184 }
185 unacked_packets_.push_back(std::move(info));
186 // Swap the retransmittable frames to avoid allocations.
187 // TODO(ianswett): Could use emplace_back when Chromium can.
188 if (has_crypto_handshake) {
189 last_crypto_packet_sent_time_ = sent_time;
190 }
191
192 mutable_packet->retransmittable_frames.swap(
193 unacked_packets_.back().retransmittable_frames);
194 }
195
RemoveObsoletePackets()196 void QuicUnackedPacketMap::RemoveObsoletePackets() {
197 while (!unacked_packets_.empty()) {
198 if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) {
199 break;
200 }
201 DeleteFrames(&unacked_packets_.front().retransmittable_frames);
202 unacked_packets_.pop_front();
203 ++least_unacked_;
204 }
205 }
206
HasRetransmittableFrames(QuicPacketNumber packet_number) const207 bool QuicUnackedPacketMap::HasRetransmittableFrames(
208 QuicPacketNumber packet_number) const {
209 QUICHE_DCHECK_GE(packet_number, least_unacked_);
210 QUICHE_DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
211 return HasRetransmittableFrames(
212 unacked_packets_[packet_number - least_unacked_]);
213 }
214
HasRetransmittableFrames(const QuicTransmissionInfo & info) const215 bool QuicUnackedPacketMap::HasRetransmittableFrames(
216 const QuicTransmissionInfo& info) const {
217 if (!QuicUtils::IsAckable(info.state)) {
218 return false;
219 }
220
221 for (const auto& frame : info.retransmittable_frames) {
222 if (session_notifier_->IsFrameOutstanding(frame)) {
223 return true;
224 }
225 }
226 return false;
227 }
228
RemoveRetransmittability(QuicTransmissionInfo * info)229 void QuicUnackedPacketMap::RemoveRetransmittability(
230 QuicTransmissionInfo* info) {
231 DeleteFrames(&info->retransmittable_frames);
232 info->first_sent_after_loss.Clear();
233 }
234
RemoveRetransmittability(QuicPacketNumber packet_number)235 void QuicUnackedPacketMap::RemoveRetransmittability(
236 QuicPacketNumber packet_number) {
237 QUICHE_DCHECK_GE(packet_number, least_unacked_);
238 QUICHE_DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
239 QuicTransmissionInfo* info =
240 &unacked_packets_[packet_number - least_unacked_];
241 RemoveRetransmittability(info);
242 }
243
IncreaseLargestAcked(QuicPacketNumber largest_acked)244 void QuicUnackedPacketMap::IncreaseLargestAcked(
245 QuicPacketNumber largest_acked) {
246 QUICHE_DCHECK(!largest_acked_.IsInitialized() ||
247 largest_acked_ <= largest_acked);
248 largest_acked_ = largest_acked;
249 }
250
MaybeUpdateLargestAckedOfPacketNumberSpace(PacketNumberSpace packet_number_space,QuicPacketNumber packet_number)251 void QuicUnackedPacketMap::MaybeUpdateLargestAckedOfPacketNumberSpace(
252 PacketNumberSpace packet_number_space, QuicPacketNumber packet_number) {
253 largest_acked_packets_[packet_number_space].UpdateMax(packet_number);
254 }
255
IsPacketUsefulForMeasuringRtt(QuicPacketNumber packet_number,const QuicTransmissionInfo & info) const256 bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
257 QuicPacketNumber packet_number, const QuicTransmissionInfo& info) const {
258 // Packet can be used for RTT measurement if it may yet be acked as the
259 // largest observed packet by the receiver.
260 return QuicUtils::IsAckable(info.state) &&
261 (!largest_acked_.IsInitialized() || packet_number > largest_acked_) &&
262 info.state != NOT_CONTRIBUTING_RTT;
263 }
264
IsPacketUsefulForCongestionControl(const QuicTransmissionInfo & info) const265 bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
266 const QuicTransmissionInfo& info) const {
267 // Packet contributes to congestion control if it is considered inflight.
268 return info.in_flight;
269 }
270
IsPacketUsefulForRetransmittableData(const QuicTransmissionInfo & info) const271 bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
272 const QuicTransmissionInfo& info) const {
273 // Wait for 1 RTT before giving up on the lost packet.
274 return info.first_sent_after_loss.IsInitialized() &&
275 (!largest_acked_.IsInitialized() ||
276 info.first_sent_after_loss > largest_acked_);
277 }
278
IsPacketUseless(QuicPacketNumber packet_number,const QuicTransmissionInfo & info) const279 bool QuicUnackedPacketMap::IsPacketUseless(
280 QuicPacketNumber packet_number, const QuicTransmissionInfo& info) const {
281 return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
282 !IsPacketUsefulForCongestionControl(info) &&
283 !IsPacketUsefulForRetransmittableData(info);
284 }
285
IsUnacked(QuicPacketNumber packet_number) const286 bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
287 if (packet_number < least_unacked_ ||
288 packet_number >= least_unacked_ + unacked_packets_.size()) {
289 return false;
290 }
291 return !IsPacketUseless(packet_number,
292 unacked_packets_[packet_number - least_unacked_]);
293 }
294
RemoveFromInFlight(QuicTransmissionInfo * info)295 void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
296 if (info->in_flight) {
297 QUIC_BUG_IF(quic_bug_12645_3, bytes_in_flight_ < info->bytes_sent);
298 QUIC_BUG_IF(quic_bug_12645_4, packets_in_flight_ == 0);
299 bytes_in_flight_ -= info->bytes_sent;
300 --packets_in_flight_;
301
302 const PacketNumberSpace packet_number_space =
303 GetPacketNumberSpace(info->encryption_level);
304 if (bytes_in_flight_per_packet_number_space_[packet_number_space] <
305 info->bytes_sent) {
306 QUIC_BUG(quic_bug_10518_3)
307 << "bytes_in_flight: "
308 << bytes_in_flight_per_packet_number_space_[packet_number_space]
309 << " is smaller than bytes_sent: " << info->bytes_sent
310 << " for packet number space: "
311 << PacketNumberSpaceToString(packet_number_space);
312 bytes_in_flight_per_packet_number_space_[packet_number_space] = 0;
313 } else {
314 bytes_in_flight_per_packet_number_space_[packet_number_space] -=
315 info->bytes_sent;
316 }
317 if (bytes_in_flight_per_packet_number_space_[packet_number_space] == 0) {
318 last_inflight_packets_sent_time_[packet_number_space] = QuicTime::Zero();
319 }
320
321 info->in_flight = false;
322 }
323 }
324
RemoveFromInFlight(QuicPacketNumber packet_number)325 void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
326 QUICHE_DCHECK_GE(packet_number, least_unacked_);
327 QUICHE_DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
328 QuicTransmissionInfo* info =
329 &unacked_packets_[packet_number - least_unacked_];
330 RemoveFromInFlight(info);
331 }
332
333 absl::InlinedVector<QuicPacketNumber, 2>
NeuterUnencryptedPackets()334 QuicUnackedPacketMap::NeuterUnencryptedPackets() {
335 absl::InlinedVector<QuicPacketNumber, 2> neutered_packets;
336 QuicPacketNumber packet_number = GetLeastUnacked();
337 for (QuicUnackedPacketMap::iterator it = begin(); it != end();
338 ++it, ++packet_number) {
339 if (!it->retransmittable_frames.empty() &&
340 it->encryption_level == ENCRYPTION_INITIAL) {
341 QUIC_DVLOG(2) << "Neutering unencrypted packet " << packet_number;
342 // Once the connection swithes to forward secure, no unencrypted packets
343 // will be sent. The data has been abandoned in the cryto stream. Remove
344 // it from in flight.
345 RemoveFromInFlight(packet_number);
346 it->state = NEUTERED;
347 neutered_packets.push_back(packet_number);
348 // Notify session that the data has been delivered (but do not notify
349 // send algorithm).
350 // TODO(b/148868195): use NotifyFramesNeutered.
351 NotifyFramesAcked(*it, QuicTime::Delta::Zero(), QuicTime::Zero());
352 QUICHE_DCHECK(!HasRetransmittableFrames(*it));
353 }
354 }
355 QUICHE_DCHECK(!supports_multiple_packet_number_spaces_ ||
356 last_inflight_packets_sent_time_[INITIAL_DATA] ==
357 QuicTime::Zero());
358 return neutered_packets;
359 }
360
361 absl::InlinedVector<QuicPacketNumber, 2>
NeuterHandshakePackets()362 QuicUnackedPacketMap::NeuterHandshakePackets() {
363 absl::InlinedVector<QuicPacketNumber, 2> neutered_packets;
364 QuicPacketNumber packet_number = GetLeastUnacked();
365 for (QuicUnackedPacketMap::iterator it = begin(); it != end();
366 ++it, ++packet_number) {
367 if (!it->retransmittable_frames.empty() &&
368 GetPacketNumberSpace(it->encryption_level) == HANDSHAKE_DATA) {
369 QUIC_DVLOG(2) << "Neutering handshake packet " << packet_number;
370 RemoveFromInFlight(packet_number);
371 // Notify session that the data has been delivered (but do not notify
372 // send algorithm).
373 it->state = NEUTERED;
374 neutered_packets.push_back(packet_number);
375 // TODO(b/148868195): use NotifyFramesNeutered.
376 NotifyFramesAcked(*it, QuicTime::Delta::Zero(), QuicTime::Zero());
377 }
378 }
379 QUICHE_DCHECK(!supports_multiple_packet_number_spaces() ||
380 last_inflight_packets_sent_time_[HANDSHAKE_DATA] ==
381 QuicTime::Zero());
382 return neutered_packets;
383 }
384
HasInFlightPackets() const385 bool QuicUnackedPacketMap::HasInFlightPackets() const {
386 return bytes_in_flight_ > 0;
387 }
388
GetTransmissionInfo(QuicPacketNumber packet_number) const389 const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
390 QuicPacketNumber packet_number) const {
391 return unacked_packets_[packet_number - least_unacked_];
392 }
393
GetMutableTransmissionInfo(QuicPacketNumber packet_number)394 QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
395 QuicPacketNumber packet_number) {
396 return &unacked_packets_[packet_number - least_unacked_];
397 }
398
GetLastInFlightPacketSentTime() const399 QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime() const {
400 return last_inflight_packet_sent_time_;
401 }
402
GetLastCryptoPacketSentTime() const403 QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
404 return last_crypto_packet_sent_time_;
405 }
406
GetNumUnackedPacketsDebugOnly() const407 size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const {
408 size_t unacked_packet_count = 0;
409 QuicPacketNumber packet_number = least_unacked_;
410 for (auto it = begin(); it != end(); ++it, ++packet_number) {
411 if (!IsPacketUseless(packet_number, *it)) {
412 ++unacked_packet_count;
413 }
414 }
415 return unacked_packet_count;
416 }
417
HasMultipleInFlightPackets() const418 bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
419 if (bytes_in_flight_ > kDefaultTCPMSS) {
420 return true;
421 }
422 size_t num_in_flight = 0;
423 for (auto it = rbegin(); it != rend(); ++it) {
424 if (it->in_flight) {
425 ++num_in_flight;
426 }
427 if (num_in_flight > 1) {
428 return true;
429 }
430 }
431 return false;
432 }
433
HasPendingCryptoPackets() const434 bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
435 return session_notifier_->HasUnackedCryptoData();
436 }
437
HasUnackedRetransmittableFrames() const438 bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
439 for (auto it = rbegin(); it != rend(); ++it) {
440 if (it->in_flight && HasRetransmittableFrames(*it)) {
441 return true;
442 }
443 }
444 return false;
445 }
446
GetLeastUnacked() const447 QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const {
448 return least_unacked_;
449 }
450
SetSessionNotifier(SessionNotifierInterface * session_notifier)451 void QuicUnackedPacketMap::SetSessionNotifier(
452 SessionNotifierInterface* session_notifier) {
453 session_notifier_ = session_notifier;
454 }
455
NotifyFramesAcked(const QuicTransmissionInfo & info,QuicTime::Delta ack_delay,QuicTime receive_timestamp)456 bool QuicUnackedPacketMap::NotifyFramesAcked(const QuicTransmissionInfo& info,
457 QuicTime::Delta ack_delay,
458 QuicTime receive_timestamp) {
459 if (session_notifier_ == nullptr) {
460 return false;
461 }
462 bool new_data_acked = false;
463 for (const QuicFrame& frame : info.retransmittable_frames) {
464 if (session_notifier_->OnFrameAcked(frame, ack_delay, receive_timestamp)) {
465 new_data_acked = true;
466 }
467 }
468 return new_data_acked;
469 }
470
NotifyFramesLost(const QuicTransmissionInfo & info,TransmissionType)471 void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
472 TransmissionType /*type*/) {
473 for (const QuicFrame& frame : info.retransmittable_frames) {
474 session_notifier_->OnFrameLost(frame);
475 }
476 }
477
RetransmitFrames(const QuicFrames & frames,TransmissionType type)478 bool QuicUnackedPacketMap::RetransmitFrames(const QuicFrames& frames,
479 TransmissionType type) {
480 return session_notifier_->RetransmitFrames(frames, type);
481 }
482
MaybeAggregateAckedStreamFrame(const QuicTransmissionInfo & info,QuicTime::Delta ack_delay,QuicTime receive_timestamp)483 void QuicUnackedPacketMap::MaybeAggregateAckedStreamFrame(
484 const QuicTransmissionInfo& info, QuicTime::Delta ack_delay,
485 QuicTime receive_timestamp) {
486 if (session_notifier_ == nullptr) {
487 return;
488 }
489 for (const auto& frame : info.retransmittable_frames) {
490 // Determine whether acked stream frame can be aggregated.
491 const bool can_aggregate =
492 frame.type == STREAM_FRAME &&
493 frame.stream_frame.stream_id == aggregated_stream_frame_.stream_id &&
494 frame.stream_frame.offset == aggregated_stream_frame_.offset +
495 aggregated_stream_frame_.data_length &&
496 // We would like to increment aggregated_stream_frame_.data_length by
497 // frame.stream_frame.data_length, so we need to make sure their sum is
498 // representable by QuicPacketLength, which is the type of the former.
499 !WillStreamFrameLengthSumWrapAround(
500 aggregated_stream_frame_.data_length,
501 frame.stream_frame.data_length);
502
503 if (can_aggregate) {
504 // Aggregate stream frame.
505 aggregated_stream_frame_.data_length += frame.stream_frame.data_length;
506 aggregated_stream_frame_.fin = frame.stream_frame.fin;
507 if (aggregated_stream_frame_.fin) {
508 // Notify session notifier aggregated stream frame gets acked if fin is
509 // acked.
510 NotifyAggregatedStreamFrameAcked(ack_delay);
511 }
512 continue;
513 }
514
515 NotifyAggregatedStreamFrameAcked(ack_delay);
516 if (frame.type != STREAM_FRAME || frame.stream_frame.fin) {
517 session_notifier_->OnFrameAcked(frame, ack_delay, receive_timestamp);
518 continue;
519 }
520
521 // Delay notifying session notifier stream frame gets acked in case it can
522 // be aggregated with following acked ones.
523 aggregated_stream_frame_.stream_id = frame.stream_frame.stream_id;
524 aggregated_stream_frame_.offset = frame.stream_frame.offset;
525 aggregated_stream_frame_.data_length = frame.stream_frame.data_length;
526 aggregated_stream_frame_.fin = frame.stream_frame.fin;
527 }
528 }
529
NotifyAggregatedStreamFrameAcked(QuicTime::Delta ack_delay)530 void QuicUnackedPacketMap::NotifyAggregatedStreamFrameAcked(
531 QuicTime::Delta ack_delay) {
532 if (aggregated_stream_frame_.stream_id == static_cast<QuicStreamId>(-1) ||
533 session_notifier_ == nullptr) {
534 // Aggregated stream frame is empty.
535 return;
536 }
537 // Note: there is no receive_timestamp for an aggregated stream frame. The
538 // frames that are aggregated may not have been received at the same time.
539 session_notifier_->OnFrameAcked(QuicFrame(aggregated_stream_frame_),
540 ack_delay,
541 /*receive_timestamp=*/QuicTime::Zero());
542 // Clear aggregated stream frame.
543 aggregated_stream_frame_.stream_id = -1;
544 }
545
GetPacketNumberSpace(QuicPacketNumber packet_number) const546 PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
547 QuicPacketNumber packet_number) const {
548 return GetPacketNumberSpace(
549 GetTransmissionInfo(packet_number).encryption_level);
550 }
551
GetPacketNumberSpace(EncryptionLevel encryption_level) const552 PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
553 EncryptionLevel encryption_level) const {
554 if (supports_multiple_packet_number_spaces_) {
555 return QuicUtils::GetPacketNumberSpace(encryption_level);
556 }
557 if (perspective_ == Perspective::IS_CLIENT) {
558 return encryption_level == ENCRYPTION_INITIAL ? HANDSHAKE_DATA
559 : APPLICATION_DATA;
560 }
561 return encryption_level == ENCRYPTION_FORWARD_SECURE ? APPLICATION_DATA
562 : HANDSHAKE_DATA;
563 }
564
GetLargestAckedOfPacketNumberSpace(PacketNumberSpace packet_number_space) const565 QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
566 PacketNumberSpace packet_number_space) const {
567 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
568 QUIC_BUG(quic_bug_10518_4)
569 << "Invalid packet number space: " << packet_number_space;
570 return QuicPacketNumber();
571 }
572 return largest_acked_packets_[packet_number_space];
573 }
574
GetLastInFlightPacketSentTime(PacketNumberSpace packet_number_space) const575 QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime(
576 PacketNumberSpace packet_number_space) const {
577 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
578 QUIC_BUG(quic_bug_10518_5)
579 << "Invalid packet number space: " << packet_number_space;
580 return QuicTime::Zero();
581 }
582 return last_inflight_packets_sent_time_[packet_number_space];
583 }
584
585 QuicPacketNumber
GetLargestSentRetransmittableOfPacketNumberSpace(PacketNumberSpace packet_number_space) const586 QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
587 PacketNumberSpace packet_number_space) const {
588 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
589 QUIC_BUG(quic_bug_10518_6)
590 << "Invalid packet number space: " << packet_number_space;
591 return QuicPacketNumber();
592 }
593 return largest_sent_retransmittable_packets_[packet_number_space];
594 }
595
596 const QuicTransmissionInfo*
GetFirstInFlightTransmissionInfo() const597 QuicUnackedPacketMap::GetFirstInFlightTransmissionInfo() const {
598 QUICHE_DCHECK(HasInFlightPackets());
599 for (auto it = begin(); it != end(); ++it) {
600 if (it->in_flight) {
601 return &(*it);
602 }
603 }
604 QUICHE_DCHECK(false);
605 return nullptr;
606 }
607
608 const QuicTransmissionInfo*
GetFirstInFlightTransmissionInfoOfSpace(PacketNumberSpace packet_number_space) const609 QuicUnackedPacketMap::GetFirstInFlightTransmissionInfoOfSpace(
610 PacketNumberSpace packet_number_space) const {
611 // TODO(fayang): Optimize this part if arm 1st PTO with first in flight sent
612 // time works.
613 for (auto it = begin(); it != end(); ++it) {
614 if (it->in_flight &&
615 GetPacketNumberSpace(it->encryption_level) == packet_number_space) {
616 return &(*it);
617 }
618 }
619 return nullptr;
620 }
621
EnableMultiplePacketNumberSpacesSupport()622 void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
623 if (supports_multiple_packet_number_spaces_) {
624 QUIC_BUG(quic_bug_10518_7)
625 << "Multiple packet number spaces has already been enabled";
626 return;
627 }
628 if (largest_sent_packet_.IsInitialized()) {
629 QUIC_BUG(quic_bug_10518_8)
630 << "Try to enable multiple packet number spaces support after any "
631 "packet has been sent.";
632 return;
633 }
634
635 supports_multiple_packet_number_spaces_ = true;
636 }
637
GetLastPacketContent() const638 int32_t QuicUnackedPacketMap::GetLastPacketContent() const {
639 if (empty()) {
640 // Use -1 to distinguish with packets with no retransmittable frames nor
641 // acks.
642 return -1;
643 }
644 int32_t content = 0;
645 const QuicTransmissionInfo& last_packet = unacked_packets_.back();
646 for (const auto& frame : last_packet.retransmittable_frames) {
647 content |= GetFrameTypeBitfield(frame.type);
648 }
649 if (last_packet.largest_acked.IsInitialized()) {
650 content |= GetFrameTypeBitfield(ACK_FRAME);
651 }
652 return content;
653 }
654
655 } // namespace quic
656