xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_coalesced_packet.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 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_coalesced_packet.h"
6 
7 #include "absl/memory/memory.h"
8 #include "absl/strings/str_cat.h"
9 #include "quiche/quic/platform/api/quic_bug_tracker.h"
10 
11 namespace quic {
12 
QuicCoalescedPacket()13 QuicCoalescedPacket::QuicCoalescedPacket()
14     : length_(0), max_packet_length_(0), ecn_codepoint_(ECN_NOT_ECT) {}
15 
~QuicCoalescedPacket()16 QuicCoalescedPacket::~QuicCoalescedPacket() { Clear(); }
17 
MaybeCoalescePacket(const SerializedPacket & packet,const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,quiche::QuicheBufferAllocator * allocator,QuicPacketLength current_max_packet_length,QuicEcnCodepoint ecn_codepoint)18 bool QuicCoalescedPacket::MaybeCoalescePacket(
19     const SerializedPacket& packet, const QuicSocketAddress& self_address,
20     const QuicSocketAddress& peer_address,
21     quiche::QuicheBufferAllocator* allocator,
22     QuicPacketLength current_max_packet_length,
23     QuicEcnCodepoint ecn_codepoint) {
24   if (packet.encrypted_length == 0) {
25     QUIC_BUG(quic_bug_10611_1) << "Trying to coalesce an empty packet";
26     return true;
27   }
28   if (length_ == 0) {
29 #ifndef NDEBUG
30     for (const auto& buffer : encrypted_buffers_) {
31       QUICHE_DCHECK(buffer.empty());
32     }
33 #endif
34     QUICHE_DCHECK(initial_packet_ == nullptr);
35     // This is the first packet, set max_packet_length and self/peer
36     // addresses.
37     max_packet_length_ = current_max_packet_length;
38     self_address_ = self_address;
39     peer_address_ = peer_address;
40   } else {
41     if (self_address_ != self_address || peer_address_ != peer_address) {
42       // Do not coalesce packet with different self/peer addresses.
43       QUIC_DLOG(INFO)
44           << "Cannot coalesce packet because self/peer address changed";
45       return false;
46     }
47     if (max_packet_length_ != current_max_packet_length) {
48       QUIC_BUG(quic_bug_10611_2)
49           << "Max packet length changes in the middle of the write path";
50       return false;
51     }
52     if (ContainsPacketOfEncryptionLevel(packet.encryption_level)) {
53       // Do not coalesce packets of the same encryption level.
54       return false;
55     }
56     if (ecn_codepoint != ecn_codepoint_) {
57       // Do not coalesce packets with different ECN codepoints.
58       return false;
59     }
60   }
61 
62   if (length_ + packet.encrypted_length > max_packet_length_) {
63     // Packet does not fit.
64     return false;
65   }
66   QUIC_DVLOG(1) << "Successfully coalesced packet: encryption_level: "
67                 << packet.encryption_level
68                 << ", encrypted_length: " << packet.encrypted_length
69                 << ", current length: " << length_
70                 << ", max_packet_length: " << max_packet_length_;
71   if (length_ > 0) {
72     QUIC_CODE_COUNT(QUIC_SUCCESSFULLY_COALESCED_MULTIPLE_PACKETS);
73   }
74   ecn_codepoint_ = ecn_codepoint;
75   length_ += packet.encrypted_length;
76   transmission_types_[packet.encryption_level] = packet.transmission_type;
77   if (packet.encryption_level == ENCRYPTION_INITIAL) {
78     // Save a copy of ENCRYPTION_INITIAL packet (excluding encrypted buffer, as
79     // the packet will be re-serialized later).
80     initial_packet_ = absl::WrapUnique<SerializedPacket>(
81         CopySerializedPacket(packet, allocator, /*copy_buffer=*/false));
82     return true;
83   }
84   // Copy encrypted buffer of packets with other encryption levels.
85   encrypted_buffers_[packet.encryption_level] =
86       std::string(packet.encrypted_buffer, packet.encrypted_length);
87   return true;
88 }
89 
Clear()90 void QuicCoalescedPacket::Clear() {
91   self_address_ = QuicSocketAddress();
92   peer_address_ = QuicSocketAddress();
93   length_ = 0;
94   max_packet_length_ = 0;
95   for (auto& packet : encrypted_buffers_) {
96     packet.clear();
97   }
98   for (size_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
99     transmission_types_[i] = NOT_RETRANSMISSION;
100   }
101   initial_packet_ = nullptr;
102 }
103 
NeuterInitialPacket()104 void QuicCoalescedPacket::NeuterInitialPacket() {
105   if (initial_packet_ == nullptr) {
106     return;
107   }
108   if (length_ < initial_packet_->encrypted_length) {
109     QUIC_BUG(quic_bug_10611_3)
110         << "length_: " << length_ << ", is less than initial packet length: "
111         << initial_packet_->encrypted_length;
112     Clear();
113     return;
114   }
115   length_ -= initial_packet_->encrypted_length;
116   if (length_ == 0) {
117     Clear();
118     return;
119   }
120   transmission_types_[ENCRYPTION_INITIAL] = NOT_RETRANSMISSION;
121   initial_packet_ = nullptr;
122 }
123 
CopyEncryptedBuffers(char * buffer,size_t buffer_len,size_t * length_copied) const124 bool QuicCoalescedPacket::CopyEncryptedBuffers(char* buffer, size_t buffer_len,
125                                                size_t* length_copied) const {
126   *length_copied = 0;
127   for (const auto& packet : encrypted_buffers_) {
128     if (packet.empty()) {
129       continue;
130     }
131     if (packet.length() > buffer_len) {
132       return false;
133     }
134     memcpy(buffer, packet.data(), packet.length());
135     buffer += packet.length();
136     buffer_len -= packet.length();
137     *length_copied += packet.length();
138   }
139   return true;
140 }
141 
ContainsPacketOfEncryptionLevel(EncryptionLevel level) const142 bool QuicCoalescedPacket::ContainsPacketOfEncryptionLevel(
143     EncryptionLevel level) const {
144   return !encrypted_buffers_[level].empty() ||
145          (level == ENCRYPTION_INITIAL && initial_packet_ != nullptr);
146 }
147 
TransmissionTypeOfPacket(EncryptionLevel level) const148 TransmissionType QuicCoalescedPacket::TransmissionTypeOfPacket(
149     EncryptionLevel level) const {
150   if (!ContainsPacketOfEncryptionLevel(level)) {
151     QUIC_BUG(quic_bug_10611_4)
152         << "Coalesced packet does not contain packet of encryption level: "
153         << EncryptionLevelToString(level);
154     return NOT_RETRANSMISSION;
155   }
156   return transmission_types_[level];
157 }
158 
NumberOfPackets() const159 size_t QuicCoalescedPacket::NumberOfPackets() const {
160   size_t num_of_packets = 0;
161   for (int8_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
162     if (ContainsPacketOfEncryptionLevel(static_cast<EncryptionLevel>(i))) {
163       ++num_of_packets;
164     }
165   }
166   return num_of_packets;
167 }
168 
ToString(size_t serialized_length) const169 std::string QuicCoalescedPacket::ToString(size_t serialized_length) const {
170   // Total length and padding size.
171   std::string info = absl::StrCat(
172       "total_length: ", serialized_length,
173       " padding_size: ", serialized_length - length_, " packets: {");
174   // Packets' encryption levels.
175   bool first_packet = true;
176   for (int8_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
177     if (ContainsPacketOfEncryptionLevel(static_cast<EncryptionLevel>(i))) {
178       absl::StrAppend(&info, first_packet ? "" : ", ",
179                       EncryptionLevelToString(static_cast<EncryptionLevel>(i)));
180       first_packet = false;
181     }
182   }
183   absl::StrAppend(&info, "}");
184   return info;
185 }
186 
packet_lengths() const187 std::vector<size_t> QuicCoalescedPacket::packet_lengths() const {
188   std::vector<size_t> lengths;
189   for (const auto& packet : encrypted_buffers_) {
190     if (lengths.empty()) {
191       lengths.push_back(
192           initial_packet_ == nullptr ? 0 : initial_packet_->encrypted_length);
193     } else {
194       lengths.push_back(packet.length());
195     }
196   }
197   return lengths;
198 }
199 
200 }  // namespace quic
201