Index: net/quic/quic_connection.cc |
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc |
index f222a1f5a49c1301636207bb0709ca7a7ae3ac63..2fa5a12de1b49ffdbd666926733e48f1e33a221f 100644 |
--- a/net/quic/quic_connection.cc |
+++ b/net/quic/quic_connection.cc |
@@ -278,6 +278,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, |
largest_seen_packet_with_stop_waiting_(0), |
max_undecryptable_packets_(0), |
pending_version_negotiation_packet_(false), |
+ save_crypto_packets_as_termination_packets_(false), |
silent_close_enabled_(false), |
received_packet_manager_(&stats_), |
ack_queued_(false), |
@@ -341,6 +342,9 @@ QuicConnection::~QuicConnection() { |
delete writer_; |
} |
STLDeleteElements(&undecryptable_packets_); |
+ if (termination_packets_.get() != nullptr) { |
+ STLDeleteElements(termination_packets_.get()); |
+ } |
STLDeleteValues(&group_map_); |
ClearQueuedPackets(); |
} |
@@ -1497,9 +1501,9 @@ bool QuicConnection::WritePacketInner(QueuedPacket* packet) { |
++stats_.packets_discarded; |
return true; |
} |
- // Connection close packets are encrypted and saved, so don't exit early. |
- const bool is_connection_close = IsConnectionClose(*packet); |
- if (writer_->IsWriteBlocked() && !is_connection_close) { |
+ // Termination packets are encrypted and saved, so don't exit early. |
+ const bool is_termination_packet = IsTerminationPacket(*packet); |
+ if (writer_->IsWriteBlocked() && !is_termination_packet) { |
return false; |
} |
@@ -1508,12 +1512,14 @@ bool QuicConnection::WritePacketInner(QueuedPacket* packet) { |
packet_number_of_last_sent_packet_ = packet_number; |
QuicEncryptedPacket* encrypted = packet->serialized_packet.packet; |
- // Connection close packets are eventually owned by TimeWaitListManager. |
+ // Termination packets are eventually owned by TimeWaitListManager. |
// Others are deleted at the end of this call. |
- if (is_connection_close) { |
- DCHECK(connection_close_packet_.get() == nullptr); |
+ if (is_termination_packet) { |
+ if (termination_packets_.get() == nullptr) { |
+ termination_packets_.reset(new std::vector<QuicEncryptedPacket*>); |
+ } |
// Clone the packet so it's owned in the future. |
- connection_close_packet_.reset(encrypted->Clone()); |
+ termination_packets_->push_back(encrypted->Clone()); |
// This assures we won't try to write *forced* packets when blocked. |
// Return true to stop processing. |
if (writer_->IsWriteBlocked()) { |
@@ -2024,6 +2030,10 @@ bool QuicConnection::HasQueuedData() const { |
!queued_packets_.empty() || packet_generator_.HasQueuedFrames(); |
} |
+void QuicConnection::EnableSavingCryptoPackets() { |
+ save_crypto_packets_as_termination_packets_ = true; |
+} |
+ |
bool QuicConnection::CanWriteStreamData() { |
// Don't write stream data if there are negotiation or queued data packets |
// to send. Otherwise, continue and bundle as many frames as possible. |
@@ -2228,7 +2238,7 @@ HasRetransmittableData QuicConnection::IsRetransmittable( |
} |
} |
-bool QuicConnection::IsConnectionClose(const QueuedPacket& packet) { |
+bool QuicConnection::IsTerminationPacket(const QueuedPacket& packet) { |
const RetransmittableFrames* retransmittable_frames = |
packet.serialized_packet.retransmittable_frames; |
if (retransmittable_frames == nullptr) { |
@@ -2238,6 +2248,11 @@ bool QuicConnection::IsConnectionClose(const QueuedPacket& packet) { |
if (frame.type == CONNECTION_CLOSE_FRAME) { |
return true; |
} |
+ if (save_crypto_packets_as_termination_packets_ && |
+ frame.type == STREAM_FRAME && |
+ frame.stream_frame->stream_id == kCryptoStreamId) { |
+ return true; |
+ } |
} |
return false; |
} |