blob: 62eee420a1662bb5e24bc9c37f762f92e76f62b6 [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_coalesced_packet.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
namespace quic {
QuicCoalescedPacket::QuicCoalescedPacket()
: length_(0), max_packet_length_(0) {}
QuicCoalescedPacket::~QuicCoalescedPacket() {
Clear();
}
bool QuicCoalescedPacket::MaybeCoalescePacket(
const SerializedPacket& packet,
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicBufferAllocator* allocator,
QuicPacketLength current_max_packet_length) {
if (packet.encrypted_length == 0) {
QUIC_BUG << "Trying to coalesce an empty packet";
return true;
}
if (length_ == 0) {
#ifndef NDEBUG
for (const auto& buffer : encrypted_buffers_) {
DCHECK(buffer.empty());
}
#endif
DCHECK(initial_packet_ == nullptr);
// This is the first packet, set max_packet_length and self/peer
// addresses.
max_packet_length_ = current_max_packet_length;
self_address_ = self_address;
peer_address_ = peer_address;
} else {
if (self_address_ != self_address || peer_address_ != peer_address) {
// Do not coalesce packet with different self/peer addresses.
QUIC_DLOG(INFO)
<< "Cannot coalesce packet because self/peer address changed";
return false;
}
if (max_packet_length_ != current_max_packet_length) {
QUIC_DLOG(INFO)
<< "Do not try to coalesce packet when max packet length changed.";
return false;
}
if (!encrypted_buffers_[packet.encryption_level].empty() ||
(packet.encryption_level == ENCRYPTION_INITIAL &&
initial_packet_ != nullptr)) {
// Do not coalesce packets of the same encryption level.
return false;
}
}
if (packet.encryption_level == ENCRYPTION_INITIAL) {
for (const auto& frame : packet.nonretransmittable_frames) {
if (frame.type == PADDING_FRAME) {
QUIC_BUG << "ENCRYPTION_INITIAL packet should not contain padding "
"frame if trying to send coalesced packet";
return false;
}
}
}
if (length_ + packet.encrypted_length > max_packet_length_) {
// Packet does not fit.
return false;
}
length_ += packet.encrypted_length;
if (packet.encryption_level == ENCRYPTION_INITIAL) {
// Save a copy of ENCRYPTION_INITIAL packet (excluding encrypted buffer, as
// the packet will be re-serialized later).
initial_packet_ = QuicWrapUnique<SerializedPacket>(
CopySerializedPacket(packet, allocator, /*copy_buffer=*/false));
return true;
}
// Copy encrypted buffer of packets with other encryption levels.
encrypted_buffers_[packet.encryption_level] =
std::string(packet.encrypted_buffer, packet.encrypted_length);
return true;
}
void QuicCoalescedPacket::Clear() {
self_address_ = QuicSocketAddress();
peer_address_ = QuicSocketAddress();
length_ = 0;
max_packet_length_ = 0;
for (auto& packet : encrypted_buffers_) {
packet.clear();
}
if (initial_packet_ != nullptr) {
ClearSerializedPacket(initial_packet_.get());
}
initial_packet_ = nullptr;
}
} // namespace quic