| Index: net/quic/quic_connection.cc
|
| diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
|
| index 0698dd354dc3d2bf142c53a3ff0c430a5cb81a86..9932032f0ac3b2b868dc9c615c9f08e6e8caa499 100644
|
| --- a/net/quic/quic_connection.cc
|
| +++ b/net/quic/quic_connection.cc
|
| @@ -125,7 +125,7 @@ QuicConnection::~QuicConnection() {
|
| it != queued_packets_.end(); ++it) {
|
| delete it->packet;
|
| }
|
| - LOG(ERROR) << "Quic connection " << write_blocked_;
|
| + DLOG(INFO) << ENDPOINT << "write_blocked: " << write_blocked_;
|
| }
|
|
|
| bool QuicConnection::SelectMutualVersion(
|
| @@ -242,6 +242,7 @@ void QuicConnection::OnVersionNegotiationPacket(
|
| if (!SelectMutualVersion(packet.versions)) {
|
| SendConnectionCloseWithDetails(QUIC_INVALID_VERSION,
|
| "no common version found");
|
| + return;
|
| }
|
|
|
| version_negotiation_state_ = NEGOTIATED_VERSION;
|
| @@ -361,19 +362,18 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
|
| congestion_manager_.OnIncomingAckFrame(incoming_ack,
|
| time_of_last_received_packet_);
|
|
|
| - // Now the we have received an ack, we might be able to send queued packets.
|
| - if (!queued_packets_.empty()) {
|
| - QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
|
| - time_of_last_received_packet_, NOT_RETRANSMISSION,
|
| - HAS_RETRANSMITTABLE_DATA);
|
| - if (delay.IsZero()) {
|
| - helper_->UnregisterSendAlarmIfRegistered();
|
| - if (!write_blocked_) {
|
| - OnCanWrite();
|
| - }
|
| - } else if (!delay.IsInfinite()) {
|
| - helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay));
|
| + // Now the we have received an ack, we might be able to send packets which are
|
| + // queued locally, or drain streams which are blocked.
|
| + QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
|
| + time_of_last_received_packet_, NOT_RETRANSMISSION,
|
| + HAS_RETRANSMITTABLE_DATA);
|
| + if (delay.IsZero()) {
|
| + helper_->UnregisterSendAlarmIfRegistered();
|
| + if (!write_blocked_) {
|
| + OnCanWrite();
|
| }
|
| + } else if (!delay.IsInfinite()) {
|
| + helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay));
|
| }
|
| return connected_;
|
| }
|
| @@ -461,24 +461,8 @@ bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
|
| return true;
|
| }
|
|
|
| -void QuicConnection::UpdatePacketInformationReceivedByPeer(
|
| - const QuicAckFrame& incoming_ack) {
|
| - SequenceNumberSet acked_packets;
|
| -
|
| - // ValidateAck should fail if largest_observed ever shrinks.
|
| - DCHECK_LE(peer_largest_observed_packet_,
|
| - incoming_ack.received_info.largest_observed);
|
| - peer_largest_observed_packet_ = incoming_ack.received_info.largest_observed;
|
| -
|
| - if (incoming_ack.received_info.missing_packets.empty()) {
|
| - least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1;
|
| - } else {
|
| - least_packet_awaited_by_peer_ =
|
| - *(incoming_ack.received_info.missing_packets.begin());
|
| - }
|
| -
|
| - entropy_manager_.ClearSentEntropyBefore(least_packet_awaited_by_peer_ - 1);
|
| -
|
| +void QuicConnection::HandleAckForSentPackets(const QuicAckFrame& incoming_ack,
|
| + SequenceNumberSet* acked_packets) {
|
| int retransmitted_packets = 0;
|
| // Go through the packets we have not received an ack for and see if this
|
| // incoming_ack shows they've been seen by the peer.
|
| @@ -492,11 +476,9 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
|
| if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
|
| // Packet was acked, so remove it from our unacked packet list.
|
| DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
|
| - acked_packets.insert(sequence_number);
|
| + acked_packets->insert(sequence_number);
|
| delete unacked;
|
| - UnackedPacketMap::iterator it_tmp = it;
|
| - ++it;
|
| - unacked_packets_.erase(it_tmp);
|
| + unacked_packets_.erase(it++);
|
| retransmission_map_.erase(sequence_number);
|
| } else {
|
| // This is a packet which we planned on retransmitting and has not been
|
| @@ -522,6 +504,48 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
|
| }
|
| }
|
| }
|
| +}
|
| +
|
| +void QuicConnection::HandleAckForSentFecPackets(
|
| + const QuicAckFrame& incoming_ack, SequenceNumberSet* acked_packets) {
|
| + UnackedPacketMap::iterator it = unacked_fec_packets_.begin();
|
| + while (it != unacked_fec_packets_.end()) {
|
| + QuicPacketSequenceNumber sequence_number = it->first;
|
| + if (sequence_number > peer_largest_observed_packet_) {
|
| + break;
|
| + }
|
| + if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
|
| + DVLOG(1) << ENDPOINT << "Got an ack for fec packet: " << sequence_number;
|
| + acked_packets->insert(sequence_number);
|
| + unacked_fec_packets_.erase(it++);
|
| + } else {
|
| + DVLOG(1) << ENDPOINT << "Still missing ack for fec packet: "
|
| + << sequence_number;
|
| + ++it;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void QuicConnection::UpdatePacketInformationReceivedByPeer(
|
| + const QuicAckFrame& incoming_ack) {
|
| + // ValidateAck should fail if largest_observed ever shrinks.
|
| + DCHECK_LE(peer_largest_observed_packet_,
|
| + incoming_ack.received_info.largest_observed);
|
| + peer_largest_observed_packet_ = incoming_ack.received_info.largest_observed;
|
| +
|
| + if (incoming_ack.received_info.missing_packets.empty()) {
|
| + least_packet_awaited_by_peer_ = peer_largest_observed_packet_ + 1;
|
| + } else {
|
| + least_packet_awaited_by_peer_ =
|
| + *(incoming_ack.received_info.missing_packets.begin());
|
| + }
|
| +
|
| + entropy_manager_.ClearSentEntropyBefore(least_packet_awaited_by_peer_ - 1);
|
| +
|
| + SequenceNumberSet acked_packets;
|
| + HandleAckForSentPackets(incoming_ack, &acked_packets);
|
| + HandleAckForSentFecPackets(incoming_ack, &acked_packets);
|
| +
|
| if (acked_packets.size() > 0) {
|
| visitor_->OnAck(acked_packets);
|
| }
|
| @@ -725,7 +749,7 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
|
| self_address_ = self_address;
|
| }
|
|
|
| - if (!(peer_address == peer_address_) && (self_address == self_address_)) {
|
| + if (!(peer_address == peer_address_ && self_address == self_address_)) {
|
| address_migrating_ = true;
|
| }
|
|
|
| @@ -960,7 +984,7 @@ bool QuicConnection::IsRetransmission(
|
| it->second.number_retransmissions > 0;
|
| }
|
|
|
| -void QuicConnection::MaybeSetupRetransmission(
|
| +void QuicConnection::SetupRetransmission(
|
| QuicPacketSequenceNumber sequence_number) {
|
| RetransmissionMap::iterator it = retransmission_map_.find(sequence_number);
|
| if (it == retransmission_map_.end()) {
|
| @@ -973,9 +997,11 @@ void QuicConnection::MaybeSetupRetransmission(
|
| congestion_manager_.GetRetransmissionDelay(
|
| unacked_packets_.size(),
|
| retransmission_info.number_retransmissions);
|
| - retransmission_info.scheduled_time =
|
| - clock_->ApproximateNow().Add(retransmission_delay);
|
| - retransmission_timeouts_.push(retransmission_info);
|
| +
|
| + retransmission_timeouts_.push(RetransmissionTime(
|
| + sequence_number,
|
| + clock_->ApproximateNow().Add(retransmission_delay),
|
| + false));
|
|
|
| // Do not set the retransmisson alarm if we're already handling the
|
| // retransmission alarm because the retransmission alarm will be reset when
|
| @@ -987,6 +1013,18 @@ void QuicConnection::MaybeSetupRetransmission(
|
| // SendStreamData().
|
| }
|
|
|
| +void QuicConnection::SetupAbandonFecTimer(
|
| + QuicPacketSequenceNumber sequence_number) {
|
| + DCHECK(ContainsKey(unacked_fec_packets_, sequence_number));
|
| + QuicTime::Delta retransmission_delay =
|
| + QuicTime::Delta::FromMilliseconds(
|
| + congestion_manager_.DefaultRetransmissionTime().ToMilliseconds() * 3);
|
| + retransmission_timeouts_.push(RetransmissionTime(
|
| + sequence_number,
|
| + clock_->ApproximateNow().Add(retransmission_delay),
|
| + true));
|
| +}
|
| +
|
| void QuicConnection::DropPacket(QuicPacketSequenceNumber sequence_number) {
|
| UnackedPacketMap::iterator unacked_it =
|
| unacked_packets_.find(sequence_number);
|
| @@ -1077,7 +1115,11 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
|
| // Set the retransmit alarm only when we have sent the packet to the client
|
| // and not when it goes to the pending queue, otherwise we will end up adding
|
| // an entry to retransmission_timeout_ every time we attempt a write.
|
| - MaybeSetupRetransmission(sequence_number);
|
| + if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
|
| + SetupRetransmission(sequence_number);
|
| + } else if (packet->is_fec_packet()) {
|
| + SetupAbandonFecTimer(sequence_number);
|
| + }
|
|
|
| congestion_manager_.SentPacket(sequence_number, now, packet->length(),
|
| retransmission);
|
| @@ -1111,6 +1153,10 @@ bool QuicConnection::OnSerializedPacket(
|
| retransmission_map_.insert(
|
| make_pair(serialized_packet.sequence_number,
|
| RetransmissionInfo(serialized_packet.sequence_number)));
|
| + } else if (serialized_packet.packet->is_fec_packet()) {
|
| + unacked_fec_packets_.insert(make_pair(
|
| + serialized_packet.sequence_number,
|
| + serialized_packet.retransmittable_frames));
|
| }
|
| return SendOrQueuePacket(encryption_level_,
|
| serialized_packet.sequence_number,
|
| @@ -1180,6 +1226,17 @@ void QuicConnection::SendAck() {
|
| packet_generator_.SetShouldSendAck(send_feedback);
|
| }
|
|
|
| +void QuicConnection::MaybeAbandonFecPacket(
|
| + QuicPacketSequenceNumber sequence_number) {
|
| + if (!ContainsKey(unacked_fec_packets_, sequence_number)) {
|
| + DVLOG(2) << ENDPOINT << "no need to abandon fec packet: "
|
| + << sequence_number << "; it's already acked'";
|
| + return;
|
| + }
|
| + congestion_manager_.AbandoningPacket(sequence_number);
|
| + // TODO(satyashekhar): Should this decrease the congestion window?
|
| +}
|
| +
|
| QuicTime QuicConnection::OnRetransmissionTimeout() {
|
| // This guards against registering the alarm later than we should.
|
| //
|
| @@ -1192,19 +1249,24 @@ QuicTime QuicConnection::OnRetransmissionTimeout() {
|
|
|
| for (size_t i = 0; i < max_packets_per_retransmission_alarm_ &&
|
| !retransmission_timeouts_.empty(); ++i) {
|
| - RetransmissionInfo retransmission_info = retransmission_timeouts_.top();
|
| - DCHECK(retransmission_info.scheduled_time.IsInitialized());
|
| - if (retransmission_info.scheduled_time > clock_->ApproximateNow()) {
|
| + RetransmissionTime retransmission_time = retransmission_timeouts_.top();
|
| + DCHECK(retransmission_time.scheduled_time.IsInitialized());
|
| + if (retransmission_time.scheduled_time > clock_->ApproximateNow()) {
|
| break;
|
| }
|
| retransmission_timeouts_.pop();
|
| - if (!MaybeRetransmitPacketForRTO(retransmission_info.sequence_number)) {
|
| +
|
| + if (retransmission_time.for_fec) {
|
| + MaybeAbandonFecPacket(retransmission_time.sequence_number);
|
| + continue;
|
| + } else if (
|
| + !MaybeRetransmitPacketForRTO(retransmission_time.sequence_number)) {
|
| DLOG(INFO) << ENDPOINT << "MaybeRetransmitPacketForRTO failed: "
|
| << "adding an extra delay for "
|
| - << retransmission_info.sequence_number;
|
| - retransmission_info.scheduled_time = clock_->ApproximateNow().Add(
|
| + << retransmission_time.sequence_number;
|
| + retransmission_time.scheduled_time = clock_->ApproximateNow().Add(
|
| congestion_manager_.DefaultRetransmissionTime());
|
| - retransmission_timeouts_.push(retransmission_info);
|
| + retransmission_timeouts_.push(retransmission_time);
|
| }
|
| }
|
|
|
| @@ -1377,21 +1439,21 @@ bool QuicConnection::HasQueuedData() const {
|
| }
|
|
|
| void QuicConnection::SetIdleNetworkTimeout(QuicTime::Delta timeout) {
|
| - // if (timeout < idle_network_timeout_) {
|
| + if (timeout < idle_network_timeout_) {
|
| idle_network_timeout_ = timeout;
|
| CheckForTimeout();
|
| - // } else {
|
| - // idle_network_timeout_ = timeout;
|
| - // }
|
| + } else {
|
| + idle_network_timeout_ = timeout;
|
| + }
|
| }
|
|
|
| void QuicConnection::SetOverallConnectionTimeout(QuicTime::Delta timeout) {
|
| - // if (timeout < overall_connection_timeout_) {
|
| + if (timeout < overall_connection_timeout_) {
|
| overall_connection_timeout_ = timeout;
|
| CheckForTimeout();
|
| - // } else {
|
| - // overall_connection_timeout_ = timeout;
|
| - // }
|
| + } else {
|
| + overall_connection_timeout_ = timeout;
|
| + }
|
| }
|
|
|
| bool QuicConnection::CheckForTimeout() {
|
| @@ -1399,6 +1461,9 @@ bool QuicConnection::CheckForTimeout() {
|
| QuicTime time_of_last_packet = std::max(time_of_last_received_packet_,
|
| time_of_last_sent_packet_);
|
|
|
| + // |delta| can be < 0 as |now| is approximate time but |time_of_last_packet|
|
| + // is accurate time. However, this should not change the behavior of
|
| + // timeout handling.
|
| QuicTime::Delta delta = now.Subtract(time_of_last_packet);
|
| DVLOG(1) << ENDPOINT << "last packet "
|
| << time_of_last_packet.ToDebuggingValue()
|
|
|