fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 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 | |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 5 | #include "quic/core/quic_coalesced_packet.h" |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 6 | |
vasilvv | 9edb31e | 2020-12-03 19:32:58 -0800 | [diff] [blame] | 7 | #include "absl/strings/str_cat.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 8 | #include "quic/platform/api/quic_bug_tracker.h" |
| 9 | #include "quic/platform/api/quic_ptr_util.h" |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 10 | |
| 11 | namespace quic { |
| 12 | |
| 13 | QuicCoalescedPacket::QuicCoalescedPacket() |
| 14 | : length_(0), max_packet_length_(0) {} |
| 15 | |
| 16 | QuicCoalescedPacket::~QuicCoalescedPacket() { |
| 17 | Clear(); |
| 18 | } |
| 19 | |
| 20 | bool 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) { |
fayang | 58f7107 | 2019-11-05 08:47:02 -0800 | [diff] [blame] | 50 | QUIC_BUG << "Max packet length changes in the middle of the write path"; |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 51 | return false; |
| 52 | } |
fayang | 9cdce50 | 2020-03-31 10:56:36 -0700 | [diff] [blame] | 53 | if (ContainsPacketOfEncryptionLevel(packet.encryption_level)) { |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 54 | // Do not coalesce packets of the same encryption level. |
| 55 | return false; |
| 56 | } |
| 57 | } |
| 58 | |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 59 | if (length_ + packet.encrypted_length > max_packet_length_) { |
| 60 | // Packet does not fit. |
| 61 | return false; |
| 62 | } |
fayang | 0875083 | 2019-10-24 11:25:34 -0700 | [diff] [blame] | 63 | QUIC_DVLOG(1) << "Successfully coalesced packet: encryption_level: " |
renjietang | b4ebb1d | 2020-05-27 18:15:51 -0700 | [diff] [blame] | 64 | << packet.encryption_level |
fayang | 0875083 | 2019-10-24 11:25:34 -0700 | [diff] [blame] | 65 | << ", encrypted_length: " << packet.encrypted_length |
| 66 | << ", current length: " << length_ |
| 67 | << ", max_packet_length: " << max_packet_length_; |
fayang | 58f7107 | 2019-11-05 08:47:02 -0800 | [diff] [blame] | 68 | if (length_ > 0) { |
| 69 | QUIC_CODE_COUNT(QUIC_SUCCESSFULLY_COALESCED_MULTIPLE_PACKETS); |
| 70 | } |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 71 | length_ += packet.encrypted_length; |
fayang | fe963c5 | 2020-07-16 06:56:09 -0700 | [diff] [blame] | 72 | transmission_types_[packet.encryption_level] = packet.transmission_type; |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 73 | 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 | |
| 86 | void 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 | } |
fayang | fe963c5 | 2020-07-16 06:56:09 -0700 | [diff] [blame] | 94 | for (size_t i = ENCRYPTION_INITIAL; i < NUM_ENCRYPTION_LEVELS; ++i) { |
| 95 | transmission_types_[i] = NOT_RETRANSMISSION; |
| 96 | } |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 97 | initial_packet_ = nullptr; |
| 98 | } |
| 99 | |
fayang | e447bc6 | 2020-08-27 13:47:11 -0700 | [diff] [blame] | 100 | void 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 | |
fayang | 0875083 | 2019-10-24 11:25:34 -0700 | [diff] [blame] | 120 | bool 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 | |
fayang | 9cdce50 | 2020-03-31 10:56:36 -0700 | [diff] [blame] | 139 | bool QuicCoalescedPacket::ContainsPacketOfEncryptionLevel( |
| 140 | EncryptionLevel level) const { |
| 141 | return !encrypted_buffers_[level].empty() || |
| 142 | (level == ENCRYPTION_INITIAL && initial_packet_ != nullptr); |
| 143 | } |
| 144 | |
fayang | fe963c5 | 2020-07-16 06:56:09 -0700 | [diff] [blame] | 145 | TransmissionType 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 | |
fayang | 9cdce50 | 2020-03-31 10:56:36 -0700 | [diff] [blame] | 155 | std::string QuicCoalescedPacket::ToString(size_t serialized_length) const { |
| 156 | // Total length and padding size. |
vasilvv | 9edb31e | 2020-12-03 19:32:58 -0800 | [diff] [blame] | 157 | std::string info = absl::StrCat( |
fayang | 9cdce50 | 2020-03-31 10:56:36 -0700 | [diff] [blame] | 158 | "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))) { |
vasilvv | 9edb31e | 2020-12-03 19:32:58 -0800 | [diff] [blame] | 164 | absl::StrAppend(&info, first_packet ? "" : ", ", |
| 165 | EncryptionLevelToString(static_cast<EncryptionLevel>(i))); |
fayang | 9cdce50 | 2020-03-31 10:56:36 -0700 | [diff] [blame] | 166 | first_packet = false; |
| 167 | } |
| 168 | } |
vasilvv | 9edb31e | 2020-12-03 19:32:58 -0800 | [diff] [blame] | 169 | absl::StrAppend(&info, "}"); |
fayang | 9cdce50 | 2020-03-31 10:56:36 -0700 | [diff] [blame] | 170 | return info; |
| 171 | } |
| 172 | |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 173 | } // namespace quic |