Merge from Chromium at DEPS revision 275586

This commit was generated by merge_to_master.py.

Change-Id: Ief3a0ffd810858bfddbe0ec5931e3ee90d53f78c
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
index 8027205..c346a63 100644
--- a/net/quic/congestion_control/fix_rate_sender.cc
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -26,7 +26,6 @@
       bitrate_(QuicBandwidth::FromBytesPerSecond(kInitialBitrate)),
       max_segment_size_(kDefaultMaxPacketSize),
       fix_rate_leaky_bucket_(bitrate_),
-      paced_sender_(bitrate_, max_segment_size_),
       latest_rtt_(QuicTime::Delta::Zero()) {
   DVLOG(1) << "FixRateSender";
 }
@@ -45,7 +44,6 @@
   if (feedback.type == kFixRate) {
     bitrate_ = feedback.fix_rate.bitrate;
     fix_rate_leaky_bucket_.SetDrainingRate(feedback_receive_time, bitrate_);
-    paced_sender_.UpdateBandwidthEstimate(feedback_receive_time, bitrate_);
   }
   // Silently ignore invalid messages in release mode.
 }
@@ -63,7 +61,6 @@
     QuicByteCount bytes,
     HasRetransmittableData /*has_retransmittable_data*/) {
   fix_rate_leaky_bucket_.Add(sent_time, bytes);
-  paced_sender_.OnPacketSent(sent_time, bytes);
 
   return true;
 }
@@ -72,24 +69,12 @@
 
 QuicTime::Delta FixRateSender::TimeUntilSend(
     QuicTime now,
-    QuicByteCount bytes_in_flight,
-    HasRetransmittableData /*has_retransmittable_data*/) {
-  if (CongestionWindow() > fix_rate_leaky_bucket_.BytesPending(now)) {
-    if (CongestionWindow() <= bytes_in_flight) {
-      // We need an ack before we send more.
-      return QuicTime::Delta::Infinite();
-    }
-    return paced_sender_.TimeUntilSend(now, QuicTime::Delta::Zero());
-  }
-  QuicTime::Delta time_remaining = fix_rate_leaky_bucket_.TimeRemaining(now);
-  if (time_remaining.IsZero()) {
-    // We need an ack before we send more.
-    return QuicTime::Delta::Infinite();
-  }
-  return paced_sender_.TimeUntilSend(now, time_remaining);
+    QuicByteCount /*bytes_in_flight*/,
+    HasRetransmittableData /*has_retransmittable_data*/) const {
+  return fix_rate_leaky_bucket_.TimeRemaining(now);
 }
 
-QuicByteCount FixRateSender::CongestionWindow() {
+QuicByteCount FixRateSender::CongestionWindow() const {
   QuicByteCount window_size_bytes = bitrate_.ToBytesPerPeriod(
       QuicTime::Delta::FromMicroseconds(kWindowSizeUs));
   // Make sure window size is not less than a packet.
diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h
index 6f85090..3cb07ff 100644
--- a/net/quic/congestion_control/fix_rate_sender.h
+++ b/net/quic/congestion_control/fix_rate_sender.h
@@ -14,7 +14,6 @@
 #include "net/quic/quic_connection_stats.h"
 #include "net/quic/quic_time.h"
 #include "net/quic/congestion_control/leaky_bucket.h"
-#include "net/quic/congestion_control/paced_sender.h"
 #include "net/quic/congestion_control/send_algorithm_interface.h"
 
 namespace net {
@@ -45,20 +44,19 @@
   virtual QuicTime::Delta TimeUntilSend(
       QuicTime now,
       QuicByteCount bytes_in_flight,
-      HasRetransmittableData has_retransmittable_data) OVERRIDE;
+      HasRetransmittableData has_retransmittable_data) const OVERRIDE;
   virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
   virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
   virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
   // End implementation of SendAlgorithmInterface.
 
  private:
-  QuicByteCount CongestionWindow();
+  QuicByteCount CongestionWindow() const;
 
   const RttStats* rtt_stats_;
   QuicBandwidth bitrate_;
   QuicByteCount max_segment_size_;
   LeakyBucket fix_rate_leaky_bucket_;
-  PacedSender paced_sender_;
   QuicTime::Delta latest_rtt_;
 
   DISALLOW_COPY_AND_ASSIGN(FixRateSender);
diff --git a/net/quic/congestion_control/fix_rate_test.cc b/net/quic/congestion_control/fix_rate_test.cc
index e696823..c82bb60 100644
--- a/net/quic/congestion_control/fix_rate_test.cc
+++ b/net/quic/congestion_control/fix_rate_test.cc
@@ -68,59 +68,33 @@
 
   sender_->OnPacketSent(clock_.Now(), kUnused, 1, kDefaultMaxPacketSize,
                         HAS_RETRANSMITTABLE_DATA);
+  EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
+                                      kDefaultMaxPacketSize,
+                                      HAS_RETRANSMITTABLE_DATA).IsZero());
+  clock_.AdvanceTime(sender_->TimeUntilSend(clock_.Now(),
+                                            kDefaultMaxPacketSize,
+                                            HAS_RETRANSMITTABLE_DATA));
   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
                                      kDefaultMaxPacketSize,
                                      HAS_RETRANSMITTABLE_DATA).IsZero());
   sender_->OnPacketSent(clock_.Now(), kUnused, 2, kDefaultMaxPacketSize,
                         HAS_RETRANSMITTABLE_DATA);
-  sender_->OnPacketSent(clock_.Now(), kUnused, 3, 600,
-                        HAS_RETRANSMITTABLE_DATA);
-  EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10),
-            sender_->TimeUntilSend(clock_.Now(),
-                                   kDefaultMaxPacketSize * 2 + 600,
-                                   HAS_RETRANSMITTABLE_DATA));
-  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
-  EXPECT_EQ(QuicTime::Delta::Infinite(),
-            sender_->TimeUntilSend(clock_.Now(),
-                                   kDefaultMaxPacketSize * 2 + 600,
-                                   HAS_RETRANSMITTABLE_DATA));
-  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+  EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
+                                      kDefaultMaxPacketSize,
+                                      HAS_RETRANSMITTABLE_DATA).IsZero());
+  // Advance the time twice as much and expect only one packet to be sent.
+  clock_.AdvanceTime(sender_->TimeUntilSend(
+      clock_.Now(),
+      kDefaultMaxPacketSize,
+      HAS_RETRANSMITTABLE_DATA).Multiply(2));
   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
-                                     0,
+                                     kDefaultMaxPacketSize,
                                      HAS_RETRANSMITTABLE_DATA).IsZero());
-}
-
-TEST_F(FixRateTest, FixRatePacing) {
-  const QuicByteCount packet_size = 1200;
-  const QuicBandwidth bitrate = QuicBandwidth::FromKBytesPerSecond(240);
-  const int64 num_packets = 200;
-  QuicCongestionFeedbackFrame feedback;
-  receiver_->SetBitrate(QuicBandwidth::FromKBytesPerSecond(240));
-  ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
-  sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
-  QuicTime acc_advance_time(QuicTime::Zero());
-  QuicPacketSequenceNumber sequence_number = 0;
-  for (int i = 0; i < num_packets; i += 2) {
-    EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
-                                       0,
-                                       HAS_RETRANSMITTABLE_DATA).IsZero());
-    sender_->OnPacketSent(clock_.Now(), kUnused, sequence_number++, packet_size,
-                          HAS_RETRANSMITTABLE_DATA);
-    EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
-                                       kDefaultMaxPacketSize,
-                                       HAS_RETRANSMITTABLE_DATA).IsZero());
-    sender_->OnPacketSent(clock_.Now(), kUnused, sequence_number++, packet_size,
-                          HAS_RETRANSMITTABLE_DATA);
-    QuicTime::Delta advance_time =
-        sender_->TimeUntilSend(clock_.Now(),
-                               2 * kDefaultMaxPacketSize,
-                               HAS_RETRANSMITTABLE_DATA);
-    clock_.AdvanceTime(advance_time);
-    acc_advance_time = acc_advance_time.Add(advance_time);
-  }
-  EXPECT_EQ(num_packets * packet_size * 1000000 / bitrate.ToBytesPerSecond(),
-            static_cast<uint64>(acc_advance_time.Subtract(start_)
-                                .ToMicroseconds()));
+  sender_->OnPacketSent(clock_.Now(), kUnused, 3, kDefaultMaxPacketSize,
+                        HAS_RETRANSMITTABLE_DATA);
+  EXPECT_FALSE(sender_->TimeUntilSend(clock_.Now(),
+                                      kDefaultMaxPacketSize,
+                                      HAS_RETRANSMITTABLE_DATA).IsZero());
 }
 
 }  // namespace test
diff --git a/net/quic/congestion_control/leaky_bucket.cc b/net/quic/congestion_control/leaky_bucket.cc
index 06c1f87..f3972f6 100644
--- a/net/quic/congestion_control/leaky_bucket.cc
+++ b/net/quic/congestion_control/leaky_bucket.cc
@@ -24,11 +24,15 @@
   bytes_ += bytes;
 }
 
-QuicTime::Delta LeakyBucket::TimeRemaining(QuicTime now) {
-  Update(now);
-  return QuicTime::Delta::FromMicroseconds(
+QuicTime::Delta LeakyBucket::TimeRemaining(QuicTime now) const {
+  QuicTime::Delta time_since_last_update = now.Subtract(time_last_updated_);
+  QuicTime::Delta send_delay = QuicTime::Delta::FromMicroseconds(
       (bytes_ * base::Time::kMicrosecondsPerSecond) /
       draining_rate_.ToBytesPerSecond());
+  if (send_delay < time_since_last_update) {
+    return QuicTime::Delta::Zero();
+  }
+  return send_delay.Subtract(time_since_last_update);
 }
 
 QuicByteCount LeakyBucket::BytesPending(QuicTime now) {
diff --git a/net/quic/congestion_control/leaky_bucket.h b/net/quic/congestion_control/leaky_bucket.h
index 8717620..eb4cdb0 100644
--- a/net/quic/congestion_control/leaky_bucket.h
+++ b/net/quic/congestion_control/leaky_bucket.h
@@ -29,7 +29,7 @@
   void Add(QuicTime now, QuicByteCount bytes);
 
   // Time until the buffer is empty.
-  QuicTime::Delta TimeRemaining(QuicTime now);
+  QuicTime::Delta TimeRemaining(QuicTime now) const;
 
   // Number of bytes in the buffer.
   QuicByteCount BytesPending(QuicTime now);
diff --git a/net/quic/congestion_control/paced_sender.cc b/net/quic/congestion_control/paced_sender.cc
deleted file mode 100644
index 87042a5..0000000
--- a/net/quic/congestion_control/paced_sender.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/congestion_control/paced_sender.h"
-
-#include <algorithm>
-
-#include "net/quic/quic_protocol.h"
-
-using std::max;
-
-namespace net {
-
-// To prevent too aggressive pacing we allow the following packet burst size.
-const int64 kMinPacketBurstSize = 2;
-// Max estimated time between calls to TimeUntilSend and
-// AvailableCongestionWindow.
-const int64 kMaxSchedulingDelayUs = 2000;
-
-PacedSender::PacedSender(QuicBandwidth estimate, QuicByteCount max_segment_size)
-    : leaky_bucket_(estimate),
-      pace_(estimate),
-      max_segment_size_(kDefaultMaxPacketSize) {
-}
-
-void PacedSender::UpdateBandwidthEstimate(QuicTime now,
-                                          QuicBandwidth estimate) {
-  leaky_bucket_.SetDrainingRate(now, estimate);
-  pace_ = estimate;
-}
-
-void PacedSender::OnPacketSent(QuicTime now, QuicByteCount bytes) {
-  leaky_bucket_.Add(now, bytes);
-}
-
-QuicTime::Delta PacedSender::TimeUntilSend(QuicTime now,
-                                           QuicTime::Delta time_until_send) {
-  if (time_until_send.ToMicroseconds() >= kMaxSchedulingDelayUs) {
-    return time_until_send;
-  }
-  // Pace the data.
-  QuicByteCount pacing_window = pace_.ToBytesPerPeriod(
-      QuicTime::Delta::FromMicroseconds(kMaxSchedulingDelayUs));
-  QuicByteCount min_window_size = kMinPacketBurstSize *  max_segment_size_;
-  pacing_window = max(pacing_window, min_window_size);
-
-  if (pacing_window > leaky_bucket_.BytesPending(now)) {
-    // We have not filled our pacing window yet.
-    return time_until_send;
-  }
-  return leaky_bucket_.TimeRemaining(now);
-}
-
-}  // namespace net
diff --git a/net/quic/congestion_control/paced_sender.h b/net/quic/congestion_control/paced_sender.h
deleted file mode 100644
index d600dcb..0000000
--- a/net/quic/congestion_control/paced_sender.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Helper class that limits the congestion window to pace the packets.
-
-#ifndef NET_QUIC_CONGESTION_CONTROL_PACED_SENDER_H_
-#define NET_QUIC_CONGESTION_CONTROL_PACED_SENDER_H_
-
-#include "base/basictypes.h"
-#include "net/base/net_export.h"
-#include "net/quic/congestion_control/leaky_bucket.h"
-#include "net/quic/quic_bandwidth.h"
-#include "net/quic/quic_time.h"
-
-namespace net {
-
-class NET_EXPORT_PRIVATE PacedSender {
- public:
-  PacedSender(QuicBandwidth bandwidth_estimate, QuicByteCount max_segment_size);
-
-  // The estimated bandidth from the congestion algorithm changed.
-  void UpdateBandwidthEstimate(QuicTime now, QuicBandwidth bandwidth_estimate);
-
-  // A packet of size bytes was sent.
-  void OnPacketSent(QuicTime now, QuicByteCount bytes);
-
-  // Return time until we can send based on the pacing.
-  QuicTime::Delta TimeUntilSend(QuicTime now, QuicTime::Delta time_until_send);
-
- private:
-  // Helper object to track the rate data can leave the buffer for pacing.
-  LeakyBucket leaky_bucket_;
-  QuicBandwidth pace_;
-  QuicByteCount max_segment_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(PacedSender);
-};
-
-}  // namespace net
-
-#endif  // NET_QUIC_CONGESTION_CONTROL_PACED_SENDER_H_
diff --git a/net/quic/congestion_control/paced_sender_test.cc b/net/quic/congestion_control/paced_sender_test.cc
deleted file mode 100644
index fa42c2c..0000000
--- a/net/quic/congestion_control/paced_sender_test.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/quic/congestion_control/paced_sender.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/test_tools/mock_clock.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace test {
-
-const int kHundredKBytesPerS = 100;
-
-class PacedSenderTest : public ::testing::Test {
- protected:
-  PacedSenderTest()
-      : zero_time_(QuicTime::Delta::Zero()),
-        paced_sender_(new PacedSender(
-            QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS),
-            kDefaultMaxPacketSize)) {
-  }
-
-  const QuicTime::Delta zero_time_;
-  MockClock clock_;
-  scoped_ptr<PacedSender> paced_sender_;
-};
-
-TEST_F(PacedSenderTest, Basic) {
-  paced_sender_->UpdateBandwidthEstimate(clock_.Now(),
-      QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS * 10));
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-  paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-  paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
-  EXPECT_EQ(static_cast<int64>(kDefaultMaxPacketSize * 2),
-            paced_sender_->TimeUntilSend(
-                clock_.Now(), zero_time_).ToMicroseconds());
-  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(24));
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-}
-
-TEST_F(PacedSenderTest, LowRate) {
-  paced_sender_->UpdateBandwidthEstimate(clock_.Now(),
-      QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS));
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-  paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-  paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
-  EXPECT_EQ(static_cast<int64>(kDefaultMaxPacketSize * 20),
-            paced_sender_->TimeUntilSend(
-                clock_.Now(), zero_time_).ToMicroseconds());
-  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(24));
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-}
-
-TEST_F(PacedSenderTest, HighRate) {
-  QuicBandwidth bandwidth_estimate = QuicBandwidth::FromKBytesPerSecond(
-      kHundredKBytesPerS * 100);
-  paced_sender_->UpdateBandwidthEstimate(clock_.Now(), bandwidth_estimate);
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-  for (int i = 0; i < 16; ++i) {
-    paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
-    EXPECT_TRUE(paced_sender_->TimeUntilSend(
-        clock_.Now(), zero_time_).IsZero());
-  }
-  paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
-  EXPECT_EQ(2040, paced_sender_->TimeUntilSend(
-      clock_.Now(), zero_time_).ToMicroseconds());
-  clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(20400));
-  EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
-}
-
-}  // namespace test
-}  // namespace net
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc
index c487d2a..97138f7 100644
--- a/net/quic/congestion_control/pacing_sender.cc
+++ b/net/quic/congestion_control/pacing_sender.cc
@@ -10,6 +10,7 @@
                            QuicTime::Delta alarm_granularity)
     : sender_(sender),
       alarm_granularity_(alarm_granularity),
+      last_delayed_packet_sent_time_(QuicTime::Zero()),
       next_packet_send_time_(QuicTime::Zero()),
       was_last_send_delayed_(false),
       has_valid_rtt_(false) {
@@ -54,7 +55,30 @@
     const float kPacingAggression = 2;
     QuicTime::Delta delay =
         BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes);
-    next_packet_send_time_ = next_packet_send_time_.Add(delay);
+    // If the last send was delayed, and the alarm took a long time to get
+    // invoked, allow the connection to make up for lost time.
+    if (was_last_send_delayed_) {
+      next_packet_send_time_ = next_packet_send_time_.Add(delay);
+      // The send was application limited if it takes longer than the
+      // pacing delay between sent packets.
+      const bool application_limited =
+          last_delayed_packet_sent_time_.IsInitialized() &&
+          sent_time > last_delayed_packet_sent_time_.Add(delay);
+      const bool making_up_for_lost_time = next_packet_send_time_ <= sent_time;
+      // As long as we're making up time and not application limited,
+      // continue to consider the packets delayed, allowing the packets to be
+      // sent immediately.
+      if (making_up_for_lost_time && !application_limited) {
+        last_delayed_packet_sent_time_ = sent_time;
+      } else {
+        was_last_send_delayed_ = false;
+        last_delayed_packet_sent_time_ = QuicTime::Zero();
+      }
+    } else {
+      next_packet_send_time_ =
+          QuicTime::Max(next_packet_send_time_.Add(delay),
+                        sent_time.Add(delay).Subtract(alarm_granularity_));
+    }
   }
   return sender_->OnPacketSent(sent_time, bytes_in_flight, sequence_number,
                                bytes, has_retransmittable_data);
@@ -67,7 +91,7 @@
 QuicTime::Delta PacingSender::TimeUntilSend(
       QuicTime now,
       QuicByteCount bytes_in_flight,
-      HasRetransmittableData has_retransmittable_data) {
+      HasRetransmittableData has_retransmittable_data) const {
   QuicTime::Delta time_until_send =
       sender_->TimeUntilSend(now, bytes_in_flight, has_retransmittable_data);
   if (!has_valid_rtt_) {
@@ -87,25 +111,14 @@
     return QuicTime::Delta::Zero();
   }
 
-  if (!was_last_send_delayed_ &&
-      (!next_packet_send_time_.IsInitialized() ||
-       now > next_packet_send_time_.Add(alarm_granularity_))) {
-    // An alarm did not go off late, instead the application is "slow"
-    // delivering data.  In this case, we restrict the amount of lost time
-    // that we can make up for.
-    next_packet_send_time_ = now.Subtract(alarm_granularity_);
-  }
-
-  // If the end of the epoch is far enough in the future, delay the send.
+  // If the next send time is within the alarm granularity, send immediately.
   if (next_packet_send_time_ > now.Add(alarm_granularity_)) {
-    was_last_send_delayed_ = true;
     DVLOG(1) << "Delaying packet: "
              << next_packet_send_time_.Subtract(now).ToMicroseconds();
+    was_last_send_delayed_ = true;
     return next_packet_send_time_.Subtract(now);
   }
 
-  // Sent it immediately.  The epoch end will be adjusted in OnPacketSent.
-  was_last_send_delayed_ = false;
   DVLOG(1) << "Sending packet now";
   return QuicTime::Delta::Zero();
 }
diff --git a/net/quic/congestion_control/pacing_sender.h b/net/quic/congestion_control/pacing_sender.h
index b1060ac..c741771 100644
--- a/net/quic/congestion_control/pacing_sender.h
+++ b/net/quic/congestion_control/pacing_sender.h
@@ -47,7 +47,7 @@
   virtual QuicTime::Delta TimeUntilSend(
       QuicTime now,
       QuicByteCount bytes_in_flight,
-      HasRetransmittableData has_retransmittable_data) OVERRIDE;
+      HasRetransmittableData has_retransmittable_data) const OVERRIDE;
   virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
   virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
   virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
@@ -55,8 +55,10 @@
  private:
   scoped_ptr<SendAlgorithmInterface> sender_;  // Underlying sender.
   QuicTime::Delta alarm_granularity_;
+  // Send time of the last packet considered delayed.
+  QuicTime last_delayed_packet_sent_time_;
   QuicTime next_packet_send_time_;  // When can the next packet be sent.
-  bool was_last_send_delayed_;  // True when the last send was delayed.
+  mutable bool was_last_send_delayed_;  // True when the last send was delayed.
   bool has_valid_rtt_;  // True if we have at least one RTT update.
 
   DISALLOW_COPY_AND_ASSIGN(PacingSender);
diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc
index 38e5d02..2dc6960 100644
--- a/net/quic/congestion_control/pacing_sender_test.cc
+++ b/net/quic/congestion_control/pacing_sender_test.cc
@@ -38,15 +38,17 @@
   void CheckPacketIsSentImmediately() {
     // In order for the packet to be sendable, the underlying sender must
     // permit it to be sent immediately.
-    EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
-                                             kBytesInFlight,
-                                             HAS_RETRANSMITTABLE_DATA))
-        .WillOnce(Return(zero_time_));
-    // Verify that the packet can be sent immediately.
-    EXPECT_EQ(zero_time_,
-              pacing_sender_->TimeUntilSend(clock_.Now(),
-                                            kBytesInFlight,
-                                            HAS_RETRANSMITTABLE_DATA));
+    for (int i = 0; i < 2; ++i) {
+      EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+                                               kBytesInFlight,
+                                               HAS_RETRANSMITTABLE_DATA))
+          .WillOnce(Return(zero_time_));
+      // Verify that the packet can be sent immediately.
+      EXPECT_EQ(zero_time_,
+                pacing_sender_->TimeUntilSend(clock_.Now(),
+                                              kBytesInFlight,
+                                              HAS_RETRANSMITTABLE_DATA));
+    }
 
     // Actually send the packet.
     EXPECT_CALL(*mock_sender_,
@@ -82,15 +84,17 @@
   void CheckPacketIsDelayed(QuicTime::Delta delay) {
     // In order for the packet to be sendable, the underlying sender must
     // permit it to be sent immediately.
-    EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
-                                             kBytesInFlight,
-                                             HAS_RETRANSMITTABLE_DATA))
-        .WillOnce(Return(zero_time_));
-    // Verify that the packet is delayed.
-    EXPECT_EQ(delay.ToMicroseconds(),
-              pacing_sender_->TimeUntilSend(
-                  clock_.Now(), kBytesInFlight,
-                  HAS_RETRANSMITTABLE_DATA).ToMicroseconds());
+    for (int i = 0; i < 2; ++i) {
+      EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+                                               kBytesInFlight,
+                                               HAS_RETRANSMITTABLE_DATA))
+          .WillOnce(Return(zero_time_));
+      // Verify that the packet is delayed.
+      EXPECT_EQ(delay.ToMicroseconds(),
+                pacing_sender_->TimeUntilSend(
+                    clock_.Now(), kBytesInFlight,
+                    HAS_RETRANSMITTABLE_DATA).ToMicroseconds());
+    }
   }
 
   const QuicTime::Delta zero_time_;
@@ -102,25 +106,29 @@
 };
 
 TEST_F(PacingSenderTest, NoSend) {
-  EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
-                                           kBytesInFlight,
-                                           HAS_RETRANSMITTABLE_DATA))
-      .WillOnce(Return(infinite_time_));
-  EXPECT_EQ(infinite_time_,
-            pacing_sender_->TimeUntilSend(clock_.Now(),
-                                          kBytesInFlight,
-                                          HAS_RETRANSMITTABLE_DATA));
+  for (int i = 0; i < 2; ++i) {
+    EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+                                             kBytesInFlight,
+                                             HAS_RETRANSMITTABLE_DATA))
+        .WillOnce(Return(infinite_time_));
+    EXPECT_EQ(infinite_time_,
+              pacing_sender_->TimeUntilSend(clock_.Now(),
+                                            kBytesInFlight,
+                                            HAS_RETRANSMITTABLE_DATA));
+  }
 }
 
 TEST_F(PacingSenderTest, SendNow) {
-  EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
-                                           kBytesInFlight,
-                                           HAS_RETRANSMITTABLE_DATA))
-      .WillOnce(Return(zero_time_));
-  EXPECT_EQ(zero_time_,
-            pacing_sender_->TimeUntilSend(clock_.Now(),
-                                          kBytesInFlight,
-                                          HAS_RETRANSMITTABLE_DATA));
+  for (int i = 0; i < 2; ++i) {
+    EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+                                             kBytesInFlight,
+                                             HAS_RETRANSMITTABLE_DATA))
+        .WillOnce(Return(zero_time_));
+    EXPECT_EQ(zero_time_,
+              pacing_sender_->TimeUntilSend(clock_.Now(),
+                                            kBytesInFlight,
+                                            HAS_RETRANSMITTABLE_DATA));
+  }
 }
 
 TEST_F(PacingSenderTest, VariousSending) {
@@ -163,6 +171,29 @@
   CheckPacketIsSentImmediately();
   CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
 
+  // Wake up really late.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  // Wake up really late again, but application pause partway through.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
   // Wake up too early.
   CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
 
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index 12cf8f6..6b1c755 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -71,7 +71,7 @@
   virtual QuicTime::Delta TimeUntilSend(
       QuicTime now,
       QuicByteCount bytes_in_flight,
-      HasRetransmittableData has_retransmittable_data) = 0;
+      HasRetransmittableData has_retransmittable_data) const = 0;
 
   // What's the current estimated bandwidth in bytes per second.
   // Returns 0 when it does not have an estimate.
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index aaec6a4..19f07d4 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -170,7 +170,7 @@
 QuicTime::Delta TcpCubicSender::TimeUntilSend(
     QuicTime /* now */,
     QuicByteCount bytes_in_flight,
-    HasRetransmittableData has_retransmittable_data) {
+    HasRetransmittableData has_retransmittable_data) const {
   if (has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
     // For TCP we can always send an ACK immediately.
     return QuicTime::Delta::Zero();
@@ -184,7 +184,7 @@
   return QuicTime::Delta::Infinite();
 }
 
-QuicByteCount TcpCubicSender::SendWindow() {
+QuicByteCount TcpCubicSender::SendWindow() const {
   // What's the current send window in bytes.
   return min(receive_window_, GetCongestionWindow());
 }
@@ -294,7 +294,7 @@
 }
 
 QuicTime::Delta TcpCubicSender::PrrTimeUntilSend(
-    QuicByteCount bytes_in_flight) {
+    QuicByteCount bytes_in_flight) const {
   DCHECK(InRecovery());
   // Return QuicTime::Zero In order to ensure limited transmit always works.
   if (prr_out_ == 0) {
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index 12fd997..f9234c9 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -57,7 +57,7 @@
   virtual QuicTime::Delta TimeUntilSend(
       QuicTime now,
       QuicByteCount bytes_in_flight,
-      HasRetransmittableData has_retransmittable_data) OVERRIDE;
+      HasRetransmittableData has_retransmittable_data) const OVERRIDE;
   virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
   virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
   virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
@@ -73,7 +73,7 @@
   void OnPacketLost(QuicPacketSequenceNumber largest_loss,
                     QuicByteCount bytes_in_flight);
 
-  QuicByteCount SendWindow();
+  QuicByteCount SendWindow() const;
   void MaybeIncreaseCwnd(QuicPacketSequenceNumber acked_sequence_number,
                          QuicByteCount bytes_in_flight);
   bool IsCwndLimited(QuicByteCount bytes_in_flight) const;
@@ -81,7 +81,7 @@
   // Methods for isolating PRR from the rest of TCP Cubic.
   void PrrOnPacketLost(QuicByteCount bytes_in_flight);
   void PrrOnPacketAcked(QuicByteCount acked_bytes);
-  QuicTime::Delta PrrTimeUntilSend(QuicByteCount bytes_in_flight);
+  QuicTime::Delta PrrTimeUntilSend(QuicByteCount bytes_in_flight) const;
 
 
   HybridSlowStart hybrid_slow_start_;
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc
index f2cd696..9e08344 100644
--- a/net/quic/crypto/crypto_handshake_message.cc
+++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -256,6 +256,7 @@
       case kKEXS:
       case kAEAD:
       case kCGST:
+      case kCOPT:
       case kLOSS:
       case kPDMD:
       case kVER:
@@ -300,6 +301,10 @@
                             static_cast<int>(it->second.size()));
         done = true;
         break;
+      case kUAID:
+        ret += it->second;
+        done = true;
+        break;
     }
 
     if (!done) {
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index c508147..c30ce44 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -47,6 +47,9 @@
 const QuicTag kPACE = TAG('P', 'A', 'C', 'E');  // Paced TCP cubic
 const QuicTag kINAR = TAG('I', 'N', 'A', 'R');  // Inter arrival
 
+// Congestion control options
+const QuicTag kTBBR = TAG('T', 'B', 'B', 'R');  // Reduced Buffer Bloat TCP
+
 // Loss detection algorithm types
 const QuicTag kNACK = TAG('N', 'A', 'C', 'K');  // TCP style nack counting
 const QuicTag kTIME = TAG('T', 'I', 'M', 'E');  // Time based
@@ -68,6 +71,7 @@
                                                 // encryption algorithms
 const QuicTag kCGST = TAG('C', 'G', 'S', 'T');  // Congestion control
                                                 // feedback types
+const QuicTag kCOPT = TAG('C', 'O', 'P', 'T');  // Congestion control options
 // kLOSS was 'L', 'O', 'S', 'S', but was changed from a tag vector to a tag.
 const QuicTag kLOSS = TAG('L', 'O', 'S', 'A');  // Loss detection algorithms
 const QuicTag kICSL = TAG('I', 'C', 'S', 'L');  // Idle connection state
@@ -89,6 +93,8 @@
 const QuicTag kEXPY = TAG('E', 'X', 'P', 'Y');  // Expiry
 const QuicTag kIFCW = TAG('I', 'F', 'C', 'W');  // Initial flow control receive
                                                 // window.
+const QuicTag kUAID = TAG('U', 'A', 'I', 'D');  // Client's User Agent ID.
+
 
 // Server hello tags
 const QuicTag kCADR = TAG('C', 'A', 'D', 'R');  // Client IP address and port
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index 31b2a60..56e9abc 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -70,22 +70,22 @@
   TestProofVerifierCallback* callback =
       new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
 
-  ProofVerifier::Status status = verifier->VerifyProof(
+  QuicAsyncStatus status = verifier->VerifyProof(
       hostname, server_config, certs, proof, verify_context.get(),
       &error_details, &details, callback);
 
   switch (status) {
-    case ProofVerifier::FAILURE:
+    case QUIC_FAILURE:
       delete callback;
       ASSERT_FALSE(expected_ok);
       ASSERT_NE("", error_details);
       return;
-    case ProofVerifier::SUCCESS:
+    case QUIC_SUCCESS:
       delete callback;
       ASSERT_TRUE(expected_ok);
       ASSERT_EQ("", error_details);
       return;
-    case ProofVerifier::PENDING:
+    case QUIC_PENDING:
       comp_callback.WaitForResult();
       ASSERT_EQ(expected_ok, ok);
       break;
diff --git a/net/quic/crypto/proof_verifier.h b/net/quic/crypto/proof_verifier.h
index 779d63f..12bbb4c 100644
--- a/net/quic/crypto/proof_verifier.h
+++ b/net/quic/crypto/proof_verifier.h
@@ -10,6 +10,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "net/base/net_export.h"
+#include "net/quic/quic_types.h"
 
 namespace net {
 
@@ -49,42 +50,33 @@
 // chain that backs the public key.
 class NET_EXPORT_PRIVATE ProofVerifier {
  public:
-  // Status enumerates the possible results of verifying a proof.
-  enum Status {
-    SUCCESS = 0,
-    FAILURE = 1,
-    // PENDING results from a verification which will occur asynchonously. When
-    // the verification is complete, |callback|'s |Run| method will be called.
-    PENDING = 2,
-  };
-
   virtual ~ProofVerifier() {}
 
   // VerifyProof checks that |signature| is a valid signature of
   // |server_config| by the public key in the leaf certificate of |certs|, and
   // that |certs| is a valid chain for |hostname|. On success, it returns
-  // SUCCESS. On failure, it returns ERROR and sets |*error_details| to a
-  // description of the problem. In either case it may set |*details|, which the
-  // caller takes ownership of.
+  // QUIC_SUCCESS. On failure, it returns QUIC_ERROR and sets |*error_details|
+  // to a description of the problem. In either case it may set |*details|,
+  // which the caller takes ownership of.
   //
   // |context| specifies an implementation specific struct (which may be NULL
   // for some implementations) that provides useful information for the
   // verifier, e.g. logging handles.
   //
-  // This function may also return PENDING, in which case the ProofVerifier
+  // This function may also return QUIC_PENDING, in which case the ProofVerifier
   // will call back, on the original thread, via |callback| when complete.
   // In this case, the ProofVerifier will take ownership of |callback|.
   //
   // The signature uses SHA-256 as the hash function and PSS padding in the
   // case of RSA.
-  virtual Status VerifyProof(const std::string& hostname,
-                             const std::string& server_config,
-                             const std::vector<std::string>& certs,
-                             const std::string& signature,
-                             const ProofVerifyContext* context,
-                             std::string* error_details,
-                             scoped_ptr<ProofVerifyDetails>* details,
-                             ProofVerifierCallback* callback) = 0;
+  virtual QuicAsyncStatus VerifyProof(const std::string& hostname,
+                                      const std::string& server_config,
+                                      const std::vector<std::string>& certs,
+                                      const std::string& signature,
+                                      const ProofVerifyContext* context,
+                                      std::string* error_details,
+                                      scoped_ptr<ProofVerifyDetails>* details,
+                                      ProofVerifierCallback* callback) = 0;
 };
 
 }  // namespace net
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index cbb4436..9829c97 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -42,13 +42,13 @@
 
   // Starts the proof verification.  If |PENDING| is returned, then |callback|
   // will be invoked asynchronously when the verification completes.
-  Status VerifyProof(const std::string& hostname,
-                     const std::string& server_config,
-                     const std::vector<std::string>& certs,
-                     const std::string& signature,
-                     std::string* error_details,
-                     scoped_ptr<ProofVerifyDetails>* verify_details,
-                     ProofVerifierCallback* callback);
+  QuicAsyncStatus VerifyProof(const std::string& hostname,
+                              const std::string& server_config,
+                              const std::vector<std::string>& certs,
+                              const std::string& signature,
+                              std::string* error_details,
+                              scoped_ptr<ProofVerifyDetails>* verify_details,
+                              ProofVerifierCallback* callback);
 
  private:
   enum State {
@@ -98,7 +98,7 @@
       net_log_(net_log) {
 }
 
-ProofVerifierChromium::Status ProofVerifierChromium::Job::VerifyProof(
+QuicAsyncStatus ProofVerifierChromium::Job::VerifyProof(
     const string& hostname,
     const string& server_config,
     const vector<string>& certs,
@@ -115,7 +115,7 @@
   if (STATE_NONE != next_state_) {
     *error_details = "Certificate is already set and VerifyProof has begun";
     DLOG(DFATAL) << *error_details;
-    return FAILURE;
+    return QUIC_FAILURE;
   }
 
   verify_details_.reset(new ProofVerifyDetailsChromium);
@@ -125,7 +125,7 @@
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
     verify_details->reset(verify_details_.release());
-    return FAILURE;
+    return QUIC_FAILURE;
   }
 
   // Convert certs to X509Certificate.
@@ -139,7 +139,7 @@
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
     verify_details->reset(verify_details_.release());
-    return FAILURE;
+    return QUIC_FAILURE;
   }
 
   // We call VerifySignature first to avoid copying of server_config and
@@ -149,7 +149,7 @@
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
     verify_details->reset(verify_details_.release());
-    return FAILURE;
+    return QUIC_FAILURE;
   }
 
   hostname_ = hostname;
@@ -158,14 +158,14 @@
   switch (DoLoop(OK)) {
     case OK:
       verify_details->reset(verify_details_.release());
-      return SUCCESS;
+      return QUIC_SUCCESS;
     case ERR_IO_PENDING:
       callback_.reset(callback);
-      return PENDING;
+      return QUIC_PENDING;
     default:
       *error_details = error_details_;
       verify_details->reset(verify_details_.release());
-      return FAILURE;
+      return QUIC_FAILURE;
   }
 }
 
@@ -317,7 +317,7 @@
   STLDeleteElements(&active_jobs_);
 }
 
-ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof(
+QuicAsyncStatus ProofVerifierChromium::VerifyProof(
     const std::string& hostname,
     const std::string& server_config,
     const std::vector<std::string>& certs,
@@ -328,14 +328,15 @@
     ProofVerifierCallback* callback) {
   if (!verify_context) {
     *error_details = "Missing context";
-    return FAILURE;
+    return QUIC_FAILURE;
   }
   const ProofVerifyContextChromium* chromium_context =
       reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
   scoped_ptr<Job> job(new Job(this, cert_verifier_, chromium_context->net_log));
-  Status status = job->VerifyProof(hostname, server_config, certs, signature,
-                                   error_details, verify_details, callback);
-  if (status == PENDING) {
+  QuicAsyncStatus status = job->VerifyProof(hostname, server_config, certs,
+                                            signature, error_details,
+                                            verify_details, callback);
+  if (status == QUIC_PENDING) {
     active_jobs_.insert(job.release());
   }
   return status;
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index ebf9a2c..6f8a231 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -48,14 +48,15 @@
   virtual ~ProofVerifierChromium();
 
   // ProofVerifier interface
-  virtual Status VerifyProof(const std::string& hostname,
-                             const std::string& server_config,
-                             const std::vector<std::string>& certs,
-                             const std::string& signature,
-                             const ProofVerifyContext* verify_context,
-                             std::string* error_details,
-                             scoped_ptr<ProofVerifyDetails>* verify_details,
-                             ProofVerifierCallback* callback) OVERRIDE;
+  virtual QuicAsyncStatus VerifyProof(
+      const std::string& hostname,
+      const std::string& server_config,
+      const std::vector<std::string>& certs,
+      const std::string& signature,
+      const ProofVerifyContext* verify_context,
+      std::string* error_details,
+      scoped_ptr<ProofVerifyDetails>* verify_details,
+      ProofVerifierCallback* callback) OVERRIDE;
 
  private:
   class Job;
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc
index f9b31fd..f19a5b4 100644
--- a/net/quic/crypto/quic_crypto_client_config.cc
+++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -305,6 +305,10 @@
   }
   out->SetValue(kVER, QuicVersionToQuicTag(preferred_version));
 
+  if (!user_agent_id_.empty()) {
+    out->SetStringPiece(kUAID, user_agent_id_);
+  }
+
   if (!cached->source_address_token().empty()) {
     out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
   }
diff --git a/net/quic/crypto/quic_crypto_client_config.h b/net/quic/crypto/quic_crypto_client_config.h
index 38575c8..a0b5c89 100644
--- a/net/quic/crypto/quic_crypto_client_config.h
+++ b/net/quic/crypto/quic_crypto_client_config.h
@@ -245,6 +245,11 @@
   // TODO(rch): remove this method when we drop support for Windows XP.
   void DisableEcdsa();
 
+  // Saves the |user_agent_id| that will be passed in QUIC's CHLO message.
+  void set_user_agent_id(const std::string& user_agent_id) {
+    user_agent_id_ = user_agent_id;
+  }
+
  private:
   typedef std::map<QuicServerId, CachedState*> CachedStateMap;
 
@@ -274,6 +279,9 @@
   // True if ECDSA should be disabled.
   bool disable_ecdsa_;
 
+  // The |user_agent_id_| passed in QUIC's CHLO message.
+  std::string user_agent_id_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientConfig);
 };
 
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc
index 260c0d4..52acd43 100644
--- a/net/quic/crypto/quic_crypto_server_config.cc
+++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -1278,7 +1278,11 @@
                                                      QuicRandom* rand,
                                                      QuicWallTime now) const {
   SourceAddressToken source_address_token;
-  source_address_token.set_ip(IPAddressToPackedString(ip.address()));
+  IPAddressNumber ip_address = ip.address();
+  if (ip.GetSockAddrFamily() == AF_INET) {
+    ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
+  }
+  source_address_token.set_ip(IPAddressToPackedString(ip_address));
   source_address_token.set_timestamp(now.ToUNIXSeconds());
 
   return config.source_address_token_boxer->Box(
@@ -1302,7 +1306,11 @@
     return false;
   }
 
-  if (source_address_token.ip() != IPAddressToPackedString(ip.address())) {
+  IPAddressNumber ip_address = ip.address();
+  if (ip.GetSockAddrFamily() == AF_INET) {
+    ip_address = ConvertIPv4NumberToIPv6Number(ip_address);
+  }
+  if (source_address_token.ip() != IPAddressToPackedString(ip_address)) {
     // It's for a different IP address.
     return false;
   }
diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc
index 8aeef00..069c523 100644
--- a/net/quic/crypto/quic_crypto_server_config_test.cc
+++ b/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -14,6 +14,7 @@
 #include "net/quic/crypto/strike_register_client.h"
 #include "net/quic/quic_time.h"
 #include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/test_tools/quic_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -261,17 +262,20 @@
   EXPECT_TRUE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary));
   EXPECT_FALSE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kOverride));
 
-  IPAddressNumber ip;
-  CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
-  IPEndPoint ip4 = IPEndPoint(ip, 1);
-  CHECK(ParseIPLiteralToNumber("2001:db8:0::42", &ip));
-  IPEndPoint ip6 = IPEndPoint(ip, 2);
+  IPEndPoint ip4 = IPEndPoint(Loopback4(), 1);
+  IPEndPoint ip4d = IPEndPoint(ConvertIPv4NumberToIPv6Number(ip4.address()), 1);
+  IPEndPoint ip6 = IPEndPoint(Loopback6(), 2);
 
   // Primary config generates configs that validate successfully.
   const string token4 = peer.NewSourceAddressToken(kPrimary, ip4, rand, now);
+  const string token4d = peer.NewSourceAddressToken(kPrimary, ip4d, rand, now);
   const string token6 = peer.NewSourceAddressToken(kPrimary, ip6, rand, now);
   EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
+  EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token4, ip4d, now));
   EXPECT_FALSE(peer.ValidateSourceAddressToken(kPrimary, token4, ip6, now));
+  EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token4d, ip4, now));
+  EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token4d, ip4d, now));
+  EXPECT_FALSE(peer.ValidateSourceAddressToken(kPrimary, token4d, ip6, now));
   EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token6, ip6, now));
 
   // Override config generates configs that validate successfully.
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 00b1411..a218dcd 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -28,6 +28,10 @@
 
 namespace {
 
+// The length of time to wait for a 0-RTT handshake to complete
+// before allowing the requests to possibly proceed over TCP.
+const int k0RttHandshakeTimeoutMs = 300;
+
 // Histograms for tracking down the crashes from http://crbug.com/354669
 // Note: these values must be kept in sync with the corresponding values in:
 // tools/metrics/histograms/histograms.xml
@@ -138,6 +142,7 @@
     const QuicConfig& config,
     uint32 max_flow_control_receive_window_bytes,
     QuicCryptoClientConfig* crypto_config,
+    base::TaskRunner* task_runner,
     NetLog* net_log)
     : QuicClientSessionBase(connection,
                             max_flow_control_receive_window_bytes,
@@ -150,6 +155,7 @@
       server_info_(server_info.Pass()),
       read_pending_(false),
       num_total_streams_(0),
+      task_runner_(task_runner),
       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)),
       logger_(net_log_),
       num_packets_read_(0),
@@ -436,16 +442,39 @@
     return ERR_CONNECTION_FAILED;
   }
 
-  bool can_notify = require_confirmation_ ?
-      IsCryptoHandshakeConfirmed() : IsEncryptionEstablished();
-  if (can_notify) {
+  if (IsCryptoHandshakeConfirmed())
     return OK;
+
+  // Unless we require handshake confirmation, activate the session if
+  // we have established initial encryption.
+  if (!require_confirmation_ && IsEncryptionEstablished()) {
+    // To mitigate the effects of hanging 0-RTT connections, set up a timer to
+    // cancel any requests, if the handshake takes too long.
+    task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&QuicClientSession::OnConnectTimeout,
+                   weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMilliseconds(k0RttHandshakeTimeoutMs));
+    return OK;
+
   }
 
   callback_ = callback;
   return ERR_IO_PENDING;
 }
 
+int QuicClientSession::ResumeCryptoConnect(const CompletionCallback& callback) {
+
+  if (IsCryptoHandshakeConfirmed())
+    return OK;
+
+  if (!connection()->connected())
+    return ERR_QUIC_HANDSHAKE_FAILED;
+
+  callback_ = callback;
+  return ERR_IO_PENDING;
+}
+
 int QuicClientSession::GetNumSentClientHellos() const {
   return crypto_stream_->num_sent_client_hellos();
 }
@@ -800,4 +829,16 @@
     stream_factory_->OnSessionClosed(this);
 }
 
+void QuicClientSession::OnConnectTimeout() {
+  DCHECK(callback_.is_null());
+  DCHECK(IsEncryptionEstablished());
+
+  if (IsCryptoHandshakeConfirmed())
+    return;
+
+  if (stream_factory_)
+    stream_factory_->OnSessionConnectTimeout(this);
+  CloseAllStreams(ERR_QUIC_HANDSHAKE_FAILED);
+}
+
 }  // namespace net
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
index ca4d7b8..f12003e 100644
--- a/net/quic/quic_client_session.h
+++ b/net/quic/quic_client_session.h
@@ -99,6 +99,7 @@
                     const QuicConfig& config,
                     uint32 max_flow_control_receive_window_bytes,
                     QuicCryptoClientConfig* crypto_config,
+                    base::TaskRunner* task_runner,
                     NetLog* net_log);
 
   virtual ~QuicClientSession();
@@ -150,6 +151,9 @@
   int CryptoConnect(bool require_confirmation,
                     const CompletionCallback& callback);
 
+  // Resumes a crypto handshake with the server after a timeout.
+  int ResumeCryptoConnect(const CompletionCallback& callback);
+
   // Causes the QuicConnectionHelper to start reading from the socket
   // and passing the data along to the QuicConnection.
   void StartReading();
@@ -214,6 +218,8 @@
   // delete |this|.
   void NotifyFactoryOfSessionClosed();
 
+  void OnConnectTimeout();
+
   bool require_confirmation_;
   scoped_ptr<QuicCryptoClientStream> crypto_stream_;
   QuicStreamFactory* stream_factory_;
@@ -227,6 +233,7 @@
   bool read_pending_;
   CompletionCallback callback_;
   size_t num_total_streams_;
+  base::TaskRunner* task_runner_;
   BoundNetLog net_log_;
   QuicConnectionLogger logger_;
   // Number of packets read in the current read loop.
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index 2ca8bc9..8706d7c 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -73,7 +73,9 @@
                  QuicServerId(kServerHostname, kServerPort, false,
                               PRIVACY_MODE_DISABLED),
                  DefaultQuicConfig(), kInitialFlowControlWindowForTest,
-                 &crypto_config_, &net_log_) {
+                 &crypto_config_,
+                 base::MessageLoop::current()->message_loop_proxy().get(),
+                 &net_log_) {
     session_.config()->SetDefaults();
     crypto_config_.SetDefaults();
   }
diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc
index 9c60671..b9703c4 100644
--- a/net/quic/quic_config.cc
+++ b/net/quic/quic_config.cc
@@ -129,8 +129,7 @@
 
 void QuicNegotiableTag::set(const QuicTagVector& possible,
                             QuicTag default_value) {
-  DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
-            possible.end());
+  DCHECK(ContainsQuicTag(possible, default_value));
   possible_values_ = possible;
   default_value_ = default_value;
 }
@@ -194,8 +193,7 @@
 
   if (hello_type == SERVER) {
     if (received_tags_length != 1 ||
-        std::find(possible_values_.begin(), possible_values_.end(),
-                  *received_tags) == possible_values_.end()) {
+        !ContainsQuicTag(possible_values_,  *received_tags)) {
       *error_details = "Invalid " + QuicUtils::TagToString(tag_);
       return QUIC_INVALID_NEGOTIATED_VALUE;
     }
@@ -268,11 +266,10 @@
   QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
   switch (error) {
     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
-      if (presence_ == PRESENCE_REQUIRED) {
-        *error_details = "Missing " + QuicUtils::TagToString(tag_);
-        break;
+      if (presence_ == PRESENCE_OPTIONAL) {
+        return QUIC_NO_ERROR;
       }
-      error = QUIC_NO_ERROR;
+      *error_details = "Missing " + QuicUtils::TagToString(tag_);
       break;
     case QUIC_NO_ERROR:
       has_receive_value_ = true;
@@ -329,18 +326,17 @@
 }
 
 QuicErrorCode QuicFixedTag::ProcessPeerHello(
-    const CryptoHandshakeMessage& client_hello,
+    const CryptoHandshakeMessage& peer_hello,
     HelloType hello_type,
     string* error_details) {
   DCHECK(error_details != NULL);
-  QuicErrorCode error = client_hello.GetUint32(tag_, &receive_value_);
+  QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
   switch (error) {
     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
-      if (presence_ == PRESENCE_REQUIRED) {
-        *error_details = "Missing " + QuicUtils::TagToString(tag_);
-        break;
+      if (presence_ == PRESENCE_OPTIONAL) {
+        return QUIC_NO_ERROR;
       }
-      error = QUIC_NO_ERROR;
+      *error_details = "Missing " + QuicUtils::TagToString(tag_);
       break;
     case QUIC_NO_ERROR:
       has_receive_value_ = true;
@@ -352,8 +348,82 @@
   return error;
 }
 
+QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
+                                       QuicConfigPresence presence)
+    : QuicConfigValue(name, presence),
+      has_send_values_(false),
+      has_receive_values_(false) {
+}
+
+QuicFixedTagVector::~QuicFixedTagVector() {}
+
+bool QuicFixedTagVector::HasSendValues() const {
+  return has_send_values_;
+}
+
+QuicTagVector QuicFixedTagVector::GetSendValues() const {
+  LOG_IF(DFATAL, !has_send_values_) << "No send values to get for tag:" << tag_;
+  return send_values_;
+}
+
+void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
+  has_send_values_ = true;
+  send_values_ = values;
+}
+
+bool QuicFixedTagVector::HasReceivedValues() const {
+  return has_receive_values_;
+}
+
+QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
+  LOG_IF(DFATAL, !has_receive_values_)
+      << "No receive value to get for tag:" << tag_;
+  return receive_values_;
+}
+
+void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
+  has_receive_values_ = true;
+  receive_values_ = values;
+}
+
+void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
+  if (has_send_values_) {
+    out->SetVector(tag_, send_values_);
+  }
+}
+
+QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
+    const CryptoHandshakeMessage& peer_hello,
+    HelloType hello_type,
+    string* error_details) {
+  DCHECK(error_details != NULL);
+  const QuicTag* received_tags;
+  size_t received_tags_length;
+  QuicErrorCode error =
+      peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
+  switch (error) {
+    case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
+      if (presence_ == PRESENCE_OPTIONAL) {
+        return QUIC_NO_ERROR;
+      }
+      *error_details = "Missing " + QuicUtils::TagToString(tag_);
+      break;
+    case QUIC_NO_ERROR:
+      has_receive_values_ = true;
+      for (size_t i = 0; i < received_tags_length; ++i) {
+        receive_values_.push_back(received_tags[i]);
+      }
+      break;
+    default:
+      *error_details = "Bad " + QuicUtils::TagToString(tag_);
+      break;
+  }
+  return error;
+}
+
 QuicConfig::QuicConfig()
-    : congestion_control_(kCGST, PRESENCE_REQUIRED),
+    : congestion_feedback_(kCGST, PRESENCE_REQUIRED),
+      congestion_options_(kCOPT, PRESENCE_OPTIONAL),
       loss_detection_(kLOSS, PRESENCE_OPTIONAL),
       idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
       keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL),
@@ -368,14 +438,27 @@
 
 QuicConfig::~QuicConfig() {}
 
-void QuicConfig::set_congestion_control(
-    const QuicTagVector& congestion_control,
-    QuicTag default_congestion_control) {
-  congestion_control_.set(congestion_control, default_congestion_control);
+void QuicConfig::set_congestion_feedback(
+    const QuicTagVector& congestion_feedback,
+    QuicTag default_congestion_feedback) {
+  congestion_feedback_.set(congestion_feedback, default_congestion_feedback);
 }
 
-QuicTag QuicConfig::congestion_control() const {
-  return congestion_control_.GetTag();
+QuicTag QuicConfig::congestion_feedback() const {
+  return congestion_feedback_.GetTag();
+}
+
+void QuicConfig::SetCongestionOptionsToSend(
+    const QuicTagVector& congestion_options) {
+  congestion_options_.SetSendValues(congestion_options);
+}
+
+bool QuicConfig::HasReceivedCongestionOptions() const {
+  return congestion_options_.HasReceivedValues();
+}
+
+QuicTagVector QuicConfig::ReceivedCongestionOptions() const {
+  return congestion_options_.GetReceivedValues();
 }
 
 void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
@@ -466,19 +549,19 @@
   // TODO(ianswett): Add the negotiated parameters once and iterate over all
   // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
   // ProcessServerHello.
-  return congestion_control_.negotiated() &&
+  return congestion_feedback_.negotiated() &&
       idle_connection_state_lifetime_seconds_.negotiated() &&
       keepalive_timeout_seconds_.negotiated() &&
       max_streams_per_connection_.negotiated();
 }
 
 void QuicConfig::SetDefaults() {
-  QuicTagVector congestion_control;
+  QuicTagVector congestion_feedback;
   if (FLAGS_enable_quic_pacing) {
-    congestion_control.push_back(kPACE);
+    congestion_feedback.push_back(kPACE);
   }
-  congestion_control.push_back(kQBIC);
-  congestion_control_.set(congestion_control, kQBIC);
+  congestion_feedback.push_back(kQBIC);
+  congestion_feedback_.set(congestion_feedback, kQBIC);
   idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
                                               kDefaultInitialTimeoutSecs);
   // kKATO is optional. Return 0 if not negotiated.
@@ -490,16 +573,16 @@
 }
 
 void QuicConfig::EnablePacing(bool enable_pacing) {
-  QuicTagVector congestion_control;
+  QuicTagVector congestion_feedback;
   if (enable_pacing) {
-    congestion_control.push_back(kPACE);
+    congestion_feedback.push_back(kPACE);
   }
-  congestion_control.push_back(kQBIC);
-  congestion_control_.set(congestion_control, kQBIC);
+  congestion_feedback.push_back(kQBIC);
+  congestion_feedback_.set(congestion_feedback, kQBIC);
 }
 
 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
-  congestion_control_.ToHandshakeMessage(out);
+  congestion_feedback_.ToHandshakeMessage(out);
   idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
   keepalive_timeout_seconds_.ToHandshakeMessage(out);
   max_streams_per_connection_.ToHandshakeMessage(out);
@@ -507,6 +590,7 @@
   initial_round_trip_time_us_.ToHandshakeMessage(out);
   loss_detection_.ToHandshakeMessage(out);
   initial_flow_control_window_bytes_.ToHandshakeMessage(out);
+  congestion_options_.ToHandshakeMessage(out);
 }
 
 QuicErrorCode QuicConfig::ProcessPeerHello(
@@ -517,7 +601,7 @@
 
   QuicErrorCode error = QUIC_NO_ERROR;
   if (error == QUIC_NO_ERROR) {
-    error = congestion_control_.ProcessPeerHello(
+    error = congestion_feedback_.ProcessPeerHello(
         peer_hello,  hello_type, error_details);
   }
   if (error == QUIC_NO_ERROR) {
@@ -548,6 +632,10 @@
     error = loss_detection_.ProcessPeerHello(
         peer_hello, hello_type, error_details);
   }
+  if (error == QUIC_NO_ERROR) {
+    error = congestion_options_.ProcessPeerHello(
+        peer_hello, hello_type, error_details);
+  }
   return error;
 }
 
diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h
index 88ad8b6..4d65097 100644
--- a/net/quic/quic_config.h
+++ b/net/quic/quic_config.h
@@ -215,6 +215,42 @@
   bool has_receive_value_;
 };
 
+// Stores tag from CHLO or SHLO messages that are not negotiated.
+class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
+ public:
+  QuicFixedTagVector(QuicTag name, QuicConfigPresence presence);
+  virtual ~QuicFixedTagVector();
+
+  bool HasSendValues() const;
+
+  QuicTagVector GetSendValues() const;
+
+  void SetSendValues(const QuicTagVector& values);
+
+  bool HasReceivedValues() const;
+
+  QuicTagVector GetReceivedValues() const;
+
+  void SetReceivedValues(const QuicTagVector& values);
+
+  // If has_send_value is true, serialises |tag_vector_| and |send_value_| to
+  // |out|.
+  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
+
+  // Sets |receive_values_| to the corresponding value from |client_hello_| if
+  // it exists.
+  virtual QuicErrorCode ProcessPeerHello(
+      const CryptoHandshakeMessage& peer_hello,
+      HelloType hello_type,
+      std::string* error_details) OVERRIDE;
+
+ private:
+  QuicTagVector send_values_;
+  bool has_send_values_;
+  QuicTagVector receive_values_;
+  bool has_receive_values_;
+};
+
 // QuicConfig contains non-crypto configuration options that are negotiated in
 // the crypto handshake.
 class NET_EXPORT_PRIVATE QuicConfig {
@@ -222,10 +258,16 @@
   QuicConfig();
   ~QuicConfig();
 
-  void set_congestion_control(const QuicTagVector& congestion_control,
-                              QuicTag default_congestion_control);
+  void set_congestion_feedback(const QuicTagVector& congestion_feedback,
+                               QuicTag default_congestion_feedback);
 
-  QuicTag congestion_control() const;
+  QuicTag congestion_feedback() const;
+
+  void SetCongestionOptionsToSend(const QuicTagVector& congestion_options);
+
+  bool HasReceivedCongestionOptions() const;
+
+  QuicTagVector ReceivedCongestionOptions() const;
 
   void SetLossDetectionToSend(QuicTag loss_detection);
 
@@ -294,7 +336,9 @@
   friend class test::QuicConfigPeer;
 
   // Congestion control feedback type.
-  QuicNegotiableTag congestion_control_;
+  QuicNegotiableTag congestion_feedback_;
+  // Congestion control option.
+  QuicFixedTagVector congestion_options_;
   // Loss detection feedback type.
   QuicFixedTag loss_detection_;
   // Idle connection state lifetime
diff --git a/net/quic/quic_config_test.cc b/net/quic/quic_config_test.cc
index 9ca449d..63299e5 100644
--- a/net/quic/quic_config_test.cc
+++ b/net/quic/quic_config_test.cc
@@ -69,12 +69,12 @@
   EXPECT_EQ(kQBIC, out[1]);
 }
 
-TEST_F(QuicConfigTest, ProcessPeerHello) {
+TEST_F(QuicConfigTest, ProcessClientHello) {
   QuicConfig client_config;
   QuicTagVector cgst;
   cgst.push_back(kINAR);
   cgst.push_back(kQBIC);
-  client_config.set_congestion_control(cgst, kQBIC);
+  client_config.set_congestion_feedback(cgst, kQBIC);
   client_config.set_idle_connection_state_lifetime(
       QuicTime::Delta::FromSeconds(2 * kDefaultTimeoutSecs),
       QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs));
@@ -82,6 +82,9 @@
       2 * kDefaultMaxStreamsPerConnection, kDefaultMaxStreamsPerConnection);
   client_config.SetInitialRoundTripTimeUsToSend(
       10 * base::Time::kMicrosecondsPerMillisecond);
+  QuicTagVector copt;
+  copt.push_back(kTBBR);
+  client_config.SetCongestionOptionsToSend(copt);
   CryptoHandshakeMessage msg;
   client_config.ToHandshakeMessage(&msg);
   string error_details;
@@ -89,7 +92,7 @@
       config_.ProcessPeerHello(msg, CLIENT, &error_details);
   EXPECT_EQ(QUIC_NO_ERROR, error);
   EXPECT_TRUE(config_.negotiated());
-  EXPECT_EQ(kQBIC, config_.congestion_control());
+  EXPECT_EQ(kQBIC, config_.congestion_feedback());
   EXPECT_EQ(QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs),
             config_.idle_connection_state_lifetime());
   EXPECT_EQ(kDefaultMaxStreamsPerConnection,
@@ -98,13 +101,16 @@
   EXPECT_EQ(10 * base::Time::kMicrosecondsPerMillisecond,
             config_.ReceivedInitialRoundTripTimeUs());
   EXPECT_FALSE(config_.HasReceivedLossDetection());
+  EXPECT_TRUE(config_.HasReceivedCongestionOptions());
+  EXPECT_EQ(1u, config_.ReceivedCongestionOptions().size());
+  EXPECT_EQ(config_.ReceivedCongestionOptions()[0], kTBBR);
 }
 
 TEST_F(QuicConfigTest, ProcessServerHello) {
   QuicConfig server_config;
   QuicTagVector cgst;
   cgst.push_back(kQBIC);
-  server_config.set_congestion_control(cgst, kQBIC);
+  server_config.set_congestion_feedback(cgst, kQBIC);
   server_config.set_idle_connection_state_lifetime(
       QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs / 2),
       QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs / 2));
@@ -121,7 +127,7 @@
       config_.ProcessPeerHello(msg, SERVER, &error_details);
   EXPECT_EQ(QUIC_NO_ERROR, error);
   EXPECT_TRUE(config_.negotiated());
-  EXPECT_EQ(kQBIC, config_.congestion_control());
+  EXPECT_EQ(kQBIC, config_.congestion_feedback());
   EXPECT_EQ(QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs / 2),
             config_.idle_connection_state_lifetime());
   EXPECT_EQ(kDefaultMaxStreamsPerConnection / 2,
@@ -211,7 +217,7 @@
   QuicTagVector cgst;
   cgst.push_back(kQBIC);
   cgst.push_back(kINAR);
-  server_config.set_congestion_control(cgst, kQBIC);
+  server_config.set_congestion_feedback(cgst, kQBIC);
 
   CryptoHandshakeMessage msg;
   server_config.ToHandshakeMessage(&msg);
@@ -226,7 +232,7 @@
   server_config.SetDefaults();
   QuicTagVector cgst;
   cgst.push_back(kINAR);
-  server_config.set_congestion_control(cgst, kINAR);
+  server_config.set_congestion_feedback(cgst, kINAR);
 
   CryptoHandshakeMessage msg;
   string error_details;
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 8162c3c..2f8c845 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -949,15 +949,8 @@
 
   // Now that 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 = sent_packet_manager_.TimeUntilSend(
-      time_of_last_received_packet_, NOT_RETRANSMISSION,
-      HAS_RETRANSMITTABLE_DATA);
-  if (delay.IsZero()) {
-    send_alarm_->Cancel();
-    WriteIfNotBlocked();
-  } else if (!delay.IsInfinite()) {
-    send_alarm_->Cancel();
-    send_alarm_->Set(time_of_last_received_packet_.Add(delay));
+  if (CanWrite(HAS_RETRANSMITTABLE_DATA)) {
+    OnCanWrite();
   }
 }
 
@@ -1066,7 +1059,7 @@
   stats_.estimated_bandwidth =
       sent_packet_manager_.BandwidthEstimate().ToBytesPerSecond();
   stats_.congestion_window = sent_packet_manager_.GetCongestionWindow();
-  stats_.max_packet_size = options()->max_packet_length;
+  stats_.max_packet_size = packet_creator_.max_packet_length();
   return stats_;
 }
 
@@ -1145,7 +1138,7 @@
   // 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)) {
+  if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
     return;
   }
 
@@ -1159,7 +1152,7 @@
   // blocked or the congestion manager to prohibit sending, so check again.
   if (visitor_->WillingAndAbleToWrite() &&
       !resume_writes_alarm_->IsSet() &&
-      CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA)) {
+      CanWrite(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.
@@ -1196,8 +1189,8 @@
            << time_of_last_received_packet_.ToDebuggingValue();
 
   if (is_server_ && encryption_level_ == ENCRYPTION_NONE &&
-      last_size_ > options()->max_packet_length) {
-    options()->max_packet_length = last_size_;
+      last_size_ > packet_creator_.max_packet_length()) {
+    packet_creator_.set_max_packet_length(last_size_);
   }
   return true;
 }
@@ -1230,7 +1223,7 @@
     const QuicSentPacketManager::PendingRetransmission pending =
         sent_packet_manager_.NextPendingRetransmission();
     if (GetPacketType(&pending.retransmittable_frames) == NORMAL &&
-        !CanWrite(pending.transmission_type, HAS_RETRANSMITTABLE_DATA)) {
+        !CanWrite(HAS_RETRANSMITTABLE_DATA)) {
       break;
     }
 
@@ -1253,7 +1246,8 @@
           pending.sequence_number, serialized_packet.sequence_number);
     }
     sent_packet_manager_.OnRetransmittedPacket(
-        pending.sequence_number, serialized_packet.sequence_number);
+        pending.sequence_number,
+        serialized_packet.sequence_number);
 
     SendOrQueuePacket(pending.retransmittable_frames.encryption_level(),
                       serialized_packet,
@@ -1288,35 +1282,25 @@
     return true;
   }
 
-  return CanWrite(transmission_type, retransmittable);
+  return CanWrite(retransmittable);
 }
 
-bool QuicConnection::CanWrite(TransmissionType transmission_type,
-                              HasRetransmittableData retransmittable) {
+bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
   if (writer_->IsWriteBlocked()) {
     visitor_->OnWriteBlocked();
     return false;
   }
 
-  // TODO(rch): consider removing this check so that if an ACK comes in
-  // before the alarm goes it, we might be able send out a packet.
-  // This check assumes that if the send alarm is set, it applies equally to all
-  // types of transmissions.
-  if (send_alarm_->IsSet()) {
-    DVLOG(1) << "Send alarm set.  Not sending.";
-    return false;
-  }
-
+  send_alarm_->Cancel();
   QuicTime now = clock_->Now();
   QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(
-      now, transmission_type, retransmittable);
+      now, retransmittable);
   if (delay.IsInfinite()) {
     return false;
   }
 
   // If the scheduler requires a delay, then we can not send this packet now.
   if (!delay.IsZero()) {
-    send_alarm_->Cancel();
     send_alarm_->Set(now.Add(delay));
     DVLOG(1) << "Delaying sending.";
     return false;
@@ -1339,8 +1323,7 @@
   // This ensures packets are sent in sequence number order.
   // 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)) {
+  if (packet.type == NORMAL && !CanWrite(packet.retransmittable)) {
     return false;
   }
 
@@ -1375,9 +1358,10 @@
     encrypted_deleter.reset(encrypted);
   }
 
-  LOG_IF(DFATAL, encrypted->length() > options()->max_packet_length)
+  LOG_IF(DFATAL, encrypted->length() >
+                 packet_creator_.max_packet_length())
       << "Writing an encrypted packet larger than max_packet_length:"
-      << options()->max_packet_length << " encrypted length: "
+      << packet_creator_.max_packet_length() << " encrypted length: "
       << encrypted->length();
   DVLOG(1) << ENDPOINT << "Sending packet " << sequence_number
            << " : " << (packet.packet->is_fec_packet() ? "FEC " :
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 2f91bb4..9e93715 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -40,6 +40,7 @@
 #include "net/quic/quic_received_packet_manager.h"
 #include "net/quic/quic_sent_entropy_manager.h"
 #include "net/quic/quic_sent_packet_manager.h"
+#include "net/quic/quic_types.h"
 
 namespace net {
 
@@ -111,10 +112,11 @@
 // Interface which gets callbacks from the QuicConnection at interesting
 // points.  Implementations must not mutate the state of the connection
 // as a result of these callbacks.
-class NET_EXPORT_PRIVATE QuicConnectionDebugVisitorInterface
-    : public QuicPacketGenerator::DebugDelegateInterface {
+class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor
+    : public QuicPacketGenerator::DebugDelegate,
+      public QuicSentPacketManager::DebugDelegate {
  public:
-  virtual ~QuicConnectionDebugVisitorInterface() {}
+  virtual ~QuicConnectionDebugVisitor() {}
 
   // Called when a packet has been sent.
   virtual void OnPacketSent(QuicPacketSequenceNumber sequence_number,
@@ -344,17 +346,22 @@
   void set_visitor(QuicConnectionVisitorInterface* visitor) {
     visitor_ = visitor;
   }
-  void set_debug_visitor(QuicConnectionDebugVisitorInterface* debug_visitor) {
+  void set_debug_visitor(QuicConnectionDebugVisitor* debug_visitor) {
     debug_visitor_ = debug_visitor;
     packet_generator_.set_debug_delegate(debug_visitor);
+    sent_packet_manager_.set_debug_delegate(debug_visitor);
   }
   const IPEndPoint& self_address() const { return self_address_; }
   const IPEndPoint& peer_address() const { return peer_address_; }
   QuicConnectionId connection_id() const { return connection_id_; }
   const QuicClock* clock() const { return clock_; }
   QuicRandom* random_generator() const { return random_generator_; }
-
-  QuicPacketCreator::Options* options() { return packet_creator_.options(); }
+  size_t max_packet_length() const {
+    return packet_creator_.max_packet_length();
+  }
+  void set_max_packet_length(size_t length) {
+    return packet_creator_.set_max_packet_length(length);
+  }
 
   bool connected() const { return connected_; }
 
@@ -455,8 +462,7 @@
     return sent_packet_manager_;
   }
 
-  bool CanWrite(TransmissionType transmission_type,
-                HasRetransmittableData retransmittable);
+  bool CanWrite(HasRetransmittableData retransmittable);
 
   // Stores current batch state for connection, puts the connection
   // into batch mode, and destruction restores the stored batch state.
@@ -695,7 +701,7 @@
   scoped_ptr<QuicAlarm> ping_alarm_;
 
   QuicConnectionVisitorInterface* visitor_;
-  QuicConnectionDebugVisitorInterface* debug_visitor_;
+  QuicConnectionDebugVisitor* debug_visitor_;
   QuicPacketCreator packet_creator_;
   QuicPacketGenerator packet_generator_;
 
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h
index 8baa1b8..c50cb9e 100644
--- a/net/quic/quic_connection_logger.h
+++ b/net/quic/quic_connection_logger.h
@@ -20,7 +20,7 @@
 // This class is a debug visitor of a QuicConnection which logs
 // events to |net_log|.
 class NET_EXPORT_PRIVATE QuicConnectionLogger
-    : public QuicConnectionDebugVisitorInterface {
+    : public QuicConnectionDebugVisitor {
  public:
   explicit QuicConnectionLogger(const BoundNetLog& net_log);
 
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 603680f..6707c4a 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -556,7 +556,7 @@
 
 // Used for testing packets revived from FEC packets.
 class FecQuicConnectionDebugVisitor
-    : public QuicConnectionDebugVisitorInterface {
+    : public QuicConnectionDebugVisitor {
  public:
   virtual void OnRevivedPacket(const QuicPacketHeader& header,
                                StringPiece data) OVERRIDE {
@@ -577,7 +577,7 @@
   QuicConnectionTest()
       : connection_id_(42),
         framer_(SupportedVersions(version()), QuicTime::Zero(), false),
-        creator_(connection_id_, &framer_, &random_generator_, false),
+        peer_creator_(connection_id_, &framer_, &random_generator_, false),
         send_algorithm_(new StrictMock<MockSendAlgorithm>),
         loss_algorithm_(new MockLossAlgorithm()),
         helper_(new TestConnectionHelper(&clock_, &random_generator_)),
@@ -652,9 +652,10 @@
   QuicPacketEntropyHash ProcessFramePacket(QuicFrame frame) {
     QuicFrames frames;
     frames.push_back(QuicFrame(frame));
-    QuicPacketCreatorPeer::SetSendVersionInPacket(&creator_,
+    QuicPacketCreatorPeer::SetSendVersionInPacket(&peer_creator_,
                                                   connection_.is_server());
-    SerializedPacket serialized_packet = creator_.SerializeAllFrames(frames);
+    SerializedPacket serialized_packet =
+        peer_creator_.SerializeAllFrames(frames);
     scoped_ptr<QuicPacket> packet(serialized_packet.packet);
     scoped_ptr<QuicEncryptedPacket> encrypted(
         framer_.EncryptPacket(ENCRYPTION_NONE,
@@ -816,7 +817,7 @@
     QuicFrame frame(&frame1_);
     frames.push_back(frame);
     QuicPacket* packet =
-        framer_.BuildUnsizedDataPacket(header_, frames).packet;
+        BuildUnsizedDataPacket(&framer_, header_, frames).packet;
     EXPECT_TRUE(packet != NULL);
     return packet;
   }
@@ -839,7 +840,7 @@
     QuicFrame frame(&qccf);
     frames.push_back(frame);
     QuicPacket* packet =
-        framer_.BuildUnsizedDataPacket(header_, frames).packet;
+        BuildUnsizedDataPacket(&framer_, header_, frames).packet;
     EXPECT_TRUE(packet != NULL);
     return packet;
   }
@@ -913,9 +914,21 @@
     EXPECT_CALL(visitor_, OnWriteBlocked()).Times(AtLeast(1));
   }
 
+  void CongestionBlockWrites() {
+    EXPECT_CALL(*send_algorithm_,
+                TimeUntilSend(_, _, _)).WillRepeatedly(
+                    testing::Return(QuicTime::Delta::FromSeconds(1)));
+  }
+
+  void CongestionUnblockWrites() {
+    EXPECT_CALL(*send_algorithm_,
+                TimeUntilSend(_, _, _)).WillRepeatedly(
+                    testing::Return(QuicTime::Delta::Zero()));
+  }
+
   QuicConnectionId connection_id_;
   QuicFramer framer_;
-  QuicPacketCreator creator_;
+  QuicPacketCreator peer_creator_;
   MockEntropyCalculator entropy_calculator_;
 
   MockSendAlgorithm* send_algorithm_;
@@ -1016,7 +1029,7 @@
   // packet the peer will not retransmit.  It indicates this by sending 'least
   // 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);
+  peer_creator_.set_sequence_number(5);
   QuicAckFrame frame = InitAckFrame(1, 4);
   EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _));
   ProcessAckPacket(&frame);
@@ -1109,7 +1122,7 @@
               TimeUntilSend(_, _, _)).WillRepeatedly(
                   testing::Return(QuicTime::Delta::Zero()));
   // Skip a packet and then record an ack.
-  creator_.set_sequence_number(2);
+  peer_creator_.set_sequence_number(2);
   QuicAckFrame frame = InitAckFrame(0, 3);
   ProcessAckPacket(&frame);
 }
@@ -1205,7 +1218,7 @@
   SendStreamDataToPeer(1, "eep", 6, !kFin, NULL);
 
   // Start out saying the least unacked is 2.
-  creator_.set_sequence_number(5);
+  peer_creator_.set_sequence_number(5);
   if (version() > QUIC_VERSION_15) {
     QuicStopWaitingFrame frame = InitStopWaitingFrame(2);
     ProcessStopWaitingPacket(&frame);
@@ -1216,7 +1229,7 @@
 
   // Change it to 1, but lower the sequence number to fake out-of-order packets.
   // This should be fine.
-  creator_.set_sequence_number(1);
+  peer_creator_.set_sequence_number(1);
   // The scheduler will not process out of order acks, but all packet processing
   // causes the connection to try to write.
   EXPECT_CALL(visitor_, OnCanWrite());
@@ -1231,7 +1244,7 @@
   // Now claim it's one, but set the ordering so it was sent "after" the first
   // one.  This should cause a connection error.
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
-  creator_.set_sequence_number(7);
+  peer_creator_.set_sequence_number(7);
   if (version() > QUIC_VERSION_15) {
     EXPECT_CALL(visitor_,
                 OnConnectionClosed(QUIC_INVALID_STOP_WAITING_DATA, false));
@@ -1277,17 +1290,19 @@
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   ProcessPacket(1);
 
-  creator_.set_sequence_number(1);
+  peer_creator_.set_sequence_number(1);
   QuicAckFrame frame1 = InitAckFrame(0, 1);
   ProcessAckPacket(&frame1);
 }
 
 TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
   QuicPacketSequenceNumber last_packet;
+  QuicPacketCreator* creator =
+      QuicConnectionPeer::GetPacketCreator(&connection_);
   SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet);
   EXPECT_EQ(1u, last_packet);
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
@@ -1297,7 +1312,7 @@
   SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet);
   EXPECT_EQ(2u, last_packet);
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   // The 1 packet lag is due to the sequence number length being recalculated in
   // QuicConnection after a packet is sent.
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
@@ -1309,7 +1324,7 @@
   SendStreamDataToPeer(1, "foo", 6, !kFin, &last_packet);
   EXPECT_EQ(3u, last_packet);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
@@ -1319,7 +1334,7 @@
   SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet);
   EXPECT_EQ(4u, last_packet);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
@@ -1329,52 +1344,51 @@
   SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet);
   EXPECT_EQ(5u, last_packet);
   EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 }
 
 TEST_P(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
   QuicPacketSequenceNumber last_packet;
+  QuicPacketCreator* creator =
+      QuicConnectionPeer::GetPacketCreator(&connection_);
   SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet);
   EXPECT_EQ(1u, last_packet);
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
-  QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(100);
+  creator->set_sequence_number(100);
 
   SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet);
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
-  QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
-      100 * 256);
+  creator->set_sequence_number(100 * 256);
 
   SendStreamDataToPeer(1, "foo", 6, !kFin, &last_packet);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
-  QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
-      100 * 256 * 256);
+  creator->set_sequence_number(100 * 256 * 256);
 
   SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 
-  QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
-      100 * 256 * 256 * 256);
+  creator->set_sequence_number(100 * 256 * 256 * 256);
 
   SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet);
   EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
-            connection_.options()->send_sequence_number_length);
+            creator->next_sequence_number_length());
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
             writer_->header().public_header.sequence_number_length);
 }
@@ -1432,18 +1446,21 @@
 
 TEST_P(QuicConnectionTest, FECSending) {
   // All packets carry version info till version is negotiated.
+  QuicPacketCreator* creator =
+      QuicConnectionPeer::GetPacketCreator(&connection_);
   size_t payload_length;
   // GetPacketLengthForOneStream() assumes a stream offset of 0 in determining
   // packet length. The size of the offset field in a stream frame is 0 for
-  // offset 0, and 2 for non-zero offsets up through 16K. Increase
+  // offset 0, and 2 for non-zero offsets up through 64K. Increase
   // max_packet_length by 2 so that subsequent packets containing subsequent
   // stream frames with non-zero offets will fit within the packet length.
-  connection_.options()->max_packet_length = 2 + GetPacketLengthForOneStream(
+  size_t length = 2 + GetPacketLengthForOneStream(
           connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
           IN_FEC_GROUP, &payload_length);
+  creator->set_max_packet_length(length);
+
   // And send FEC every two packets.
-  EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(
-      QuicConnectionPeer::GetPacketCreator(&connection_), 2));
+  EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(creator, 2));
 
   // Send 4 data packets and 2 FEC packets.
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
@@ -1451,25 +1468,28 @@
   const string payload(payload_length * 4 + 2, 'a');
   connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
   // Expect the FEC group to be closed after SendStreamDataWithString.
-  EXPECT_FALSE(creator_.ShouldSendFec(true));
+  EXPECT_FALSE(creator->ShouldSendFec(true));
+  EXPECT_TRUE(creator->IsFecProtected());
 }
 
 TEST_P(QuicConnectionTest, FECQueueing) {
   // All packets carry version info till version is negotiated.
   size_t payload_length;
-  connection_.options()->max_packet_length =
-      GetPacketLengthForOneStream(
-          connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
-          IN_FEC_GROUP, &payload_length);
+  QuicPacketCreator* creator =
+      QuicConnectionPeer::GetPacketCreator(&connection_);
+  size_t length = GetPacketLengthForOneStream(
+      connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
+      IN_FEC_GROUP, &payload_length);
+  creator->set_max_packet_length(length);
   // And send FEC every two packets.
-  EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(
-      QuicConnectionPeer::GetPacketCreator(&connection_), 2));
+  EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(creator, 2));
 
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   BlockOnNextWrite();
   const string payload(payload_length, 'a');
   connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
-  EXPECT_FALSE(creator_.ShouldSendFec(true));
+  EXPECT_FALSE(creator->ShouldSendFec(true));
+  EXPECT_TRUE(creator->IsFecProtected());
   // Expect the first data packet and the fec packet to be queued.
   EXPECT_EQ(2u, connection_.NumQueuedPackets());
 }
@@ -1560,9 +1580,7 @@
 }
 
 TEST_P(QuicConnectionTest, FramePacking) {
-  // Block the connection.
-  connection_.GetSendAlarm()->Set(
-      clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+  CongestionBlockWrites();
 
   // Send an ack and two stream frames in 1 packet by queueing them.
   connection_.SendAck();
@@ -1573,7 +1591,7 @@
                                      &TestConnection::SendStreamData5))));
 
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
-  // Unblock the connection.
+  CongestionUnblockWrites();
   connection_.GetSendAlarm()->Fire();
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   EXPECT_FALSE(connection_.HasQueuedData());
@@ -1587,15 +1605,13 @@
     EXPECT_EQ(3u, writer_->frame_count());
   }
   EXPECT_FALSE(writer_->ack_frames().empty());
-  EXPECT_EQ(2u, writer_->stream_frames().size());
+  ASSERT_EQ(2u, writer_->stream_frames().size());
   EXPECT_EQ(kClientDataStreamId1, writer_->stream_frames()[0].stream_id);
   EXPECT_EQ(kClientDataStreamId2, writer_->stream_frames()[1].stream_id);
 }
 
 TEST_P(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
-  // Block the connection.
-  connection_.GetSendAlarm()->Set(
-      clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+  CongestionBlockWrites();
 
   // Send an ack and two stream frames (one non-crypto, then one crypto) in 2
   // packets by queueing them.
@@ -1607,21 +1623,19 @@
                                      &TestConnection::SendCryptoStreamData))));
 
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
-  // Unblock the connection.
+  CongestionUnblockWrites();
   connection_.GetSendAlarm()->Fire();
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   EXPECT_FALSE(connection_.HasQueuedData());
 
   // Parse the last packet and ensure it's the crypto stream frame.
   EXPECT_EQ(1u, writer_->frame_count());
-  EXPECT_EQ(1u, writer_->stream_frames().size());
+  ASSERT_EQ(1u, writer_->stream_frames().size());
   EXPECT_EQ(kCryptoStreamId, writer_->stream_frames()[0].stream_id);
 }
 
 TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
-  // Block the connection.
-  connection_.GetSendAlarm()->Set(
-      clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+  CongestionBlockWrites();
 
   // Send an ack and two stream frames (one crypto, then one non-crypto) in 3
   // packets by queueing them.
@@ -1633,28 +1647,23 @@
                                      &TestConnection::SendStreamData3))));
 
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
-  // Unblock the connection.
+  CongestionUnblockWrites();
   connection_.GetSendAlarm()->Fire();
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   EXPECT_FALSE(connection_.HasQueuedData());
 
   // Parse the last packet and ensure it's the stream frame from stream 3.
   EXPECT_EQ(1u, writer_->frame_count());
-  EXPECT_EQ(1u, writer_->stream_frames().size());
+  ASSERT_EQ(1u, writer_->stream_frames().size());
   EXPECT_EQ(kClientDataStreamId1, writer_->stream_frames()[0].stream_id);
 }
 
 TEST_P(QuicConnectionTest, FramePackingFEC) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   // Enable fec.
   EXPECT_TRUE(QuicPacketCreatorPeer::SwitchFecProtectionOn(
       QuicConnectionPeer::GetPacketCreator(&connection_), 6));
 
-  // Block the connection.
-  connection_.GetSendAlarm()->Set(
-      clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
+  CongestionBlockWrites();
 
   // Send an ack and two stream frames in 1 packet by queueing them.
   connection_.SendAck();
@@ -1665,7 +1674,7 @@
                                      &TestConnection::SendStreamData5))));
 
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
-  // Unblock the connection.
+  CongestionUnblockWrites();
   connection_.GetSendAlarm()->Fire();
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
   EXPECT_FALSE(connection_.HasQueuedData());
@@ -1690,7 +1699,7 @@
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
 
   // Process an ack to cause the visitor's OnCanWrite to be invoked.
-  creator_.set_sequence_number(2);
+  peer_creator_.set_sequence_number(2);
   QuicAckFrame ack_one = InitAckFrame(0, 0);
   ProcessAckPacket(&ack_one);
 
@@ -2099,9 +2108,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketAfterFecPacket) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   // Don't send missing packet 1.
@@ -2111,9 +2117,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingSeqNumLengths) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   // Set up a debug visitor to the connection.
@@ -2143,9 +2146,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketWithVaryingConnectionIdLengths) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   // Set up a debug visitor to the connection.
@@ -2175,9 +2175,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketThenFecPacket) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   ProcessFecProtectedPacket(1, false, kEntropyFlag);
@@ -2188,9 +2185,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacketsThenFecPacket) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   ProcessFecProtectedPacket(1, false, !kEntropyFlag);
@@ -2203,9 +2197,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   // Don't send missing packet 1.
@@ -2217,9 +2208,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   ProcessFecProtectedPacket(1, false, !kEntropyFlag);
@@ -2548,7 +2536,7 @@
   ASSERT_EQ(1u, connection_.NumFecGroups());
 
   // Now send non-fec protected ack packet and close the group.
-  creator_.set_sequence_number(4);
+  peer_creator_.set_sequence_number(4);
   if (version() > QUIC_VERSION_15) {
     QuicStopWaitingFrame frame = InitStopWaitingFrame(5);
     ProcessStopWaitingPacket(&frame);
@@ -2585,9 +2573,6 @@
 }
 
 TEST_P(QuicConnectionTest, DontUpdateQuicCongestionFeedbackFrameForRevived) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   SendAckPacketToPeer();
   // Process an FEC packet, and revive the missing data packet
@@ -2759,8 +2744,7 @@
 }
 
 TEST_P(QuicConnectionTest, SendSchedulerDelayThenRetransmit) {
-  EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _))
-      .WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+  CongestionUnblockWrites();
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _));
   connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -2769,17 +2753,13 @@
   // Test that if we send a retransmit with a delay, it ends up queued in the
   // sent packet manager, but not yet serialized.
   EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
-  EXPECT_CALL(*send_algorithm_,
-              TimeUntilSend(_, _, _)).WillOnce(
-                  testing::Return(QuicTime::Delta::FromMicroseconds(1)));
+  CongestionBlockWrites();
   connection_.GetRetransmissionAlarm()->Fire();
   EXPECT_EQ(0u, connection_.NumQueuedPackets());
 
   // Advance the clock to fire the alarm, and configure the scheduler
   // to permit the packet to be sent.
-  EXPECT_CALL(*send_algorithm_,
-              TimeUntilSend(_, _, _)).Times(3).
-                  WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
+  CongestionUnblockWrites();
 
   // Ensure the scheduler is notified this is a retransmit.
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
@@ -2854,9 +2834,7 @@
   // TODO(ianswett): This test is unrealistic, because we would not serialize
   // new data if the send algorithm said not to.
   QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
-  EXPECT_CALL(*send_algorithm_,
-              TimeUntilSend(_, _, _)).WillOnce(
-                  testing::Return(QuicTime::Delta::FromMicroseconds(10)));
+  CongestionBlockWrites();
   connection_.SendPacket(
       ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
   EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -2870,10 +2848,11 @@
 TEST_P(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
   // All packets carry version info till version is negotiated.
   size_t payload_length;
-  connection_.options()->max_packet_length =
-      GetPacketLengthForOneStream(
-          connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
-          NOT_IN_FEC_GROUP, &payload_length);
+  size_t length = GetPacketLengthForOneStream(
+      connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
+      NOT_IN_FEC_GROUP, &payload_length);
+  QuicConnectionPeer::GetPacketCreator(&connection_)->set_max_packet_length(
+      length);
 
   // Queue the first packet.
   EXPECT_CALL(*send_algorithm_,
@@ -2894,9 +2873,11 @@
   // offset 0, and 2 for non-zero offsets up through 16K. Increase
   // max_packet_length by 2 so that subsequent packets containing subsequent
   // stream frames with non-zero offets will fit within the packet length.
-  connection_.options()->max_packet_length = 2 + GetPacketLengthForOneStream(
+  size_t length = 2 + GetPacketLengthForOneStream(
           connection_.version(), kIncludeVersion, PACKET_1BYTE_SEQUENCE_NUMBER,
           NOT_IN_FEC_GROUP, &payload_length);
+  QuicConnectionPeer::GetPacketCreator(&connection_)->set_max_packet_length(
+      length);
 
   // Queue the first packet.
   EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(7);
@@ -3160,7 +3141,7 @@
 
 TEST_P(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
   // Set the sequence number of the ack packet to be least unacked (4).
-  creator_.set_sequence_number(3);
+  peer_creator_.set_sequence_number(3);
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   if (version() > QUIC_VERSION_15) {
     QuicStopWaitingFrame frame = InitStopWaitingFrame(4);
@@ -3183,9 +3164,6 @@
 }
 
 TEST_P(QuicConnectionTest, ReceivedEntropyHashCalculationHalfFEC) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   // FEC packets should not change the entropy hash calculation.
   EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(AtLeast(1));
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3204,7 +3182,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.
-  creator_.set_sequence_number(5);
+  peer_creator_.set_sequence_number(5);
   QuicPacketEntropyHash six_packet_entropy_hash = 0;
   QuicPacketEntropyHash kRandomEntropyHash = 129u;
   if (version() > QUIC_VERSION_15) {
@@ -3232,7 +3210,7 @@
   ProcessDataPacket(5, 1, !kEntropyFlag);
   ProcessDataPacket(22, 1, kEntropyFlag);
   EXPECT_EQ(66u, outgoing_ack()->received_info.entropy_hash);
-  creator_.set_sequence_number(22);
+  peer_creator_.set_sequence_number(22);
   QuicPacketEntropyHash kRandomEntropyHash = 85u;
   // Current packet is the least unacked packet.
   QuicPacketEntropyHash ack_entropy_hash;
@@ -3278,7 +3256,7 @@
 }
 
 TEST_P(QuicConnectionTest, CheckSentEntropyHash) {
-  creator_.set_sequence_number(1);
+  peer_creator_.set_sequence_number(1);
   SequenceNumberSet missing_packets;
   QuicPacketEntropyHash entropy_hash = 0;
   QuicPacketSequenceNumber max_sequence_number = 51;
@@ -3323,7 +3301,7 @@
   QuicFrame frame(&frame1_);
   frames.push_back(frame);
   scoped_ptr<QuicPacket> packet(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer_, header, frames).packet);
   scoped_ptr<QuicEncryptedPacket> encrypted(
       framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
 
@@ -3361,7 +3339,7 @@
   QuicFrame frame(&frame1_);
   frames.push_back(frame);
   scoped_ptr<QuicPacket> packet(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer_, header, frames).packet);
   scoped_ptr<QuicEncryptedPacket> encrypted(
       framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
 
@@ -3406,7 +3384,7 @@
   QuicFrame frame(&frame1_);
   frames.push_back(frame);
   scoped_ptr<QuicPacket> packet(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer_, header, frames).packet);
   scoped_ptr<QuicEncryptedPacket> encrypted(
       framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
 
@@ -3451,7 +3429,7 @@
   QuicFrame frame(&frame1_);
   frames.push_back(frame);
   scoped_ptr<QuicPacket> packet(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer_, header, frames).packet);
   encrypted.reset(framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
   EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(1);
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3532,9 +3510,6 @@
 }
 
 TEST_P(QuicConnectionTest, CheckReceiveStats) {
-  if (version() < QUIC_VERSION_15) {
-    return;
-  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   size_t received_bytes = 0;
@@ -3596,7 +3571,7 @@
   frames.push_back(stream_frame);
   frames.push_back(close_frame);
   scoped_ptr<QuicPacket> packet(
-      framer_.BuildUnsizedDataPacket(header_, frames).packet);
+      BuildUnsizedDataPacket(&framer_, header_, frames).packet);
   EXPECT_TRUE(NULL != packet.get());
   scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
       ENCRYPTION_NONE, 1, *packet));
@@ -3886,7 +3861,7 @@
   ack_header.fec_group = 1;
 
   QuicPacket* packet =
-      framer_.BuildUnsizedDataPacket(ack_header, frames).packet;
+      BuildUnsizedDataPacket(&framer_, ack_header, frames).packet;
 
   // Take the packet which contains the ACK frame, and construct and deliver an
   // FEC packet which allows the ACK packet to be recovered.
@@ -3894,7 +3869,7 @@
 }
 
 class MockQuicConnectionDebugVisitor
-    : public QuicConnectionDebugVisitorInterface {
+    : public QuicConnectionDebugVisitor {
  public:
   MOCK_METHOD1(OnFrameAddedToPacket,
                void(const QuicFrame&));
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index d684a49..dcc4182 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -132,7 +132,7 @@
           // Pad the inchoate client hello to fill up a packet.
           const size_t kFramingOverhead = 50;  // A rough estimate.
           const size_t max_packet_size =
-              session()->connection()->options()->max_packet_length;
+              session()->connection()->max_packet_length();
           if (max_packet_size <= kFramingOverhead) {
             DLOG(DFATAL) << "max_packet_length (" << max_packet_size
                          << ") has no room for framing overhead.";
@@ -237,7 +237,7 @@
 
         verify_ok_ = false;
 
-        ProofVerifier::Status status = verifier->VerifyProof(
+        QuicAsyncStatus status = verifier->VerifyProof(
             server_id_.host(),
             cached->server_config(),
             cached->certs(),
@@ -248,14 +248,14 @@
             proof_verify_callback);
 
         switch (status) {
-          case ProofVerifier::PENDING:
+          case QUIC_PENDING:
             proof_verify_callback_ = proof_verify_callback;
             DVLOG(1) << "Doing VerifyProof";
             return;
-          case ProofVerifier::FAILURE:
+          case QUIC_FAILURE:
             delete proof_verify_callback;
             break;
-          case ProofVerifier::SUCCESS:
+          case QUIC_SUCCESS:
             delete proof_verify_callback;
             verify_ok_ = true;
             break;
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 14ff3fd..3515d32 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -93,7 +93,7 @@
 
   const QuicConfig* config = session_->config();
   EXPECT_EQ(FLAGS_enable_quic_pacing ? kPACE : kQBIC,
-            config->congestion_control());
+            config->congestion_feedback());
   EXPECT_EQ(kDefaultTimeoutSecs,
             config->idle_connection_state_lifetime().ToSeconds());
   EXPECT_EQ(kDefaultMaxStreamsPerConnection,
diff --git a/net/quic/quic_data_stream_test.cc b/net/quic/quic_data_stream_test.cc
index 6799131..04b7c4e 100644
--- a/net/quic/quic_data_stream_test.cc
+++ b/net/quic/quic_data_stream_test.cc
@@ -497,7 +497,8 @@
   string body;
   GenerateBody(&body, kWindow + 1);
   QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body));
-  EXPECT_CALL(*connection_, SendConnectionClose(QUIC_FLOW_CONTROL_ERROR));
+  EXPECT_CALL(*connection_,
+              SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA));
   stream_->OnStreamFrame(frame);
 }
 
@@ -534,7 +535,8 @@
   EXPECT_LT(body.size(),  kStreamWindow);
   QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body));
 
-  EXPECT_CALL(*connection_, SendConnectionClose(QUIC_FLOW_CONTROL_ERROR));
+  EXPECT_CALL(*connection_,
+              SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA));
   stream_->OnStreamFrame(frame);
 }
 
diff --git a/net/quic/quic_flow_controller.cc b/net/quic/quic_flow_controller.cc
index 412f250..6ca3520 100644
--- a/net/quic/quic_flow_controller.cc
+++ b/net/quic/quic_flow_controller.cc
@@ -13,31 +13,32 @@
 
 #define ENDPOINT (is_server_ ? "Server: " : " Client: ")
 
-QuicFlowController::QuicFlowController(QuicVersion version,
+QuicFlowController::QuicFlowController(QuicConnection* connection,
                                        QuicStreamId id,
                                        bool is_server,
                                        uint64 send_window_offset,
                                        uint64 receive_window_offset,
                                        uint64 max_receive_window)
-      : id_(id),
-        is_enabled_(true),
-        is_server_(is_server),
-        bytes_consumed_(0),
-        bytes_buffered_(0),
-        bytes_sent_(0),
-        send_window_offset_(send_window_offset),
-        receive_window_offset_(receive_window_offset),
-        max_receive_window_(max_receive_window),
-        last_blocked_send_window_offset_(0) {
+    : connection_(connection),
+      id_(id),
+      is_enabled_(true),
+      is_server_(is_server),
+      bytes_consumed_(0),
+      highest_received_byte_offset_(0),
+      bytes_sent_(0),
+      send_window_offset_(send_window_offset),
+      receive_window_offset_(receive_window_offset),
+      max_receive_window_(max_receive_window),
+      last_blocked_send_window_offset_(0) {
   DVLOG(1) << ENDPOINT << "Created flow controller for stream " << id_
            << ", setting initial receive window offset to: "
            << receive_window_offset_
            << ", max receive window to: "
            << max_receive_window_
            << ", setting send window offset to: " << send_window_offset_;
-  if (version < QUIC_VERSION_17) {
+  if (connection_->version() < QUIC_VERSION_17) {
     DVLOG(1) << ENDPOINT << "Disabling QuicFlowController for stream " << id_
-             << ", QUIC version " << version;
+             << ", QUIC version " << connection_->version();
     Disable();
   }
 }
@@ -49,31 +50,25 @@
 
   bytes_consumed_ += bytes_consumed;
   DVLOG(1) << ENDPOINT << "Stream " << id_ << " consumed: " << bytes_consumed_;
+
+  MaybeSendWindowUpdate();
 }
 
-void QuicFlowController::AddBytesBuffered(uint64 bytes_buffered) {
+bool QuicFlowController::UpdateHighestReceivedOffset(uint64 new_offset) {
   if (!IsEnabled()) {
-    return;
+    return false;
   }
 
-  bytes_buffered_ += bytes_buffered;
-  DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_;
-}
-
-void QuicFlowController::RemoveBytesBuffered(uint64 bytes_buffered) {
-  if (!IsEnabled()) {
-    return;
+  // Only update if offset has increased.
+  if (new_offset <= highest_received_byte_offset_) {
+    return false;
   }
 
-  if (bytes_buffered_ < bytes_buffered) {
-    LOG(DFATAL) << "Trying to remove " << bytes_buffered << " bytes, when only "
-                << bytes_buffered_ << " bytes are buffered";
-    bytes_buffered_ = 0;
-    return;
-  }
-
-  bytes_buffered_ -= bytes_buffered;
-  DVLOG(1) << ENDPOINT << "Stream " << id_ << " buffered: " << bytes_buffered_;
+  DVLOG(1) << ENDPOINT << "Stream " << id_
+           << " highest byte offset increased from: "
+           << highest_received_byte_offset_ << " to " << new_offset;
+  highest_received_byte_offset_ = new_offset;
+  return true;
 }
 
 void QuicFlowController::AddBytesSent(uint64 bytes_sent) {
@@ -86,6 +81,9 @@
                 << bytes_sent << " bytes, when bytes_sent = " << bytes_sent_
                 << ", and send_window_offset_ = " << send_window_offset_;
     bytes_sent_ = send_window_offset_;
+
+    // This is an error on our side, close the connection as soon as possible.
+    connection_->SendConnectionClose(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
     return;
   }
 
@@ -98,18 +96,18 @@
     return false;
   }
 
-  if (receive_window_offset_ < TotalReceivedBytes()) {
-    LOG(ERROR)
-        << ENDPOINT << "Flow control violation on stream " << id_
-        << ", receive window: " << receive_window_offset_
-        << ", bytes received: " << TotalReceivedBytes();
-
+  if (highest_received_byte_offset_ > receive_window_offset_) {
+    LOG(ERROR) << ENDPOINT << "Flow control violation on stream "
+               << id_ << ", receive window offset: "
+               << receive_window_offset_
+               << ", highest received byte offset: "
+               << highest_received_byte_offset_;
     return true;
   }
   return false;
 }
 
-void QuicFlowController::MaybeSendWindowUpdate(QuicConnection* connection) {
+void QuicFlowController::MaybeSendWindowUpdate() {
   if (!IsEnabled()) {
     return;
   }
@@ -117,6 +115,7 @@
   // Send WindowUpdate to increase receive window if
   // (receive window offset - consumed bytes) < (max window / 2).
   // This is behaviour copied from SPDY.
+  DCHECK_LT(bytes_consumed_, receive_window_offset_);
   size_t consumed_window = receive_window_offset_ - bytes_consumed_;
   size_t threshold = (max_receive_window_ / 2);
 
@@ -132,11 +131,11 @@
              << ". New receive window offset is: " << receive_window_offset_;
 
     // Inform the peer of our new receive window.
-    connection->SendWindowUpdate(id_, receive_window_offset_);
+    connection_->SendWindowUpdate(id_, receive_window_offset_);
   }
 }
 
-void QuicFlowController::MaybeSendBlocked(QuicConnection* connection) {
+void QuicFlowController::MaybeSendBlocked() {
   if (!IsEnabled()) {
     return;
   }
@@ -149,7 +148,7 @@
              << ", send limit: " << send_window_offset_;
     // The entire send_window has been consumed, we are now flow control
     // blocked.
-    connection->SendBlocked(id_);
+    connection_->SendBlocked(id_);
 
     // Keep track of when we last sent a BLOCKED frame so that we only send one
     // at a given send offset.
@@ -201,8 +200,4 @@
   return send_window_offset_ - bytes_sent_;
 }
 
-uint64 QuicFlowController::TotalReceivedBytes() const {
-  return bytes_consumed_ + bytes_buffered_;
-}
-
 }  // namespace net
diff --git a/net/quic/quic_flow_controller.h b/net/quic/quic_flow_controller.h
index 3125b81..e5f5494 100644
--- a/net/quic/quic_flow_controller.h
+++ b/net/quic/quic_flow_controller.h
@@ -25,7 +25,7 @@
 // can send WINDOW_UPDATE or BLOCKED frames when needed.
 class NET_EXPORT_PRIVATE QuicFlowController {
  public:
-  QuicFlowController(QuicVersion version,
+  QuicFlowController(QuicConnection* connection,
                      QuicStreamId id,
                      bool is_server,
                      uint64 send_window_offset,
@@ -33,13 +33,14 @@
                      uint64 max_receive_window);
   ~QuicFlowController() {}
 
-  // Called when bytes are received from the peer, and buffered.
-  void AddBytesBuffered(uint64 bytes_buffered);
+  // Called when we see a new highest received byte offset from the peer, either
+  // via a data frame or a RST.
+  // Returns true if this call changes highest_received_byte_offset_, and false
+  // in the case where |new_offset| is <= highest_received_byte_offset_.
+  bool UpdateHighestReceivedOffset(uint64 new_offset);
 
-  // Called when bytes currently buffered locally, are removed from the buffer.
-  void RemoveBytesBuffered(uint64 bytes_buffered);
-
-  // Called when bytes received from the peer are consumed locally.
+  // Called when bytes received from the peer are consumed locally. This may
+  // trigger the sending of a WINDOW_UPDATE frame using |connection|.
   void AddBytesConsumed(uint64 bytes_consumed);
 
   // Called when bytes are sent to the peer.
@@ -53,11 +54,8 @@
   // Returns the current available send window.
   uint64 SendWindowSize() const;
 
-  // Send a BLOCKED frame on |connection| if appropriate.
-  void MaybeSendBlocked(QuicConnection* connection);
-
-  // Send a WINDOW_UPDATE frame on |connection| if appropriate.
-  void MaybeSendWindowUpdate(QuicConnection* connection);
+  // Send a BLOCKED frame if appropriate.
+  void MaybeSendBlocked();
 
   // Disable flow control.
   void Disable();
@@ -71,11 +69,22 @@
   // Returns true if flow control receive limits have been violated by the peer.
   bool FlowControlViolation();
 
+  uint64 bytes_consumed() const { return bytes_consumed_; }
+
+  uint64 highest_received_byte_offset() const {
+    return highest_received_byte_offset_;
+  }
+
  private:
   friend class test::QuicFlowControllerPeer;
 
-  // Total received bytes is the sum of bytes buffered, and bytes consumed.
-  uint64 TotalReceivedBytes() const;
+  // Send a WINDOW_UPDATE frame if appropriate.
+  void MaybeSendWindowUpdate();
+
+  // The parent connection, used to send connection close on flow control
+  // violation, and WINDOW_UPDATE and BLOCKED frames when appropriate.
+  // Not owned.
+  QuicConnection* connection_;
 
   // ID of stream this flow controller belongs to. This can be 0 if this is a
   // connection level flow controller.
@@ -91,8 +100,9 @@
   // locally.
   uint64 bytes_consumed_;
 
-  // Tracks number of bytes received from the peer, and buffered locally.
-  uint64 bytes_buffered_;
+  // The highest byte offset we have seen from the peer. This could be the
+  // highest offset in a data frame, or a final value in a RST.
+  uint64 highest_received_byte_offset_;
 
   // Tracks number of bytes sent to the peer.
   uint64 bytes_sent_;
diff --git a/net/quic/quic_flow_controller_test.cc b/net/quic/quic_flow_controller_test.cc
index f0bf629..e40dc94 100644
--- a/net/quic/quic_flow_controller_test.cc
+++ b/net/quic/quic_flow_controller_test.cc
@@ -7,6 +7,7 @@
 #include "base/strings/stringprintf.h"
 #include "net/quic/quic_flags.h"
 #include "net/quic/quic_utils.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
 #include "net/quic/test_tools/quic_flow_controller_peer.h"
 #include "net/quic/test_tools/quic_test_utils.h"
 #include "net/test/gtest_util.h"
@@ -23,28 +24,26 @@
  public:
   QuicFlowControllerTest()
       : stream_id_(1234),
-        send_window_(100),
-        receive_window_(200),
-        max_receive_window_(200),
-        version_(QuicVersionMax()),
+        send_window_(kInitialFlowControlWindowForTest),
+        receive_window_(kInitialFlowControlWindowForTest),
+        max_receive_window_(kInitialFlowControlWindowForTest),
+        connection_(false),
         old_flag_(&FLAGS_enable_quic_stream_flow_control_2, true) {
   }
 
   void Initialize() {
-    flow_controller_.reset(new QuicFlowController(version_, stream_id_, false,
-                                                  send_window_, receive_window_,
-                                                  max_receive_window_));
+    flow_controller_.reset(new QuicFlowController(
+        &connection_, stream_id_, false, send_window_,
+        receive_window_, max_receive_window_));
   }
 
-  void set_version(QuicVersion version) { version_ = version; }
-
  protected:
   QuicStreamId stream_id_;
   uint64 send_window_;
   uint64 receive_window_;
   uint64 max_receive_window_;
-  QuicVersion version_;
   scoped_ptr<QuicFlowController> flow_controller_;
+  MockConnection connection_;
   ValueRestore<bool> old_flag_;
 };
 
@@ -67,9 +66,8 @@
   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
 
   // BLOCKED frame should get sent.
-  MockConnection connection(false);
-  EXPECT_CALL(connection, SendBlocked(stream_id_)).Times(1);
-  flow_controller_->MaybeSendBlocked(&connection);
+  EXPECT_CALL(connection_, SendBlocked(stream_id_)).Times(1);
+  flow_controller_->MaybeSendBlocked();
 
   // Update the send window, and verify this has unblocked.
   EXPECT_TRUE(flow_controller_->UpdateSendWindowOffset(2 * send_window_));
@@ -81,6 +79,8 @@
   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
 
   // Try to send more bytes, violating flow control.
+  EXPECT_CALL(connection_,
+              SendConnectionClose(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA));
   EXPECT_DFATAL(
       flow_controller_->AddBytesSent(send_window_ * 10),
       StringPrintf("Trying to send an extra %d bytes",
@@ -95,30 +95,39 @@
   EXPECT_TRUE(flow_controller_->IsEnabled());
   EXPECT_FALSE(flow_controller_->IsBlocked());
   EXPECT_FALSE(flow_controller_->FlowControlViolation());
-
-  // Buffer some bytes, not enough to fill window.
-  flow_controller_->AddBytesBuffered(receive_window_ / 2);
-  EXPECT_FALSE(flow_controller_->FlowControlViolation());
-  EXPECT_EQ(receive_window_ / 2,
+  EXPECT_EQ(kInitialFlowControlWindowForTest,
             QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
 
-  // Consume enough bytes to send a WINDOW_UPDATE frame.
-  flow_controller_->RemoveBytesBuffered(receive_window_ / 2);
-  flow_controller_->AddBytesConsumed(1 + receive_window_ / 2);
+  // Receive some bytes, updating highest received offset, but not enough to
+  // fill flow control receive window.
+  EXPECT_TRUE(
+      flow_controller_->UpdateHighestReceivedOffset(1 + receive_window_ / 2));
   EXPECT_FALSE(flow_controller_->FlowControlViolation());
   EXPECT_EQ((receive_window_ / 2) - 1,
             QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
 
-  MockConnection connection(false);
-  EXPECT_CALL(connection, SendWindowUpdate(stream_id_, _)).Times(1);
-  flow_controller_->MaybeSendWindowUpdate(&connection);
+  // Consume enough bytes to send a WINDOW_UPDATE frame.
+  EXPECT_CALL(connection_, SendWindowUpdate(stream_id_, _)).Times(1);
+
+  flow_controller_->AddBytesConsumed(1 + receive_window_ / 2);
+
+  // Result is that once again we have a fully open receive window.
+  EXPECT_FALSE(flow_controller_->FlowControlViolation());
+  EXPECT_EQ(kInitialFlowControlWindowForTest,
+            QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get()));
 }
 
 TEST_F(QuicFlowControllerTest,
        DisabledWhenQuicVersionDoesNotSupportFlowControl) {
-  set_version(QUIC_VERSION_16);
+  // Only support version 16: no flow control.
+  QuicVersionVector supported_versions;
+  supported_versions.push_back(QUIC_VERSION_16);
+  QuicConnectionPeer::SetSupportedVersions(&connection_, supported_versions);
+
   Initialize();
 
+  MockConnection connection(false);
+
   // Should not be enabled, and should not report as blocked.
   EXPECT_FALSE(flow_controller_->IsEnabled());
   EXPECT_FALSE(flow_controller_->IsBlocked());
@@ -132,8 +141,7 @@
                                  flow_controller_.get()));
   flow_controller_->AddBytesSent(123);
   flow_controller_->AddBytesConsumed(456);
-  flow_controller_->AddBytesBuffered(789);
-  flow_controller_->RemoveBytesBuffered(321);
+  flow_controller_->UpdateHighestReceivedOffset(789);
   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
   EXPECT_EQ(send_window_,
             QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
@@ -149,15 +157,14 @@
   EXPECT_EQ(send_window_,
             QuicFlowControllerPeer::SendWindowOffset(flow_controller_.get()));
 
-  // Should never send WINDOW_UPDATE or BLOCKED frames, even if the internal
-  // state implies that it should.
-  MockConnection connection(false);
+  // The connection should never send WINDOW_UPDATE or BLOCKED frames, even if
+  // the internal state implies that it should.
 
   // If the flow controller was enabled, then a send window size of 0 would
   // trigger a BLOCKED frame to be sent.
   EXPECT_EQ(send_window_, flow_controller_->SendWindowSize());
-  EXPECT_CALL(connection, SendBlocked(_)).Times(0);
-  flow_controller_->MaybeSendBlocked(&connection);
+  EXPECT_CALL(connection_, SendBlocked(_)).Times(0);
+  flow_controller_->MaybeSendBlocked();
 
   // If the flow controller was enabled, then a WINDOW_UPDATE would be sent if
   // (receive window) < (max receive window / 2)
@@ -165,8 +172,8 @@
                                                  max_receive_window_ / 10);
   EXPECT_TRUE(QuicFlowControllerPeer::ReceiveWindowSize(
                   flow_controller_.get()) < (max_receive_window_ / 2));
-  EXPECT_CALL(connection, SendWindowUpdate(_, _)).Times(0);
-  flow_controller_->MaybeSendWindowUpdate(&connection);
+  EXPECT_CALL(connection_, SendWindowUpdate(_, _)).Times(0);
+  flow_controller_->AddBytesConsumed(0);
 
   // Should not be enabled, and should not report as blocked.
   EXPECT_FALSE(flow_controller_->IsEnabled());
@@ -190,18 +197,17 @@
   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
 
   // Expect that 2 BLOCKED frames should get sent in total.
-  MockConnection connection(false);
-  EXPECT_CALL(connection, SendBlocked(stream_id_)).Times(2);
+  EXPECT_CALL(connection_, SendBlocked(stream_id_)).Times(2);
 
   // BLOCKED frame should get sent.
-  flow_controller_->MaybeSendBlocked(&connection);
+  flow_controller_->MaybeSendBlocked();
 
   // BLOCKED frame should not get sent again until our send offset changes.
-  flow_controller_->MaybeSendBlocked(&connection);
-  flow_controller_->MaybeSendBlocked(&connection);
-  flow_controller_->MaybeSendBlocked(&connection);
-  flow_controller_->MaybeSendBlocked(&connection);
-  flow_controller_->MaybeSendBlocked(&connection);
+  flow_controller_->MaybeSendBlocked();
+  flow_controller_->MaybeSendBlocked();
+  flow_controller_->MaybeSendBlocked();
+  flow_controller_->MaybeSendBlocked();
+  flow_controller_->MaybeSendBlocked();
 
   // Update the send window, then send enough bytes to block again.
   EXPECT_TRUE(flow_controller_->UpdateSendWindowOffset(2 * send_window_));
@@ -212,7 +218,7 @@
   EXPECT_EQ(0u, flow_controller_->SendWindowSize());
 
   // BLOCKED frame should get sent as send offset has changed.
-  flow_controller_->MaybeSendBlocked(&connection);
+  flow_controller_->MaybeSendBlocked();
 }
 
 }  // namespace test
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 8ff2ee7..e44bd2d 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -332,26 +332,6 @@
   return header.entropy_flag << (header.packet_sequence_number % 8);
 }
 
-// Test only.
-SerializedPacket QuicFramer::BuildUnsizedDataPacket(
-    const QuicPacketHeader& header,
-    const QuicFrames& frames) {
-  const size_t max_plaintext_size = GetMaxPlaintextSize(kMaxPacketSize);
-  size_t packet_size = GetPacketHeaderSize(header);
-  for (size_t i = 0; i < frames.size(); ++i) {
-    DCHECK_LE(packet_size, max_plaintext_size);
-    bool first_frame = i == 0;
-    bool last_frame = i == frames.size() - 1;
-    const size_t frame_size = GetSerializedFrameLength(
-        frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
-        header.is_in_fec_group,
-        header.public_header.sequence_number_length);
-    DCHECK(frame_size);
-    packet_size += frame_size;
-  }
-  return BuildDataPacket(header, frames, packet_size);
-}
-
 SerializedPacket QuicFramer::BuildDataPacket(
     const QuicPacketHeader& header,
     const QuicFrames& frames,
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h
index a7e8a08..e947eb4 100644
--- a/net/quic/quic_framer.h
+++ b/net/quic/quic_framer.h
@@ -306,13 +306,6 @@
       QuicSequenceNumberLength sequence_number_length);
 
   // Returns a SerializedPacket whose |packet| member is owned by the caller,
-  // and is populated with the fields in |header| and |frames|, or is NULL if
-  // the packet could not be created.
-  // TODO(ianswett): Used for testing only.
-  SerializedPacket BuildUnsizedDataPacket(const QuicPacketHeader& header,
-                                          const QuicFrames& frames);
-
-  // Returns a SerializedPacket whose |packet| member is owned by the caller,
   // is created from the first |num_frames| frames, or is NULL if the packet
   // could not be created.  The packet must be of size |packet_size|.
   SerializedPacket BuildDataPacket(const QuicPacketHeader& header,
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index 5dd3e35..fd206e1 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -494,6 +494,11 @@
         << " wire_sequence_number: " << wire_sequence_number;
   }
 
+  QuicPacket* BuildDataPacket(const QuicPacketHeader& header,
+                              const QuicFrames& frames) {
+    return BuildUnsizedDataPacket(&framer_, header, frames).packet;
+  }
+
   test::TestEncrypter* encrypter_;
   test::TestDecrypter* decrypter_;
   QuicVersion version_;
@@ -2148,8 +2153,7 @@
   // Verify that the packet re-serializes identically.
   QuicFrames frames;
   frames.push_back(QuicFrame(frame));
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -2210,8 +2214,7 @@
   // Verify that the packet re-serializes identically.
   QuicFrames frames;
   frames.push_back(QuicFrame(frame));
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -2285,8 +2288,7 @@
   // Verify that the packet re-serializes identically.
   QuicFrames frames;
   frames.push_back(QuicFrame(frame));
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -2367,8 +2369,7 @@
   // Verify that the packet re-serializes identically.
   QuicFrames frames;
   frames.push_back(QuicFrame(frame));
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3245,8 +3246,7 @@
                           PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
   memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3292,8 +3292,7 @@
                           PACKET_4BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
   memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3339,8 +3338,7 @@
                           PACKET_2BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
   memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3386,8 +3384,7 @@
                           PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
   memset(packet + header_size + 1, 0x00, kMaxPacketSize - header_size - 1);
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3440,8 +3437,7 @@
     'r',  'l',  'd',  '!',
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3496,8 +3492,7 @@
     'r',  'l',  'd',  '!',
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3552,8 +3547,7 @@
   };
 
   QuicFramerPeer::SetIsServer(&framer_, false);
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3642,8 +3636,7 @@
     0x00,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3713,8 +3706,7 @@
     0x00,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -3946,8 +3938,7 @@
     0x03, 0x04,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4016,8 +4007,7 @@
     0x02, 0x00, 0x00, 0x00,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4066,8 +4056,7 @@
     0x00, 0x00,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4113,8 +4102,7 @@
     0x01, 0x02, 0x03, 0x04,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4141,7 +4129,7 @@
 
   scoped_ptr<QuicPacket> data;
   EXPECT_DFATAL(
-      data.reset(framer_.BuildUnsizedDataPacket(header, frames).packet),
+      data.reset(BuildDataPacket(header, frames)),
       "AppendCongestionFeedbackFrame failed");
   ASSERT_TRUE(data == NULL);
 }
@@ -4195,8 +4183,7 @@
   QuicFrames frames;
   frames.push_back(QuicFrame(&rst_frame));
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4246,8 +4233,7 @@
     'n',
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4300,8 +4286,7 @@
     'n',
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet",
@@ -4347,8 +4332,7 @@
     0x44, 0x33, 0x22, 0x11,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -4390,8 +4374,7 @@
     0x04, 0x03, 0x02, 0x01,
   };
 
-  scoped_ptr<QuicPacket> data(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != NULL);
 
   test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -4431,8 +4414,7 @@
   };
 
   if (version_ > QUIC_VERSION_17) {
-    scoped_ptr<QuicPacket> data(
-        framer_.BuildUnsizedDataPacket(header, frames).packet);
+    scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
     ASSERT_TRUE(data != NULL);
 
     test::CompareCharArraysWithHexError("constructed packet", data->data(),
@@ -4441,7 +4423,7 @@
   } else {
     string expected_error =
         "Attempt to add a PingFrame in " + QuicVersionToString(version_);
-    EXPECT_DFATAL(framer_.BuildUnsizedDataPacket(header, frames),
+    EXPECT_DFATAL(BuildDataPacket(header, frames),
                   expected_error);
     return;
   }
@@ -4770,8 +4752,7 @@
   QuicFrames frames;
   frames.push_back(frame);
 
-  scoped_ptr<QuicPacket> raw_ack_packet(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
   ASSERT_TRUE(raw_ack_packet != NULL);
 
   scoped_ptr<QuicEncryptedPacket> ack_packet(
@@ -4819,8 +4800,7 @@
   QuicFrames frames;
   frames.push_back(frame);
 
-  scoped_ptr<QuicPacket> raw_ack_packet(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
   ASSERT_TRUE(raw_ack_packet != NULL);
 
   scoped_ptr<QuicEncryptedPacket> ack_packet(
@@ -4838,8 +4818,7 @@
   frames.push_back(frame);
 
   size_t original_raw_length = raw_ack_packet->length();
-  raw_ack_packet.reset(
-      framer_.BuildUnsizedDataPacket(header, frames).packet);
+  raw_ack_packet.reset(BuildDataPacket(header, frames));
   ASSERT_TRUE(raw_ack_packet != NULL);
   EXPECT_EQ(original_raw_length, raw_ack_packet->length());
   ASSERT_TRUE(raw_ack_packet != NULL);
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 9fc78d9..66261d4 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -214,6 +214,8 @@
                                            false, PRIVACY_MODE_DISABLED),
                               DefaultQuicConfig(),
                               kInitialFlowControlWindowForTest, &crypto_config_,
+                              base::MessageLoop::current()->
+                                  message_loop_proxy().get(),
                               NULL));
     session_->GetCryptoStream()->CryptoConnect();
     EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index cb67569..af6fb7b 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -831,6 +831,11 @@
 
   AddHangingNonAlternateProtocolSocketData();
 
+  // Second Alternate-protocol job which will race with the TCP job.
+  StaticSocketDataProvider quic_data2(quic_reads, arraysize(quic_reads),
+                                      NULL, 0);
+  socket_factory_.AddSocketDataProvider(&quic_data2);
+
   // Final job that will proceed when the QUIC job fails.
   MockRead http_reads[] = {
     MockRead("HTTP/1.1 200 OK\r\n\r\n"),
@@ -855,6 +860,34 @@
   EXPECT_TRUE(quic_data.at_write_eof());
 }
 
+TEST_P(QuicNetworkTransactionTest, HangingZeroRttFallback) {
+  // Alternate-protocol job
+  MockRead quic_reads[] = {
+    MockRead(ASYNC, ERR_IO_PENDING),
+  };
+  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
+                                     NULL, 0);
+  socket_factory_.AddSocketDataProvider(&quic_data);
+
+  // Main job that will proceed when the QUIC job fails.
+  MockRead http_reads[] = {
+    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+    MockRead("hello from http"),
+    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+    MockRead(ASYNC, OK)
+  };
+
+  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+                                     NULL, 0);
+  socket_factory_.AddSocketDataProvider(&http_data);
+
+  CreateSessionWithNextProtos();
+
+  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
+
+  SendRequestAndExpectHttpResponse("hello from http");
+}
+
 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) {
   // Alternate-protocol job will fail before creating a QUIC session.
   StaticSocketDataProvider quic_data(NULL, 0, NULL, 0);
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index 4b64ae5..f7d2d14 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -68,7 +68,11 @@
       fec_group_number_(0),
       is_server_(is_server),
       send_version_in_packet_(!is_server),
-      sequence_number_length_(options_.send_sequence_number_length),
+      max_packet_length_(kDefaultMaxPacketSize),
+      max_packets_per_fec_group_(0),
+      connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
+      next_sequence_number_length_(PACKET_1BYTE_SEQUENCE_NUMBER),
+      sequence_number_length_(next_sequence_number_length_),
       packet_size_(0) {
   framer_->set_fec_builder(this);
 }
@@ -87,7 +91,7 @@
 bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
   return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 &&
       (force_close || fec_group_->NumReceivedPackets() >=
-                      options_.max_packets_per_fec_group);
+                      max_packets_per_fec_group_);
 }
 
 void QuicPacketCreator::StartFecProtectingPackets() {
@@ -123,18 +127,7 @@
 }
 
 bool QuicPacketCreator::IsFecEnabled() const {
-  return options_.max_packets_per_fec_group > 0;
-}
-
-size_t QuicPacketCreator::max_packets_per_fec_group() const {
-  return options_.max_packets_per_fec_group;
-}
-
-void QuicPacketCreator::set_max_packets_per_fec_group(
-    size_t max_packets_per_fec_group) {
-  // To turn off FEC protection, use StopFecProtectingPackets().
-  DCHECK_NE(0u, max_packets_per_fec_group);
-  options_.max_packets_per_fec_group = max_packets_per_fec_group;
+  return max_packets_per_fec_group_ > 0;
 }
 
 InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() {
@@ -147,8 +140,9 @@
     // Don't change creator state if there are frames queued.
     return fec_group_.get() == NULL ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
   }
-  // TODO(jri): Add max_packet_length and send_connection_id_length here too.
-  sequence_number_length_ = options_.send_sequence_number_length;
+
+  // Update sequence number length only on packet and FEC group boundaries.
+  sequence_number_length_ = next_sequence_number_length_;
 
   if (!should_fec_protect_) {
     return NOT_IN_FEC_GROUP;
@@ -179,12 +173,12 @@
   // Since the packet creator will not change sequence number length mid FEC
   // group, include the size of an FEC group to be safe.
   const QuicPacketSequenceNumber current_delta =
-      options_.max_packets_per_fec_group + sequence_number_ + 1
+      max_packets_per_fec_group_ + sequence_number_ + 1
       - least_packet_awaited_by_peer;
   const uint64 congestion_window_packets =
-      congestion_window / options_.max_packet_length;
+      congestion_window / max_packet_length_;
   const uint64 delta = max(current_delta, congestion_window_packets);
-  options_.send_sequence_number_length =
+  next_sequence_number_length_ =
       QuicFramer::GetMinSequenceNumberLength(delta * 4);
 }
 
@@ -219,8 +213,7 @@
                                             QuicStreamOffset offset,
                                             bool fin,
                                             QuicFrame* frame) {
-  DCHECK_GT(options_.max_packet_length,
-            StreamFramePacketOverhead(
+  DCHECK_GT(max_packet_length_, StreamFramePacketOverhead(
                 framer_->version(), PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
                 PACKET_6BYTE_SEQUENCE_NUMBER, offset, IN_FEC_GROUP));
 
@@ -277,19 +270,19 @@
     QuicSequenceNumberLength original_length) {
   DCHECK(fec_group_.get() == NULL);
   const QuicSequenceNumberLength saved_length = sequence_number_length_;
-  const QuicSequenceNumberLength saved_options_length =
-      options_.send_sequence_number_length;
+  const QuicSequenceNumberLength saved_next_length =
+      next_sequence_number_length_;
   const bool saved_should_fec_protect = should_fec_protect_;
 
   // Temporarily set the sequence number length and stop FEC protection.
   sequence_number_length_ = original_length;
-  options_.send_sequence_number_length = original_length;
+  next_sequence_number_length_ = original_length;
   should_fec_protect_ = false;
 
   // Serialize the packet and restore the FEC and sequence number length state.
   SerializedPacket serialized_packet = SerializeAllFrames(frames);
   sequence_number_length_ = saved_length;
-  options_.send_sequence_number_length = saved_options_length;
+  next_sequence_number_length_ = saved_next_length;
   should_fec_protect_ = saved_should_fec_protect;
 
   return serialized_packet;
@@ -330,26 +323,23 @@
 
 size_t QuicPacketCreator::BytesFree() const {
   const size_t max_plaintext_size =
-      framer_->GetMaxPlaintextSize(options_.max_packet_length);
+      framer_->GetMaxPlaintextSize(max_packet_length_);
   DCHECK_GE(max_plaintext_size, PacketSize());
   return max_plaintext_size - min(max_plaintext_size, PacketSize()
                                   + ExpansionOnNewFrame());
 }
 
 size_t QuicPacketCreator::PacketSize() const {
-  if (queued_frames_.empty()) {
-    // Only adjust the sequence number length when the FEC group is not open,
-    // to ensure no packets in a group are too large.
-    if (fec_group_.get() == NULL ||
-        fec_group_->NumReceivedPackets() == 0) {
-      sequence_number_length_ = options_.send_sequence_number_length;
-    }
-    packet_size_ = GetPacketHeaderSize(options_.send_connection_id_length,
-                                       send_version_in_packet_,
-                                       sequence_number_length_,
-                                       should_fec_protect_ ? IN_FEC_GROUP :
-                                                             NOT_IN_FEC_GROUP);
+  if (!queued_frames_.empty()) {
+    return packet_size_;
   }
+  if (fec_group_.get() == NULL) {
+    // Update sequence number length on packet and FEC boundary.
+    sequence_number_length_ = next_sequence_number_length_;
+  }
+  packet_size_ = GetPacketHeaderSize(
+      connection_id_length_, send_version_in_packet_, sequence_number_length_,
+      should_fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP);
   return packet_size_;
 }
 
@@ -367,7 +357,7 @@
   MaybeAddPadding();
 
   size_t max_plaintext_size =
-      framer_->GetMaxPlaintextSize(options_.max_packet_length);
+      framer_->GetMaxPlaintextSize(max_packet_length_);
   DCHECK_GE(max_plaintext_size, packet_size_);
   // ACK Frames will be truncated only if they're the only frame in the packet,
   // and if packet_size_ was set to max_plaintext_size. If truncation occurred,
@@ -384,7 +374,6 @@
   if (!possibly_truncated) {
     DCHECK_EQ(packet_size_, serialized.packet->length());
   }
-
   packet_size_ = 0;
   queued_frames_.clear();
   serialized.retransmittable_frames = queued_retransmittable_frames_.release();
@@ -409,7 +398,7 @@
   packet_size_ = 0;
   LOG_IF(DFATAL, !serialized.packet)
       << "Failed to serialize fec packet for group:" << fec_data.fec_group;
-  DCHECK_GE(options_.max_packet_length, serialized.packet->length());
+  DCHECK_GE(max_packet_length_, serialized.packet->length());
   return serialized;
 }
 
@@ -431,7 +420,7 @@
   QuicEncryptedPacket* encrypted =
       framer_->BuildVersionNegotiationPacket(header, supported_versions);
   DCHECK(encrypted);
-  DCHECK_GE(options_.max_packet_length, encrypted->length());
+  DCHECK_GE(max_packet_length_, encrypted->length());
   return encrypted;
 }
 
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h
index 36ab5df..0e19887 100644
--- a/net/quic/quic_packet_creator.h
+++ b/net/quic/quic_packet_creator.h
@@ -29,22 +29,6 @@
 
 class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
  public:
-  // Options for controlling how packets are created.
-  struct Options {
-    Options()
-        : max_packet_length(kDefaultMaxPacketSize),
-          max_packets_per_fec_group(0),
-          send_connection_id_length(PACKET_8BYTE_CONNECTION_ID),
-          send_sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER) {}
-
-    size_t max_packet_length;
-    // 0 indicates fec is disabled.
-    size_t max_packets_per_fec_group;
-    // Length of connection_id to send over the wire.
-    QuicConnectionIdLength send_connection_id_length;
-    QuicSequenceNumberLength send_sequence_number_length;
-  };
-
   // QuicRandom* required for packet entropy.
   QuicPacketCreator(QuicConnectionId connection_id,
                     QuicFramer* framer,
@@ -63,21 +47,15 @@
   void StartFecProtectingPackets();
 
   // Turn off FEC protection for subsequently created packets. If the creator
-  // has any open fec group, call will fail. It is the caller's responsibility
+  // has any open FEC group, call will fail. It is the caller's responsibility
   // to flush out FEC packets in generation, and to verify with ShouldSendFec()
   // that there is no open FEC group.
   void StopFecProtectingPackets();
 
   // Checks if it's time to send an FEC packet.  |force_close| forces this to
-  // return true if an fec group is open.
+  // return true if an FEC group is open.
   bool ShouldSendFec(bool force_close) const;
 
-  // Returns current max number of packets covered by an FEC group.
-  size_t max_packets_per_fec_group() const;
-
-  // Sets creator's max number of packets covered by an FEC group.
-  void set_max_packets_per_fec_group(size_t max_packets_per_fec_group);
-
   // Makes the framer not serialize the protocol version in sent packets.
   void StopSendingVersion();
 
@@ -213,8 +191,39 @@
     sequence_number_ = s;
   }
 
-  Options* options() {
-    return &options_;
+  QuicConnectionIdLength connection_id_length() const {
+    return connection_id_length_;
+  }
+
+  QuicSequenceNumberLength next_sequence_number_length() const {
+    return next_sequence_number_length_;
+  }
+
+  void set_next_sequence_number_length(QuicSequenceNumberLength length) {
+    next_sequence_number_length_ = length;
+  }
+
+  size_t max_packet_length() const {
+    return max_packet_length_;
+  }
+
+  void set_max_packet_length(size_t length) {
+    // |max_packet_length_| should not be changed mid-packet or mid-FEC group.
+    DCHECK(fec_group_.get() == NULL && queued_frames_.empty());
+    max_packet_length_ = length;
+  }
+
+  // Returns current max number of packets covered by an FEC group.
+  size_t max_packets_per_fec_group() const {
+      return max_packets_per_fec_group_;
+  }
+
+  // Sets creator's max number of packets covered by an FEC group.
+  void set_max_packets_per_fec_group(
+      size_t max_packets_per_fec_group) {
+    // To turn off FEC protection, use StopFecProtectingPackets().
+    DCHECK_NE(0u, max_packets_per_fec_group);
+    max_packets_per_fec_group_ = max_packets_per_fec_group;
   }
 
  private:
@@ -222,9 +231,12 @@
 
   static bool ShouldRetransmit(const QuicFrame& frame);
 
-  // Updates sequence number length on a packet or FEC group boundary.
-  // Also starts an FEC group if FEC protection is on and there is not already
-  // an FEC group open.
+  // Updates sequence number and max packet lengths on a packet or FEC group
+  // boundary.
+  void MaybeUpdateLengths();
+
+  // Updates lengths and also starts an FEC group if FEC protection is on and
+  // there is not already an FEC group open.
   InFecGroup MaybeUpdateLengthsAndStartFec();
 
   void FillPacketHeader(QuicFecGroupNumber fec_group,
@@ -240,7 +252,6 @@
   // padding frame.
   void MaybeAddPadding();
 
-  Options options_;
   QuicConnectionId connection_id_;
   EncryptionLevel encryption_level_;
   QuicFramer* framer_;
@@ -255,9 +266,20 @@
   // Controls whether protocol version should be included while serializing the
   // packet.
   bool send_version_in_packet_;
-  // The sequence number length for the current packet and the current FEC group
-  // if FEC is enabled.
-  // Mutable so PacketSize() can adjust it when the packet is empty.
+  // Maximum length including headers and encryption (UDP payload length.)
+  size_t max_packet_length_;
+  // 0 indicates FEC is disabled.
+  size_t max_packets_per_fec_group_;
+  // Length of connection_id to send over the wire.
+  QuicConnectionIdLength connection_id_length_;
+  // Staging variable to hold next packet sequence number length. When sequence
+  // number length is to be changed, this variable holds the new length until
+  // a packet or FEC group boundary, when the creator's sequence_number_length_
+  // can be changed to this new value.
+  QuicSequenceNumberLength next_sequence_number_length_;
+  // Sequence number length for the current packet and for the current FEC group
+  // when FEC is enabled. Mutable so PacketSize() can adjust it when the packet
+  // is empty.
   mutable QuicSequenceNumberLength sequence_number_length_;
   // packet_size_ is mutable because it's just a cache of the current size.
   // packet_size should never be read directly, use PacketSize() instead.
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 57bf2f4..d4b7f44 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -100,18 +100,17 @@
   // Returns the number of bytes consumed by the header of packet, including
   // the version.
   size_t GetPacketHeaderOverhead(InFecGroup is_in_fec_group) {
-    return GetPacketHeaderSize(creator_.options()->send_connection_id_length,
+    return GetPacketHeaderSize(creator_.connection_id_length(),
                                kIncludeVersion,
-                               creator_.options()->send_sequence_number_length,
+                               creator_.next_sequence_number_length(),
                                is_in_fec_group);
   }
 
   // Returns the number of bytes of overhead that will be added to a packet
   // of maximum length.
   size_t GetEncryptionOverhead() {
-    return creator_.options()->max_packet_length -
-        client_framer_.GetMaxPlaintextSize(
-            creator_.options()->max_packet_length);
+    return creator_.max_packet_length() - client_framer_.GetMaxPlaintextSize(
+        creator_.max_packet_length());
   }
 
   // Returns the number of bytes consumed by the non-data fields of a stream
@@ -216,8 +215,7 @@
 TEST_P(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
   frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u, 0u))));
   creator_.AddSavedFrame(frames_[0]);
-  creator_.options()->send_sequence_number_length =
-      PACKET_4BYTE_SEQUENCE_NUMBER;
+  creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
   SerializedPacket serialized = creator_.SerializePacket();
   // The sequence number length will not change mid-packet.
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
@@ -270,8 +268,7 @@
   creator_.AddSavedFrame(ack_frame);
 
   // Now change sequence number length.
-  creator_.options()->send_sequence_number_length =
-      PACKET_4BYTE_SEQUENCE_NUMBER;
+  creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
 
   // Add a STOP_WAITING frame since it contains a packet sequence number,
   // whose length should be 1.
@@ -351,8 +348,7 @@
   // Generate Packet 1.
   creator_.AddSavedFrame(frames_[0]);
   // Change the sequence number length mid-FEC group and it should not change.
-  creator_.options()->send_sequence_number_length =
-      PACKET_4BYTE_SEQUENCE_NUMBER;
+  creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
   SerializedPacket serialized = creator_.SerializePacket();
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
 
@@ -424,15 +420,14 @@
   // If the original packet sequence number length, the current sequence number
   // length, and the configured send sequence number length are different, the
   // retransmit must sent with the original length and the others do not change.
-  creator_.options()->send_sequence_number_length =
-      PACKET_4BYTE_SEQUENCE_NUMBER;
+  creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
   QuicPacketCreatorPeer::SetSequenceNumberLength(&creator_,
                                                  PACKET_2BYTE_SEQUENCE_NUMBER);
   frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
   SerializedPacket serialized =
       creator_.ReserializeAllFrames(frames_, PACKET_1BYTE_SEQUENCE_NUMBER);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
             QuicPacketCreatorPeer::GetSequenceNumberLength(&creator_));
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
@@ -582,7 +577,7 @@
   const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP)
                           + GetEncryptionOverhead();
   for (size_t i = overhead; i < overhead + 100; ++i) {
-    creator_.options()->max_packet_length = i;
+    creator_.set_max_packet_length(i);
     const bool should_have_room = i > overhead + GetStreamFrameOverhead(
         NOT_IN_FEC_GROUP);
     ASSERT_EQ(should_have_room, creator_.HasRoomForStreamFrame(
@@ -740,49 +735,49 @@
 
 TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthLeastAwaiting) {
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.set_sequence_number(64);
   creator_.UpdateSequenceNumberLength(2, 10000);
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.set_sequence_number(64 * 256);
   creator_.UpdateSequenceNumberLength(2, 10000);
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.set_sequence_number(64 * 256 * 256);
   creator_.UpdateSequenceNumberLength(2, 10000);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.set_sequence_number(GG_UINT64_C(64) * 256 * 256 * 256 * 256);
   creator_.UpdateSequenceNumberLength(2, 10000);
   EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 }
 
 TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthBandwidth) {
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.UpdateSequenceNumberLength(1, 10000);
   EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.UpdateSequenceNumberLength(1, 10000 * 256);
   EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.UpdateSequenceNumberLength(1, 10000 * 256 * 256);
   EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 
   creator_.UpdateSequenceNumberLength(
       1, GG_UINT64_C(1000) * 256 * 256 * 256 * 256);
   EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
-            creator_.options()->send_sequence_number_length);
+            creator_.next_sequence_number_length());
 }
 
 TEST_P(QuicPacketCreatorTest, CreateStreamFrameWithNotifier) {
@@ -833,10 +828,10 @@
   }
   // A string larger than fits into a frame.
   size_t payload_length;
-  creator_.options()->max_packet_length = GetPacketLengthForOneStream(
+  creator_.set_max_packet_length(GetPacketLengthForOneStream(
       client_framer_.version(),
       QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
-      PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP, &payload_length);
+      PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP, &payload_length));
   QuicFrame frame;
   const string too_long_payload(payload_length * 2, 'a');
   size_t consumed = creator_.CreateStreamFrame(
@@ -852,11 +847,11 @@
     creator_.StopSendingVersion();
   }
   const size_t max_plaintext_size =
-      client_framer_.GetMaxPlaintextSize(creator_.options()->max_packet_length);
+      client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
   EXPECT_FALSE(creator_.HasPendingFrames());
   EXPECT_EQ(max_plaintext_size -
             GetPacketHeaderSize(
-                creator_.options()->send_connection_id_length,
+                creator_.connection_id_length(),
                 QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
                 PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP),
             creator_.BytesFree());
@@ -900,7 +895,7 @@
   EXPECT_FALSE(creator_.HasPendingFrames());
   EXPECT_EQ(max_plaintext_size -
             GetPacketHeaderSize(
-                creator_.options()->send_connection_id_length,
+                creator_.connection_id_length(),
                 QuicPacketCreatorPeer::SendVersionInPacket(&creator_),
                 PACKET_1BYTE_SEQUENCE_NUMBER,
                 NOT_IN_FEC_GROUP),
@@ -911,9 +906,9 @@
   if (!GetParam().version_serialization) {
     creator_.StopSendingVersion();
   }
-  creator_.options()->max_packet_length = kMaxPacketSize;
+  creator_.set_max_packet_length(kMaxPacketSize);
   const size_t max_plaintext_size =
-      client_framer_.GetMaxPlaintextSize(creator_.options()->max_packet_length);
+      client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
 
   // Serialized length of ack frame with 2000 nack ranges should be limited by
   // the number of nack ranges that can be fit in an ack frame.
@@ -955,9 +950,10 @@
   if (!GetParam().version_serialization) {
     creator_.StopSendingVersion();
   }
-  creator_.options()->max_packet_length = 500u;
+  creator_.set_max_packet_length(500u);
+
   const size_t max_plaintext_size =
-      client_framer_.GetMaxPlaintextSize(creator_.options()->max_packet_length);
+      client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
   EXPECT_EQ(max_plaintext_size - creator_.PacketSize(), creator_.BytesFree());
 
   // Serialized length of ack frame with 2000 nack ranges should be limited by
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc
index 785c940..b91ccc6 100644
--- a/net/quic/quic_packet_generator.cc
+++ b/net/quic/quic_packet_generator.cc
@@ -16,7 +16,7 @@
 class QuicAckNotifier;
 
 QuicPacketGenerator::QuicPacketGenerator(DelegateInterface* delegate,
-                                         DebugDelegateInterface* debug_delegate,
+                                         DebugDelegate* debug_delegate,
                                          QuicPacketCreator* creator)
     : delegate_(delegate),
       debug_delegate_(debug_delegate),
diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h
index 12caf34..957477a 100644
--- a/net/quic/quic_packet_generator.h
+++ b/net/quic/quic_packet_generator.h
@@ -54,6 +54,7 @@
 #define NET_QUIC_QUIC_PACKET_GENERATOR_H_
 
 #include "net/quic/quic_packet_creator.h"
+#include "net/quic/quic_types.h"
 
 namespace net {
 
@@ -78,16 +79,16 @@
   // Interface which gets callbacks from the QuicPacketGenerator at interesting
   // points.  Implementations must not mutate the state of the generator
   // as a result of these callbacks.
-  class NET_EXPORT_PRIVATE DebugDelegateInterface {
+  class NET_EXPORT_PRIVATE DebugDelegate {
    public:
-    virtual ~DebugDelegateInterface() {}
+    virtual ~DebugDelegate() {}
 
     // Called when a frame has been added to the current packet.
     virtual void OnFrameAddedToPacket(const QuicFrame& frame) {}
   };
 
   QuicPacketGenerator(DelegateInterface* delegate,
-                      DebugDelegateInterface* debug_delegate,
+                      DebugDelegate* debug_delegate,
                       QuicPacketCreator* creator);
 
   virtual ~QuicPacketGenerator();
@@ -131,7 +132,7 @@
 
   bool HasQueuedFrames() const;
 
-  void set_debug_delegate(DebugDelegateInterface* debug_delegate) {
+  void set_debug_delegate(DebugDelegate* debug_delegate) {
     debug_delegate_ = debug_delegate;
   }
 
@@ -152,7 +153,7 @@
   void SerializeAndSendPacket();
 
   DelegateInterface* delegate_;
-  DebugDelegateInterface* debug_delegate_;
+  DebugDelegate* debug_delegate_;
 
   QuicPacketCreator* packet_creator_;
   QuicFrames queued_control_frames_;
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 16f9748..c06f6f6 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -231,7 +231,7 @@
   scoped_ptr<char[]> data_array_;
 };
 
-class MockDebugDelegate : public QuicPacketGenerator::DebugDelegateInterface {
+class MockDebugDelegate : public QuicPacketGenerator::DebugDelegate {
  public:
   MOCK_METHOD1(OnFrameAddedToPacket,
                void(const QuicFrame&));
@@ -503,11 +503,11 @@
 TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
   // Set the packet size be enough for two stream frames with 0 stream offset,
   // but not enough for a stream frame of 0 offset and one with non-zero offset.
-  creator_.options()->max_packet_length =
+  size_t length =
       NullEncrypter().GetCiphertextSize(0) +
-      GetPacketHeaderSize(creator_.options()->send_connection_id_length,
+      GetPacketHeaderSize(creator_.connection_id_length(),
                           true,
-                          creator_.options()->send_sequence_number_length,
+                          creator_.next_sequence_number_length(),
                           NOT_IN_FEC_GROUP) +
       // Add an extra 3 bytes for the payload and 1 byte so BytesFree is larger
       // than the GetMinStreamFrameSize.
@@ -515,6 +515,7 @@
                                         NOT_IN_FEC_GROUP) + 3 +
       QuicFramer::GetMinStreamFrameSize(framer_.version(), 1, 0, true,
                                         NOT_IN_FEC_GROUP) + 1;
+  creator_.set_max_packet_length(length);
   delegate_.SetCanWriteAnything();
   {
      InSequence dummy;
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index df3bfa5..cd73694 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -144,6 +144,11 @@
          static_cast<uint32>(d) << 24;
 }
 
+bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag) {
+  return std::find(tag_vector.begin(), tag_vector.end(),  tag)
+      != tag_vector.end();
+}
+
 QuicVersionVector QuicSupportedVersions() {
   QuicVersionVector supported_versions;
   for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
@@ -746,6 +751,7 @@
       sent_time(QuicTime::Zero()),
       bytes_sent(0),
       nack_count(0),
+      transmission_type(NOT_RETRANSMISSION),
       all_transmissions(NULL),
       in_flight(false) { }
 
@@ -758,6 +764,7 @@
       sent_time(QuicTime::Zero()),
       bytes_sent(0),
       nack_count(0),
+      transmission_type(NOT_RETRANSMISSION),
       all_transmissions(new SequenceNumberSet),
       in_flight(false) {
   all_transmissions->insert(sequence_number);
@@ -767,38 +774,17 @@
     RetransmittableFrames* retransmittable_frames,
     QuicPacketSequenceNumber sequence_number,
     QuicSequenceNumberLength sequence_number_length,
+    TransmissionType transmission_type,
     SequenceNumberSet* all_transmissions)
     : retransmittable_frames(retransmittable_frames),
       sequence_number_length(sequence_number_length),
       sent_time(QuicTime::Zero()),
       bytes_sent(0),
       nack_count(0),
+      transmission_type(transmission_type),
       all_transmissions(all_transmissions),
       in_flight(false) {
   all_transmissions->insert(sequence_number);
 }
 
-QuicConsumedData::QuicConsumedData(size_t bytes_consumed,
-                                   bool fin_consumed)
-      : bytes_consumed(bytes_consumed),
-        fin_consumed(fin_consumed) {
-}
-
-ostream& operator<<(ostream& os, const QuicConsumedData& s) {
-  os << "bytes_consumed: " << s.bytes_consumed
-     << " fin_consumed: " << s.fin_consumed;
-  return os;
-}
-
-WriteResult::WriteResult()
-    : status(WRITE_STATUS_ERROR),
-      bytes_written(0) {
-}
-
-WriteResult::WriteResult(WriteStatus status,
-                         int bytes_written_or_error_code)
-    : status(status),
-      bytes_written(bytes_written_or_error_code) {
-}
-
 }  // namespace net
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 6fb423a..76b31f4 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -318,6 +318,9 @@
 //   MakeQuicTag('C', 'H', 'L', 'O');
 NET_EXPORT_PRIVATE QuicTag MakeQuicTag(char a, char b, char c, char d);
 
+// Returns true if the tag vector contains the specified tag.
+bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag);
+
 // Size in bytes of the data or fec packet header.
 NET_EXPORT_PRIVATE size_t GetPacketHeaderSize(const QuicPacketHeader& header);
 
@@ -451,8 +454,12 @@
   QUIC_INVALID_STREAM_FRAME = 50,
   // We received invalid data on the headers stream.
   QUIC_INVALID_HEADERS_STREAM_DATA = 56,
-  // The peer violated the flow control protocol.
-  QUIC_FLOW_CONTROL_ERROR = 59,
+  // The peer received too much data, violating flow control.
+  QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA = 59,
+  // The peer sent too much data, violating flow control.
+  QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA = 63,
+  // The peer received an invalid flow control window.
+  QUIC_FLOW_CONTROL_INVALID_WINDOW = 64,
   // The connection has been IP pooled into an existing connection.
   QUIC_CONNECTION_IP_POOLED = 62,
 
@@ -510,7 +517,7 @@
   QUIC_VERSION_NEGOTIATION_MISMATCH = 55,
 
   // No error. Used as bound while iterating.
-  QUIC_LAST_ERROR = 63,
+  QUIC_LAST_ERROR = 65,
 };
 
 struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
@@ -1027,6 +1034,7 @@
   TransmissionInfo(RetransmittableFrames* retransmittable_frames,
                    QuicPacketSequenceNumber sequence_number,
                    QuicSequenceNumberLength sequence_number_length,
+                   TransmissionType transmission_type,
                    SequenceNumberSet* all_transmissions);
 
   RetransmittableFrames* retransmittable_frames;
@@ -1036,6 +1044,8 @@
   // Zero when the packet is serialized, non-zero once it's sent.
   QuicByteCount bytes_sent;
   size_t nack_count;
+  // Reason why this packet was transmitted.
+  TransmissionType transmission_type;
   // Stores the sequence numbers of all transmissions of this packet.
   // Can never be null.
   SequenceNumberSet* all_transmissions;
@@ -1043,43 +1053,6 @@
   bool in_flight;
 };
 
-// A struct for functions which consume data payloads and fins.
-struct NET_EXPORT_PRIVATE QuicConsumedData {
-  QuicConsumedData(size_t bytes_consumed, bool fin_consumed);
-
-  // By default, gtest prints the raw bytes of an object. The bool data
-  // member causes this object to have padding bytes, which causes the
-  // default gtest object printer to read uninitialize memory. So we need
-  // to teach gtest how to print this object.
-  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
-      std::ostream& os, const QuicConsumedData& s);
-
-  // How many bytes were consumed.
-  size_t bytes_consumed;
-
-  // True if an incoming fin was consumed.
-  bool fin_consumed;
-};
-
-enum WriteStatus {
-  WRITE_STATUS_OK,
-  WRITE_STATUS_BLOCKED,
-  WRITE_STATUS_ERROR,
-};
-
-// A struct used to return the result of write calls including either the number
-// of bytes written or the error code, depending upon the status.
-struct NET_EXPORT_PRIVATE WriteResult {
-  WriteResult(WriteStatus status, int bytes_written_or_error_code);
-  WriteResult();
-
-  WriteStatus status;
-  union {
-    int bytes_written;  // only valid when status is OK
-    int error_code;  // only valid when status is ERROR
-  };
-};
-
 }  // namespace net
 
 #endif  // NET_QUIC_QUIC_PROTOCOL_H_
diff --git a/net/quic/quic_reliable_client_stream.cc b/net/quic/quic_reliable_client_stream.cc
index 6445ff2..4eb74d6 100644
--- a/net/quic/quic_reliable_client_stream.cc
+++ b/net/quic/quic_reliable_client_stream.cc
@@ -93,8 +93,7 @@
 }
 
 bool QuicReliableClientStream::CanWrite(const CompletionCallback& callback) {
-  bool can_write =  session()->connection()->CanWrite(
-      NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+  bool can_write =  session()->connection()->CanWrite(HAS_RETRANSMITTABLE_DATA);
   if (!can_write) {
     session()->MarkWriteBlocked(id(), EffectivePriority());
     DCHECK(callback_.is_null());
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index eaf66bd..8c41b9c 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -62,6 +62,7 @@
       is_server_(is_server),
       clock_(clock),
       stats_(stats),
+      debug_delegate_(NULL),
       send_algorithm_(
           SendAlgorithmInterface::Create(clock, &rtt_stats_, type, stats)),
       loss_algorithm_(LossDetectionInterface::Create(loss_type)),
@@ -69,6 +70,7 @@
       consecutive_rto_count_(0),
       consecutive_tlp_count_(0),
       consecutive_crypto_retransmission_count_(0),
+      pending_tlp_transmission_(false),
       max_tail_loss_probes_(kDefaultMaxTailLossProbes),
       using_pacing_(false) {
 }
@@ -82,7 +84,13 @@
     rtt_stats_.set_initial_rtt_us(min(kMaxInitialRoundTripTimeUs,
                                       config.ReceivedInitialRoundTripTimeUs()));
   }
-  if (config.congestion_control() == kPACE) {
+  // TODO(ianswett): BBR is currently a server only feature.
+  if (config.HasReceivedCongestionOptions() &&
+      ContainsQuicTag(config.ReceivedCongestionOptions(), kTBBR)) {
+    send_algorithm_.reset(
+        SendAlgorithmInterface::Create(clock_, &rtt_stats_, kTCPBBR, stats_));
+  }
+  if (config.congestion_feedback() == kPACE) {
     MaybeEnablePacing();
   }
   if (config.HasReceivedLossDetection() &&
@@ -106,9 +114,17 @@
 void QuicSentPacketManager::OnRetransmittedPacket(
     QuicPacketSequenceNumber old_sequence_number,
     QuicPacketSequenceNumber new_sequence_number) {
-  DCHECK(ContainsKey(pending_retransmissions_, old_sequence_number));
-
-  pending_retransmissions_.erase(old_sequence_number);
+  TransmissionType transmission_type;
+  PendingRetransmissionMap::iterator it =
+      pending_retransmissions_.find(old_sequence_number);
+  if (it != pending_retransmissions_.end()) {
+    transmission_type = it->second;
+    pending_retransmissions_.erase(it);
+  } else {
+    DLOG(DFATAL) << "Expected sequence number to be in "
+        "pending_retransmissions_.  sequence_number: " << old_sequence_number;
+    transmission_type = NOT_RETRANSMISSION;
+  }
 
   // A notifier may be waiting to hear about ACKs for the original sequence
   // number. Inform them that the sequence number has changed.
@@ -116,7 +132,8 @@
                                              new_sequence_number);
 
   unacked_packets_.OnRetransmittedPacket(old_sequence_number,
-                                         new_sequence_number);
+                                         new_sequence_number,
+                                         transmission_type);
 }
 
 void QuicSentPacketManager::OnIncomingAck(
@@ -269,6 +286,27 @@
   pending_retransmissions_[sequence_number] = transmission_type;
 }
 
+void QuicSentPacketManager::RecordSpuriousRetransmissions(
+    const SequenceNumberSet& all_transmissions,
+    QuicPacketSequenceNumber acked_sequence_number) {
+  for (SequenceNumberSet::const_iterator
+           it = all_transmissions.upper_bound(acked_sequence_number),
+           end = all_transmissions.end();
+       it != end;
+       ++it) {
+    const TransmissionInfo& retransmit_info =
+        unacked_packets_.GetTransmissionInfo(*it);
+
+    stats_->bytes_spuriously_retransmitted += retransmit_info.bytes_sent;
+    ++stats_->packets_spuriously_retransmitted;
+    if (debug_delegate_ != NULL) {
+      debug_delegate_->OnSpuriousPacketRetransmition(
+          retransmit_info.transmission_type,
+          retransmit_info.bytes_sent);
+    }
+  }
+}
+
 bool QuicSentPacketManager::HasPendingRetransmissions() const {
   return !pending_retransmissions_.empty();
 }
@@ -341,19 +379,22 @@
   // Remove the most recent packet, if it is pending retransmission.
   pending_retransmissions_.erase(newest_transmission);
 
+  // Notify observers about the ACKed packet.
+  {
+    // The AckNotifierManager needs to be notified about the most recent
+    // transmission, since that's the one only one it tracks.
+    ack_notifier_manager_.OnPacketAcked(newest_transmission,
+                                        delta_largest_observed);
+    if (newest_transmission != sequence_number) {
+      RecordSpuriousRetransmissions(*transmission_info.all_transmissions,
+                                    sequence_number);
+    }
+  }
+
   // Two cases for MarkPacketHandled:
   // 1) Handle the most recent or a crypto packet, so remove all transmissions.
   // 2) Handle old transmission, keep all other pending transmissions,
   //    but disassociate them from one another.
-  if (newest_transmission != sequence_number) {
-    stats_->bytes_spuriously_retransmitted += transmission_info.bytes_sent;
-    ++stats_->packets_spuriously_retransmitted;
-  }
-
-  // The AckNotifierManager needs to be notified about the most recent
-  // transmission, since that's the one only one it tracks.
-  ack_notifier_manager_.OnPacketAcked(newest_transmission,
-                                      delta_largest_observed);
 
   // If it's a crypto handshake packet, discard it and all retransmissions,
   // since they won't be acked now that one has been processed.
@@ -396,6 +437,7 @@
     HasRetransmittableData has_retransmittable_data) {
   DCHECK_LT(0u, sequence_number);
   LOG_IF(DFATAL, bytes == 0) << "Cannot send empty packets.";
+  pending_tlp_transmission_ = false;
   // In rare circumstances, the packet could be serialized, sent, and then acked
   // before OnPacketSent is called.
   if (!unacked_packets_.IsUnacked(sequence_number)) {
@@ -446,6 +488,7 @@
       // If no tail loss probe can be sent, because there are no retransmittable
       // packets, execute a conventional RTO to abandon old packets.
       ++stats_->tlp_count;
+      pending_tlp_transmission_ = true;
       RetransmitOldestPacket();
       return;
     case RTO_MODE:
@@ -497,12 +540,8 @@
 }
 
 void QuicSentPacketManager::RetransmitAllPackets() {
-  // Abandon all retransmittable packets and packets older than the
-  // retransmission delay.
-
-  DVLOG(1) << "OnRetransmissionTimeout() fired with "
+  DVLOG(1) << "RetransmitAllPackets() called with "
            << unacked_packets_.GetNumUnackedPackets() << " unacked packets.";
-
   // Request retransmission of all retransmittable packets when the RTO
   // fires, and let the congestion manager decide how many to send
   // immediately and the remaining packets will be queued.
@@ -605,11 +644,10 @@
 
 QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
     QuicTime now,
-    TransmissionType transmission_type,
     HasRetransmittableData retransmittable) {
   // The TLP logic is entirely contained within QuicSentPacketManager, so the
   // send algorithm does not need to be consulted.
-  if (transmission_type == TLP_RETRANSMISSION) {
+  if (pending_tlp_transmission_) {
     return QuicTime::Delta::Zero();
   }
   return send_algorithm_->TimeUntilSend(
@@ -731,10 +769,11 @@
     return;
   }
 
+  // Set up a pacing sender with a 5 millisecond alarm granularity.
   using_pacing_ = true;
   send_algorithm_.reset(
       new PacingSender(send_algorithm_.release(),
-                       QuicTime::Delta::FromMicroseconds(1)));
+                       QuicTime::Delta::FromMilliseconds(5)));
 }
 
 }  // namespace net
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h
index d65e361..395d212 100644
--- a/net/quic/quic_sent_packet_manager.h
+++ b/net/quic/quic_sent_packet_manager.h
@@ -41,6 +41,19 @@
 // previous transmission is acked, the data will not be retransmitted.
 class NET_EXPORT_PRIVATE QuicSentPacketManager {
  public:
+  // Interface which gets callbacks from the QuicSentPacketManager at
+  // interesting points.  Implementations must not mutate the state of
+  // the packet manager or connection as a result of these callbacks.
+  class NET_EXPORT_PRIVATE DebugDelegate {
+   public:
+    virtual ~DebugDelegate() {}
+
+    // Called when a spurious retransmission is detected.
+    virtual void OnSpuriousPacketRetransmition(
+        TransmissionType transmission_type,
+        QuicByteCount byte_size) {}
+  };
+
   // Struct to store the pending retransmission information.
   struct PendingRetransmission {
     PendingRetransmission(QuicPacketSequenceNumber sequence_number,
@@ -133,7 +146,6 @@
   // Note 2: Send algorithms may or may not use |retransmit| in their
   // calculations.
   virtual QuicTime::Delta TimeUntilSend(QuicTime now,
-                                        TransmissionType transmission_type,
                                         HasRetransmittableData retransmittable);
 
   // Returns amount of time for delayed ack timer.
@@ -160,6 +172,10 @@
 
   bool using_pacing() const { return using_pacing_; }
 
+  void set_debug_delegate(DebugDelegate* debug_delegate) {
+    debug_delegate_ = debug_delegate;
+  }
+
  private:
   friend class test::QuicConnectionPeer;
   friend class test::QuicSentPacketManagerPeer;
@@ -240,6 +256,11 @@
   void MarkForRetransmission(QuicPacketSequenceNumber sequence_number,
                              TransmissionType transmission_type);
 
+  // Notify observers about spurious retransmits.
+  void RecordSpuriousRetransmissions(
+      const SequenceNumberSet& all_transmissions,
+      QuicPacketSequenceNumber acked_sequence_number);
+
   // Newly serialized retransmittable and fec packets are added to this map,
   // which contains owning pointers to any contained frames.  If a packet is
   // retransmitted, this map will contain entries for both the old and the new
@@ -263,6 +284,7 @@
 
   const QuicClock* clock_;
   QuicConnectionStats* stats_;
+  DebugDelegate* debug_delegate_;
   RttStats rtt_stats_;
   scoped_ptr<SendAlgorithmInterface> send_algorithm_;
   scoped_ptr<LossDetectionInterface> loss_algorithm_;
@@ -274,6 +296,8 @@
   size_t consecutive_tlp_count_;
   // Number of times the crypto handshake has been retransmitted.
   size_t consecutive_crypto_retransmission_count_;
+  // Whether a tlp packet can be sent even if the send algorithm says not to.
+  bool pending_tlp_transmission_;
   // Maximum number of tail loss probes to send before firing an RTO.
   size_t max_tail_loss_probes_;
   bool using_pacing_;
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index b3c1fdc..ef13a22 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -32,6 +32,13 @@
   return std::tr1::get<0>(arg).first == std::tr1::get<1>(arg);
 }
 
+class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate {
+ public:
+  MOCK_METHOD2(OnSpuriousPacketRetransmition,
+               void(TransmissionType transmission_type,
+                    QuicByteCount byte_size));
+};
+
 class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
  protected:
   QuicSentPacketManagerTest()
@@ -129,7 +136,8 @@
     EXPECT_EQ(old_sequence_number, next_retransmission.sequence_number);
     EXPECT_EQ(TLP_RETRANSMISSION,
               next_retransmission.transmission_type);
-    manager_.OnRetransmittedPacket(old_sequence_number, new_sequence_number);
+    manager_.OnRetransmittedPacket(old_sequence_number,
+                                   new_sequence_number);
     EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(
         &manager_, new_sequence_number));
   }
@@ -232,8 +240,8 @@
                     .Times(1).WillOnce(Return(true));
     const QuicSentPacketManager::PendingRetransmission pending =
         manager_.NextPendingRetransmission();
-    manager_.OnRetransmittedPacket(
-        pending.sequence_number, retransmission_sequence_number);
+    manager_.OnRetransmittedPacket(pending.sequence_number,
+                                   retransmission_sequence_number);
     manager_.OnPacketSent(retransmission_sequence_number, clock_.Now(),
                           kDefaultLength, pending.transmission_type,
                           HAS_RETRANSMITTABLE_DATA);
@@ -428,6 +436,11 @@
 }
 
 TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
+  StrictMock<MockDebugDelegate> debug_delegate;
+  EXPECT_CALL(debug_delegate, OnSpuriousPacketRetransmition(
+      TLP_RETRANSMISSION, kDefaultLength)).Times(2);
+  manager_.set_debug_delegate(&debug_delegate);
+
   SendDataPacket(1);
   RetransmitAndSendPacket(1, 2);
   RetransmitAndSendPacket(2, 3);
@@ -465,7 +478,7 @@
 
   VerifyUnackedPackets(NULL, 0);
   EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
-  EXPECT_EQ(1u, stats_.packets_spuriously_retransmitted);
+  EXPECT_EQ(2u, stats_.packets_spuriously_retransmitted);
 }
 
 TEST_F(QuicSentPacketManagerTest, LoseButDontRetransmitRevivedPacket) {
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 9b28103..e0bddfe 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -118,8 +118,8 @@
     max_flow_control_receive_window_bytes_ = kDefaultFlowControlSendWindow;
   }
   flow_controller_.reset(new QuicFlowController(
-      connection_->supported_versions().front(), 0, is_server(),
-      kDefaultFlowControlSendWindow, max_flow_control_receive_window_bytes_,
+      connection_.get(), 0, is_server(), kDefaultFlowControlSendWindow,
+      max_flow_control_receive_window_bytes_,
       max_flow_control_receive_window_bytes_));
 
   connection_->set_visitor(visitor_shim_.get());
@@ -422,7 +422,7 @@
           << "Peer sent us an invalid flow control send window: "
           << new_flow_control_send_window
           << ", below default: " << kDefaultFlowControlSendWindow;
-      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR);
+      connection_->SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW);
       return;
     }
     DataStreamMap::iterator it = stream_map_.begin();
@@ -643,6 +643,15 @@
   if (version < QUIC_VERSION_19) {
     flow_controller_->Disable();
   }
+
+  // Inform all streams about the negotiated version. They may have been created
+  // with a different version.
+  for (DataStreamMap::iterator it = stream_map_.begin();
+       it != stream_map_.end(); ++it) {
+    if (version < QUIC_VERSION_17) {
+      it->second->flow_controller()->Disable();
+    }
+  }
 }
 
 }  // namespace net
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index d23b684..b9ce0de 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -175,8 +175,6 @@
     return connection_->connection_id();
   }
 
-  QuicPacketCreator::Options* options() { return connection()->options(); }
-
   // Returns the number of currently open streams, including those which have
   // been implicitly created, but excluding the reserved headers and crypto
   // streams.
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index 92c3cab..b70be5a 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -168,6 +168,8 @@
     return WritevData(id, IOVector(), 0, true, NULL);
   }
 
+  using QuicSession::PostProcessAfterData;
+
  private:
   StrictMock<TestCryptoStream> crypto_stream_;
 
@@ -661,7 +663,8 @@
       session_.config()->ProcessPeerHello(msg, CLIENT, &error_details);
   EXPECT_EQ(QUIC_NO_ERROR, error);
 
-  EXPECT_CALL(*connection_, SendConnectionClose(QUIC_FLOW_CONTROL_ERROR));
+  EXPECT_CALL(*connection_,
+              SendConnectionClose(QUIC_FLOW_CONTROL_INVALID_WINDOW));
   session_.OnConfigNegotiated();
 }
 
@@ -676,6 +679,101 @@
             session.max_flow_control_receive_window_bytes());
 }
 
+TEST_P(QuicSessionTest, ConnectionFlowControlAccountingRstOutOfOrder) {
+  FLAGS_enable_quic_stream_flow_control_2 = true;
+  FLAGS_enable_quic_connection_flow_control = true;
+  if (version() < QUIC_VERSION_19) {
+    return;
+  }
+
+  // Test that when we receive an out of order stream RST we correctly adjust
+  // our connection level flow control receive window.
+  // On close, the stream should mark as consumed all bytes between the highest
+  // byte consumed so far and the final byte offset from the RST frame.
+  TestStream* stream = session_.CreateOutgoingDataStream();
+
+  const QuicStreamOffset kByteOffset = 1 + kInitialFlowControlWindowForTest / 2;
+  // Expect no stream WINDOW_UPDATE frames, as stream read side closed.
+  EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0);
+  // We do expect a connection level WINDOW_UPDATE when the stream is reset.
+  EXPECT_CALL(*connection_,
+              SendWindowUpdate(
+                  0, kInitialFlowControlWindowForTest + kByteOffset)).Times(1);
+
+  QuicRstStreamFrame rst_frame(stream->id(), QUIC_STREAM_CANCELLED,
+                               kByteOffset);
+  session_.OnRstStream(rst_frame);
+  session_.PostProcessAfterData();
+  EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
+}
+
+TEST_P(QuicSessionTest, ConnectionFlowControlAccountingFinAndLocalReset) {
+  FLAGS_enable_quic_stream_flow_control_2 = true;
+  FLAGS_enable_quic_connection_flow_control = true;
+  if (version() < QUIC_VERSION_19) {
+    return;
+  }
+
+  // Test the situation where we receive a FIN on a stream, and before we fully
+  // consume all the data from the sequencer buffer we locally RST the stream.
+  // The bytes between highest consumed byte, and the final byte offset that we
+  // determined when the FIN arrived, should be marked as consumed at the
+  // connection level flow controller when the stream is reset.
+  TestStream* stream = session_.CreateOutgoingDataStream();
+
+  const QuicStreamOffset kByteOffset = 1 + kInitialFlowControlWindowForTest / 2;
+  QuicStreamFrame frame(stream->id(), true, kByteOffset, IOVector());
+  vector<QuicStreamFrame> frames;
+  frames.push_back(frame);
+  session_.OnStreamFrames(frames);
+  session_.PostProcessAfterData();
+
+  EXPECT_EQ(0u, stream->flow_controller()->bytes_consumed());
+  EXPECT_EQ(kByteOffset,
+            stream->flow_controller()->highest_received_byte_offset());
+
+  // Expect no stream WINDOW_UPDATE frames, as stream read side closed.
+  EXPECT_CALL(*connection_, SendWindowUpdate(stream->id(), _)).Times(0);
+  // We do expect a connection level WINDOW_UPDATE when the stream is reset.
+  EXPECT_CALL(*connection_,
+              SendWindowUpdate(
+                  0, kInitialFlowControlWindowForTest + kByteOffset)).Times(1);
+
+  // Reset stream locally.
+  stream->Reset(QUIC_STREAM_CANCELLED);
+
+  EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
+}
+
+TEST_P(QuicSessionTest, VersionNegotiationDisablesFlowControl) {
+  ValueRestore<bool> old_stream_flag(
+      &FLAGS_enable_quic_stream_flow_control_2, true);
+  ValueRestore<bool> old_connection_flag(
+      &FLAGS_enable_quic_connection_flow_control, true);
+  if (version() < QUIC_VERSION_19) {
+    return;
+  }
+
+  // Test that after successful version negotiation, flow control is disabled
+  // appropriately at both the connection and stream level.
+
+  // Initially both stream and connection flow control are enabled.
+  TestStream* stream = session_.CreateOutgoingDataStream();
+  EXPECT_TRUE(stream->flow_controller()->IsEnabled());
+  EXPECT_TRUE(session_.flow_controller()->IsEnabled());
+
+  // Version 17 implies that stream flow control is enabled, but connection
+  // level is disabled.
+  session_.OnSuccessfulVersionNegotiation(QUIC_VERSION_17);
+  EXPECT_FALSE(session_.flow_controller()->IsEnabled());
+  EXPECT_TRUE(stream->flow_controller()->IsEnabled());
+
+  // Version 16 means all flow control is disabled.
+  session_.OnSuccessfulVersionNegotiation(QUIC_VERSION_16);
+  EXPECT_FALSE(session_.flow_controller()->IsEnabled());
+  EXPECT_FALSE(stream->flow_controller()->IsEnabled());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 152d70b..52c7168 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -120,6 +120,13 @@
       QuicServerInfo* server_info,
       const BoundNetLog& net_log);
 
+  // Creates a new job to handle the resumption of for connecting an
+  // existing session.
+  Job(QuicStreamFactory* factory,
+      HostResolver* host_resolver,
+      QuicClientSession* session,
+      QuicServerId server_id);
+
   ~Job();
 
   int Run(const CompletionCallback& callback);
@@ -130,6 +137,7 @@
   int DoLoadServerInfo();
   int DoLoadServerInfoComplete(int rv);
   int DoConnect();
+  int DoResumeConnect();
   int DoConnectComplete(int rv);
 
   void OnIOComplete(int rv);
@@ -150,6 +158,7 @@
     STATE_LOAD_SERVER_INFO,
     STATE_LOAD_SERVER_INFO_COMPLETE,
     STATE_CONNECT,
+    STATE_RESUME_CONNECT,
     STATE_CONNECT_COMPLETE,
   };
   IoState io_state_;
@@ -178,7 +187,8 @@
                             base::StringPiece method,
                             QuicServerInfo* server_info,
                             const BoundNetLog& net_log)
-    : factory_(factory),
+    : io_state_(STATE_RESOLVE_HOST),
+      factory_(factory),
       host_resolver_(host_resolver),
       server_id_(host_port_pair, is_https, privacy_mode),
       is_post_(method == "POST"),
@@ -189,11 +199,24 @@
       session_(NULL),
       weak_factory_(this) {}
 
+QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
+                            HostResolver* host_resolver,
+                            QuicClientSession* session,
+                            QuicServerId server_id)
+    : io_state_(STATE_RESUME_CONNECT),
+      factory_(factory),
+      host_resolver_(host_resolver),  // unused
+      server_id_(server_id),
+      is_post_(false),  // unused
+      was_alternate_protocol_recently_broken_(false),  // unused
+      net_log_(session->net_log()),  // unused
+      session_(session),
+      weak_factory_(this) {}
+
 QuicStreamFactory::Job::~Job() {
 }
 
 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
-  io_state_ = STATE_RESOLVE_HOST;
   int rv = DoLoop(OK);
   if (rv == ERR_IO_PENDING)
     callback_ = callback;
@@ -224,6 +247,10 @@
         CHECK_EQ(OK, rv);
         rv = DoConnect();
         break;
+      case STATE_RESUME_CONNECT:
+        CHECK_EQ(OK, rv);
+        rv = DoResumeConnect();
+        break;
       case STATE_CONNECT_COMPLETE:
         rv = DoConnectComplete(rv);
         break;
@@ -326,6 +353,16 @@
   return rv;
 }
 
+int QuicStreamFactory::Job::DoResumeConnect() {
+  io_state_ = STATE_CONNECT_COMPLETE;
+
+  int rv = session_->ResumeCryptoConnect(
+      base::Bind(&QuicStreamFactory::Job::OnIOComplete,
+                 base::Unretained(this)));
+
+  return rv;
+}
+
 int QuicStreamFactory::Job::DoConnectComplete(int rv) {
   if (rv != OK)
     return rv;
@@ -401,6 +438,7 @@
     QuicRandom* random_generator,
     QuicClock* clock,
     size_t max_packet_length,
+    const std::string& user_agent_id,
     const QuicVersionVector& supported_versions,
     bool enable_port_selection,
     bool enable_pacing,
@@ -429,6 +467,7 @@
       QuicTime::Delta::FromSeconds(30));
 
   crypto_config_.SetDefaults();
+  crypto_config_.set_user_agent_id(user_agent_id);
   crypto_config_.AddCanonicalSuffix(".c.youtube.com");
   crypto_config_.AddCanonicalSuffix(".googlevideo.com");
   crypto_config_.SetProofVerifier(new ProofVerifierChromium(cert_verifier));
@@ -603,6 +642,35 @@
   all_sessions_.erase(session);
 }
 
+void QuicStreamFactory::OnSessionConnectTimeout(
+    QuicClientSession* session) {
+  const AliasSet& aliases = session_aliases_[session];
+  for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end();
+       ++it) {
+    DCHECK(active_sessions_.count(*it));
+    DCHECK_EQ(session, active_sessions_[*it]);
+    active_sessions_.erase(*it);
+  }
+
+  if (aliases.empty()) {
+    return;
+  }
+
+  const IpAliasKey ip_alias_key(session->connection()->peer_address(),
+                                aliases.begin()->is_https());
+  ip_aliases_[ip_alias_key].erase(session);
+  if (ip_aliases_[ip_alias_key].empty()) {
+    ip_aliases_.erase(ip_alias_key);
+  }
+  QuicServerId server_id = *aliases.begin();
+  session_aliases_.erase(session);
+  Job* job = new Job(this, host_resolver_, session, server_id);
+  active_jobs_[server_id] = job;
+  int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
+                               base::Unretained(this), job));
+  DCHECK_EQ(ERR_IO_PENDING, rv);
+}
+
 void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
   DCHECK(ContainsKey(active_requests_, request));
   Job* job = active_requests_[request];
@@ -749,7 +817,7 @@
       new QuicConnection(connection_id, addr, helper_.get(), writer.get(),
                          false, supported_versions_);
   writer->SetConnection(connection);
-  connection->options()->max_packet_length = max_packet_length_;
+  connection->set_max_packet_length(max_packet_length_);
 
   InitializeCachedStateInCryptoConfig(server_id, server_info);
 
@@ -769,7 +837,9 @@
   *session = new QuicClientSession(
       connection, socket.Pass(), writer.Pass(), this,
       quic_crypto_client_stream_factory_, server_info.Pass(), server_id,
-      config, kInitialReceiveWindowSize, &crypto_config_, net_log.net_log());
+      config, kInitialReceiveWindowSize, &crypto_config_,
+      base::MessageLoop::current()->message_loop_proxy().get(),
+      net_log.net_log());
   all_sessions_[*session] = server_id;  // owning pointer
   return OK;
 }
@@ -782,6 +852,7 @@
     const QuicServerId& server_id,
     QuicClientSession* session) {
   DCHECK(!HasActiveSession(server_id));
+  UMA_HISTOGRAM_COUNTS("Net.QuicActiveSessions", active_sessions_.size());
   active_sessions_[server_id] = session;
   session_aliases_[session].insert(server_id);
   const IpAliasKey ip_alias_key(session->connection()->peer_address(),
@@ -834,16 +905,39 @@
   UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
                        stats.packets_received);
 
-  if (session_was_active) {
-    // TODO(rch):  In the special case where the session has received no
-    // packets from the peer, we should consider blacklisting this
-    // differently so that we still race TCP but we don't consider the
-    // session connected until the handshake has been confirmed.
-    HistogramBrokenAlternateProtocolLocation(
-        BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
-    http_server_properties_->SetBrokenAlternateProtocol(
-        server_id.host_port_pair());
-  }
+  if (!session_was_active)
+    return;
+
+  const HostPortPair& server = server_id.host_port_pair();
+  // Don't try to change the alternate-protocol state, if the
+  // alternate-protocol state is unknown.
+  if (!http_server_properties_->HasAlternateProtocol(server))
+    return;
+
+  // TODO(rch):  In the special case where the session has received no
+  // packets from the peer, we should consider blacklisting this
+  // differently so that we still race TCP but we don't consider the
+  // session connected until the handshake has been confirmed.
+  HistogramBrokenAlternateProtocolLocation(
+      BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
+  PortAlternateProtocolPair alternate =
+      http_server_properties_->GetAlternateProtocol(server);
+  DCHECK_EQ(QUIC, alternate.protocol);
+
+  // Since the session was active, there's no longer an
+  // HttpStreamFactoryImpl::Job running which can mark it broken, unless the
+  // TCP job also fails. So to avoid not using QUIC when we otherwise could,
+  // we mark it as broken, and then immediately re-enable it. This leaves
+  // QUIC as "recently broken" which means that 0-RTT will be disabled but
+  // we'll still race.
+  http_server_properties_->SetBrokenAlternateProtocol(server);
+  http_server_properties_->ClearAlternateProtocol(server);
+  http_server_properties_->SetAlternateProtocol(
+      server, alternate.port, alternate.protocol);
+  DCHECK_EQ(QUIC,
+            http_server_properties_->GetAlternateProtocol(server).protocol);
+  DCHECK(http_server_properties_->WasAlternateProtocolRecentlyBroken(
+      server));
 }
 
 }  // namespace net
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 97da453..cc79285 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -95,6 +95,7 @@
       QuicRandom* random_generator,
       QuicClock* clock,
       size_t max_packet_length,
+      const std::string& user_agent_id,
       const QuicVersionVector& supported_versions,
       bool enable_port_selection,
       bool enable_pacing,
@@ -125,6 +126,9 @@
   // Called by a session after it shuts down.
   void OnSessionClosed(QuicClientSession* session);
 
+  // Called by a session whose connection has timed out.
+  void OnSessionConnectTimeout(QuicClientSession* session);
+
   // Cancels a pending request.
   void CancelRequest(QuicStreamRequest* request);
 
@@ -158,6 +162,10 @@
 
   bool enable_port_selection() const { return enable_port_selection_; }
 
+  bool has_quic_server_info_factory() {
+    return quic_server_info_factory_ != NULL;
+  }
+
   void set_quic_server_info_factory(
       QuicServerInfoFactory* quic_server_info_factory) {
     DCHECK(!quic_server_info_factory_);
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 8189989..f50c387 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -90,10 +90,9 @@
         clock_(new MockClock()),
         cert_verifier_(CertVerifier::CreateDefault()),
         factory_(&host_resolver_, &socket_factory_,
-                 base::WeakPtr<HttpServerProperties>(),
-                 cert_verifier_.get(),
-                 &crypto_client_stream_factory_,
-                 &random_generator_, clock_, kDefaultMaxPacketSize,
+                 base::WeakPtr<HttpServerProperties>(), cert_verifier_.get(),
+                 &crypto_client_stream_factory_, &random_generator_, clock_,
+                 kDefaultMaxPacketSize, std::string(),
                  SupportedVersions(GetParam()), true, true, true),
         host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
         is_https_(false),
diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc
index 61b4f7c..d0b6933 100644
--- a/net/quic/quic_stream_sequencer.cc
+++ b/net/quic/quic_stream_sequencer.cc
@@ -68,7 +68,6 @@
     }
     num_bytes_consumed_ += bytes_consumed;
     stream_->AddBytesConsumed(bytes_consumed);
-    stream_->MaybeSendWindowUpdate();
 
     if (MaybeCloseStream()) {
       return true;
@@ -95,7 +94,6 @@
         byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len)));
     byte_offset += iov.iov_len;
     num_bytes_buffered_ += iov.iov_len;
-    stream_->AddBytesBuffered(iov.iov_len);
   }
   return true;
 }
@@ -248,8 +246,6 @@
   num_bytes_buffered_ -= bytes_consumed;
 
   stream_->AddBytesConsumed(bytes_consumed);
-  stream_->RemoveBytesBuffered(bytes_consumed);
-  stream_->MaybeSendWindowUpdate();
 }
 
 }  // namespace net
diff --git a/net/quic/quic_types.cc b/net/quic/quic_types.cc
new file mode 100644
index 0000000..cdfb36d
--- /dev/null
+++ b/net/quic/quic_types.cc
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_types.h"
+
+using std::ostream;
+
+namespace net {
+
+QuicConsumedData::QuicConsumedData(size_t bytes_consumed,
+                                   bool fin_consumed)
+      : bytes_consumed(bytes_consumed),
+        fin_consumed(fin_consumed) {
+}
+
+ostream& operator<<(ostream& os, const QuicConsumedData& s) {
+  os << "bytes_consumed: " << s.bytes_consumed
+     << " fin_consumed: " << s.fin_consumed;
+  return os;
+}
+
+WriteResult::WriteResult()
+    : status(WRITE_STATUS_ERROR),
+      bytes_written(0) {
+}
+
+WriteResult::WriteResult(WriteStatus status,
+                         int bytes_written_or_error_code)
+    : status(status),
+      bytes_written(bytes_written_or_error_code) {
+}
+
+}  // namespace net
diff --git a/net/quic/quic_types.h b/net/quic/quic_types.h
new file mode 100644
index 0000000..01415bc
--- /dev/null
+++ b/net/quic/quic_types.h
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_TYPES_H_
+#define NET_QUIC_QUIC_TYPES_H_
+
+// This header defines some basic types that don't depend on quic_protocol.h,
+// so that classes not directly related to the protocol wire format can avoid
+// including quic_protocol.h.
+
+#include <stddef.h>
+#include <ostream>
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// A struct for functions which consume data payloads and fins.
+struct NET_EXPORT_PRIVATE QuicConsumedData {
+  QuicConsumedData(size_t bytes_consumed, bool fin_consumed);
+
+  // By default, gtest prints the raw bytes of an object. The bool data
+  // member causes this object to have padding bytes, which causes the
+  // default gtest object printer to read uninitialize memory. So we need
+  // to teach gtest how to print this object.
+  NET_EXPORT_PRIVATE friend std::ostream& operator<<(
+      std::ostream& os, const QuicConsumedData& s);
+
+  // How many bytes were consumed.
+  size_t bytes_consumed;
+
+  // True if an incoming fin was consumed.
+  bool fin_consumed;
+};
+
+// QuicAsyncStatus enumerates the possible results of an asynchronous
+// operation.
+enum QuicAsyncStatus {
+  QUIC_SUCCESS = 0,
+  QUIC_FAILURE = 1,
+  // QUIC_PENDING results from an operation that will occur asynchonously. When
+  // the operation is complete, a callback's |Run| method will be called.
+  QUIC_PENDING = 2,
+};
+
+// TODO(wtc): see if WriteStatus can be replaced by QuicAsyncStatus.
+enum WriteStatus {
+  WRITE_STATUS_OK,
+  WRITE_STATUS_BLOCKED,
+  WRITE_STATUS_ERROR,
+};
+
+// A struct used to return the result of write calls including either the number
+// of bytes written or the error code, depending upon the status.
+struct NET_EXPORT_PRIVATE WriteResult {
+  WriteResult(WriteStatus status, int bytes_written_or_error_code);
+  WriteResult();
+
+  WriteStatus status;
+  union {
+    int bytes_written;  // only valid when status is WRITE_STATUS_OK
+    int error_code;  // only valid when status is WRITE_STATUS_ERROR
+  };
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_TYPES_H_
diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc
index b230485..e9dd136 100644
--- a/net/quic/quic_unacked_packet_map.cc
+++ b/net/quic/quic_unacked_packet_map.cc
@@ -57,7 +57,8 @@
 
 void QuicUnackedPacketMap::OnRetransmittedPacket(
     QuicPacketSequenceNumber old_sequence_number,
-    QuicPacketSequenceNumber new_sequence_number) {
+    QuicPacketSequenceNumber new_sequence_number,
+    TransmissionType transmission_type) {
   DCHECK(ContainsKey(unacked_packets_, old_sequence_number));
   DCHECK(unacked_packets_.empty() ||
          unacked_packets_.rbegin()->first < new_sequence_number);
@@ -77,6 +78,7 @@
       TransmissionInfo(frames,
                        new_sequence_number,
                        transmission_info->sequence_number_length,
+                       transmission_type,
                        transmission_info->all_transmissions);
 }
 
diff --git a/net/quic/quic_unacked_packet_map.h b/net/quic/quic_unacked_packet_map.h
index 0263422..ae72548 100644
--- a/net/quic/quic_unacked_packet_map.h
+++ b/net/quic/quic_unacked_packet_map.h
@@ -27,7 +27,8 @@
   // retransmittable data associated with it. |new_sequence_number| will
   // be both unacked and associated with retransmittable data.
   void OnRetransmittedPacket(QuicPacketSequenceNumber old_sequence_number,
-                             QuicPacketSequenceNumber new_sequence_number);
+                             QuicPacketSequenceNumber new_sequence_number,
+                             TransmissionType transmission_type);
 
   // Returns true if the packet |sequence_number| is unacked.
   bool IsUnacked(QuicPacketSequenceNumber sequence_number) const;
diff --git a/net/quic/quic_unacked_packet_map_test.cc b/net/quic/quic_unacked_packet_map_test.cc
index 0ff0cf0..c5264fd 100644
--- a/net/quic/quic_unacked_packet_map_test.cc
+++ b/net/quic/quic_unacked_packet_map_test.cc
@@ -130,7 +130,7 @@
   // transmission being acked.
   unacked_packets_.AddPacket(CreateRetransmittablePacket(1));
   unacked_packets_.SetSent(1, now_, kDefaultLength, true);
-  unacked_packets_.OnRetransmittedPacket(1, 2);
+  unacked_packets_.OnRetransmittedPacket(1, 2, LOSS_RETRANSMISSION);
   unacked_packets_.SetSent(2, now_, kDefaultLength, true);
 
   QuicPacketSequenceNumber unacked[] = { 1, 2 };
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc
index 3abc226..ae4bb2e 100644
--- a/net/quic/quic_utils.cc
+++ b/net/quic/quic_utils.cc
@@ -202,7 +202,9 @@
     RETURN_STRING_LITERAL(QUIC_PACKET_READ_ERROR);
     RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_FRAME);
     RETURN_STRING_LITERAL(QUIC_INVALID_HEADERS_STREAM_DATA);
-    RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_ERROR);
+    RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
+    RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
+    RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_INVALID_WINDOW);
     RETURN_STRING_LITERAL(QUIC_CONNECTION_IP_POOLED);
     RETURN_STRING_LITERAL(QUIC_PROOF_INVALID);
     RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG);
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index aefdb41..b73185b 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -124,7 +124,7 @@
       rst_sent_(false),
       is_server_(session_->is_server()),
       flow_controller_(
-          session_->connection()->version(),
+          session_->connection(),
           id_,
           is_server_,
           session_->config()->HasReceivedInitialFlowControlWindowBytes() ?
@@ -151,23 +151,22 @@
   }
 
   // This count include duplicate data received.
-  stream_bytes_read_ += frame.data.TotalBufferSize();
+  size_t frame_payload_size = frame.data.TotalBufferSize();
+  stream_bytes_read_ += frame_payload_size;
 
-  bool accepted = sequencer_.OnStreamFrame(frame);
-
-  if (flow_controller_.FlowControlViolation() ||
-      connection_flow_controller_->FlowControlViolation()) {
-    session_->connection()->SendConnectionClose(QUIC_FLOW_CONTROL_ERROR);
-    return false;
+  // Flow control is interested in tracking highest received offset.
+  if (MaybeIncreaseHighestReceivedOffset(frame.offset + frame_payload_size)) {
+    // As the highest received offset has changed, we should check to see if
+    // this is a violation of flow control.
+    if (flow_controller_.FlowControlViolation() ||
+        connection_flow_controller_->FlowControlViolation()) {
+      session_->connection()->SendConnectionClose(
+          QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
+      return false;
+    }
   }
-  MaybeSendWindowUpdate();
 
-  return accepted;
-}
-
-void ReliableQuicStream::MaybeSendWindowUpdate() {
-  flow_controller_.MaybeSendWindowUpdate(session()->connection());
-  connection_flow_controller_->MaybeSendWindowUpdate(session()->connection());
+  return sequencer_.OnStreamFrame(frame);
 }
 
 int ReliableQuicStream::num_frames_received() const {
@@ -179,6 +178,8 @@
 }
 
 void ReliableQuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
+  MaybeIncreaseHighestReceivedOffset(frame.byte_offset);
+
   stream_error_ = frame.error_code;
   CloseWriteSide();
   CloseReadSide();
@@ -298,8 +299,8 @@
 }
 
 void ReliableQuicStream::MaybeSendBlocked() {
-  flow_controller_.MaybeSendBlocked(session()->connection());
-  connection_flow_controller_->MaybeSendBlocked(session()->connection());
+  flow_controller_.MaybeSendBlocked();
+  connection_flow_controller_->MaybeSendBlocked();
   // If we are connection level flow control blocked, then add the stream
   // to the write blocked list. It will be given a chance to write when a
   // connection level WINDOW_UPDATE arrives.
@@ -417,6 +418,14 @@
                             stream_bytes_written_);
     rst_sent_ = true;
   }
+
+  // We are closing the stream and will not process any further incoming bytes.
+  // As there may be more bytes in flight and we need to ensure that both
+  // endpoints have the same connection level flow control state, mark all
+  // unreceived or buffered bytes as consumed.
+  uint64 bytes_to_consume = flow_controller_.highest_received_byte_offset() -
+      flow_controller_.bytes_consumed();
+  AddBytesConsumed(bytes_to_consume);
 }
 
 void ReliableQuicStream::OnWindowUpdateFrame(
@@ -436,18 +445,21 @@
   }
 }
 
-void ReliableQuicStream::AddBytesBuffered(uint64 bytes) {
+bool ReliableQuicStream::MaybeIncreaseHighestReceivedOffset(uint64 new_offset) {
   if (flow_controller_.IsEnabled()) {
-    flow_controller_.AddBytesBuffered(bytes);
-    connection_flow_controller_->AddBytesBuffered(bytes);
+    uint64 increment =
+        new_offset - flow_controller_.highest_received_byte_offset();
+    if (flow_controller_.UpdateHighestReceivedOffset(new_offset)) {
+      // If |new_offset| increased the stream flow controller's highest received
+      // offset, then we need to increase the connection flow controller's value
+      // by the incremental difference.
+      connection_flow_controller_->UpdateHighestReceivedOffset(
+          connection_flow_controller_->highest_received_byte_offset() +
+          increment);
+      return true;
+    }
   }
-}
-
-void ReliableQuicStream::RemoveBytesBuffered(uint64 bytes) {
-  if (flow_controller_.IsEnabled()) {
-    flow_controller_.RemoveBytesBuffered(bytes);
-    connection_flow_controller_->RemoveBytesBuffered(bytes);
-  }
+  return false;
 }
 
 void ReliableQuicStream::AddBytesSent(uint64 bytes) {
@@ -459,7 +471,11 @@
 
 void ReliableQuicStream::AddBytesConsumed(uint64 bytes) {
   if (flow_controller_.IsEnabled()) {
-    flow_controller_.AddBytesConsumed(bytes);
+    // Only adjust stream level flow controller if we are still reading.
+    if (!read_side_closed_) {
+      flow_controller_.AddBytesConsumed(bytes);
+    }
+
     connection_flow_controller_->AddBytesConsumed(bytes);
   }
 }
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h
index 90cdac4..9d8fe88 100644
--- a/net/quic/reliable_quic_stream.h
+++ b/net/quic/reliable_quic_stream.h
@@ -20,6 +20,7 @@
 #include "net/quic/quic_flow_controller.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_stream_sequencer.h"
+#include "net/quic/quic_types.h"
 
 namespace net {
 
@@ -92,24 +93,20 @@
   // Adjust our flow control windows according to new offset in |frame|.
   virtual void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame);
 
-  // If our receive window has dropped below the threshold, then send a
-  // WINDOW_UPDATE frame. This is called whenever bytes are consumed from the
-  // sequencer's buffer.
-  void MaybeSendWindowUpdate();
-
   int num_frames_received() const;
 
   int num_duplicate_frames_received() const;
 
   QuicFlowController* flow_controller() { return &flow_controller_; }
 
-  // Called by the stream sequeuncer as bytes are added to the buffer.
-  void AddBytesBuffered(uint64 bytes);
-  // Called by the stream sequeuncer as bytes are removed from the buffer.
-  void RemoveBytesBuffered(uint64 bytes);
+  // Called when we see a frame which could increase the highest offset.
+  // Returns true if the highest offset did increase.
+  bool MaybeIncreaseHighestReceivedOffset(uint64 new_offset);
   // Called when bytese are sent to the peer.
   void AddBytesSent(uint64 bytes);
-  // Called by the stream sequeuncer as bytes are consumed from the buffer.
+  // Called by the stream sequencer as bytes are consumed from the buffer.
+  // If our receive window has dropped below the threshold, then send a
+  // WINDOW_UPDATE frame.
   void AddBytesConsumed(uint64 bytes);
 
   // Returns true if the stream is flow control blocked, by the stream flow
@@ -171,12 +168,6 @@
     scoped_refptr<ProxyAckNotifierDelegate> delegate;
   };
 
-  // Calculates and returns available flow control send window.
-  uint64 SendWindowSize() const;
-
-  // Calculates and returns total number of bytes this stream has received.
-  uint64 TotalReceivedBytes() const;
-
   // Calls MaybeSendBlocked on our flow controller, and connection level flow
   // controller. If we are flow control blocked, marks this stream as write
   // blocked.
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc
index 9e212ce..5d1ea9d 100644
--- a/net/quic/reliable_quic_stream_test.cc
+++ b/net/quic/reliable_quic_stream_test.cc
@@ -11,6 +11,7 @@
 #include "net/quic/quic_write_blocked_list.h"
 #include "net/quic/spdy_utils.h"
 #include "net/quic/test_tools/quic_config_peer.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
 #include "net/quic/test_tools/quic_flow_controller_peer.h"
 #include "net/quic/test_tools/quic_session_peer.h"
 #include "net/quic/test_tools/quic_test_utils.h"
@@ -150,13 +151,14 @@
 TEST_F(ReliableQuicStreamTest, WriteAllData) {
   Initialize(kShouldProcessData);
 
-  connection_->options()->max_packet_length =
-      1 + QuicPacketCreator::StreamFramePacketOverhead(
-              connection_->version(), PACKET_8BYTE_CONNECTION_ID,
-              !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER, 0u,
-              NOT_IN_FEC_GROUP);
-  EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _))
-      .WillOnce(Return(QuicConsumedData(kDataLen, true)));
+  size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
+      connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP);
+  QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length(
+      length);
+
+  EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _)).WillOnce(
+      Return(QuicConsumedData(kDataLen, true)));
   stream_->WriteOrBufferData(kData1, false, NULL);
   EXPECT_FALSE(HasWriteBlockedStreams());
 }
@@ -209,10 +211,12 @@
   Initialize(kShouldProcessData);
 
   EXPECT_FALSE(HasWriteBlockedStreams());
-  connection_->options()->max_packet_length =
-      1 + QuicPacketCreator::StreamFramePacketOverhead(
-          connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
-          PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP);
+  size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead(
+      connection_->version(), PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+      PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP);
+  QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length(
+      length);
+
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).WillOnce(
       Return(QuicConsumedData(kDataLen - 1, false)));
   stream_->WriteOrBufferData(kData1, false, NULL);
@@ -553,6 +557,33 @@
   proxy_delegate->OnAckNotification(10, 20, 30, 40, zero_);
 }
 
+
+// Verify that when we receive a packet which violates flow control (i.e. sends
+// too much data on the stream) that the stream sequencer never sees this frame,
+// as we check for violation and close the connection early.
+TEST_F(ReliableQuicStreamTest,
+       StreamSequencerNeverSeesPacketsViolatingFlowControl) {
+  ValueRestore<bool> old_stream_flag(
+      &FLAGS_enable_quic_stream_flow_control_2, true);
+  ValueRestore<bool> old_connection_flag(
+      &FLAGS_enable_quic_connection_flow_control, true);
+
+  Initialize(kShouldProcessData);
+
+  // Receive a stream frame that violates flow control: the byte offset is
+  // higher than the receive window offset.
+  QuicStreamFrame frame(stream_->id(), false,
+                        kInitialFlowControlWindowForTest + 1,
+                        MakeIOVector("."));
+  EXPECT_GT(frame.offset, QuicFlowControllerPeer::ReceiveWindowOffset(
+                              stream_->flow_controller()));
+
+  // Stream should not accept the frame, and the connection should be closed.
+  EXPECT_CALL(*connection_,
+              SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA));
+  EXPECT_FALSE(stream_->OnStreamFrame(frame));
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/mock_crypto_client_stream.cc b/net/quic/test_tools/mock_crypto_client_stream.cc
index 6710dcd..a4b3ab0 100644
--- a/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -83,7 +83,7 @@
   QuicTagVector cgst;
   cgst.push_back(kINAR);
   cgst.push_back(kQBIC);
-  session()->config()->set_congestion_control(cgst, kQBIC);
+  session()->config()->set_congestion_feedback(cgst, kQBIC);
   session()->config()->set_idle_connection_state_lifetime(
       QuicTime::Delta::FromSeconds(2 * kDefaultTimeoutSecs),
       QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs));
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index a8e1db5..9d7c83f 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -215,5 +215,11 @@
   return connection->connection_close_packet_.get();
 }
 
+// static
+void QuicConnectionPeer::SetSupportedVersions(QuicConnection* connection,
+                                              QuicVersionVector versions) {
+  connection->framer_.SetSupportedVersions(versions);
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 8c74c1a..cf0ea38 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -108,6 +108,9 @@
   static QuicEncryptedPacket* GetConnectionClosePacket(
       QuicConnection* connection);
 
+  static void SetSupportedVersions(QuicConnection* connection,
+                                   QuicVersionVector versions);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
 };
diff --git a/net/quic/test_tools/quic_flow_controller_peer.cc b/net/quic/test_tools/quic_flow_controller_peer.cc
index 80b5e2b..35882ed 100644
--- a/net/quic/test_tools/quic_flow_controller_peer.cc
+++ b/net/quic/test_tools/quic_flow_controller_peer.cc
@@ -54,7 +54,7 @@
 uint64 QuicFlowControllerPeer::ReceiveWindowSize(
     QuicFlowController* flow_controller) {
   return flow_controller->receive_window_offset_ -
-         flow_controller->TotalReceivedBytes();
+         flow_controller->highest_received_byte_offset_;
 }
 
 }  // namespace test
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc
index 397f39f..7f0835f 100644
--- a/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -84,7 +84,7 @@
 
   QuicFramer framer(SupportedVersions(version_), QuicTime::Zero(), false);
   scoped_ptr<QuicPacket> packet(
-      framer.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer, header, frames).packet);
   return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
       ENCRYPTION_NONE, header.packet_sequence_number, *packet));
 }
@@ -143,7 +143,7 @@
   }
 
   scoped_ptr<QuicPacket> packet(
-      framer.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer, header, frames).packet);
   return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
       ENCRYPTION_NONE, header.packet_sequence_number, *packet));
 }
@@ -227,7 +227,7 @@
   QuicFrames frames;
   frames.push_back(frame);
   scoped_ptr<QuicPacket> packet(
-      framer.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer, header, frames).packet);
   return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
       ENCRYPTION_NONE, header.packet_sequence_number, *packet));
 }
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 1f7759d..39458e1 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -63,6 +63,25 @@
   return ack;
 }
 
+SerializedPacket BuildUnsizedDataPacket(QuicFramer* framer,
+                                        const QuicPacketHeader& header,
+                                        const QuicFrames& frames) {
+  const size_t max_plaintext_size = framer->GetMaxPlaintextSize(kMaxPacketSize);
+  size_t packet_size = GetPacketHeaderSize(header);
+  for (size_t i = 0; i < frames.size(); ++i) {
+    DCHECK_LE(packet_size, max_plaintext_size);
+    bool first_frame = i == 0;
+    bool last_frame = i == frames.size() - 1;
+    const size_t frame_size = framer->GetSerializedFrameLength(
+        frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
+        header.is_in_fec_group,
+        header.public_header.sequence_number_length);
+    DCHECK(frame_size);
+    packet_size += frame_size;
+  }
+  return framer->BuildDataPacket(header, frames, packet_size);
+}
+
 MockFramerVisitor::MockFramerVisitor() {
   // By default, we want to accept packets.
   ON_CALL(*this, OnProtocolVersionMismatch(_))
@@ -391,6 +410,12 @@
   return addr;
 }
 
+IPAddressNumber Loopback6() {
+  IPAddressNumber addr;
+  CHECK(ParseIPLiteralToNumber("::1", &addr));
+  return addr;
+}
+
 void GenerateBody(string* body, int length) {
   body->clear();
   body->reserve(length);
@@ -423,7 +448,7 @@
   frames.push_back(frame);
   QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
   scoped_ptr<QuicPacket> packet(
-      framer.BuildUnsizedDataPacket(header, frames).packet);
+      BuildUnsizedDataPacket(&framer, header, frames).packet);
   EXPECT_TRUE(packet != NULL);
   QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE,
                                                         sequence_number,
@@ -500,7 +525,7 @@
   QuicFrame frame(&stream_frame);
   QuicFrames frames;
   frames.push_back(frame);
-  return quic_framer.BuildUnsizedDataPacket(header, frames).packet;
+  return BuildUnsizedDataPacket(&quic_framer, header, frames).packet;
 }
 
 QuicPacket* ConstructHandshakePacket(QuicConnectionId connection_id,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 8bf069b..83d2837 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -49,6 +49,9 @@
 // Returns an address for 127.0.0.1.
 IPAddressNumber Loopback4();
 
+// Returns an address for ::1.
+IPAddressNumber Loopback6();
+
 void GenerateBody(std::string* body, int length);
 
 // Create an encrypted packet for testing.
@@ -93,6 +96,13 @@
 QuicAckFrame MakeAckFrameWithNackRanges(size_t num_nack_ranges,
                                         QuicPacketSequenceNumber least_unacked);
 
+// Returns a SerializedPacket whose |packet| member is owned by the caller,
+// and is populated with the fields in |header| and |frames|, or is NULL if
+// the packet could not be created.
+SerializedPacket BuildUnsizedDataPacket(QuicFramer* framer,
+                                        const QuicPacketHeader& header,
+                                        const QuicFrames& frames);
+
 template<typename SaveType>
 class ValueRestore {
  public:
@@ -419,9 +429,10 @@
                bool(QuicTime, QuicByteCount, QuicPacketSequenceNumber,
                     QuicByteCount, HasRetransmittableData));
   MOCK_METHOD1(OnRetransmissionTimeout, void(bool));
-  MOCK_METHOD3(TimeUntilSend, QuicTime::Delta(QuicTime now,
-                                              QuicByteCount bytes_in_flight,
-                                              HasRetransmittableData));
+  MOCK_CONST_METHOD3(TimeUntilSend,
+                     QuicTime::Delta(QuicTime now,
+                                     QuicByteCount bytes_in_flight,
+                                     HasRetransmittableData));
   MOCK_CONST_METHOD0(BandwidthEstimate, QuicBandwidth(void));
   MOCK_METHOD1(OnRttUpdated, void(QuicPacketSequenceNumber));
   MOCK_CONST_METHOD0(RetransmissionDelay, QuicTime::Delta(void));