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