| 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;
|
| }
|
|
|
|
|