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 | |
| 5 | #include "net/third_party/quiche/src/quic/core/quic_coalesced_packet.h" |
| 6 | |
| 7 | #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" |
| 8 | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| 9 | |
| 10 | namespace quic { |
| 11 | |
| 12 | QuicCoalescedPacket::QuicCoalescedPacket() |
| 13 | : length_(0), max_packet_length_(0) {} |
| 14 | |
| 15 | QuicCoalescedPacket::~QuicCoalescedPacket() { |
| 16 | Clear(); |
| 17 | } |
| 18 | |
| 19 | bool QuicCoalescedPacket::MaybeCoalescePacket( |
| 20 | const SerializedPacket& packet, |
| 21 | const QuicSocketAddress& self_address, |
| 22 | const QuicSocketAddress& peer_address, |
| 23 | QuicBufferAllocator* allocator, |
| 24 | QuicPacketLength current_max_packet_length) { |
| 25 | if (packet.encrypted_length == 0) { |
| 26 | QUIC_BUG << "Trying to coalesce an empty packet"; |
| 27 | return true; |
| 28 | } |
| 29 | if (length_ == 0) { |
| 30 | #ifndef NDEBUG |
| 31 | for (const auto& buffer : encrypted_buffers_) { |
| 32 | DCHECK(buffer.empty()); |
| 33 | } |
| 34 | #endif |
| 35 | DCHECK(initial_packet_ == nullptr); |
| 36 | // This is the first packet, set max_packet_length and self/peer |
| 37 | // addresses. |
| 38 | max_packet_length_ = current_max_packet_length; |
| 39 | self_address_ = self_address; |
| 40 | peer_address_ = peer_address; |
| 41 | } else { |
| 42 | if (self_address_ != self_address || peer_address_ != peer_address) { |
| 43 | // Do not coalesce packet with different self/peer addresses. |
| 44 | QUIC_DLOG(INFO) |
| 45 | << "Cannot coalesce packet because self/peer address changed"; |
| 46 | return false; |
| 47 | } |
| 48 | if (max_packet_length_ != current_max_packet_length) { |
fayang | 58f7107 | 2019-11-05 08:47:02 -0800 | [diff] [blame] | 49 | QUIC_BUG << "Max packet length changes in the middle of the write path"; |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 50 | return false; |
| 51 | } |
| 52 | if (!encrypted_buffers_[packet.encryption_level].empty() || |
| 53 | (packet.encryption_level == ENCRYPTION_INITIAL && |
| 54 | initial_packet_ != nullptr)) { |
| 55 | // Do not coalesce packets of the same encryption level. |
| 56 | return false; |
| 57 | } |
| 58 | } |
| 59 | |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 60 | if (length_ + packet.encrypted_length > max_packet_length_) { |
| 61 | // Packet does not fit. |
| 62 | return false; |
| 63 | } |
fayang | 0875083 | 2019-10-24 11:25:34 -0700 | [diff] [blame] | 64 | QUIC_DVLOG(1) << "Successfully coalesced packet: encryption_level: " |
| 65 | << EncryptionLevelToString(packet.encryption_level) |
| 66 | << ", encrypted_length: " << packet.encrypted_length |
| 67 | << ", current length: " << length_ |
| 68 | << ", max_packet_length: " << max_packet_length_; |
fayang | 58f7107 | 2019-11-05 08:47:02 -0800 | [diff] [blame] | 69 | if (length_ > 0) { |
| 70 | QUIC_CODE_COUNT(QUIC_SUCCESSFULLY_COALESCED_MULTIPLE_PACKETS); |
| 71 | } |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 72 | length_ += packet.encrypted_length; |
| 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 | } |
| 94 | if (initial_packet_ != nullptr) { |
| 95 | ClearSerializedPacket(initial_packet_.get()); |
| 96 | } |
| 97 | initial_packet_ = nullptr; |
| 98 | } |
| 99 | |
fayang | 0875083 | 2019-10-24 11:25:34 -0700 | [diff] [blame] | 100 | bool QuicCoalescedPacket::CopyEncryptedBuffers(char* buffer, |
| 101 | size_t buffer_len, |
| 102 | size_t* length_copied) const { |
| 103 | *length_copied = 0; |
| 104 | for (const auto& packet : encrypted_buffers_) { |
| 105 | if (packet.empty()) { |
| 106 | continue; |
| 107 | } |
| 108 | if (packet.length() > buffer_len) { |
| 109 | return false; |
| 110 | } |
| 111 | memcpy(buffer, packet.data(), packet.length()); |
| 112 | buffer += packet.length(); |
| 113 | buffer_len -= packet.length(); |
| 114 | *length_copied += packet.length(); |
| 115 | } |
| 116 | return true; |
| 117 | } |
| 118 | |
fayang | 503ca4f | 2019-10-23 07:20:51 -0700 | [diff] [blame] | 119 | } // namespace quic |