Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Unified Diff: net/quic/quic_connection.cc

Issue 1811043002: Landing Recent QUIC changes until 2016-03-15 16:26 UTC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add an export clause. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_stats.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_connection.cc
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 74bc9e3aaad9c97b7f8ca048a65b9cf814861f29..7dea3eedffa23d28cccf7aa8b1aa223801ab68ff 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -223,7 +223,6 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
random_generator_(helper->GetRandomGenerator()),
connection_id_(connection_id),
peer_address_(address),
- migrating_peer_port_(0),
last_packet_decrypted_(false),
last_size_(0),
current_packet_data_(nullptr),
@@ -235,6 +234,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
pending_version_negotiation_packet_(false),
save_crypto_packets_as_termination_packets_(false),
silent_close_enabled_(false),
+ close_connection_after_five_rtos_(false),
received_packet_manager_(&stats_),
ack_queued_(false),
num_retransmittable_packets_received_since_last_ack_sent_(0),
@@ -281,10 +281,6 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id,
version_negotiation_state_(START_NEGOTIATION),
perspective_(perspective),
connected_(true),
- peer_ip_changed_(false),
- peer_port_changed_(false),
- self_ip_changed_(false),
- self_port_changed_(false),
can_truncate_connection_ids_(true),
mtu_discovery_target_(0),
mtu_probe_count_(0),
@@ -370,6 +366,10 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
config.HasClientSentConnectionOption(kAKD2, perspective_)) {
ack_mode_ = ACK_DECIMATION_WITH_REORDERING;
}
+ if (FLAGS_quic_enable_rto_timeout &&
+ config.HasClientSentConnectionOption(k5RTO, perspective_)) {
+ close_connection_after_five_rtos_ = true;
+ }
}
void QuicConnection::OnSendConnectionState(
@@ -580,6 +580,13 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
"when multipath is not enabled.");
return false;
}
+ if (!packet_generator_.IsPendingPacketEmpty()) {
+ QUIC_BUG << "Pending frames must be serialized before incoming packets are "
+ << "processed, because that may change a queued ack frame.";
+ SendConnectionCloseWithDetails(QUIC_INTERNAL_ERROR,
+ "Should not process packets while sending.");
+ return false;
+ }
// If this packet has already been seen, or the sender has told us that it
// will not be retransmitted, then stop processing the packet.
@@ -669,7 +676,7 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
return false;
}
- if (FLAGS_quic_respect_send_alarm2 && send_alarm_->IsSet()) {
+ if (send_alarm_->IsSet()) {
send_alarm_->Cancel();
}
ProcessAckFrame(incoming_ack);
@@ -1024,6 +1031,10 @@ void QuicConnection::PopulateAckFrame(QuicAckFrame* ack) {
clock_->ApproximateNow());
}
+const QuicFrame QuicConnection::GetUpdatedAckFrame() {
+ return received_packet_manager_.GetUpdatedAckFrame(clock_->ApproximateNow());
+}
+
void QuicConnection::PopulateStopWaitingFrame(
QuicStopWaitingFrame* stop_waiting) {
stop_waiting->least_unacked = GetLeastUnacked();
@@ -1105,7 +1116,7 @@ QuicConsumedData QuicConnection::SendStreamData(
// also if there is possibility of revival. Only bundle an ack if there's no
// processing left that may cause received_info_ to change.
ScopedRetransmissionScheduler alarm_delayer(this);
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
return packet_generator_.ConsumeData(id, iov, offset, fin, listener);
}
@@ -1113,7 +1124,7 @@ void QuicConnection::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(QuicFrame(new QuicRstStreamFrame(
id, AdjustErrorForVersion(error, version()), bytes_written)));
@@ -1147,20 +1158,20 @@ void QuicConnection::SendRstStream(QuicStreamId id,
void QuicConnection::SendWindowUpdate(QuicStreamId id,
QuicStreamOffset byte_offset) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicWindowUpdateFrame(id, byte_offset)));
}
void QuicConnection::SendBlocked(QuicStreamId id) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(QuicFrame(new QuicBlockedFrame(id)));
}
void QuicConnection::SendPathClose(QuicPathId path_id) {
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(QuicFrame(new QuicPathCloseFrame(path_id)));
OnPathClosed(path_id);
}
@@ -1201,17 +1212,13 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
last_size_ = packet.length();
current_packet_data_ = packet.data();
- if (FLAGS_check_peer_address_change_after_decryption) {
- last_packet_destination_address_ = self_address;
- last_packet_source_address_ = peer_address;
- if (!IsInitializedIPEndPoint(self_address_)) {
- self_address_ = last_packet_destination_address_;
- }
- if (!IsInitializedIPEndPoint(peer_address_)) {
- peer_address_ = last_packet_source_address_;
- }
- } else {
- CheckForAddressMigration(self_address, peer_address);
+ last_packet_destination_address_ = self_address;
+ last_packet_source_address_ = peer_address;
+ if (!IsInitializedIPEndPoint(self_address_)) {
+ self_address_ = last_packet_destination_address_;
+ }
+ if (!IsInitializedIPEndPoint(peer_address_)) {
+ peer_address_ = last_packet_source_address_;
}
stats_.bytes_received += packet.length();
@@ -1242,35 +1249,6 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
current_packet_data_ = nullptr;
}
-void QuicConnection::CheckForAddressMigration(const IPEndPoint& self_address,
- const IPEndPoint& peer_address) {
- peer_ip_changed_ = false;
- peer_port_changed_ = false;
- self_ip_changed_ = false;
- self_port_changed_ = false;
-
- if (peer_address_.address().empty()) {
- peer_address_ = peer_address;
- }
- if (self_address_.address().empty()) {
- self_address_ = self_address;
- }
-
- if (!peer_address.address().empty() && !peer_address_.address().empty()) {
- peer_ip_changed_ = (peer_address.address() != peer_address_.address());
- peer_port_changed_ = (peer_address.port() != peer_address_.port());
-
- // Store in case we want to migrate connection in ProcessValidatedPacket.
- migrating_peer_ip_ = peer_address.address();
- migrating_peer_port_ = peer_address.port();
- }
-
- if (!self_address.address().empty() && !self_address_.address().empty()) {
- self_ip_changed_ = (self_address.address() != self_address_.address());
- self_port_changed_ = (self_address.port() != self_address_.port());
- }
-}
-
void QuicConnection::OnCanWrite() {
DCHECK(!writer_->IsWriteBlocked());
@@ -1285,8 +1263,8 @@ void QuicConnection::OnCanWrite() {
return;
}
- { // Limit the scope of the bundler. ACK inclusion happens elsewhere.
- ScopedPacketBundler bundler(this, NO_ACK);
+ {
+ ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
visitor_->OnCanWrite();
visitor_->PostProcessAfterData();
}
@@ -1310,7 +1288,7 @@ void QuicConnection::WriteIfNotBlocked() {
void QuicConnection::WriteAndBundleAcksIfNotBlocked() {
if (!writer_->IsWriteBlocked()) {
- ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK);
+ ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
OnCanWrite();
}
}
@@ -1321,24 +1299,14 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
return false;
}
- if (FLAGS_check_peer_address_change_after_decryption) {
- if (perspective_ == Perspective::IS_SERVER &&
- IsInitializedIPEndPoint(self_address_) &&
- IsInitializedIPEndPoint(last_packet_destination_address_) &&
- (!(self_address_ == last_packet_destination_address_))) {
- SendConnectionCloseWithDetails(
- QUIC_ERROR_MIGRATING_ADDRESS,
- "Self address migration is not supported at the server.");
- return false;
- }
- } else {
- if (perspective_ == Perspective::IS_SERVER &&
- (self_ip_changed_ || self_port_changed_)) {
- SendConnectionCloseWithDetails(
- QUIC_ERROR_MIGRATING_ADDRESS,
- "Self address migration is not supported at the server.");
- return false;
- }
+ if (perspective_ == Perspective::IS_SERVER &&
+ IsInitializedIPEndPoint(self_address_) &&
+ IsInitializedIPEndPoint(last_packet_destination_address_) &&
+ (!(self_address_ == last_packet_destination_address_))) {
+ SendConnectionCloseWithDetails(
+ QUIC_ERROR_MIGRATING_ADDRESS,
+ "Self address migration is not supported at the server.");
+ return false;
}
if (!Near(header.packet_number, last_header_.packet_number)) {
@@ -1474,17 +1442,15 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
return false;
}
- if (FLAGS_quic_respect_send_alarm2) {
- // Allow acks to be sent immediately.
- // TODO(ianswett): Remove retransmittable from
- // SendAlgorithmInterface::TimeUntilSend.
- if (retransmittable == NO_RETRANSMITTABLE_DATA) {
- return true;
- }
- // If the send alarm is set, wait for it to fire.
- if (send_alarm_->IsSet()) {
- return false;
- }
+ // Allow acks to be sent immediately.
+ // TODO(ianswett): Remove retransmittable from
+ // SendAlgorithmInterface::TimeUntilSend.
+ if (retransmittable == NO_RETRANSMITTABLE_DATA) {
+ return true;
+ }
+ // If the send alarm is set, wait for it to fire.
+ if (send_alarm_->IsSet()) {
+ return false;
}
QuicTime now = clock_->Now();
@@ -1502,9 +1468,6 @@ bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
<< "ms";
return false;
}
- if (!FLAGS_quic_respect_send_alarm2) {
- send_alarm_->Cancel();
- }
return true;
}
@@ -1760,7 +1723,7 @@ void QuicConnection::OnPingTimeout() {
}
void QuicConnection::SendPing() {
- ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK);
+ ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED);
packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame()));
// Send PING frame immediately, without checking for congestion window bounds.
packet_generator_.FlushAllQueuedFrames();
@@ -1782,6 +1745,14 @@ void QuicConnection::OnRetransmissionTimeout() {
return;
}
+ if (close_connection_after_five_rtos_ &&
+ sent_packet_manager_.consecutive_rto_count() >= 4) {
+ // Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred.
+ SendConnectionCloseWithDetails(QUIC_TOO_MANY_RTOS,
+ "5 consecutive retransmission timeouts");
+ return;
+ }
+
sent_packet_manager_.OnRetransmissionTimeout();
WriteIfNotBlocked();
@@ -1956,7 +1927,7 @@ void QuicConnection::SendGoAway(QuicErrorCode error,
<< QuicUtils::ErrorToString(error) << " (" << error << ")";
// Opportunistically bundle an ack with this outgoing packet.
- ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK);
+ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING);
packet_generator_.AddControlFrame(
QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason)));
}
@@ -2121,7 +2092,7 @@ void QuicConnection::MaybeSetMtuAlarm() {
QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
QuicConnection* connection,
- AckBundling send_ack)
+ AckBundling ack_mode)
: connection_(connection),
already_in_batch_mode_(connection != nullptr &&
connection->packet_generator_.InBatchMode()) {
@@ -2134,18 +2105,30 @@ QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
DVLOG(1) << "Entering Batch Mode.";
connection_->packet_generator_.StartBatchOperations();
}
- // Bundle an ack if the alarm is set or with every second packet if we need to
- // raise the peer's least unacked.
- bool ack_pending =
- connection_->ack_alarm_->IsSet() || connection_->stop_waiting_count_ > 1;
- if (send_ack == SEND_ACK || (send_ack == BUNDLE_PENDING_ACK && ack_pending)) {
+ if (ShouldSendAck(ack_mode)) {
DVLOG(1) << "Bundling ack with outgoing packet.";
- DCHECK(send_ack == SEND_ACK || connection_->ack_frame_updated() ||
+ DCHECK(ack_mode == SEND_ACK || connection_->ack_frame_updated() ||
connection_->stop_waiting_count_ > 1);
connection_->SendAck();
}
}
+bool QuicConnection::ScopedPacketBundler::ShouldSendAck(
+ AckBundling ack_mode) const {
+ switch (ack_mode) {
+ case SEND_ACK:
+ return true;
+ case SEND_ACK_IF_QUEUED:
+ return connection_->ack_queued();
+ case SEND_ACK_IF_PENDING:
+ return connection_->ack_alarm_->IsSet() ||
+ connection_->stop_waiting_count_ > 1;
+ default:
+ QUIC_BUG << "Unsupported ack_mode.";
+ return true;
+ }
+}
+
QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() {
if (connection_ == nullptr) {
return;
@@ -2271,50 +2254,25 @@ void QuicConnection::DiscoverMtu() {
void QuicConnection::MaybeMigrateConnectionToNewPeerAddress() {
IPEndPoint last_peer_address;
- if (FLAGS_check_peer_address_change_after_decryption) {
- last_peer_address = last_packet_source_address_;
- } else {
- last_peer_address = IPEndPoint(
- peer_ip_changed_ ? migrating_peer_ip_ : peer_address_.address(),
- peer_port_changed_ ? migrating_peer_port_ : peer_address_.port());
- }
+ last_peer_address = last_packet_source_address_;
PeerAddressChangeType peer_address_change_type =
QuicUtils::DetermineAddressChangeType(peer_address_, last_peer_address);
// TODO(fayang): Currently, all peer address change type are allowed. Need to
// add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
- // determine whehter |type| is allowed.
- if (FLAGS_check_peer_address_change_after_decryption) {
- if (peer_address_change_type == NO_CHANGE) {
- return;
- }
-
- IPEndPoint old_peer_address = peer_address_;
- peer_address_ = last_packet_source_address_;
-
- DVLOG(1) << ENDPOINT << "Peer's ip:port changed from "
- << old_peer_address.ToString() << " to "
- << peer_address_.ToString() << ", migrating connection.";
-
- visitor_->OnConnectionMigration(peer_address_change_type);
- sent_packet_manager_.OnConnectionMigration(peer_address_change_type);
-
+ // determine whether |type| is allowed.
+ if (peer_address_change_type == NO_CHANGE) {
return;
}
- if (peer_ip_changed_ || peer_port_changed_) {
- IPEndPoint old_peer_address = peer_address_;
- peer_address_ = IPEndPoint(
- peer_ip_changed_ ? migrating_peer_ip_ : peer_address_.address(),
- peer_port_changed_ ? migrating_peer_port_ : peer_address_.port());
+ IPEndPoint old_peer_address = peer_address_;
+ peer_address_ = last_packet_source_address_;
- DVLOG(1) << ENDPOINT << "Peer's ip:port changed from "
- << old_peer_address.ToString() << " to "
- << peer_address_.ToString() << ", migrating connection.";
+ DVLOG(1) << ENDPOINT << "Peer's ip:port changed from "
+ << old_peer_address.ToString() << " to " << peer_address_.ToString()
+ << ", migrating connection.";
- visitor_->OnConnectionMigration(peer_address_change_type);
- DCHECK_NE(peer_address_change_type, NO_CHANGE);
- sent_packet_manager_.OnConnectionMigration(peer_address_change_type);
- }
+ visitor_->OnConnectionMigration(peer_address_change_type);
+ sent_packet_manager_.OnConnectionMigration(peer_address_change_type);
}
void QuicConnection::OnPathClosed(QuicPathId path_id) {
« no previous file with comments | « net/quic/quic_connection.h ('k') | net/quic/quic_connection_stats.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698