blob: 3d5579da4502acf209d9c8e97b017f697631fa1a [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 "net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h"
6
7#include <limits>
8#include <type_traits>
9
10#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
11#include "net/third_party/quiche/src/quic/core/quic_utils.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
14
15namespace quic {
16
17namespace {
18bool WillStreamFrameLengthSumWrapAround(QuicPacketLength lhs,
19 QuicPacketLength rhs) {
20 static_assert(
21 std::is_unsigned<QuicPacketLength>::value,
22 "This function assumes QuicPacketLength is an unsigned integer type.");
23 return std::numeric_limits<QuicPacketLength>::max() - lhs < rhs;
24}
fayang037883b2020-08-18 07:03:01 -070025
26enum QuicFrameTypeBitfield : uint32_t {
27 kInvalidFrameBitfield = 0,
28 kPaddingFrameBitfield = 1,
29 kRstStreamFrameBitfield = 1 << 1,
30 kConnectionCloseFrameBitfield = 1 << 2,
31 kGoawayFrameBitfield = 1 << 3,
32 kWindowUpdateFrameBitfield = 1 << 4,
33 kBlockedFrameBitfield = 1 << 5,
34 kStopWaitingFrameBitfield = 1 << 6,
35 kPingFrameBitfield = 1 << 7,
36 kCryptoFrameBitfield = 1 << 8,
37 kHandshakeDoneFrameBitfield = 1 << 9,
38 kStreamFrameBitfield = 1 << 10,
39 kAckFrameBitfield = 1 << 11,
40 kMtuDiscoveryFrameBitfield = 1 << 12,
41 kNewConnectionIdFrameBitfield = 1 << 13,
42 kMaxStreamsFrameBitfield = 1 << 14,
43 kStreamsBlockedFrameBitfield = 1 << 15,
44 kPathResponseFrameBitfield = 1 << 16,
45 kPathChallengeFrameBitfield = 1 << 17,
46 kStopSendingFrameBitfield = 1 << 18,
47 kMessageFrameBitfield = 1 << 19,
48 kNewTokenFrameBitfield = 1 << 20,
49 kRetireConnectionIdFrameBitfield = 1 << 21,
50 kAckFrequencyFrameBitfield = 1 << 22,
51};
52
53QuicFrameTypeBitfield GetFrameTypeBitfield(QuicFrameType type) {
54 switch (type) {
55 case PADDING_FRAME:
56 return kPaddingFrameBitfield;
57 case RST_STREAM_FRAME:
58 return kRstStreamFrameBitfield;
59 case CONNECTION_CLOSE_FRAME:
60 return kConnectionCloseFrameBitfield;
61 case GOAWAY_FRAME:
62 return kGoawayFrameBitfield;
63 case WINDOW_UPDATE_FRAME:
64 return kWindowUpdateFrameBitfield;
65 case BLOCKED_FRAME:
66 return kBlockedFrameBitfield;
67 case STOP_WAITING_FRAME:
68 return kStopWaitingFrameBitfield;
69 case PING_FRAME:
70 return kPingFrameBitfield;
71 case CRYPTO_FRAME:
72 return kCryptoFrameBitfield;
73 case HANDSHAKE_DONE_FRAME:
74 return kHandshakeDoneFrameBitfield;
75 case STREAM_FRAME:
76 return kStreamFrameBitfield;
77 case ACK_FRAME:
78 return kAckFrameBitfield;
79 case MTU_DISCOVERY_FRAME:
80 return kMtuDiscoveryFrameBitfield;
81 case NEW_CONNECTION_ID_FRAME:
82 return kNewConnectionIdFrameBitfield;
83 case MAX_STREAMS_FRAME:
84 return kMaxStreamsFrameBitfield;
85 case STREAMS_BLOCKED_FRAME:
86 return kStreamsBlockedFrameBitfield;
87 case PATH_RESPONSE_FRAME:
88 return kPathResponseFrameBitfield;
89 case PATH_CHALLENGE_FRAME:
90 return kPathChallengeFrameBitfield;
91 case STOP_SENDING_FRAME:
92 return kStopSendingFrameBitfield;
93 case MESSAGE_FRAME:
94 return kMessageFrameBitfield;
95 case NEW_TOKEN_FRAME:
96 return kNewTokenFrameBitfield;
97 case RETIRE_CONNECTION_ID_FRAME:
98 return kRetireConnectionIdFrameBitfield;
99 case ACK_FREQUENCY_FRAME:
100 return kAckFrequencyFrameBitfield;
101 case NUM_FRAME_TYPES:
102 QUIC_BUG << "Unexpected frame type";
103 return kInvalidFrameBitfield;
104 }
105 QUIC_BUG << "Unexpected frame type";
106 return kInvalidFrameBitfield;
107}
108
QUICHE teama6ef0a62019-03-07 20:34:33 -0500109} // namespace
110
111QuicUnackedPacketMap::QuicUnackedPacketMap(Perspective perspective)
112 : perspective_(perspective),
113 least_unacked_(FirstSendingPacketNumber()),
114 bytes_in_flight_(0),
fayang40334262020-05-19 15:18:28 -0700115 bytes_in_flight_per_packet_number_space_{0, 0, 0},
fayang4c908f02019-11-01 07:26:17 -0700116 packets_in_flight_(0),
ianswett479fea32019-09-04 02:51:01 -0700117 last_inflight_packet_sent_time_(QuicTime::Zero()),
fayang18ff23b2020-01-28 09:19:00 -0800118 last_inflight_packets_sent_time_{{QuicTime::Zero()},
119 {QuicTime::Zero()},
120 {QuicTime::Zero()}},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 last_crypto_packet_sent_time_(QuicTime::Zero()),
122 session_notifier_(nullptr),
ianswette3567522019-10-28 07:20:10 -0700123 supports_multiple_packet_number_spaces_(false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124
125QuicUnackedPacketMap::~QuicUnackedPacketMap() {
126 for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
127 DeleteFrames(&(transmission_info.retransmittable_frames));
128 }
129}
130
wubb0567e22020-09-11 17:42:29 -0700131void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* mutable_packet,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132 TransmissionType transmission_type,
133 QuicTime sent_time,
danzh8c7d1192020-08-25 08:01:43 -0700134 bool set_in_flight,
135 bool measure_rtt) {
wubb0567e22020-09-11 17:42:29 -0700136 const SerializedPacket& packet = *mutable_packet;
137 QuicPacketNumber packet_number = packet.packet_number;
138 QuicPacketLength bytes_sent = packet.encrypted_length;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 QUIC_BUG_IF(largest_sent_packet_.IsInitialized() &&
140 largest_sent_packet_ >= packet_number)
141 << "largest_sent_packet_: " << largest_sent_packet_
142 << ", packet_number: " << packet_number;
143 DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
144 while (least_unacked_ + unacked_packets_.size() < packet_number) {
145 unacked_packets_.push_back(QuicTransmissionInfo());
146 unacked_packets_.back().state = NEVER_SENT;
147 }
148
wubb0567e22020-09-11 17:42:29 -0700149 const bool has_crypto_handshake = packet.has_crypto_handshake == IS_HANDSHAKE;
150 QuicTransmissionInfo info(packet.encryption_level, transmission_type,
fayang88b87232020-06-24 15:31:08 -0700151 sent_time, bytes_sent, has_crypto_handshake);
wubb0567e22020-09-11 17:42:29 -0700152 info.largest_acked = packet.largest_acked;
153 largest_sent_largest_acked_.UpdateMax(packet.largest_acked);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154
danzh8c7d1192020-08-25 08:01:43 -0700155 if (!measure_rtt) {
156 QUIC_BUG_IF(set_in_flight);
157 info.state = NOT_CONTRIBUTING_RTT;
158 }
159
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 largest_sent_packet_ = packet_number;
161 if (set_in_flight) {
fayang18ff23b2020-01-28 09:19:00 -0800162 const PacketNumberSpace packet_number_space =
163 GetPacketNumberSpace(info.encryption_level);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500164 bytes_in_flight_ += bytes_sent;
fayang40334262020-05-19 15:18:28 -0700165 bytes_in_flight_per_packet_number_space_[packet_number_space] += bytes_sent;
fayang4c908f02019-11-01 07:26:17 -0700166 ++packets_in_flight_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500167 info.in_flight = true;
fayang18ff23b2020-01-28 09:19:00 -0800168 largest_sent_retransmittable_packets_[packet_number_space] = packet_number;
ianswett479fea32019-09-04 02:51:01 -0700169 last_inflight_packet_sent_time_ = sent_time;
fayang18ff23b2020-01-28 09:19:00 -0800170 last_inflight_packets_sent_time_[packet_number_space] = sent_time;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500171 }
172 unacked_packets_.push_back(info);
173 // Swap the retransmittable frames to avoid allocations.
174 // TODO(ianswett): Could use emplace_back when Chromium can.
fayangcff885a2019-10-22 07:39:04 -0700175 if (has_crypto_handshake) {
176 last_crypto_packet_sent_time_ = sent_time;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500177 }
fayangcff885a2019-10-22 07:39:04 -0700178
wubb0567e22020-09-11 17:42:29 -0700179 mutable_packet->retransmittable_frames.swap(
fayangcff885a2019-10-22 07:39:04 -0700180 unacked_packets_.back().retransmittable_frames);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181}
182
183void QuicUnackedPacketMap::RemoveObsoletePackets() {
184 while (!unacked_packets_.empty()) {
185 if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) {
186 break;
187 }
fayangcff885a2019-10-22 07:39:04 -0700188 DeleteFrames(&unacked_packets_.front().retransmittable_frames);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500189 unacked_packets_.pop_front();
190 ++least_unacked_;
191 }
192}
193
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194bool QuicUnackedPacketMap::HasRetransmittableFrames(
195 QuicPacketNumber packet_number) const {
196 DCHECK_GE(packet_number, least_unacked_);
197 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
198 return HasRetransmittableFrames(
199 unacked_packets_[packet_number - least_unacked_]);
200}
201
202bool QuicUnackedPacketMap::HasRetransmittableFrames(
203 const QuicTransmissionInfo& info) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500204 if (!QuicUtils::IsAckable(info.state)) {
205 return false;
206 }
207
208 for (const auto& frame : info.retransmittable_frames) {
209 if (session_notifier_->IsFrameOutstanding(frame)) {
210 return true;
211 }
212 }
213 return false;
214}
215
216void QuicUnackedPacketMap::RemoveRetransmittability(
217 QuicTransmissionInfo* info) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218 DeleteFrames(&info->retransmittable_frames);
renjietang178e6442020-07-30 11:00:27 -0700219 info->first_sent_after_loss.Clear();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500220}
221
222void QuicUnackedPacketMap::RemoveRetransmittability(
223 QuicPacketNumber packet_number) {
224 DCHECK_GE(packet_number, least_unacked_);
225 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
226 QuicTransmissionInfo* info =
227 &unacked_packets_[packet_number - least_unacked_];
228 RemoveRetransmittability(info);
229}
230
231void QuicUnackedPacketMap::IncreaseLargestAcked(
232 QuicPacketNumber largest_acked) {
233 DCHECK(!largest_acked_.IsInitialized() || largest_acked_ <= largest_acked);
234 largest_acked_ = largest_acked;
235}
236
237void QuicUnackedPacketMap::MaybeUpdateLargestAckedOfPacketNumberSpace(
fayang3eb82212019-04-16 12:05:46 -0700238 PacketNumberSpace packet_number_space,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500239 QuicPacketNumber packet_number) {
QUICHE teamc264e362019-03-19 14:21:06 -0700240 largest_acked_packets_[packet_number_space].UpdateMax(packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241}
242
243bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
244 QuicPacketNumber packet_number,
245 const QuicTransmissionInfo& info) const {
246 // Packet can be used for RTT measurement if it may yet be acked as the
247 // largest observed packet by the receiver.
248 return QuicUtils::IsAckable(info.state) &&
danzh8c7d1192020-08-25 08:01:43 -0700249 (!largest_acked_.IsInitialized() || packet_number > largest_acked_) &&
250 info.state != NOT_CONTRIBUTING_RTT;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500251}
252
253bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
254 const QuicTransmissionInfo& info) const {
255 // Packet contributes to congestion control if it is considered inflight.
256 return info.in_flight;
257}
258
259bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
260 const QuicTransmissionInfo& info) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261 // Wait for 1 RTT before giving up on the lost packet.
renjietang178e6442020-07-30 11:00:27 -0700262 return info.first_sent_after_loss.IsInitialized() &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500263 (!largest_acked_.IsInitialized() ||
renjietang178e6442020-07-30 11:00:27 -0700264 info.first_sent_after_loss > largest_acked_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500265}
266
267bool QuicUnackedPacketMap::IsPacketUseless(
268 QuicPacketNumber packet_number,
269 const QuicTransmissionInfo& info) const {
270 return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
271 !IsPacketUsefulForCongestionControl(info) &&
272 !IsPacketUsefulForRetransmittableData(info);
273}
274
275bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
276 if (packet_number < least_unacked_ ||
277 packet_number >= least_unacked_ + unacked_packets_.size()) {
278 return false;
279 }
280 return !IsPacketUseless(packet_number,
281 unacked_packets_[packet_number - least_unacked_]);
282}
283
284void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
285 if (info->in_flight) {
286 QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
fayang4c908f02019-11-01 07:26:17 -0700287 QUIC_BUG_IF(packets_in_flight_ == 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500288 bytes_in_flight_ -= info->bytes_sent;
fayang4c908f02019-11-01 07:26:17 -0700289 --packets_in_flight_;
fayang40334262020-05-19 15:18:28 -0700290
291 const PacketNumberSpace packet_number_space =
292 GetPacketNumberSpace(info->encryption_level);
293 if (bytes_in_flight_per_packet_number_space_[packet_number_space] <
294 info->bytes_sent) {
295 QUIC_BUG << "bytes_in_flight: "
296 << bytes_in_flight_per_packet_number_space_[packet_number_space]
297 << " is smaller than bytes_sent: " << info->bytes_sent
298 << " for packet number space: "
299 << PacketNumberSpaceToString(packet_number_space);
300 bytes_in_flight_per_packet_number_space_[packet_number_space] = 0;
301 } else {
302 bytes_in_flight_per_packet_number_space_[packet_number_space] -=
303 info->bytes_sent;
304 }
fayang4ae5f982020-06-29 07:56:37 -0700305 if (bytes_in_flight_per_packet_number_space_[packet_number_space] == 0) {
fayang40334262020-05-19 15:18:28 -0700306 last_inflight_packets_sent_time_[packet_number_space] = QuicTime::Zero();
307 }
308
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 info->in_flight = false;
310 }
311}
312
313void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
314 DCHECK_GE(packet_number, least_unacked_);
315 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
316 QuicTransmissionInfo* info =
317 &unacked_packets_[packet_number - least_unacked_];
318 RemoveFromInFlight(info);
319}
320
wubf4ab9652020-02-20 14:45:43 -0800321QuicInlinedVector<QuicPacketNumber, 2>
322QuicUnackedPacketMap::NeuterUnencryptedPackets() {
323 QuicInlinedVector<QuicPacketNumber, 2> neutered_packets;
fayangfacc4bc2020-01-27 11:44:54 -0800324 QuicPacketNumber packet_number = GetLeastUnacked();
325 for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
326 it != unacked_packets_.end(); ++it, ++packet_number) {
327 if (!it->retransmittable_frames.empty() &&
328 it->encryption_level == ENCRYPTION_INITIAL) {
wubf4ab9652020-02-20 14:45:43 -0800329 QUIC_DVLOG(2) << "Neutering unencrypted packet " << packet_number;
fayangfacc4bc2020-01-27 11:44:54 -0800330 // Once the connection swithes to forward secure, no unencrypted packets
331 // will be sent. The data has been abandoned in the cryto stream. Remove
332 // it from in flight.
333 RemoveFromInFlight(packet_number);
334 it->state = NEUTERED;
wubf4ab9652020-02-20 14:45:43 -0800335 neutered_packets.push_back(packet_number);
fayang1f8619f2020-03-16 08:39:58 -0700336 // Notify session that the data has been delivered (but do not notify
337 // send algorithm).
338 // TODO(b/148868195): use NotifyFramesNeutered.
339 NotifyFramesAcked(*it, QuicTime::Delta::Zero(), QuicTime::Zero());
fayangfacc4bc2020-01-27 11:44:54 -0800340 DCHECK(!HasRetransmittableFrames(*it));
341 }
342 }
fayang4ae5f982020-06-29 07:56:37 -0700343 DCHECK(!supports_multiple_packet_number_spaces_ ||
344 last_inflight_packets_sent_time_[INITIAL_DATA] == QuicTime::Zero());
wubf4ab9652020-02-20 14:45:43 -0800345 return neutered_packets;
fayangfacc4bc2020-01-27 11:44:54 -0800346}
347
wubf4ab9652020-02-20 14:45:43 -0800348QuicInlinedVector<QuicPacketNumber, 2>
349QuicUnackedPacketMap::NeuterHandshakePackets() {
350 QuicInlinedVector<QuicPacketNumber, 2> neutered_packets;
fayangfacc4bc2020-01-27 11:44:54 -0800351 QuicPacketNumber packet_number = GetLeastUnacked();
352 for (QuicUnackedPacketMap::iterator it = unacked_packets_.begin();
353 it != unacked_packets_.end(); ++it, ++packet_number) {
354 if (!it->retransmittable_frames.empty() &&
355 GetPacketNumberSpace(it->encryption_level) == HANDSHAKE_DATA) {
wubf4ab9652020-02-20 14:45:43 -0800356 QUIC_DVLOG(2) << "Neutering handshake packet " << packet_number;
fayangfacc4bc2020-01-27 11:44:54 -0800357 RemoveFromInFlight(packet_number);
358 // Notify session that the data has been delivered (but do not notify
359 // send algorithm).
360 it->state = NEUTERED;
wubf4ab9652020-02-20 14:45:43 -0800361 neutered_packets.push_back(packet_number);
fayangd5c2ffb2020-02-04 11:49:05 -0800362 // TODO(b/148868195): use NotifyFramesNeutered.
fayangfacc4bc2020-01-27 11:44:54 -0800363 NotifyFramesAcked(*it, QuicTime::Delta::Zero(), QuicTime::Zero());
364 }
365 }
fayang4ae5f982020-06-29 07:56:37 -0700366 DCHECK(!supports_multiple_packet_number_spaces() ||
367 last_inflight_packets_sent_time_[HANDSHAKE_DATA] == QuicTime::Zero());
wubf4ab9652020-02-20 14:45:43 -0800368 return neutered_packets;
fayangfacc4bc2020-01-27 11:44:54 -0800369}
370
QUICHE teama6ef0a62019-03-07 20:34:33 -0500371bool QuicUnackedPacketMap::HasInFlightPackets() const {
372 return bytes_in_flight_ > 0;
373}
374
375const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
376 QuicPacketNumber packet_number) const {
377 return unacked_packets_[packet_number - least_unacked_];
378}
379
380QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
381 QuicPacketNumber packet_number) {
382 return &unacked_packets_[packet_number - least_unacked_];
383}
384
ianswett479fea32019-09-04 02:51:01 -0700385QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime() const {
ianswette3567522019-10-28 07:20:10 -0700386 return last_inflight_packet_sent_time_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500387}
388
389QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
390 return last_crypto_packet_sent_time_;
391}
392
393size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const {
394 size_t unacked_packet_count = 0;
395 QuicPacketNumber packet_number = least_unacked_;
396 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
397 ++it, ++packet_number) {
398 if (!IsPacketUseless(packet_number, *it)) {
399 ++unacked_packet_count;
400 }
401 }
402 return unacked_packet_count;
403}
404
405bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
406 if (bytes_in_flight_ > kDefaultTCPMSS) {
407 return true;
408 }
409 size_t num_in_flight = 0;
410 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
411 ++it) {
412 if (it->in_flight) {
413 ++num_in_flight;
414 }
415 if (num_in_flight > 1) {
416 return true;
417 }
418 }
419 return false;
420}
421
422bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500423 return session_notifier_->HasUnackedCryptoData();
424}
425
426bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500427 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
428 ++it) {
429 if (it->in_flight && HasRetransmittableFrames(*it)) {
430 return true;
431 }
432 }
433 return false;
434}
435
436QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const {
437 return least_unacked_;
438}
439
440void QuicUnackedPacketMap::SetSessionNotifier(
441 SessionNotifierInterface* session_notifier) {
442 session_notifier_ = session_notifier;
443}
444
445bool QuicUnackedPacketMap::NotifyFramesAcked(const QuicTransmissionInfo& info,
QUICHE team9467db02019-05-30 09:38:45 -0700446 QuicTime::Delta ack_delay,
447 QuicTime receive_timestamp) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500448 if (session_notifier_ == nullptr) {
449 return false;
450 }
451 bool new_data_acked = false;
452 for (const QuicFrame& frame : info.retransmittable_frames) {
QUICHE team9467db02019-05-30 09:38:45 -0700453 if (session_notifier_->OnFrameAcked(frame, ack_delay, receive_timestamp)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500454 new_data_acked = true;
455 }
456 }
457 return new_data_acked;
458}
459
460void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
dschinazi17d42422019-06-18 16:35:07 -0700461 TransmissionType /*type*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500462 for (const QuicFrame& frame : info.retransmittable_frames) {
463 session_notifier_->OnFrameLost(frame);
464 }
465}
466
467void QuicUnackedPacketMap::RetransmitFrames(const QuicTransmissionInfo& info,
468 TransmissionType type) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500469 session_notifier_->RetransmitFrames(info.retransmittable_frames, type);
470}
471
472void QuicUnackedPacketMap::MaybeAggregateAckedStreamFrame(
473 const QuicTransmissionInfo& info,
QUICHE team9467db02019-05-30 09:38:45 -0700474 QuicTime::Delta ack_delay,
475 QuicTime receive_timestamp) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500476 if (session_notifier_ == nullptr) {
477 return;
478 }
479 for (const auto& frame : info.retransmittable_frames) {
480 // Determine whether acked stream frame can be aggregated.
481 const bool can_aggregate =
482 frame.type == STREAM_FRAME &&
483 frame.stream_frame.stream_id == aggregated_stream_frame_.stream_id &&
484 frame.stream_frame.offset == aggregated_stream_frame_.offset +
485 aggregated_stream_frame_.data_length &&
486 // We would like to increment aggregated_stream_frame_.data_length by
487 // frame.stream_frame.data_length, so we need to make sure their sum is
488 // representable by QuicPacketLength, which is the type of the former.
489 !WillStreamFrameLengthSumWrapAround(
490 aggregated_stream_frame_.data_length,
491 frame.stream_frame.data_length);
492
493 if (can_aggregate) {
494 // Aggregate stream frame.
495 aggregated_stream_frame_.data_length += frame.stream_frame.data_length;
496 aggregated_stream_frame_.fin = frame.stream_frame.fin;
497 if (aggregated_stream_frame_.fin) {
498 // Notify session notifier aggregated stream frame gets acked if fin is
499 // acked.
500 NotifyAggregatedStreamFrameAcked(ack_delay);
501 }
502 continue;
503 }
504
505 NotifyAggregatedStreamFrameAcked(ack_delay);
506 if (frame.type != STREAM_FRAME || frame.stream_frame.fin) {
QUICHE team9467db02019-05-30 09:38:45 -0700507 session_notifier_->OnFrameAcked(frame, ack_delay, receive_timestamp);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500508 continue;
509 }
510
511 // Delay notifying session notifier stream frame gets acked in case it can
512 // be aggregated with following acked ones.
513 aggregated_stream_frame_.stream_id = frame.stream_frame.stream_id;
514 aggregated_stream_frame_.offset = frame.stream_frame.offset;
515 aggregated_stream_frame_.data_length = frame.stream_frame.data_length;
516 aggregated_stream_frame_.fin = frame.stream_frame.fin;
517 }
518}
519
520void QuicUnackedPacketMap::NotifyAggregatedStreamFrameAcked(
521 QuicTime::Delta ack_delay) {
522 if (aggregated_stream_frame_.stream_id == static_cast<QuicStreamId>(-1) ||
523 session_notifier_ == nullptr) {
524 // Aggregated stream frame is empty.
525 return;
526 }
QUICHE team9467db02019-05-30 09:38:45 -0700527 // Note: there is no receive_timestamp for an aggregated stream frame. The
528 // frames that are aggregated may not have been received at the same time.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500529 session_notifier_->OnFrameAcked(QuicFrame(aggregated_stream_frame_),
QUICHE team9467db02019-05-30 09:38:45 -0700530 ack_delay,
531 /*receive_timestamp=*/QuicTime::Zero());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500532 // Clear aggregated stream frame.
533 aggregated_stream_frame_.stream_id = -1;
534}
535
536PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
537 QuicPacketNumber packet_number) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500538 return GetPacketNumberSpace(
539 GetTransmissionInfo(packet_number).encryption_level);
540}
541
542PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
543 EncryptionLevel encryption_level) const {
QUICHE teamc279cec2019-03-22 06:51:48 -0700544 if (supports_multiple_packet_number_spaces_) {
545 return QuicUtils::GetPacketNumberSpace(encryption_level);
546 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500547 if (perspective_ == Perspective::IS_CLIENT) {
QUICHE team6987b4a2019-03-15 16:23:04 -0700548 return encryption_level == ENCRYPTION_INITIAL ? HANDSHAKE_DATA
549 : APPLICATION_DATA;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500550 }
551 return encryption_level == ENCRYPTION_FORWARD_SECURE ? APPLICATION_DATA
552 : HANDSHAKE_DATA;
553}
554
555QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
556 PacketNumberSpace packet_number_space) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500557 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
558 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
559 return QuicPacketNumber();
560 }
561 return largest_acked_packets_[packet_number_space];
562}
563
fayang18ff23b2020-01-28 09:19:00 -0800564QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime(
565 PacketNumberSpace packet_number_space) const {
566 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
567 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
568 return QuicTime::Zero();
569 }
570 return last_inflight_packets_sent_time_[packet_number_space];
571}
572
QUICHE teama6ef0a62019-03-07 20:34:33 -0500573QuicPacketNumber
574QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
575 PacketNumberSpace packet_number_space) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500576 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
577 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
578 return QuicPacketNumber();
579 }
580 return largest_sent_retransmittable_packets_[packet_number_space];
581}
582
fayang2ccfbcf2020-02-28 12:37:08 -0800583const QuicTransmissionInfo*
584QuicUnackedPacketMap::GetFirstInFlightTransmissionInfo() const {
585 DCHECK(HasInFlightPackets());
586 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it) {
587 if (it->in_flight) {
588 return &(*it);
589 }
590 }
591 DCHECK(false);
592 return nullptr;
593}
594
595const QuicTransmissionInfo*
596QuicUnackedPacketMap::GetFirstInFlightTransmissionInfoOfSpace(
597 PacketNumberSpace packet_number_space) const {
598 // TODO(fayang): Optimize this part if arm 1st PTO with first in flight sent
599 // time works.
600 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it) {
601 if (it->in_flight &&
602 GetPacketNumberSpace(it->encryption_level) == packet_number_space) {
603 return &(*it);
604 }
605 }
606 return nullptr;
607}
608
QUICHE teamc279cec2019-03-22 06:51:48 -0700609void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
610 if (supports_multiple_packet_number_spaces_) {
611 QUIC_BUG << "Multiple packet number spaces has already been enabled";
612 return;
613 }
614 if (largest_sent_packet_.IsInitialized()) {
615 QUIC_BUG << "Try to enable multiple packet number spaces support after any "
616 "packet has been sent.";
617 return;
618 }
619
620 supports_multiple_packet_number_spaces_ = true;
621}
622
fayang037883b2020-08-18 07:03:01 -0700623int32_t QuicUnackedPacketMap::GetLastPacketContent() const {
fayang8cc90d02020-08-13 12:09:55 -0700624 if (empty()) {
fayang037883b2020-08-18 07:03:01 -0700625 // Use -1 to distinguish with packets with no retransmittable frames nor
626 // acks.
627 return -1;
fayang8cc90d02020-08-13 12:09:55 -0700628 }
fayang037883b2020-08-18 07:03:01 -0700629 int32_t content = 0;
fayang8cc90d02020-08-13 12:09:55 -0700630 const QuicTransmissionInfo& last_packet = unacked_packets_.back();
631 for (const auto& frame : last_packet.retransmittable_frames) {
fayang037883b2020-08-18 07:03:01 -0700632 content |= GetFrameTypeBitfield(frame.type);
fayang8cc90d02020-08-13 12:09:55 -0700633 }
634 if (last_packet.largest_acked.IsInitialized()) {
fayang037883b2020-08-18 07:03:01 -0700635 content |= GetFrameTypeBitfield(ACK_FRAME);
fayang8cc90d02020-08-13 12:09:55 -0700636 }
637 return content;
638}
639
QUICHE teama6ef0a62019-03-07 20:34:33 -0500640} // namespace quic