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