Index: net/quic/quic_connection.cc |
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc |
index 6838a1ec30a8c07484d194943f1b5793ff0c9466..d834f207630c5c563c30d154ae966b1554103f71 100644 |
--- a/net/quic/quic_connection.cc |
+++ b/net/quic/quic_connection.cc |
@@ -204,6 +204,7 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, |
random_generator_(helper->GetRandomGenerator()), |
connection_id_(connection_id), |
peer_address_(address), |
+ migrating_peer_port_(0), |
last_packet_revived_(false), |
last_size_(0), |
last_decrypted_packet_level_(ENCRYPTION_NONE), |
@@ -234,7 +235,10 @@ QuicConnection::QuicConnection(QuicConnectionId connection_id, |
version_negotiation_state_(START_NEGOTIATION), |
is_server_(is_server), |
connected_(true), |
- address_migrating_(false), |
+ peer_ip_changed_(false), |
+ peer_port_changed_(false), |
+ self_ip_changed_(false), |
+ self_port_changed_(false), |
max_flow_control_receive_window_bytes_( |
max_flow_control_receive_window_bytes) { |
if (max_flow_control_receive_window_bytes_ < kDefaultFlowControlSendWindow) { |
@@ -1105,18 +1109,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address, |
last_packet_revived_ = false; |
last_size_ = packet.length(); |
- address_migrating_ = false; |
- |
- if (peer_address_.address().empty()) { |
- peer_address_ = peer_address; |
- } |
- if (self_address_.address().empty()) { |
- self_address_ = self_address; |
- } |
- |
- if (!(peer_address == peer_address_ && self_address == self_address_)) { |
- address_migrating_ = true; |
- } |
+ CheckForAddressMigration(self_address, peer_address); |
stats_.bytes_received += packet.length(); |
++stats_.packets_received; |
@@ -1141,20 +1134,45 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address, |
SetPingAlarm(); |
} |
+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_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()); |
WriteQueuedPackets(); |
WritePendingRetransmissions(); |
- IsHandshake pending_handshake = visitor_->HasPendingHandshake() ? |
- IS_HANDSHAKE : NOT_HANDSHAKE; |
// Sending queued packets may have caused the socket to become write blocked, |
// or the congestion manager to prohibit sending. If we've sent everything |
// we had queued and we're still not blocked, let the visitor know it can |
// write more. |
- if (!CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, |
- pending_handshake)) { |
+ if (!CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA)) { |
return; |
} |
@@ -1166,11 +1184,8 @@ void QuicConnection::OnCanWrite() { |
// After the visitor writes, it may have caused the socket to become write |
// blocked or the congestion manager to prohibit sending, so check again. |
- pending_handshake = visitor_->HasPendingHandshake() ? |
- IS_HANDSHAKE : NOT_HANDSHAKE; |
if (visitor_->HasPendingWrites() && !resume_writes_alarm_->IsSet() && |
- CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, |
- pending_handshake)) { |
+ CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA)) { |
// We're not write blocked, but some stream didn't write out all of its |
// bytes. Register for 'immediate' resumption so we'll keep writing after |
// other connections and events have had a chance to use the thread. |
@@ -1185,12 +1200,23 @@ void QuicConnection::WriteIfNotBlocked() { |
} |
bool QuicConnection::ProcessValidatedPacket() { |
- if (address_migrating_) { |
+ if ((!FLAGS_quic_allow_port_migration && peer_port_changed_) || |
+ peer_ip_changed_ || self_ip_changed_ || self_port_changed_) { |
SendConnectionCloseWithDetails( |
QUIC_ERROR_MIGRATING_ADDRESS, |
- "Address migration is not yet a supported feature"); |
+ "IP or port migration is not yet a supported feature"); |
return false; |
} |
+ |
+ // Port migration is supported, do it now if port has changed. |
+ if (FLAGS_quic_allow_port_migration && |
+ peer_port_changed_) { |
+ DVLOG(1) << ENDPOINT << "Peer's port changed from " |
+ << peer_address_.port() << " to " << migrating_peer_port_ |
+ << ", migrating connection."; |
+ peer_address_ = IPEndPoint(peer_address_.address(), migrating_peer_port_); |
+ } |
+ |
time_of_last_received_packet_ = clock_->Now(); |
DVLOG(1) << ENDPOINT << "time of last received packet: " |
<< time_of_last_received_packet_.ToDebuggingValue(); |
@@ -1230,8 +1256,7 @@ void QuicConnection::WritePendingRetransmissions() { |
const QuicSentPacketManager::PendingRetransmission pending = |
sent_packet_manager_.NextPendingRetransmission(); |
if (GetPacketType(&pending.retransmittable_frames) == NORMAL && |
- !CanWrite(pending.transmission_type, HAS_RETRANSMITTABLE_DATA, |
- pending.retransmittable_frames.HasCryptoHandshake())) { |
+ !CanWrite(pending.transmission_type, HAS_RETRANSMITTABLE_DATA)) { |
break; |
} |
@@ -1269,8 +1294,8 @@ void QuicConnection::RetransmitUnackedPackets( |
WriteIfNotBlocked(); |
} |
-void QuicConnection::DiscardUnencryptedPackets() { |
- sent_packet_manager_.DiscardUnencryptedPackets(); |
+void QuicConnection::NeuterUnencryptedPackets() { |
+ sent_packet_manager_.NeuterUnencryptedPackets(); |
// This may have changed the retransmission timer, so re-arm it. |
retransmission_alarm_->Cancel(); |
QuicTime retransmission_time = sent_packet_manager_.GetRetransmissionTime(); |
@@ -1289,12 +1314,11 @@ bool QuicConnection::ShouldGeneratePacket( |
return true; |
} |
- return CanWrite(transmission_type, retransmittable, handshake); |
+ return CanWrite(transmission_type, retransmittable); |
} |
bool QuicConnection::CanWrite(TransmissionType transmission_type, |
- HasRetransmittableData retransmittable, |
- IsHandshake handshake) { |
+ HasRetransmittableData retransmittable) { |
if (writer_->IsWriteBlocked()) { |
visitor_->OnWriteBlocked(); |
return false; |
@@ -1342,8 +1366,7 @@ bool QuicConnection::WritePacket(QueuedPacket packet) { |
// TODO(ianswett): The congestion control should have been consulted before |
// serializing the packet, so this could be turned into a LOG_IF(DFATAL). |
if (packet.type == NORMAL && !CanWrite(packet.transmission_type, |
- packet.retransmittable, |
- packet.handshake)) { |
+ packet.retransmittable)) { |
return false; |
} |