• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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