Land Recent QUIC Changes.

Cleanup. Saner QuicConnectionTest around entropy hashes; initialize all
fields in QuicAckFrame.

Merge internal change: 58299852
https://codereview.chromium.org/107573005/


QUIC Cleanup to use GetRetransmissionTime() instead of
GetRetransmissionDelay() in SentPacketManager to allow the
SentPacketManager more future control over the retransmission timer.

Merge internal change: 58289241
https://codereview.chromium.org/116953002/


Added GetIncomingReliableStream method to QuicSessionPeer and other
cosmetic changes.

This is part of "Change the ownership model for ...QuicStream and
QuicFasterStatsGatherer" internal change.

Merge internal change: 58281240
https://codereview.chromium.org/114973006/


QuicSentPacketManager cleanup CL to move the handling of acks into one
place.

Merge internal change: 58181919
https://codereview.chromium.org/115933004/

[email protected]

Review URL: https://codereview.chromium.org/100543004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241489 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/quic/congestion_control/inter_arrival_sender_test.cc b/net/quic/congestion_control/inter_arrival_sender_test.cc
index fe8dd3c..7d9c39c 100644
--- a/net/quic/congestion_control/inter_arrival_sender_test.cc
+++ b/net/quic/congestion_control/inter_arrival_sender_test.cc
@@ -41,7 +41,7 @@
       QuicByteCount bytes_in_packet = kDefaultMaxPacketSize;
       sent_packets_[sequence_number_] =
           new class SendAlgorithmInterface::SentPacket(
-              bytes_in_packet, send_clock_.Now(), HAS_RETRANSMITTABLE_DATA);
+              bytes_in_packet, send_clock_.Now());
 
       sender_.OnPacketSent(send_clock_.Now(), sequence_number_, bytes_in_packet,
                            NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 87a5f9c..44c943f 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -24,19 +24,13 @@
  public:
   class SentPacket {
    public:
-    SentPacket(QuicByteCount bytes,
-               QuicTime timestamp,
-               HasRetransmittableData has_retransmittable_data)
+    SentPacket(QuicByteCount bytes, QuicTime timestamp)
         : bytes_sent_(bytes),
           send_timestamp_(timestamp),
-          has_retransmittable_data_(has_retransmittable_data),
           nack_count_(0) {
     }
     QuicByteCount bytes_sent() const { return bytes_sent_; }
     const QuicTime& send_timestamp() const { return send_timestamp_; }
-    HasRetransmittableData has_retransmittable_data() const {
-      return has_retransmittable_data_;
-    }
     size_t nack_count() const { return nack_count_; }
 
     void Nack(size_t min_nacks) {
@@ -46,7 +40,6 @@
    private:
     QuicByteCount bytes_sent_;
     QuicTime send_timestamp_;
-    HasRetransmittableData has_retransmittable_data_;
     size_t nack_count_;
   };
 
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 51a83cc..5cc630d 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -506,12 +506,10 @@
 
   if (reset_retransmission_alarm) {
     retransmission_alarm_->Cancel();
-    // Reset the RTO and FEC alarms if the are unacked packets.
-    if (sent_packet_manager_.HasUnackedPackets()) {
-      QuicTime::Delta retransmission_delay =
-          sent_packet_manager_.GetRetransmissionDelay();
-      retransmission_alarm_->Set(
-          clock_->ApproximateNow().Add(retransmission_delay));
+    QuicTime retransmission_time =
+        sent_packet_manager_.GetRetransmissionTime();
+    if (retransmission_time != QuicTime::Zero()) {
+      retransmission_alarm_->Set(retransmission_time);
     }
   }
 }
@@ -1084,25 +1082,6 @@
   return true;
 }
 
-void QuicConnection::SetupRetransmissionAlarm(
-    QuicPacketSequenceNumber sequence_number) {
-  if (!sent_packet_manager_.HasRetransmittableFrames(sequence_number)) {
-    DVLOG(1) << ENDPOINT << "Will not retransmit packet " << sequence_number;
-    return;
-  }
-
-  // Do not set the retransmission alarm if we're already handling one, since
-  // it will be reset when OnRetransmissionTimeout completes.
-  if (retransmission_alarm_->IsSet()) {
-    return;
-  }
-
-  QuicTime::Delta retransmission_delay =
-      sent_packet_manager_.GetRetransmissionDelay();
-  retransmission_alarm_->Set(
-      clock_->ApproximateNow().Add(retransmission_delay));
-}
-
 bool QuicConnection::WritePacket(EncryptionLevel level,
                                  QuicPacketSequenceNumber sequence_number,
                                  QuicPacket* packet,
@@ -1297,13 +1276,6 @@
   DVLOG(1) << ENDPOINT << "time of last sent packet: "
            << now.ToDebuggingValue();
 
-  // 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.
-  if (retransmittable == HAS_RETRANSMITTABLE_DATA || is_fec_packet) {
-    SetupRetransmissionAlarm(sequence_number);
-  }
-
   // TODO(ianswett): Change the sequence number length and other packet creator
   // options by a more explicit API than setting a struct value directly.
   packet_creator_.UpdateSequenceNumberLength(
@@ -1314,6 +1286,19 @@
   sent_packet_manager_.OnPacketSent(sequence_number, now, length,
                                     transmission_type, retransmittable);
 
+  // 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.
+  // Do not set the retransmission alarm if we're already handling one, since
+  // it will be reset when OnRetransmissionTimeout completes.
+  if ((retransmittable == HAS_RETRANSMITTABLE_DATA || is_fec_packet) &&
+      !retransmission_alarm_->IsSet()) {
+    QuicTime retransmission_time =
+        sent_packet_manager_.GetRetransmissionTime();
+    DCHECK(retransmission_time != QuicTime::Zero());
+    retransmission_alarm_->Set(retransmission_time);
+  }
+
   stats_.bytes_sent += result.bytes_written;
   ++stats_.packets_sent;
 
@@ -1399,11 +1384,11 @@
   WriteIfNotBlocked();
 
   // Ensure the retransmission alarm is always set if there are unacked packets.
-  if (sent_packet_manager_.HasUnackedPackets() && !HasQueuedData() &&
-      !retransmission_alarm_->IsSet()) {
-    QuicTime rto_timeout = clock_->ApproximateNow().Add(
-        sent_packet_manager_.GetRetransmissionDelay());
-    retransmission_alarm_->Set(rto_timeout);
+  if (!HasQueuedData() && !retransmission_alarm_->IsSet()) {
+    QuicTime rto_timeout = sent_packet_manager_.GetRetransmissionTime();
+    if (rto_timeout != QuicTime::Zero()) {
+      retransmission_alarm_->Set(rto_timeout);
+    }
   }
 }
 
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index beb8985..b7cf2d2 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -502,37 +502,6 @@
     Force forced;
   };
 
-  struct RetransmissionInfo {
-    RetransmissionInfo(QuicPacketSequenceNumber sequence_number,
-                       QuicSequenceNumberLength sequence_number_length,
-                       QuicTime sent_time)
-        : sequence_number(sequence_number),
-          sequence_number_length(sequence_number_length),
-          sent_time(sent_time),
-          number_nacks(0),
-          number_retransmissions(0) {
-    }
-
-    QuicPacketSequenceNumber sequence_number;
-    QuicSequenceNumberLength sequence_number_length;
-    QuicTime sent_time;
-    size_t number_nacks;
-    size_t number_retransmissions;
-  };
-
-  struct RetransmissionTime {
-    RetransmissionTime(QuicPacketSequenceNumber sequence_number,
-                       const QuicTime& scheduled_time,
-                       bool for_fec)
-        : sequence_number(sequence_number),
-          scheduled_time(scheduled_time),
-          for_fec(for_fec) { }
-
-    QuicPacketSequenceNumber sequence_number;
-    QuicTime scheduled_time;
-    bool for_fec;
-  };
-
   struct PendingWrite {
     PendingWrite(QuicPacketSequenceNumber sequence_number,
                  TransmissionType transmission_type,
@@ -555,27 +524,12 @@
     size_t length;
   };
 
-  class RetransmissionTimeComparator {
-   public:
-    bool operator()(const RetransmissionTime& lhs,
-                    const RetransmissionTime& rhs) const {
-      DCHECK(lhs.scheduled_time.IsInitialized() &&
-             rhs.scheduled_time.IsInitialized());
-      return lhs.scheduled_time > rhs.scheduled_time;
-    }
-  };
-
   typedef std::list<QueuedPacket> QueuedPacketList;
   typedef std::map<QuicFecGroupNumber, QuicFecGroup*> FecGroupMap;
-  typedef std::priority_queue<RetransmissionTime,
-                              std::vector<RetransmissionTime>,
-                              RetransmissionTimeComparator>
-      RetransmissionTimeouts;
 
   // Sends a version negotiation packet to the peer.
   void SendVersionNegotiationPacket();
 
-  void SetupRetransmissionAlarm(QuicPacketSequenceNumber sequence_number);
   bool IsRetransmission(QuicPacketSequenceNumber sequence_number);
 
   void SetupAbandonFecTimer(QuicPacketSequenceNumber sequence_number);
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 39655d0..108cf04 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -31,6 +31,7 @@
 using testing::_;
 using testing::AnyNumber;
 using testing::ContainerEq;
+using testing::Contains;
 using testing::DoAll;
 using testing::InSequence;
 using testing::InvokeWithoutArgs;
@@ -781,6 +782,40 @@
     return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
   }
 
+  // Initialize a frame acknowledging all packets up to largest_observed.
+  const QuicAckFrame InitAckFrame(QuicPacketSequenceNumber largest_observed,
+                                  QuicPacketSequenceNumber least_unacked) {
+    QuicAckFrame frame(largest_observed, QuicTime::Zero(), least_unacked);
+    if (largest_observed > 0) {
+      frame.received_info.entropy_hash =
+        QuicConnectionPeer::GetSentEntropyHash(&connection_, largest_observed);
+    }
+    return frame;
+  }
+
+  // Explicitly nack a packet.
+  void NackPacket(QuicPacketSequenceNumber missing, QuicAckFrame* frame) {
+    frame->received_info.missing_packets.insert(missing);
+    frame->received_info.entropy_hash ^=
+      QuicConnectionPeer::GetSentEntropyHash(&connection_, missing);
+    if (missing > 1) {
+      frame->received_info.entropy_hash ^=
+        QuicConnectionPeer::GetSentEntropyHash(&connection_, missing - 1);
+    }
+  }
+
+  // Undo nacking a packet within the frame.
+  void AckPacket(QuicPacketSequenceNumber arrived, QuicAckFrame* frame) {
+    EXPECT_THAT(frame->received_info.missing_packets, Contains(arrived));
+    frame->received_info.missing_packets.erase(arrived);
+    frame->received_info.entropy_hash ^=
+      QuicConnectionPeer::GetSentEntropyHash(&connection_, arrived);
+    if (arrived > 1) {
+      frame->received_info.entropy_hash ^=
+        QuicConnectionPeer::GetSentEntropyHash(&connection_, arrived - 1);
+    }
+  }
+
   QuicGuid guid_;
   QuicFramer framer_;
   QuicPacketCreator creator_;
@@ -892,7 +927,7 @@
   // awaiting' is 4.  The connection should then realize 1 will not be
   // retransmitted, and will remove it from the missing list.
   creator_.set_sequence_number(5);
-  QuicAckFrame frame(0, QuicTime::Zero(), 4);
+  QuicAckFrame frame = InitAckFrame(0, 4);
   ProcessAckPacket(&frame);
 
   // Force an ack to be sent.
@@ -914,12 +949,11 @@
     SendStreamDataToPeer(1, "foo", i * 3, !kFin, NULL);
   }
 
-  QuicAckFrame frame(num_packets, QuicTime::Zero(), 1);
+  QuicAckFrame frame = InitAckFrame(num_packets, 1);
   // Create an ack with 256 nacks, none adjacent to one another.
   for (QuicPacketSequenceNumber i = 1; i <= 256; ++i) {
-    frame.received_info.missing_packets.insert(i * 2);
+    NackPacket(i * 2, &frame);
   }
-  frame.received_info.entropy_hash = 0;
   EXPECT_CALL(entropy_calculator_,
               EntropyHash(511)).WillOnce(testing::Return(0));
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(256);
@@ -933,8 +967,7 @@
   EXPECT_GT(num_packets,
             received_packet_manager->peer_largest_observed_packet());
 
-  frame.received_info.missing_packets.erase(192);
-  frame.received_info.entropy_hash = 2;
+  AckPacket(192, &frame);
 
   // Removing one missing packet allows us to ack 192 and one more range.
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
@@ -962,7 +995,7 @@
                   testing::Return(QuicTime::Delta::Zero()));
   // Skip a packet and then record an ack.
   creator_.set_sequence_number(2);
-  QuicAckFrame frame(0, QuicTime::Zero(), 3);
+  QuicAckFrame frame = InitAckFrame(0, 3);
   ProcessAckPacket(&frame);
 }
 
@@ -996,10 +1029,8 @@
                       Return(true)));
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
   connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
-  QuicAckFrame frame(original, QuicTime::Zero(), 1);
-  frame.received_info.missing_packets.insert(original);
-  frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
-      &connection_, original - 1);
+  QuicAckFrame frame = InitAckFrame(original, 1);
+  NackPacket(original, &frame);
   // First nack triggers early retransmit.
   QuicPacketSequenceNumber retransmission;
   EXPECT_CALL(*send_algorithm_,
@@ -1009,11 +1040,8 @@
 
   ProcessAckPacket(&frame);
 
-  QuicAckFrame frame2(retransmission, QuicTime::Zero(), 1);
-  frame2.received_info.missing_packets.insert(original);
-  frame2.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, retransmission) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, original);
+  QuicAckFrame frame2 = InitAckFrame(retransmission, 1);
+  NackPacket(original, &frame2);
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _));
 
   ProcessAckPacket(&frame2);
@@ -1024,9 +1052,7 @@
   ProcessAckPacket(&frame2);
 
   // But an ack with no missing packets will not send an ack.
-  frame2.received_info.missing_packets.clear();
-  frame2.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, retransmission);
+  AckPacket(original, &frame2);
   ProcessAckPacket(&frame2);
   ProcessAckPacket(&frame2);
 }
@@ -1040,13 +1066,13 @@
 
   // Start out saying the least unacked is 2.
   creator_.set_sequence_number(5);
-  QuicAckFrame frame(0, QuicTime::Zero(), 2);
+  QuicAckFrame frame = InitAckFrame(0, 2);
   ProcessAckPacket(&frame);
 
   // Change it to 1, but lower the sequence number to fake out-of-order packets.
   // This should be fine.
   creator_.set_sequence_number(1);
-  QuicAckFrame frame2(0, QuicTime::Zero(), 1);
+  QuicAckFrame frame2 = InitAckFrame(0, 1);
   // The scheduler will not process out of order acks.
   EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
   ProcessAckPacket(&frame2);
@@ -1068,16 +1094,14 @@
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
 
   // Start out saying the largest observed is 2.
-  QuicAckFrame frame(2, QuicTime::Zero(), 0);
-  frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
-      &connection_, 2);
-  ProcessAckPacket(&frame);
+  QuicAckFrame frame1 = InitAckFrame(1, 0);
+  QuicAckFrame frame2 = InitAckFrame(2, 0);
+  ProcessAckPacket(&frame2);
 
   // Now change it to 1, and it should cause a connection error.
-  QuicAckFrame frame2(1, QuicTime::Zero(), 0);
   EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, false));
   EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
-  ProcessAckPacket(&frame2);
+  ProcessAckPacket(&frame1);
 }
 
 TEST_F(QuicConnectionTest, AckUnsentData) {
@@ -1095,7 +1119,7 @@
   ProcessPacket(1);
 
   creator_.set_sequence_number(1);
-  QuicAckFrame frame1(0, QuicTime::Zero(), 1);
+  QuicAckFrame frame1 = InitAckFrame(0, 1);
   ProcessAckPacket(&frame1);
 }
 
@@ -1218,9 +1242,7 @@
   EXPECT_EQ(1u, last_ack()->sent_info.least_unacked);
 
   // Peer acks up to packet 3.
-  QuicAckFrame frame(3, QuicTime::Zero(), 0);
-  frame.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3);
+  QuicAckFrame frame = InitAckFrame(3, 0);
   ProcessAckPacket(&frame);
   SendAckPacketToPeer();  // Packet 6
 
@@ -1229,9 +1251,7 @@
   EXPECT_EQ(4u, last_ack()->sent_info.least_unacked);
 
   // Peer acks up to packet 4, the last packet.
-  QuicAckFrame frame2(6, QuicTime::Zero(), 0);
-  frame2.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 6);
+  QuicAckFrame frame2 = InitAckFrame(6, 0);
   ProcessAckPacket(&frame2);  // Acks don't instigate acks.
 
   // Verify that we did not send an ack.
@@ -1248,7 +1268,7 @@
   SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet);  // Packet 8
   EXPECT_EQ(8u, last_packet);
   SendAckPacketToPeer();  // Packet 9
-  EXPECT_EQ(8u, last_ack()->sent_info.least_unacked);
+  EXPECT_EQ(7u, last_ack()->sent_info.least_unacked);
 }
 
 TEST_F(QuicConnectionTest, FECSending) {
@@ -1318,19 +1338,14 @@
   connection_.SendStreamDataWithString(1, "foo", 3, !kFin, NULL);
   connection_.SendStreamDataWithString(1, "foo", 6, !kFin, NULL);
 
-  QuicAckFrame ack_fec(2, QuicTime::Zero(), 1);
+  QuicAckFrame ack_fec = InitAckFrame(2, 1);
   // Data packet missing.
   // TODO(ianswett): Note that this is not a sensible ack, since if the FEC was
   // received, it would cause the covered packet to be acked as well.
-  ack_fec.received_info.missing_packets.insert(1);
-  ack_fec.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  NackPacket(1, &ack_fec);
 
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
-
   ProcessAckPacket(&ack_fec);
-
   clock_.AdvanceTime(DefaultRetransmissionTime());
 
   // Don't abandon the acked FEC packet, but it will abandon 2 the subsequent
@@ -1354,16 +1369,10 @@
   clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
   connection_.SendStreamDataWithString(1, "foo", 6, !kFin, NULL);
 
-  QuicAckFrame ack_fec(5, QuicTime::Zero(), 1);
+  QuicAckFrame ack_fec = InitAckFrame(5, 1);
   // Ack all data packets, but no fec packets.
-  ack_fec.received_info.missing_packets.insert(2);
-  ack_fec.received_info.missing_packets.insert(4);
-  ack_fec.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 5) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 4) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  NackPacket(2, &ack_fec);
+  NackPacket(4, &ack_fec);
 
   // Lose the first FEC packet and ack the three data packets.
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(3);
@@ -1520,7 +1529,7 @@
 
   // Process an ack to cause the visitor's OnCanWrite to be invoked.
   creator_.set_sequence_number(2);
-  QuicAckFrame ack_one(0, QuicTime::Zero(), 0);
+  QuicAckFrame ack_one = InitAckFrame(0, 0);
   ProcessAckPacket(&ack_one);
 
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -1644,21 +1653,15 @@
 
   // Peer acks one but not two or three.  Right now we only retransmit on
   // explicit nack, so it should not trigger a retransmission.
-  QuicAckFrame ack_one(1, QuicTime::Zero(), 0);
-  ack_one.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame ack_one = InitAckFrame(1, 0);
   ProcessAckPacket(&ack_one);
   ProcessAckPacket(&ack_one);
   ProcessAckPacket(&ack_one);
 
   // Peer acks up to 3 with two explicitly missing.
   // Early retransmit causes 2 to be retransmitted on the first ack.
-  QuicAckFrame nack_two(3, QuicTime::Zero(), 0);
-  nack_two.received_info.missing_packets.insert(2);
-  nack_two.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame nack_two = InitAckFrame(3, 0);
+  NackPacket(2, &nack_two);
   // The third nack should trigger a retransmission.
   EXPECT_CALL(*send_algorithm_,
               OnPacketSent(_, _, second_packet_size - kQuicVersionSize,
@@ -1679,21 +1682,15 @@
 
   // Peer acks one but not two or three.  Right now we only retransmit on
   // explicit nack, so it should not trigger a retransmission.
-  QuicAckFrame ack_one(1, QuicTime::Zero(), 0);
-  ack_one.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame ack_one = InitAckFrame(1, 0);
   ProcessAckPacket(&ack_one);
   ProcessAckPacket(&ack_one);
   ProcessAckPacket(&ack_one);
 
   // Peer acks up to 3 with two explicitly missing.  Two nacks should cause no
   // change.
-  QuicAckFrame nack_two(3, QuicTime::Zero(), 0);
-  nack_two.received_info.missing_packets.insert(2);
-  nack_two.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame nack_two = InitAckFrame(3, 0);
+  NackPacket(2, &nack_two);
   // The first nack should trigger a fast retransmission, but we'll be
   // write blocked, so the packet will be queued.
   writer_->set_blocked(true);
@@ -1702,9 +1699,7 @@
   EXPECT_EQ(1u, connection_.NumQueuedPackets());
 
   // Now, ack the previous transmission.
-  QuicAckFrame ack_all(3, QuicTime::Zero(), 0);
-  ack_all.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3);
+  QuicAckFrame ack_all = InitAckFrame(3, 0);
   ProcessAckPacket(&ack_all);
 
   // Unblock the socket and attempt to send the queued packets.  However,
@@ -1729,10 +1724,8 @@
                       Return(true)));
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
   connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
-  QuicAckFrame frame(1, QuicTime::Zero(), largest_observed);
-  frame.received_info.missing_packets.insert(largest_observed);
-  frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
-      &connection_, largest_observed - 1);
+  QuicAckFrame frame = InitAckFrame(1, largest_observed);
+  NackPacket(largest_observed, &frame);
   // The first nack should retransmit the largest observed packet.
   EXPECT_CALL(*send_algorithm_,
               OnPacketSent(_, _, packet_size - kQuicVersionSize,
@@ -1802,15 +1795,11 @@
   }
 
   // Ack 15, nack 1-14.
-  QuicAckFrame nack(15, QuicTime::Zero(), 0);
+  QuicAckFrame nack = InitAckFrame(15, 0);
   for (int i = 1; i < 15; ++i) {
-    nack.received_info.missing_packets.insert(i);
+    NackPacket(i, &nack);
   }
 
-  nack.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 15) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 14);
-
   // 13 packets have been NACK'd 3 times, but we limit retransmissions to 2.
   EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
@@ -1839,34 +1828,26 @@
   EXPECT_EQ(6u, last_packet);
 
   // Client will ack packets 1, 2, [!3], 4, 5.
-  QuicAckFrame frame1(5, QuicTime::Zero(), 0);
-  frame1.received_info.missing_packets.insert(3);
-  frame1.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 5) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2);
-
+  QuicAckFrame frame1 = InitAckFrame(5, 0);
+  NackPacket(3, &frame1);
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
   ProcessAckPacket(&frame1);
 
   // Now the client implicitly acks 3, and explicitly acks 6.
-  QuicAckFrame frame2(6, QuicTime::Zero(), 0);
-  frame2.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 6);
-
+  QuicAckFrame frame2 = InitAckFrame(6, 0);
   ProcessAckPacket(&frame2);
 }
 
 TEST_F(QuicConnectionTest, DontLatchUnackedPacket) {
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
   SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);  // Packet 1;
+  // From now on, we send acks, so the send algorithm won't save them.
+  ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+              .WillByDefault(Return(false));
   SendAckPacketToPeer();  // Packet 2
 
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  QuicAckFrame frame(1, QuicTime::Zero(), 0);
-  frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
-      &connection_, 1);
+  QuicAckFrame frame = InitAckFrame(1, 0);
   ProcessAckPacket(&frame);
 
   // Verify that our internal state has least-unacked as 3.
@@ -1881,8 +1862,12 @@
   // Check that the outgoing ack had its sequence number as least_unacked.
   EXPECT_EQ(3u, last_ack()->sent_info.least_unacked);
 
+  ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+              .WillByDefault(Return(true));
   SendStreamDataToPeer(1, "bar", 3, false, NULL);  // Packet 4
   EXPECT_EQ(4u, outgoing_ack()->sent_info.least_unacked);
+  ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+              .WillByDefault(Return(false));
   SendAckPacketToPeer();  // Packet 5
   EXPECT_EQ(4u, last_ack()->sent_info.least_unacked);
 }
@@ -2175,15 +2160,10 @@
       .Times(AnyNumber());
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NACK_RETRANSMISSION, _))
       .WillOnce(DoAll(SaveArg<1>(&nack_sequence_number), Return(true)));
-  QuicAckFrame ack(rto_sequence_number, QuicTime::Zero(), 0);
+  QuicAckFrame ack = InitAckFrame(rto_sequence_number, 0);
   // Ack the retransmitted packet.
-  ack.received_info.missing_packets.insert(original_sequence_number);
-  ack.received_info.missing_packets.insert(rto_sequence_number);
-  ack.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_,
-                                             rto_sequence_number - 1) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_,
-                                             original_sequence_number);
+  NackPacket(original_sequence_number, &ack);
+  NackPacket(rto_sequence_number, &ack);
   for (int i = 0; i < 3; i++) {
     ProcessAckPacket(&ack);
   }
@@ -2221,9 +2201,7 @@
   // packet to delay the RTO.
   clock_.AdvanceTime(DefaultRetransmissionTime());
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
-  QuicAckFrame ack(1, QuicTime::Zero(), 0);
-  ack.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame ack = InitAckFrame(1, 0);
   ProcessAckPacket(&ack);
   EXPECT_TRUE(retransmission_alarm->IsSet());
 
@@ -2276,7 +2254,7 @@
   ASSERT_EQ(1u, connection_.NumFecGroups());
 
   // Now send non-fec protected ack packet and close the group.
-  QuicAckFrame frame(0, QuicTime::Zero(), 5);
+  QuicAckFrame frame = InitAckFrame(0, 5);
   creator_.set_sequence_number(4);
   ProcessAckPacket(&frame);
   ASSERT_EQ(0u, connection_.NumFecGroups());
@@ -2504,7 +2482,7 @@
 
   // Now send non-retransmitting information, that we're not going to
   // retransmit 3. The far end should stop waiting for it.
-  QuicAckFrame frame(0, QuicTime::Zero(), 1);
+  QuicAckFrame frame = InitAckFrame(0, 1);
   EXPECT_CALL(*send_algorithm_,
               TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
                   testing::Return(QuicTime::Delta::Zero()));
@@ -2529,7 +2507,7 @@
 
   // Now send non-retransmitting information, that we're not going to
   // retransmit 3.  The far end should stop waiting for it.
-  QuicAckFrame frame(0, QuicTime::Zero(), 1);
+  QuicAckFrame frame = InitAckFrame(0, 1);
   EXPECT_CALL(*send_algorithm_,
               TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
                   testing::Return(QuicTime::Delta::FromMicroseconds(1)));
@@ -2715,7 +2693,7 @@
 }
 
 TEST_F(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
-  QuicAckFrame ack(0, QuicTime::Zero(), 4);
+  QuicAckFrame ack = InitAckFrame(0, 4);
   // Set the sequence number of the ack packet to be least unacked (4).
   creator_.set_sequence_number(3);
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -2741,7 +2719,7 @@
   ProcessDataPacket(4, 1, !kEntropyFlag);
   EXPECT_EQ(34u, outgoing_ack()->received_info.entropy_hash);
   // Make 4th packet my least unacked, and update entropy for 2, 3 packets.
-  QuicAckFrame ack(0, QuicTime::Zero(), 4);
+  QuicAckFrame ack = InitAckFrame(0, 4);
   QuicPacketEntropyHash kRandomEntropyHash = 129u;
   ack.sent_info.entropy_hash = kRandomEntropyHash;
   creator_.set_sequence_number(5);
@@ -2764,7 +2742,7 @@
   creator_.set_sequence_number(22);
   QuicPacketEntropyHash kRandomEntropyHash = 85u;
   // Current packet is the least unacked packet.
-  QuicAckFrame ack(0, QuicTime::Zero(), 23);
+  QuicAckFrame ack = InitAckFrame(0, 23);
   ack.sent_info.entropy_hash = kRandomEntropyHash;
   QuicPacketEntropyHash ack_entropy_hash =  ProcessAckPacket(&ack);
   EXPECT_EQ((kRandomEntropyHash + ack_entropy_hash),
@@ -3034,14 +3012,9 @@
   connection_.GetRetransmissionAlarm()->Fire();
 
   // Retransmit due to explicit nacks.
-  QuicAckFrame nack_three(4, QuicTime::Zero(), 0);
-  nack_three.received_info.missing_packets.insert(3);
-  nack_three.received_info.missing_packets.insert(1);
-  nack_three.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 4) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame nack_three = InitAckFrame(4, 0);
+  NackPacket(3, &nack_three);
+  NackPacket(1, &nack_three);
   QuicFrame frame(&nack_three);
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
@@ -3222,9 +3195,7 @@
 
   // Process an ACK from the server which should trigger the callback.
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
-  QuicAckFrame frame(1, QuicTime::Zero(), 0);
-  frame.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame frame = InitAckFrame(1, 0);
   ProcessAckPacket(&frame);
 }
 
@@ -3247,11 +3218,8 @@
 
   // Now we receive ACK for packets 2 and 3, but importantly missing packet 1
   // which we registered to be notified about.
-  QuicAckFrame frame(3, QuicTime::Zero(), 0);
-  frame.received_info.missing_packets.insert(1);
-  frame.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame frame = InitAckFrame(3, 0);
+  NackPacket(1, &frame);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _));
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _));
   ProcessAckPacket(&frame);
@@ -3274,12 +3242,8 @@
   connection_.SendStreamDataWithString(1, "qux", 0, !kFin, NULL);
 
   // Now we receive ACK for packets 1, 3, and 4, which invokes fast retransmit.
-  QuicAckFrame frame(4, QuicTime::Zero(), 0);
-  frame.received_info.missing_packets.insert(2);
-  frame.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 4) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame frame = InitAckFrame(4, 0);
+  NackPacket(2, &frame);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _));
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _));
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -3287,9 +3251,7 @@
 
   // Now we get an ACK for packet 5 (retransmitted packet 2), which should
   // trigger the callback.
-  QuicAckFrame second_ack_frame(5, QuicTime::Zero(), 0);
-  second_ack_frame.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 5);
+  QuicAckFrame second_ack_frame = InitAckFrame(5, 0);
   ProcessAckPacket(&second_ack_frame);
 }
 
@@ -3313,9 +3275,7 @@
   // Should recover the Ack packet and trigger the notification callback.
   QuicFrames frames;
 
-  QuicAckFrame ack_frame(1, QuicTime::Zero(), 0);
-  ack_frame.received_info.entropy_hash =
-      QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+  QuicAckFrame ack_frame = InitAckFrame(1, 0);
   frames.push_back(QuicFrame(&ack_frame));
 
   // Dummy stream frame to satisfy expectations set elsewhere.
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index cc02882..610dc57 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -2070,7 +2070,7 @@
 }
 
 bool QuicFramer::RaiseError(QuicErrorCode error) {
-  DVLOG(1) << detailed_error_;
+  DVLOG(1) << "Error detail: " << detailed_error_;
   set_error(error);
   visitor_->OnError(this);
   reader_.reset(NULL);
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 97ae972..ad14ee18 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -190,7 +190,7 @@
     EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _, _)).
         Times(AnyNumber());
     EXPECT_CALL(*send_algorithm_,
-                OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
+                OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
     EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
         Return(QuicTime::Delta::Zero()));
     EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index cc37c111..e53daec 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -210,10 +210,10 @@
 }
 
 ReceivedPacketInfo::ReceivedPacketInfo()
-    : largest_observed(0),
+    : entropy_hash(0),
+      largest_observed(0),
       delta_time_largest_observed(QuicTime::Delta::Infinite()),
-      is_truncated(false) {
-}
+      is_truncated(false) {}
 
 ReceivedPacketInfo::~ReceivedPacketInfo() {}
 
@@ -231,7 +231,9 @@
   }
 }
 
-SentPacketInfo::SentPacketInfo() {}
+SentPacketInfo::SentPacketInfo()
+    : entropy_hash(0),
+      least_unacked(0) {}
 
 SentPacketInfo::~SentPacketInfo() {}
 
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index bda30c7..bb7f496 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -104,16 +104,14 @@
   send_algorithm_->SetMaxPacketSize(max_packet_size);
 }
 
+// TODO(ianswett): Combine this method with OnPacketSent once packets are always
+// sent in order and the connection tracks RetransmittableFrames for longer.
 void QuicSentPacketManager::OnSerializedPacket(
     const SerializedPacket& serialized_packet) {
-  if (serialized_packet.retransmittable_frames == NULL &&
-      !serialized_packet.packet->is_fec_packet()) {
-    // Don't track ack/congestion feedback packets.
-    return;
+  if (serialized_packet.retransmittable_frames) {
+    ack_notifier_manager_.OnSerializedPacket(serialized_packet);
   }
 
-  ack_notifier_manager_.OnSerializedPacket(serialized_packet);
-
   DCHECK(unacked_packets_.empty() ||
          unacked_packets_.rbegin()->first < serialized_packet.sequence_number);
   unacked_packets_[serialized_packet.sequence_number] =
@@ -130,6 +128,7 @@
          unacked_packets_.rbegin()->first < new_sequence_number);
 
   pending_retransmissions_.erase(old_sequence_number);
+  // TODO(ianswett): Discard and lose the packet lazily instead of immediately.
 
   UnackedPacketMap::iterator unacked_it =
       unacked_packets_.find(old_sequence_number);
@@ -172,16 +171,9 @@
   bool new_least_unacked = !IsAwaitingPacket(received_info,
                                              least_unacked_sent_before);
 
+  MaybeUpdateRTT(received_info, ack_receive_time);
   HandleAckForSentPackets(received_info);
-
-  SequenceNumberSet retransmission_packets =
-      OnIncomingAckFrame(received_info, ack_receive_time);
-
-  for (SequenceNumberSet::const_iterator it = retransmission_packets.begin();
-       it != retransmission_packets.end(); ++it) {
-    DCHECK(!ContainsKey(pending_packets_, *it));
-    MarkForRetransmission(*it, NACK_RETRANSMISSION);
-  }
+  MaybeRetransmitOnAckFrame(received_info, ack_receive_time);
 
   if (new_least_unacked) {
     consecutive_rto_count_ = 0;
@@ -192,7 +184,7 @@
 
 void QuicSentPacketManager::DiscardUnackedPacket(
     QuicPacketSequenceNumber sequence_number) {
-  MarkPacketReceivedByPeer(sequence_number);
+  MarkPacketHandled(sequence_number, NOT_RECEIVED_BY_PEER);
 }
 
 void QuicSentPacketManager::HandleAckForSentPackets(
@@ -216,7 +208,7 @@
     DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
     // If data is associated with the most recent transmission of this
     // packet, then inform the caller.
-    it = MarkPacketReceivedByPeer(sequence_number);
+    it = MarkPacketHandled(sequence_number, RECEIVED_BY_PEER);
 
     // The AckNotifierManager is informed of every ACKed sequence number.
     ack_notifier_manager_.OnPacketAcked(sequence_number);
@@ -287,29 +279,28 @@
       // TODO(satyamshekhar): Think about congestion control here.
       // Specifically, about the retransmission count of packets being sent
       // proactively to achieve 0 (minimal) RTT.
-      OnPacketAbandoned(unacked_it->first);
-      if (!MarkForRetransmission(unacked_it->first, NACK_RETRANSMISSION)) {
+      if (unacked_it->second.retransmittable_frames) {
+        OnPacketAbandoned(unacked_it->first);
+        MarkForRetransmission(unacked_it->first, NACK_RETRANSMISSION);
+      } else {
         DiscardUnackedPacket(unacked_it->first);
       }
     }
   }
 }
 
-bool QuicSentPacketManager::MarkForRetransmission(
+void QuicSentPacketManager::MarkForRetransmission(
     QuicPacketSequenceNumber sequence_number,
     TransmissionType transmission_type) {
   DCHECK(ContainsKey(unacked_packets_, sequence_number));
-  if (!HasRetransmittableFrames(sequence_number)) {
-    return false;
-  }
-  // If it's already in the retransmission map, don't add it again, just let
-  // the prior retransmission request win out.
+  DCHECK(HasRetransmittableFrames(sequence_number));
+  // TODO(ianswett): Currently the RTO can fire while there are pending NACK
+  // retransmissions for the same data, which is not ideal.
   if (ContainsKey(pending_retransmissions_, sequence_number)) {
-    return true;
+    return;
   }
 
   pending_retransmissions_[sequence_number] = transmission_type;
-  return true;
 }
 
 bool QuicSentPacketManager::HasPendingRetransmissions() const {
@@ -347,10 +338,21 @@
 }
 
 QuicSentPacketManager::UnackedPacketMap::iterator
-QuicSentPacketManager::MarkPacketReceivedByPeer(
-    QuicPacketSequenceNumber sequence_number) {
+QuicSentPacketManager::MarkPacketHandled(
+    QuicPacketSequenceNumber sequence_number, ReceivedByPeer received_by_peer) {
   DCHECK(ContainsKey(unacked_packets_, sequence_number));
 
+  // If this packet is pending, remove it and inform the send algorithm.
+  if (pending_packets_.erase(sequence_number)) {
+    size_t bytes_sent = packet_history_map_[sequence_number]->bytes_sent();
+    if (received_by_peer == RECEIVED_BY_PEER) {
+      send_algorithm_->OnPacketAcked(sequence_number, bytes_sent, rtt_sample_);
+    } else {
+      // It's been abandoned.
+      send_algorithm_->OnPacketAbandoned(sequence_number, bytes_sent);
+    }
+  }
+
   // If this packet has never been retransmitted, then simply drop it.
   UnackedPacketMap::const_iterator previous_it =
       unacked_packets_.find(sequence_number);
@@ -470,18 +472,20 @@
     HasRetransmittableData has_retransmittable_data) {
   DCHECK_LT(0u, sequence_number);
   DCHECK(!ContainsKey(pending_packets_, sequence_number));
-  if (ContainsKey(unacked_packets_, sequence_number)) {
-    unacked_packets_[sequence_number].sent_time = sent_time;
-  }
+  DCHECK(ContainsKey(unacked_packets_, sequence_number));
 
   // Only track packets the send algorithm wants us to track.
   if (!send_algorithm_->OnPacketSent(sent_time, sequence_number, bytes,
                                      transmission_type,
                                      has_retransmittable_data)) {
+    DCHECK(unacked_packets_[sequence_number].retransmittable_frames == NULL);
+    unacked_packets_.erase(sequence_number);
     return;
   }
-  packet_history_map_[sequence_number] = new SendAlgorithmInterface::SentPacket(
-      bytes, sent_time, has_retransmittable_data);
+
+  unacked_packets_[sequence_number].sent_time = sent_time;
+  packet_history_map_[sequence_number] =
+      new SendAlgorithmInterface::SentPacket(bytes, sent_time);
   pending_packets_.insert(sequence_number);
   CleanupPacketHistory();
 }
@@ -492,23 +496,6 @@
   QuicTime::Delta retransmission_delay = GetRetransmissionDelay();
   QuicTime max_send_time =
       clock_->ApproximateNow().Subtract(retransmission_delay);
-  for (SequenceNumberSet::iterator it = pending_packets_.begin();
-       it != pending_packets_.end();) {
-    QuicPacketSequenceNumber sequence_number = *it;
-    DCHECK(ContainsKey(packet_history_map_, sequence_number));
-    DCHECK(ContainsKey(unacked_packets_, sequence_number));
-    const TransmissionInfo& transmission_info =
-        unacked_packets_.find(sequence_number)->second;
-    // Abandon retransmittable packet and old non-retransmittable packets.
-    if (transmission_info.retransmittable_frames ||
-        transmission_info.sent_time <= max_send_time) {
-      pending_packets_.erase(it++);
-      send_algorithm_->OnPacketAbandoned(
-          sequence_number, packet_history_map_[sequence_number]->bytes_sent());
-    } else {
-      ++it;
-    }
-  }
 
   // Attempt to send all the unacked packets when the RTO fires, let the
   // congestion manager decide how many to send immediately and the remaining
@@ -516,13 +503,16 @@
   DVLOG(1) << "OnRetransmissionTimeout() fired with "
            << unacked_packets_.size() << " unacked packets.";
 
-  // Retransmit any packet with retransmittable frames.
+  // Retransmit any packet with retransmittable frames and abandon the rest.
   bool packets_retransmitted = false;
   for (UnackedPacketMap::const_iterator it = unacked_packets_.begin();
        it != unacked_packets_.end(); ++it) {
     if (it->second.retransmittable_frames != NULL) {
+      OnPacketAbandoned(it->first);
       packets_retransmitted = true;
       MarkForRetransmission(it->first, RTO_RETRANSMISSION);
+    } else if (it->second.sent_time <= max_send_time) {
+      OnPacketAbandoned(it->first);
     }
   }
 
@@ -551,38 +541,28 @@
       frame, feedback_receive_time, packet_history_map_);
 }
 
-SequenceNumberSet QuicSentPacketManager::OnIncomingAckFrame(
+void QuicSentPacketManager::MaybeRetransmitOnAckFrame(
     const ReceivedPacketInfo& received_info,
     const QuicTime& ack_receive_time) {
-  MaybeUpdateRTT(received_info, ack_receive_time);
-
-  // We want to.
-  // * Get all packets lower(including) than largest_observed
-  //   from pending_packets_.
-  // * Remove all packets no longer being waited for(ie: acked).
-  // * Send each ACK in the list to send_algorithm_.
+  // Go through all pending packets up to the largest observed and see if any
+  // need to be retransmitted or lost.
   SequenceNumberSet::iterator it = pending_packets_.begin();
   SequenceNumberSet::iterator it_upper =
       pending_packets_.upper_bound(received_info.largest_observed);
 
-  SequenceNumberSet retransmission_packets;
+  size_t num_retransmitted = 0;
   SequenceNumberSet lost_packets;
   while (it != it_upper) {
     QuicPacketSequenceNumber sequence_number = *it;
+    DVLOG(1) << "still missing packet " << sequence_number;
+    // Acks must be handled previously, so ensure it's missing and not acked.
+    DCHECK(IsAwaitingPacket(received_info, sequence_number));
+    DCHECK(ContainsKey(packet_history_map_, sequence_number));
     const SendAlgorithmInterface::SentPacket* sent_packet =
         packet_history_map_[sequence_number];
-    if (!IsAwaitingPacket(received_info, sequence_number)) {
-      // Not missing, hence implicitly acked.
-      size_t bytes_sent = sent_packet->bytes_sent();
-      send_algorithm_->OnPacketAcked(sequence_number, bytes_sent, rtt_sample_);
-      pending_packets_.erase(it++);  // Must be incremented post to work.
-      continue;
-    }
+    const TransmissionInfo& transmission_info =
+        unacked_packets_[sequence_number];
 
-    // The peer got packets after this sequence number.  This is an explicit
-    // nack.
-    DVLOG(1) << "still missing packet " << sequence_number;
-    DCHECK(ContainsKey(packet_history_map_, sequence_number));
     // Consider it multiple nacks when there is a gap between the missing packet
     // and the largest observed, since the purpose of a nack threshold is to
     // tolerate re-ordering.  This handles both StretchAcks and Forward Acks.
@@ -595,8 +575,8 @@
     // Check for early retransmit(RFC5827) when the last packet gets acked and
     // the there are fewer than 4 pending packets.
     if (pending_packets_.size() <= kNumberOfNacksBeforeRetransmission &&
-        sent_packet->has_retransmittable_data() == HAS_RETRANSMITTABLE_DATA &&
-        *pending_packets_.rbegin() == received_info.largest_observed) {
+        transmission_info.retransmittable_frames &&
+        packet_history_map_.rbegin()->first == received_info.largest_observed) {
       num_nacks_needed = received_info.largest_observed - sequence_number;
     }
 
@@ -607,14 +587,15 @@
 
     // If the number of retransmissions has maxed out, don't lose or retransmit
     // any more packets.
-    if (retransmission_packets.size() >= kMaxRetransmissionsPerAck) {
+    if (num_retransmitted >= kMaxRetransmissionsPerAck) {
       ++it;
       continue;
     }
 
     lost_packets.insert(sequence_number);
-    if (sent_packet->has_retransmittable_data() == HAS_RETRANSMITTABLE_DATA) {
-      retransmission_packets.insert(sequence_number);
+    if (transmission_info.retransmittable_frames) {
+      ++num_retransmitted;
+      MarkForRetransmission(*it, NACK_RETRANSMISSION);
     }
 
     ++it;
@@ -632,8 +613,6 @@
     send_algorithm_->OnPacketLost(*it, ack_receive_time);
     OnPacketAbandoned(*it);
   }
-
-  return retransmission_packets;
 }
 
 void QuicSentPacketManager::MaybeUpdateRTT(
@@ -687,6 +666,13 @@
   return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
 }
 
+const QuicTime QuicSentPacketManager::GetRetransmissionTime() const {
+  if (pending_packets_.empty()) {
+    return QuicTime::Zero();
+  }
+  return clock_->ApproximateNow().Add(GetRetransmissionDelay());
+}
+
 const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
   size_t number_retransmissions = consecutive_rto_count_;
   if (FLAGS_limit_rto_increase_for_tests) {
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h
index 71c61e9..70129c8 100644
--- a/net/quic/quic_sent_packet_manager.h
+++ b/net/quic/quic_sent_packet_manager.h
@@ -94,7 +94,8 @@
 
   // Discards any information for the packet corresponding to |sequence_number|.
   // If this packet has been retransmitted, information on those packets
-  // will be discarded as well.
+  // will be discarded as well.  Also discards it from the congestion window if
+  // it is present.
   void DiscardUnackedPacket(QuicPacketSequenceNumber sequence_number);
 
   // Returns true if the non-FEC packet |sequence_number| is unacked.
@@ -133,15 +134,6 @@
   // Returns true if |sequence_number| is a previous transmission of packet.
   bool IsPreviousTransmission(QuicPacketSequenceNumber sequence_number) const;
 
-  // TODO(ianswett): Combine the congestion control related methods below with
-  // some of the methods above and cleanup the resulting code.
-  // Called when we have received an ack frame from peer.
-  // Returns a set containing all the sequence numbers to be nack retransmitted
-  // as a result of the ack.
-  virtual SequenceNumberSet OnIncomingAckFrame(
-      const ReceivedPacketInfo& received_info,
-      const QuicTime& ack_receive_time);
-
   // Called when a congestion feedback frame is received from peer.
   virtual void OnIncomingQuicCongestionFeedbackFrame(
       const QuicCongestionFeedbackFrame& frame,
@@ -175,6 +167,11 @@
   // Returns amount of time for delayed ack timer.
   const QuicTime::Delta DelayedAckTime();
 
+  // Returns the current delay for the retransmission timer, which may send
+  // either a tail loss probe or do a full RTO.  Retrans QuicTime::Zero() if
+  // there are no outstanding packets to abandon or retransmit.
+  const QuicTime GetRetransmissionTime() const;
+
   // Returns the current RTO delay.
   const QuicTime::Delta GetRetransmissionDelay() const;
 
@@ -200,6 +197,11 @@
   friend class test::QuicConnectionPeer;
   friend class test::QuicSentPacketManagerPeer;
 
+  enum ReceivedByPeer {
+    RECEIVED_BY_PEER,
+    NOT_RECEIVED_BY_PEER,
+  };
+
   struct TransmissionInfo {
     TransmissionInfo()
         : retransmittable_frames(NULL),
@@ -227,8 +229,6 @@
                           TransmissionInfo> UnackedPacketMap;
   typedef linked_hash_map<QuicPacketSequenceNumber,
                           TransmissionType> PendingRetransmissionMap;
-  typedef base::hash_map<QuicPacketSequenceNumber, SequenceNumberSet*>
-                         PreviousTransmissionMap;
 
   // Process the incoming ack looking for newly ack'd data packets.
   void HandleAckForSentPackets(const ReceivedPacketInfo& received_info);
@@ -237,19 +237,25 @@
   void MaybeUpdateRTT(const ReceivedPacketInfo& received_info,
                       const QuicTime& ack_receive_time);
 
-  // Marks |sequence_number| as having been seen by the peer.  Returns an
-  // iterator to the next remaining unacked packet.
-  UnackedPacketMap::iterator MarkPacketReceivedByPeer(
-      QuicPacketSequenceNumber sequence_number);
+  // Chooses whether to nack retransmit any packets based on the receipt info.
+  // All acks have been handled before this method is invoked.
+  void MaybeRetransmitOnAckFrame(const ReceivedPacketInfo& received_info,
+                                 const QuicTime& ack_receive_time);
 
-  // Simply removes the entries, if any, from the unacked packet map
-  // and the retransmission map.
+  // Marks |sequence_number| as being fully handled, either due to receipt
+  // by the peer, or having been discarded as indecipherable.  Returns an
+  // iterator to the next remaining unacked packet.
+  UnackedPacketMap::iterator MarkPacketHandled(
+      QuicPacketSequenceNumber sequence_number,
+      ReceivedByPeer received_by_peer);
+
+  // Removes entries from the unacked packet map.
   void DiscardPacket(QuicPacketSequenceNumber sequence_number);
 
   // Request that |sequence_number| be retransmitted after the other pending
-  // retransmissions.  Returns false if there are no retransmittable frames for
-  // |sequence_number| and true if it will be retransmitted.
-  bool MarkForRetransmission(QuicPacketSequenceNumber sequence_number,
+  // retransmissions.  Does not add it to the retransmissions if it's already
+  // a pending retransmission.
+  void MarkForRetransmission(QuicPacketSequenceNumber sequence_number,
                              TransmissionType transmission_type);
 
   // Returns the length of the serialized sequence number for
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index 168cbf3..a0b78ec8 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -96,12 +96,19 @@
         &manager_, new_sequence_number));
   }
 
-  SerializedPacket CreatePacket(QuicPacketSequenceNumber sequence_number) {
+  SerializedPacket CreateDataPacket(QuicPacketSequenceNumber sequence_number) {
+    return CreatePacket(sequence_number, true);
+  }
+
+  SerializedPacket CreatePacket(QuicPacketSequenceNumber sequence_number,
+                                bool retransmittable) {
     packets_.push_back(QuicPacket::NewDataPacket(
         NULL, 0, false, PACKET_8BYTE_GUID, false,
         PACKET_6BYTE_SEQUENCE_NUMBER));
-    return SerializedPacket(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
-                            packets_.back(), 0u, new RetransmittableFrames());
+    return SerializedPacket(
+        sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
+        packets_.back(), 0u,
+        retransmittable ? new RetransmittableFrames() : NULL);
   }
 
   SerializedPacket CreateFecPacket(QuicPacketSequenceNumber sequence_number) {
@@ -115,9 +122,9 @@
   void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, sequence_number, _, _, _))
                     .Times(1).WillOnce(Return(true));
-    SerializedPacket packet(CreatePacket(sequence_number));
+    SerializedPacket packet(CreateDataPacket(sequence_number));
     manager_.OnSerializedPacket(packet);
-    manager_.OnPacketSent(sequence_number, clock_.ApproximateNow(),
+    manager_.OnPacketSent(sequence_number, clock_.Now(),
                           packet.packet->length(), NOT_RETRANSMISSION,
                           HAS_RETRANSMITTABLE_DATA);
   }
@@ -148,7 +155,7 @@
 TEST_F(QuicSentPacketManagerTest, IsUnacked) {
   VerifyUnackedPackets(NULL, 0);
 
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
 
@@ -159,7 +166,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   RetransmitPacket(1, 2);
@@ -172,7 +179,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   RetransmitPacket(1, 2);
@@ -189,7 +196,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   QuicSentPacketManagerPeer::MarkForRetransmission(
@@ -210,7 +217,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   RetransmitPacket(1, 2);
@@ -234,7 +241,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   RetransmitPacket(1, 2);
@@ -259,7 +266,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, TruncatedAck) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   RetransmitPacket(1, 2);
@@ -282,9 +289,9 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
-  manager_.OnSerializedPacket(CreatePacket(1));
-  manager_.OnSerializedPacket(CreatePacket(2));
-  manager_.OnSerializedPacket(CreatePacket(3));
+  manager_.OnSerializedPacket(CreateDataPacket(1));
+  manager_.OnSerializedPacket(CreateDataPacket(2));
+  manager_.OnSerializedPacket(CreateDataPacket(3));
 
   {
     // Ack packets 1 and 3.
@@ -299,8 +306,8 @@
     VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
   }
 
-  manager_.OnSerializedPacket(CreatePacket(4));
-  manager_.OnSerializedPacket(CreatePacket(5));
+  manager_.OnSerializedPacket(CreateDataPacket(4));
+  manager_.OnSerializedPacket(CreateDataPacket(5));
 
   {
     // Ack packets 5.
@@ -316,8 +323,8 @@
     VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
   }
 
-  manager_.OnSerializedPacket(CreatePacket(6));
-  manager_.OnSerializedPacket(CreatePacket(7));
+  manager_.OnSerializedPacket(CreateDataPacket(6));
+  manager_.OnSerializedPacket(CreateDataPacket(7));
 
   {
     // Ack packets 7.
@@ -335,8 +342,8 @@
   }
 
   RetransmitPacket(2, 8);
-  manager_.OnSerializedPacket(CreatePacket(9));
-  manager_.OnSerializedPacket(CreatePacket(10));
+  manager_.OnSerializedPacket(CreateDataPacket(9));
+  manager_.OnSerializedPacket(CreateDataPacket(10));
 
   {
     // Ack packet 10.
@@ -357,8 +364,8 @@
 
 
   RetransmitPacket(4, 11);
-  manager_.OnSerializedPacket(CreatePacket(12));
-  manager_.OnSerializedPacket(CreatePacket(13));
+  manager_.OnSerializedPacket(CreateDataPacket(12));
+  manager_.OnSerializedPacket(CreateDataPacket(13));
 
   {
     // Ack packet 13.
@@ -380,8 +387,8 @@
   }
 
   RetransmitPacket(6, 14);
-  manager_.OnSerializedPacket(CreatePacket(15));
-  manager_.OnSerializedPacket(CreatePacket(16));
+  manager_.OnSerializedPacket(CreateDataPacket(15));
+  manager_.OnSerializedPacket(CreateDataPacket(16));
 
   {
     // Ack packet 16.
@@ -411,7 +418,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacketUnacked) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
@@ -425,7 +432,7 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacketDiscardUnacked) {
-  SerializedPacket serialized_packet(CreatePacket(1));
+  SerializedPacket serialized_packet(CreateDataPacket(1));
 
   manager_.OnSerializedPacket(serialized_packet);
   manager_.DiscardUnackedPacket(1u);
@@ -498,10 +505,7 @@
   const size_t kNumSentPackets = 4;
   // Transmit 4 packets.
   for (size_t i = 1; i <= kNumSentPackets; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Nack the first packet 3 times with increasing largest observed.
@@ -516,9 +520,10 @@
       EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
       EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
     }
-    SequenceNumberSet retransmissions =
-        manager_.OnIncomingAckFrame(received_info, clock_.Now());
-    EXPECT_EQ(i == 3 ? 1u : 0u, retransmissions.size());
+    manager_.OnIncomingAck(received_info, clock_.Now());
+    EXPECT_EQ(
+        i == 3 ? 1u : 0u,
+        QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
     EXPECT_EQ(i, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
   }
 }
@@ -529,10 +534,7 @@
   const size_t kNumSentPackets = 4;
   // Transmit 4 packets.
   for (size_t i = 1; i <= kNumSentPackets; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Nack the first packet 3 times in a single StretchAck.
@@ -544,21 +546,18 @@
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(3);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
-  SequenceNumberSet retransmissions =
-      manager_.OnIncomingAckFrame(received_info, clock_.Now());
-  EXPECT_EQ(1u, retransmissions.size());
+  manager_.OnIncomingAck(received_info, clock_.Now());
+  EXPECT_EQ(
+      1u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
   EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
 }
 
 // Ack a packet 3 packets ahead, causing a retransmit.
 TEST_F(QuicSentPacketManagerTest, NackRetransmit1PacketSingleAck) {
-  const size_t kNumSentPackets = 4;
-  // Transmit 4 packets.
+  const size_t kNumSentPackets = 5;
+  // Transmit 5 packets.
   for (size_t i = 1; i <= kNumSentPackets; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Nack the first packet 3 times in an AckFrame with three missing packets.
@@ -568,13 +567,13 @@
   received_info.missing_packets.insert(1);
   received_info.missing_packets.insert(2);
   received_info.missing_packets.insert(3);
-  received_info.largest_observed = kNumSentPackets;
-  EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+  received_info.largest_observed = 4;
+  EXPECT_CALL(*send_algorithm_, OnPacketAcked(4, _, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
-  SequenceNumberSet retransmissions =
-      manager_.OnIncomingAckFrame(received_info, clock_.Now());
-  EXPECT_EQ(1u, retransmissions.size());
+  manager_.OnIncomingAck(received_info, clock_.Now());
+  EXPECT_EQ(
+      1u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
   EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
 }
 
@@ -582,10 +581,7 @@
   const size_t kNumSentPackets = 2;
   // Transmit 2 packets.
   for (size_t i = 1; i <= kNumSentPackets; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Early retransmit when the final packet gets acked and the first is nacked.
@@ -597,19 +593,16 @@
   EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
-  SequenceNumberSet retransmissions =
-      manager_.OnIncomingAckFrame(received_info, clock_.Now());
-  EXPECT_EQ(1u, retransmissions.size());
+  manager_.OnIncomingAck(received_info, clock_.Now());
+  EXPECT_EQ(
+      1u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
   EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
 }
 
 TEST_F(QuicSentPacketManagerTest, DontEarlyRetransmitPacket) {
-  const size_t kNumSentPackets = 4;
+  const size_t kNumSentPackets = 5;
   for (size_t i = 1; i <= kNumSentPackets; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Fast retransmit when the final packet gets acked, but don't early
@@ -621,24 +614,22 @@
   received_info.missing_packets.insert(1);
   received_info.missing_packets.insert(2);
   received_info.missing_packets.insert(3);
+  received_info.missing_packets.insert(4);
   received_info.largest_observed = kNumSentPackets;
-  EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
-  EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
-  EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
-  SequenceNumberSet retransmissions =
-      manager_.OnIncomingAckFrame(received_info, clock_.Now());
-  EXPECT_EQ(1u, retransmissions.size());
-  EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+  EXPECT_CALL(*send_algorithm_, OnPacketAcked(5, _, _)).Times(1);
+  EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+  EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+  manager_.OnIncomingAck(received_info, clock_.Now());
+  EXPECT_EQ(
+      2u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
+  EXPECT_EQ(4u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
 }
 
 TEST_F(QuicSentPacketManagerTest, NackRetransmit2Packets) {
   const size_t kNumSentPackets = 20;
   // Transmit 20 packets.
   for (QuicPacketSequenceNumber i = 1; i <= kNumSentPackets; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Nack the first 19 packets 3 times.
@@ -653,9 +644,9 @@
               OnPacketAcked(kNumSentPackets, _, _)).Times(1);
   EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
-  SequenceNumberSet retransmissions =
-      manager_.OnIncomingAckFrame(received_info, clock_.Now());
-  EXPECT_EQ(2u, retransmissions.size());
+  manager_.OnIncomingAck(received_info, clock_.Now());
+  EXPECT_EQ(
+      2u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
   for (size_t i = 1; i < kNumSentPackets; ++i) {
     EXPECT_EQ(kNumSentPackets - i,
               QuicSentPacketManagerPeer::GetNackCount(&manager_, i));
@@ -669,6 +660,8 @@
   for (QuicPacketSequenceNumber i = 1; i <= kNumSentPackets; ++i) {
     EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
                     .Times(1).WillOnce(Return(i % 2 == 0 ? false : true));
+    SerializedPacket packet(CreatePacket(i, i % 2 == 1));
+    manager_.OnSerializedPacket(packet);
     manager_.OnPacketSent(
         i, clock_.Now(), 1000, NOT_RETRANSMISSION,
         i % 2 == 0 ? NO_RETRANSMITTABLE_DATA : HAS_RETRANSMITTABLE_DATA);
@@ -686,9 +679,9 @@
   // not saved.
   EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
   EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
-  SequenceNumberSet retransmissions =
-      manager_.OnIncomingAckFrame(received_info, clock_.Now());
-  EXPECT_EQ(2u, retransmissions.size());
+  manager_.OnIncomingAck(received_info, clock_.Now());
+  ASSERT_EQ(
+      2u, QuicSentPacketManagerPeer::GetPendingRetransmissionCount(&manager_));
   // Only non-ack packets have a nack count.
   for (size_t i = 1; i < kNumSentPackets; i += 2) {
     EXPECT_EQ(kNumSentPackets - i,
@@ -697,19 +690,15 @@
 
   // Ensure only the odd packets were retransmitted, since the others were not
   // retransmittable(ie: acks).
-  for (SequenceNumberSet::const_iterator it = retransmissions.begin();
-       it != retransmissions.end(); ++it) {
-    EXPECT_EQ(1u, *it % 2);
-  }
+  EXPECT_EQ(1u, manager_.NextPendingRetransmission().sequence_number);
+  manager_.OnRetransmittedPacket(1u, kNumSentPackets + 1);
+  EXPECT_EQ(3u, manager_.NextPendingRetransmission().sequence_number);
 }
 
 TEST_F(QuicSentPacketManagerTest, NackTwiceThenAck) {
   // Transmit 4 packets.
   for (QuicPacketSequenceNumber i = 1; i <= 4; ++i) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                    .Times(1).WillOnce(Return(true));
-    manager_.OnPacketSent(i, clock_.Now(), 1000,
-                           NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+    SendDataPacket(i);
   }
 
   // Nack the first packet 2 times, then ack it.
@@ -724,9 +713,8 @@
         QuicTime::Delta::FromMilliseconds(5);
     EXPECT_CALL(*send_algorithm_,
                 OnPacketAcked(_, _, _)).Times(i == 3 ? 2 : 1);
-    SequenceNumberSet retransmissions =
-        manager_.OnIncomingAckFrame(received_info, clock_.Now());
-    EXPECT_EQ(0u, retransmissions.size());
+    manager_.OnIncomingAck(received_info, clock_.Now());
+    EXPECT_FALSE(manager_.HasPendingRetransmissions());
     // The nack count remains at 2 when the packet is acked.
     EXPECT_EQ(i == 3 ? 2u : i,
               QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
@@ -736,21 +724,16 @@
 TEST_F(QuicSentPacketManagerTest, Rtt) {
   QuicPacketSequenceNumber sequence_number = 1;
   QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(15);
-
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                               .Times(1).WillOnce(Return(true));
-  EXPECT_CALL(*send_algorithm_,
-              OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
-
-  manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
-                         NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+  SendDataPacket(sequence_number);
   clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
 
+  EXPECT_CALL(*send_algorithm_,
+              OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
   ReceivedPacketInfo received_info;
   received_info.largest_observed = sequence_number;
   received_info.delta_time_largest_observed =
       QuicTime::Delta::FromMilliseconds(5);
-  manager_.OnIncomingAckFrame(received_info, clock_.Now());
+  manager_.OnIncomingAck(received_info, clock_.Now());
   EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
 }
 
@@ -760,21 +743,16 @@
   // and is hence invalid.
   QuicPacketSequenceNumber sequence_number = 1;
   QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
+  SendDataPacket(sequence_number);
+  clock_.AdvanceTime(expected_rtt);
 
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                               .Times(1).WillOnce(Return(true));
   EXPECT_CALL(*send_algorithm_,
-              OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
-
-  manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
-                         NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
-  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
-
+               OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
   ReceivedPacketInfo received_info;
   received_info.largest_observed = sequence_number;
   received_info.delta_time_largest_observed =
       QuicTime::Delta::FromMilliseconds(11);
-  manager_.OnIncomingAckFrame(received_info, clock_.Now());
+  manager_.OnIncomingAck(received_info, clock_.Now());
   EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
 }
 
@@ -783,20 +761,15 @@
   // delta_time_largest_observed is infinite, and is hence invalid.
   QuicPacketSequenceNumber sequence_number = 1;
   QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
+  SendDataPacket(sequence_number);
+  clock_.AdvanceTime(expected_rtt);
 
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                               .Times(1).WillOnce(Return(true));
   EXPECT_CALL(*send_algorithm_,
               OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
-
-  manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
-                         NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
-  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
-
   ReceivedPacketInfo received_info;
   received_info.largest_observed = sequence_number;
   received_info.delta_time_largest_observed = QuicTime::Delta::Infinite();
-  manager_.OnIncomingAckFrame(received_info, clock_.Now());
+  manager_.OnIncomingAck(received_info, clock_.Now());
   EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
 }
 
@@ -805,20 +778,15 @@
   // delta_time_largest_observed is zero.
   QuicPacketSequenceNumber sequence_number = 1;
   QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
-
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
-                               .Times(1).WillOnce(Return(true));
-  EXPECT_CALL(*send_algorithm_, OnPacketAcked(sequence_number, _, expected_rtt))
-      .Times(1);
-
-  manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
-                         NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+  SendDataPacket(sequence_number);
   clock_.AdvanceTime(expected_rtt);
 
+  EXPECT_CALL(*send_algorithm_, OnPacketAcked(sequence_number, _, expected_rtt))
+      .Times(1);
   ReceivedPacketInfo received_info;
   received_info.largest_observed = sequence_number;
   received_info.delta_time_largest_observed = QuicTime::Delta::Zero();
-  manager_.OnIncomingAckFrame(received_info, clock_.Now());
+  manager_.OnIncomingAck(received_info, clock_.Now());
   EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
 }
 
@@ -837,6 +805,10 @@
   manager_.OnRetransmissionTimeout();
 }
 
+TEST_F(QuicSentPacketManagerTest, GetTransmissionTime) {
+  EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
+}
+
 TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
   EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
       .WillOnce(Return(QuicTime::Delta::FromMilliseconds(1)));
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
index e2e7c02..429a4050 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -28,6 +28,12 @@
 }
 
 // static
+size_t QuicSentPacketManagerPeer::GetPendingRetransmissionCount(
+    const QuicSentPacketManager* sent_packet_manager) {
+  return sent_packet_manager->pending_retransmissions_.size();
+}
+
+// static
 QuicTime QuicSentPacketManagerPeer::GetSentTime(
     const QuicSentPacketManager* sent_packet_manager,
     QuicPacketSequenceNumber sequence_number) {
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.h b/net/quic/test_tools/quic_sent_packet_manager_peer.h
index 2ed9b21..9728d43 100644
--- a/net/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -23,6 +23,9 @@
       const QuicSentPacketManager* sent_packet_manager,
       QuicPacketSequenceNumber sequence_number);
 
+  static size_t GetPendingRetransmissionCount(
+      const QuicSentPacketManager* sent_packet_manager);
+
   static QuicTime GetSentTime(const QuicSentPacketManager* sent_packet_manager,
                               QuicPacketSequenceNumber sequence_number);
 
diff --git a/net/quic/test_tools/quic_session_peer.cc b/net/quic/test_tools/quic_session_peer.cc
index c25b42fb..c1fe7e0 100644
--- a/net/quic/test_tools/quic_session_peer.cc
+++ b/net/quic/test_tools/quic_session_peer.cc
@@ -27,5 +27,12 @@
   return &session->write_blocked_streams_;
 }
 
+// static
+QuicDataStream* QuicSessionPeer::GetIncomingReliableStream(
+    QuicSession* session,
+    QuicStreamId stream_id) {
+  return session->GetIncomingReliableStream(stream_id);
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/quic_session_peer.h b/net/quic/test_tools/quic_session_peer.h
index fb4529c..3151d84b 100644
--- a/net/quic/test_tools/quic_session_peer.h
+++ b/net/quic/test_tools/quic_session_peer.h
@@ -10,6 +10,7 @@
 
 namespace net {
 
+class QuicDataStream;
 class QuicSession;
 class ReliableQuicStream;
 
@@ -21,6 +22,8 @@
   static void SetMaxOpenStreams(QuicSession* session, uint32 max_streams);
   static WriteBlockedList<QuicStreamId>* GetWriteblockedStreams(
       QuicSession* session);
+  static QuicDataStream* GetIncomingReliableStream(QuicSession* session,
+                                                   QuicStreamId stream_id);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(QuicSessionPeer);
diff --git a/net/quic/test_tools/reliable_quic_stream_peer.cc b/net/quic/test_tools/reliable_quic_stream_peer.cc
index 5119d03..6379c07 100644
--- a/net/quic/test_tools/reliable_quic_stream_peer.cc
+++ b/net/quic/test_tools/reliable_quic_stream_peer.cc
@@ -22,5 +22,10 @@
   stream->stream_bytes_written_ = stream_bytes_written;
 }
 
+// static
+void ReliableQuicStreamPeer::CloseReadSide(ReliableQuicStream* stream) {
+  stream->CloseReadSide();
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/reliable_quic_stream_peer.h b/net/quic/test_tools/reliable_quic_stream_peer.h
index da229da..291794f8 100644
--- a/net/quic/test_tools/reliable_quic_stream_peer.h
+++ b/net/quic/test_tools/reliable_quic_stream_peer.h
@@ -19,6 +19,7 @@
   static void SetWriteSideClosed(bool value, ReliableQuicStream* stream);
   static void SetStreamBytesWritten(QuicStreamOffset stream_bytes_written,
                                     ReliableQuicStream* stream);
+  static void CloseReadSide(ReliableQuicStream* stream);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ReliableQuicStreamPeer);
diff --git a/net/tools/quic/quic_server_session.h b/net/tools/quic/quic_server_session.h
index f470551..ff921bb 100644
--- a/net/tools/quic/quic_server_session.h
+++ b/net/tools/quic/quic_server_session.h
@@ -52,7 +52,9 @@
 
   virtual void InitializeSession(const QuicCryptoServerConfig& crypto_config);
 
-  const QuicCryptoServerStream* crypto_stream() { return crypto_stream_.get(); }
+  const QuicCryptoServerStream* crypto_stream() const {
+    return crypto_stream_.get();
+  }
 
  protected:
   // QuicSession methods: