xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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