gfe-relnote: Remove QuicPacketGenerator.
Deprecate gfe2_reloadable_flag_quic_combine_generator_and_creator.
PiperOrigin-RevId: 278697040
Change-Id: I0358b83acdbb8c129b4decc40b237f3beb3b115a
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 64f7eea..adbca34 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -24,7 +24,6 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
@@ -294,10 +293,7 @@
&arena_)),
visitor_(nullptr),
debug_visitor_(nullptr),
- packet_generator_(server_connection_id_,
- &framer_,
- random_generator_,
- this),
+ packet_creator_(server_connection_id_, &framer_, random_generator_, this),
idle_network_timeout_(QuicTime::Delta::Infinite()),
handshake_timeout_(QuicTime::Delta::Infinite()),
time_of_first_packet_sent_after_receiving_(QuicTime::Zero()),
@@ -431,7 +427,7 @@
sent_packet_manager_.SetFromConfig(config);
if (config.HasReceivedBytesForConnectionId() &&
can_truncate_connection_ids_) {
- packet_generator_.SetServerConnectionIdLength(
+ packet_creator_.SetServerConnectionIdLength(
config.ReceivedBytesForConnectionId());
}
max_undecryptable_packets_ = config.max_undecryptable_packets();
@@ -665,8 +661,8 @@
<< ", received token "
<< QuicTextUtils::HexEncode(retry_token);
server_connection_id_ = new_connection_id;
- packet_generator_.SetServerConnectionId(server_connection_id_);
- packet_generator_.SetRetryToken(retry_token);
+ packet_creator_.SetServerConnectionId(server_connection_id_);
+ packet_creator_.SetRetryToken(retry_token);
// Reinstall initial crypters because the connection ID changed.
InstallInitialCrypters(server_connection_id_);
@@ -759,7 +755,7 @@
GetServerConnectionIdAsRecipient(header, perspective_)) ||
PacketCanReplaceConnectionId(header, perspective_));
- if (packet_generator_.HasPendingFrames()) {
+ if (packet_creator_.HasPendingFrames()) {
// Incoming packets may change a queued ACK frame.
const std::string error_details =
"Pending frames must be serialized before incoming packets are "
@@ -1567,7 +1563,7 @@
framer_.supported_versions())
<< "}, " << (ietf_quic ? "" : "!") << "ietf_quic";
std::unique_ptr<QuicEncryptedPacket> version_packet(
- packet_generator_.SerializeVersionNegotiationPacket(
+ packet_creator_.SerializeVersionNegotiationPacket(
ietf_quic, has_length_prefix, framer_.supported_versions()));
QUIC_DVLOG(2) << ENDPOINT << "Sending version negotiation packet: {"
<< ParsedQuicVersionVectorToString(framer_.supported_versions())
@@ -1604,7 +1600,7 @@
return 0;
}
ScopedPacketFlusher flusher(this);
- return packet_generator_.ConsumeCryptoData(level, write_length, offset);
+ return packet_creator_.ConsumeCryptoData(level, write_length, offset);
}
QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
@@ -1622,7 +1618,7 @@
// packet (a handshake packet from client to server could result in a REJ or a
// SHLO from the server, leading to two different decrypters at the server.)
ScopedPacketFlusher flusher(this);
- return packet_generator_.ConsumeData(id, write_length, offset, state);
+ return packet_creator_.ConsumeData(id, write_length, offset, state);
}
bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
@@ -1640,14 +1636,14 @@
}
ScopedPacketFlusher flusher(this);
const bool consumed =
- packet_generator_.ConsumeRetransmittableControlFrame(frame);
+ packet_creator_.ConsumeRetransmittableControlFrame(frame);
if (!consumed) {
QUIC_DVLOG(1) << ENDPOINT << "Failed to send control frame: " << frame;
return false;
}
if (frame.type == PING_FRAME) {
// Flush PING frame immediately.
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPingSent();
}
@@ -1666,9 +1662,9 @@
return;
}
// Flush stream frames of reset stream.
- if (packet_generator_.HasPendingStreamFramesOfStream(id)) {
+ if (packet_creator_.HasPendingStreamFramesOfStream(id)) {
ScopedPacketFlusher flusher(this);
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
}
// Remove all queued packets which only contain data for the reset stream.
@@ -1711,7 +1707,7 @@
stats_.srtt_us = srtt.ToMicroseconds();
stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
- stats_.max_packet_size = packet_generator_.GetCurrentMaxPacketLength();
+ stats_.max_packet_size = packet_creator_.max_packet_length();
stats_.max_received_packet_size = largest_received_packet_size_;
return stats_;
}
@@ -1950,7 +1946,7 @@
<< server_connection_id_ << " with "
<< header.source_connection_id;
server_connection_id_ = header.source_connection_id;
- packet_generator_.SetServerConnectionId(server_connection_id_);
+ packet_creator_.SetServerConnectionId(server_connection_id_);
}
if (!ValidateReceivedPacketNumber(header.packet_number)) {
@@ -1965,7 +1961,7 @@
// it should stop sending version since the version negotiation is done.
// IETF QUIC stops sending version once encryption level switches to
// forward secure.
- packet_generator_.StopSendingVersion();
+ packet_creator_.StopSendingVersion();
}
version_negotiated_ = true;
visitor_->OnSuccessfulVersionNegotiation(version());
@@ -1981,7 +1977,7 @@
if (perspective_ == Perspective::IS_SERVER &&
encryption_level_ == ENCRYPTION_INITIAL &&
- last_size_ > packet_generator_.GetCurrentMaxPacketLength()) {
+ last_size_ > packet_creator_.max_packet_length()) {
SetMaxPacketLength(last_size_);
}
return true;
@@ -2243,7 +2239,7 @@
packet->encrypted_length > long_term_mtu_;
DCHECK_LE(encrypted_length, kMaxOutgoingPacketSize);
if (!looks_like_mtu_probe) {
- DCHECK_LE(encrypted_length, packet_generator_.GetCurrentMaxPacketLength());
+ DCHECK_LE(encrypted_length, packet_creator_.max_packet_length());
}
QUIC_DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
<< (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
@@ -2279,7 +2275,7 @@
if (!coalesced_packet_.MaybeCoalescePacket(
*packet, self_address(), peer_address(),
helper_->GetStreamSendBufferAllocator(),
- packet_generator_.GetCurrentMaxPacketLength())) {
+ packet_creator_.max_packet_length())) {
// Failed to coalesce packet, flush current coalesced packet.
if (!FlushCoalescedPacket()) {
// Failed to flush coalesced packet, write error has been handled.
@@ -2288,7 +2284,7 @@
if (!coalesced_packet_.MaybeCoalescePacket(
*packet, self_address(), peer_address(),
helper_->GetStreamSendBufferAllocator(),
- packet_generator_.GetCurrentMaxPacketLength())) {
+ packet_creator_.max_packet_length())) {
// Failed to coalesce packet even it is the only packet, raise a write
// error.
QUIC_DLOG(ERROR) << ENDPOINT << "Failed to coalesce packet";
@@ -2300,7 +2296,7 @@
QUIC_DVLOG(1) << ENDPOINT << "Trying to set soft max packet length to "
<< coalesced_packet_.max_packet_length() -
coalesced_packet_.length();
- packet_generator_.SetSoftMaxPacketLength(
+ packet_creator_.SetSoftMaxPacketLength(
coalesced_packet_.max_packet_length() - coalesced_packet_.length());
}
break;
@@ -2422,7 +2418,7 @@
// The packet number length must be updated after OnPacketSent, because it
// may change the packet number length in packet.
- packet_generator_.UpdatePacketNumberLength(
+ packet_creator_.UpdatePacketNumberLength(
sent_packet_manager_.GetLeastUnacked(),
sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
@@ -2644,7 +2640,7 @@
PopulateStopWaitingFrame(&stop_waiting);
frames.push_back(QuicFrame(stop_waiting));
}
- if (!packet_generator_.FlushAckFrame(frames)) {
+ if (!packet_creator_.FlushAckFrame(frames)) {
return;
}
ResetAckStates();
@@ -2653,7 +2649,7 @@
return;
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
- if (packet_generator_.HasRetransmittableFrames() ||
+ if (packet_creator_.HasPendingRetransmittableFrames() ||
visitor_->WillingAndAbleToWrite()) {
// There are pending retransmittable frames.
return;
@@ -2672,7 +2668,7 @@
(sent_packet_manager_.handshake_mode_disabled() &&
!sent_packet_manager_.handshake_confirmed()));
const QuicPacketNumber previous_created_packet_number =
- packet_generator_.packet_number();
+ packet_creator_.packet_number();
if (close_connection_after_five_rtos_ &&
sent_packet_manager_.GetConsecutiveRtoCount() >= 4) {
// Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
@@ -2696,7 +2692,7 @@
sent_packet_manager_.pending_timer_transmission_count() == 1) {
// Skip a packet number when a single PTO packet is sent to elicit an
// immediate ACK.
- packet_generator_.SkipNPacketNumbers(
+ packet_creator_.SkipNPacketNumbers(
1, sent_packet_manager_.GetLeastUnacked(),
sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
}
@@ -2717,7 +2713,7 @@
WriteIfNotBlocked();
}
- if (packet_generator_.packet_number() == previous_created_packet_number &&
+ if (packet_creator_.packet_number() == previous_created_packet_number &&
(retransmission_mode == QuicSentPacketManager::TLP_MODE ||
retransmission_mode == QuicSentPacketManager::RTO_MODE ||
retransmission_mode == QuicSentPacketManager::PTO_MODE) &&
@@ -2743,12 +2739,12 @@
// When timer fires in TLP or RTO mode, ensure 1) at least one packet is
// created, or there is data to send and available credit (such that
// packets will be sent eventually).
- QUIC_BUG_IF(packet_generator_.packet_number() ==
+ QUIC_BUG_IF(packet_creator_.packet_number() ==
previous_created_packet_number &&
(!visitor_->WillingAndAbleToWrite() ||
sent_packet_manager_.pending_timer_transmission_count() == 0u))
<< "retransmission_mode: " << retransmission_mode
- << ", packet_number: " << packet_generator_.packet_number()
+ << ", packet_number: " << packet_creator_.packet_number()
<< ", session has data to write: " << visitor_->WillingAndAbleToWrite()
<< ", writer is blocked: " << writer_->IsWriteBlocked()
<< ", pending_timer_transmission_count: "
@@ -2766,26 +2762,26 @@
void QuicConnection::SetEncrypter(EncryptionLevel level,
std::unique_ptr<QuicEncrypter> encrypter) {
- packet_generator_.SetEncrypter(level, std::move(encrypter));
+ packet_creator_.SetEncrypter(level, std::move(encrypter));
}
void QuicConnection::SetDiversificationNonce(
const DiversificationNonce& nonce) {
DCHECK_EQ(Perspective::IS_SERVER, perspective_);
- packet_generator_.SetDiversificationNonce(nonce);
+ packet_creator_.SetDiversificationNonce(nonce);
}
void QuicConnection::SetDefaultEncryptionLevel(EncryptionLevel level) {
QUIC_DVLOG(1) << ENDPOINT << "Setting default encryption level from "
<< EncryptionLevelToString(encryption_level_) << " to "
<< EncryptionLevelToString(level);
- if (level != encryption_level_ && packet_generator_.HasPendingFrames()) {
+ if (level != encryption_level_ && packet_creator_.HasPendingFrames()) {
// Flush all queued frames when encryption level changes.
ScopedPacketFlusher flusher(this);
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
}
encryption_level_ = level;
- packet_generator_.set_encryption_level(level);
+ packet_creator_.set_encryption_level(level);
}
void QuicConnection::SetDecrypter(EncryptionLevel level,
@@ -2856,7 +2852,7 @@
while (connected_ && !undecryptable_packets_.empty()) {
// Making sure there is no pending frames when processing next undecrypted
// packet because the queued ack frame may change.
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
if (!connected_) {
return;
}
@@ -2899,7 +2895,7 @@
while (connected_ && !received_coalesced_packets_.empty()) {
// Making sure there are no pending frames when processing the next
// coalesced packet because the queued ack frame may change.
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.FlushCurrentPacket();
if (!connected_) {
return;
}
@@ -2966,8 +2962,8 @@
frame = new QuicConnectionCloseFrame(transport_version(), error, details,
framer_.current_received_frame_type());
- packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
+ packet_creator_.FlushCurrentPacket();
if (version().CanSendCoalescedPackets()) {
FlushCoalescedPacket();
}
@@ -3002,8 +2998,8 @@
auto* frame =
new QuicConnectionCloseFrame(transport_version(), error, details,
framer_.current_received_frame_type());
- packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
- packet_generator_.FlushAllQueuedFrames();
+ packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
+ packet_creator_.FlushCurrentPacket();
if (!version().CanSendCoalescedPackets()) {
ClearQueuedPackets();
}
@@ -3059,17 +3055,17 @@
}
QuicByteCount QuicConnection::max_packet_length() const {
- return packet_generator_.GetCurrentMaxPacketLength();
+ return packet_creator_.max_packet_length();
}
void QuicConnection::SetMaxPacketLength(QuicByteCount length) {
long_term_mtu_ = length;
- packet_generator_.SetMaxPacketLength(GetLimitedMaxPacketSize(length));
+ packet_creator_.SetMaxPacketLength(GetLimitedMaxPacketSize(length));
}
bool QuicConnection::HasQueuedData() const {
return pending_version_negotiation_packet_ || !queued_packets_.empty() ||
- packet_generator_.HasPendingFrames() || !buffered_packets_.empty();
+ packet_creator_.HasPendingFrames() || !buffered_packets_.empty();
}
bool QuicConnection::CanWriteStreamData() {
@@ -3226,7 +3222,7 @@
}
void QuicConnection::SetRetransmissionAlarm() {
- if (packet_generator_.PacketFlusherAttached()) {
+ if (packet_creator_.PacketFlusherAttached()) {
pending_retransmission_alarm_ = true;
return;
}
@@ -3296,9 +3292,9 @@
return;
}
- if (!connection_->packet_generator_.PacketFlusherAttached()) {
+ if (!connection_->packet_creator_.PacketFlusherAttached()) {
flush_and_set_pending_retransmission_alarm_on_delete_ = true;
- connection->packet_generator_.AttachPacketFlusher();
+ connection->packet_creator_.AttachPacketFlusher();
}
}
@@ -3337,7 +3333,7 @@
connection_->SendAck();
}
}
- connection_->packet_generator_.Flush();
+ connection_->packet_creator_.Flush();
if (connection_->version().CanSendCoalescedPackets()) {
connection_->FlushCoalescedPacket();
}
@@ -3371,7 +3367,7 @@
}
}
DCHECK_EQ(flush_and_set_pending_retransmission_alarm_on_delete_,
- !connection_->packet_generator_.PacketFlusherAttached());
+ !connection_->packet_creator_.PacketFlusherAttached());
}
QuicConnection::BufferedPacket::BufferedPacket(
@@ -3454,7 +3450,7 @@
DCHECK_EQ(target_mtu, GetLimitedMaxPacketSize(target_mtu));
// Send the probe.
- packet_generator_.GenerateMtuDiscoveryPacket(target_mtu);
+ packet_creator_.GenerateMtuDiscoveryPacket(target_mtu);
}
// TODO(zhongyi): change this method to generate a connectivity probing packet
@@ -3509,7 +3505,7 @@
if (!VersionHasIetfQuicFrames(transport_version())) {
// Non-IETF QUIC, generate a padded ping regardless of whether this is a
// request or a response.
- probing_packet = packet_generator_.SerializeConnectivityProbingPacket();
+ probing_packet = packet_creator_.SerializeConnectivityProbingPacket();
} else {
if (is_response) {
// Respond using IETF QUIC PATH_RESPONSE frame
@@ -3517,14 +3513,14 @@
// Pad the response if the request was a google connectivity probe
// (padded).
probing_packet =
- packet_generator_.SerializePathResponseConnectivityProbingPacket(
+ packet_creator_.SerializePathResponseConnectivityProbingPacket(
received_path_challenge_payloads_, /* is_padded = */ true);
received_path_challenge_payloads_.clear();
} else {
// Do not pad the response if the path challenge was not a google
// connectivity probe.
probing_packet =
- packet_generator_.SerializePathResponseConnectivityProbingPacket(
+ packet_creator_.SerializePathResponseConnectivityProbingPacket(
received_path_challenge_payloads_,
/* is_padded = */ false);
received_path_challenge_payloads_.clear();
@@ -3534,7 +3530,7 @@
transmitted_connectivity_probe_payload_ =
std::make_unique<QuicPathFrameBuffer>();
probing_packet =
- packet_generator_.SerializePathChallengeConnectivityProbingPacket(
+ packet_creator_.SerializePathChallengeConnectivityProbingPacket(
transmitted_connectivity_probe_payload_.get());
if (!probing_packet) {
transmitted_connectivity_probe_payload_ = nullptr;
@@ -3847,7 +3843,7 @@
}
void QuicConnection::SetTransmissionType(TransmissionType type) {
- packet_generator_.SetTransmissionType(type);
+ packet_creator_.SetTransmissionType(type);
}
void QuicConnection::UpdateReleaseTimeIntoFuture() {
@@ -3882,15 +3878,15 @@
return MESSAGE_STATUS_BLOCKED;
}
ScopedPacketFlusher flusher(this);
- return packet_generator_.AddMessageFrame(message_id, message);
+ return packet_creator_.AddMessageFrame(message_id, message);
}
QuicPacketLength QuicConnection::GetCurrentLargestMessagePayload() const {
- return packet_generator_.GetCurrentLargestMessagePayload();
+ return packet_creator_.GetCurrentLargestMessagePayload();
}
QuicPacketLength QuicConnection::GetGuaranteedLargestMessagePayload() const {
- return packet_generator_.GetGuaranteedLargestMessagePayload();
+ return packet_creator_.GetGuaranteedLargestMessagePayload();
}
uint32_t QuicConnection::cipher_id() const {
@@ -3953,7 +3949,7 @@
QuicFrames frames;
frames.push_back(uber_received_packet_manager_.GetUpdatedAckFrame(
static_cast<PacketNumberSpace>(i), clock_->ApproximateNow()));
- const bool flushed = packet_generator_.FlushAckFrame(frames);
+ const bool flushed = packet_creator_.FlushAckFrame(frames);
if (!flushed) {
// Connection is write blocked.
QUIC_BUG_IF(!writer_->IsWriteBlocked())
@@ -3979,7 +3975,7 @@
return;
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
- if (packet_generator_.HasRetransmittableFrames() ||
+ if (packet_creator_.HasPendingRetransmittableFrames() ||
visitor_->WillingAndAbleToWrite()) {
// There are pending retransmittable frames.
return;
@@ -3999,7 +3995,7 @@
}
QUIC_DVLOG(1) << ENDPOINT << "Sending coalesced packet";
char buffer[kMaxOutgoingPacketSize];
- const size_t length = packet_generator_.SerializeCoalescedPacket(
+ const size_t length = packet_creator_.SerializeCoalescedPacket(
coalesced_packet_, buffer, coalesced_packet_.max_packet_length());
if (length == 0) {
return false;
@@ -4176,7 +4172,7 @@
<< client_connection_id_
<< " for connection with server connection ID "
<< server_connection_id_;
- packet_generator_.SetClientConnectionId(client_connection_id_);
+ packet_creator_.SetClientConnectionId(client_connection_id_);
framer_.SetExpectedClientConnectionIdLength(client_connection_id_.length());
}
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 7bbd931..d858e3a 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -37,7 +37,6 @@
#include "net/third_party/quiche/src/quic/core/quic_mtu_discovery.h"
#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
-#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
@@ -513,12 +512,10 @@
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override;
- // QuicPacketGenerator::DelegateInterface
+ // QuicPacketCreator::DelegateInterface
bool ShouldGeneratePacket(HasRetransmittableData retransmittable,
IsHandshake handshake) override;
const QuicFrames MaybeBundleAckOpportunistically() override;
-
- // QuicPacketCreator::DelegateInterface
char* GetPacketBuffer() override;
void OnSerializedPacket(SerializedPacket* packet) override;
void OnUnrecoverableError(QuicErrorCode error,
@@ -566,7 +563,7 @@
}
// Used in Chromium, but not internally.
void set_creator_debug_delegate(QuicPacketCreator::DebugDelegate* visitor) {
- packet_generator_.set_debug_delegate(visitor);
+ packet_creator_.set_debug_delegate(visitor);
}
const QuicSocketAddress& self_address() const { return self_address_; }
const QuicSocketAddress& peer_address() const { return direct_peer_address_; }
@@ -784,9 +781,7 @@
const QuicFramer& framer() const { return framer_; }
- const QuicPacketGenerator& packet_generator() const {
- return packet_generator_;
- }
+ const QuicPacketCreator& packet_creator() const { return packet_creator_; }
EncryptionLevel encryption_level() const { return encryption_level_; }
EncryptionLevel last_decrypted_level() const {
@@ -811,11 +806,11 @@
// can only be set to false if there is some other mechanism of preventing
// amplification attacks, such as ICE (plus its a non-standard quic).
void set_fully_pad_crypto_handshake_packets(bool new_value) {
- packet_generator_.set_fully_pad_crypto_handshake_packets(new_value);
+ packet_creator_.set_fully_pad_crypto_handshake_packets(new_value);
}
bool fully_pad_during_crypto_handshake() const {
- return packet_generator_.fully_pad_crypto_handshake_packets();
+ return packet_creator_.fully_pad_crypto_handshake_packets();
}
size_t min_received_before_ack_decimation() const;
@@ -1344,7 +1339,7 @@
QuicConnectionVisitorInterface* visitor_;
QuicConnectionDebugVisitor* debug_visitor_;
- QuicPacketGenerator packet_generator_;
+ QuicPacketCreator packet_creator_;
// Network idle time before this connection is closed.
QuicTime::Delta idle_network_timeout_;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 5a2e0ef..5194a9c 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -36,7 +36,6 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
@@ -969,7 +968,6 @@
Perspective::IS_CLIENT,
version()),
creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
- generator_(QuicConnectionPeer::GetPacketGenerator(&connection_)),
manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
frame1_(0, false, 0, QuicStringPiece(data1)),
frame2_(0, false, 3, QuicStringPiece(data2)),
@@ -1625,7 +1623,6 @@
std::unique_ptr<TestPacketWriter> writer_;
TestConnection connection_;
QuicPacketCreator* creator_;
- QuicPacketGenerator* generator_;
QuicSentPacketManager* manager_;
StrictMock<MockQuicConnectionVisitor> visitor_;
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index ac467a2..b64ed3f 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -125,14 +125,9 @@
flusher_attached_(false),
fully_pad_crypto_handshake_packets_(true),
latched_hard_max_packet_length_(0),
- combine_generator_and_creator_(
- GetQuicReloadableFlag(quic_combine_generator_and_creator)),
populate_nonretransmittable_frames_(
GetQuicReloadableFlag(quic_populate_nonretransmittable_frames)) {
SetMaxPacketLength(kDefaultMaxPacketSize);
- if (combine_generator_and_creator_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_combine_generator_and_creator);
- }
if (populate_nonretransmittable_frames_) {
QUIC_RELOADABLE_FLAG_COUNT(quic_populate_nonretransmittable_frames);
}
@@ -1098,7 +1093,6 @@
bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
const QuicFrame& frame) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(IsControlFrame(frame.type) && !GetControlFrameId(frame))
<< "Adding a control frame with no control frame id: " << frame;
DCHECK(QuicUtils::IsRetransmittableFrame(frame.type)) << frame;
@@ -1126,7 +1120,6 @@
size_t write_length,
QuicStreamOffset offset,
StreamSendingState state) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write stream data.";
bool has_handshake = QuicUtils::IsCryptoStreamId(transport_version(), id);
@@ -1218,7 +1211,6 @@
QuicStreamOffset offset,
bool fin,
size_t total_bytes_consumed) {
- DCHECK(combine_generator_and_creator_);
DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
while (total_bytes_consumed < write_length &&
@@ -1239,7 +1231,6 @@
size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
size_t write_length,
QuicStreamOffset offset) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to write crypto data.";
MaybeBundleAckOpportunistically();
@@ -1277,7 +1268,6 @@
}
void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
- DCHECK(combine_generator_and_creator_);
// MTU discovery frames must be sent by themselves.
if (!CanSetMaxPacketLength()) {
QUIC_BUG << "MTU discovery packets should only be sent when no other "
@@ -1305,7 +1295,6 @@
}
void QuicPacketCreator::MaybeBundleAckOpportunistically() {
- DCHECK(combine_generator_and_creator_);
if (has_ack()) {
// Ack already queued, nothing to do.
return;
@@ -1321,7 +1310,6 @@
}
bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to send ACK frame.";
for (const auto& frame : frames) {
@@ -1346,12 +1334,10 @@
}
void QuicPacketCreator::AddRandomPadding() {
- DCHECK(combine_generator_and_creator_);
AddPendingPadding(random_->RandUint64() % kMaxNumRandomPaddingBytes + 1);
}
void QuicPacketCreator::AttachPacketFlusher() {
- DCHECK(combine_generator_and_creator_);
flusher_attached_ = true;
if (!write_start_packet_number_.IsInitialized()) {
write_start_packet_number_ = NextSendingPacketNumber();
@@ -1359,7 +1345,6 @@
}
void QuicPacketCreator::Flush() {
- DCHECK(combine_generator_and_creator_);
FlushCurrentPacket();
SendRemainingPendingPadding();
flusher_attached_ = false;
@@ -1377,7 +1362,6 @@
}
void QuicPacketCreator::SendRemainingPendingPadding() {
- DCHECK(combine_generator_and_creator_);
while (
pending_padding_bytes() > 0 && !HasPendingFrames() &&
delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)) {
@@ -1386,7 +1370,6 @@
}
void QuicPacketCreator::SetServerConnectionIdLength(uint32_t length) {
- DCHECK(combine_generator_and_creator_);
if (length == 0) {
SetServerConnectionIdIncluded(CONNECTION_ID_ABSENT);
} else {
@@ -1395,13 +1378,11 @@
}
void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
- DCHECK(combine_generator_and_creator_);
next_transmission_type_ = type;
}
MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
QuicMemSliceSpan message) {
- DCHECK(combine_generator_and_creator_);
QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
"generator tries to add message frame.";
MaybeBundleAckOpportunistically();
@@ -1809,7 +1790,6 @@
}
bool QuicPacketCreator::PacketFlusherAttached() const {
- DCHECK(combine_generator_and_creator_);
return flusher_attached_;
}
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
index b8240c1..7460502 100644
--- a/quic/core/quic_packet_creator.h
+++ b/quic/core/quic_packet_creator.h
@@ -2,8 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Accumulates frames for the next packet until more frames no longer fit or
-// it's time to create a packet from them.
+// Responsible for creating packets on behalf of a QuicConnection.
+// Packets are serialized just-in-time. Stream data and control frames will be
+// requested from the Connection just-in-time. Frames are accumulated into
+// "current" packet until no more frames can fit, then current packet gets
+// serialized and passed to connection via OnSerializedPacket().
+//
+// Whether a packet should be serialized is determined by whether delegate is
+// writable. If the Delegate is not writable, then no operations will cause
+// a packet to be serialized.
#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_
#define QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_
@@ -377,19 +384,13 @@
bool PacketFlusherAttached() const;
void set_fully_pad_crypto_handshake_packets(bool new_value) {
- DCHECK(combine_generator_and_creator_);
fully_pad_crypto_handshake_packets_ = new_value;
}
bool fully_pad_crypto_handshake_packets() const {
- DCHECK(combine_generator_and_creator_);
return fully_pad_crypto_handshake_packets_;
}
- bool combine_generator_and_creator() const {
- return combine_generator_and_creator_;
- }
-
// Serialize a probing packet that uses IETF QUIC's PATH CHALLENGE frame. Also
// fills the packet with padding.
size_t BuildPaddedPathChallengePacket(const QuicPacketHeader& header,
@@ -592,9 +593,6 @@
// set to a soft value.
QuicByteCount latched_hard_max_packet_length_;
- // Latched value of quic_combine_generator_and_creator.
- const bool combine_generator_and_creator_;
-
// Latched value of quic_populate_nonretransmittable_frames.
const bool populate_nonretransmittable_frames_;
};
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 4efcbfe..25161e1 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -30,6 +30,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
+#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
using testing::_;
using testing::DoAll;
@@ -2239,6 +2240,1495 @@
EXPECT_TRUE(creator_.HasPendingFrames());
}
+class MockDelegate : public QuicPacketCreator::DelegateInterface {
+ public:
+ MockDelegate() {}
+ MockDelegate(const MockDelegate&) = delete;
+ MockDelegate& operator=(const MockDelegate&) = delete;
+ ~MockDelegate() override {}
+
+ MOCK_METHOD2(ShouldGeneratePacket,
+ bool(HasRetransmittableData retransmittable,
+ IsHandshake handshake));
+ MOCK_METHOD0(MaybeBundleAckOpportunistically, const QuicFrames());
+ MOCK_METHOD0(GetPacketBuffer, char*());
+ MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
+ MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, const std::string&));
+
+ void SetCanWriteAnything() {
+ EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
+ .WillRepeatedly(Return(true));
+ }
+
+ void SetCanNotWrite() {
+ EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
+ .WillRepeatedly(Return(false));
+ }
+
+ // Use this when only ack frames should be allowed to be written.
+ void SetCanWriteOnlyNonRetransmittable() {
+ EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
+ .WillRepeatedly(Return(true));
+ }
+};
+
+// Simple struct for describing the contents of a packet.
+// Useful in conjunction with a SimpleQuicFrame for validating that a packet
+// contains the expected frames.
+struct PacketContents {
+ PacketContents()
+ : num_ack_frames(0),
+ num_connection_close_frames(0),
+ num_goaway_frames(0),
+ num_rst_stream_frames(0),
+ num_stop_waiting_frames(0),
+ num_stream_frames(0),
+ num_crypto_frames(0),
+ num_ping_frames(0),
+ num_mtu_discovery_frames(0),
+ num_padding_frames(0) {}
+
+ size_t num_ack_frames;
+ size_t num_connection_close_frames;
+ size_t num_goaway_frames;
+ size_t num_rst_stream_frames;
+ size_t num_stop_waiting_frames;
+ size_t num_stream_frames;
+ size_t num_crypto_frames;
+ size_t num_ping_frames;
+ size_t num_mtu_discovery_frames;
+ size_t num_padding_frames;
+};
+
+class MultiplePacketsTestPacketCreator : public QuicPacketCreator {
+ public:
+ MultiplePacketsTestPacketCreator(
+ QuicConnectionId connection_id,
+ QuicFramer* framer,
+ QuicRandom* random_generator,
+ QuicPacketCreator::DelegateInterface* delegate,
+ SimpleDataProducer* producer)
+ : QuicPacketCreator(connection_id, framer, random_generator, delegate),
+ ack_frame_(InitAckFrame(1)),
+ delegate_(static_cast<MockDelegate*>(delegate)),
+ producer_(producer) {}
+
+ bool ConsumeRetransmittableControlFrame(const QuicFrame& frame,
+ bool bundle_ack) {
+ if (!has_ack()) {
+ QuicFrames frames;
+ if (bundle_ack) {
+ frames.push_back(QuicFrame(&ack_frame_));
+ }
+ if (delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically())
+ .WillOnce(Return(frames));
+ }
+ }
+ return QuicPacketCreator::ConsumeRetransmittableControlFrame(frame);
+ }
+
+ QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ size_t total_length,
+ QuicStreamOffset offset,
+ bool fin) {
+ // Save data before data is consumed.
+ if (total_length > 0) {
+ producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
+ }
+ return QuicPacketCreator::ConsumeDataFastPath(id, total_length, offset, fin,
+ 0);
+ }
+
+ QuicConsumedData ConsumeData(QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ size_t total_length,
+ QuicStreamOffset offset,
+ StreamSendingState state) {
+ // Save data before data is consumed.
+ if (total_length > 0) {
+ producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
+ }
+ if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
+ }
+ return QuicPacketCreator::ConsumeData(id, total_length, offset, state);
+ }
+
+ MessageStatus AddMessageFrame(QuicMessageId message_id,
+ QuicMemSliceSpan message) {
+ if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
+ }
+ return QuicPacketCreator::AddMessageFrame(message_id, message);
+ }
+
+ size_t ConsumeCryptoData(EncryptionLevel level,
+ QuicStringPiece data,
+ QuicStreamOffset offset) {
+ producer_->SaveCryptoData(level, offset, data);
+ if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE)) {
+ EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
+ }
+ return QuicPacketCreator::ConsumeCryptoData(level, data.length(), offset);
+ }
+
+ QuicAckFrame ack_frame_;
+ MockDelegate* delegate_;
+ SimpleDataProducer* producer_;
+};
+
+class QuicPacketCreatorMultiplePacketsTest : public QuicTest {
+ public:
+ QuicPacketCreatorMultiplePacketsTest()
+ : framer_(AllSupportedVersions(),
+ QuicTime::Zero(),
+ Perspective::IS_CLIENT,
+ kQuicDefaultConnectionIdLength),
+ creator_(TestConnectionId(),
+ &framer_,
+ &random_creator_,
+ &delegate_,
+ &producer_),
+ ack_frame_(InitAckFrame(1)) {
+ EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
+ creator_.SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
+ creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE);
+ framer_.set_data_producer(&producer_);
+ if (simple_framer_.framer()->version().KnowsWhichDecrypterToUse()) {
+ simple_framer_.framer()->InstallDecrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
+ }
+ creator_.AttachPacketFlusher();
+ }
+
+ ~QuicPacketCreatorMultiplePacketsTest() override {
+ for (SerializedPacket& packet : packets_) {
+ delete[] packet.encrypted_buffer;
+ ClearSerializedPacket(&packet);
+ }
+ }
+
+ void SavePacket(SerializedPacket* packet) {
+ packet->encrypted_buffer = CopyBuffer(*packet);
+ packets_.push_back(*packet);
+ packet->encrypted_buffer = nullptr;
+ packet->retransmittable_frames.clear();
+ }
+
+ protected:
+ QuicRstStreamFrame* CreateRstStreamFrame() {
+ return new QuicRstStreamFrame(1, 1, QUIC_STREAM_NO_ERROR, 0);
+ }
+
+ QuicGoAwayFrame* CreateGoAwayFrame() {
+ return new QuicGoAwayFrame(2, QUIC_NO_ERROR, 1, std::string());
+ }
+
+ void CheckPacketContains(const PacketContents& contents,
+ size_t packet_index) {
+ ASSERT_GT(packets_.size(), packet_index);
+ const SerializedPacket& packet = packets_[packet_index];
+ size_t num_retransmittable_frames =
+ contents.num_connection_close_frames + contents.num_goaway_frames +
+ contents.num_rst_stream_frames + contents.num_stream_frames +
+ contents.num_crypto_frames + contents.num_ping_frames;
+ size_t num_frames =
+ contents.num_ack_frames + contents.num_stop_waiting_frames +
+ contents.num_mtu_discovery_frames + contents.num_padding_frames +
+ num_retransmittable_frames;
+
+ if (num_retransmittable_frames == 0) {
+ ASSERT_TRUE(packet.retransmittable_frames.empty());
+ } else {
+ ASSERT_FALSE(packet.retransmittable_frames.empty());
+ EXPECT_EQ(num_retransmittable_frames,
+ packet.retransmittable_frames.size());
+ }
+
+ ASSERT_TRUE(packet.encrypted_buffer != nullptr);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(
+ QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
+ size_t num_padding_frames = 0;
+ if (contents.num_padding_frames == 0) {
+ num_padding_frames = simple_framer_.padding_frames().size();
+ }
+ EXPECT_EQ(num_frames + num_padding_frames, simple_framer_.num_frames());
+ EXPECT_EQ(contents.num_ack_frames, simple_framer_.ack_frames().size());
+ EXPECT_EQ(contents.num_connection_close_frames,
+ simple_framer_.connection_close_frames().size());
+ EXPECT_EQ(contents.num_goaway_frames,
+ simple_framer_.goaway_frames().size());
+ EXPECT_EQ(contents.num_rst_stream_frames,
+ simple_framer_.rst_stream_frames().size());
+ EXPECT_EQ(contents.num_stream_frames,
+ simple_framer_.stream_frames().size());
+ EXPECT_EQ(contents.num_crypto_frames,
+ simple_framer_.crypto_frames().size());
+ EXPECT_EQ(contents.num_stop_waiting_frames,
+ simple_framer_.stop_waiting_frames().size());
+ if (contents.num_padding_frames != 0) {
+ EXPECT_EQ(contents.num_padding_frames,
+ simple_framer_.padding_frames().size());
+ }
+
+ // From the receiver's perspective, MTU discovery frames are ping frames.
+ EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames,
+ simple_framer_.ping_frames().size());
+ }
+
+ void CheckPacketHasSingleStreamFrame(size_t packet_index) {
+ ASSERT_GT(packets_.size(), packet_index);
+ const SerializedPacket& packet = packets_[packet_index];
+ ASSERT_FALSE(packet.retransmittable_frames.empty());
+ EXPECT_EQ(1u, packet.retransmittable_frames.size());
+ ASSERT_TRUE(packet.encrypted_buffer != nullptr);
+ ASSERT_TRUE(simple_framer_.ProcessPacket(
+ QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
+ EXPECT_EQ(1u, simple_framer_.num_frames());
+ EXPECT_EQ(1u, simple_framer_.stream_frames().size());
+ }
+
+ void CheckAllPacketsHaveSingleStreamFrame() {
+ for (size_t i = 0; i < packets_.size(); i++) {
+ CheckPacketHasSingleStreamFrame(i);
+ }
+ }
+
+ void CreateData(size_t len) {
+ data_array_.reset(new char[len]);
+ memset(data_array_.get(), '?', len);
+ iov_.iov_base = data_array_.get();
+ iov_.iov_len = len;
+ }
+
+ QuicFramer framer_;
+ MockRandom random_creator_;
+ StrictMock<MockDelegate> delegate_;
+ MultiplePacketsTestPacketCreator creator_;
+ SimpleQuicFramer simple_framer_;
+ std::vector<SerializedPacket> packets_;
+ QuicAckFrame ack_frame_;
+ struct iovec iov_;
+ SimpleBufferAllocator allocator_;
+
+ private:
+ std::unique_ptr<char[]> data_array_;
+ SimpleDataProducer producer_;
+};
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, AddControlFrame_NotWritable) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ delete rst_frame;
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, AddControlFrame_OnlyAckWritable) {
+ delegate_.SetCanWriteOnlyNonRetransmittable();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ delete rst_frame;
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ AddControlFrame_WritableAndShouldNotFlush) {
+ delegate_.SetCanWriteAnything();
+
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/false);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ AddControlFrame_NotWritableBatchThenFlush) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ delete rst_frame;
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ AddControlFrame_WritableAndShouldFlush) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/false);
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_rst_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeCryptoData) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ std::string data = "crypto data";
+ size_t consumed_bytes =
+ creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
+ creator_.Flush();
+ EXPECT_EQ(data.length(), consumed_bytes);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_crypto_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_NotWritable) {
+ delegate_.SetCanNotWrite();
+
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(0u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_WritableAndShouldNotFlush) {
+ delegate_.SetCanWriteAnything();
+
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_WritableAndShouldFlush) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ creator_.Flush();
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+// Test the behavior of ConsumeData when the data consumed is for the crypto
+// handshake stream. Ensure that the packet is always sent and padded even if
+// the creator operates in batch mode.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_Handshake) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ std::string data = "foo bar";
+ MakeIOVector(data, &iov_);
+ size_t consumed_bytes = 0;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ consumed_bytes = creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
+ } else {
+ consumed_bytes =
+ creator_
+ .ConsumeData(
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN)
+ .bytes_consumed;
+ }
+ EXPECT_EQ(7u, consumed_bytes);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ contents.num_crypto_frames = 1;
+ } else {
+ contents.num_stream_frames = 1;
+ }
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ ASSERT_EQ(1u, packets_.size());
+ ASSERT_EQ(kDefaultMaxPacketSize, creator_.max_packet_length());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+}
+
+// Test the behavior of ConsumeData when the data is for the crypto handshake
+// stream, but padding is disabled.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_Handshake_PaddingDisabled) {
+ creator_.set_fully_pad_crypto_handshake_packets(false);
+
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ std::string data = "foo";
+ MakeIOVector(data, &iov_);
+ size_t bytes_consumed = 0;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ bytes_consumed = creator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
+ } else {
+ bytes_consumed =
+ creator_
+ .ConsumeData(
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN)
+ .bytes_consumed;
+ }
+ EXPECT_EQ(3u, bytes_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ contents.num_crypto_frames = 1;
+ } else {
+ contents.num_stream_frames = 1;
+ }
+ contents.num_padding_frames = 0;
+ CheckPacketContains(contents, 0);
+
+ ASSERT_EQ(1u, packets_.size());
+
+ // Packet is not fully padded, but we want to future packets to be larger.
+ ASSERT_EQ(kDefaultMaxPacketSize, creator_.max_packet_length());
+ size_t expected_packet_length = 27;
+ if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
+ // The framing of CRYPTO frames is slightly different than that of stream
+ // frames, so the expected packet length differs slightly.
+ expected_packet_length = 28;
+ }
+ if (framer_.version().HasHeaderProtection()) {
+ expected_packet_length = 29;
+ }
+ EXPECT_EQ(expected_packet_length, packets_[0].encrypted_length);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_EmptyData) {
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_QUIC_BUG(creator_.ConsumeData(
+ QuicUtils::QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ nullptr, 0, 0, 0, NO_FIN),
+ "Attempt to consume empty data without FIN.");
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeDataMultipleTimes_WritableAndShouldNotFlush) {
+ delegate_.SetCanWriteAnything();
+
+ MakeIOVector("foo", &iov_);
+ creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ MakeIOVector("quux", &iov_);
+ QuicConsumedData consumed =
+ creator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 3, NO_FIN);
+ EXPECT_EQ(4u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeData_BatchOperations) {
+ delegate_.SetCanWriteAnything();
+
+ MakeIOVector("foo", &iov_);
+ creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ MakeIOVector("quux", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 3, FIN);
+ EXPECT_EQ(4u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Now both frames will be flushed out.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames =
+ GetQuicReloadableFlag(quic_coalesce_stream_frames) ? 1 : 2;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConsumeData_FramesPreviouslyQueued) {
+ // Set the packet size be enough for two stream frames with 0 stream offset,
+ // but not enough for a stream frame of 0 offset and one with non-zero offset.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ // Add an extra 3 bytes for the payload and 1 byte so
+ // BytesFree is larger than the GetMinStreamFrameSize.
+ QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0,
+ false, 3) +
+ 3 +
+ QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0, true,
+ 1) +
+ 1;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ {
+ InSequence dummy;
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ }
+ // Queue enough data to prevent a stream frame with a non-zero offset from
+ // fitting.
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // This frame will not fit with the existing frame, causing the queued frame
+ // to be serialized, and it will be added to a new open packet.
+ MakeIOVector("bar", &iov_);
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 3, FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ creator_.FlushCurrentPacket();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+ CheckPacketContains(contents, 1);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataFastPath) {
+ delegate_.SetCanWriteAnything();
+ creator_.SetTransmissionType(LOSS_RETRANSMISSION);
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ QuicConsumedData consumed = creator_.ConsumeDataFastPath(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, true);
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(LOSS_RETRANSMISSION, packet.transmission_type);
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataLarge) {
+ delegate_.SetCanWriteAnything();
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataLargeSendAckFalse) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool success =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ delegate_.SetCanWriteAnything();
+
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false);
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateRstStreamFrame()),
+ /*bundle_ack=*/true);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ creator_.Flush();
+
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConsumeDataLargeSendAckTrue) {
+ if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
+ return;
+ }
+ delegate_.SetCanNotWrite();
+ delegate_.SetCanWriteAnything();
+
+ // Create a 10000 byte IOVector.
+ CreateData(10000);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ creator_.Flush();
+
+ EXPECT_EQ(10000u, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_FALSE(packets_.empty());
+ SerializedPacket packet = packets_.back();
+ EXPECT_TRUE(!packet.retransmittable_frames.empty());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ const QuicStreamFrame& stream_frame =
+ packet.retransmittable_frames.front().stream_frame;
+ EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, NotWritableThenBatchOperations) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool consumed =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ EXPECT_FALSE(consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(3));
+
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_TRUE(
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false));
+ // Send some data and a control frame
+ MakeIOVector("quux", &iov_);
+ creator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateGoAwayFrame()),
+ /*bundle_ack=*/false);
+ }
+ EXPECT_TRUE(creator_.HasPendingStreamFramesOfStream(3));
+
+ // All five frames will be flushed out in a single packet.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ EXPECT_FALSE(creator_.HasPendingStreamFramesOfStream(3));
+
+ PacketContents contents;
+ // ACK will be flushed by connection.
+ contents.num_ack_frames = 0;
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ contents.num_goaway_frames = 1;
+ } else {
+ contents.num_goaway_frames = 0;
+ }
+ contents.num_rst_stream_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, NotWritableThenBatchOperations2) {
+ delegate_.SetCanNotWrite();
+
+ QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
+ const bool success =
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/true);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ delegate_.SetCanWriteAnything();
+
+ {
+ InSequence dummy;
+ // All five frames will be flushed out in a single packet
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ }
+ EXPECT_TRUE(
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
+ /*bundle_ack=*/false));
+ // Send enough data to exceed one packet
+ size_t data_len = kDefaultMaxPacketSize + 100;
+ CreateData(data_len);
+ QuicConsumedData consumed =
+ creator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(CreateGoAwayFrame()),
+ /*bundle_ack=*/false);
+ }
+
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // The first packet should have the queued data and part of the stream data.
+ PacketContents contents;
+ // ACK will be sent by connection.
+ contents.num_ack_frames = 0;
+ contents.num_rst_stream_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ // The second should have the remainder of the stream data.
+ PacketContents contents2;
+ if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
+ contents2.num_goaway_frames = 1;
+ } else {
+ contents2.num_goaway_frames = 0;
+ }
+ contents2.num_stream_frames = 1;
+ CheckPacketContains(contents2, 1);
+}
+
+// Regression test of b/120493795.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, PacketTransmissionType) {
+ delegate_.SetCanWriteAnything();
+
+ // The first ConsumeData will fill the packet without flush.
+ creator_.SetTransmissionType(LOSS_RETRANSMISSION);
+
+ size_t data_len = 1324;
+ CreateData(data_len);
+ QuicStreamId stream1_id = QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT);
+ QuicConsumedData consumed =
+ creator_.ConsumeData(stream1_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ ASSERT_EQ(0u, creator_.BytesFree())
+ << "Test setup failed: Please increase data_len to "
+ << data_len + creator_.BytesFree() << " bytes.";
+
+ // The second ConsumeData can not be added to the packet and will flush.
+ creator_.SetTransmissionType(NOT_RETRANSMISSION);
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ QuicStreamId stream2_id = stream1_id + 4;
+
+ consumed =
+ creator_.ConsumeData(stream2_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+
+ // Ensure the packet is successfully created.
+ ASSERT_EQ(1u, packets_.size());
+ ASSERT_TRUE(packets_[0].encrypted_buffer);
+ ASSERT_EQ(1u, packets_[0].retransmittable_frames.size());
+ EXPECT_EQ(stream1_id,
+ packets_[0].retransmittable_frames[0].stream_frame.stream_id);
+
+ // Since the second frame was not added, the packet's transmission type
+ // should be the first frame's type.
+ EXPECT_EQ(packets_[0].transmission_type, LOSS_RETRANSMISSION);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, TestConnectionIdLength) {
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ creator_.SetServerConnectionIdLength(0);
+ EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
+ creator_.GetDestinationConnectionIdLength());
+
+ for (size_t i = 1; i < 10; i++) {
+ creator_.SetServerConnectionIdLength(i);
+ if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
+ EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
+ creator_.GetDestinationConnectionIdLength());
+ } else {
+ EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID,
+ creator_.GetDestinationConnectionIdLength());
+ }
+ }
+}
+
+// Test whether SetMaxPacketLength() works in the situation when the queue is
+// empty, and we send three packets worth of data.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, SetMaxPacketLength_Initial) {
+ delegate_.SetCanWriteAnything();
+
+ // Send enough data for three packets.
+ size_t data_len = 3 * kDefaultMaxPacketSize + 1;
+ size_t packet_len = kDefaultMaxPacketSize + 100;
+ ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
+ creator_.SetMaxPacketLength(packet_len);
+ EXPECT_EQ(packet_len, creator_.max_packet_length());
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .Times(3)
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ CreateData(data_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, FIN);
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect three packets, and first two of them have to be of packet_len
+ // size. We check multiple packets (instead of just one) because we want to
+ // ensure that |max_packet_length_| does not get changed incorrectly by the
+ // creator after first packet is serialized.
+ ASSERT_EQ(3u, packets_.size());
+ EXPECT_EQ(packet_len, packets_[0].encrypted_length);
+ EXPECT_EQ(packet_len, packets_[1].encrypted_length);
+ CheckAllPacketsHaveSingleStreamFrame();
+}
+
+// Test whether SetMaxPacketLength() works in the situation when we first write
+// data, then change packet size, then write data again.
+TEST_F(QuicPacketCreatorMultiplePacketsTest, SetMaxPacketLength_Middle) {
+ delegate_.SetCanWriteAnything();
+
+ // We send enough data to overflow default packet length, but not the altered
+ // one.
+ size_t data_len = kDefaultMaxPacketSize;
+ size_t packet_len = kDefaultMaxPacketSize + 100;
+ ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
+
+ // We expect to see three packets in total.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .Times(3)
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Send two packets before packet size change.
+ CreateData(data_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, NO_FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // Make sure we already have two packets.
+ ASSERT_EQ(2u, packets_.size());
+
+ // Increase packet size.
+ creator_.SetMaxPacketLength(packet_len);
+ EXPECT_EQ(packet_len, creator_.max_packet_length());
+
+ // Send a packet after packet size change.
+ CreateData(data_len);
+ creator_.AttachPacketFlusher();
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, data_len, FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect first data chunk to get fragmented, but the second one to fit
+ // into a single packet.
+ ASSERT_EQ(3u, packets_.size());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_LE(kDefaultMaxPacketSize, packets_[2].encrypted_length);
+ CheckAllPacketsHaveSingleStreamFrame();
+}
+
+// Test whether SetMaxPacketLength() works correctly when we force the change of
+// the packet size in the middle of the batched packet.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ SetMaxPacketLength_MidpacketFlush) {
+ delegate_.SetCanWriteAnything();
+
+ size_t first_write_len = kDefaultMaxPacketSize / 2;
+ size_t packet_len = kDefaultMaxPacketSize + 100;
+ size_t second_write_len = packet_len + 1;
+ ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
+
+ // First send half of the packet worth of data. We are in the batch mode, so
+ // should not cause packet serialization.
+ CreateData(first_write_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, NO_FIN);
+ EXPECT_EQ(first_write_len, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Make sure we have no packets so far.
+ ASSERT_EQ(0u, packets_.size());
+
+ // Expect a packet to be flushed.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Increase packet size after flushing all frames.
+ // Ensure it's immediately enacted.
+ creator_.FlushCurrentPacket();
+ creator_.SetMaxPacketLength(packet_len);
+ EXPECT_EQ(packet_len, creator_.max_packet_length());
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect to see exactly one packet serialized after that, because we send
+ // a value somewhat exceeding new max packet size, and the tail data does not
+ // get serialized because we are still in the batch mode.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Send a more than a packet worth of data to the same stream. This should
+ // trigger serialization of one packet, and queue another one.
+ CreateData(second_write_len);
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/first_write_len, FIN);
+ EXPECT_EQ(second_write_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // We expect the first packet to be underfilled, and the second packet be up
+ // to the new max packet size.
+ ASSERT_EQ(2u, packets_.size());
+ EXPECT_GT(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_EQ(packet_len, packets_[1].encrypted_length);
+
+ CheckAllPacketsHaveSingleStreamFrame();
+}
+
+// Test sending a connectivity probing packet.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ GenerateConnectivityProbingPacket) {
+ delegate_.SetCanWriteAnything();
+
+ OwningSerializedPacketPointer probing_packet;
+ if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+ QuicPathFrameBuffer payload = {
+ {0xde, 0xad, 0xbe, 0xef, 0xba, 0xdc, 0x0f, 0xfe}};
+ probing_packet =
+ creator_.SerializePathChallengeConnectivityProbingPacket(&payload);
+ } else {
+ probing_packet = creator_.SerializeConnectivityProbingPacket();
+ }
+
+ ASSERT_TRUE(simple_framer_.ProcessPacket(QuicEncryptedPacket(
+ probing_packet->encrypted_buffer, probing_packet->encrypted_length)));
+
+ EXPECT_EQ(2u, simple_framer_.num_frames());
+ if (VersionHasIetfQuicFrames(framer_.transport_version())) {
+ EXPECT_EQ(1u, simple_framer_.path_challenge_frames().size());
+ } else {
+ EXPECT_EQ(1u, simple_framer_.ping_frames().size());
+ }
+ EXPECT_EQ(1u, simple_framer_.padding_frames().size());
+}
+
+// Test sending an MTU probe, without any surrounding data.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ GenerateMtuDiscoveryPacket_Simple) {
+ delegate_.SetCanWriteAnything();
+
+ const size_t target_mtu = kDefaultMaxPacketSize + 100;
+ static_assert(target_mtu < kMaxOutgoingPacketSize,
+ "The MTU probe used by the test exceeds maximum packet size");
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ creator_.GenerateMtuDiscoveryPacket(target_mtu);
+
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+ ASSERT_EQ(1u, packets_.size());
+ EXPECT_EQ(target_mtu, packets_[0].encrypted_length);
+
+ PacketContents contents;
+ contents.num_mtu_discovery_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+// Test sending an MTU probe. Surround it with data, to ensure that it resets
+// the MTU to the value before the probe was sent.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ GenerateMtuDiscoveryPacket_SurroundedByData) {
+ delegate_.SetCanWriteAnything();
+
+ const size_t target_mtu = kDefaultMaxPacketSize + 100;
+ static_assert(target_mtu < kMaxOutgoingPacketSize,
+ "The MTU probe used by the test exceeds maximum packet size");
+
+ // Send enough data so it would always cause two packets to be sent.
+ const size_t data_len = target_mtu + 1;
+
+ // Send a total of five packets: two packets before the probe, the probe
+ // itself, and two packets after the probe.
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .Times(5)
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ // Send data before the MTU probe.
+ CreateData(data_len);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/0, NO_FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_FALSE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // Send the MTU probe.
+ creator_.GenerateMtuDiscoveryPacket(target_mtu);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ // Send data after the MTU probe.
+ CreateData(data_len);
+ creator_.AttachPacketFlusher();
+ consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len,
+ /*offset=*/data_len, FIN);
+ creator_.Flush();
+ EXPECT_EQ(data_len, consumed.bytes_consumed);
+ EXPECT_TRUE(consumed.fin_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ ASSERT_EQ(5u, packets_.size());
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
+ EXPECT_EQ(target_mtu, packets_[2].encrypted_length);
+ EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].encrypted_length);
+
+ PacketContents probe_contents;
+ probe_contents.num_mtu_discovery_frames = 1;
+ probe_contents.num_padding_frames = 1;
+
+ CheckPacketHasSingleStreamFrame(0);
+ CheckPacketHasSingleStreamFrame(1);
+ CheckPacketContains(probe_contents, 2);
+ CheckPacketHasSingleStreamFrame(3);
+ CheckPacketHasSingleStreamFrame(4);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, DontCrashOnInvalidStopWaiting) {
+ if (VersionSupportsMessageFrames(framer_.transport_version())) {
+ return;
+ }
+ // Test added to ensure the creator does not crash when an invalid frame is
+ // added. Because this is an indication of internal programming errors,
+ // DFATALs are expected.
+ // A 1 byte packet number length can't encode a gap of 1000.
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 1000);
+
+ delegate_.SetCanNotWrite();
+ delegate_.SetCanWriteAnything();
+
+ // This will not serialize any packets, because of the invalid frame.
+ EXPECT_CALL(delegate_,
+ OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _));
+ EXPECT_QUIC_BUG(creator_.Flush(),
+ "packet_number_length 1 is too small "
+ "for least_unacked_delta: 1001");
+}
+
+// Regression test for b/31486443.
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ ConnectionCloseFrameLargerThanPacketSize) {
+ delegate_.SetCanWriteAnything();
+ char buf[2000] = {};
+ QuicStringPiece error_details(buf, 2000);
+ const QuicErrorCode kQuicErrorCode = QUIC_PACKET_WRITE_ERROR;
+
+ QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
+ framer_.transport_version(), kQuicErrorCode, std::string(error_details),
+ /*transport_close_frame_type=*/0);
+ creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame),
+ /*bundle_ack=*/false);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ RandomPaddingAfterFinSingleStreamSinglePacket) {
+ const QuicByteCount kStreamFramePayloadSize = 100u;
+ char buf[kStreamFramePayloadSize] = {};
+ const QuicStreamId kDataStreamId = 5;
+ // Set the packet size be enough for one stream frame with 0 stream offset and
+ // max size of random padding.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ QuicFramer::GetMinStreamFrameSize(
+ framer_.transport_version(), kDataStreamId, 0,
+ /*last_frame_in_packet=*/false,
+ kStreamFramePayloadSize + kMaxNumRandomPaddingBytes) +
+ kStreamFramePayloadSize + kMaxNumRandomPaddingBytes;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
+ creator_.Flush();
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_EQ(1u, packets_.size());
+ PacketContents contents;
+ // The packet has both stream and padding frames.
+ contents.num_padding_frames = 1;
+ contents.num_stream_frames = 1;
+ CheckPacketContains(contents, 0);
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ RandomPaddingAfterFinSingleStreamMultiplePackets) {
+ const QuicByteCount kStreamFramePayloadSize = 100u;
+ char buf[kStreamFramePayloadSize] = {};
+ const QuicStreamId kDataStreamId = 5;
+ // Set the packet size be enough for one stream frame with 0 stream offset +
+ // 1. One or more packets will accommodate.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ QuicFramer::GetMinStreamFrameSize(
+ framer_.transport_version(), kDataStreamId, 0,
+ /*last_frame_in_packet=*/false, kStreamFramePayloadSize + 1) +
+ kStreamFramePayloadSize + 1;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
+ creator_.Flush();
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_LE(1u, packets_.size());
+ PacketContents contents;
+ // The first packet has both stream and padding frames.
+ contents.num_stream_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 0);
+
+ for (size_t i = 1; i < packets_.size(); ++i) {
+ // Following packets only have paddings.
+ contents.num_stream_frames = 0;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, i);
+ }
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ RandomPaddingAfterFinMultipleStreamsMultiplePackets) {
+ const QuicByteCount kStreamFramePayloadSize = 100u;
+ char buf[kStreamFramePayloadSize] = {};
+ const QuicStreamId kDataStreamId1 = 5;
+ const QuicStreamId kDataStreamId2 = 6;
+ // Set the packet size be enough for first frame with 0 stream offset + second
+ // frame + 1 byte payload. two or more packets will accommodate.
+ size_t length =
+ NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
+ GetPacketHeaderSize(
+ framer_.transport_version(),
+ creator_.GetDestinationConnectionIdLength(),
+ creator_.GetSourceConnectionIdLength(),
+ QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
+ !kIncludeDiversificationNonce,
+ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(&creator_), 0,
+ QuicPacketCreatorPeer::GetLengthLength(&creator_)) +
+ QuicFramer::GetMinStreamFrameSize(
+ framer_.transport_version(), kDataStreamId1, 0,
+ /*last_frame_in_packet=*/false, kStreamFramePayloadSize) +
+ kStreamFramePayloadSize +
+ QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
+ kDataStreamId1, 0,
+ /*last_frame_in_packet=*/false, 1) +
+ 1;
+ creator_.SetMaxPacketLength(length);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillRepeatedly(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ QuicConsumedData consumed = creator_.ConsumeData(
+ kDataStreamId1, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
+ consumed = creator_.ConsumeData(kDataStreamId2, &iov_, 1u, iov_.iov_len, 0,
+ FIN_AND_PADDING);
+ EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
+ creator_.Flush();
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ EXPECT_FALSE(creator_.HasPendingRetransmittableFrames());
+
+ EXPECT_LE(2u, packets_.size());
+ PacketContents contents;
+ // The first packet has two stream frames.
+ contents.num_stream_frames = 2;
+ CheckPacketContains(contents, 0);
+
+ // The second packet has one stream frame and padding frames.
+ contents.num_stream_frames = 1;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, 1);
+
+ for (size_t i = 2; i < packets_.size(); ++i) {
+ // Following packets only have paddings.
+ contents.num_stream_frames = 0;
+ contents.num_padding_frames = 1;
+ CheckPacketContains(contents, i);
+ }
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, AddMessageFrame) {
+ if (!VersionSupportsMessageFrames(framer_.transport_version())) {
+ return;
+ }
+ quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
+ delegate_.SetCanWriteAnything();
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(
+ Invoke(this, &QuicPacketCreatorMultiplePacketsTest::SavePacket));
+
+ MakeIOVector("foo", &iov_);
+ creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
+ framer_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(
+ MESSAGE_STATUS_SUCCESS,
+ creator_.AddMessageFrame(1, MakeSpan(&allocator_, "message", &storage)));
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Add a message which causes the flush of current packet.
+ EXPECT_EQ(
+ MESSAGE_STATUS_SUCCESS,
+ creator_.AddMessageFrame(
+ 2,
+ MakeSpan(&allocator_,
+ std::string(creator_.GetCurrentLargestMessagePayload(), 'a'),
+ &storage)));
+ EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
+
+ // Failed to send messages which cannot fit into one packet.
+ EXPECT_EQ(
+ MESSAGE_STATUS_TOO_LARGE,
+ creator_.AddMessageFrame(
+ 3, MakeSpan(&allocator_,
+ std::string(
+ creator_.GetCurrentLargestMessagePayload() + 10, 'a'),
+ &storage)));
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest, ConnectionId) {
+ creator_.SetServerConnectionId(TestConnectionId(0x1337));
+ EXPECT_EQ(TestConnectionId(0x1337), creator_.GetDestinationConnectionId());
+ EXPECT_EQ(EmptyQuicConnectionId(), creator_.GetSourceConnectionId());
+ if (!framer_.version().SupportsClientConnectionIds()) {
+ return;
+ }
+ creator_.SetClientConnectionId(TestConnectionId(0x33));
+ EXPECT_EQ(TestConnectionId(0x1337), creator_.GetDestinationConnectionId());
+ EXPECT_EQ(TestConnectionId(0x33), creator_.GetSourceConnectionId());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_packet_generator.cc b/quic/core/quic_packet_generator.cc
deleted file mode 100644
index f4a5773..0000000
--- a/quic/core/quic_packet_generator.cc
+++ /dev/null
@@ -1,553 +0,0 @@
-// Copyright (c) 2012 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_packet_generator.h"
-
-#include <cstdint>
-
-#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
-
-namespace quic {
-
-QuicPacketGenerator::QuicPacketGenerator(
- QuicConnectionId server_connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator,
- QuicPacketCreator::DelegateInterface* delegate)
- : delegate_(delegate),
- packet_creator_(server_connection_id, framer, random_generator, delegate),
- next_transmission_type_(NOT_RETRANSMISSION),
- flusher_attached_(false),
- random_generator_(random_generator),
- fully_pad_crypto_handshake_packets_(true) {}
-
-QuicPacketGenerator::~QuicPacketGenerator() {}
-
-bool QuicPacketGenerator::ConsumeRetransmittableControlFrame(
- const QuicFrame& frame) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeRetransmittableControlFrame(frame);
- }
- QUIC_BUG_IF(IsControlFrame(frame.type) && !GetControlFrameId(frame))
- << "Adding a control frame with no control frame id: " << frame;
- DCHECK(QuicUtils::IsRetransmittableFrame(frame.type)) << frame;
- MaybeBundleAckOpportunistically();
- if (packet_creator_.HasPendingFrames()) {
- if (packet_creator_.AddSavedFrame(frame, next_transmission_type_)) {
- // There is pending frames and current frame fits.
- return true;
- }
- }
- DCHECK(!packet_creator_.HasPendingFrames());
- if (frame.type != PING_FRAME && frame.type != CONNECTION_CLOSE_FRAME &&
- !delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- // Do not check congestion window for ping or connection close frames.
- return false;
- }
- const bool success =
- packet_creator_.AddSavedFrame(frame, next_transmission_type_);
- DCHECK(success);
- return success;
-}
-
-size_t QuicPacketGenerator::ConsumeCryptoData(EncryptionLevel level,
- size_t write_length,
- QuicStreamOffset offset) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeCryptoData(level, write_length, offset);
- }
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to write crypto data.";
- MaybeBundleAckOpportunistically();
- // To make reasoning about crypto frames easier, we don't combine them with
- // other retransmittable frames in a single packet.
- // TODO(nharper): Once we have separate packet number spaces, everything
- // should be driven by encryption level, and we should stop flushing in this
- // spot.
- if (packet_creator_.HasPendingRetransmittableFrames()) {
- packet_creator_.FlushCurrentPacket();
- }
-
- size_t total_bytes_consumed = 0;
-
- while (total_bytes_consumed < write_length) {
- QuicFrame frame;
- if (!packet_creator_.ConsumeCryptoDataToFillCurrentPacket(
- level, write_length - total_bytes_consumed,
- offset + total_bytes_consumed, fully_pad_crypto_handshake_packets_,
- next_transmission_type_, &frame)) {
- // The only pending data in the packet is non-retransmittable frames. I'm
- // assuming here that they won't occupy so much of the packet that a
- // CRYPTO frame won't fit.
- QUIC_BUG << "Failed to ConsumeCryptoData at level " << level;
- return 0;
- }
- total_bytes_consumed += frame.crypto_frame->data_length;
-
- // TODO(ianswett): Move to having the creator flush itself when it's full.
- packet_creator_.FlushCurrentPacket();
- }
-
- // Don't allow the handshake to be bundled with other retransmittable frames.
- packet_creator_.FlushCurrentPacket();
-
- return total_bytes_consumed;
-}
-
-QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeData(id, write_length, offset, state);
- }
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to write stream data.";
- bool has_handshake =
- QuicUtils::IsCryptoStreamId(packet_creator_.transport_version(), id);
- MaybeBundleAckOpportunistically();
- bool fin = state != NO_FIN;
- QUIC_BUG_IF(has_handshake && fin)
- << "Handshake packets should never send a fin";
- // To make reasoning about crypto frames easier, we don't combine them with
- // other retransmittable frames in a single packet.
- if (has_handshake && packet_creator_.HasPendingRetransmittableFrames()) {
- packet_creator_.FlushCurrentPacket();
- }
-
- size_t total_bytes_consumed = 0;
- bool fin_consumed = false;
-
- if (!packet_creator_.HasRoomForStreamFrame(id, offset, write_length)) {
- packet_creator_.FlushCurrentPacket();
- }
-
- if (!fin && (write_length == 0)) {
- QUIC_BUG << "Attempt to consume empty data without FIN.";
- return QuicConsumedData(0, false);
- }
- // We determine if we can enter the fast path before executing
- // the slow path loop.
- bool run_fast_path =
- !has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
- write_length - total_bytes_consumed > kMaxOutgoingPacketSize;
-
- while (!run_fast_path && delegate_->ShouldGeneratePacket(
- HAS_RETRANSMITTABLE_DATA,
- has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) {
- QuicFrame frame;
- bool needs_full_padding =
- has_handshake && fully_pad_crypto_handshake_packets_;
-
- if (!packet_creator_.ConsumeDataToFillCurrentPacket(
- id, write_length - total_bytes_consumed,
- offset + total_bytes_consumed, fin, needs_full_padding,
- next_transmission_type_, &frame)) {
- // The creator is always flushed if there's not enough room for a new
- // stream frame before ConsumeData, so ConsumeData should always succeed.
- QUIC_BUG << "Failed to ConsumeData, stream:" << id;
- return QuicConsumedData(0, false);
- }
-
- // A stream frame is created and added.
- size_t bytes_consumed = frame.stream_frame.data_length;
- total_bytes_consumed += bytes_consumed;
- fin_consumed = fin && total_bytes_consumed == write_length;
- if (fin_consumed && state == FIN_AND_PADDING) {
- AddRandomPadding();
- }
- DCHECK(total_bytes_consumed == write_length ||
- (bytes_consumed > 0 && packet_creator_.HasPendingFrames()));
-
- if (total_bytes_consumed == write_length) {
- // We're done writing the data. Exit the loop.
- // We don't make this a precondition because we could have 0 bytes of data
- // if we're simply writing a fin.
- break;
- }
- // TODO(ianswett): Move to having the creator flush itself when it's full.
- packet_creator_.FlushCurrentPacket();
-
- run_fast_path =
- !has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
- write_length - total_bytes_consumed > kMaxOutgoingPacketSize;
- }
-
- if (run_fast_path) {
- return ConsumeDataFastPath(id, write_length, offset, state != NO_FIN,
- total_bytes_consumed);
- }
-
- // Don't allow the handshake to be bundled with other retransmittable frames.
- if (has_handshake) {
- packet_creator_.FlushCurrentPacket();
- }
-
- return QuicConsumedData(total_bytes_consumed, fin_consumed);
-}
-
-QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- bool fin,
- size_t total_bytes_consumed) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.ConsumeDataFastPath(id, write_length, offset, fin,
- total_bytes_consumed);
- }
- DCHECK(!QuicUtils::IsCryptoStreamId(packet_creator_.transport_version(), id));
-
- while (total_bytes_consumed < write_length &&
- delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- // Serialize and encrypt the packet.
- size_t bytes_consumed = 0;
- packet_creator_.CreateAndSerializeStreamFrame(
- id, write_length, total_bytes_consumed, offset + total_bytes_consumed,
- fin, next_transmission_type_, &bytes_consumed);
- total_bytes_consumed += bytes_consumed;
- }
-
- return QuicConsumedData(total_bytes_consumed,
- fin && (total_bytes_consumed == write_length));
-}
-
-void QuicPacketGenerator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.GenerateMtuDiscoveryPacket(target_mtu);
- return;
- }
- // MTU discovery frames must be sent by themselves.
- if (!packet_creator_.CanSetMaxPacketLength()) {
- QUIC_BUG << "MTU discovery packets should only be sent when no other "
- << "frames needs to be sent.";
- return;
- }
- const QuicByteCount current_mtu = GetCurrentMaxPacketLength();
-
- // The MTU discovery frame is allocated on the stack, since it is going to be
- // serialized within this function.
- QuicMtuDiscoveryFrame mtu_discovery_frame;
- QuicFrame frame(mtu_discovery_frame);
-
- // Send the probe packet with the new length.
- SetMaxPacketLength(target_mtu);
- const bool success =
- packet_creator_.AddPaddedSavedFrame(frame, next_transmission_type_);
- packet_creator_.FlushCurrentPacket();
- // The only reason AddFrame can fail is that the packet is too full to fit in
- // a ping. This is not possible for any sane MTU.
- DCHECK(success);
-
- // Reset the packet length back.
- SetMaxPacketLength(current_mtu);
-}
-
-bool QuicPacketGenerator::PacketFlusherAttached() const {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.PacketFlusherAttached();
- }
- return flusher_attached_;
-}
-
-void QuicPacketGenerator::AttachPacketFlusher() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.AttachPacketFlusher();
- return;
- }
- flusher_attached_ = true;
- if (!write_start_packet_number_.IsInitialized()) {
- write_start_packet_number_ = packet_creator_.NextSendingPacketNumber();
- }
-}
-
-void QuicPacketGenerator::Flush() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.Flush();
- return;
- }
- packet_creator_.FlushCurrentPacket();
- SendRemainingPendingPadding();
- flusher_attached_ = false;
- if (GetQuicFlag(FLAGS_quic_export_server_num_packets_per_write_histogram)) {
- if (!write_start_packet_number_.IsInitialized()) {
- QUIC_BUG << "write_start_packet_number is not initialized";
- return;
- }
- QUIC_SERVER_HISTOGRAM_COUNTS(
- "quic_server_num_written_packets_per_write",
- packet_creator_.NextSendingPacketNumber() - write_start_packet_number_,
- 1, 200, 50, "Number of QUIC packets written per write operation");
- }
- write_start_packet_number_.Clear();
-}
-
-void QuicPacketGenerator::FlushAllQueuedFrames() {
- packet_creator_.FlushCurrentPacket();
-}
-
-bool QuicPacketGenerator::HasPendingFrames() const {
- return packet_creator_.HasPendingFrames();
-}
-
-void QuicPacketGenerator::StopSendingVersion() {
- packet_creator_.StopSendingVersion();
-}
-
-void QuicPacketGenerator::SetDiversificationNonce(
- const DiversificationNonce& nonce) {
- packet_creator_.SetDiversificationNonce(nonce);
-}
-
-QuicPacketNumber QuicPacketGenerator::packet_number() const {
- return packet_creator_.packet_number();
-}
-
-QuicByteCount QuicPacketGenerator::GetCurrentMaxPacketLength() const {
- return packet_creator_.max_packet_length();
-}
-
-void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length) {
- DCHECK(packet_creator_.CanSetMaxPacketLength());
- packet_creator_.SetMaxPacketLength(length);
-}
-
-std::unique_ptr<QuicEncryptedPacket>
-QuicPacketGenerator::SerializeVersionNegotiationPacket(
- bool ietf_quic,
- bool use_length_prefix,
- const ParsedQuicVersionVector& supported_versions) {
- return packet_creator_.SerializeVersionNegotiationPacket(
- ietf_quic, use_length_prefix, supported_versions);
-}
-
-OwningSerializedPacketPointer
-QuicPacketGenerator::SerializeConnectivityProbingPacket() {
- return packet_creator_.SerializeConnectivityProbingPacket();
-}
-
-OwningSerializedPacketPointer
-QuicPacketGenerator::SerializePathChallengeConnectivityProbingPacket(
- QuicPathFrameBuffer* payload) {
- return packet_creator_.SerializePathChallengeConnectivityProbingPacket(
- payload);
-}
-
-OwningSerializedPacketPointer
-QuicPacketGenerator::SerializePathResponseConnectivityProbingPacket(
- const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded) {
- return packet_creator_.SerializePathResponseConnectivityProbingPacket(
- payloads, is_padded);
-}
-
-void QuicPacketGenerator::UpdatePacketNumberLength(
- QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight) {
- return packet_creator_.UpdatePacketNumberLength(least_packet_awaited_by_peer,
- max_packets_in_flight);
-}
-
-void QuicPacketGenerator::SkipNPacketNumbers(
- QuicPacketCount count,
- QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight) {
- packet_creator_.SkipNPacketNumbers(count, least_packet_awaited_by_peer,
- max_packets_in_flight);
-}
-
-void QuicPacketGenerator::SetServerConnectionIdLength(uint32_t length) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.SetServerConnectionIdLength(length);
- return;
- }
- if (length == 0) {
- packet_creator_.SetServerConnectionIdIncluded(CONNECTION_ID_ABSENT);
- } else {
- packet_creator_.SetServerConnectionIdIncluded(CONNECTION_ID_PRESENT);
- }
-}
-
-void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) {
- packet_creator_.set_encryption_level(level);
-}
-
-void QuicPacketGenerator::SetEncrypter(
- EncryptionLevel level,
- std::unique_ptr<QuicEncrypter> encrypter) {
- packet_creator_.SetEncrypter(level, std::move(encrypter));
-}
-
-void QuicPacketGenerator::AddRandomPadding() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.AddRandomPadding();
- return;
- }
- packet_creator_.AddPendingPadding(
- random_generator_->RandUint64() % kMaxNumRandomPaddingBytes + 1);
-}
-
-void QuicPacketGenerator::SendRemainingPendingPadding() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.SendRemainingPendingPadding();
- return;
- }
- while (
- packet_creator_.pending_padding_bytes() > 0 && !HasPendingFrames() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)) {
- packet_creator_.FlushCurrentPacket();
- }
-}
-
-bool QuicPacketGenerator::HasRetransmittableFrames() const {
- return packet_creator_.HasPendingRetransmittableFrames();
-}
-
-bool QuicPacketGenerator::HasPendingStreamFramesOfStream(
- QuicStreamId id) const {
- return packet_creator_.HasPendingStreamFramesOfStream(id);
-}
-
-void QuicPacketGenerator::SetTransmissionType(TransmissionType type) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.SetTransmissionType(type);
- return;
- }
- next_transmission_type_ = type;
-}
-
-void QuicPacketGenerator::SetRetryToken(QuicStringPiece retry_token) {
- packet_creator_.SetRetryToken(retry_token);
-}
-
-MessageStatus QuicPacketGenerator::AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.AddMessageFrame(message_id, message);
- }
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to add message frame.";
- MaybeBundleAckOpportunistically();
- const QuicByteCount message_length = message.total_length();
- if (message_length > GetCurrentLargestMessagePayload()) {
- return MESSAGE_STATUS_TOO_LARGE;
- }
- if (!packet_creator_.HasRoomForMessageFrame(message_length)) {
- packet_creator_.FlushCurrentPacket();
- }
- QuicMessageFrame* frame = new QuicMessageFrame(message_id, message);
- const bool success =
- packet_creator_.AddSavedFrame(QuicFrame(frame), next_transmission_type_);
- if (!success) {
- QUIC_BUG << "Failed to send message " << message_id;
- delete frame;
- return MESSAGE_STATUS_INTERNAL_ERROR;
- }
- return MESSAGE_STATUS_SUCCESS;
-}
-
-void QuicPacketGenerator::MaybeBundleAckOpportunistically() {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.MaybeBundleAckOpportunistically();
- return;
- }
- if (packet_creator_.has_ack()) {
- // Ack already queued, nothing to do.
- return;
- }
- if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- return;
- }
- const bool flushed =
- FlushAckFrame(delegate_->MaybeBundleAckOpportunistically());
- DCHECK(flushed);
-}
-
-bool QuicPacketGenerator::FlushAckFrame(const QuicFrames& frames) {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.FlushAckFrame(frames);
- }
- QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
- "generator tries to send ACK frame.";
- for (const auto& frame : frames) {
- DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME);
- if (packet_creator_.HasPendingFrames()) {
- if (packet_creator_.AddSavedFrame(frame, next_transmission_type_)) {
- // There is pending frames and current frame fits.
- continue;
- }
- }
- DCHECK(!packet_creator_.HasPendingFrames());
- // There is no pending frames, consult the delegate whether a packet can be
- // generated.
- if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- return false;
- }
- const bool success =
- packet_creator_.AddSavedFrame(frame, next_transmission_type_);
- QUIC_BUG_IF(!success) << "Failed to flush " << frame;
- }
- return true;
-}
-
-QuicPacketLength QuicPacketGenerator::GetCurrentLargestMessagePayload() const {
- return packet_creator_.GetCurrentLargestMessagePayload();
-}
-
-QuicPacketLength QuicPacketGenerator::GetGuaranteedLargestMessagePayload()
- const {
- return packet_creator_.GetGuaranteedLargestMessagePayload();
-}
-
-void QuicPacketGenerator::SetServerConnectionId(
- QuicConnectionId server_connection_id) {
- packet_creator_.SetServerConnectionId(server_connection_id);
-}
-
-void QuicPacketGenerator::SetClientConnectionId(
- QuicConnectionId client_connection_id) {
- packet_creator_.SetClientConnectionId(client_connection_id);
-}
-
-size_t QuicPacketGenerator::SerializeCoalescedPacket(
- const QuicCoalescedPacket& coalesced,
- char* buffer,
- size_t buffer_len) {
- return packet_creator_.SerializeCoalescedPacket(coalesced, buffer,
- buffer_len);
-}
-
-void QuicPacketGenerator::SetSoftMaxPacketLength(QuicByteCount length) {
- packet_creator_.SetSoftMaxPacketLength(length);
-}
-
-void QuicPacketGenerator::set_fully_pad_crypto_handshake_packets(
- bool new_value) {
- if (packet_creator_.combine_generator_and_creator()) {
- packet_creator_.set_fully_pad_crypto_handshake_packets(new_value);
- return;
- }
- fully_pad_crypto_handshake_packets_ = new_value;
-}
-
-bool QuicPacketGenerator::fully_pad_crypto_handshake_packets() const {
- if (packet_creator_.combine_generator_and_creator()) {
- return packet_creator_.fully_pad_crypto_handshake_packets();
- }
- return fully_pad_crypto_handshake_packets_;
-}
-
-} // namespace quic
diff --git a/quic/core/quic_packet_generator.h b/quic/core/quic_packet_generator.h
deleted file mode 100644
index efeed75..0000000
--- a/quic/core/quic_packet_generator.h
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Responsible for generating packets on behalf of a QuicConnection.
-// Packets are serialized just-in-time.
-// Ack and Feedback frames will be requested from the Connection
-// just-in-time. When a packet needs to be sent, the Generator
-// will serialize a packet and pass it to QuicConnection::SendOrQueuePacket()
-//
-// The Generator's mode of operation is controlled by two conditions:
-//
-// 1) Is the Delegate writable?
-//
-// If the Delegate is not writable, then no operations will cause
-// a packet to be serialized. In particular:
-// * SetShouldSendAck will simply record that an ack is to be sent.
-// * AddControlFrame will enqueue the control frame.
-// * ConsumeData will do nothing.
-//
-// If the Delegate is writable, then the behavior depends on the second
-// condition:
-//
-// 2) Is the Generator in batch mode?
-//
-// If the Generator is NOT in batch mode, then each call to a write
-// operation will serialize one or more packets. The contents will
-// include any previous queued frames. If an ack should be sent
-// but has not been sent, then the Delegate will be asked to create
-// an Ack frame which will then be included in the packet. When
-// the write call completes, the current packet will be serialized
-// and sent to the Delegate, even if it is not full.
-//
-// If the Generator is in batch mode, then each write operation will
-// add data to the "current" packet. When the current packet becomes
-// full, it will be serialized and sent to the packet. When batch
-// mode is ended via |FinishBatchOperations|, the current packet
-// will be serialzied, even if it is not full.
-
-#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
-#define QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
-
-#include <cstddef>
-#include <cstdint>
-#include <list>
-
-#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
-#include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
-
-namespace quic {
-
-namespace test {
-class QuicPacketGeneratorPeer;
-} // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicPacketGenerator {
- public:
- QuicPacketGenerator(QuicConnectionId server_connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator,
- QuicPacketCreator::DelegateInterface* delegate);
- QuicPacketGenerator(const QuicPacketGenerator&) = delete;
- QuicPacketGenerator& operator=(const QuicPacketGenerator&) = delete;
-
- ~QuicPacketGenerator();
-
- // Consumes retransmittable control |frame|. Returns true if the frame is
- // successfully consumed. Returns false otherwise.
- bool ConsumeRetransmittableControlFrame(const QuicFrame& frame);
-
- // Given some data, may consume part or all of it and pass it to the
- // packet creator to be serialized into packets. If not in batch
- // mode, these packets will also be sent during this call.
- // When |state| is FIN_AND_PADDING, random padding of size [1, 256] will be
- // added after stream frames. If current constructed packet cannot
- // accommodate, the padding will overflow to the next packet(s).
- QuicConsumedData ConsumeData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state);
-
- // Consumes data for CRYPTO frames sent at |level| starting at |offset| for a
- // total of |write_length| bytes, and returns the number of bytes consumed.
- // The data is passed into the packet creator and serialized into one or more
- // packets.
- size_t ConsumeCryptoData(EncryptionLevel level,
- size_t write_length,
- QuicStreamOffset offset);
-
- // Sends as many data only packets as allowed by the send algorithm and the
- // available iov.
- // This path does not support padding, or bundling pending frames.
- // In case we access this method from ConsumeData, total_bytes_consumed
- // keeps track of how many bytes have already been consumed.
- QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- bool fin,
- size_t total_bytes_consumed);
-
- // Generates an MTU discovery packet of specified size.
- void GenerateMtuDiscoveryPacket(QuicByteCount target_mtu);
-
- // Indicates whether packet flusher is currently attached.
- bool PacketFlusherAttached() const;
- // Attaches packet flusher.
- void AttachPacketFlusher();
- // Flushes everything, including current open packet and pending padding.
- void Flush();
-
- // Flushes current open packet.
- void FlushAllQueuedFrames();
-
- // Returns true if there are frames pending to be serialized.
- bool HasPendingFrames() const;
-
- // Makes the framer not serialize the protocol version in sent packets.
- void StopSendingVersion();
-
- // SetDiversificationNonce sets the nonce that will be sent in each public
- // header of packets encrypted at the initial encryption level. Should only
- // be called by servers.
- void SetDiversificationNonce(const DiversificationNonce& nonce);
-
- // Creates a version negotiation packet which supports |supported_versions|.
- std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
- bool ietf_quic,
- bool use_length_prefix,
- const ParsedQuicVersionVector& supported_versions);
-
- // Creates a connectivity probing packet.
- OwningSerializedPacketPointer SerializeConnectivityProbingPacket();
-
- // Create connectivity probing request and response packets using PATH
- // CHALLENGE and PATH RESPONSE frames, respectively.
- // SerializePathChallengeConnectivityProbingPacket will pad the packet to be
- // MTU bytes long.
- OwningSerializedPacketPointer SerializePathChallengeConnectivityProbingPacket(
- QuicPathFrameBuffer* payload);
-
- // If |is_padded| is true then SerializePathResponseConnectivityProbingPacket
- // will pad the packet to be MTU bytes long, else it will not pad the packet.
- // |payloads| is cleared.
- OwningSerializedPacketPointer SerializePathResponseConnectivityProbingPacket(
- const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded);
-
- // Update the packet number length to use in future packets as soon as it
- // can be safely changed.
- void UpdatePacketNumberLength(QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight);
-
- // Skip |count| packet numbers.
- void SkipNPacketNumbers(QuicPacketCount count,
- QuicPacketNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight);
-
- // Set the minimum number of bytes for the server connection id length;
- void SetServerConnectionIdLength(uint32_t length);
-
- // Sets the encrypter to use for the encryption level.
- void SetEncrypter(EncryptionLevel level,
- std::unique_ptr<QuicEncrypter> encrypter);
-
- // Returns true if there are control frames or current constructed packet has
- // pending retransmittable frames.
- bool HasRetransmittableFrames() const;
-
- // Returns true if current constructed packet has pending stream frames for
- // stream |id|.
- bool HasPendingStreamFramesOfStream(QuicStreamId id) const;
-
- // Sets the encryption level that will be applied to new packets.
- void set_encryption_level(EncryptionLevel level);
-
- // packet number of the last created packet, or 0 if no packets have been
- // created.
- QuicPacketNumber packet_number() const;
-
- // Returns the maximum length a current packet can actually have.
- QuicByteCount GetCurrentMaxPacketLength() const;
-
- // Set maximum packet length in the creator immediately. May not be called
- // when there are frames queued in the creator.
- void SetMaxPacketLength(QuicByteCount length);
-
- // Set transmission type of next constructed packets.
- void SetTransmissionType(TransmissionType type);
-
- // Sets the retry token to be sent over the wire in IETF Initial packets.
- void SetRetryToken(QuicStringPiece retry_token);
-
- // Tries to add a message frame containing |message| and returns the status.
- MessageStatus AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message);
-
- // Called to flush ACK and STOP_WAITING frames, returns false if the flush
- // fails.
- bool FlushAckFrame(const QuicFrames& frames);
-
- // Returns the largest payload that will fit into a single MESSAGE frame.
- QuicPacketLength GetCurrentLargestMessagePayload() const;
- QuicPacketLength GetGuaranteedLargestMessagePayload() const;
-
- // Update the server connection ID used in outgoing packets.
- void SetServerConnectionId(QuicConnectionId server_connection_id);
-
- // Update the client connection ID used in outgoing packets.
- void SetClientConnectionId(QuicConnectionId client_connection_id);
-
- // Serializes |coalesced| to provided |buffer|, returns coalesced packet
- // length if serialization succeeds. Otherwise, returns 0.
- size_t SerializeCoalescedPacket(const QuicCoalescedPacket& coalesced,
- char* buffer,
- size_t buffer_len);
-
- // Set a soft maximum packet length in the creator. If a packet cannot be
- // successfully created, creator will remove the soft limit and use the actual
- // max packet length.
- void SetSoftMaxPacketLength(QuicByteCount length);
-
- void set_debug_delegate(QuicPacketCreator::DebugDelegate* debug_delegate) {
- packet_creator_.set_debug_delegate(debug_delegate);
- }
-
- void set_fully_pad_crypto_handshake_packets(bool new_value);
-
- bool fully_pad_crypto_handshake_packets() const;
-
- private:
- friend class test::QuicPacketGeneratorPeer;
-
- // Adds a random amount of padding (between 1 to 256 bytes).
- void AddRandomPadding();
-
- // Sends remaining pending padding.
- // Pending paddings should only be sent when there is nothing else to send.
- void SendRemainingPendingPadding();
-
- // Called when there is data to be sent, Retrieves updated ACK frame from
- // delegate_ and flushes it.
- void MaybeBundleAckOpportunistically();
-
- QuicPacketCreator::DelegateInterface* delegate_;
-
- QuicPacketCreator packet_creator_;
-
- // Transmission type of the next serialized packet.
- TransmissionType next_transmission_type_;
-
- // True if packet flusher is currently attached.
- bool flusher_attached_;
-
- QuicRandom* random_generator_;
-
- // Whether crypto handshake packets should be fully padded.
- bool fully_pad_crypto_handshake_packets_;
-
- // Packet number of the first packet of a write operation. This gets set
- // when the out-most flusher attaches and gets cleared when the out-most
- // flusher detaches.
- QuicPacketNumber write_start_packet_number_;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_
diff --git a/quic/core/quic_packet_generator_test.cc b/quic/core/quic_packet_generator_test.cc
deleted file mode 100644
index 7a7701e..0000000
--- a/quic/core/quic_packet_generator_test.cc
+++ /dev/null
@@ -1,1511 +0,0 @@
-// Copyright (c) 2012 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_packet_generator.h"
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
-#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
-#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
-#include "net/third_party/quiche/src/quic/core/quic_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
-#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_creator_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_packet_generator_peer.h"
-#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
-#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
-#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
-
-using testing::_;
-using testing::InSequence;
-using testing::Return;
-using testing::StrictMock;
-
-namespace quic {
-namespace test {
-namespace {
-
-class MockDelegate : public QuicPacketCreator::DelegateInterface {
- public:
- MockDelegate() {}
- MockDelegate(const MockDelegate&) = delete;
- MockDelegate& operator=(const MockDelegate&) = delete;
- ~MockDelegate() override {}
-
- MOCK_METHOD2(ShouldGeneratePacket,
- bool(HasRetransmittableData retransmittable,
- IsHandshake handshake));
- MOCK_METHOD0(MaybeBundleAckOpportunistically, const QuicFrames());
- MOCK_METHOD0(GetPacketBuffer, char*());
- MOCK_METHOD1(OnSerializedPacket, void(SerializedPacket* packet));
- MOCK_METHOD2(OnUnrecoverableError, void(QuicErrorCode, const std::string&));
-
- void SetCanWriteAnything() {
- EXPECT_CALL(*this, ShouldGeneratePacket(_, _)).WillRepeatedly(Return(true));
- EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
- .WillRepeatedly(Return(true));
- }
-
- void SetCanNotWrite() {
- EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
- .WillRepeatedly(Return(false));
- }
-
- // Use this when only ack frames should be allowed to be written.
- void SetCanWriteOnlyNonRetransmittable() {
- EXPECT_CALL(*this, ShouldGeneratePacket(_, _))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
- .WillRepeatedly(Return(true));
- }
-};
-
-// Simple struct for describing the contents of a packet.
-// Useful in conjunction with a SimpleQuicFrame for validating that a packet
-// contains the expected frames.
-struct PacketContents {
- PacketContents()
- : num_ack_frames(0),
- num_connection_close_frames(0),
- num_goaway_frames(0),
- num_rst_stream_frames(0),
- num_stop_waiting_frames(0),
- num_stream_frames(0),
- num_crypto_frames(0),
- num_ping_frames(0),
- num_mtu_discovery_frames(0),
- num_padding_frames(0) {}
-
- size_t num_ack_frames;
- size_t num_connection_close_frames;
- size_t num_goaway_frames;
- size_t num_rst_stream_frames;
- size_t num_stop_waiting_frames;
- size_t num_stream_frames;
- size_t num_crypto_frames;
- size_t num_ping_frames;
- size_t num_mtu_discovery_frames;
- size_t num_padding_frames;
-};
-
-} // namespace
-
-class TestPacketGenerator : public QuicPacketGenerator {
- public:
- TestPacketGenerator(QuicConnectionId connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator,
- QuicPacketCreator::DelegateInterface* delegate,
- SimpleDataProducer* producer)
- : QuicPacketGenerator(connection_id, framer, random_generator, delegate),
- ack_frame_(InitAckFrame(1)),
- delegate_(static_cast<MockDelegate*>(delegate)),
- producer_(producer) {}
-
- bool ConsumeRetransmittableControlFrame(const QuicFrame& frame,
- bool bundle_ack) {
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack()) {
- QuicFrames frames;
- if (bundle_ack) {
- frames.push_back(QuicFrame(&ack_frame_));
- }
- if (delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically())
- .WillOnce(Return(frames));
- }
- }
- return QuicPacketGenerator::ConsumeRetransmittableControlFrame(frame);
- }
-
- QuicConsumedData ConsumeDataFastPath(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- size_t total_length,
- QuicStreamOffset offset,
- bool fin) {
- // Save data before data is consumed.
- if (total_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
- }
- return QuicPacketGenerator::ConsumeDataFastPath(id, total_length, offset,
- fin, 0);
- }
-
- QuicConsumedData ConsumeData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- size_t total_length,
- QuicStreamOffset offset,
- StreamSendingState state) {
- // Save data before data is consumed.
- if (total_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
- }
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
- }
- return QuicPacketGenerator::ConsumeData(id, total_length, offset, state);
- }
-
- MessageStatus AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message) {
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
- }
- return QuicPacketGenerator::AddMessageFrame(message_id, message);
- }
-
- size_t ConsumeCryptoData(EncryptionLevel level,
- QuicStringPiece data,
- QuicStreamOffset offset) {
- producer_->SaveCryptoData(level, offset, data);
- if (!QuicPacketGeneratorPeer::GetPacketCreator(this)->has_ack() &&
- delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
- NOT_HANDSHAKE)) {
- EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
- }
- return QuicPacketGenerator::ConsumeCryptoData(level, data.length(), offset);
- }
-
- QuicAckFrame ack_frame_;
- MockDelegate* delegate_;
- SimpleDataProducer* producer_;
-};
-
-class QuicPacketGeneratorTest : public QuicTest {
- public:
- QuicPacketGeneratorTest()
- : framer_(AllSupportedVersions(),
- QuicTime::Zero(),
- Perspective::IS_CLIENT,
- kQuicDefaultConnectionIdLength),
- generator_(TestConnectionId(),
- &framer_,
- &random_generator_,
- &delegate_,
- &producer_),
- creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)),
- ack_frame_(InitAckFrame(1)) {
- EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
- creator_->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
- creator_->set_encryption_level(ENCRYPTION_FORWARD_SECURE);
- framer_.set_data_producer(&producer_);
- if (simple_framer_.framer()->version().KnowsWhichDecrypterToUse()) {
- simple_framer_.framer()->InstallDecrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
- }
- generator_.AttachPacketFlusher();
- }
-
- ~QuicPacketGeneratorTest() override {
- for (SerializedPacket& packet : packets_) {
- delete[] packet.encrypted_buffer;
- ClearSerializedPacket(&packet);
- }
- }
-
- void SavePacket(SerializedPacket* packet) {
- packet->encrypted_buffer = CopyBuffer(*packet);
- packets_.push_back(*packet);
- packet->encrypted_buffer = nullptr;
- packet->retransmittable_frames.clear();
- }
-
- protected:
- QuicRstStreamFrame* CreateRstStreamFrame() {
- return new QuicRstStreamFrame(1, 1, QUIC_STREAM_NO_ERROR, 0);
- }
-
- QuicGoAwayFrame* CreateGoAwayFrame() {
- return new QuicGoAwayFrame(2, QUIC_NO_ERROR, 1, std::string());
- }
-
- void CheckPacketContains(const PacketContents& contents,
- size_t packet_index) {
- ASSERT_GT(packets_.size(), packet_index);
- const SerializedPacket& packet = packets_[packet_index];
- size_t num_retransmittable_frames =
- contents.num_connection_close_frames + contents.num_goaway_frames +
- contents.num_rst_stream_frames + contents.num_stream_frames +
- contents.num_crypto_frames + contents.num_ping_frames;
- size_t num_frames =
- contents.num_ack_frames + contents.num_stop_waiting_frames +
- contents.num_mtu_discovery_frames + contents.num_padding_frames +
- num_retransmittable_frames;
-
- if (num_retransmittable_frames == 0) {
- ASSERT_TRUE(packet.retransmittable_frames.empty());
- } else {
- ASSERT_FALSE(packet.retransmittable_frames.empty());
- EXPECT_EQ(num_retransmittable_frames,
- packet.retransmittable_frames.size());
- }
-
- ASSERT_TRUE(packet.encrypted_buffer != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(
- QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
- size_t num_padding_frames = 0;
- if (contents.num_padding_frames == 0) {
- num_padding_frames = simple_framer_.padding_frames().size();
- }
- EXPECT_EQ(num_frames + num_padding_frames, simple_framer_.num_frames());
- EXPECT_EQ(contents.num_ack_frames, simple_framer_.ack_frames().size());
- EXPECT_EQ(contents.num_connection_close_frames,
- simple_framer_.connection_close_frames().size());
- EXPECT_EQ(contents.num_goaway_frames,
- simple_framer_.goaway_frames().size());
- EXPECT_EQ(contents.num_rst_stream_frames,
- simple_framer_.rst_stream_frames().size());
- EXPECT_EQ(contents.num_stream_frames,
- simple_framer_.stream_frames().size());
- EXPECT_EQ(contents.num_crypto_frames,
- simple_framer_.crypto_frames().size());
- EXPECT_EQ(contents.num_stop_waiting_frames,
- simple_framer_.stop_waiting_frames().size());
- if (contents.num_padding_frames != 0) {
- EXPECT_EQ(contents.num_padding_frames,
- simple_framer_.padding_frames().size());
- }
-
- // From the receiver's perspective, MTU discovery frames are ping frames.
- EXPECT_EQ(contents.num_ping_frames + contents.num_mtu_discovery_frames,
- simple_framer_.ping_frames().size());
- }
-
- void CheckPacketHasSingleStreamFrame(size_t packet_index) {
- ASSERT_GT(packets_.size(), packet_index);
- const SerializedPacket& packet = packets_[packet_index];
- ASSERT_FALSE(packet.retransmittable_frames.empty());
- EXPECT_EQ(1u, packet.retransmittable_frames.size());
- ASSERT_TRUE(packet.encrypted_buffer != nullptr);
- ASSERT_TRUE(simple_framer_.ProcessPacket(
- QuicEncryptedPacket(packet.encrypted_buffer, packet.encrypted_length)));
- EXPECT_EQ(1u, simple_framer_.num_frames());
- EXPECT_EQ(1u, simple_framer_.stream_frames().size());
- }
-
- void CheckAllPacketsHaveSingleStreamFrame() {
- for (size_t i = 0; i < packets_.size(); i++) {
- CheckPacketHasSingleStreamFrame(i);
- }
- }
-
- void CreateData(size_t len) {
- data_array_.reset(new char[len]);
- memset(data_array_.get(), '?', len);
- iov_.iov_base = data_array_.get();
- iov_.iov_len = len;
- }
-
- QuicFramer framer_;
- MockRandom random_generator_;
- StrictMock<MockDelegate> delegate_;
- TestPacketGenerator generator_;
- QuicPacketCreator* creator_;
- SimpleQuicFramer simple_framer_;
- std::vector<SerializedPacket> packets_;
- QuicAckFrame ack_frame_;
- struct iovec iov_;
- SimpleBufferAllocator allocator_;
-
- private:
- std::unique_ptr<char[]> data_array_;
- SimpleDataProducer producer_;
-};
-
-class MockDebugDelegate : public QuicPacketCreator::DebugDelegate {
- public:
- MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&));
-};
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritable) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- delete rst_frame;
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_OnlyAckWritable) {
- delegate_.SetCanWriteOnlyNonRetransmittable();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- delete rst_frame;
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
- delegate_.SetCanWriteAnything();
-
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- delete rst_frame;
-}
-
-TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/false);
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_rst_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeCryptoData) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- std::string data = "crypto data";
- size_t consumed_bytes =
- generator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
- generator_.Flush();
- EXPECT_EQ(data.length(), consumed_bytes);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_crypto_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
- delegate_.SetCanNotWrite();
-
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(0u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
- delegate_.SetCanWriteAnything();
-
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- generator_.Flush();
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-// Test the behavior of ConsumeData when the data consumed is for the crypto
-// handshake stream. Ensure that the packet is always sent and padded even if
-// the generator operates in batch mode.
-TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- std::string data = "foo bar";
- MakeIOVector(data, &iov_);
- size_t consumed_bytes = 0;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- consumed_bytes = generator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
- } else {
- consumed_bytes =
- generator_
- .ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_.transport_version()),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN)
- .bytes_consumed;
- }
- EXPECT_EQ(7u, consumed_bytes);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- contents.num_crypto_frames = 1;
- } else {
- contents.num_stream_frames = 1;
- }
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-
- ASSERT_EQ(1u, packets_.size());
- ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
-}
-
-// Test the behavior of ConsumeData when the data is for the crypto handshake
-// stream, but padding is disabled.
-TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake_PaddingDisabled) {
- generator_.set_fully_pad_crypto_handshake_packets(false);
-
- delegate_.SetCanWriteAnything();
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- std::string data = "foo";
- MakeIOVector(data, &iov_);
- size_t bytes_consumed = 0;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- bytes_consumed = generator_.ConsumeCryptoData(ENCRYPTION_INITIAL, data, 0);
- } else {
- bytes_consumed =
- generator_
- .ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_.transport_version()),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN)
- .bytes_consumed;
- }
- EXPECT_EQ(3u, bytes_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- contents.num_crypto_frames = 1;
- } else {
- contents.num_stream_frames = 1;
- }
- contents.num_padding_frames = 0;
- CheckPacketContains(contents, 0);
-
- ASSERT_EQ(1u, packets_.size());
-
- // Packet is not fully padded, but we want to future packets to be larger.
- ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
- size_t expected_packet_length = 27;
- if (QuicVersionUsesCryptoFrames(framer_.transport_version())) {
- // The framing of CRYPTO frames is slightly different than that of stream
- // frames, so the expected packet length differs slightly.
- expected_packet_length = 28;
- }
- if (framer_.version().HasHeaderProtection()) {
- expected_packet_length = 29;
- }
- EXPECT_EQ(expected_packet_length, packets_[0].encrypted_length);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
- delegate_.SetCanWriteAnything();
-
- EXPECT_QUIC_BUG(generator_.ConsumeData(
- QuicUtils::QuicUtils::GetFirstBidirectionalStreamId(
- framer_.transport_version(), Perspective::IS_CLIENT),
- nullptr, 0, 0, 0, NO_FIN),
- "Attempt to consume empty data without FIN.");
-}
-
-TEST_F(QuicPacketGeneratorTest,
- ConsumeDataMultipleTimes_WritableAndShouldNotFlush) {
- delegate_.SetCanWriteAnything();
-
- MakeIOVector("foo", &iov_);
- generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- MakeIOVector("quux", &iov_);
- QuicConsumedData consumed =
- generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 3, NO_FIN);
- EXPECT_EQ(4u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
- delegate_.SetCanWriteAnything();
-
- MakeIOVector("foo", &iov_);
- generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- MakeIOVector("quux", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 3, FIN);
- EXPECT_EQ(4u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Now both frames will be flushed out.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames =
- GetQuicReloadableFlag(quic_coalesce_stream_frames) ? 1 : 2;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
- // Set the packet size be enough for two stream frames with 0 stream offset,
- // but not enough for a stream frame of 0 offset and one with non-zero offset.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- // Add an extra 3 bytes for the payload and 1 byte so
- // BytesFree is larger than the GetMinStreamFrameSize.
- QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0,
- false, 3) +
- 3 +
- QuicFramer::GetMinStreamFrameSize(framer_.transport_version(), 1, 0, true,
- 1) +
- 1;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- {
- InSequence dummy;
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- // Queue enough data to prevent a stream frame with a non-zero offset from
- // fitting.
- MakeIOVector("foo", &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // This frame will not fit with the existing frame, causing the queued frame
- // to be serialized, and it will be added to a new open packet.
- MakeIOVector("bar", &iov_);
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 3, FIN);
- EXPECT_EQ(3u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- creator_->FlushCurrentPacket();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
- CheckPacketContains(contents, 1);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataFastPath) {
- delegate_.SetCanWriteAnything();
- generator_.SetTransmissionType(LOSS_RETRANSMISSION);
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeDataFastPath(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, true);
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(LOSS_RETRANSMISSION, packet.transmission_type);
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataLarge) {
- delegate_.SetCanWriteAnything();
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- PacketContents contents;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckFalse) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool success =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/true);
- EXPECT_FALSE(success);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- delegate_.SetCanWriteAnything();
-
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false);
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateRstStreamFrame()),
- /*bundle_ack=*/true);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- generator_.Flush();
-
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, ConsumeDataLargeSendAckTrue) {
- if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
- return;
- }
- delegate_.SetCanNotWrite();
- delegate_.SetCanWriteAnything();
-
- // Create a 10000 byte IOVector.
- CreateData(10000);
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- generator_.Flush();
-
- EXPECT_EQ(10000u, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_FALSE(packets_.empty());
- SerializedPacket packet = packets_.back();
- EXPECT_TRUE(!packet.retransmittable_frames.empty());
- EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
- const QuicStreamFrame& stream_frame =
- packet.retransmittable_frames.front().stream_frame;
- EXPECT_EQ(10000u, stream_frame.data_length + stream_frame.offset);
-}
-
-TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool consumed =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/true);
- EXPECT_FALSE(consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- EXPECT_FALSE(generator_.HasPendingStreamFramesOfStream(3));
-
- delegate_.SetCanWriteAnything();
-
- EXPECT_TRUE(
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false));
- // Send some data and a control frame
- MakeIOVector("quux", &iov_);
- generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateGoAwayFrame()),
- /*bundle_ack=*/false);
- }
- EXPECT_TRUE(generator_.HasPendingStreamFramesOfStream(3));
-
- // All five frames will be flushed out in a single packet.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- EXPECT_FALSE(generator_.HasPendingStreamFramesOfStream(3));
-
- PacketContents contents;
- // ACK will be flushed by connection.
- contents.num_ack_frames = 0;
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- contents.num_goaway_frames = 1;
- } else {
- contents.num_goaway_frames = 0;
- }
- contents.num_rst_stream_frames = 1;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
- delegate_.SetCanNotWrite();
-
- QuicRstStreamFrame* rst_frame = CreateRstStreamFrame();
- const bool success =
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/true);
- EXPECT_FALSE(success);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- delegate_.SetCanWriteAnything();
-
- {
- InSequence dummy;
- // All five frames will be flushed out in a single packet
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- }
- EXPECT_TRUE(
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(rst_frame),
- /*bundle_ack=*/false));
- // Send enough data to exceed one packet
- size_t data_len = kDefaultMaxPacketSize + 100;
- CreateData(data_len);
- QuicConsumedData consumed =
- generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- generator_.ConsumeRetransmittableControlFrame(
- QuicFrame(CreateGoAwayFrame()),
- /*bundle_ack=*/false);
- }
-
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // The first packet should have the queued data and part of the stream data.
- PacketContents contents;
- // ACK will be sent by connection.
- contents.num_ack_frames = 0;
- contents.num_rst_stream_frames = 1;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-
- // The second should have the remainder of the stream data.
- PacketContents contents2;
- if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
- contents2.num_goaway_frames = 1;
- } else {
- contents2.num_goaway_frames = 0;
- }
- contents2.num_stream_frames = 1;
- CheckPacketContains(contents2, 1);
-}
-
-// Regression test of b/120493795.
-TEST_F(QuicPacketGeneratorTest, PacketTransmissionType) {
- delegate_.SetCanWriteAnything();
-
- // The first ConsumeData will fill the packet without flush.
- generator_.SetTransmissionType(LOSS_RETRANSMISSION);
-
- size_t data_len = 1324;
- CreateData(data_len);
- QuicStreamId stream1_id = QuicUtils::GetFirstBidirectionalStreamId(
- framer_.transport_version(), Perspective::IS_CLIENT);
- QuicConsumedData consumed =
- generator_.ConsumeData(stream1_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- ASSERT_EQ(0u, creator_->BytesFree())
- << "Test setup failed: Please increase data_len to "
- << data_len + creator_->BytesFree() << " bytes.";
-
- // The second ConsumeData can not be added to the packet and will flush.
- generator_.SetTransmissionType(NOT_RETRANSMISSION);
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- QuicStreamId stream2_id = stream1_id + 4;
-
- consumed =
- generator_.ConsumeData(stream2_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
-
- // Ensure the packet is successfully created.
- ASSERT_EQ(1u, packets_.size());
- ASSERT_TRUE(packets_[0].encrypted_buffer);
- ASSERT_EQ(1u, packets_[0].retransmittable_frames.size());
- EXPECT_EQ(stream1_id,
- packets_[0].retransmittable_frames[0].stream_frame.stream_id);
-
- // Since the second frame was not added, the packet's transmission type
- // should be the first frame's type.
- EXPECT_EQ(packets_[0].transmission_type, LOSS_RETRANSMISSION);
-}
-
-TEST_F(QuicPacketGeneratorTest, TestConnectionIdLength) {
- QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
- generator_.SetServerConnectionIdLength(0);
- EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
- creator_->GetDestinationConnectionIdLength());
-
- for (size_t i = 1; i < 10; i++) {
- generator_.SetServerConnectionIdLength(i);
- if (VersionHasIetfInvariantHeader(framer_.transport_version())) {
- EXPECT_EQ(PACKET_0BYTE_CONNECTION_ID,
- creator_->GetDestinationConnectionIdLength());
- } else {
- EXPECT_EQ(PACKET_8BYTE_CONNECTION_ID,
- creator_->GetDestinationConnectionIdLength());
- }
- }
-}
-
-// Test whether SetMaxPacketLength() works in the situation when the queue is
-// empty, and we send three packets worth of data.
-TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Initial) {
- delegate_.SetCanWriteAnything();
-
- // Send enough data for three packets.
- size_t data_len = 3 * kDefaultMaxPacketSize + 1;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
- generator_.SetMaxPacketLength(packet_len);
- EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(3)
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- CreateData(data_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, FIN);
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // We expect three packets, and first two of them have to be of packet_len
- // size. We check multiple packets (instead of just one) because we want to
- // ensure that |max_packet_length_| does not get changed incorrectly by the
- // generator after first packet is serialized.
- ASSERT_EQ(3u, packets_.size());
- EXPECT_EQ(packet_len, packets_[0].encrypted_length);
- EXPECT_EQ(packet_len, packets_[1].encrypted_length);
- CheckAllPacketsHaveSingleStreamFrame();
-}
-
-// Test whether SetMaxPacketLength() works in the situation when we first write
-// data, then change packet size, then write data again.
-TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_Middle) {
- delegate_.SetCanWriteAnything();
-
- // We send enough data to overflow default packet length, but not the altered
- // one.
- size_t data_len = kDefaultMaxPacketSize;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
-
- // We expect to see three packets in total.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(3)
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send two packets before packet size change.
- CreateData(data_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, NO_FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // Make sure we already have two packets.
- ASSERT_EQ(2u, packets_.size());
-
- // Increase packet size.
- generator_.SetMaxPacketLength(packet_len);
- EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
-
- // Send a packet after packet size change.
- CreateData(data_len);
- generator_.AttachPacketFlusher();
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, data_len, FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // We expect first data chunk to get fragmented, but the second one to fit
- // into a single packet.
- ASSERT_EQ(3u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
- EXPECT_LE(kDefaultMaxPacketSize, packets_[2].encrypted_length);
- CheckAllPacketsHaveSingleStreamFrame();
-}
-
-// Test whether SetMaxPacketLength() works correctly when we force the change of
-// the packet size in the middle of the batched packet.
-TEST_F(QuicPacketGeneratorTest, SetMaxPacketLength_MidpacketFlush) {
- delegate_.SetCanWriteAnything();
-
- size_t first_write_len = kDefaultMaxPacketSize / 2;
- size_t packet_len = kDefaultMaxPacketSize + 100;
- size_t second_write_len = packet_len + 1;
- ASSERT_LE(packet_len, kMaxOutgoingPacketSize);
-
- // First send half of the packet worth of data. We are in the batch mode, so
- // should not cause packet serialization.
- CreateData(first_write_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, NO_FIN);
- EXPECT_EQ(first_write_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Make sure we have no packets so far.
- ASSERT_EQ(0u, packets_.size());
-
- // Expect a packet to be flushed.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Increase packet size after flushing all frames.
- // Ensure it's immediately enacted.
- generator_.FlushAllQueuedFrames();
- generator_.SetMaxPacketLength(packet_len);
- EXPECT_EQ(packet_len, generator_.GetCurrentMaxPacketLength());
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // We expect to see exactly one packet serialized after that, because we send
- // a value somewhat exceeding new max packet size, and the tail data does not
- // get serialized because we are still in the batch mode.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send a more than a packet worth of data to the same stream. This should
- // trigger serialization of one packet, and queue another one.
- CreateData(second_write_len);
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/first_write_len, FIN);
- EXPECT_EQ(second_write_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // We expect the first packet to be underfilled, and the second packet be up
- // to the new max packet size.
- ASSERT_EQ(2u, packets_.size());
- EXPECT_GT(kDefaultMaxPacketSize, packets_[0].encrypted_length);
- EXPECT_EQ(packet_len, packets_[1].encrypted_length);
-
- CheckAllPacketsHaveSingleStreamFrame();
-}
-
-// Test sending a connectivity probing packet.
-TEST_F(QuicPacketGeneratorTest, GenerateConnectivityProbingPacket) {
- delegate_.SetCanWriteAnything();
-
- OwningSerializedPacketPointer probing_packet;
- if (VersionHasIetfQuicFrames(framer_.transport_version())) {
- QuicPathFrameBuffer payload = {
- {0xde, 0xad, 0xbe, 0xef, 0xba, 0xdc, 0x0f, 0xfe}};
- probing_packet =
- generator_.SerializePathChallengeConnectivityProbingPacket(&payload);
- } else {
- probing_packet = generator_.SerializeConnectivityProbingPacket();
- }
-
- ASSERT_TRUE(simple_framer_.ProcessPacket(QuicEncryptedPacket(
- probing_packet->encrypted_buffer, probing_packet->encrypted_length)));
-
- EXPECT_EQ(2u, simple_framer_.num_frames());
- if (VersionHasIetfQuicFrames(framer_.transport_version())) {
- EXPECT_EQ(1u, simple_framer_.path_challenge_frames().size());
- } else {
- EXPECT_EQ(1u, simple_framer_.ping_frames().size());
- }
- EXPECT_EQ(1u, simple_framer_.padding_frames().size());
-}
-
-// Test sending an MTU probe, without any surrounding data.
-TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_Simple) {
- delegate_.SetCanWriteAnything();
-
- const size_t target_mtu = kDefaultMaxPacketSize + 100;
- static_assert(target_mtu < kMaxOutgoingPacketSize,
- "The MTU probe used by the test exceeds maximum packet size");
-
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- generator_.GenerateMtuDiscoveryPacket(target_mtu);
-
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
- ASSERT_EQ(1u, packets_.size());
- EXPECT_EQ(target_mtu, packets_[0].encrypted_length);
-
- PacketContents contents;
- contents.num_mtu_discovery_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-// Test sending an MTU probe. Surround it with data, to ensure that it resets
-// the MTU to the value before the probe was sent.
-TEST_F(QuicPacketGeneratorTest, GenerateMtuDiscoveryPacket_SurroundedByData) {
- delegate_.SetCanWriteAnything();
-
- const size_t target_mtu = kDefaultMaxPacketSize + 100;
- static_assert(target_mtu < kMaxOutgoingPacketSize,
- "The MTU probe used by the test exceeds maximum packet size");
-
- // Send enough data so it would always cause two packets to be sent.
- const size_t data_len = target_mtu + 1;
-
- // Send a total of five packets: two packets before the probe, the probe
- // itself, and two packets after the probe.
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .Times(5)
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- // Send data before the MTU probe.
- CreateData(data_len);
- QuicConsumedData consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/0, NO_FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // Send the MTU probe.
- generator_.GenerateMtuDiscoveryPacket(target_mtu);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- // Send data after the MTU probe.
- CreateData(data_len);
- generator_.AttachPacketFlusher();
- consumed = generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len,
- /*offset=*/data_len, FIN);
- generator_.Flush();
- EXPECT_EQ(data_len, consumed.bytes_consumed);
- EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- ASSERT_EQ(5u, packets_.size());
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
- EXPECT_EQ(target_mtu, packets_[2].encrypted_length);
- EXPECT_EQ(kDefaultMaxPacketSize, packets_[3].encrypted_length);
-
- PacketContents probe_contents;
- probe_contents.num_mtu_discovery_frames = 1;
- probe_contents.num_padding_frames = 1;
-
- CheckPacketHasSingleStreamFrame(0);
- CheckPacketHasSingleStreamFrame(1);
- CheckPacketContains(probe_contents, 2);
- CheckPacketHasSingleStreamFrame(3);
- CheckPacketHasSingleStreamFrame(4);
-}
-
-TEST_F(QuicPacketGeneratorTest, DontCrashOnInvalidStopWaiting) {
- if (VersionSupportsMessageFrames(framer_.transport_version())) {
- return;
- }
- // Test added to ensure the generator does not crash when an invalid frame is
- // added. Because this is an indication of internal programming errors,
- // DFATALs are expected.
- // A 1 byte packet number length can't encode a gap of 1000.
- QuicPacketCreatorPeer::SetPacketNumber(creator_, 1000);
-
- delegate_.SetCanNotWrite();
- delegate_.SetCanWriteAnything();
-
- // This will not serialize any packets, because of the invalid frame.
- EXPECT_CALL(delegate_,
- OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET, _));
- EXPECT_QUIC_BUG(generator_.Flush(),
- "packet_number_length 1 is too small "
- "for least_unacked_delta: 1001");
-}
-
-// Regression test for b/31486443.
-TEST_F(QuicPacketGeneratorTest, ConnectionCloseFrameLargerThanPacketSize) {
- delegate_.SetCanWriteAnything();
- char buf[2000] = {};
- QuicStringPiece error_details(buf, 2000);
- const QuicErrorCode kQuicErrorCode = QUIC_PACKET_WRITE_ERROR;
-
- QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame(
- framer_.transport_version(), kQuicErrorCode, std::string(error_details),
- /*transport_close_frame_type=*/0);
- generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame),
- /*bundle_ack=*/false);
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-}
-
-TEST_F(QuicPacketGeneratorTest, RandomPaddingAfterFinSingleStreamSinglePacket) {
- const QuicByteCount kStreamFramePayloadSize = 100u;
- char buf[kStreamFramePayloadSize] = {};
- const QuicStreamId kDataStreamId = 5;
- // Set the packet size be enough for one stream frame with 0 stream offset and
- // max size of random padding.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- QuicFramer::GetMinStreamFrameSize(
- framer_.transport_version(), kDataStreamId, 0,
- /*last_frame_in_packet=*/false,
- kStreamFramePayloadSize + kMaxNumRandomPaddingBytes) +
- kStreamFramePayloadSize + kMaxNumRandomPaddingBytes;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
- generator_.Flush();
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_EQ(1u, packets_.size());
- PacketContents contents;
- // The packet has both stream and padding frames.
- contents.num_padding_frames = 1;
- contents.num_stream_frames = 1;
- CheckPacketContains(contents, 0);
-}
-
-TEST_F(QuicPacketGeneratorTest,
- RandomPaddingAfterFinSingleStreamMultiplePackets) {
- const QuicByteCount kStreamFramePayloadSize = 100u;
- char buf[kStreamFramePayloadSize] = {};
- const QuicStreamId kDataStreamId = 5;
- // Set the packet size be enough for one stream frame with 0 stream offset +
- // 1. One or more packets will accommodate.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- QuicFramer::GetMinStreamFrameSize(
- framer_.transport_version(), kDataStreamId, 0,
- /*last_frame_in_packet=*/false, kStreamFramePayloadSize + 1) +
- kStreamFramePayloadSize + 1;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- kDataStreamId, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
- generator_.Flush();
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_LE(1u, packets_.size());
- PacketContents contents;
- // The first packet has both stream and padding frames.
- contents.num_stream_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 0);
-
- for (size_t i = 1; i < packets_.size(); ++i) {
- // Following packets only have paddings.
- contents.num_stream_frames = 0;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, i);
- }
-}
-
-TEST_F(QuicPacketGeneratorTest,
- RandomPaddingAfterFinMultipleStreamsMultiplePackets) {
- const QuicByteCount kStreamFramePayloadSize = 100u;
- char buf[kStreamFramePayloadSize] = {};
- const QuicStreamId kDataStreamId1 = 5;
- const QuicStreamId kDataStreamId2 = 6;
- // Set the packet size be enough for first frame with 0 stream offset + second
- // frame + 1 byte payload. two or more packets will accommodate.
- size_t length =
- NullEncrypter(Perspective::IS_CLIENT).GetCiphertextSize(0) +
- GetPacketHeaderSize(
- framer_.transport_version(),
- creator_->GetDestinationConnectionIdLength(),
- creator_->GetSourceConnectionIdLength(),
- QuicPacketCreatorPeer::SendVersionInPacket(creator_),
- !kIncludeDiversificationNonce,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
- QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_), 0,
- QuicPacketCreatorPeer::GetLengthLength(creator_)) +
- QuicFramer::GetMinStreamFrameSize(
- framer_.transport_version(), kDataStreamId1, 0,
- /*last_frame_in_packet=*/false, kStreamFramePayloadSize) +
- kStreamFramePayloadSize +
- QuicFramer::GetMinStreamFrameSize(framer_.transport_version(),
- kDataStreamId1, 0,
- /*last_frame_in_packet=*/false, 1) +
- 1;
- generator_.SetMaxPacketLength(length);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillRepeatedly(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- QuicConsumedData consumed = generator_.ConsumeData(
- kDataStreamId1, &iov_, 1u, iov_.iov_len, 0, FIN_AND_PADDING);
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- MakeIOVector(QuicStringPiece(buf, kStreamFramePayloadSize), &iov_);
- consumed = generator_.ConsumeData(kDataStreamId2, &iov_, 1u, iov_.iov_len, 0,
- FIN_AND_PADDING);
- EXPECT_EQ(kStreamFramePayloadSize, consumed.bytes_consumed);
- generator_.Flush();
- EXPECT_FALSE(generator_.HasPendingFrames());
- EXPECT_FALSE(generator_.HasRetransmittableFrames());
-
- EXPECT_LE(2u, packets_.size());
- PacketContents contents;
- // The first packet has two stream frames.
- contents.num_stream_frames = 2;
- CheckPacketContains(contents, 0);
-
- // The second packet has one stream frame and padding frames.
- contents.num_stream_frames = 1;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, 1);
-
- for (size_t i = 2; i < packets_.size(); ++i) {
- // Following packets only have paddings.
- contents.num_stream_frames = 0;
- contents.num_padding_frames = 1;
- CheckPacketContains(contents, i);
- }
-}
-
-TEST_F(QuicPacketGeneratorTest, AddMessageFrame) {
- if (!VersionSupportsMessageFrames(framer_.transport_version())) {
- return;
- }
- quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
- delegate_.SetCanWriteAnything();
- EXPECT_CALL(delegate_, OnSerializedPacket(_))
- .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
-
- MakeIOVector("foo", &iov_);
- generator_.ConsumeData(
- QuicUtils::GetFirstBidirectionalStreamId(framer_.transport_version(),
- Perspective::IS_CLIENT),
- &iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
- generator_.AddMessageFrame(
- 1, MakeSpan(&allocator_, "message", &storage)));
- EXPECT_TRUE(generator_.HasPendingFrames());
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Add a message which causes the flush of current packet.
- EXPECT_EQ(
- MESSAGE_STATUS_SUCCESS,
- generator_.AddMessageFrame(
- 2, MakeSpan(
- &allocator_,
- std::string(generator_.GetCurrentLargestMessagePayload(), 'a'),
- &storage)));
- EXPECT_TRUE(generator_.HasRetransmittableFrames());
-
- // Failed to send messages which cannot fit into one packet.
- EXPECT_EQ(
- MESSAGE_STATUS_TOO_LARGE,
- generator_.AddMessageFrame(
- 3,
- MakeSpan(&allocator_,
- std::string(
- generator_.GetCurrentLargestMessagePayload() + 10, 'a'),
- &storage)));
-}
-
-TEST_F(QuicPacketGeneratorTest, ConnectionId) {
- generator_.SetServerConnectionId(TestConnectionId(0x1337));
- EXPECT_EQ(TestConnectionId(0x1337), creator_->GetDestinationConnectionId());
- EXPECT_EQ(EmptyQuicConnectionId(), creator_->GetSourceConnectionId());
- if (!framer_.version().SupportsClientConnectionIds()) {
- return;
- }
- generator_.SetClientConnectionId(TestConnectionId(0x33));
- EXPECT_EQ(TestConnectionId(0x1337), creator_->GetDestinationConnectionId());
- EXPECT_EQ(TestConnectionId(0x33), creator_->GetSourceConnectionId());
-}
-
-} // namespace test
-} // namespace quic