| Index: net/quic/quic_connection.cc
|
| diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
|
| index 180e196dd6e5509c58ea69f4cb2ad25ab20fb7ab..e29130a04358b116959a026e1a04b73259a4988e 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();
|
| }
|
| @@ -843,12 +847,12 @@ bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
|
| return false;
|
| }
|
|
|
| - for (QuicPacketNumber revived_packet : incoming_ack.revived_packets) {
|
| - if (!incoming_ack.missing_packets.Contains(revived_packet)) {
|
| - DLOG(ERROR) << ENDPOINT
|
| - << "Peer specified revived packet which was not missing.";
|
| - return false;
|
| - }
|
| + if (incoming_ack.latest_revived_packet != 0 &&
|
| + !incoming_ack.missing_packets.Contains(
|
| + incoming_ack.latest_revived_packet)) {
|
| + DLOG(ERROR) << ENDPOINT
|
| + << "Peer specified revived packet which was not missing.";
|
| + return false;
|
| }
|
| return true;
|
| }
|
| @@ -1103,8 +1107,7 @@ void QuicConnection::SendVersionNegotiationPacket() {
|
| self_address().address(), peer_address());
|
|
|
| if (result.status == WRITE_STATUS_ERROR) {
|
| - // We can't send an error as the socket is presumably borked.
|
| - CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
|
| + OnWriteError(result.error_code);
|
| return;
|
| }
|
| if (result.status == WRITE_STATUS_BLOCKED) {
|
| @@ -1340,6 +1343,15 @@ bool QuicConnection::ProcessValidatedPacket() {
|
| }
|
|
|
| if (peer_ip_changed_ || peer_port_changed_) {
|
| + PeerAddressChangeType type = DeterminePeerAddressChangeType();
|
| + if (type != NO_CHANGE && type != UNKNOWN &&
|
| + (FLAGS_quic_disable_non_nat_address_migration &&
|
| + type != NAT_PORT_REBINDING && type != IPV4_SUBNET_REBINDING)) {
|
| + SendConnectionCloseWithDetails(QUIC_ERROR_MIGRATING_ADDRESS,
|
| + "Invalid peer address migration.");
|
| + return false;
|
| + }
|
| +
|
| IPEndPoint old_peer_address = peer_address_;
|
| peer_address_ = IPEndPoint(
|
| peer_ip_changed_ ? migrating_peer_ip_ : peer_address_.address(),
|
| @@ -1498,9 +1510,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;
|
| }
|
|
|
| @@ -1509,12 +1521,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()) {
|
| @@ -1523,9 +1537,7 @@ bool QuicConnection::WritePacketInner(QueuedPacket* packet) {
|
| }
|
| }
|
|
|
| - if (!FLAGS_quic_allow_oversized_packets_for_test) {
|
| - DCHECK_LE(encrypted->length(), kMaxPacketSize);
|
| - }
|
| + DCHECK_LE(encrypted->length(), kMaxPacketSize);
|
| DCHECK_LE(encrypted->length(), packet_generator_.GetMaxPacketLength());
|
| DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
|
| << (packet->serialized_packet.is_fec_packet
|
| @@ -1738,6 +1750,10 @@ void QuicConnection::SendOrQueuePacket(QueuedPacket packet) {
|
| }
|
| }
|
|
|
| +PeerAddressChangeType QuicConnection::DeterminePeerAddressChangeType() {
|
| + return UNKNOWN;
|
| +}
|
| +
|
| void QuicConnection::SendPing() {
|
| if (retransmission_alarm_->IsSet()) {
|
| return;
|
| @@ -2027,6 +2043,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.
|
| @@ -2231,7 +2251,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) {
|
| @@ -2241,6 +2261,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;
|
| }
|
| @@ -2251,10 +2276,6 @@ void QuicConnection::SetMtuDiscoveryTarget(QuicByteCount target) {
|
|
|
| QuicByteCount QuicConnection::LimitMaxPacketSize(
|
| QuicByteCount suggested_max_packet_size) {
|
| - if (FLAGS_quic_allow_oversized_packets_for_test) {
|
| - return suggested_max_packet_size;
|
| - }
|
| -
|
| if (peer_address_.address().empty()) {
|
| LOG(DFATAL) << "Attempted to use a connection without a valid peer address";
|
| return suggested_max_packet_size;
|
|
|