summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-28 08:39:25 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-28 08:39:25 +0000
commitb007e638225570ce6998328782dfa44c6fd94b10 (patch)
tree972148818e714f8d66ac3210a931a5f1efac2fd4
parent3bcd34cdcc9a842e840777b8e643ded999467741 (diff)
downloadchromium_src-b007e638225570ce6998328782dfa44c6fd94b10.zip
chromium_src-b007e638225570ce6998328782dfa44c6fd94b10.tar.gz
chromium_src-b007e638225570ce6998328782dfa44c6fd94b10.tar.bz2
Land Recent QUIC changes.
Fix a bug in the quic_client where disconnecting and re-connecting would re-use the same packet writer, and attempt to write to the same (now closed) socket. Merge internal change: 55509535 If the most significant byte of a QuicTag is 255 ('\xff'), print that byte as a space rather than printing the QuicTag as a decimal number. Add a unit test for QuicUtils::TagToString. as "CRT " instead of its decimal value "4283716163". Merge internal change: 55493160 Miscellaneous cleanup of the supported_versions CL. Remove QuicVersionArrayToString. Replace the only QuicVersionArrayToString call by QuicVersionVectorToString. Add a protected supported_versions() getter method to QuicDispatcher to allow access to supported_versions_ by derived classes of QuicDispatcher. Document the purpose of each combination of supported versions in gfe/quic/end_to_end_test.cc. "gfe2/quic_versions" and its value no longer has an extraneous comma at the end. For example, "QUIC_VERSION_11,QUIC_VERSION_10" as opposed to "QUIC_VERSION_11,QUIC_VERSION_10," Merge internal change: 55490062 Implement encoding and decoding of unsigned half precision floats in QUIC. Merge internal change: 55454508 Annotate QUIC streams as server/client in DLOG output. Merge internal change: 55419499 Expose methods for getting/setting the QUIC congestion manager's congestion window value. Merge internal change: 55416317 Return the unused server port once EndToEndTest has finished, to reduce the chance PickUnusedPortOrDie will fail in the future. Merge internal change: 55376533 This change hasn't been enabled in chromium. Fix quic prober to use new QuicClient constructor which takes QuicSupportedVersions as argument. Merge internal change: 55353942 Change all QuicConfig constructors to DefaultQuicConfig. Merge internal change: 55307326 Fixing TSAN warnings in the PacketDroppingTestWriter by adding a lock. Merge internal change: 55234723 Fixing potential bugs with write blocking in QuicConnection. Merge internal change: 55230366 Added back QuicVersionMax to fix borg TAP failures. This is a temporary fix until until CL 55170273 lands. Merge internal change: 55173927 Test server/client various combinations of supported versions. - Fix to handle if chrome were to send VERSION 11 and GFE supports version 10 and vice versa (fixes to setting of NULL decrypter). Fixed unit tests to handle different packet sizes between 11 and 10 because of changes to Null encrypter/decrypter. - Send version negotiation packet packet again (from server) if that packet is dropped. - Changed end_to_end_test.cc to configure the client to support multiple versions and configure the server to support only one version and vice versa. - Moved QuicVersionMax and QuicVersonMin to quic_test_utils.cc. Most of the bug fixes are from rch. re-transmitting that packet again. Fixed bugs with server supporting VERSION 10 and chrome negotiating down from 11 to 10. Added tests for version negotiation and testing of various combinations of server and client version negotiation. Merge internal change: 55168938 Don't cast a uint32 to int32 then to a uint64. Seen in test logs: I1018 11:55:44.626228 1775 packet_dropping_test_writer.cc:50] Seeding packet loss with -508765393 I1018 11:55:44.626275 1775 packet_dropping_test_writer.cc:50] Seeding packet loss with 631710332 Merge internal change: 55135280 R=rch@chromium.org Review URL: https://codereview.chromium.org/47283002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231296 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/quic/congestion_control/fix_rate_sender.cc7
-rw-r--r--net/quic/congestion_control/fix_rate_sender.h2
-rw-r--r--net/quic/congestion_control/inter_arrival_sender.cc7
-rw-r--r--net/quic/congestion_control/inter_arrival_sender.h2
-rw-r--r--net/quic/congestion_control/quic_congestion_manager.cc8
-rw-r--r--net/quic/congestion_control/quic_congestion_manager.h8
-rw-r--r--net/quic/congestion_control/send_algorithm_interface.h8
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.cc18
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.h2
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender_test.cc6
-rw-r--r--net/quic/quic_client_session_test.cc2
-rw-r--r--net/quic/quic_connection.cc35
-rw-r--r--net/quic/quic_connection.h2
-rw-r--r--net/quic/quic_connection_helper_test.cc5
-rw-r--r--net/quic/quic_connection_test.cc48
-rw-r--r--net/quic/quic_crypto_client_stream_test.cc2
-rw-r--r--net/quic/quic_crypto_server_stream_test.cc2
-rw-r--r--net/quic/quic_data_reader.cc34
-rw-r--r--net/quic/quic_data_reader.h5
-rw-r--r--net/quic/quic_data_writer.cc39
-rw-r--r--net/quic/quic_data_writer.h4
-rw-r--r--net/quic/quic_data_writer_test.cc131
-rw-r--r--net/quic/quic_end_to_end_unittest.cc1
-rw-r--r--net/quic/quic_framer.cc22
-rw-r--r--net/quic/quic_framer.h15
-rw-r--r--net/quic/quic_framer_test.cc18
-rw-r--r--net/quic/quic_http_stream_test.cc5
-rw-r--r--net/quic/quic_network_transaction_unittest.cc4
-rw-r--r--net/quic/quic_packet_creator_test.cc6
-rw-r--r--net/quic/quic_packet_generator_test.cc5
-rw-r--r--net/quic/quic_protocol.cc22
-rw-r--r--net/quic/quic_protocol.h30
-rw-r--r--net/quic/quic_protocol_test.cc18
-rw-r--r--net/quic/quic_session.h2
-rw-r--r--net/quic/quic_stream_factory.cc2
-rw-r--r--net/quic/quic_stream_factory_test.cc4
-rw-r--r--net/quic/quic_stream_sequencer_test.cc10
-rw-r--r--net/quic/quic_utils.cc2
-rw-r--r--net/quic/quic_utils_test.cc16
-rw-r--r--net/quic/reliable_quic_stream.cc21
-rw-r--r--net/quic/reliable_quic_stream.h5
-rw-r--r--net/quic/test_tools/crypto_test_utils.cc4
-rw-r--r--net/quic/test_tools/quic_test_utils.cc18
-rw-r--r--net/quic/test_tools/quic_test_utils.h8
-rw-r--r--net/quic/test_tools/simple_quic_framer.cc2
-rw-r--r--net/tools/quic/end_to_end_test.cc97
-rw-r--r--net/tools/quic/quic_client.cc16
-rw-r--r--net/tools/quic/quic_client.h12
-rw-r--r--net/tools/quic/quic_client_bin.cc5
-rw-r--r--net/tools/quic/quic_client_session_test.cc5
-rw-r--r--net/tools/quic/quic_dispatcher.cc13
-rw-r--r--net/tools/quic/quic_dispatcher.h14
-rw-r--r--net/tools/quic/quic_dispatcher_test.cc5
-rw-r--r--net/tools/quic/quic_epoll_connection_helper_test.cc7
-rw-r--r--net/tools/quic/quic_reliable_client_stream_test.cc3
-rw-r--r--net/tools/quic/quic_server.cc14
-rw-r--r--net/tools/quic/quic_server.h9
-rw-r--r--net/tools/quic/quic_time_wait_list_manager.cc5
-rw-r--r--net/tools/quic/quic_time_wait_list_manager.h3
-rw-r--r--net/tools/quic/quic_time_wait_list_manager_test.cc38
-rw-r--r--net/tools/quic/test_tools/mock_quic_dispatcher.cc4
-rw-r--r--net/tools/quic/test_tools/packet_dropping_test_writer.cc9
-rw-r--r--net/tools/quic/test_tools/packet_dropping_test_writer.h11
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc25
-rw-r--r--net/tools/quic/test_tools/quic_test_client.h6
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.cc10
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.h6
-rw-r--r--net/tools/quic/test_tools/server_thread.cc3
-rw-r--r--net/tools/quic/test_tools/server_thread.h1
69 files changed, 724 insertions, 214 deletions
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
index 082264d..05fcb35 100644
--- a/net/quic/congestion_control/fix_rate_sender.cc
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -123,4 +123,11 @@ QuicTime::Delta FixRateSender::RetransmissionDelay() {
return latest_rtt_.Add(latest_rtt_);
}
+QuicByteCount FixRateSender::GetCongestionWindow() {
+ return 0;
+}
+
+void FixRateSender::SetCongestionWindow(QuicByteCount window) {
+}
+
} // namespace net
diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h
index b14e4d5..bbbee68 100644
--- a/net/quic/congestion_control/fix_rate_sender.h
+++ b/net/quic/congestion_control/fix_rate_sender.h
@@ -48,6 +48,8 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
virtual QuicBandwidth BandwidthEstimate() OVERRIDE;
virtual QuicTime::Delta SmoothedRtt() OVERRIDE;
virtual QuicTime::Delta RetransmissionDelay() OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() OVERRIDE;
+ virtual void SetCongestionWindow(QuicByteCount window) OVERRIDE;
// End implementation of SendAlgorithmInterface.
private:
diff --git a/net/quic/congestion_control/inter_arrival_sender.cc b/net/quic/congestion_control/inter_arrival_sender.cc
index 4ec40fb..2740f1e 100644
--- a/net/quic/congestion_control/inter_arrival_sender.cc
+++ b/net/quic/congestion_control/inter_arrival_sender.cc
@@ -324,6 +324,13 @@ QuicTime::Delta InterArrivalSender::RetransmissionDelay() {
return smoothed_rtt_.Add(smoothed_rtt_);
}
+QuicByteCount InterArrivalSender::GetCongestionWindow() {
+ return 0;
+}
+
+void InterArrivalSender::SetCongestionWindow(QuicByteCount window) {
+}
+
void InterArrivalSender::EstimateNewBandwidth(QuicTime feedback_receive_time,
QuicBandwidth sent_bandwidth) {
QuicBandwidth new_bandwidth = bitrate_ramp_up_->GetNewBitrate(sent_bandwidth);
diff --git a/net/quic/congestion_control/inter_arrival_sender.h b/net/quic/congestion_control/inter_arrival_sender.h
index 606956b..3961a2b 100644
--- a/net/quic/congestion_control/inter_arrival_sender.h
+++ b/net/quic/congestion_control/inter_arrival_sender.h
@@ -62,6 +62,8 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface {
virtual QuicBandwidth BandwidthEstimate() OVERRIDE;
virtual QuicTime::Delta SmoothedRtt() OVERRIDE;
virtual QuicTime::Delta RetransmissionDelay() OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() OVERRIDE;
+ virtual void SetCongestionWindow(QuicByteCount window) OVERRIDE;
// End implementation of SendAlgorithmInterface.
private:
diff --git a/net/quic/congestion_control/quic_congestion_manager.cc b/net/quic/congestion_control/quic_congestion_manager.cc
index c288a5c..ed133fc 100644
--- a/net/quic/congestion_control/quic_congestion_manager.cc
+++ b/net/quic/congestion_control/quic_congestion_manager.cc
@@ -215,6 +215,14 @@ QuicBandwidth QuicCongestionManager::BandwidthEstimate() {
return send_algorithm_->BandwidthEstimate();
}
+QuicByteCount QuicCongestionManager::GetCongestionWindow() {
+ return send_algorithm_->GetCongestionWindow();
+}
+
+void QuicCongestionManager::SetCongestionWindow(QuicByteCount window) {
+ send_algorithm_->SetCongestionWindow(window);
+}
+
void QuicCongestionManager::CleanupPacketHistory() {
const QuicTime::Delta kHistoryPeriod =
QuicTime::Delta::FromMilliseconds(kHistoryPeriodMs);
diff --git a/net/quic/congestion_control/quic_congestion_manager.h b/net/quic/congestion_control/quic_congestion_manager.h
index d574e51..6d15719 100644
--- a/net/quic/congestion_control/quic_congestion_manager.h
+++ b/net/quic/congestion_control/quic_congestion_manager.h
@@ -95,6 +95,14 @@ class NET_EXPORT_PRIVATE QuicCongestionManager {
// Returns the estimated bandwidth calculated by the congestion algorithm.
QuicBandwidth BandwidthEstimate();
+ // Returns the size of the current congestion window. Note, this
+ // is not the *available* window. Some send algorithms may not use a
+ // congestion window and will return 0.
+ QuicByteCount GetCongestionWindow();
+
+ // Sets the value of the current congestion window to |window|.
+ void SetCongestionWindow(QuicByteCount window);
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicCongestionManagerPeer;
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
index b0b4cac..8ff3961 100644
--- a/net/quic/congestion_control/send_algorithm_interface.h
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -87,6 +87,14 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
// Note 1: the caller is responsible for sanity checking this value.
// Note 2: this will return zero if we don't have enough data for an estimate.
virtual QuicTime::Delta RetransmissionDelay() = 0;
+
+ // Returns the size of the current congestion window. Note, this
+ // is not the *available* window. Some send algorithms may not use a
+ // congestion window and will return 0.
+ virtual QuicByteCount GetCongestionWindow() = 0;
+
+ // Sets the value of the current congestion window to |window|.
+ virtual void SetCongestionWindow(QuicByteCount window) = 0;
};
} // namespace net
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 14804a9..0a7a897 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -12,6 +12,8 @@ namespace net {
namespace {
// Constants based on TCP defaults.
+//TODO(rch): set to 2.
+const QuicTcpCongestionWindow kMinimumCongestionWindow = 1;
const int64 kHybridStartLowWindow = 16;
const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
const QuicByteCount kDefaultReceiveWindow = 64000;
@@ -94,7 +96,7 @@ void TcpCubicSender::OnIncomingLoss(QuicTime /*ack_receive_time*/) {
}
// Sanity, make sure that we don't end up with an empty window.
if (congestion_window_ == 0) {
- congestion_window_ = 1;
+ congestion_window_ = kMinimumCongestionWindow;
}
DLOG(INFO) << "Incoming loss; congestion window:" << congestion_window_;
}
@@ -155,8 +157,7 @@ QuicByteCount TcpCubicSender::AvailableSendWindow() {
QuicByteCount TcpCubicSender::SendWindow() {
// What's the current send window in bytes.
- return std::min(receive_window_,
- congestion_window_ * kMaxSegmentSize);
+ return std::min(receive_window_, GetCongestionWindow());
}
QuicBandwidth TcpCubicSender::BandwidthEstimate() {
@@ -178,6 +179,17 @@ QuicTime::Delta TcpCubicSender::RetransmissionDelay() {
smoothed_rtt_.ToMicroseconds() + 4 * mean_deviation_.ToMicroseconds());
}
+QuicByteCount TcpCubicSender::GetCongestionWindow() {
+ return congestion_window_ * kMaxSegmentSize;
+}
+
+void TcpCubicSender::SetCongestionWindow(QuicByteCount window) {
+ congestion_window_ = window / kMaxSegmentSize;
+ if (congestion_window_ < kMinimumCongestionWindow) {
+ congestion_window_ = kMinimumCongestionWindow;
+ }
+}
+
void TcpCubicSender::Reset() {
delay_min_ = QuicTime::Delta::Zero();
hybrid_slow_start_.Restart();
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index f83de11..cf5f2ff 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -60,6 +60,8 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
virtual QuicBandwidth BandwidthEstimate() OVERRIDE;
virtual QuicTime::Delta SmoothedRtt() OVERRIDE;
virtual QuicTime::Delta RetransmissionDelay() OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() OVERRIDE;
+ virtual void SetCongestionWindow(QuicByteCount window) OVERRIDE;
// End implementation of SendAlgorithmInterface.
private:
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index 5c2db40..15845cd 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -75,8 +75,8 @@ class TcpCubicSenderTest : public ::testing::Test {
TEST_F(TcpCubicSenderTest, SimpleSender) {
QuicCongestionFeedbackFrame feedback;
// At startup make sure we are at the default.
- EXPECT_EQ(kDefaultWindowTCP,
- sender_->AvailableSendWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// At startup make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
@@ -89,6 +89,7 @@ TEST_F(TcpCubicSenderTest, SimpleSender) {
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
// And that window is un-affected.
EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// A retransmit should always return 0.
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
@@ -146,6 +147,7 @@ TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
QuicByteCount expected_send_window =
kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAck);
EXPECT_EQ(expected_send_window, sender_->SendWindow());
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
// We should now have fallen out of slow start.
SendAvailableSendWindow();
AckNPackets(2);
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index 8298ff2..f04e640 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -39,7 +39,7 @@ class TestPacketWriter : public QuicDefaultPacketWriter {
const IPAddressNumber& self_address,
const IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), true);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), true);
FramerVisitorCapturingFrames visitor;
framer.set_visitor(&visitor);
QuicEncryptedPacket packet(buffer, buf_len);
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index ea575aa..97082d6 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -199,8 +199,8 @@ QuicConnection::QuicConnection(QuicGuid guid,
QuicConnectionHelperInterface* helper,
QuicPacketWriter* writer,
bool is_server,
- QuicVersion version)
- : framer_(version,
+ const QuicVersionVector& supported_versions)
+ : framer_(supported_versions,
helper->GetClock()->ApproximateNow(),
is_server),
helper_(helper),
@@ -237,6 +237,7 @@ QuicConnection::QuicConnection(QuicGuid guid,
connected_(true),
received_truncated_ack_(false),
address_migrating_(false) {
+ DLOG(INFO) << ENDPOINT << "Created connection with guid: " << guid;
timeout_alarm_->Set(clock_->ApproximateNow().Add(idle_network_timeout_));
framer_.set_visitor(this);
framer_.set_received_entropy_calculator(&received_packet_manager_);
@@ -256,8 +257,9 @@ bool QuicConnection::SelectMutualVersion(
// Try to find the highest mutual version by iterating over supported
// versions, starting with the highest, and breaking out of the loop once we
// find a matching version in the provided available_versions vector.
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- const QuicVersion& version = kSupportedQuicVersions[i];
+ const QuicVersionVector& supported_versions = framer_.supported_versions();
+ for (size_t i = 0; i < supported_versions.size(); ++i) {
+ const QuicVersion& version = supported_versions[i];
if (std::find(available_versions.begin(), available_versions.end(),
version) != available_versions.end()) {
framer_.set_version(version);
@@ -294,6 +296,8 @@ void QuicConnection::OnPublicResetPacket(
}
bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
+ DLOG(INFO) << ENDPOINT << "Received packet with mismatched version "
+ << received_version;
// TODO(satyamshekhar): Implement no server state in this mode.
if (!is_server_) {
LOG(DFATAL) << ENDPOINT << "Framer called OnProtocolVersionMismatch. "
@@ -318,7 +322,7 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
case NEGOTIATION_IN_PROGRESS:
if (!framer_.IsSupportedVersion(received_version)) {
- // Drop packets which can't be parsed due to version mismatch.
+ SendVersionNegotiationPacket();
return false;
}
break;
@@ -334,6 +338,7 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
version_negotiation_state_ = NEGOTIATED_VERSION;
visitor_->OnSuccessfulVersionNegotiation(received_version);
+ DLOG(INFO) << ENDPOINT << "version negotiated " << received_version;
// Store the new version.
framer_.set_version(received_version);
@@ -378,6 +383,7 @@ void QuicConnection::OnVersionNegotiationPacket(
return;
}
+ DLOG(INFO) << ENDPOINT << "negotiating version " << version();
version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
RetransmitUnackedPackets(ALL_PACKETS);
}
@@ -824,16 +830,16 @@ void QuicConnection::MaybeSendInResponseToPacket(
}
void QuicConnection::SendVersionNegotiationPacket() {
- QuicVersionVector supported_versions;
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- supported_versions.push_back(kSupportedQuicVersions[i]);
- }
scoped_ptr<QuicEncryptedPacket> version_packet(
- packet_creator_.SerializeVersionNegotiationPacket(supported_versions));
+ packet_creator_.SerializeVersionNegotiationPacket(
+ framer_.supported_versions()));
// TODO(satyamshekhar): implement zero server state negotiation.
WriteResult result =
writer_->WritePacket(version_packet->data(), version_packet->length(),
self_address().address(), peer_address(), this);
+ if (result.status == WRITE_STATUS_BLOCKED) {
+ write_blocked_ = true;
+ }
if (result.status == WRITE_STATUS_OK ||
(result.status == WRITE_STATUS_BLOCKED &&
writer_->IsWriteBlockedDataBuffered())) {
@@ -844,9 +850,6 @@ void QuicConnection::SendVersionNegotiationPacket() {
// We can't send an error as the socket is presumably borked.
CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
}
- if (result.status == WRITE_STATUS_BLOCKED) {
- write_blocked_ = true;
- }
pending_version_negotiation_packet_ = true;
}
@@ -1254,6 +1257,11 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
return true;
}
+ // If we're write blocked, we know we can't write.
+ if (write_blocked_) {
+ return false;
+ }
+
// If we are not forced and we can't write, then simply return false;
if (forced == NO_FORCE &&
!CanWrite(transmission_type, retransmittable, handshake)) {
@@ -1402,6 +1410,7 @@ bool QuicConnection::OnPacketSent(WriteResult result) {
pending_write_.reset();
if (result.status == WRITE_STATUS_ERROR) {
+ DLOG(INFO) << "Write failed with error code: " << result.error_code;
// We can't send an error as the socket is presumably borked.
CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
return false;
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 0487b3e..6283b3b 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -196,7 +196,7 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicConnectionHelperInterface* helper,
QuicPacketWriter* writer,
bool is_server,
- QuicVersion version);
+ const QuicVersionVector& supported_versions);
virtual ~QuicConnection();
// Send the data in |data| to the peer in as few packets as possible.
diff --git a/net/quic/quic_connection_helper_test.cc b/net/quic/quic_connection_helper_test.cc
index 89915bc..d3d97e5 100644
--- a/net/quic/quic_connection_helper_test.cc
+++ b/net/quic/quic_connection_helper_test.cc
@@ -52,7 +52,8 @@ class TestConnection : public QuicConnection {
IPEndPoint address,
QuicConnectionHelper* helper,
QuicPacketWriter* writer)
- : QuicConnection(guid, address, helper, writer, false, QuicVersionMax()) {
+ : QuicConnection(guid, address, helper, writer, false,
+ QuicSupportedVersions()) {
}
void SendAck() {
@@ -79,7 +80,7 @@ class QuicConnectionHelperTest : public ::testing::Test {
QuicConnectionHelperTest()
: guid_(2),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
net_log_(BoundNetLog()),
frame_(1, false, 0, kData) {
Initialize();
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 5cf94d7..2433648 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -296,7 +296,7 @@ class TestPacketWriter : public QuicPacketWriter {
sizeof(final_bytes_of_last_packet_));
}
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), !is_server_);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), !is_server_);
if (use_tagging_decrypter_) {
framer.SetDecrypter(new TaggingDecrypter);
}
@@ -402,7 +402,7 @@ class TestConnection : public QuicConnection {
TestPacketWriter* writer,
bool is_server)
: QuicConnection(guid, address, helper, writer, is_server,
- QuicVersionMax()),
+ QuicSupportedVersions()),
helper_(helper),
writer_(writer) {
writer_->set_is_server(is_server);
@@ -533,7 +533,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<bool> {
protected:
QuicConnectionTest()
: guid_(42),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
creator_(guid_, &framer_, QuicRandom::GetInstance(), false),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
helper_(new TestConnectionHelper(&clock_, &random_generator_)),
@@ -2844,6 +2844,7 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_TRUE(connection_.HasQueuedData());
+ EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
writer_->set_blocked(false);
connection_.OnCanWrite();
@@ -2861,6 +2862,37 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
}
}
+TEST_P(QuicConnectionTest,
+ ServerSendsVersionNegotiationPacketSocketBlockedDataBuffered) {
+ framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
+
+ QuicPacketHeader header;
+ header.public_header.guid = guid_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = true;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.packet_sequence_number = 12;
+ header.fec_group = 0;
+
+ QuicFrames frames;
+ QuicFrame frame(&frame1_);
+ frames.push_back(frame);
+ scoped_ptr<QuicPacket> packet(
+ framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicEncryptedPacket> encrypted(
+ framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
+
+ framer_.set_version(QuicVersionMax());
+ connection_.set_is_server(true);
+ writer_->set_blocked(true);
+ writer_->set_is_write_blocked_data_buffered(true);
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+ EXPECT_EQ(0u, writer_->last_packet_size());
+ EXPECT_FALSE(connection_.HasQueuedData());
+ EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
+}
+
TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
// Start out with some unsupported version.
QuicConnectionPeer::GetFramer(&connection_)->set_version_for_tests(
@@ -3065,8 +3097,8 @@ TEST_P(QuicConnectionTest, DontProcessFramesIfPacketClosedConnection) {
TEST_P(QuicConnectionTest, SelectMutualVersion) {
// Set the connection to speak the lowest quic version.
- connection_.set_version(QuicVersionMin());
- EXPECT_EQ(QuicVersionMin(), connection_.version());
+ connection_.set_version(test::QuicVersionMin());
+ EXPECT_EQ(test::QuicVersionMin(), connection_.version());
// Pass in available versions which includes a higher mutually supported
// version. The higher mutually supported version should be selected.
@@ -3080,11 +3112,11 @@ TEST_P(QuicConnectionTest, SelectMutualVersion) {
// Expect that the lowest version is selected.
// Ensure the lowest supported version is less than the max, unless they're
// the same.
- EXPECT_LE(QuicVersionMin(), QuicVersionMax());
+ EXPECT_LE(test::QuicVersionMin(), QuicVersionMax());
QuicVersionVector lowest_version_vector;
- lowest_version_vector.push_back(QuicVersionMin());
+ lowest_version_vector.push_back(test::QuicVersionMin());
EXPECT_TRUE(connection_.SelectMutualVersion(lowest_version_vector));
- EXPECT_EQ(QuicVersionMin(), connection_.version());
+ EXPECT_EQ(test::QuicVersionMin(), connection_.version());
// Shouldn't be able to find a mutually supported version.
QuicVersionVector unsupported_version;
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index e07ad46..8595d6c 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -116,7 +116,7 @@ TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) {
CompleteCryptoHandshake();
connection_ = new PacketSavingConnection(1, addr_, true);
- session_.reset(new TestSession(connection_, QuicConfig(), true));
+ session_.reset(new TestSession(connection_, DefaultQuicConfig(), true));
stream_.reset(new QuicCryptoClientStream(kServerHostname, session_.get(),
&crypto_config_));
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index bfea221..d622342 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -43,7 +43,7 @@ class QuicCryptoServerStreamTest : public ::testing::Test {
addr_(ParseIPLiteralToNumber("192.0.2.33", &ip_) ?
ip_ : IPAddressNumber(), 1),
connection_(new PacketSavingConnection(guid_, addr_, true)),
- session_(connection_, QuicConfig(), true),
+ session_(connection_, DefaultQuicConfig(), true),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance()),
stream_(crypto_config_, &session_) {
diff --git a/net/quic/quic_data_reader.cc b/net/quic/quic_data_reader.cc
index 3bb7fc3..b9a6acf 100644
--- a/net/quic/quic_data_reader.cc
+++ b/net/quic/quic_data_reader.cc
@@ -4,6 +4,9 @@
#include "net/quic/quic_data_reader.h"
+#include "net/base/int128.h"
+#include "net/quic/quic_protocol.h"
+
using base::StringPiece;
namespace net {
@@ -59,6 +62,37 @@ bool QuicDataReader::ReadUInt128(uint128* result) {
return true;
}
+bool QuicDataReader::ReadUFloat16(uint64* result) {
+ uint16 value;
+ if (!ReadUInt16(&value)) {
+ return false;
+ }
+
+ *result = value;
+ if (*result < (1 << kUFloat16MantissaEffectiveBits)) {
+ // Fast path: either the value is denormalized (no hidden bit), or
+ // normalized (hidden bit set, exponent offset by one) with exponent zero.
+ // Zero exponent offset by one sets the bit exactly where the hidden bit is.
+ // So in both cases the value encodes itself.
+ return true;
+ }
+
+ uint16 exponent = value >> kUFloat16MantissaBits; // No sign extend on uint!
+ // After the fast pass, the exponent is at least one (offset by one).
+ // Un-offset the exponent.
+ --exponent;
+ DCHECK_GE(exponent, 1);
+ DCHECK_LE(exponent, kUFloat16MaxExponent);
+ // Here we need to clear the exponent and set the hidden bit. We have already
+ // decremented the exponent, so when we subtract it, it leaves behind the
+ // hidden bit.
+ *result -= exponent << kUFloat16MantissaBits;
+ *result <<= exponent;
+ DCHECK_GE(value, 1 << kUFloat16MantissaEffectiveBits);
+ DCHECK_LE(value, kUFloat16MaxValue);
+ return true;
+}
+
bool QuicDataReader::ReadStringPiece16(StringPiece* result) {
// Read resultant length.
uint16 result_len;
diff --git a/net/quic/quic_data_reader.h b/net/quic/quic_data_reader.h
index fff07dd..9effa1c 100644
--- a/net/quic/quic_data_reader.h
+++ b/net/quic/quic_data_reader.h
@@ -59,6 +59,11 @@ class NET_EXPORT_PRIVATE QuicDataReader {
// Returns true on success, false otherwise.
bool ReadUInt128(uint128* result);
+ // Reads a 16-bit unsigned float into the given output parameter.
+ // Forwards the internal iterator on success.
+ // Returns true on success, false otherwise.
+ bool ReadUFloat16(uint64* result);
+
// Reads a string prefixed with 16-bit length into the given output parameter.
//
// NOTE: Does not copy but rather references strings in the underlying buffer.
diff --git a/net/quic/quic_data_writer.cc b/net/quic/quic_data_writer.cc
index 61e7292..65ce7be 100644
--- a/net/quic/quic_data_writer.cc
+++ b/net/quic/quic_data_writer.cc
@@ -56,6 +56,45 @@ bool QuicDataWriter::WriteUInt64(uint64 value) {
return WriteBytes(&value, sizeof(value));
}
+bool QuicDataWriter::WriteUFloat16(uint64 value) {
+ uint16 result;
+ if (value < (GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
+ // Fast path: either the value is denormalized, or has exponent zero.
+ // Both cases are represented by the value itself.
+ result = value;
+ } else if (value >= kUFloat16MaxValue) {
+ // Value is out of range; clamp it to the maximum representable.
+ result = numeric_limits<uint16>::max();
+ } else {
+ // The highest bit is between position 13 and 42 (zero-based), which
+ // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10,
+ // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11
+ // and count the shifts.
+ uint16 exponent = 0;
+ for (uint16 offset = 16; offset > 0; offset /= 2) {
+ // Right-shift the value until the highest bit is in position 11.
+ // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30),
+ // shift if the bit is at or above 11 + offset.
+ if (value >= (GG_UINT64_C(1) << (kUFloat16MantissaBits + offset))) {
+ exponent += offset;
+ value >>= offset;
+ }
+ }
+
+ DCHECK_GE(exponent, 1);
+ DCHECK_LE(exponent, kUFloat16MaxExponent);
+ DCHECK_GE(value, GG_UINT64_C(1) << kUFloat16MantissaBits);
+ DCHECK_LT(value, GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits);
+
+ // Hidden bit (position 11) is set. We should remove it and increment the
+ // exponent. Equivalently, we just add it to the exponent.
+ // This hides the bit.
+ result = value + (exponent << kUFloat16MantissaBits);
+ }
+
+ return WriteBytes(&result, sizeof(result));
+}
+
bool QuicDataWriter::WriteStringPiece16(StringPiece val) {
if (val.length() > numeric_limits<uint16>::max()) {
return false;
diff --git a/net/quic/quic_data_writer.h b/net/quic/quic_data_writer.h
index b18121d..857bcc8 100644
--- a/net/quic/quic_data_writer.h
+++ b/net/quic/quic_data_writer.h
@@ -43,6 +43,10 @@ class NET_EXPORT_PRIVATE QuicDataWriter {
bool WriteUInt32(uint32 value);
bool WriteUInt48(uint64 value);
bool WriteUInt64(uint64 value);
+ // Write unsigned floating point corresponding to the value. Large values are
+ // clamped to the maximum representable (kUFloat16MaxValue). Values that can
+ // not be represented directly are rounded down.
+ bool WriteUFloat16(uint64 value);
bool WriteStringPiece16(base::StringPiece val);
bool WriteBytes(const void* data, size_t data_len);
bool WriteRepeatedByte(uint8 byte, size_t count);
diff --git a/net/quic/quic_data_writer_test.cc b/net/quic/quic_data_writer_test.cc
index 4fbd7e4..9106947 100644
--- a/net/quic/quic_data_writer_test.cc
+++ b/net/quic/quic_data_writer_test.cc
@@ -4,13 +4,15 @@
#include "net/quic/quic_data_writer.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_data_reader.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
namespace {
-TEST(QuicDataWriterTest, WriteUint8ToOffset) {
+TEST(QuicDataWriterTest, WriteUInt8ToOffset) {
QuicDataWriter writer(4);
writer.WriteUInt32(0xfefdfcfb);
@@ -19,17 +21,15 @@ TEST(QuicDataWriterTest, WriteUint8ToOffset) {
EXPECT_TRUE(writer.WriteUInt8ToOffset(3, 2));
EXPECT_TRUE(writer.WriteUInt8ToOffset(4, 3));
- char* data = writer.take();
+ scoped_ptr<char[]> data(writer.take());
EXPECT_EQ(1, data[0]);
EXPECT_EQ(2, data[1]);
EXPECT_EQ(3, data[2]);
EXPECT_EQ(4, data[3]);
-
- delete[] data;
}
-TEST(QuicDataWriterDeathTest, WriteUint8ToOffset) {
+TEST(QuicDataWriterDeathTest, WriteUInt8ToOffset) {
QuicDataWriter writer(4);
#if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
@@ -41,6 +41,127 @@ TEST(QuicDataWriterDeathTest, WriteUint8ToOffset) {
#endif
}
+TEST(QuicDataWriterTest, SanityCheckUFloat16Consts) {
+ // Check the arithmetic on the constants - otherwise the values below make
+ // no sense.
+ EXPECT_EQ(30, kUFloat16MaxExponent);
+ EXPECT_EQ(11, kUFloat16MantissaBits);
+ EXPECT_EQ(12, kUFloat16MantissaEffectiveBits);
+ EXPECT_EQ(GG_UINT64_C(0x3FFC0000000), kUFloat16MaxValue);
+}
+
+TEST(QuicDataWriterTest, WriteUFloat16) {
+ struct TestCase {
+ uint64 decoded;
+ uint16 encoded;
+ };
+ TestCase test_cases[] = {
+ // Small numbers represent themselves.
+ { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 },
+ { 7, 7 }, { 15, 15 }, { 31, 31 }, { 42, 42 }, { 123, 123 }, { 1234, 1234 },
+ // Check transition through 2^11.
+ { 2046, 2046 }, { 2047, 2047 }, { 2048, 2048 }, { 2049, 2049 },
+ // Running out of mantissa at 2^12.
+ { 4094, 4094 }, { 4095, 4095 }, { 4096, 4096 }, { 4097, 4096 },
+ { 4098, 4097 }, { 4099, 4097 }, { 4100, 4098 }, { 4101, 4098 },
+ // Check transition through 2^13.
+ { 8190, 6143 }, { 8191, 6143 }, { 8192, 6144 }, { 8193, 6144 },
+ { 8194, 6144 }, { 8195, 6144 }, { 8196, 6145 }, { 8197, 6145 },
+ // Half-way through the exponents.
+ { 0x7FF8000, 0x87FF }, { 0x7FFFFFF, 0x87FF }, { 0x8000000, 0x8800 },
+ { 0xFFF0000, 0x8FFF }, { 0xFFFFFFF, 0x8FFF }, { 0x10000000, 0x9000 },
+ // Transition into the largest exponent.
+ { 0x1FFFFFFFFFE, 0xF7FF}, { 0x1FFFFFFFFFF, 0xF7FF},
+ { 0x20000000000, 0xF800}, { 0x20000000001, 0xF800},
+ { 0x2003FFFFFFE, 0xF800}, { 0x2003FFFFFFF, 0xF800},
+ { 0x20040000000, 0xF801}, { 0x20040000001, 0xF801},
+ // Transition into the max value and clamping.
+ { 0x3FF80000000, 0xFFFE}, { 0x3FFBFFFFFFF, 0xFFFE},
+ { 0x3FFC0000000, 0xFFFF}, { 0x3FFC0000001, 0xFFFF},
+ { 0x3FFFFFFFFFF, 0xFFFF}, { 0x40000000000, 0xFFFF},
+ { 0xFFFFFFFFFFFFFFFF, 0xFFFF},
+ };
+ int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+
+ for (int i = 0; i < num_test_cases; ++i) {
+ QuicDataWriter writer(2);
+ EXPECT_TRUE(writer.WriteUFloat16(test_cases[i].decoded));
+ scoped_ptr<char[]> data(writer.take());
+ EXPECT_EQ(test_cases[i].encoded, *reinterpret_cast<uint16*>(data.get()));
+ }
+}
+
+TEST(QuicDataWriterTest, ReadUFloat16) {
+ struct TestCase {
+ uint64 decoded;
+ uint16 encoded;
+ };
+ TestCase test_cases[] = {
+ // There are fewer decoding test cases because encoding truncates, and
+ // decoding returns the smallest expansion.
+ // Small numbers represent themselves.
+ { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 },
+ { 7, 7 }, { 15, 15 }, { 31, 31 }, { 42, 42 }, { 123, 123 }, { 1234, 1234 },
+ // Check transition through 2^11.
+ { 2046, 2046 }, { 2047, 2047 }, { 2048, 2048 }, { 2049, 2049 },
+ // Running out of mantissa at 2^12.
+ { 4094, 4094 }, { 4095, 4095 }, { 4096, 4096 },
+ { 4098, 4097 }, { 4100, 4098 },
+ // Check transition through 2^13.
+ { 8190, 6143 }, { 8192, 6144 }, { 8196, 6145 },
+ // Half-way through the exponents.
+ { 0x7FF8000, 0x87FF }, { 0x8000000, 0x8800 },
+ { 0xFFF0000, 0x8FFF }, { 0x10000000, 0x9000 },
+ // Transition into the largest exponent.
+ { 0x1FFE0000000, 0xF7FF}, { 0x20000000000, 0xF800},
+ { 0x20040000000, 0xF801},
+ // Transition into the max value.
+ { 0x3FF80000000, 0xFFFE}, { 0x3FFC0000000, 0xFFFF},
+ };
+ int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+
+ for (int i = 0; i < num_test_cases; ++i) {
+ QuicDataReader reader(reinterpret_cast<char*>(&test_cases[i].encoded), 2);
+ uint64 value;
+ EXPECT_TRUE(reader.ReadUFloat16(&value));
+ EXPECT_EQ(test_cases[i].decoded, value);
+ }
+}
+
+TEST(QuicDataWriterTest, RoundTripUFloat16) {
+ // Just test all 16-bit encoded values. 0 and max already tested above.
+ uint64 previous_value = 0;
+ for (uint16 i = 1; i < 0xFFFF; ++i) {
+ // Read the two bytes.
+ QuicDataReader reader(reinterpret_cast<char*>(&i), 2);
+ uint64 value;
+ // All values must be decodable.
+ EXPECT_TRUE(reader.ReadUFloat16(&value));
+ // Check that small numbers represent themselves
+ if (i < 4097)
+ EXPECT_EQ(i, value);
+ // Check there's monotonic growth.
+ EXPECT_LT(previous_value, value);
+ // Check that precision is within 0.5% away from the denormals.
+ if (i > 2000)
+ EXPECT_GT(previous_value * 1005, value * 1000);
+ // Check we're always within the promised range.
+ EXPECT_LT(value, GG_UINT64_C(0x3FFC0000000));
+ previous_value = value;
+ QuicDataWriter writer(6);
+ EXPECT_TRUE(writer.WriteUFloat16(value - 1));
+ EXPECT_TRUE(writer.WriteUFloat16(value));
+ EXPECT_TRUE(writer.WriteUFloat16(value + 1));
+ scoped_ptr<char[]> data(writer.take());
+ // Check minimal decoding (previous decoding has previous encoding).
+ EXPECT_EQ(i-1, *reinterpret_cast<uint16*>(data.get()));
+ // Check roundtrip.
+ EXPECT_EQ(i, *reinterpret_cast<uint16*>(data.get() + 2));
+ // Check next decoding.
+ EXPECT_EQ(i < 4096? i+1 : i, *reinterpret_cast<uint16*>(data.get() + 4));
+ }
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc
index 2d6a51e..99a040d 100644
--- a/net/quic/quic_end_to_end_unittest.cc
+++ b/net/quic/quic_end_to_end_unittest.cc
@@ -138,6 +138,7 @@ class QuicEndToEndTest : public PlatformTest {
server_address_ = IPEndPoint(ip, 0);
server_config_.SetDefaults();
server_thread_.reset(new ServerThread(server_address_, server_config_,
+ QuicSupportedVersions(),
strike_register_no_startup_period_));
server_thread_->Start();
server_thread_->listening()->Wait();
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 2701f39..493cf80 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -114,7 +114,7 @@ QuicTag GetNullTag(QuicVersion version) {
} // namespace
-QuicFramer::QuicFramer(QuicVersion version,
+QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
QuicTime creation_time,
bool is_server)
: visitor_(NULL),
@@ -122,13 +122,15 @@ QuicFramer::QuicFramer(QuicVersion version,
error_(QUIC_NO_ERROR),
last_sequence_number_(0),
last_serialized_guid_(0),
- quic_version_(version),
- decrypter_(QuicDecrypter::Create(GetNullTag(version))),
+ supported_versions_(supported_versions),
alternative_decrypter_latch_(false),
is_server_(is_server),
creation_time_(creation_time) {
- DCHECK(IsSupportedVersion(version));
- encrypter_[ENCRYPTION_NONE].reset(QuicEncrypter::Create(GetNullTag(version)));
+ DCHECK(!supported_versions.empty());
+ quic_version_ = supported_versions_[0];
+ decrypter_.reset(QuicDecrypter::Create(GetNullTag(quic_version_)));
+ encrypter_[ENCRYPTION_NONE].reset(
+ QuicEncrypter::Create(GetNullTag(quic_version_)));
}
QuicFramer::~QuicFramer() {}
@@ -229,8 +231,8 @@ bool QuicFramer::CanTruncate(const QuicFrame& frame, size_t free_bytes) {
}
bool QuicFramer::IsSupportedVersion(const QuicVersion version) const {
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- if (version == kSupportedQuicVersions[i]) {
+ for (size_t i = 0; i < supported_versions_.size(); ++i) {
+ if (version == supported_versions_[i]) {
return true;
}
}
@@ -1433,7 +1435,8 @@ size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
// level to hand. At the moment, the NullEncrypter has a tag length of 16
// bytes and AES-GCM has a tag length of 12. We take the minimum plaintext
// length just to be safe.
- size_t min_plaintext_size = ciphertext_size;
+ // TODO(rtenneti): remove '- 16' after we delete QUIC_VERSION_10.
+ size_t min_plaintext_size = ciphertext_size - 16;
for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; i++) {
if (encrypter_[i].get() != NULL) {
@@ -1684,6 +1687,9 @@ QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved(
void QuicFramer::set_version(const QuicVersion version) {
DCHECK(IsSupportedVersion(version));
+ // Handle version incompatibility between QUIC_VERSION_10 and QUIC_VERSION_11
+ // because of introduction of a new QUIC null encryption format in
+ // QUIC_VERSION_11.
if ((quic_version_ > QUIC_VERSION_10 && version <= QUIC_VERSION_10) ||
(quic_version_ <= QUIC_VERSION_10 && version > QUIC_VERSION_10)) {
// TODO(rtenneti): remove the following code after we delete
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h
index e2556df..5d55138 100644
--- a/net/quic/quic_framer.h
+++ b/net/quic/quic_framer.h
@@ -150,8 +150,10 @@ class NET_EXPORT_PRIVATE QuicReceivedEntropyHashCalculatorInterface {
class NET_EXPORT_PRIVATE QuicFramer {
public:
// Constructs a new framer that installs a kNULL QuicEncrypter and
- // QuicDecrypter for level ENCRYPTION_NONE.
- QuicFramer(QuicVersion quic_version,
+ // QuicDecrypter for level ENCRYPTION_NONE. |supported_versions| specifies the
+ // list of supported QUIC versions. |quic_version_| is set to the maximum
+ // version in |supported_versions|.
+ QuicFramer(const QuicVersionVector& supported_versions,
QuicTime creation_time,
bool is_server);
@@ -182,6 +184,10 @@ class NET_EXPORT_PRIVATE QuicFramer {
fec_builder_ = builder;
}
+ const QuicVersionVector& supported_versions() const {
+ return supported_versions_;
+ }
+
QuicVersion version() const {
return quic_version_;
}
@@ -429,6 +435,11 @@ class NET_EXPORT_PRIVATE QuicFramer {
scoped_ptr<QuicData> decrypted_;
// Version of the protocol being used.
QuicVersion quic_version_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary).
+ QuicVersionVector supported_versions_;
// Primary decrypter used to decrypt packets during parsing.
scoped_ptr<QuicDecrypter> decrypter_;
// Alternative decrypter that can also be used to decrypt packets.
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index f679b81..31c7c45 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -309,7 +309,7 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
: encrypter_(new test::TestEncrypter()),
decrypter_(new test::TestDecrypter()),
start_(QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(0x10))),
- framer_(QuicVersionMax(), start_, true) {
+ framer_(QuicSupportedVersions(), start_, true) {
version_ = GetParam();
framer_.set_version(version_);
framer_.SetDecrypter(decrypter_);
@@ -2285,9 +2285,11 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
framer_.BuildUnsizedDataPacket(header, frames).packet);
ASSERT_TRUE(data != NULL);
+ // TODO(rtenneti): remove "- 16" when we remove QUIC_VERSION_10.
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet) - 16);
}
TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
@@ -2331,9 +2333,11 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
framer_.BuildUnsizedDataPacket(header, frames).packet);
ASSERT_TRUE(data != NULL);
+ // TODO(rtenneti): remove "- 16" when we remove QUIC_VERSION_10.
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet) - 16);
}
TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
@@ -2377,9 +2381,11 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
framer_.BuildUnsizedDataPacket(header, frames).packet);
ASSERT_TRUE(data != NULL);
+ // TODO(rtenneti): remove "- 16" when we remove QUIC_VERSION_10.
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet) - 16);
}
TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
@@ -2423,9 +2429,11 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
framer_.BuildUnsizedDataPacket(header, frames).packet);
ASSERT_TRUE(data != NULL);
+ // TODO(rtenneti): remove "- 16" when we remove QUIC_VERSION_10.
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet) - 16);
}
TEST_P(QuicFramerTest, BuildStreamFramePacket) {
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 450afcb..e3f3fd5 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -54,7 +54,8 @@ class TestQuicConnection : public QuicConnection {
IPEndPoint address,
QuicConnectionHelper* helper,
QuicPacketWriter* writer)
- : QuicConnection(guid, address, helper, writer, false, QuicVersionMax()) {
+ : QuicConnection(guid, address, helper, writer, false,
+ QuicSupportedVersions()) {
}
void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
@@ -134,7 +135,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
use_closing_stream_(false),
read_buffer_(new IOBufferWithSize(4096)),
guid_(2),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
creator_(guid_, &framer_, &random_, false) {
IPAddressNumber ip;
CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index efd0139..137ceda 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -145,7 +145,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
feedback.tcp.accumulated_number_of_lost_packets = 0;
feedback.tcp.receive_window = 256000;
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(QuicFrame(&ack));
frames.push_back(QuicFrame(&feedback));
@@ -198,7 +198,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
scoped_ptr<QuicEncryptedPacket> ConstructPacket(
const QuicPacketHeader& header,
const QuicFrame& frame) {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 4f243ef..841d5d1 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -49,8 +49,8 @@ class ValueRestore {
class QuicPacketCreatorTest : public ::testing::TestWithParam<bool> {
protected:
QuicPacketCreatorTest()
- : server_framer_(QuicVersionMax(), QuicTime::Zero(), true),
- client_framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ : server_framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
+ client_framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
sequence_number_(0),
guid_(2),
data_("foo"),
@@ -455,7 +455,7 @@ TEST_F(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) {
TEST_F(QuicPacketCreatorTest, SerializeVersionNegotiationPacket) {
QuicPacketCreatorPeer::SetIsServer(&creator_, true);
QuicVersionVector versions;
- versions.push_back(QuicVersionMax());
+ versions.push_back(test::QuicVersionMax());
scoped_ptr<QuicEncryptedPacket> encrypted(
creator_.SerializeVersionNegotiationPacket(versions));
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 68fcab5..a1e30aa 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -100,7 +100,7 @@ struct PacketContents {
class QuicPacketGeneratorTest : public ::testing::Test {
protected:
QuicPacketGeneratorTest()
- : framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ : framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
creator_(42, &framer_, &random_, false),
generator_(&delegate_, NULL, &creator_),
packet_(0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL),
@@ -481,9 +481,8 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataSendsFecAtEnd) {
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.
- bool use_short_hash = framer_.version() >= QUIC_VERSION_11;
creator_.options()->max_packet_length =
- NullEncrypter(use_short_hash).GetCiphertextSize(0) +
+ NullEncrypter(false).GetCiphertextSize(0) +
GetPacketHeaderSize(creator_.options()->send_guid_length,
true,
creator_.options()->send_sequence_number_length,
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index c586d29..23c3b4f 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -113,10 +113,12 @@ uint32 MakeQuicTag(char a, char b, char c, char d) {
static_cast<uint32>(d) << 24;
}
-QuicVersion QuicVersionMax() { return kSupportedQuicVersions[0]; }
-
-QuicVersion QuicVersionMin() {
- return kSupportedQuicVersions[arraysize(kSupportedQuicVersions) - 1];
+QuicVersionVector QuicSupportedVersions() {
+ QuicVersionVector supported_versions;
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ supported_versions.push_back(kSupportedQuicVersions[i]);
+ }
+ return supported_versions;
}
QuicTag QuicVersionToQuicTag(const QuicVersion version) {
@@ -158,13 +160,13 @@ string QuicVersionToString(const QuicVersion version) {
}
}
-string QuicVersionArrayToString(const QuicVersion versions[],
- int num_versions) {
+string QuicVersionVectorToString(const QuicVersionVector& versions) {
string result = "";
- for (int i = 0; i < num_versions; ++i) {
- const QuicVersion& version = versions[i];
- result.append(QuicVersionToString(version));
- result.append(",");
+ for (size_t i = 0; i < versions.size(); ++i) {
+ if (i != 0) {
+ result.append(",");
+ }
+ result.append(QuicVersionToString(versions[i]));
}
return result;
}
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index c2ccc07..6e380e4 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -83,6 +83,23 @@ const int64 kDefaultInitialTimeoutSecs = 120; // 2 mins.
const int64 kDefaultTimeoutSecs = 60 * 10; // 10 minutes.
const int64 kDefaultMaxTimeForCryptoHandshakeSecs = 5; // 5 secs.
+// We define an unsigned 16-bit floating point value, inspired by IEEE floats
+// (http://en.wikipedia.org/wiki/Half_precision_floating-point_format),
+// with 5-bit exponent (bias 1), 11-bit mantissa (effective 12 with hidden
+// bit) and denormals, but without signs, transfinites or fractions. Wire format
+// 16 bits (little-endian byte order) are split into exponent (high 5) and
+// mantissa (low 11) and decoded as:
+// uint64 value;
+// if (exponent == 0) value = mantissa;
+// else value = (mantissa | 1 << 11) << (exponent - 1)
+const int kUFloat16ExponentBits = 5;
+const int kUFloat16MaxExponent = (1 << kUFloat16ExponentBits) - 2; // 30
+const int kUFloat16MantissaBits = 16 - kUFloat16ExponentBits; // 11
+const int kUFloat16MantissaEffectiveBits = kUFloat16MantissaBits + 1; // 12
+const uint64 kUFloat16MaxValue = // 0x3FFC0000000
+ ((GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits) - 1) <<
+ kUFloat16MaxExponent;
+
enum TransmissionType {
NOT_RETRANSMISSION,
NACK_RETRANSMISSION,
@@ -203,11 +220,8 @@ static const QuicVersion kSupportedQuicVersions[] =
typedef std::vector<QuicVersion> QuicVersionVector;
-// Upper limit on versions we support.
-NET_EXPORT_PRIVATE QuicVersion QuicVersionMax();
-
-// Lower limit on versions we support.
-NET_EXPORT_PRIVATE QuicVersion QuicVersionMin();
+// Returns a vector of QUIC versions in kSupportedQuicVersions.
+NET_EXPORT_PRIVATE QuicVersionVector QuicSupportedVersions();
// QuicTag is written to and read from the wire, but we prefer to use
// the more readable QuicVersion at other levels.
@@ -224,9 +238,9 @@ NET_EXPORT_PRIVATE QuicVersion QuicTagToQuicVersion(const QuicTag version_tag);
NET_EXPORT_PRIVATE std::string QuicVersionToString(const QuicVersion version);
// Returns comma separated list of string representations of QuicVersion enum
-// values in the supplied QuicVersionArray.
-NET_EXPORT_PRIVATE std::string QuicVersionArrayToString(
- const QuicVersion versions[], int num_versions);
+// values in the supplied |versions| vector.
+NET_EXPORT_PRIVATE std::string QuicVersionVectorToString(
+ const QuicVersionVector& versions);
// Version and Crypto tags are written to the wire with a big-endian
// representation of the name of the tag. For example
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc
index 0dcfcc6..0d54ea4 100644
--- a/net/quic/quic_protocol_test.cc
+++ b/net/quic/quic_protocol_test.cc
@@ -132,13 +132,19 @@ TEST(QuicProtocolTest, QuicVersionToString) {
QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
QuicVersion single_version[] = {QUIC_VERSION_10};
- EXPECT_EQ("QUIC_VERSION_10,",
- QuicVersionArrayToString(single_version,
- arraysize(single_version)));
+ QuicVersionVector versions_vector;
+ for (size_t i = 0; i < arraysize(single_version); ++i) {
+ versions_vector.push_back(single_version[i]);
+ }
+ EXPECT_EQ("QUIC_VERSION_10", QuicVersionVectorToString(versions_vector));
+
QuicVersion multiple_versions[] = {QUIC_VERSION_11, QUIC_VERSION_10};
- EXPECT_EQ("QUIC_VERSION_11,QUIC_VERSION_10,",
- QuicVersionArrayToString(multiple_versions,
- arraysize(multiple_versions)));
+ versions_vector.clear();
+ for (size_t i = 0; i < arraysize(multiple_versions); ++i) {
+ versions_vector.push_back(multiple_versions[i]);
+ }
+ EXPECT_EQ("QUIC_VERSION_11,QUIC_VERSION_10",
+ QuicVersionVectorToString(versions_vector));
// Make sure that all supported versions are present in QuicVersionToString.
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index b2b6a06..3867ff6 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -162,6 +162,8 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
QuicErrorCode error() const { return error_; }
+ bool is_server() const { return is_server_; }
+
protected:
// Creates a new stream, owned by the caller, to handle a peer-initiated
// stream. Returns NULL and does error handling if the stream can not be
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index a7bca03..4df9610 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -451,7 +451,7 @@ QuicClientSession* QuicStreamFactory::CreateSession(
QuicConnection* connection = new QuicConnection(guid, addr, helper_.get(),
writer.get(), false,
- QuicVersionMax());
+ QuicSupportedVersions());
writer->SetConnection(connection);
QuicCryptoClientConfig* crypto_config =
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 3f16fa8..c5c75e3 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -108,7 +108,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
feedback.tcp.accumulated_number_of_lost_packets = 0;
feedback.tcp.receive_window = 16000;
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(QuicFrame(&ack));
frames.push_back(QuicFrame(&feedback));
@@ -142,7 +142,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
scoped_ptr<QuicEncryptedPacket> ConstructPacket(
const QuicPacketHeader& header,
const QuicFrame& frame) {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index af094a2..f572f9a 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -8,7 +8,9 @@
#include <vector>
#include "base/rand_util.h"
+#include "net/base/ip_endpoint.h"
#include "net/quic/reliable_quic_stream.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -85,8 +87,9 @@ static const char kPayload[] =
class QuicStreamSequencerTest : public ::testing::Test {
protected:
QuicStreamSequencerTest()
- : session_(NULL),
- stream_(session_, 1),
+ : connection_(new MockConnection(1, IPEndPoint(), false)),
+ session_(connection_, true),
+ stream_(&session_, 1),
sequencer_(new QuicStreamSequencerPeer(&stream_)) {
}
@@ -128,7 +131,8 @@ class QuicStreamSequencerTest : public ::testing::Test {
return true;
}
- QuicSession* session_;
+ MockConnection* connection_;
+ MockSession session_;
testing::StrictMock<MockStream> stream_;
scoped_ptr<QuicStreamSequencerPeer> sequencer_;
};
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc
index ed0cac3..bf1601f 100644
--- a/net/quic/quic_utils.cc
+++ b/net/quic/quic_utils.cc
@@ -230,7 +230,7 @@ string QuicUtils::TagToString(QuicTag tag) {
for (size_t i = 0; i < sizeof(chars); i++) {
chars[i] = tag;
- if (chars[i] == 0 && i == 3) {
+ if ((chars[i] == 0 || chars[i] == '\xff') && i == 3) {
chars[i] = ' ';
}
if (!isprint(static_cast<unsigned char>(chars[i]))) {
diff --git a/net/quic/quic_utils_test.cc b/net/quic/quic_utils_test.cc
index 0e50aec..0a0355f 100644
--- a/net/quic/quic_utils_test.cc
+++ b/net/quic/quic_utils_test.cc
@@ -4,6 +4,7 @@
#include "net/quic/quic_utils.h"
+#include "net/quic/crypto/crypto_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -68,6 +69,21 @@ TEST(QuicUtilsTest, StringToHexASCIIDumpSuccess) {
string(reinterpret_cast<const char*>(kString), sizeof(kString))));
}
+TEST(QuicUtilsTest, TagToString) {
+ EXPECT_EQ("SCFG",
+ QuicUtils::TagToString(kSCFG));
+ EXPECT_EQ("SNO ",
+ QuicUtils::TagToString(kServerNonceTag));
+ EXPECT_EQ("CRT ",
+ QuicUtils::TagToString(kCertificateTag));
+ EXPECT_EQ("CHLO",
+ QuicUtils::TagToString(MakeQuicTag('C', 'H', 'L', 'O')));
+ // A tag that contains a non-printing character will be printed as a decimal
+ // number.
+ EXPECT_EQ("525092931",
+ QuicUtils::TagToString(MakeQuicTag('C', 'H', 'L', '\x1f')));
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index 0ac6ecd..afba1f0 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -61,7 +61,8 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
write_side_closed_(false),
priority_parsed_(false),
fin_buffered_(false),
- fin_sent_(false) {
+ fin_sent_(false),
+ is_server_(session_->is_server()) {
}
ReliableQuicStream::~ReliableQuicStream() {
@@ -82,7 +83,7 @@ bool ReliableQuicStream::WillAcceptStreamFrame(
bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK_EQ(frame.stream_id, id_);
if (read_side_closed_) {
- DLOG(INFO) << "Ignoring frame " << frame.stream_id;
+ DLOG(INFO) << ENDPOINT << "Ignoring frame " << frame.stream_id;
// We don't want to be reading: blackhole the data.
return true;
}
@@ -261,7 +262,7 @@ QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov,
int iov_count,
bool fin) {
if (write_side_closed_) {
- DLOG(ERROR) << "Attempt to write when the write side is closed";
+ DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
return QuicConsumedData(0, false);
}
@@ -293,11 +294,11 @@ void ReliableQuicStream::CloseReadSide() {
if (read_side_closed_) {
return;
}
- DLOG(INFO) << "Done reading from stream " << id();
+ DLOG(INFO) << ENDPOINT << "Done reading from stream " << id();
read_side_closed_ = true;
if (write_side_closed_) {
- DLOG(INFO) << "Closing stream: " << id();
+ DLOG(INFO) << ENDPOINT << "Closing stream: " << id();
session_->CloseStream(id());
}
}
@@ -338,7 +339,8 @@ uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
// Ensure that this header id looks sane.
if (headers_id_ < current_header_id ||
headers_id_ > kMaxHeaderIdDelta + current_header_id) {
- DVLOG(1) << "Invalid headers for stream: " << id()
+ DVLOG(1) << ENDPOINT
+ << "Invalid headers for stream: " << id()
<< " header_id: " << headers_id_
<< " current_header_id: " << current_header_id;
session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
@@ -348,7 +350,8 @@ uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
// If we are head-of-line blocked on decompression, then back up.
if (current_header_id != headers_id_) {
session_->MarkDecompressionBlocked(headers_id_, id());
- DVLOG(1) << "Unable to decompress header data for stream: " << id()
+ DVLOG(1) << ENDPOINT
+ << "Unable to decompress header data for stream: " << id()
<< " header_id: " << headers_id_;
return total_bytes_consumed;
}
@@ -463,11 +466,11 @@ void ReliableQuicStream::CloseWriteSide() {
if (write_side_closed_) {
return;
}
- DLOG(INFO) << "Done writing to stream " << id();
+ DLOG(INFO) << ENDPOINT << "Done writing to stream " << id();
write_side_closed_ = true;
if (read_side_closed_) {
- DLOG(INFO) << "Closing stream: " << id();
+ DLOG(INFO) << ENDPOINT << "Closing stream: " << id();
session_->CloseStream(id());
}
}
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h
index 52eb8aa..bc7d29c 100644
--- a/net/quic/reliable_quic_stream.h
+++ b/net/quic/reliable_quic_stream.h
@@ -28,6 +28,8 @@ class IPEndPoint;
class QuicSession;
class SSLInfo;
+#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
+
// All this does right now is send data to subclasses via the sequencer.
class NET_EXPORT_PRIVATE ReliableQuicStream : public
QuicSpdyDecompressor::Visitor {
@@ -224,6 +226,9 @@ class NET_EXPORT_PRIVATE ReliableQuicStream : public
bool priority_parsed_;
bool fin_buffered_;
bool fin_sent_;
+
+ // True if the session this stream is running under is a server session.
+ bool is_server_;
};
} // namespace net
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 73b5bab..76de7fa 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -136,7 +136,7 @@ int CryptoTestUtils::HandshakeWithFakeServer(
IPEndPoint addr = IPEndPoint(ip, 1);
PacketSavingConnection* server_conn =
new PacketSavingConnection(guid, addr, true);
- TestSession server_session(server_conn, QuicConfig(), true);
+ TestSession server_session(server_conn, DefaultQuicConfig(), true);
QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance());
@@ -169,7 +169,7 @@ int CryptoTestUtils::HandshakeWithFakeClient(
IPEndPoint addr = IPEndPoint(ip, 1);
PacketSavingConnection* client_conn =
new PacketSavingConnection(guid, addr, false);
- TestSession client_session(client_conn, QuicConfig(), false);
+ TestSession client_session(client_conn, DefaultQuicConfig(), false);
QuicCryptoClientConfig crypto_config;
client_session.config()->SetDefaults();
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index d2bc7e9..e1d148f 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -213,7 +213,7 @@ MockConnection::MockConnection(QuicGuid guid,
bool is_server)
: QuicConnection(guid, address, new testing::NiceMock<MockHelper>(),
new testing::NiceMock<MockPacketWriter>(),
- is_server, QuicVersionMax()),
+ is_server, QuicSupportedVersions()),
has_mock_helper_(true),
writer_(QuicConnectionPeer::GetWriter(this)),
helper_(helper()) {
@@ -225,7 +225,7 @@ MockConnection::MockConnection(QuicGuid guid,
QuicPacketWriter* writer,
bool is_server)
: QuicConnection(guid, address, helper, writer, is_server,
- QuicVersionMax()),
+ QuicSupportedVersions()),
has_mock_helper_(false) {
}
@@ -350,12 +350,17 @@ string HexDumpWithMarks(const char* data, int length,
} // namespace
+QuicVersion QuicVersionMax() { return QuicSupportedVersions().front(); }
+
+QuicVersion QuicVersionMin() { return QuicSupportedVersions().back(); }
+
void CompareCharArraysWithHexError(
const string& description,
const char* actual,
const int actual_len,
const char* expected,
const int expected_len) {
+ EXPECT_EQ(actual_len, expected_len);
const int min_len = min(actual_len, expected_len);
const int max_len = max(actual_len, expected_len);
scoped_ptr<bool[]> marks(new bool[max_len]);
@@ -387,7 +392,7 @@ static QuicPacket* ConstructPacketFromHandshakeMessage(
bool should_include_version) {
CryptoFramer crypto_framer;
scoped_ptr<QuicData> data(crypto_framer.ConstructHandshakeMessage(message));
- QuicFramer quic_framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer quic_framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicPacketHeader header;
header.public_header.guid = guid;
@@ -421,13 +426,12 @@ size_t GetPacketLengthForOneStream(
InFecGroup is_in_fec_group,
size_t* payload_length) {
*payload_length = 1;
- bool use_short_hash = version >= QUIC_VERSION_11;
const size_t stream_length =
- NullEncrypter(use_short_hash).GetCiphertextSize(*payload_length) +
+ NullEncrypter(false).GetCiphertextSize(*payload_length) +
QuicPacketCreator::StreamFramePacketOverhead(
version, PACKET_8BYTE_GUID, include_version,
sequence_number_length, is_in_fec_group);
- const size_t ack_length = NullEncrypter(use_short_hash).GetCiphertextSize(
+ const size_t ack_length = NullEncrypter(false).GetCiphertextSize(
QuicFramer::GetMinAckFrameSize()) +
GetPacketHeaderSize(PACKET_8BYTE_GUID, include_version,
sequence_number_length, is_in_fec_group);
@@ -435,7 +439,7 @@ size_t GetPacketLengthForOneStream(
*payload_length = 1 + ack_length - stream_length;
}
- return NullEncrypter(use_short_hash).GetCiphertextSize(*payload_length) +
+ return NullEncrypter(false).GetCiphertextSize(*payload_length) +
QuicPacketCreator::StreamFramePacketOverhead(
version, PACKET_8BYTE_GUID, include_version,
sequence_number_length, is_in_fec_group);
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 2992125..3ad8e3d 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -25,6 +25,12 @@ namespace net {
namespace test {
+// Upper limit on versions we support.
+QuicVersion QuicVersionMax();
+
+// Lower limit on versions we support.
+QuicVersion QuicVersionMin();
+
void CompareCharArraysWithHexError(const std::string& description,
const char* actual,
const int actual_len,
@@ -360,6 +366,8 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
MOCK_METHOD0(BandwidthEstimate, QuicBandwidth(void));
MOCK_METHOD0(SmoothedRtt, QuicTime::Delta(void));
MOCK_METHOD0(RetransmissionDelay, QuicTime::Delta(void));
+ MOCK_METHOD0(GetCongestionWindow, QuicByteCount());
+ MOCK_METHOD1(SetCongestionWindow, void(QuicByteCount));
private:
DISALLOW_COPY_AND_ASSIGN(MockSendAlgorithm);
diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc
index 46be3a8..bb61a12 100644
--- a/net/quic/test_tools/simple_quic_framer.cc
+++ b/net/quic/test_tools/simple_quic_framer.cc
@@ -128,7 +128,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
};
SimpleQuicFramer::SimpleQuicFramer()
- : framer_(QuicVersionMax(), QuicTime::Zero(), true) {
+ : framer_(QuicSupportedVersions(), QuicTime::Zero(), true) {
}
SimpleQuicFramer::~SimpleQuicFramer() {
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index adedabb..b0a963f 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -70,22 +70,65 @@ void GenerateBody(string* body, int length) {
// Run all tests with the cross products of all versions
// and all values of FLAGS_pad_quic_handshake_packets.
struct TestParams {
- TestParams(QuicVersion version,
+ TestParams(const QuicVersionVector& client_supported_versions,
+ const QuicVersionVector& server_supported_versions,
+ QuicVersion negotiated_version,
bool use_padding)
- : version(version),
+ : client_supported_versions(client_supported_versions),
+ server_supported_versions(server_supported_versions),
+ negotiated_version(negotiated_version),
use_padding(use_padding) {
}
- QuicVersion version;
+ QuicVersionVector client_supported_versions;
+ QuicVersionVector server_supported_versions;
+ QuicVersion negotiated_version;
bool use_padding;
};
-// Constructs all the various test permutations.
+// Constructs various test permutations.
vector<TestParams> GetTestParams() {
vector<TestParams> params;
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- params.push_back(TestParams(kSupportedQuicVersions[i], true));
- params.push_back(TestParams(kSupportedQuicVersions[i], false));
+ QuicVersionVector all_supported_versions = QuicSupportedVersions();
+
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(all_supported_versions, all_supported_versions,
+ all_supported_versions[0], true));
+ params.push_back(TestParams(all_supported_versions, all_supported_versions,
+ all_supported_versions[0], false));
+
+ // Test client supporting 1 version and server supporting all versions.
+ // Simulate an old client and exercise version downgrade in the server.
+ // No protocol negotiation should occur. Skip the i = 0 case because it
+ // is essentially the same as the default case.
+ for (size_t i = 1; i < all_supported_versions.size(); ++i) {
+ QuicVersionVector client_supported_versions;
+ client_supported_versions.push_back(all_supported_versions[i]);
+ params.push_back(TestParams(client_supported_versions,
+ all_supported_versions,
+ client_supported_versions[0],
+ true));
+ params.push_back(TestParams(client_supported_versions,
+ all_supported_versions,
+ client_supported_versions[0],
+ false));
+ }
+
+ // Test client supporting all versions and server supporting 1 version.
+ // Simulate an old server and exercise version downgrade in the client.
+ // Protocol negotiation should occur. Skip the i = 0 case because it is
+ // essentially the same as the default case.
+ for (size_t i = 1; i < all_supported_versions.size(); ++i) {
+ QuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(all_supported_versions[i]);
+ params.push_back(TestParams(all_supported_versions,
+ server_supported_versions,
+ server_supported_versions[0],
+ true));
+ params.push_back(TestParams(all_supported_versions,
+ server_supported_versions,
+ server_supported_versions[0],
+ false));
}
return params;
}
@@ -109,12 +152,23 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
"HTTP/1.1", "200", "OK", kFooResponseBody);
AddToCache("GET", "https://www.google.com/bar",
"HTTP/1.1", "200", "OK", kBarResponseBody);
- version_ = GetParam().version;
- FLAGS_pad_quic_handshake_packets =
- GetParam().use_padding;
+
+ client_supported_versions_ = GetParam().client_supported_versions;
+ server_supported_versions_ = GetParam().server_supported_versions;
+ negotiated_version_ = GetParam().negotiated_version;
+ FLAGS_pad_quic_handshake_packets = GetParam().use_padding;
+ LOG(INFO) << "server running " << QuicVersionVectorToString(
+ server_supported_versions_);
+ LOG(INFO) << "client running " << QuicVersionVectorToString(
+ client_supported_versions_);
+ LOG(INFO) << "negotiated_version_ " << QuicVersionToString(
+ negotiated_version_);
+ LOG(INFO) << "use_padding " << GetParam().use_padding;
}
virtual ~EndToEndTest() {
+ // TODO(rtenneti): port RecycleUnusedPort if needed.
+ // RecycleUnusedPort(server_address_.port());
QuicInMemoryCachePeer::ResetForTests();
}
@@ -123,7 +177,7 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
server_hostname_,
false, // not secure
client_config_,
- version_);
+ client_supported_versions_);
client->UseWriter(writer);
client->Connect();
return client;
@@ -155,6 +209,7 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
void StartServer() {
server_thread_.reset(new ServerThread(server_address_, server_config_,
+ server_supported_versions_,
strike_register_no_startup_period_));
server_thread_->Start();
server_thread_->listening()->Wait();
@@ -217,7 +272,9 @@ class EndToEndTest : public ::testing::TestWithParam<TestParams> {
bool server_started_;
QuicConfig client_config_;
QuicConfig server_config_;
- QuicVersion version_;
+ QuicVersionVector client_supported_versions_;
+ QuicVersionVector server_supported_versions_;
+ QuicVersion negotiated_version_;
bool strike_register_no_startup_period_;
};
@@ -312,14 +369,12 @@ TEST_P(EndToEndTest, RequestOverMultiplePackets) {
const size_t kStreamDataLength = 3;
const QuicStreamId kStreamId = 1u;
const QuicStreamOffset kStreamOffset = 0u;
- size_t stream_payload_size =
- QuicFramer::GetMinStreamFrameSize(
- version_, kStreamId, kStreamOffset, true) + kStreamDataLength;
+ size_t stream_payload_size = QuicFramer::GetMinStreamFrameSize(
+ negotiated_version_, kStreamId, kStreamOffset, true) + kStreamDataLength;
size_t min_payload_size =
std::max(kCongestionFeedbackFrameSize, stream_payload_size);
- bool use_short_hash = version_ >= QUIC_VERSION_11;
size_t ciphertext_size =
- NullEncrypter(use_short_hash).GetCiphertextSize(min_payload_size);
+ NullEncrypter(false).GetCiphertextSize(min_payload_size);
// TODO(satyashekhar): Fix this when versioning is implemented.
client_->options()->max_packet_length =
GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
@@ -345,14 +400,12 @@ TEST_P(EndToEndTest, MultipleFramesRandomOrder) {
const size_t kStreamDataLength = 3;
const QuicStreamId kStreamId = 1u;
const QuicStreamOffset kStreamOffset = 0u;
- size_t stream_payload_size =
- QuicFramer::GetMinStreamFrameSize(
- version_, kStreamId, kStreamOffset, true) + kStreamDataLength;
+ size_t stream_payload_size = QuicFramer::GetMinStreamFrameSize(
+ negotiated_version_, kStreamId, kStreamOffset, true) + kStreamDataLength;
size_t min_payload_size =
std::max(kCongestionFeedbackFrameSize, stream_payload_size);
- bool use_short_hash = version_ >= QUIC_VERSION_11;
size_t ciphertext_size =
- NullEncrypter(use_short_hash).GetCiphertextSize(min_payload_size);
+ NullEncrypter(false).GetCiphertextSize(min_payload_size);
// TODO(satyashekhar): Fix this when versioning is implemented.
client_->options()->max_packet_length =
GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index b8cf6e9..b1fa935 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -32,7 +32,7 @@ const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
QuicClient::QuicClient(IPEndPoint server_address,
const string& server_hostname,
- const QuicVersion version,
+ const QuicVersionVector& supported_versions,
bool print_response)
: server_address_(server_address),
server_hostname_(server_hostname),
@@ -42,7 +42,7 @@ QuicClient::QuicClient(IPEndPoint server_address,
initialized_(false),
packets_dropped_(0),
overflow_supported_(false),
- version_(version),
+ supported_versions_(supported_versions),
print_response_(print_response) {
config_.SetDefaults();
}
@@ -50,7 +50,7 @@ QuicClient::QuicClient(IPEndPoint server_address,
QuicClient::QuicClient(IPEndPoint server_address,
const string& server_hostname,
const QuicConfig& config,
- const QuicVersion version)
+ const QuicVersionVector& supported_versions)
: server_address_(server_address),
server_hostname_(server_hostname),
config_(config),
@@ -60,7 +60,7 @@ QuicClient::QuicClient(IPEndPoint server_address,
initialized_(false),
packets_dropped_(0),
overflow_supported_(false),
- version_(version),
+ supported_versions_(supported_versions),
print_response_(false) {
}
@@ -155,14 +155,16 @@ bool QuicClient::Connect() {
bool QuicClient::StartConnect() {
DCHECK(!connected() && initialized_);
- if (!writer_.get()) {
- writer_.reset(CreateQuicPacketWriter());
+ QuicPacketWriter* writer = CreateQuicPacketWriter();
+ if (writer_.get() != writer) {
+ writer_.reset(writer);
}
+
session_.reset(new QuicClientSession(
server_hostname_,
config_,
new QuicConnection(GenerateGuid(), server_address_, helper_.get(),
- writer_.get(), false, version_),
+ writer_.get(), false, supported_versions_),
&crypto_config_));
return session_->CryptoConnect();
}
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index c8e65a1..4835f4b 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -39,12 +39,12 @@ class QuicClient : public EpollCallbackInterface,
public:
QuicClient(IPEndPoint server_address,
const string& server_hostname,
- const QuicVersion version,
+ const QuicVersionVector& supported_versions,
bool print_response);
QuicClient(IPEndPoint server_address,
const std::string& server_hostname,
const QuicConfig& config,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
virtual ~QuicClient();
@@ -201,8 +201,12 @@ class QuicClient : public EpollCallbackInterface,
// because the socket would otherwise overflow.
bool overflow_supported_;
- // Which QUIC version does this client talk?
- QuicVersion version_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary). We will always pick supported_versions_[0] as the
+ // initial version to use.
+ QuicVersionVector supported_versions_;
// If true, then the contents of each response will be printed to stdout
// when the stream is closed (in OnClose).
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc
index 5591b87..2f8cfac 100644
--- a/net/tools/quic/quic_client_bin.cc
+++ b/net/tools/quic/quic_client_bin.cc
@@ -59,8 +59,9 @@ int main(int argc, char *argv[]) {
net::IPAddressNumber addr;
CHECK(net::ParseIPLiteralToNumber(FLAGS_address, &addr));
// TODO(rjshade): Set version on command line.
- net::tools::QuicClient client(net::IPEndPoint(addr, FLAGS_port),
- FLAGS_hostname, net::QuicVersionMax(), true);
+ net::tools::QuicClient client(
+ net::IPEndPoint(addr, FLAGS_port), FLAGS_hostname,
+ net::QuicSupportedVersions(), true);
client.Initialize();
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index d5b63a8..50201c9 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -13,9 +13,10 @@
#include "net/tools/quic/quic_reliable_client_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
-using testing::_;
using net::test::CryptoTestUtils;
+using net::test::DefaultQuicConfig;
using net::test::PacketSavingConnection;
+using testing::_;
namespace net {
namespace tools {
@@ -30,7 +31,7 @@ class ToolsQuicClientSessionTest : public ::testing::Test {
: guid_(1),
connection_(new PacketSavingConnection(guid_, IPEndPoint(), false)) {
crypto_config_.SetDefaults();
- session_.reset(new QuicClientSession(kServerHostname, QuicConfig(),
+ session_.reset(new QuicClientSession(kServerHostname, DefaultQuicConfig(),
connection_, &crypto_config_));
session_->config()->SetDefaults();
}
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index 0ec5470..2e7b9e6 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -37,18 +37,20 @@ class DeleteSessionsAlarm : public EpollAlarm {
QuicDispatcher::QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
+ const QuicVersionVector& supported_versions,
int fd,
EpollServer* epoll_server)
: config_(config),
crypto_config_(crypto_config),
time_wait_list_manager_(
- new QuicTimeWaitListManager(this, epoll_server)),
+ new QuicTimeWaitListManager(this, epoll_server, supported_versions)),
delete_sessions_alarm_(new DeleteSessionsAlarm(this)),
epoll_server_(epoll_server),
fd_(fd),
write_blocked_(false),
helper_(new QuicEpollConnectionHelper(epoll_server_)),
- writer_(new QuicDefaultPacketWriter(fd)) {
+ writer_(new QuicDefaultPacketWriter(fd)),
+ supported_versions_(supported_versions) {
}
QuicDispatcher::~QuicDispatcher() {
@@ -102,9 +104,10 @@ void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
if (session == NULL) {
DLOG(INFO) << "Failed to create session for " << guid;
- // Add this guid fo the time-wait state, to safely nack future packets.
+ // Add this guid fo the time-wait state, to safely reject future packets.
// We don't know the version here, so assume latest.
- time_wait_list_manager_->AddGuidToTimeWait(guid, QuicVersionMax());
+ time_wait_list_manager_->AddGuidToTimeWait(guid,
+ supported_versions_.front());
time_wait_list_manager_->ProcessPacket(server_address,
client_address,
guid,
@@ -202,7 +205,7 @@ QuicSession* QuicDispatcher::CreateQuicSession(
const IPEndPoint& client_address) {
QuicServerSession* session = new QuicServerSession(
config_, new QuicConnection(guid, client_address, helper_.get(), this,
- true, QuicVersionMax()), this);
+ true, supported_versions_), this);
session->InitializeSession(crypto_config_);
return session;
}
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index c20c356..280f8b2 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -55,9 +55,11 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
typedef linked_hash_map<QuicBlockedWriterInterface*, bool> WriteBlockedList;
// Due to the way delete_sessions_closure_ is registered, the Dispatcher
- // must live until epoll_server Shutdown.
+ // must live until epoll_server Shutdown. |supported_versions| specifies the
+ // list of supported QUIC versions.
QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
+ const QuicVersionVector& supported_versions,
int fd,
EpollServer* epoll_server);
virtual ~QuicDispatcher();
@@ -118,6 +120,10 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
QuicEpollConnectionHelper* helper() { return helper_.get(); }
EpollServer* epoll_server() { return epoll_server_; }
+ const QuicVersionVector& supported_versions() const {
+ return supported_versions_;
+ }
+
private:
friend class net::tools::test::QuicDispatcherPeer;
@@ -154,6 +160,12 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
// The writer to write to the socket with.
scoped_ptr<QuicPacketWriter> writer_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary).
+ const QuicVersionVector supported_versions_;
+
DISALLOW_COPY_AND_ASSIGN(QuicDispatcher);
};
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index a3e6885..90b3074 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -41,7 +41,8 @@ class TestDispatcher : public QuicDispatcher {
explicit TestDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, 1, eps) {}
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), 1, eps) {
+ }
MOCK_METHOD2(CreateQuicSession, QuicSession*(
QuicGuid guid,
@@ -174,7 +175,7 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
public:
MockTimeWaitListManager(QuicPacketWriter* writer,
EpollServer* eps)
- : QuicTimeWaitListManager(writer, eps) {
+ : QuicTimeWaitListManager(writer, eps, QuicSupportedVersions()) {
}
MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
diff --git a/net/tools/quic/quic_epoll_connection_helper_test.cc b/net/tools/quic/quic_epoll_connection_helper_test.cc
index eec3e0c..7d09d0b 100644
--- a/net/tools/quic/quic_epoll_connection_helper_test.cc
+++ b/net/tools/quic/quic_epoll_connection_helper_test.cc
@@ -41,7 +41,7 @@ class TestWriter : public QuicPacketWriter {
const IPAddressNumber& self_address,
const IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), true);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), true);
FramerVisitorCapturingFrames visitor;
framer.set_visitor(&visitor);
QuicEncryptedPacket packet(buffer, buf_len);
@@ -67,7 +67,8 @@ class TestConnection : public QuicConnection {
IPEndPoint address,
QuicEpollConnectionHelper* helper,
TestWriter* writer)
- : QuicConnection(guid, address, helper, writer, false, QuicVersionMax()) {
+ : QuicConnection(guid, address, helper, writer, false,
+ QuicSupportedVersions()) {
}
void SendAck() {
@@ -83,7 +84,7 @@ class QuicEpollConnectionHelperTest : public ::testing::Test {
protected:
QuicEpollConnectionHelperTest()
: guid_(42),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
send_algorithm_(new testing::StrictMock<MockSendAlgorithm>),
helper_(&epoll_server_),
connection_(guid_, IPEndPoint(), &helper_, &writer_),
diff --git a/net/tools/quic/quic_reliable_client_stream_test.cc b/net/tools/quic/quic_reliable_client_stream_test.cc
index d004fac..bdb97cc 100644
--- a/net/tools/quic/quic_reliable_client_stream_test.cc
+++ b/net/tools/quic/quic_reliable_client_stream_test.cc
@@ -15,6 +15,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using net::test::DefaultQuicConfig;
using testing::TestWithParam;
namespace net {
@@ -25,7 +26,7 @@ namespace {
class QuicClientStreamTest : public ::testing::Test {
public:
QuicClientStreamTest()
- : session_("example.com", QuicConfig(),
+ : session_("example.com", DefaultQuicConfig(),
new MockConnection(1, IPEndPoint(), 0, &eps_, false),
&crypto_config_),
body_("hello world") {
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index a5c1e5b..66a9aa9 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -39,20 +39,23 @@ QuicServer::QuicServer()
packets_dropped_(0),
overflow_supported_(false),
use_recvmmsg_(false),
- crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()) {
+ crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
+ supported_versions_(QuicSupportedVersions()) {
// Use hardcoded crypto parameters for now.
config_.SetDefaults();
Initialize();
}
-QuicServer::QuicServer(const QuicConfig& config)
+QuicServer::QuicServer(const QuicConfig& config,
+ const QuicVersionVector& supported_versions)
: port_(0),
fd_(-1),
packets_dropped_(0),
overflow_supported_(false),
use_recvmmsg_(false),
config_(config),
- crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()) {
+ crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
+ supported_versions_(supported_versions) {
Initialize();
}
@@ -141,8 +144,9 @@ bool QuicServer::Listen(const IPEndPoint& address) {
}
epoll_server_.RegisterFD(fd_, this, kEpollFlags);
- dispatcher_.reset(new QuicDispatcher(config_, crypto_config_, fd_,
- &epoll_server_));
+ dispatcher_.reset(new QuicDispatcher(config_, crypto_config_,
+ supported_versions_,
+ fd_, &epoll_server_));
return true;
}
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h
index 5fee644..f166555 100644
--- a/net/tools/quic/quic_server.h
+++ b/net/tools/quic/quic_server.h
@@ -29,7 +29,8 @@ class QuicDispatcher;
class QuicServer : public EpollCallbackInterface {
public:
QuicServer();
- explicit QuicServer(const QuicConfig& config);
+ QuicServer(const QuicConfig& config,
+ const QuicVersionVector& supported_versions);
virtual ~QuicServer();
@@ -114,6 +115,12 @@ class QuicServer : public EpollCallbackInterface {
// crypto_config_ contains crypto parameters for the handshake.
QuicCryptoServerConfig crypto_config_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary).
+ QuicVersionVector supported_versions_;
+
DISALLOW_COPY_AND_ASSIGN(QuicServer);
};
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index 345ddb2..98d129b 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -92,8 +92,9 @@ class QuicTimeWaitListManager::QueuedPacket {
QuicTimeWaitListManager::QuicTimeWaitListManager(
QuicPacketWriter* writer,
- EpollServer* epoll_server)
- : framer_(QuicVersionMax(),
+ EpollServer* epoll_server,
+ const QuicVersionVector& supported_versions)
+ : framer_(supported_versions,
QuicTime::Zero(), // unused
true),
epoll_server_(epoll_server),
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h
index 50c70fa..f208395 100644
--- a/net/tools/quic/quic_time_wait_list_manager.h
+++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -37,7 +37,8 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface,
// writer - the entity that writes to the socket. (Owned by the dispatcher)
// epoll_server - used to run clean up alarms. (Owned by the dispatcher)
QuicTimeWaitListManager(QuicPacketWriter* writer,
- EpollServer* epoll_server);
+ EpollServer* epoll_server,
+ const QuicVersionVector& supported_versions);
virtual ~QuicTimeWaitListManager();
// Adds the given guid to time wait state for kTimeWaitPeriod. Henceforth,
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 38a4394..92d1fc4 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -38,7 +38,7 @@ class TestTimeWaitListManager : public QuicTimeWaitListManager {
public:
TestTimeWaitListManager(QuicPacketWriter* writer,
EpollServer* epoll_server)
- : QuicTimeWaitListManager(writer, epoll_server) {
+ : QuicTimeWaitListManager(writer, epoll_server, QuicSupportedVersions()) {
}
using QuicTimeWaitListManager::is_write_blocked;
@@ -57,16 +57,14 @@ class QuicTimeWaitListManagerTest : public testing::Test {
protected:
QuicTimeWaitListManagerTest()
: time_wait_list_manager_(&writer_, &epoll_server_),
- framer_(QuicVersionMax(),
- QuicTime::Zero(),
- true),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
guid_(45) {
}
virtual ~QuicTimeWaitListManagerTest() {}
void AddGuid(QuicGuid guid) {
- time_wait_list_manager_.AddGuidToTimeWait(guid, QuicVersionMax());
+ time_wait_list_manager_.AddGuidToTimeWait(guid, test::QuicVersionMax());
}
void AddGuid(QuicGuid guid, QuicVersion version) {
@@ -134,7 +132,7 @@ class ValidatePublicResetPacketPredicate
const std::tr1::tuple<const char*, int> packet_buffer,
testing::MatchResultListener* /* listener */) const {
FramerVisitorCapturingPublicReset visitor;
- QuicFramer framer(QuicVersionMax(),
+ QuicFramer framer(QuicSupportedVersions(),
QuicTime::Zero(),
false);
framer.set_visitor(&visitor);
@@ -161,9 +159,7 @@ void ValidPublicResetPacketPredicate(
QuicPacketSequenceNumber expected_sequence_number,
const std::tr1::tuple<const char*, int>& packet_buffer) {
FramerVisitorCapturingPublicReset visitor;
- QuicFramer framer(QuicVersionMax(),
- QuicTime::Zero(),
- false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
framer.set_visitor(&visitor);
QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer),
std::tr1::get<1>(packet_buffer));
@@ -350,28 +346,28 @@ TEST_F(QuicTimeWaitListManagerTest, MakeSureFramerUsesCorrectVersion) {
const int kRandomSequenceNumber = 1;
scoped_ptr<QuicEncryptedPacket> packet;
- AddGuid(guid_, QuicVersionMin());
- framer_.set_version(QuicVersionMin());
+ AddGuid(guid_, test::QuicVersionMin());
+ framer_.set_version(test::QuicVersionMin());
packet.reset(ConstructEncryptedPacket(guid_, kRandomSequenceNumber));
// Reset packet should be written, using the minimum quic version.
EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(1)
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
ProcessPacket(guid_, *packet);
- EXPECT_EQ(time_wait_list_manager_.version(), QuicVersionMin());
+ EXPECT_EQ(time_wait_list_manager_.version(), test::QuicVersionMin());
// New guid
++guid_;
- AddGuid(guid_, QuicVersionMax());
- framer_.set_version(QuicVersionMax());
+ AddGuid(guid_, test::QuicVersionMax());
+ framer_.set_version(test::QuicVersionMax());
packet.reset(ConstructEncryptedPacket(guid_, kRandomSequenceNumber));
// Reset packet should be written, using the maximum quic version.
EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(1)
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
ProcessPacket(guid_, *packet);
- EXPECT_EQ(time_wait_list_manager_.version(), QuicVersionMax());
+ EXPECT_EQ(time_wait_list_manager_.version(), test::QuicVersionMax());
}
TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
@@ -379,15 +375,15 @@ TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
const int kGuid2 = 456;
const int kGuid3 = 789;
- AddGuid(kGuid1, QuicVersionMin());
- AddGuid(kGuid2, QuicVersionMax());
- AddGuid(kGuid3, QuicVersionMax());
+ AddGuid(kGuid1, test::QuicVersionMin());
+ AddGuid(kGuid2, test::QuicVersionMax());
+ AddGuid(kGuid3, test::QuicVersionMax());
- EXPECT_EQ(QuicVersionMin(),
+ EXPECT_EQ(test::QuicVersionMin(),
time_wait_list_manager_.GetQuicVersionFromGuid(kGuid1));
- EXPECT_EQ(QuicVersionMax(),
+ EXPECT_EQ(test::QuicVersionMax(),
time_wait_list_manager_.GetQuicVersionFromGuid(kGuid2));
- EXPECT_EQ(QuicVersionMax(),
+ EXPECT_EQ(test::QuicVersionMax(),
time_wait_list_manager_.GetQuicVersionFromGuid(kGuid3));
}
diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.cc b/net/tools/quic/test_tools/mock_quic_dispatcher.cc
index 3a2b1d9..2d9c1ec 100644
--- a/net/tools/quic/test_tools/mock_quic_dispatcher.cc
+++ b/net/tools/quic/test_tools/mock_quic_dispatcher.cc
@@ -13,7 +13,9 @@ MockQuicDispatcher::MockQuicDispatcher(
const QuicCryptoServerConfig& crypto_config,
QuicGuid guid,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, guid, eps) { }
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), guid,
+ eps) {
+}
MockQuicDispatcher::~MockQuicDispatcher() {}
} // namespace test
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.cc b/net/tools/quic/test_tools/packet_dropping_test_writer.cc
index 8ea2992..872b2a2 100644
--- a/net/tools/quic/test_tools/packet_dropping_test_writer.cc
+++ b/net/tools/quic/test_tools/packet_dropping_test_writer.cc
@@ -4,6 +4,8 @@
#include "net/tools/quic/test_tools/packet_dropping_test_writer.h"
+#include <limits>
+
#include "base/rand_util.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_socket_utils.h"
@@ -49,11 +51,12 @@ class DelayAlarm : public QuicAlarm::Delegate {
PacketDroppingTestWriter::PacketDroppingTestWriter()
: clock_(NULL),
blocked_writer_(NULL),
+ config_mutex_(),
fake_packet_loss_percentage_(0),
fake_blocked_socket_percentage_(0),
fake_packet_reorder_percentage_(0),
fake_packet_delay_(QuicTime::Delta::Zero()) {
- int64 seed = base::RandUint64();
+ uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max());
LOG(INFO) << "Seeding packet loss with " << seed;
simple_random_.set_seed(seed);
}
@@ -74,6 +77,7 @@ WriteResult PacketDroppingTestWriter::WritePacket(
const net::IPAddressNumber& self_address,
const net::IPEndPoint& peer_address,
QuicBlockedWriterInterface* blocked_writer) {
+ base::AutoLock locked(config_mutex_);
if (fake_packet_loss_percentage_ > 0 &&
simple_random_.RandUint64() % 100 <
static_cast<uint64>(fake_packet_loss_percentage_)) {
@@ -98,7 +102,7 @@ WriteResult PacketDroppingTestWriter::WritePacket(
// Queue it to be sent.
QuicTime send_time = clock_->ApproximateNow().Add(fake_packet_delay_);
delayed_packets_.push_back(DelayedWrite(buffer, buf_len, self_address,
- peer_address, send_time));
+ peer_address, send_time));
// Set the alarm if it's not yet set.
if (!delay_alarm_->IsSet()) {
delay_alarm_->Set(send_time);
@@ -119,6 +123,7 @@ QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
if (delayed_packets_.empty()) {
return QuicTime::Zero();
}
+ base::AutoLock locked(config_mutex_);
DelayedPacketList::iterator iter = delayed_packets_.begin();
// Determine if we should re-order.
if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 &&
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.h b/net/tools/quic/test_tools/packet_dropping_test_writer.h
index 943551e..d35f67f 100644
--- a/net/tools/quic/test_tools/packet_dropping_test_writer.h
+++ b/net/tools/quic/test_tools/packet_dropping_test_writer.h
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
#include "net/quic/quic_alarm.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_packet_writer.h"
@@ -49,6 +50,7 @@ class PacketDroppingTestWriter : public net::test::QuicTestWriter {
// The percent of time a packet is simulated as being lost.
void set_fake_packet_loss_percentage(int32 fake_packet_loss_percentage) {
+ base::AutoLock locked(config_mutex_);
fake_packet_loss_percentage_ = fake_packet_loss_percentage;
}
@@ -57,12 +59,14 @@ class PacketDroppingTestWriter : public net::test::QuicTestWriter {
void set_fake_blocked_socket_percentage(
int32 fake_blocked_socket_percentage) {
DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
fake_blocked_socket_percentage_ = fake_blocked_socket_percentage;
}
// The percent of time a packet is simulated as being reordered.
void set_fake_reorder_percentage(int32 fake_packet_reorder_percentage) {
DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
DCHECK(!fake_packet_delay_.IsZero());
fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
}
@@ -71,6 +75,7 @@ class PacketDroppingTestWriter : public net::test::QuicTestWriter {
// to WRITE_STATUS_BLOCKED.
void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
fake_packet_delay_ = fake_packet_delay;
}
@@ -101,12 +106,14 @@ class PacketDroppingTestWriter : public net::test::QuicTestWriter {
scoped_ptr<QuicAlarm> write_unblocked_alarm_;
scoped_ptr<QuicAlarm> delay_alarm_;
QuicBlockedWriterInterface* blocked_writer_;
+ SimpleRandom simple_random_;
+ DelayedPacketList delayed_packets_;
+
+ base::Lock config_mutex_;
int32 fake_packet_loss_percentage_;
int32 fake_blocked_socket_percentage_;
int32 fake_packet_reorder_percentage_;
QuicTime::Delta fake_packet_delay_;
- SimpleRandom simple_random_;
- DelayedPacketList delayed_packets_;
DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter);
};
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index b4094a4..c188d5e 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -101,16 +101,16 @@ class QuicEpollClient : public QuicClient {
QuicEpollClient(IPEndPoint server_address,
const string& server_hostname,
- const QuicVersion version)
- : Super(server_address, server_hostname, version, false),
+ const QuicVersionVector& supported_versions)
+ : Super(server_address, server_hostname, supported_versions, false),
override_guid_(0), test_writer_(NULL) {
}
QuicEpollClient(IPEndPoint server_address,
const string& server_hostname,
const QuicConfig& config,
- const QuicVersion version)
- : Super(server_address, server_hostname, config, version),
+ const QuicVersionVector& supported_versions)
+ : Super(server_address, server_hostname, config, supported_versions),
override_guid_(0), test_writer_(NULL) {
}
@@ -146,16 +146,16 @@ class QuicEpollClient : public QuicClient {
};
QuicTestClient::QuicTestClient(IPEndPoint address, const string& hostname,
- const QuicVersion version)
- : client_(new QuicEpollClient(address, hostname, version)) {
+ const QuicVersionVector& supported_versions)
+ : client_(new QuicEpollClient(address, hostname, supported_versions)) {
Initialize(address, hostname, true);
}
QuicTestClient::QuicTestClient(IPEndPoint address,
const string& hostname,
bool secure,
- const QuicVersion version)
- : client_(new QuicEpollClient(address, hostname, version)) {
+ const QuicVersionVector& supported_versions)
+ : client_(new QuicEpollClient(address, hostname, supported_versions)) {
Initialize(address, hostname, secure);
}
@@ -163,8 +163,9 @@ QuicTestClient::QuicTestClient(IPEndPoint address,
const string& hostname,
bool secure,
const QuicConfig& config,
- const QuicVersion version)
- : client_(new QuicEpollClient(address, hostname, config, version)) {
+ const QuicVersionVector& supported_versions)
+ : client_(new QuicEpollClient(address, hostname, config,
+ supported_versions)) {
Initialize(address, hostname, secure);
}
@@ -303,7 +304,9 @@ void QuicTestClient::ResetConnection() {
}
void QuicTestClient::Disconnect() {
- client_->Disconnect();
+ if (client_->connected()) {
+ client_->Disconnect();
+ }
connect_attempted_ = false;
}
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index b6629fd..c493b8c 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -29,16 +29,16 @@ class HTTPMessage;
class QuicTestClient : public ReliableQuicStream::Visitor {
public:
QuicTestClient(IPEndPoint server_address, const string& server_hostname,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
QuicTestClient(IPEndPoint server_address,
const string& server_hostname,
bool secure,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
QuicTestClient(IPEndPoint server_address,
const string& server_hostname,
bool secure,
const QuicConfig& config,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
virtual ~QuicTestClient();
diff --git a/net/tools/quic/test_tools/quic_test_utils.cc b/net/tools/quic/test_tools/quic_test_utils.cc
index 7222e1e..054c7fb 100644
--- a/net/tools/quic/test_tools/quic_test_utils.cc
+++ b/net/tools/quic/test_tools/quic_test_utils.cc
@@ -17,6 +17,10 @@ namespace net {
namespace tools {
namespace test {
+QuicVersion QuicVersionMax() { return QuicSupportedVersions().front(); }
+
+QuicVersion QuicVersionMin() { return QuicSupportedVersions().back(); }
+
MockConnection::MockConnection(QuicGuid guid,
IPEndPoint address,
int fd,
@@ -25,7 +29,7 @@ MockConnection::MockConnection(QuicGuid guid,
: QuicConnection(guid, address,
new QuicEpollConnectionHelper(eps),
new QuicDefaultPacketWriter(fd), is_server,
- QuicVersionMax()),
+ QuicSupportedVersions()),
has_mock_helper_(false),
writer_(net::test::QuicConnectionPeer::GetWriter(this)),
helper_(helper()) {
@@ -36,7 +40,7 @@ MockConnection::MockConnection(QuicGuid guid,
bool is_server)
: QuicConnection(guid, address, new testing::NiceMock<MockHelper>(),
new testing::NiceMock<MockPacketWriter>(),
- is_server, QuicVersionMax()),
+ is_server, QuicSupportedVersions()),
has_mock_helper_(true),
writer_(net::test::QuicConnectionPeer::GetWriter(this)),
helper_(helper()) {
@@ -48,7 +52,7 @@ MockConnection::MockConnection(QuicGuid guid,
QuicPacketWriter* writer,
bool is_server)
: QuicConnection(guid, address, helper, writer, is_server,
- QuicVersionMax()),
+ QuicSupportedVersions()),
has_mock_helper_(false) {
}
diff --git a/net/tools/quic/test_tools/quic_test_utils.h b/net/tools/quic/test_tools/quic_test_utils.h
index 3ea1283..52b74c1 100644
--- a/net/tools/quic/test_tools/quic_test_utils.h
+++ b/net/tools/quic/test_tools/quic_test_utils.h
@@ -24,6 +24,12 @@ class IPEndPoint;
namespace tools {
namespace test {
+// Upper limit on versions we support.
+QuicVersion QuicVersionMax();
+
+// Lower limit on versions we support.
+QuicVersion QuicVersionMin();
+
// Simple random number generator used to compute random numbers suitable
// for pseudo-randomly dropping packets in tests. It works by computing
// the sha1 hash of the current seed, and using the first 64 bits as
diff --git a/net/tools/quic/test_tools/server_thread.cc b/net/tools/quic/test_tools/server_thread.cc
index e82b3b3..dc41e09e 100644
--- a/net/tools/quic/test_tools/server_thread.cc
+++ b/net/tools/quic/test_tools/server_thread.cc
@@ -10,11 +10,12 @@ namespace test {
ServerThread::ServerThread(IPEndPoint address,
const QuicConfig& config,
+ const QuicVersionVector& supported_versions,
bool strike_register_no_startup_period)
: SimpleThread("server_thread"),
listening_(true, false),
quit_(true, false),
- server_(config),
+ server_(config, supported_versions),
address_(address),
port_(0) {
if (strike_register_no_startup_period) {
diff --git a/net/tools/quic/test_tools/server_thread.h b/net/tools/quic/test_tools/server_thread.h
index b4c904f..2011882 100644
--- a/net/tools/quic/test_tools/server_thread.h
+++ b/net/tools/quic/test_tools/server_thread.h
@@ -19,6 +19,7 @@ class ServerThread : public base::SimpleThread {
public:
ServerThread(IPEndPoint address,
const QuicConfig& config,
+ const QuicVersionVector& supported_versions,
bool strike_register_no_startup_period);
virtual ~ServerThread();