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