blob: 47aa93b8ed349b62b7cfe4276a9ad69368d8240b [file] [log] [blame]
fayang503ca4f2019-10-23 07:20:51 -07001// 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/core/quic_coalesced_packet.h"
fayang503ca4f2019-10-23 07:20:51 -07006
vasilvv9edb31e2020-12-03 19:32:58 -08007#include "absl/strings/str_cat.h"
QUICHE team5be974e2020-12-29 18:35:24 -05008#include "quic/platform/api/quic_bug_tracker.h"
9#include "quic/platform/api/quic_ptr_util.h"
fayang503ca4f2019-10-23 07:20:51 -070010
11namespace quic {
12
13QuicCoalescedPacket::QuicCoalescedPacket()
14 : length_(0), max_packet_length_(0) {}
15
16QuicCoalescedPacket::~QuicCoalescedPacket() {
17 Clear();
18}
19
20bool QuicCoalescedPacket::MaybeCoalescePacket(
21 const SerializedPacket& packet,
22 const QuicSocketAddress& self_address,
23 const QuicSocketAddress& peer_address,
24 QuicBufferAllocator* allocator,
25 QuicPacketLength current_max_packet_length) {
26 if (packet.encrypted_length == 0) {
27 QUIC_BUG << "Trying to coalesce an empty packet";
28 return true;
29 }
30 if (length_ == 0) {
31#ifndef NDEBUG
32 for (const auto& buffer : encrypted_buffers_) {
33 DCHECK(buffer.empty());
34 }
35#endif
36 DCHECK(initial_packet_ == nullptr);
37 // This is the first packet, set max_packet_length and self/peer
38 // addresses.
39 max_packet_length_ = current_max_packet_length;
40 self_address_ = self_address;
41 peer_address_ = peer_address;
42 } else {
43 if (self_address_ != self_address || peer_address_ != peer_address) {
44 // Do not coalesce packet with different self/peer addresses.
45 QUIC_DLOG(INFO)
46 << "Cannot coalesce packet because self/peer address changed";
47 return false;
48 }
49 if (max_packet_length_ != current_max_packet_length) {
fayang58f71072019-11-05 08:47:02 -080050 QUIC_BUG << "Max packet length changes in the middle of the write path";
fayang503ca4f2019-10-23 07:20:51 -070051 return false;
52 }
fayang9cdce502020-03-31 10:56:36 -070053 if (ContainsPacketOfEncryptionLevel(packet.encryption_level)) {
fayang503ca4f2019-10-23 07:20:51 -070054 // Do not coalesce packets of the same encryption level.
55 return false;
56 }
57 }
58
fayang503ca4f2019-10-23 07:20:51 -070059 if (length_ + packet.encrypted_length > max_packet_length_) {
60 // Packet does not fit.
61 return false;
62 }
fayang08750832019-10-24 11:25:34 -070063 QUIC_DVLOG(1) << "Successfully coalesced packet: encryption_level: "
renjietangb4ebb1d2020-05-27 18:15:51 -070064 << packet.encryption_level
fayang08750832019-10-24 11:25:34 -070065 << ", encrypted_length: " << packet.encrypted_length
66 << ", current length: " << length_
67 << ", max_packet_length: " << max_packet_length_;
fayang58f71072019-11-05 08:47:02 -080068 if (length_ > 0) {
69 QUIC_CODE_COUNT(QUIC_SUCCESSFULLY_COALESCED_MULTIPLE_PACKETS);
70 }
fayang503ca4f2019-10-23 07:20:51 -070071 length_ += packet.encrypted_length;
fayangfe963c52020-07-16 06:56:09 -070072 transmission_types_[packet.encryption_level] = packet.transmission_type;
fayang503ca4f2019-10-23 07:20:51 -070073 if (packet.encryption_level == ENCRYPTION_INITIAL) {
74 // Save a copy of ENCRYPTION_INITIAL packet (excluding encrypted buffer, as
75 // the packet will be re-serialized later).
76 initial_packet_ = QuicWrapUnique<SerializedPacket>(
77 CopySerializedPacket(packet, allocator, /*copy_buffer=*/false));
78 return true;
79 }
80 // Copy encrypted buffer of packets with other encryption levels.
81 encrypted_buffers_[packet.encryption_level] =
82 std::string(packet.encrypted_buffer, packet.encrypted_length);
83 return true;
84}
85
86void QuicCoalescedPacket::Clear() {
87 self_address_ = QuicSocketAddress();
88 peer_address_ = QuicSocketAddress();
89 length_ = 0;
90 max_packet_length_ = 0;
91 for (auto& packet : encrypted_buffers_) {
92 packet.clear();
93 }
fayangfe963c52020-07-16 06:56:09 -070094 for (size_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
95 transmission_types_[i] = NOT_RETRANSMISSION;
96 }
fayang503ca4f2019-10-23 07:20:51 -070097 initial_packet_ = nullptr;
98}
99
fayange447bc62020-08-27 13:47:11 -0700100void QuicCoalescedPacket::NeuterInitialPacket() {
101 if (initial_packet_ == nullptr) {
102 return;
103 }
104 if (length_ < initial_packet_->encrypted_length) {
105 QUIC_BUG << "length_: " << length_
106 << ", is less than initial packet length: "
107 << initial_packet_->encrypted_length;
108 Clear();
109 return;
110 }
111 length_ -= initial_packet_->encrypted_length;
112 if (length_ == 0) {
113 Clear();
114 return;
115 }
116 transmission_types_[ENCRYPTION_INITIAL] = NOT_RETRANSMISSION;
117 initial_packet_ = nullptr;
118}
119
fayang08750832019-10-24 11:25:34 -0700120bool QuicCoalescedPacket::CopyEncryptedBuffers(char* buffer,
121 size_t buffer_len,
122 size_t* length_copied) const {
123 *length_copied = 0;
124 for (const auto& packet : encrypted_buffers_) {
125 if (packet.empty()) {
126 continue;
127 }
128 if (packet.length() > buffer_len) {
129 return false;
130 }
131 memcpy(buffer, packet.data(), packet.length());
132 buffer += packet.length();
133 buffer_len -= packet.length();
134 *length_copied += packet.length();
135 }
136 return true;
137}
138
fayang9cdce502020-03-31 10:56:36 -0700139bool QuicCoalescedPacket::ContainsPacketOfEncryptionLevel(
140 EncryptionLevel level) const {
141 return !encrypted_buffers_[level].empty() ||
142 (level == ENCRYPTION_INITIAL && initial_packet_ != nullptr);
143}
144
fayangfe963c52020-07-16 06:56:09 -0700145TransmissionType QuicCoalescedPacket::TransmissionTypeOfPacket(
146 EncryptionLevel level) const {
147 if (!ContainsPacketOfEncryptionLevel(level)) {
148 QUIC_BUG << "Coalesced packet does not contain packet of encryption level: "
149 << EncryptionLevelToString(level);
150 return NOT_RETRANSMISSION;
151 }
152 return transmission_types_[level];
153}
154
fayang9cdce502020-03-31 10:56:36 -0700155std::string QuicCoalescedPacket::ToString(size_t serialized_length) const {
156 // Total length and padding size.
vasilvv9edb31e2020-12-03 19:32:58 -0800157 std::string info = absl::StrCat(
fayang9cdce502020-03-31 10:56:36 -0700158 "total_length: ", serialized_length,
159 " padding_size: ", serialized_length - length_, " packets: {");
160 // Packets' encryption levels.
161 bool first_packet = true;
162 for (int8_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) {
163 if (ContainsPacketOfEncryptionLevel(static_cast<EncryptionLevel>(i))) {
vasilvv9edb31e2020-12-03 19:32:58 -0800164 absl::StrAppend(&info, first_packet ? "" : ", ",
165 EncryptionLevelToString(static_cast<EncryptionLevel>(i)));
fayang9cdce502020-03-31 10:56:36 -0700166 first_packet = false;
167 }
168 }
vasilvv9edb31e2020-12-03 19:32:58 -0800169 absl::StrAppend(&info, "}");
fayang9cdce502020-03-31 10:56:36 -0700170 return info;
171}
172
fayang503ca4f2019-10-23 07:20:51 -0700173} // namespace quic