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