summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorjokulik <jokulik@chromium.org>2016-03-24 15:35:30 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-24 22:37:10 +0000
commitf2bd55c5ab99300b7df0a97b3d0ef16c9a2e584a (patch)
treea075e02a5d98fce698e53b975674271b17673b3b /net
parentef26d8f77ba056704780199893f1ebaf518136de (diff)
downloadchromium_src-f2bd55c5ab99300b7df0a97b3d0ef16c9a2e584a.zip
chromium_src-f2bd55c5ab99300b7df0a97b3d0ef16c9a2e584a.tar.gz
chromium_src-f2bd55c5ab99300b7df0a97b3d0ef16c9a2e584a.tar.bz2
Landing Recent QUIC changes until 3/18/2016 23:30 UTC
relnote: Add a QUIC end to end test of huge post. The test code has been added but is currently disabled, due to net_unittest timeout issues. Merge internal change: 117596033 https://codereview.chromium.org/1830253002/ relnote: Do not read rejected packet number in PUBLIC RESET packet. Merge internal change: 117595846 https://codereview.chromium.org/1834683002/ relnote: Trailers are now parsed and stored in QuicSpdyStream. Moved the TrailersWithoutOffset test to the parent QuicSpdyStreamTest. Deleted the ReceiveTrailersBeforeHeaders test entirely as it doesn't test useful behavior: it calls OnTrailingHeadersComplete directly but this is only ever called from within QuicSpdyStream (and subclasses). Switch to the new WriteOrBufferBody method. Merge internal change: 117582133 https://codereview.chromium.org/1832513004/ relnote: Move QuicSpdyClientStream::SendBody to QuicSpdyStream::WriteBody. Merge internal change: 117577200 https://codereview.chromium.org/1830043004/ relnote: Make ShouldCreate{Incoming,Outgoing}DynamicStream abstract methods in QuicSpdySession. No behavior change. Merge internal change: 117574127 https://codereview.chromium.org/1828123003/ relnote: Correctly set cmsg space for timestamping. Additionally, guard against future cmsg overflows. Not flag protected. The previous calculation for the cmsg space was too small by 8B. Merge internal change: 117568981 https://codereview.chromium.org/1828953002/ relnote: Creating a basic QUIC packet dumper Adding newlines to any logged quic frames Merge internal change: 117543172 https://codereview.chromium.org/1834593002/ relnote: Rename StreamSequencerBuffer to QuicStreamSequencerBuffer to bring it in line with other classes in //gfe/quic. No behavior change. Merge internal change: 117487896 https://codereview.chromium.org/1831723002/ relnote: Rename QuicSpdyStream::response_trailers_ to received_trailers_. No behavior change. QuicSpdyStream is used by servers and clients, received trailers could be request trailers. Merge internal change: 117483696 https://codereview.chromium.org/1822763002/ relnote: Introduces a QUIC_OVERLAPPING_STREAM_DATA error code, sent when receiving a stream frame containing data that overlaps with buffered data. Renames QUIC_INVALID_STREAM_FRAME to QUIC_EMPTY_STREAM_FRAME_NO_FIN Dan pointed out that QUIC_INVALID_STREAM_DATA is also used in the framer, making debugging the sequencer specific errors harder. Also the description of QUIC_INVALID_STREAM_DATA is that "STREAM frame data is malformed." which I don't think is true here: it's not malformed, it's just overlapping. Merge internal change: 117452324 https://codereview.chromium.org/1830063002/ relnote: Close QUIC connection if any error occurs in QuicStreamSequencerBuffer::OnStreamData. Flag protected behind default enabled --flag_quic_consolidate_onstreamframe_errors Flag protecting out of paranoia: new behavior is that if ever hit the QUIC_INTERNAL_ERROR branch in OnStreamData then we will now close the connection, whereas we did not before. Additionally a stream frame containing data which overlaps with existing data will now result in QUIC_INVALID_STREAM_DATA being sent on close, instead of QUIC_INVALID_STREAM_FRAME. Merge internal change: 117446575 https://codereview.chromium.org/1830773002/ relnote: Use SO_TIMESTAMPING for received packet timestamps. Guarded by flag_quic_use_socket_timestamp. This corrects the RTT for extremely low RTT connections (i.e. RTT < EpollServer iteration duration). This manifests as a ~1.5Gbps improvement in egress at 100% GFE CPU in the ustreamer load test, which while not indicative of reality, does bring it closer to the TCP+SSL load test behavior. In practice, this really just manages to reduce the number of calls to EpollServer::Now(). This is part of a broader set of changes to enable PACKET_RX_RING and all of the capabilities it provides, notably PACKET_TIMESTAMPING. Additionally, in QuicPacketReader's plain recvmsg path, ensure the returned server IP is valid as is done in the recvmmsg path. Merge internal change: 117434383 https://codereview.chromium.org/1828863002/ relnote: Remove QuicStreamSequencerBufferInterface that only has a single implementation. No behavior change. Merge internal change: 117397110 https://codereview.chromium.org/1823803003/ relnote: Report no client nonce as INCHOATE_HELLO_FAILURE. Merge internal change: 117371001 https://codereview.chromium.org/1820383002/ relnote: Add and plumb QuicReceivedPacket in the packet reception path. Optionally use its timestamp, guarded by gfe2_restart_flag_quic_use_socket_timestamp. This is part of a broader set of changes to enable socket-level timestamping and to enable PACKET_RX_RING with all of the capabilities it provides. Merge internal change: 117362867 https://codereview.chromium.org/1821843003/ relnote: Add QUIC 32 in which FEC related fields are removed from private flags and revived packet list are removed from ACK frame. Merge internal change: 117278937 https://codereview.chromium.org/1817223002/ relnote: rename QuicSpdyClientStream::headers to response_headers Merge internal change: 117272106 https://codereview.chromium.org/1822763002/ R=rch@chromium.org BUG= Review URL: https://codereview.chromium.org/1832953002 Cr-Commit-Position: refs/heads/master@{#383171}
Diffstat (limited to 'net')
-rw-r--r--net/net.gypi6
-rw-r--r--net/quic/bidirectional_stream_quic_impl_unittest.cc32
-rw-r--r--net/quic/crypto/crypto_server_test.cc38
-rw-r--r--net/quic/crypto/quic_crypto_server_config.cc14
-rw-r--r--net/quic/p2p/quic_p2p_session.cc2
-rw-r--r--net/quic/p2p/quic_p2p_session.h4
-rw-r--r--net/quic/quic_chromium_client_session.cc22
-rw-r--r--net/quic/quic_chromium_client_session.h6
-rw-r--r--net/quic/quic_chromium_client_stream.cc2
-rw-r--r--net/quic/quic_chromium_client_stream_test.cc4
-rw-r--r--net/quic/quic_chromium_packet_reader.cc2
-rw-r--r--net/quic/quic_chromium_packet_reader.h2
-rw-r--r--net/quic/quic_connection.cc16
-rw-r--r--net/quic/quic_connection.h2
-rw-r--r--net/quic/quic_connection_test.cc38
-rw-r--r--net/quic/quic_crypto_server_stream_test.cc2
-rw-r--r--net/quic/quic_flags.cc8
-rw-r--r--net/quic/quic_flags.h2
-rw-r--r--net/quic/quic_framer.cc41
-rw-r--r--net/quic/quic_framer_test.cc603
-rw-r--r--net/quic/quic_http_stream_test.cc38
-rw-r--r--net/quic/quic_protocol.cc52
-rw-r--r--net/quic/quic_protocol.h45
-rw-r--r--net/quic/quic_session.cc2
-rw-r--r--net/quic/quic_session.h2
-rw-r--r--net/quic/quic_session_test.cc12
-rw-r--r--net/quic/quic_spdy_session.h6
-rw-r--r--net/quic/quic_spdy_stream.cc9
-rw-r--r--net/quic/quic_spdy_stream.h11
-rw-r--r--net/quic/quic_spdy_stream_test.cc29
-rw-r--r--net/quic/quic_stream_sequencer.cc36
-rw-r--r--net/quic/quic_stream_sequencer.h4
-rw-r--r--net/quic/quic_stream_sequencer_buffer.cc (renamed from net/quic/stream_sequencer_buffer.cc)77
-rw-r--r--net/quic/quic_stream_sequencer_buffer.h (renamed from net/quic/stream_sequencer_buffer.h)89
-rw-r--r--net/quic/quic_stream_sequencer_buffer_test.cc (renamed from net/quic/stream_sequencer_buffer_test.cc)287
-rw-r--r--net/quic/quic_stream_sequencer_test.cc8
-rw-r--r--net/quic/quic_utils.cc3
-rw-r--r--net/quic/spdy_utils.cc2
-rw-r--r--net/quic/spdy_utils.h2
-rw-r--r--net/quic/spdy_utils_test.cc2
-rw-r--r--net/quic/test_tools/mock_quic_dispatcher.h2
-rw-r--r--net/quic/test_tools/quic_test_packet_maker.cc63
-rw-r--r--net/quic/test_tools/quic_test_packet_maker.h56
-rw-r--r--net/quic/test_tools/quic_test_utils.cc9
-rw-r--r--net/quic/test_tools/quic_test_utils.h14
-rw-r--r--net/tools/quic/end_to_end_test.cc86
-rw-r--r--net/tools/quic/quic_client.cc19
-rw-r--r--net/tools/quic/quic_client.h2
-rw-r--r--net/tools/quic/quic_client_session.h11
-rw-r--r--net/tools/quic/quic_client_session_test.cc14
-rw-r--r--net/tools/quic/quic_dispatcher.cc2
-rw-r--r--net/tools/quic/quic_dispatcher.h6
-rw-r--r--net/tools/quic/quic_dispatcher_test.cc9
-rw-r--r--net/tools/quic/quic_packet_reader.cc61
-rw-r--r--net/tools/quic/quic_packet_reader.h12
-rw-r--r--net/tools/quic/quic_process_packet_interface.h2
-rw-r--r--net/tools/quic/quic_server.cc2
-rw-r--r--net/tools/quic/quic_server_session_base.h4
-rw-r--r--net/tools/quic/quic_server_test.cc7
-rw-r--r--net/tools/quic/quic_simple_client.cc5
-rw-r--r--net/tools/quic/quic_simple_client.h2
-rw-r--r--net/tools/quic/quic_simple_server.cc3
-rw-r--r--net/tools/quic/quic_simple_server_stream.cc4
-rw-r--r--net/tools/quic/quic_simple_server_stream.h2
-rw-r--r--net/tools/quic/quic_simple_server_test.cc7
-rw-r--r--net/tools/quic/quic_socket_utils.cc73
-rw-r--r--net/tools/quic/quic_socket_utils.h43
-rw-r--r--net/tools/quic/quic_spdy_client_stream.cc14
-rw-r--r--net/tools/quic/quic_spdy_client_stream.h11
-rw-r--r--net/tools/quic/quic_spdy_client_stream_test.cc6
-rw-r--r--net/tools/quic/quic_time_wait_list_manager_test.cc12
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc18
-rw-r--r--net/tools/quic/test_tools/quic_test_client.h2
73 files changed, 1610 insertions, 535 deletions
diff --git a/net/net.gypi b/net/net.gypi
index 5b48ac9..a224d4b 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -398,6 +398,8 @@
'quic/quic_socket_address_coder.h',
'quic/quic_stream_sequencer.cc',
'quic/quic_stream_sequencer.h',
+ 'quic/quic_stream_sequencer_buffer.cc',
+ 'quic/quic_stream_sequencer_buffer.h',
'quic/quic_stream_sequencer_buffer_interface.h',
'quic/quic_sustained_bandwidth_recorder.cc',
'quic/quic_sustained_bandwidth_recorder.h',
@@ -414,8 +416,6 @@
'quic/quic_write_blocked_list.h',
'quic/reliable_quic_stream.cc',
'quic/reliable_quic_stream.h',
- 'quic/stream_sequencer_buffer.cc',
- 'quic/stream_sequencer_buffer.h',
],
'net_non_nacl_sources': [
'android/cert_verify_result_android.cc',
@@ -1659,7 +1659,7 @@
'quic/quic_write_blocked_list_test.cc',
'quic/reliable_quic_stream_test.cc',
'quic/spdy_utils_test.cc',
- 'quic/stream_sequencer_buffer_test.cc',
+ 'quic/quic_stream_sequencer_buffer_test.cc',
'quic/test_tools/crypto_test_utils.cc',
'quic/test_tools/crypto_test_utils.h',
'quic/test_tools/crypto_test_utils_chromium.cc',
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index b394ed8..3b8847c 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -265,11 +265,11 @@ class BidirectionalStreamQuicImplTest
// Holds a packet to be written to the wire, and the IO mode that should
// be used by the mock socket when performing the write.
struct PacketToWrite {
- PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
+ PacketToWrite(IoMode mode, QuicReceivedPacket* packet)
: mode(mode), packet(packet) {}
PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
IoMode mode;
- QuicEncryptedPacket* packet;
+ QuicReceivedPacket* packet;
int rv;
};
@@ -300,11 +300,11 @@ class BidirectionalStreamQuicImplTest
}
// Adds a packet to the list of expected writes.
- void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
+ void AddWrite(scoped_ptr<QuicReceivedPacket> packet) {
writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
}
- void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
+ void ProcessPacket(scoped_ptr<QuicReceivedPacket> packet) {
connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
}
@@ -361,20 +361,20 @@ class BidirectionalStreamQuicImplTest
return maker_.GetResponseHeaders(response_code);
}
- scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructDataPacket(
QuicPacketNumber packet_number,
bool should_include_version,
bool fin,
QuicStreamOffset offset,
base::StringPiece data) {
- scoped_ptr<QuicEncryptedPacket> packet(maker_.MakeDataPacket(
+ scoped_ptr<QuicReceivedPacket> packet(maker_.MakeDataPacket(
packet_number, stream_id_, should_include_version, fin, offset, data));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
<< QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
return packet;
}
- scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
QuicPacketNumber packet_number,
bool fin,
RequestPriority request_priority,
@@ -386,7 +386,7 @@ class BidirectionalStreamQuicImplTest
request_headers_, spdy_headers_frame_length);
}
- scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
QuicPacketNumber packet_number,
bool fin,
const SpdyHeaderBlock& response_headers,
@@ -397,7 +397,7 @@ class BidirectionalStreamQuicImplTest
spdy_headers_frame_length, offset);
}
- scoped_ptr<QuicEncryptedPacket> ConstructResponseTrailersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructResponseTrailersPacket(
QuicPacketNumber packet_number,
bool fin,
const SpdyHeaderBlock& trailers,
@@ -408,15 +408,15 @@ class BidirectionalStreamQuicImplTest
spdy_headers_frame_length, offset);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamPacket(
QuicPacketNumber packet_number) {
return ConstructRstStreamCancelledPacket(packet_number, 0);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamCancelledPacket(
QuicPacketNumber packet_number,
size_t bytes_written) {
- scoped_ptr<QuicEncryptedPacket> packet(
+ scoped_ptr<QuicReceivedPacket> packet(
maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
QUIC_STREAM_CANCELLED, bytes_written));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
@@ -424,7 +424,7 @@ class BidirectionalStreamQuicImplTest
return packet;
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber ack_least_unacked,
@@ -435,7 +435,7 @@ class BidirectionalStreamQuicImplTest
!kIncludeCongestionFeedback);
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckAndDataPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndDataPacket(
QuicPacketNumber packet_number,
bool should_include_version,
QuicPacketNumber largest_received,
@@ -443,7 +443,7 @@ class BidirectionalStreamQuicImplTest
bool fin,
QuicStreamOffset offset,
base::StringPiece data) {
- scoped_ptr<QuicEncryptedPacket> packet(maker_.MakeAckAndDataPacket(
+ scoped_ptr<QuicReceivedPacket> packet(maker_.MakeAckAndDataPacket(
packet_number, should_include_version, stream_id_, largest_received,
least_unacked, fin, offset, data));
DVLOG(2) << "packet(" << packet_number << "): " << std::endl
@@ -451,7 +451,7 @@ class BidirectionalStreamQuicImplTest
return packet;
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked) {
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc
index c65927a..8fc3689 100644
--- a/net/quic/crypto/crypto_server_test.cc
+++ b/net/quic/crypto/crypto_server_test.cc
@@ -633,6 +633,42 @@ TEST_P(CryptoServerTest, BadClientNonce) {
}
}
+TEST_P(CryptoServerTest, NoClientNonce) {
+ // No client nonces should result in INCHOATE_HELLO_FAILURE.
+ // clang-format off
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message(
+ "CHLO",
+ "VER\0", client_version_string_.c_str(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ nullptr);
+ // clang-format on
+
+ ShouldSucceed(msg);
+ const HandshakeFailureReason kRejectReasons[] = {
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
+
+ // clang-format off
+ CryptoHandshakeMessage msg1 = CryptoTestUtils::Message(
+ "CHLO",
+ "AEAD", "AESG",
+ "KEXS", "C255",
+ "SCID", scid_hex_.c_str(),
+ "#004b5453", srct_hex_.c_str(),
+ "PUBS", pub_hex_.c_str(),
+ "XLCT", XlctHexString().c_str(),
+ "VER\0", client_version_string_.c_str(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ nullptr);
+ // clang-format on
+
+ ShouldSucceed(msg1);
+ CheckRejectTag();
+ const HandshakeFailureReason kRejectReasons1[] = {
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
+ CheckRejectReasons(kRejectReasons1, arraysize(kRejectReasons1));
+}
+
TEST_P(CryptoServerTest, DowngradeAttack) {
if (supported_versions_.size() == 1) {
// No downgrade attack is possible if the server only supports one version.
@@ -745,7 +781,7 @@ TEST_P(CryptoServerTest, CorruptMultipleTags) {
ShouldSucceed(msg);
CheckRejectTag();
- if (client_version_ <= QUIC_VERSION_31) {
+ if (client_version_ <= QUIC_VERSION_32) {
const HandshakeFailureReason kRejectReasons[] = {
SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE,
SERVER_NONCE_DECRYPTION_FAILURE};
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc
index c6d32e5..6378de9 100644
--- a/net/quic/crypto/quic_crypto_server_config.cc
+++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -1031,6 +1031,13 @@ void QuicCryptoServerConfig::EvaluateClientHello(
return;
}
+ if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
+ info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
+ // Report no client nonce as INCHOATE_HELLO_FAILURE.
+ helper.ValidationComplete(QUIC_NO_ERROR, "");
+ return;
+ }
+
bool found_error = false;
if (source_address_token_error != HANDSHAKE_OK) {
info->reject_reasons.push_back(source_address_token_error);
@@ -1063,8 +1070,7 @@ void QuicCryptoServerConfig::EvaluateClientHello(
}
}
- if (!client_hello.GetStringPiece(kNONC, &info->client_nonce) ||
- info->client_nonce.size() != kNonceSize) {
+ if (info->client_nonce.size() != kNonceSize) {
info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
// Invalid client nonce.
LOG(ERROR) << "Invalid client nonce: " << client_hello.DebugString();
@@ -1079,8 +1085,8 @@ void QuicCryptoServerConfig::EvaluateClientHello(
// Server nonce is optional, and used for key derivation if present.
client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
- if (version > QUIC_VERSION_31) {
- DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_32 and higher.";
+ if (version > QUIC_VERSION_32) {
+ DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
// If the server nonce is empty and we're requiring handshake confirmation
// for DoS reasons then we must reject the CHLO.
if (FLAGS_quic_require_handshake_confirmation &&
diff --git a/net/quic/p2p/quic_p2p_session.cc b/net/quic/p2p/quic_p2p_session.cc
index 6bd17d6..f165bf7 100644
--- a/net/quic/p2p/quic_p2p_session.cc
+++ b/net/quic/p2p/quic_p2p_session.cc
@@ -124,7 +124,7 @@ int QuicP2PSession::DoReadComplete(int result) {
return result;
}
- QuicEncryptedPacket packet(read_buffer_->data(), result);
+ QuicReceivedPacket packet(read_buffer_->data(), result, clock_.Now());
connection()->ProcessUdpPacket(connection()->self_address(),
connection()->peer_address(), packet);
return OK;
diff --git a/net/quic/p2p/quic_p2p_session.h b/net/quic/p2p/quic_p2p_session.h
index 734b6e59..1f821d3 100644
--- a/net/quic/p2p/quic_p2p_session.h
+++ b/net/quic/p2p/quic_p2p_session.h
@@ -10,6 +10,7 @@
#include "base/strings/string_piece.h"
#include "net/quic/p2p/quic_p2p_stream.h"
#include "net/quic/quic_client_session_base.h"
+#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -82,6 +83,9 @@ class NET_EXPORT QuicP2PSession : public QuicSession {
ReadState read_state_ = READ_STATE_DO_READ;
scoped_refptr<IOBuffer> read_buffer_;
+ // For recording receipt time
+ QuicClock clock_;
+
DISALLOW_COPY_AND_ASSIGN(QuicP2PSession);
};
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 08145fc..0f018bb 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -655,24 +655,32 @@ bool QuicChromiumClientSession::CanPool(const std::string& hostname,
server_id_.host(), hostname);
}
-QuicChromiumClientStream*
-QuicChromiumClientSession::CreateIncomingDynamicStream(QuicStreamId id) {
+bool QuicChromiumClientSession::ShouldCreateIncomingDynamicStream(
+ QuicStreamId id) {
if (!connection()->connected()) {
LOG(DFATAL) << "ShouldCreateIncomingDynamicStream called when disconnected";
- return nullptr;
+ return false;
}
if (goaway_received()) {
- DVLOG(1) << "Failed to create a new outgoing stream. "
+ DVLOG(1) << "Cannot create a new outgoing stream. "
<< "Already received goaway.";
- return nullptr;
+ return false;
}
if (going_away_) {
- return nullptr;
+ return false;
}
if (id % 2 != 0) {
LOG(WARNING) << "Received invalid push stream id " << id;
connection()->SendConnectionCloseWithDetails(
QUIC_INVALID_STREAM_ID, "Server created odd numbered stream");
+ return false;
+ }
+ return true;
+}
+
+QuicChromiumClientStream*
+QuicChromiumClientSession::CreateIncomingDynamicStream(QuicStreamId id) {
+ if (!ShouldCreateIncomingDynamicStream(id)) {
return nullptr;
}
return CreateIncomingReliableStreamImpl(id);
@@ -1056,7 +1064,7 @@ void QuicChromiumClientSession::OnReadError(
NotifyFactoryOfSessionClosedLater();
}
-bool QuicChromiumClientSession::OnPacket(const QuicEncryptedPacket& packet,
+bool QuicChromiumClientSession::OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) {
ProcessUdpPacket(local_address, peer_address, packet);
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index 4f100c9..1d587e1 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -158,7 +158,6 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// QuicSession methods:
void OnStreamFrame(const QuicStreamFrame& frame) override;
- bool ShouldCreateOutgoingDynamicStream();
QuicChromiumClientStream* CreateOutgoingDynamicStream(
SpdyPriority priority) override;
QuicCryptoClientStream* GetCryptoStream() override;
@@ -187,7 +186,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// QuicChromiumPacketReader::Visitor methods:
void OnReadError(int result, const DatagramClientSocket* socket) override;
- bool OnPacket(const QuicEncryptedPacket& packet,
+ bool OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) override;
@@ -270,6 +269,9 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
protected:
// QuicSession methods:
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
+ bool ShouldCreateOutgoingDynamicStream() override;
+
QuicChromiumClientStream* CreateIncomingDynamicStream(
QuicStreamId id) override;
diff --git a/net/quic/quic_chromium_client_stream.cc b/net/quic/quic_chromium_client_stream.cc
index 5d9946c..06ec942 100644
--- a/net/quic/quic_chromium_client_stream.cc
+++ b/net/quic/quic_chromium_client_stream.cc
@@ -40,7 +40,7 @@ void QuicChromiumClientStream::OnStreamHeadersComplete(bool fin,
if (decompressed_headers().empty() && !decompressed_trailers().empty()) {
DCHECK(trailers_decompressed());
// The delegate will read the trailers via a posted task.
- NotifyDelegateOfHeadersCompleteLater(response_trailers(), frame_len);
+ NotifyDelegateOfHeadersCompleteLater(received_trailers(), frame_len);
} else {
DCHECK(!headers_delivered_);
SpdyHeaderBlock headers;
diff --git a/net/quic/quic_chromium_client_stream_test.cc b/net/quic/quic_chromium_client_stream_test.cc
index 4e9e2bc..275ed48 100644
--- a/net/quic/quic_chromium_client_stream_test.cc
+++ b/net/quic/quic_chromium_client_stream_test.cc
@@ -112,6 +112,10 @@ class MockQuicClientSessionBase : public QuicClientSessionBase {
const ProofVerifyDetails& verify_details) override {}
bool IsAuthorized(const std::string& hostname) override { return true; }
+ protected:
+ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
+ MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
+
private:
scoped_ptr<QuicCryptoStream> crypto_stream_;
diff --git a/net/quic/quic_chromium_packet_reader.cc b/net/quic/quic_chromium_packet_reader.cc
index ac45510..4a57ecb 100644
--- a/net/quic/quic_chromium_packet_reader.cc
+++ b/net/quic/quic_chromium_packet_reader.cc
@@ -77,7 +77,7 @@ void QuicChromiumPacketReader::OnReadComplete(int result) {
return;
}
- QuicEncryptedPacket packet(read_buffer_->data(), result);
+ QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now());
IPEndPoint local_address;
IPEndPoint peer_address;
socket_->GetLocalAddress(&local_address);
diff --git a/net/quic/quic_chromium_packet_reader.h b/net/quic/quic_chromium_packet_reader.h
index e3e708c..1f0aaed 100644
--- a/net/quic/quic_chromium_packet_reader.h
+++ b/net/quic/quic_chromium_packet_reader.h
@@ -32,7 +32,7 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketReader {
virtual ~Visitor(){};
virtual void OnReadError(int result,
const DatagramClientSocket* socket) = 0;
- virtual bool OnPacket(const QuicEncryptedPacket& packet,
+ virtual bool OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) = 0;
};
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 7dea3ee..f2d5607 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -1202,7 +1202,7 @@ const QuicConnectionStats& QuicConnection::GetStats() {
void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
if (!connected_) {
return;
}
@@ -1224,6 +1224,12 @@ void QuicConnection::ProcessUdpPacket(const IPEndPoint& self_address,
stats_.bytes_received += packet.length();
++stats_.packets_received;
+ if (FLAGS_quic_use_socket_timestamp) {
+ time_of_last_received_packet_ = packet.receipt_time();
+ DVLOG(1) << ENDPOINT << "time of last received packet: "
+ << time_of_last_received_packet_.ToDebuggingValue();
+ }
+
ScopedRetransmissionScheduler alarm_delayer(this);
if (!framer_.ProcessPacket(packet)) {
// If we are unable to decrypt this packet, it might be
@@ -1353,9 +1359,11 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
DCHECK_EQ(NEGOTIATED_VERSION, version_negotiation_state_);
- time_of_last_received_packet_ = clock_->Now();
- DVLOG(1) << ENDPOINT << "time of last received packet: "
- << time_of_last_received_packet_.ToDebuggingValue();
+ if (!FLAGS_quic_use_socket_timestamp) {
+ time_of_last_received_packet_ = clock_->Now();
+ DVLOG(1) << ENDPOINT << "time of last received packet: "
+ << time_of_last_received_packet_.ToDebuggingValue();
+ }
if (last_size_ > largest_received_packet_size_) {
largest_received_packet_size_ = last_size_;
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 169145e..0127c49 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -392,7 +392,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// than that of this connection.
virtual void ProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet);
+ const QuicReceivedPacket& packet);
// QuicBlockedWriterInterface
// Called when the underlying connection becomes writable to allow queued
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 95cbeb3..329da5b 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -750,8 +750,8 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
self_address, peer_address,
- QuicEncryptedPacket(serialized_packet.encrypted_buffer,
- serialized_packet.encrypted_length));
+ QuicReceivedPacket(serialized_packet.encrypted_buffer,
+ serialized_packet.encrypted_length, clock_.Now()));
if (connection_.GetSendAlarm()->IsSet()) {
connection_.GetSendAlarm()->Fire();
}
@@ -778,7 +778,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
level, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
return base::checked_cast<QuicPacketEntropyHash>(encrypted_length);
}
@@ -801,7 +801,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
level, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
if (connection_.GetSendAlarm()->IsSet()) {
connection_.GetSendAlarm()->Fire();
}
@@ -815,7 +815,7 @@ class QuicConnectionTest : public ::testing::TestWithParam<TestParams> {
ENCRYPTION_NONE, path_id, number, *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
}
QuicByteCount SendStreamDataToPeer(QuicStreamId id,
@@ -1102,7 +1102,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_EQ(kMaxPacketSize, connection_.max_packet_length());
}
@@ -1136,7 +1136,7 @@ TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSizeWhileWriterLimited) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
// Here, the limit imposed by the writer is lower than the size of the packet
// received, so the writer max packet size is used.
@@ -3916,9 +3916,11 @@ TEST_P(QuicConnectionTest, PublicReset) {
header.rejected_packet_number = 10101;
scoped_ptr<QuicEncryptedPacket> packet(
framer_.BuildPublicResetPacket(header));
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*packet, QuicTime::Zero()));
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PUBLIC_RESET,
ConnectionCloseSource::FROM_PEER));
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *packet);
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
}
TEST_P(QuicConnectionTest, GoAway) {
@@ -3963,7 +3965,7 @@ TEST_P(QuicConnectionTest, PathClose) {
TEST_P(QuicConnectionTest, ZeroBytePacket) {
// Don't close the connection for zero byte packets.
EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(0);
- QuicEncryptedPacket encrypted(nullptr, 0);
+ QuicReceivedPacket encrypted(nullptr, 0, QuicTime::Zero());
connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, encrypted);
}
@@ -4074,7 +4076,7 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
connection_.set_perspective(Perspective::IS_SERVER);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_TRUE(writer_->version_negotiation_packet() != nullptr);
size_t num_versions = arraysize(kSupportedQuicVersions);
@@ -4110,7 +4112,7 @@ TEST_P(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
BlockOnNextWrite();
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_TRUE(connection_.HasQueuedData());
@@ -4153,7 +4155,7 @@ TEST_P(QuicConnectionTest,
writer_->set_is_write_blocked_data_buffered(true);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encryped_length, false));
+ QuicReceivedPacket(buffer, encryped_length, QuicTime::Zero(), false));
EXPECT_EQ(0u, writer_->last_packet_size());
EXPECT_FALSE(connection_.HasQueuedData());
}
@@ -4167,7 +4169,9 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.BuildVersionNegotiationPacket(connection_id_,
QuicSupportedVersions()));
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted);
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
// Now force another packet. The connection should transition into
// NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion.
@@ -4187,7 +4191,7 @@ TEST_P(QuicConnectionTest, ClientHandlesVersionNegotiation) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket(creator_));
}
@@ -4201,7 +4205,9 @@ TEST_P(QuicConnectionTest, BadVersionNegotiation) {
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.BuildVersionNegotiationPacket(connection_id_,
QuicSupportedVersions()));
- connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *encrypted);
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
+ connection_.ProcessUdpPacket(kSelfAddress, kPeerAddress, *received);
}
TEST_P(QuicConnectionTest, CheckSendStats) {
@@ -4277,7 +4283,7 @@ TEST_P(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicEncryptedPacket(buffer, encrypted_length, false));
+ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
}
TEST_P(QuicConnectionTest, SelectMutualVersion) {
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index 8d1ff31..d87d14d 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -146,7 +146,7 @@ class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
}
bool AsyncStrikeRegisterVerification() {
- if (server_connection_->version() > QUIC_VERSION_31) {
+ if (server_connection_->version() > QUIC_VERSION_32) {
return false;
}
return GetParam();
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index 67f3a0c..e86474b 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -138,3 +138,11 @@ bool FLAGS_quic_dont_copy_acks = true;
// Use a byte conservation approach instead of packet conservation in the
// Slow Start Large Reduction experiment.
bool FLAGS_quic_sslr_byte_conservation = true;
+
+// Try to use the socket timestamp to determine the time a packet was
+// received instead of Now().
+bool FLAGS_quic_use_socket_timestamp = true;
+
+// If true, handling of errors from invalid stream frames is done in
+// one place in QuicStreamSequencer::OnStreamFrame.
+bool FLAGS_quic_consolidate_onstreamframe_errors = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index 5936e8b..0e70632 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -46,5 +46,7 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_rto_timeout;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_dont_limit_max_cwnd;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_dont_copy_acks;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_sslr_byte_conservation;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_socket_timestamp;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_consolidate_onstreamframe_errors;
#endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index fa667f2..3d3e36f 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -621,12 +621,6 @@ bool QuicFramer::ProcessPublicResetPacket(
}
// TODO(satyamshekhar): validate nonce to protect against DoS.
- if (reset->GetUint64(kRSEQ, &packet.rejected_packet_number) !=
- QUIC_NO_ERROR) {
- set_detailed_error("Unable to read rejected packet number.");
- return RaiseError(QUIC_INVALID_PUBLIC_RST_PACKET);
- }
-
StringPiece address;
if (reset->GetStringPiece(kCADR, &address)) {
QuicSocketAddressCoder address_coder;
@@ -1009,9 +1003,16 @@ bool QuicFramer::ProcessAuthenticatedHeader(QuicDataReader* reader,
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
- if (private_flags > PACKET_PRIVATE_FLAGS_MAX) {
- set_detailed_error("Illegal private flags value.");
- return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ if (quic_version_ > QUIC_VERSION_31) {
+ if (private_flags > PACKET_PRIVATE_FLAGS_MAX_VERSION_32) {
+ set_detailed_error("Illegal private flags value.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ } else {
+ if (private_flags > PACKET_PRIVATE_FLAGS_MAX) {
+ set_detailed_error("Illegal private flags value.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
}
header->entropy_flag = (private_flags & PACKET_PRIVATE_FLAGS_ENTROPY) != 0;
@@ -1369,6 +1370,10 @@ bool QuicFramer::ProcessAckFrame(QuicDataReader* reader,
last_packet_number -= (range_length + 1);
}
+ if (quic_version_ > QUIC_VERSION_31) {
+ return true;
+ }
+
// Parse the revived packets list.
// TODO(ianswett): Change the ack frame so it only expresses one revived.
uint8_t num_revived_packets;
@@ -1753,7 +1758,10 @@ size_t QuicFramer::GetAckFrameSize(
size_t ack_size = GetMinAckFrameSize(largest_observed_length);
if (!ack_info.nack_ranges.empty()) {
- ack_size += kNumberOfNackRangesSize + kNumberOfRevivedPacketsSize;
+ ack_size += kNumberOfNackRangesSize;
+ if (quic_version_ <= QUIC_VERSION_31) {
+ ack_size += kNumberOfRevivedPacketsSize;
+ }
ack_size += min(ack_info.nack_ranges.size(), kMaxNackRanges) *
(missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER);
}
@@ -1935,9 +1943,12 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
QuicPacketNumberLength missing_packet_number_length =
GetMinSequenceNumberLength(ack_info.max_delta);
// Determine whether we need to truncate ranges.
- size_t available_range_bytes =
- writer->capacity() - writer->length() - kNumberOfRevivedPacketsSize -
- kNumberOfNackRangesSize - GetMinAckFrameSize(largest_observed_length);
+ size_t available_range_bytes = writer->capacity() - writer->length() -
+ kNumberOfNackRangesSize -
+ GetMinAckFrameSize(largest_observed_length);
+ if (quic_version_ <= QUIC_VERSION_31) {
+ available_range_bytes -= kNumberOfRevivedPacketsSize;
+ }
size_t max_num_ranges =
available_range_bytes /
(missing_packet_number_length + PACKET_1BYTE_PACKET_NUMBER);
@@ -2043,6 +2054,10 @@ bool QuicFramer::AppendAckFrameAndTypeByte(const QuicPacketHeader& header,
}
DCHECK_EQ(num_missing_ranges, num_ranges_written);
+ if (quic_version_ > QUIC_VERSION_31) {
+ return true;
+ }
+
// Append revived packets.
// FEC is not supported.
uint8_t num_revived_packets = 0;
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index d770db9..80f7683 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -1381,10 +1381,16 @@ TEST_P(QuicFramerTest, InvalidFECGroupOffset) {
0x10
};
// clang-format on
- CheckProcessingFails(packet, arraysize(packet),
- "First fec protected packet offset must be less "
- "than the packet number.",
- QUIC_INVALID_PACKET_HEADER);
+ if (framer_.version() > QUIC_VERSION_31) {
+ CheckProcessingFails(packet, arraysize(packet),
+ "Illegal private flags value.",
+ QUIC_INVALID_PACKET_HEADER);
+ } else {
+ CheckProcessingFails(packet, arraysize(packet),
+ "First fec protected packet offset must be less "
+ "than the packet number.",
+ QUIC_INVALID_PACKET_HEADER);
+ }
};
TEST_P(QuicFramerTest, PaddingFrame) {
@@ -1791,6 +1797,10 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ return;
+ }
+
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -1869,6 +1879,119 @@ TEST_P(QuicFramerTest, AckFrameTwoTimestamp) {
}
}
+TEST_P(QuicFramerTest, AckFrameTwoTimestampVersion32) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet number
+ 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Number of timestamps.
+ 0x02,
+ // Delta from largest observed.
+ 0x01,
+ // Delta time.
+ 0x10, 0x32, 0x54, 0x76,
+ // Delta from largest observed.
+ 0x02,
+ // Delta time.
+ 0x10, 0x32,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ };
+ // clang-format on
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ return;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.NumPacketsSlow());
+ ASSERT_EQ(2u, frame.received_packet_times.size());
+ EXPECT_EQ(kMissingPacket, frame.missing_packets.Min());
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset =
+ kReceivedEntropyOffset + kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset =
+ kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER;
+ const size_t kNumTimestampsOffset =
+ kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize;
+ const size_t kTimestampDeltaLargestObserved1 =
+ kNumTimestampsOffset + kQuicNumTimestampsSize;
+ const size_t kTimestampTimeDeltaLargestObserved1 =
+ kTimestampDeltaLargestObserved1 + 1;
+ const size_t kTimestampDeltaLargestObserved2 =
+ kTimestampTimeDeltaLargestObserved1 + 4;
+ const size_t kTimestampTimeDeltaLargestObserved2 =
+ kTimestampDeltaLargestObserved2 + 1;
+ const size_t kNumMissingPacketOffset =
+ kTimestampTimeDeltaLargestObserved2 + 2;
+ const size_t kMissingPacketsOffset =
+ kNumMissingPacketOffset + kNumberOfNackRangesSize;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = PACKET_1BYTE_PACKET_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumTimestampsOffset) {
+ expected_error = "Unable to read ack delay time.";
+ } else if (i < kTimestampDeltaLargestObserved1) {
+ expected_error = "Unable to read num received packets.";
+ } else if (i < kTimestampTimeDeltaLargestObserved1) {
+ expected_error = "Unable to read sequence delta in received packets.";
+ } else if (i < kTimestampDeltaLargestObserved2) {
+ expected_error = "Unable to read time delta in received packets.";
+ } else if (i < kTimestampTimeDeltaLargestObserved2) {
+ expected_error = "Unable to read sequence delta in received packets.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error =
+ "Unable to read incremental time delta in received packets.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else {
+ expected_error = "Unable to read missing packet number delta.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
// clang-format off
unsigned char packet[] = {
@@ -1907,6 +2030,10 @@ TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ return;
+ }
+
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -1975,6 +2102,105 @@ TEST_P(QuicFramerTest, AckFrameOneTimestamp) {
}
}
+TEST_P(QuicFramerTest, AckFrameOneTimestampVersion32) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet number
+ 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Number of timestamps.
+ 0x01,
+ // Delta from largest observed.
+ 0x01,
+ // Delta time.
+ 0x10, 0x32, 0x54, 0x76,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ };
+ // clang-format on
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ return;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.NumPacketsSlow());
+ ASSERT_EQ(1u, frame.received_packet_times.size());
+ EXPECT_EQ(kMissingPacket, frame.missing_packets.Min());
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset =
+ kReceivedEntropyOffset + kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset =
+ kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER;
+ const size_t kNumTimestampsOffset =
+ kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize;
+ const size_t kTimestampDeltaLargestObserved =
+ kNumTimestampsOffset + kQuicNumTimestampsSize;
+ const size_t kTimestampTimeDeltaLargestObserved =
+ kTimestampDeltaLargestObserved + 1;
+ const size_t kNumMissingPacketOffset = kTimestampTimeDeltaLargestObserved + 4;
+ const size_t kMissingPacketsOffset =
+ kNumMissingPacketOffset + kNumberOfNackRangesSize;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = PACKET_1BYTE_PACKET_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumTimestampsOffset) {
+ expected_error = "Unable to read ack delay time.";
+ } else if (i < kTimestampDeltaLargestObserved) {
+ expected_error = "Unable to read num received packets.";
+ } else if (i < kTimestampTimeDeltaLargestObserved) {
+ expected_error = "Unable to read sequence delta in received packets.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error = "Unable to read time delta in received packets.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else {
+ expected_error = "Unable to read missing packet number delta.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
TEST_P(QuicFramerTest, AckFrame) {
// clang-format off
unsigned char packet[] = {
@@ -2009,6 +2235,10 @@ TEST_P(QuicFramerTest, AckFrame) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ return;
+ }
+
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2069,6 +2299,93 @@ TEST_P(QuicFramerTest, AckFrame) {
}
}
+TEST_P(QuicFramerTest, AckFrameVersion32) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet number
+ 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Number of timestamps.
+ 0x00,
+ // num missing packets
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ };
+ // clang-format on
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ return;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame.entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame.largest_observed);
+ ASSERT_EQ(1u, frame.missing_packets.NumPacketsSlow());
+ EXPECT_EQ(kMissingPacket, frame.missing_packets.Min());
+
+ const size_t kReceivedEntropyOffset = kQuicFrameTypeSize;
+ const size_t kLargestObservedOffset =
+ kReceivedEntropyOffset + kQuicEntropyHashSize;
+ const size_t kMissingDeltaTimeOffset =
+ kLargestObservedOffset + PACKET_6BYTE_PACKET_NUMBER;
+ const size_t kNumTimestampsOffset =
+ kMissingDeltaTimeOffset + kQuicDeltaTimeLargestObservedSize;
+ const size_t kNumMissingPacketOffset =
+ kNumTimestampsOffset + kQuicNumTimestampsSize;
+ const size_t kMissingPacketsOffset =
+ kNumMissingPacketOffset + kNumberOfNackRangesSize;
+ // Now test framing boundaries.
+ const size_t ack_frame_size = PACKET_1BYTE_PACKET_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
+ string expected_error;
+ if (i < kLargestObservedOffset) {
+ expected_error = "Unable to read entropy hash for received packets.";
+ } else if (i < kMissingDeltaTimeOffset) {
+ expected_error = "Unable to read largest observed.";
+ } else if (i < kNumTimestampsOffset) {
+ expected_error = "Unable to read ack delay time.";
+ } else if (i < kNumMissingPacketOffset) {
+ expected_error = "Unable to read num received packets.";
+ } else if (i < kMissingPacketsOffset) {
+ expected_error = "Unable to read num missing packet ranges.";
+ } else {
+ expected_error = "Unable to read missing packet number delta.";
+ }
+ CheckProcessingFails(
+ packet,
+ i + GetPacketHeaderSize(PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
+ !kIncludePathId, PACKET_6BYTE_PACKET_NUMBER),
+ expected_error, QUIC_INVALID_ACK_DATA);
+ }
+}
+
TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
// clang-format off
unsigned char packet[] = {
@@ -2107,6 +2424,10 @@ TEST_P(QuicFramerTest, AckFrameRevivedPackets) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ return;
+ }
+
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2264,6 +2585,79 @@ TEST_P(QuicFramerTest, AckFrame500Nacks) {
};
// clang-format on
+ if (framer_.version() > QUIC_VERSION_31) {
+ return;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(encrypted, !kIncludeVersion, !kIncludePathId));
+
+ EXPECT_EQ(0u, visitor_.stream_frames_.size());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame* frame = visitor_.ack_frames_[0];
+ EXPECT_EQ(0xBA, frame->entropy_hash);
+ EXPECT_EQ(kLargestObserved, frame->largest_observed);
+ ASSERT_EQ(500u, frame->missing_packets.NumPacketsSlow());
+ EXPECT_EQ(kMissingPacket - 499, frame->missing_packets.Min());
+ EXPECT_EQ(kMissingPacket, frame->missing_packets.Max());
+
+ // Verify that the packet re-serializes identically.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame));
+ scoped_ptr<QuicPacket> data(BuildDataPacket(*visitor_.header_, frames));
+ ASSERT_TRUE(data != nullptr);
+
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+}
+
+TEST_P(QuicFramerTest, AckFrame500NacksVersion32) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xA8, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet number
+ 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // Zero delta time.
+ 0x00, 0x00,
+ // No received packets.
+ 0x00,
+ // num missing packet ranges
+ 0x02,
+ // missing packet delta
+ 0x01,
+ // 243 more missing packets in range.
+ // The ranges are listed in this order so the re-constructed packet
+ // matches.
+ 0xF3,
+ // No gap between ranges
+ 0x00,
+ // 255 more missing packets in range.
+ 0xFF,
+ };
+ // clang-format on
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ return;
+ }
+
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -2737,8 +3131,7 @@ TEST_P(QuicFramerTest, PublicResetPacket) {
EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag);
EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag);
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
- EXPECT_EQ(kPacketNumber,
- visitor_.public_reset_packet_->rejected_packet_number);
+ EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
EXPECT_EQ(ADDRESS_FAMILY_UNSPECIFIED,
visitor_.public_reset_packet_->client_address.GetFamily());
@@ -2844,8 +3237,7 @@ TEST_P(QuicFramerTest, PublicResetPacketWithClientAddress) {
EXPECT_TRUE(visitor_.public_reset_packet_->public_header.reset_flag);
EXPECT_FALSE(visitor_.public_reset_packet_->public_header.version_flag);
EXPECT_EQ(kNonceProof, visitor_.public_reset_packet_->nonce_proof);
- EXPECT_EQ(kPacketNumber,
- visitor_.public_reset_packet_->rejected_packet_number);
+ EXPECT_EQ(0u, visitor_.public_reset_packet_->rejected_packet_number);
EXPECT_EQ("4.31.198.44",
visitor_.public_reset_packet_->client_address.address().ToString());
EXPECT_EQ(443, visitor_.public_reset_packet_->client_address.port());
@@ -2933,9 +3325,13 @@ TEST_P(QuicFramerTest, DropFecPacket) {
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
-
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ if (framer_.version() <= QUIC_VERSION_31) {
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ } else {
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(QUIC_INVALID_PACKET_HEADER, framer_.error());
+ }
EXPECT_FALSE(visitor_.header_.get());
}
@@ -3412,12 +3808,49 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) {
};
// clang-format on
+ // clang-format off
+ unsigned char packet_version32[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
+ // entropy hash of all received packets.
+ 0x43,
+ // largest observed packet number
+ 0xBF, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // Zero delta time.
+ 0x00, 0x00,
+ // num received packets.
+ 0x00,
+ // num missing packet ranges
+ 0x01,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
+ };
+ // clang-format on
+
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ if (framer_.version() <= QUIC_VERSION_31) {
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+ } else {
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(),
+ AsChars(packet_version32), arraysize(packet_version32));
+ }
}
// TODO(jri): Add test for tuncated packets in which the original ack frame had
@@ -3526,12 +3959,94 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameLargePacket) {
};
// clang-format on
+ // clang-format off
+ unsigned char packet_version32[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, is truncated, 2 byte largest observed, 1 byte delta)
+ 0x74,
+ // entropy hash of all received packets, set to 1 by TestEntropyCalculator
+ // since ack is truncated.
+ 0x01,
+ // 2-byte largest observed packet number.
+ // Expected to be 510 (0x1FE), since only 255 nack ranges can fit.
+ 0xFE, 0x01,
+ // Zero delta time.
+ 0x00, 0x00,
+ // num missing packet ranges (limited to 255 by size of this field).
+ 0xFF,
+ // {missing packet delta, further missing packets in range}
+ // 6 nack ranges x 42 + 3 nack ranges
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ };
+ // clang-format on
+
scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ if (framer_.version() <= QUIC_VERSION_31) {
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+ } else {
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(),
+ AsChars(packet_version32), arraysize(packet_version32));
+ }
}
TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
@@ -3590,13 +4105,53 @@ TEST_P(QuicFramerTest, BuildTruncatedAckFrameSmallPacket) {
};
// clang-format on
- scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames, 37u));
- ASSERT_TRUE(data != nullptr);
- // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
- EXPECT_EQ(36u, data->length());
- test::CompareCharArraysWithHexError("constructed packet", data->data(),
- data->length(), AsChars(packet),
- arraysize(packet));
+ // clang-format off
+ unsigned char packet_version32[] = {
+ // public flags (8 byte connection_id)
+ 0x3C,
+ // connection_id
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
+ // packet number
+ 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (has nacks, is truncated, 2 byte largest observed, 1 byte delta)
+ 0x74,
+ // entropy hash of all received packets, set to 1 by TestEntropyCalculator
+ // since ack is truncated.
+ 0x01,
+ // 2-byte largest observed packet number.
+ // Expected to be 12 (0x0C), since only 6 nack ranges can fit.
+ 0x0C, 0x00,
+ // Zero delta time.
+ 0x00, 0x00,
+ // num missing packet ranges (limited to 6 by packet size of 37).
+ 0x06,
+ // {missing packet delta, further missing packets in range}
+ // 6 nack ranges
+ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+ };
+ // clang-format on
+
+ if (framer_.version() <= QUIC_VERSION_31) {
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames, 37u));
+ ASSERT_TRUE(data != nullptr);
+ // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
+ EXPECT_EQ(36u, data->length());
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ arraysize(packet));
+ } else {
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames, 36u));
+ ASSERT_TRUE(data != nullptr);
+ // Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
+ EXPECT_EQ(35u, data->length());
+ test::CompareCharArraysWithHexError(
+ "constructed packet", data->data(), data->length(),
+ AsChars(packet_version32), arraysize(packet_version32));
+ }
}
TEST_P(QuicFramerTest, BuildStopWaitingPacket) {
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 3e2c444..569d285 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -129,11 +129,11 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
// Holds a packet to be written to the wire, and the IO mode that should
// be used by the mock socket when performing the write.
struct PacketToWrite {
- PacketToWrite(IoMode mode, QuicEncryptedPacket* packet)
+ PacketToWrite(IoMode mode, QuicReceivedPacket* packet)
: mode(mode), packet(packet) {}
PacketToWrite(IoMode mode, int rv) : mode(mode), packet(nullptr), rv(rv) {}
IoMode mode;
- QuicEncryptedPacket* packet;
+ QuicReceivedPacket* packet;
int rv;
};
@@ -161,7 +161,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
}
// Adds a packet to the list of expected writes.
- void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
+ void AddWrite(scoped_ptr<QuicReceivedPacket> packet) {
writes_.push_back(PacketToWrite(SYNCHRONOUS, packet.release()));
}
@@ -170,14 +170,14 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
}
// Returns the packet to be written at position |pos|.
- QuicEncryptedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
+ QuicReceivedPacket* GetWrite(size_t pos) { return writes_[pos].packet; }
bool AtEof() {
return socket_data_->AllReadDataConsumed() &&
socket_data_->AllWriteDataConsumed();
}
- void ProcessPacket(scoped_ptr<QuicEncryptedPacket> packet) {
+ void ProcessPacket(scoped_ptr<QuicReceivedPacket> packet) {
connection_->ProcessUdpPacket(self_addr_, peer_addr_, *packet);
}
@@ -283,7 +283,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
response_data_ = body;
}
- scoped_ptr<QuicEncryptedPacket> InnerConstructDataPacket(
+ scoped_ptr<QuicReceivedPacket> InnerConstructDataPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -294,7 +294,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
should_include_version, fin, offset, data);
}
- scoped_ptr<QuicEncryptedPacket> ConstructDataPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructDataPacket(
QuicPacketNumber packet_number,
bool should_include_version,
bool fin,
@@ -304,7 +304,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
should_include_version, fin, offset, data);
}
- scoped_ptr<QuicEncryptedPacket> InnerConstructRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> InnerConstructRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -318,7 +318,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
request_headers_, spdy_headers_frame_length);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRequestHeadersPacket(
QuicPacketNumber packet_number,
bool fin,
RequestPriority request_priority,
@@ -328,7 +328,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
spdy_headers_frame_length);
}
- scoped_ptr<QuicEncryptedPacket> InnerConstructResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> InnerConstructResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool fin,
@@ -338,7 +338,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
spdy_headers_frame_length, &response_offset_);
}
- scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacket(
QuicPacketNumber packet_number,
bool fin,
size_t* spdy_headers_frame_length) {
@@ -346,7 +346,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
spdy_headers_frame_length);
}
- scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacketWithOffset(
+ scoped_ptr<QuicReceivedPacket> ConstructResponseHeadersPacketWithOffset(
QuicPacketNumber packet_number,
bool fin,
size_t* spdy_headers_frame_length,
@@ -356,7 +356,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
spdy_headers_frame_length, offset);
}
- scoped_ptr<QuicEncryptedPacket> ConstructResponseTrailersPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructResponseTrailersPacket(
QuicPacketNumber packet_number,
bool fin,
const SpdyHeaderBlock& trailers,
@@ -367,26 +367,26 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
spdy_headers_frame_length, offset);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamPacket(
QuicPacketNumber packet_number) {
return maker_.MakeRstPacket(
packet_number, true, stream_id_,
AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamCancelledPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamCancelledPacket(
QuicPacketNumber packet_number) {
return maker_.MakeRstPacket(packet_number, !kIncludeVersion, stream_id_,
QUIC_STREAM_CANCELLED);
}
- scoped_ptr<QuicEncryptedPacket> ConstructRstStreamVaryMismatchPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructRstStreamVaryMismatchPacket(
QuicPacketNumber packet_number) {
return maker_.MakeRstPacket(packet_number, !kIncludeVersion, promise_id_,
QUIC_PROMISE_VARY_MISMATCH);
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber ack_least_unacked,
@@ -397,12 +397,12 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<QuicVersion> {
!kIncludeCongestionFeedback);
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckAndRstStreamPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckAndRstStreamPacket(
QuicPacketNumber packet_number) {
return ConstructAckAndRstStreamPacket(packet_number, 2, 1, 1);
}
- scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
+ scoped_ptr<QuicReceivedPacket> ConstructAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked) {
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 4ec1012..2da013e 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -194,6 +194,8 @@ QuicTag QuicVersionToQuicTag(const QuicVersion version) {
return MakeQuicTag('Q', '0', '3', '0');
case QUIC_VERSION_31:
return MakeQuicTag('Q', '0', '3', '1');
+ case QUIC_VERSION_32:
+ return MakeQuicTag('Q', '0', '3', '2');
default:
// This shold be an ERROR because we should never attempt to convert an
// invalid QuicVersion to be written to the wire.
@@ -227,6 +229,7 @@ string QuicVersionToString(const QuicVersion version) {
RETURN_STRING_LITERAL(QUIC_VERSION_29);
RETURN_STRING_LITERAL(QUIC_VERSION_30);
RETURN_STRING_LITERAL(QUIC_VERSION_31);
+ RETURN_STRING_LITERAL(QUIC_VERSION_32);
default:
return "QUIC_VERSION_UNSUPPORTED";
}
@@ -354,7 +357,7 @@ QuicFrame::QuicFrame(QuicPathCloseFrame* frame)
ostream& operator<<(ostream& os, const QuicStopWaitingFrame& sent_info) {
os << "entropy_hash: " << static_cast<int>(sent_info.entropy_hash)
- << " least_unacked: " << sent_info.least_unacked;
+ << " least_unacked: " << sent_info.least_unacked << "\n";
return os;
}
@@ -532,7 +535,7 @@ ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) {
ack_frame.received_packet_times) {
os << p.first << " at " << p.second.ToDebuggingValue() << " ";
}
- os << " ]";
+ os << " ]\n";
return os;
}
@@ -695,6 +698,40 @@ QuicEncryptedPacket::QuicEncryptedPacket(char* buffer,
bool owns_buffer)
: QuicData(buffer, length, owns_buffer) {}
+QuicEncryptedPacket* QuicEncryptedPacket::Clone() const {
+ char* buffer = new char[this->length()];
+ memcpy(buffer, this->data(), this->length());
+ return new QuicEncryptedPacket(buffer, this->length(), true);
+}
+
+ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
+ os << s.length() << "-byte data";
+ return os;
+}
+
+QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
+ size_t length,
+ QuicTime receipt_time)
+ : QuicEncryptedPacket(buffer, length), receipt_time_(receipt_time) {}
+
+QuicReceivedPacket::QuicReceivedPacket(char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer)
+ : QuicEncryptedPacket(buffer, length, owns_buffer),
+ receipt_time_(receipt_time) {}
+
+QuicReceivedPacket* QuicReceivedPacket::Clone() const {
+ char* buffer = new char[this->length()];
+ memcpy(buffer, this->data(), this->length());
+ return new QuicReceivedPacket(buffer, this->length(), receipt_time(), true);
+}
+
+ostream& operator<<(ostream& os, const QuicReceivedPacket& s) {
+ os << s.length() << "-byte data";
+ return os;
+}
+
StringPiece QuicPacket::AssociatedData() const {
return StringPiece(data(), GetStartOfEncryptedData(
connection_id_length_, includes_version_,
@@ -746,17 +783,6 @@ SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
SerializedPacket::~SerializedPacket() {}
-QuicEncryptedPacket* QuicEncryptedPacket::Clone() const {
- char* buffer = new char[this->length()];
- memcpy(buffer, this->data(), this->length());
- return new QuicEncryptedPacket(buffer, this->length(), true);
-}
-
-ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
- os << s.length() << "-byte data";
- return os;
-}
-
TransmissionInfo::TransmissionInfo()
: encryption_level(ENCRYPTION_NONE),
packet_number_length(PACKET_1BYTE_PACKET_NUMBER),
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 7757c23..73ebf3a 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -337,7 +337,10 @@ enum QuicPacketPrivateFlags {
PACKET_PRIVATE_FLAGS_FEC = 1 << 2,
// All bits set (bits 3-7 are not currently used): 00000111
- PACKET_PRIVATE_FLAGS_MAX = (1 << 3) - 1
+ PACKET_PRIVATE_FLAGS_MAX = (1 << 3) - 1,
+
+ // For version 32 (bits 1-7 are not used): 00000001
+ PACKET_PRIVATE_FLAGS_MAX_VERSION_32 = (1 << 1) - 1
};
// The available versions of QUIC. Guaranteed that the integer value of the enum
@@ -358,6 +361,7 @@ enum QuicVersion {
QUIC_VERSION_29 = 29, // Server and client honor QUIC_STREAM_NO_ERROR.
QUIC_VERSION_30 = 30, // Add server side support of cert transparency.
QUIC_VERSION_31 = 31, // Adds a hash of the client hello to crypto proof.
+ QUIC_VERSION_32 = 32, // FEC related fields are removed from wire format.
};
// This vector contains QUIC versions which we currently support.
@@ -368,8 +372,8 @@ enum QuicVersion {
// IMPORTANT: if you are adding to this list, follow the instructions at
// http://sites/quic/adding-and-removing-versions
static const QuicVersion kSupportedQuicVersions[] = {
- QUIC_VERSION_31, QUIC_VERSION_30, QUIC_VERSION_29, QUIC_VERSION_28,
- QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25};
+ QUIC_VERSION_32, QUIC_VERSION_31, QUIC_VERSION_30, QUIC_VERSION_29,
+ QUIC_VERSION_28, QUIC_VERSION_27, QUIC_VERSION_26, QUIC_VERSION_25};
typedef std::vector<QuicVersion> QuicVersionVector;
@@ -494,6 +498,8 @@ enum QuicErrorCode {
QUIC_INVALID_FEC_DATA = 5,
// STREAM frame data is malformed.
QUIC_INVALID_STREAM_DATA = 46,
+ // STREAM frame data overlaps with buffered data.
+ QUIC_OVERLAPPING_STREAM_DATA = 87,
// STREAM frame data is not encrypted.
QUIC_UNENCRYPTED_STREAM_DATA = 61,
// FEC frame data is not encrypted.
@@ -559,7 +565,7 @@ enum QuicErrorCode {
// There was an error while reading from the socket.
QUIC_PACKET_READ_ERROR = 51,
// We received a STREAM_FRAME with no data and no fin flag set.
- QUIC_INVALID_STREAM_FRAME = 50,
+ QUIC_EMPTY_STREAM_FRAME_NO_FIN = 50,
// We received invalid data on the headers stream.
QUIC_INVALID_HEADERS_STREAM_DATA = 56,
// The peer received too much data, violating flow control.
@@ -662,7 +668,7 @@ enum QuicErrorCode {
QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM = 84,
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 87,
+ QUIC_LAST_ERROR = 88,
};
// Must be updated any time a QuicErrorCode is deprecated.
@@ -1245,6 +1251,35 @@ class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
};
+// A received encrypted QUIC packet, with a recorded time of receipt.
+class NET_EXPORT_PRIVATE QuicReceivedPacket : public QuicEncryptedPacket {
+ public:
+ QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
+ QuicReceivedPacket(char* buffer,
+ size_t length,
+ QuicTime receipt_time,
+ bool owns_buffer);
+
+ // Clones the packet into a new packet which owns the buffer.
+ QuicReceivedPacket* Clone() const;
+
+ // Returns the time at which the packet was received.
+ QuicTime receipt_time() const { return receipt_time_; }
+
+ // By default, gtest prints the raw bytes of an object. The bool data
+ // member (in the base class QuicData) causes this object to have padding
+ // bytes, which causes the default gtest object printer to read
+ // uninitialize memory. So we need to teach gtest how to print this object.
+ NET_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicReceivedPacket& s);
+
+ private:
+ const QuicTime receipt_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
+};
+
// Pure virtual class to listen for packet acknowledgements.
class NET_EXPORT_PRIVATE QuicAckListenerInterface
: public base::RefCounted<QuicAckListenerInterface> {
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 14edd79..9448d98 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -230,7 +230,7 @@ bool QuicSession::HasOpenDynamicStreams() const {
void QuicSession::ProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
connection_->ProcessUdpPacket(self_address, peer_address, packet);
}
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index 988c000..a8b610f 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -88,7 +88,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// Called on every incoming packet. Passes |packet| through to |connection_|.
virtual void ProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet);
+ const QuicReceivedPacket& packet);
// Called by streams when they want to write data to the peer.
// Returns a pair with the number of bytes consumed from data, and a boolean
diff --git a/net/quic/quic_session_test.cc b/net/quic/quic_session_test.cc
index 534b6682..65702f8 100644
--- a/net/quic/quic_session_test.cc
+++ b/net/quic/quic_session_test.cc
@@ -89,10 +89,6 @@ class TestStream : public QuicSpdyStream {
void OnDataAvailable() override {}
- void SendBody(const string& data, bool fin) {
- WriteOrBufferData(data, fin, nullptr);
- }
-
MOCK_METHOD0(OnCanWrite, void());
};
@@ -142,6 +138,12 @@ class TestSession : public QuicSpdySession {
}
}
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId /*id*/) override {
+ return true;
+ }
+
+ bool ShouldCreateOutgoingDynamicStream() override { return true; }
+
bool IsClosedStream(QuicStreamId id) {
return QuicSession::IsClosedStream(id);
}
@@ -723,7 +725,7 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
EXPECT_CALL(*connection_, SendBlocked(stream2->id()));
EXPECT_CALL(*connection_, SendBlocked(0));
- stream2->SendBody(body, false);
+ stream2->WriteOrBufferBody(body, false, nullptr);
EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
diff --git a/net/quic/quic_spdy_session.h b/net/quic/quic_spdy_session.h
index 246a6de..8db7049 100644
--- a/net/quic/quic_spdy_session.h
+++ b/net/quic/quic_spdy_session.h
@@ -89,6 +89,12 @@ class NET_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
+ // If an incoming stream can be created, return true.
+ virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id) = 0;
+
+ // If an outgoing stream can be created, return true.
+ virtual bool ShouldCreateOutgoingDynamicStream() = 0;
+
private:
friend class test::QuicSpdySessionPeer;
diff --git a/net/quic/quic_spdy_stream.cc b/net/quic/quic_spdy_stream.cc
index 3486593..514d317 100644
--- a/net/quic/quic_spdy_stream.cc
+++ b/net/quic/quic_spdy_stream.cc
@@ -77,6 +77,13 @@ size_t QuicSpdyStream::WriteHeaders(
return bytes_written;
}
+void QuicSpdyStream::WriteOrBufferBody(
+ const string& data,
+ bool fin,
+ QuicAckListenerInterface* ack_notifier_delegate) {
+ WriteOrBufferData(data, fin, ack_notifier_delegate);
+}
+
size_t QuicSpdyStream::WriteTrailers(
SpdyHeaderBlock trailer_block,
QuicAckListenerInterface* ack_notifier_delegate) {
@@ -218,7 +225,7 @@ void QuicSpdyStream::OnTrailingHeadersComplete(bool fin, size_t /*frame_len*/) {
SpdyHeaderBlock trailers;
if (!SpdyUtils::ParseTrailers(decompressed_trailers().data(),
decompressed_trailers().length(),
- &final_byte_offset, &response_trailers_)) {
+ &final_byte_offset, &received_trailers_)) {
DLOG(ERROR) << "Trailers are malformed: " << id();
session()->connection()->SendConnectionCloseWithDetails(
QUIC_INVALID_HEADERS_STREAM_DATA, "Trailers are malformed");
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h
index a5adfe2..ee3a9a21 100644
--- a/net/quic/quic_spdy_stream.h
+++ b/net/quic/quic_spdy_stream.h
@@ -105,6 +105,11 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
bool fin,
QuicAckListenerInterface* ack_notifier_delegate);
+ // Sends |data| to the peer, or buffers if it can't be sent immediately.
+ void WriteOrBufferBody(const std::string& data,
+ bool fin,
+ QuicAckListenerInterface* ack_notifier_delegate);
+
// Writes the trailers contained in |trailer_block| to the dedicated
// headers stream. Trailers will always have the FIN set.
size_t WriteTrailers(SpdyHeaderBlock trailer_block,
@@ -142,8 +147,8 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
}
// Returns whatever trailers have been received for this stream.
- const SpdyHeaderBlock& response_trailers() const {
- return response_trailers_;
+ const SpdyHeaderBlock& received_trailers() const {
+ return received_trailers_;
}
virtual SpdyPriority priority() const;
@@ -188,7 +193,7 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream {
// via ProcessData or Readv.
std::string decompressed_trailers_;
// The parsed trailers received from the peer.
- SpdyHeaderBlock response_trailers_;
+ SpdyHeaderBlock received_trailers_;
DISALLOW_COPY_AND_ASSIGN(QuicSpdyStream);
};
diff --git a/net/quic/quic_spdy_stream_test.cc b/net/quic/quic_spdy_stream_test.cc
index 1e7abc6..36eda71 100644
--- a/net/quic/quic_spdy_stream_test.cc
+++ b/net/quic/quic_spdy_stream_test.cc
@@ -646,6 +646,35 @@ TEST_P(QuicSpdyStreamTest, ReceivingTrailers) {
EXPECT_EQ("", stream_->decompressed_trailers());
}
+TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutOffset) {
+ // Test that receiving trailers without a final offset field is an error.
+ Initialize(kShouldProcessData);
+
+ // Receive initial headers.
+ string headers = SpdyUtils::SerializeUncompressedHeaders(headers_);
+ stream_->OnStreamHeaders(headers);
+ stream_->OnStreamHeadersComplete(false, headers.size());
+ stream_->MarkHeadersConsumed(stream_->decompressed_headers().size());
+
+ const string body = "this is the body";
+ // Receive trailing headers, without kFinalOffsetHeaderKey.
+ SpdyHeaderBlock trailers_block;
+ trailers_block["key1"] = "value1";
+ trailers_block["key2"] = "value2";
+ trailers_block["key3"] = "value3";
+ string trailers = SpdyUtils::SerializeUncompressedHeaders(trailers_block);
+ stream_->OnStreamHeaders(trailers);
+
+ // Verify that the trailers block didn't contain a final offset.
+ EXPECT_EQ("", trailers_block[kFinalOffsetHeaderKey].as_string());
+
+ // Receipt of the malformed trailers will close the connection.
+ EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
+ QUIC_INVALID_HEADERS_STREAM_DATA, _))
+ .Times(1);
+ stream_->OnStreamHeadersComplete(/*fin=*/true, trailers.size());
+}
+
TEST_P(QuicSpdyStreamTest, ReceivingTrailersWithoutFin) {
// Test that received Trailers must always have the FIN set.
Initialize(kShouldProcessData);
diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc
index 113f4ff..5228a0a 100644
--- a/net/quic/quic_stream_sequencer.cc
+++ b/net/quic/quic_stream_sequencer.cc
@@ -13,8 +13,9 @@
#include "net/quic/quic_clock.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
+#include "net/quic/quic_utils.h"
#include "net/quic/reliable_quic_stream.h"
-#include "net/quic/stream_sequencer_buffer.h"
using std::min;
using std::numeric_limits;
@@ -40,11 +41,12 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
++num_frames_received_;
const QuicStreamOffset byte_offset = frame.offset;
const size_t data_len = frame.frame_length;
- if (data_len == 0 && !frame.fin) {
+ bool consolidate_errors = FLAGS_quic_consolidate_onstreamframe_errors;
+ if (!consolidate_errors && data_len == 0 && !frame.fin) {
// Stream frames must have data or a fin flag.
LOG(WARNING) << "QUIC_INVALID_STREAM_FRAM: Empty stream frame "
"without FIN set.";
- stream_->CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME,
+ stream_->CloseConnectionWithDetails(QUIC_EMPTY_STREAM_FRAME_NO_FIN,
"Empty stream frame without FIN set.");
return;
}
@@ -56,18 +58,28 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
}
}
size_t bytes_written;
+ string error_details;
QuicErrorCode result = buffered_frames_.OnStreamData(
byte_offset, StringPiece(frame.frame_buffer, frame.frame_length),
- clock_->ApproximateNow(), &bytes_written);
-
- if (result == QUIC_INVALID_STREAM_DATA) {
- LOG(WARNING) << "QUIC_INVALID_STREAM_FRAME: Stream frame "
- "overlaps with buffered data.";
- stream_->CloseConnectionWithDetails(
- QUIC_INVALID_STREAM_FRAME, "Stream frame overlaps with buffered data.");
- return;
+ clock_->ApproximateNow(), &bytes_written, &error_details);
+ if (!consolidate_errors) {
+ if (result == QUIC_OVERLAPPING_STREAM_DATA) {
+ LOG(WARNING) << "QUIC_INVALID_STREAM_FRAME: Stream frame "
+ "overlaps with buffered data.";
+ stream_->CloseConnectionWithDetails(
+ QUIC_EMPTY_STREAM_FRAME_NO_FIN,
+ "Stream frame overlaps with buffered data.");
+ return;
+ }
+ } else {
+ if (result != QUIC_NO_ERROR) {
+ LOG(WARNING) << QuicUtils::ErrorToString(result) << ": " << error_details;
+ stream_->CloseConnectionWithDetails(result, error_details);
+ return;
+ }
}
- if (result == QUIC_NO_ERROR && bytes_written == 0) {
+
+ if ((consolidate_errors || result == QUIC_NO_ERROR) && bytes_written == 0) {
++num_duplicate_frames_received_;
// Silently ignore duplicates.
return;
diff --git a/net/quic/quic_stream_sequencer.h b/net/quic/quic_stream_sequencer.h
index 1d06d2f..add7fbc 100644
--- a/net/quic/quic_stream_sequencer.h
+++ b/net/quic/quic_stream_sequencer.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "net/quic/quic_protocol.h"
-#include "net/quic/stream_sequencer_buffer.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
using std::string;
@@ -116,7 +116,7 @@ class NET_EXPORT_PRIVATE QuicStreamSequencer {
ReliableQuicStream* stream_;
// Stores received data in offset order.
- StreamSequencerBuffer buffered_frames_;
+ QuicStreamSequencerBuffer buffered_frames_;
// The offset, if any, we got a stream termination for. When this many bytes
// have been processed, the sequencer will be closed.
diff --git a/net/quic/stream_sequencer_buffer.cc b/net/quic/quic_stream_sequencer_buffer.cc
index 0582fd7..5f94085 100644
--- a/net/quic/stream_sequencer_buffer.cc
+++ b/net/quic/quic_stream_sequencer_buffer.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/stream_sequencer_buffer.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
#include "base/logging.h"
#include "net/quic/quic_bug_tracker.h"
@@ -11,17 +11,18 @@ using std::min;
namespace net {
-StreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset,
- QuicStreamOffset end_offset)
+QuicStreamSequencerBuffer::Gap::Gap(QuicStreamOffset begin_offset,
+ QuicStreamOffset end_offset)
: begin_offset(begin_offset), end_offset(end_offset) {}
-StreamSequencerBuffer::FrameInfo::FrameInfo()
+QuicStreamSequencerBuffer::FrameInfo::FrameInfo()
: length(1), timestamp(QuicTime::Zero()) {}
-StreamSequencerBuffer::FrameInfo::FrameInfo(size_t length, QuicTime timestamp)
+QuicStreamSequencerBuffer::FrameInfo::FrameInfo(size_t length,
+ QuicTime timestamp)
: length(length), timestamp(timestamp) {}
-StreamSequencerBuffer::StreamSequencerBuffer(size_t max_capacity_bytes)
+QuicStreamSequencerBuffer::QuicStreamSequencerBuffer(size_t max_capacity_bytes)
: max_buffer_capacity_bytes_(max_capacity_bytes),
blocks_count_(
ceil(static_cast<double>(max_capacity_bytes) / kBlockSizeBytes)),
@@ -30,11 +31,11 @@ StreamSequencerBuffer::StreamSequencerBuffer(size_t max_capacity_bytes)
Clear();
}
-StreamSequencerBuffer::~StreamSequencerBuffer() {
+QuicStreamSequencerBuffer::~QuicStreamSequencerBuffer() {
Clear();
}
-void StreamSequencerBuffer::Clear() {
+void QuicStreamSequencerBuffer::Clear() {
for (size_t i = 0; i < blocks_count_; ++i) {
if (blocks_[i] != nullptr) {
RetireBlock(i);
@@ -49,24 +50,25 @@ void StreamSequencerBuffer::Clear() {
frame_arrival_time_map_.clear();
}
-void StreamSequencerBuffer::RetireBlock(size_t idx) {
+void QuicStreamSequencerBuffer::RetireBlock(size_t idx) {
DCHECK(blocks_[idx] != nullptr);
delete blocks_[idx];
blocks_[idx] = nullptr;
DVLOG(1) << "Retired block with index: " << idx;
}
-QuicErrorCode StreamSequencerBuffer::OnStreamData(
+QuicErrorCode QuicStreamSequencerBuffer::OnStreamData(
QuicStreamOffset starting_offset,
base::StringPiece data,
QuicTime timestamp,
- size_t* const bytes_buffered) {
+ size_t* const bytes_buffered,
+ std::string* error_details) {
*bytes_buffered = 0;
QuicStreamOffset offset = starting_offset;
size_t size = data.size();
if (size == 0) {
- QUIC_BUG << "Attempted to write 0 bytes of data.";
- return QUIC_INVALID_STREAM_FRAME;
+ *error_details = "Received empty stream frame without FIN.";
+ return QUIC_EMPTY_STREAM_FRAME_NO_FIN;
}
// Find the first gap not ending before |offset|. This gap maybe the gap to
@@ -90,15 +92,18 @@ QuicErrorCode StreamSequencerBuffer::OnStreamData(
if (offset < current_gap->begin_offset &&
offset + size > current_gap->begin_offset) {
// Beginning of new data overlaps data before current gap.
- return QUIC_INVALID_STREAM_DATA;
+ *error_details = "Beginning of received data overlaps with buffered data.";
+ return QUIC_OVERLAPPING_STREAM_DATA;
}
if (offset + size > current_gap->end_offset) {
// End of new data overlaps with data after current gap.
- return QUIC_INVALID_STREAM_DATA;
+ *error_details = "End of received data overlaps with buffered data.";
+ return QUIC_OVERLAPPING_STREAM_DATA;
}
// Write beyond the current range this buffer is covering.
if (offset + size > total_bytes_read_ + max_buffer_capacity_bytes_) {
+ *error_details = "Received data beyond available range.";
return QUIC_INTERNAL_ERROR;
}
@@ -148,7 +153,7 @@ QuicErrorCode StreamSequencerBuffer::OnStreamData(
return QUIC_NO_ERROR;
}
-inline void StreamSequencerBuffer::UpdateGapList(
+inline void QuicStreamSequencerBuffer::UpdateGapList(
std::list<Gap>::iterator gap_with_new_data_written,
QuicStreamOffset start_offset,
size_t bytes_written) {
@@ -178,7 +183,8 @@ inline void StreamSequencerBuffer::UpdateGapList(
}
}
-size_t StreamSequencerBuffer::Readv(const iovec* dest_iov, size_t dest_count) {
+size_t QuicStreamSequencerBuffer::Readv(const iovec* dest_iov,
+ size_t dest_count) {
size_t bytes_read = 0;
for (size_t i = 0; i < dest_count && ReadableBytes() > 0; ++i) {
char* dest = reinterpret_cast<char*>(dest_iov[i].iov_base);
@@ -215,8 +221,8 @@ size_t StreamSequencerBuffer::Readv(const iovec* dest_iov, size_t dest_count) {
return bytes_read;
}
-int StreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
- int iov_count) const {
+int QuicStreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
+ int iov_count) const {
DCHECK(iov != nullptr);
DCHECK_GT(iov_count, 0);
@@ -273,8 +279,8 @@ int StreamSequencerBuffer::GetReadableRegions(struct iovec* iov,
return iov_used;
}
-bool StreamSequencerBuffer::GetReadableRegion(iovec* iov,
- QuicTime* timestamp) const {
+bool QuicStreamSequencerBuffer::GetReadableRegion(iovec* iov,
+ QuicTime* timestamp) const {
if (ReadableBytes() == 0) {
iov[0].iov_base = nullptr;
iov[0].iov_len = 0;
@@ -312,7 +318,7 @@ bool StreamSequencerBuffer::GetReadableRegion(iovec* iov,
return true;
}
-bool StreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
+bool QuicStreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
if (bytes_used > ReadableBytes()) {
return false;
}
@@ -338,46 +344,47 @@ bool StreamSequencerBuffer::MarkConsumed(size_t bytes_used) {
return true;
}
-size_t StreamSequencerBuffer::FlushBufferedFrames() {
+size_t QuicStreamSequencerBuffer::FlushBufferedFrames() {
size_t prev_total_bytes_read = total_bytes_read_;
total_bytes_read_ = gaps_.back().begin_offset;
Clear();
return total_bytes_read_ - prev_total_bytes_read;
}
-size_t StreamSequencerBuffer::ReadableBytes() const {
+size_t QuicStreamSequencerBuffer::ReadableBytes() const {
return gaps_.front().begin_offset - total_bytes_read_;
}
-bool StreamSequencerBuffer::HasBytesToRead() const {
+bool QuicStreamSequencerBuffer::HasBytesToRead() const {
return ReadableBytes() > 0;
}
-QuicStreamOffset StreamSequencerBuffer::BytesConsumed() const {
+QuicStreamOffset QuicStreamSequencerBuffer::BytesConsumed() const {
return total_bytes_read_;
}
-size_t StreamSequencerBuffer::BytesBuffered() const {
+size_t QuicStreamSequencerBuffer::BytesBuffered() const {
return num_bytes_buffered_;
}
-size_t StreamSequencerBuffer::GetBlockIndex(QuicStreamOffset offset) const {
+size_t QuicStreamSequencerBuffer::GetBlockIndex(QuicStreamOffset offset) const {
return (offset % max_buffer_capacity_bytes_) / kBlockSizeBytes;
}
-size_t StreamSequencerBuffer::GetInBlockOffset(QuicStreamOffset offset) const {
+size_t QuicStreamSequencerBuffer::GetInBlockOffset(
+ QuicStreamOffset offset) const {
return (offset % max_buffer_capacity_bytes_) % kBlockSizeBytes;
}
-size_t StreamSequencerBuffer::ReadOffset() const {
+size_t QuicStreamSequencerBuffer::ReadOffset() const {
return GetInBlockOffset(total_bytes_read_);
}
-size_t StreamSequencerBuffer::NextBlockToRead() const {
+size_t QuicStreamSequencerBuffer::NextBlockToRead() const {
return GetBlockIndex(total_bytes_read_);
}
-void StreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
+void QuicStreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
DCHECK(ReadableBytes() == 0 || GetInBlockOffset(total_bytes_read_) == 0)
<< "RetireBlockIfEmpty() should only be called when advancing to next "
"block"
@@ -411,11 +418,11 @@ void StreamSequencerBuffer::RetireBlockIfEmpty(size_t block_index) {
RetireBlock(block_index);
}
-bool StreamSequencerBuffer::Empty() const {
+bool QuicStreamSequencerBuffer::Empty() const {
return gaps_.size() == 1 && gaps_.front().begin_offset == total_bytes_read_;
}
-size_t StreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
+size_t QuicStreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
if ((block_index + 1) == blocks_count_) {
size_t result = max_buffer_capacity_bytes_ % kBlockSizeBytes;
if (result == 0) { // whole block
@@ -427,7 +434,7 @@ size_t StreamSequencerBuffer::GetBlockCapacity(size_t block_index) const {
}
}
-void StreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) {
+void QuicStreamSequencerBuffer::UpdateFrameArrivalMap(QuicStreamOffset offset) {
// Get the frame before which all frames should be removed.
auto next_frame = frame_arrival_time_map_.upper_bound(offset);
DCHECK(next_frame != frame_arrival_time_map_.begin());
diff --git a/net/quic/stream_sequencer_buffer.h b/net/quic/quic_stream_sequencer_buffer.h
index 93dd57c..2a59041 100644
--- a/net/quic/stream_sequencer_buffer.h
+++ b/net/quic/quic_stream_sequencer_buffer.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
-#define NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#ifndef NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#define NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
-// StreamSequencerBuffer implements QuicStreamSequencerBufferInterface.
+// QuicStreamSequencerBuffer implements QuicStreamSequencerBufferInterface.
// It is a circular stream buffer with random write and
// in-sequence read. It consists of a vector of pointers pointing
// to memory blocks created as needed and a list of Gaps to indicate
@@ -20,14 +20,14 @@
//
// This class is thread-unsafe.
//
-// StreamSequencerBuffer maintains a concept of the readable region, which
+// QuicStreamSequencerBuffer maintains a concept of the readable region, which
// contains all written data that has not been read.
// It promises stability of the underlying memory addresses in the readable
// region, so pointers into it can be maintained, and the offset of a pointer
// from the start of the read region can be calculated.
//
// Expected Use:
-// StreamSequencerBuffer buffer(2.5 * 8 * 1024);
+// QuicStreamSequencerBuffer buffer(2.5 * 8 * 1024);
// std::string source(1024, 'a');
// base::StringPiece std::string_piece(source.data(), source.size());
// size_t written = 0;
@@ -68,16 +68,16 @@
#include "base/macros.h"
#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_stream_sequencer_buffer_interface.h"
+
+using base::StringPiece;
namespace net {
namespace test {
-class StreamSequencerBufferPeer;
+class QuicStreamSequencerBufferPeer;
} // namespace test
-class NET_EXPORT_PRIVATE StreamSequencerBuffer
- : public QuicStreamSequencerBufferInterface {
+class NET_EXPORT_PRIVATE QuicStreamSequencerBuffer {
public:
// A Gap indicates a missing chunk of bytes between
// [begin_offset, end_offset) in the stream
@@ -106,28 +106,65 @@ class NET_EXPORT_PRIVATE StreamSequencerBuffer
char buffer[kBlockSizeBytes];
};
- explicit StreamSequencerBuffer(size_t max_capacity_bytes);
+ explicit QuicStreamSequencerBuffer(size_t max_capacity_bytes);
+ ~QuicStreamSequencerBuffer();
+
+ // Free the space used to buffer data.
+ void Clear();
- ~StreamSequencerBuffer() override;
+ // Returns true if there is nothing to read in this buffer.
+ bool Empty() const;
- // QuicStreamSequencerBufferInterface implementation.
- void Clear() override;
- bool Empty() const override;
+ // Called to buffer new data received for this stream. If the data was
+ // successfully buffered, returns QUIC_NO_ERROR and stores the number of
+ // bytes buffered in |bytes_buffered|. Returns an error otherwise.
+ // |timestamp| is the time the data arrived.
QuicErrorCode OnStreamData(QuicStreamOffset offset,
base::StringPiece data,
QuicTime timestamp,
- size_t* bytes_buffered) override;
- size_t Readv(const struct iovec* dest_iov, size_t dest_count) override;
- int GetReadableRegions(struct iovec* iov, int iov_len) const override;
- bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const override;
- bool MarkConsumed(size_t bytes_buffered) override;
- size_t FlushBufferedFrames() override;
- bool HasBytesToRead() const override;
- QuicStreamOffset BytesConsumed() const override;
- size_t BytesBuffered() const override;
+ size_t* bytes_buffered,
+ std::string* error_details);
+
+ // Reads from this buffer into given iovec array, up to number of iov_len
+ // iovec objects and returns the number of bytes read.
+ size_t Readv(const struct iovec* dest_iov, size_t dest_count);
+
+ // Returns the readable region of valid data in iovec format. The readable
+ // region is the buffer region where there is valid data not yet read by
+ // client.
+ // Returns the number of iovec entries in |iov| which were populated.
+ // If the region is empty, one iovec entry with 0 length
+ // is returned, and the function returns 0. If there are more readable
+ // regions than iov_size, the function only processes the first
+ // iov_size of them.
+ int GetReadableRegions(struct iovec* iov, int iov_len) const;
+
+ // Fills in one iovec with data which all arrived at the same time from the
+ // next readable region.
+ // Populates |timestamp| with the time that this data arrived.
+ // Returns false if there is no readable region available.
+ bool GetReadableRegion(iovec* iov, QuicTime* timestamp) const;
+
+ // Called after GetReadableRegions() to free up |bytes_used| space if these
+ // bytes are processed.
+ // Pre-requisite: bytes_used <= available bytes to read.
+ bool MarkConsumed(size_t bytes_buffered);
+
+ // Deletes and records as consumed any buffered data and clear the buffer.
+ // (To be called only after sequencer's StopReading has been called.)
+ size_t FlushBufferedFrames();
+
+ // Whether there are bytes can be read out.
+ bool HasBytesToRead() const;
+
+ // Count how many bytes have been consumed (read out of buffer).
+ QuicStreamOffset BytesConsumed() const;
+
+ // Count how many bytes are in buffer at this moment.
+ size_t BytesBuffered() const;
private:
- friend class test::StreamSequencerBufferPeer;
+ friend class test::QuicStreamSequencerBufferPeer;
// Dispose the given buffer block.
// After calling this method, blocks_[index] is set to nullptr
@@ -196,8 +233,8 @@ class NET_EXPORT_PRIVATE StreamSequencerBuffer
// Stores all the buffered frames' start offset, length and arrival time.
std::map<QuicStreamOffset, FrameInfo> frame_arrival_time_map_;
- DISALLOW_COPY_AND_ASSIGN(StreamSequencerBuffer);
+ DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBuffer);
};
} // namespace net
-#endif // NET_QUIC_STREAM_SEQUENCER_BUFFER_H_
+#endif // NET_QUIC_QUIC_STREAM_SEQUENCER_BUFFER_H_
diff --git a/net/quic/stream_sequencer_buffer_test.cc b/net/quic/quic_stream_sequencer_buffer_test.cc
index 348205f..5d9bda8 100644
--- a/net/quic/stream_sequencer_buffer_test.cc
+++ b/net/quic/quic_stream_sequencer_buffer_test.cc
@@ -1,8 +1,7 @@
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
-#include "net/quic/stream_sequencer_buffer.h"
+#include "net/quic/quic_stream_sequencer_buffer.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -41,14 +40,15 @@ char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
return '\0';
}
-static const size_t kBlockSizeBytes = StreamSequencerBuffer::kBlockSizeBytes;
-typedef StreamSequencerBuffer::BufferBlock BufferBlock;
-typedef StreamSequencerBuffer::Gap Gap;
-typedef StreamSequencerBuffer::FrameInfo FrameInfo;
+static const size_t kBlockSizeBytes =
+ QuicStreamSequencerBuffer::kBlockSizeBytes;
+typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock;
+typedef QuicStreamSequencerBuffer::Gap Gap;
+typedef QuicStreamSequencerBuffer::FrameInfo FrameInfo;
-class StreamSequencerBufferPeer {
+class QuicStreamSequencerBufferPeer {
public:
- explicit StreamSequencerBufferPeer(StreamSequencerBuffer* buffer)
+ explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer)
: buffer_(buffer) {}
// Read from this buffer_->into the given destination buffer_-> up to the
@@ -142,12 +142,12 @@ class StreamSequencerBufferPeer {
void set_gaps(const std::list<Gap>& gaps) { buffer_->gaps_ = gaps; }
private:
- StreamSequencerBuffer* buffer_;
+ QuicStreamSequencerBuffer* buffer_;
};
namespace {
-class StreamSequencerBufferTest : public testing::Test {
+class QuicStreamSequencerBufferTest : public testing::Test {
public:
void SetUp() override { Initialize(); }
@@ -158,8 +158,8 @@ class StreamSequencerBufferTest : public testing::Test {
protected:
void Initialize() {
- buffer_.reset(new StreamSequencerBuffer(max_capacity_bytes_));
- helper_.reset(new StreamSequencerBufferPeer(buffer_.get()));
+ buffer_.reset(new QuicStreamSequencerBuffer(max_capacity_bytes_));
+ helper_.reset(new QuicStreamSequencerBufferPeer(buffer_.get()));
}
// Use 2.5 here to make sure the buffer has more than one block and its end
@@ -168,42 +168,43 @@ class StreamSequencerBufferTest : public testing::Test {
size_t max_capacity_bytes_ = 2.5 * kBlockSizeBytes;
MockClock clock_;
- std::unique_ptr<StreamSequencerBuffer> buffer_;
- std::unique_ptr<StreamSequencerBufferPeer> helper_;
+ std::unique_ptr<QuicStreamSequencerBuffer> buffer_;
+ std::unique_ptr<QuicStreamSequencerBufferPeer> helper_;
+ string error_details_;
};
-TEST_F(StreamSequencerBufferTest, InitializationWithDifferentSizes) {
- const size_t kCapacity = 2 * StreamSequencerBuffer::kBlockSizeBytes;
+TEST_F(QuicStreamSequencerBufferTest, InitializationWithDifferentSizes) {
+ const size_t kCapacity = 2 * QuicStreamSequencerBuffer::kBlockSizeBytes;
ResetMaxCapacityBytes(kCapacity);
EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
EXPECT_TRUE(helper_->CheckInitialState());
- const size_t kCapacity1 = 8 * StreamSequencerBuffer::kBlockSizeBytes;
+ const size_t kCapacity1 = 8 * QuicStreamSequencerBuffer::kBlockSizeBytes;
ResetMaxCapacityBytes(kCapacity1);
EXPECT_EQ(kCapacity1, helper_->max_buffer_capacity());
EXPECT_TRUE(helper_->CheckInitialState());
}
-TEST_F(StreamSequencerBufferTest, ClearOnEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, ClearOnEmpty) {
buffer_->Clear();
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamData0length) {
- std::string source;
+TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
size_t written;
- EXPECT_DFATAL(
- buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written),
- "Attempted to write 0 bytes of data.");
+ QuicErrorCode error = buffer_->OnStreamData(800, "", clock_.ApproximateNow(),
+ &written, &error_details_);
+ EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN);
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataWithinBlock) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
std::string source(1024, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(800, source, t, &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(800, source, t, &written, &error_details_));
BufferBlock* block_ptr = helper_->GetBlock(0);
for (size_t i = 0; i < source.size(); ++i) {
ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
@@ -219,71 +220,77 @@ TEST_F(StreamSequencerBufferTest, OnStreamDataWithinBlock) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataWithOverlap) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
std::string source(1024, 'a');
// Write something into [800, 1824)
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t1 = clock_.ApproximateNow();
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(800, source, t1, &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(800, source, t1, &written, &error_details_));
// Try to write to [0, 1024) and [1024, 2048).
// But no byte will be written since overlap.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t2 = clock_.ApproximateNow();
- EXPECT_EQ(QUIC_INVALID_STREAM_DATA,
- buffer_->OnStreamData(0, source, t2, &written));
- EXPECT_EQ(QUIC_INVALID_STREAM_DATA,
- buffer_->OnStreamData(1024, source, t2, &written));
+ EXPECT_EQ(QUIC_OVERLAPPING_STREAM_DATA,
+ buffer_->OnStreamData(0, source, t2, &written, &error_details_));
+ EXPECT_EQ(QUIC_OVERLAPPING_STREAM_DATA,
+ buffer_->OnStreamData(1024, source, t2, &written, &error_details_));
auto frame_map = helper_->frame_arrival_time_map();
EXPECT_EQ(1u, frame_map->size());
EXPECT_EQ(t1, (*frame_map)[800].timestamp);
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataOverlapAndDuplicateCornerCases) {
+TEST_F(QuicStreamSequencerBufferTest,
+ OnStreamDataOverlapAndDuplicateCornerCases) {
std::string source(1024, 'a');
// Write something into [800, 1824)
size_t written;
- buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(800, source, clock_.ApproximateNow(), &written,
+ &error_details_);
source = std::string(800, 'b');
// Try to write to [1, 801), but should fail due to overlapping
- EXPECT_EQ(
- QUIC_INVALID_STREAM_DATA,
- buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_OVERLAPPING_STREAM_DATA,
+ buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
+ &error_details_));
// write to [0, 800)
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(
- 0, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_));
// Try to write one byte to [1823, 1824), but should count as duplicate
std::string one_byte = "c";
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(1823, one_byte, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(1823, one_byte, clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(0u, written);
// write one byte to [1824, 1825)
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(1824, one_byte, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(1824, one_byte, clock_.ApproximateNow(),
+ &written, &error_details_));
auto frame_map = helper_->frame_arrival_time_map();
EXPECT_EQ(3u, frame_map->size());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithoutOverlap) {
std::string source(1024, 'a');
// Write something into [800, 1824).
size_t written;
- EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(
- 800, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(800, source, clock_.ApproximateNow(),
+ &written, &error_details_));
source = std::string(100, 'b');
// Write something into [kBlockSizeBytes * 2 - 20, kBlockSizeBytes * 2 + 80).
EXPECT_EQ(QUIC_NO_ERROR,
buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_EQ(3, helper_->GapSize());
EXPECT_EQ(1024u + 100u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
// Assume a stream has already buffered almost 4GB.
uint64_t total_bytes_read = pow(2, 32) - 1;
helper_->set_total_bytes_read(total_bytes_read);
@@ -296,84 +303,89 @@ TEST_F(StreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
size_t written;
// Frame [2^32 + 500, 2^32 + 600).
QuicStreamOffset offset = pow(2, 32) + 500;
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(offset, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(offset, source, clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(2, helper_->GapSize());
// Frame [2^32 + 700, 2^32 + 800).
offset = pow(2, 32) + 700;
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(offset, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(offset, source, clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(3, helper_->GapSize());
// Another frame [2^32 + 300, 2^32 + 400).
offset = pow(2, 32) + 300;
- EXPECT_EQ(
- QUIC_NO_ERROR,
- buffer_->OnStreamData(offset, source, clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR,
+ buffer_->OnStreamData(offset, source, clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(4, helper_->GapSize());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataTillEnd) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEnd) {
// Write 50 bytes to the end.
const size_t kBytesToWrite = 50;
std::string source(kBytesToWrite, 'a');
size_t written;
EXPECT_EQ(QUIC_NO_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_EQ(50u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataTillEndCorner) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEndCorner) {
// Write 1 byte to the end.
const size_t kBytesToWrite = 1;
std::string source(kBytesToWrite, 'a');
size_t written;
EXPECT_EQ(QUIC_NO_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_EQ(1u, buffer_->BytesBuffered());
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
+TEST_F(QuicStreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
std::string source(60, 'a');
size_t written;
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ - 50, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
source = "b";
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(max_capacity_bytes_, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(max_capacity_bytes_ * 1000, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(0u, buffer_->BytesBuffered());
}
-TEST_F(StreamSequencerBufferTest, Readv100Bytes) {
+TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
std::string source(1024, 'a');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t1 = clock_.ApproximateNow();
// Write something into [kBlockSizeBytes, kBlockSizeBytes + 1024).
size_t written;
- buffer_->OnStreamData(kBlockSizeBytes, source, t1, &written);
+ buffer_->OnStreamData(kBlockSizeBytes, source, t1, &written, &error_details_);
EXPECT_FALSE(buffer_->HasBytesToRead());
source = std::string(100, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t2 = clock_.ApproximateNow();
// Write something into [0, 100).
- buffer_->OnStreamData(0, source, t2, &written);
+ buffer_->OnStreamData(0, source, t2, &written, &error_details_);
EXPECT_TRUE(buffer_->HasBytesToRead());
EXPECT_EQ(2u, helper_->frame_arrival_time_map()->size());
// Read into a iovec array with total capacity of 120 bytes.
@@ -387,11 +399,12 @@ TEST_F(StreamSequencerBufferTest, Readv100Bytes) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, ReadvAcrossBlocks) {
+TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
std::string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full and extand 50 bytes to next block.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
EXPECT_EQ(source.size(), helper_->ReadableBytes());
// Iteratively read 512 bytes from buffer_-> Overwrite dest[] each time.
char dest[512];
@@ -408,11 +421,12 @@ TEST_F(StreamSequencerBufferTest, ReadvAcrossBlocks) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, ClearAfterRead) {
+TEST_F(QuicStreamSequencerBufferTest, ClearAfterRead) {
std::string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full with 'a'.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Read first 512 bytes from buffer to make space at the beginning.
char dest[512]{0};
const iovec iov{dest, 512};
@@ -423,11 +437,13 @@ TEST_F(StreamSequencerBufferTest, ClearAfterRead) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, OnStreamDataAcrossLastBlockAndFillCapacity) {
+TEST_F(QuicStreamSequencerBufferTest,
+ OnStreamDataAcrossLastBlockAndFillCapacity) {
std::string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full with 'a'.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Read first 512 bytes from buffer to make space at the beginning.
char dest[512]{0};
const iovec iov{dest, 512};
@@ -437,19 +453,20 @@ TEST_F(StreamSequencerBufferTest, OnStreamDataAcrossLastBlockAndFillCapacity) {
// Write more than half block size of bytes in the last block with 'b', which
// will wrap to the beginning and reaches the full capacity.
source = std::string(0.5 * kBlockSizeBytes + 512, 'b');
- EXPECT_EQ(QUIC_NO_ERROR,
- buffer_->OnStreamData(2 * kBlockSizeBytes, source,
- clock_.ApproximateNow(), &written));
+ EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(2 * kBlockSizeBytes, source,
+ clock_.ApproximateNow(),
+ &written, &error_details_));
EXPECT_EQ(source.size(), written);
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest,
+TEST_F(QuicStreamSequencerBufferTest,
OnStreamDataAcrossLastBlockAndExceedCapacity) {
std::string source(kBlockSizeBytes + 50, 'a');
// Write 1st block to full.
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Read first 512 bytes from buffer to make space at the beginning.
char dest[512]{0};
const iovec iov{dest, 512};
@@ -460,25 +477,27 @@ TEST_F(StreamSequencerBufferTest,
source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
EXPECT_EQ(QUIC_INTERNAL_ERROR,
buffer_->OnStreamData(2 * kBlockSizeBytes, source,
- clock_.ApproximateNow(), &written));
+ clock_.ApproximateNow(), &written,
+ &error_details_));
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, ReadvAcrossLastBlock) {
+TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
// Write to full capacity and read out 512 bytes at beginning and continue
// appending 256 bytes.
std::string source(max_capacity_bytes_, 'a');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
size_t written;
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[512]{0};
const iovec iov{dest, 512};
buffer_->Readv(&iov, 1);
source = std::string(256, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t2 = clock_.ApproximateNow();
- buffer_->OnStreamData(max_capacity_bytes_, source, t2, &written);
+ buffer_->OnStreamData(max_capacity_bytes_, source, t2, &written,
+ &error_details_);
EXPECT_TRUE(helper_->CheckBufferInvariants());
EXPECT_EQ(2u, helper_->frame_arrival_time_map()->size());
@@ -492,7 +511,7 @@ TEST_F(StreamSequencerBufferTest, ReadvAcrossLastBlock) {
EXPECT_EQ(0u, helper_->frame_arrival_time_map()->size());
}
-TEST_F(StreamSequencerBufferTest, ReadvEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, ReadvEmpty) {
char dest[512]{0};
iovec iov{dest, 512};
size_t read = buffer_->Readv(&iov, 1);
@@ -500,7 +519,7 @@ TEST_F(StreamSequencerBufferTest, ReadvEmpty) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
EXPECT_EQ(0, iov_count);
@@ -508,23 +527,25 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsEmpty) {
EXPECT_EQ(0u, iovs[iov_count].iov_len);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
// Write into [1, 1024).
std::string source(1023, 'a');
size_t written;
- buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// Try to get readable regions, but none is there.
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
EXPECT_EQ(0, iov_count);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
// Write first block to full with [0, 256) 'a' and the rest 'b' then read out
// [0, 256)
std::string source(kBlockSizeBytes, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1024)
@@ -536,11 +557,12 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
iovs[0].iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
// Write into [0, 1024) and then read out [0, 256)
std::string source(1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1024)
@@ -552,11 +574,13 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
iovs[0].iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsAcrossBlockWithLongIOV) {
+TEST_F(QuicStreamSequencerBufferTest,
+ GetReadableRegionsAcrossBlockWithLongIOV) {
// Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
std::string source(2 * kBlockSizeBytes + 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
@@ -568,18 +592,20 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsAcrossBlockWithLongIOV) {
EXPECT_EQ(1024u, iovs[2].iov_len);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithMultipleIOVsAcrossEnd) {
+TEST_F(QuicStreamSequencerBufferTest,
+ GetReadableRegionsWithMultipleIOVsAcrossEnd) {
// Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
// and then append 1024 + 512 bytes.
std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
// Write across the end.
source = std::string(1024 + 512, 'b');
buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source,
- clock_.ApproximateNow(), &written);
+ clock_.ApproximateNow(), &written, &error_details_);
// Use short iovec's.
iovec iovs[2];
int iov_count = buffer_->GetReadableRegions(iovs, 2);
@@ -596,7 +622,7 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionsWithMultipleIOVsAcrossEnd) {
iovs1[3].iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionEmpty) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionEmpty) {
iovec iov;
QuicTime t = QuicTime::Zero();
EXPECT_FALSE(buffer_->GetReadableRegion(&iov, &t));
@@ -604,11 +630,12 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionEmpty) {
EXPECT_EQ(0u, iov.iov_len);
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionBeforeGap) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionBeforeGap) {
// Write into [1, 1024).
std::string source(1023, 'a');
size_t written;
- buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
+ &error_details_);
// GetReadableRegion should return false because range [0,1) hasn't been
// filled yet.
iovec iov;
@@ -616,13 +643,13 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionBeforeGap) {
EXPECT_FALSE(buffer_->GetReadableRegion(&iov, &t));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
// Write into [0, kBlockSizeBytes + 1) and then read out [0, 256)
std::string source(kBlockSizeBytes + 1, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1024)
@@ -635,13 +662,13 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionTillGap) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillGap) {
// Write into [0, kBlockSizeBytes - 1) and then read out [0, 256)
std::string source(kBlockSizeBytes - 1, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Get readable region from [256, 1023)
@@ -654,25 +681,27 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionTillGap) {
std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
}
-TEST_F(StreamSequencerBufferTest, GetReadableRegionByArrivalTime) {
+TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionByArrivalTime) {
// Write into [0, kBlockSizeBytes - 100) and then read out [0, 256)
std::string source(kBlockSizeBytes - 100, 'a');
size_t written;
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
// Write into [kBlockSizeBytes - 100, kBlockSizeBytes - 50)] in same time
std::string source2(50, 'b');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
- buffer_->OnStreamData(kBlockSizeBytes - 100, source2, t, &written);
+ buffer_->OnStreamData(kBlockSizeBytes - 100, source2, t, &written,
+ &error_details_);
// Write into [kBlockSizeBytes - 50, kBlockSizeBytes)] in another time
std::string source3(50, 'c');
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
QuicTime t3 = clock_.ApproximateNow();
- buffer_->OnStreamData(kBlockSizeBytes - 50, source3, t3, &written);
+ buffer_->OnStreamData(kBlockSizeBytes - 50, source3, t3, &written,
+ &error_details_);
// Get readable region from [256, 1024 - 50)
iovec iov;
@@ -684,11 +713,12 @@ TEST_F(StreamSequencerBufferTest, GetReadableRegionByArrivalTime) {
std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedInOneBlock) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedInOneBlock) {
// Write into [0, 1024) and then read out [0, 256)
std::string source(1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[256];
helper_->Read(dest, 256);
@@ -702,12 +732,12 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedInOneBlock) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
// Write into [0, 1024) and then read out [0, 256)
std::string source(1024, 'a');
size_t written;
QuicTime t = clock_.ApproximateNow();
- buffer_->OnStreamData(0, source, t, &written);
+ buffer_->OnStreamData(0, source, t, &written, &error_details_);
char dest[256];
helper_->Read(dest, 256);
@@ -725,11 +755,12 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossBlock) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossBlock) {
// Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
std::string source(2 * kBlockSizeBytes + 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
@@ -739,17 +770,18 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossBlock) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossEnd) {
+TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossEnd) {
// Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024)
// and then append 1024 + 512 bytes.
std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
source = std::string(1024 + 512, 'b');
buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source,
- clock_.ApproximateNow(), &written);
+ clock_.ApproximateNow(), &written, &error_details_);
EXPECT_EQ(1024u, buffer_->BytesConsumed());
// Consume to the end of 2nd block.
@@ -766,18 +798,19 @@ TEST_F(StreamSequencerBufferTest, MarkConsumedAcrossEnd) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-TEST_F(StreamSequencerBufferTest, FlushBufferedFrames) {
+TEST_F(QuicStreamSequencerBufferTest, FlushBufferedFrames) {
// Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024).
std::string source(max_capacity_bytes_ - 1024, 'a');
size_t written;
- buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written);
+ buffer_->OnStreamData(0, source, clock_.ApproximateNow(), &written,
+ &error_details_);
char dest[1024];
helper_->Read(dest, 1024);
EXPECT_EQ(1024u, buffer_->BytesConsumed());
// Write [1024, 512) to the physical beginning.
source = std::string(512, 'b');
buffer_->OnStreamData(max_capacity_bytes_, source, clock_.ApproximateNow(),
- &written);
+ &written, &error_details_);
EXPECT_EQ(512u, written);
EXPECT_EQ(max_capacity_bytes_ - 1024 + 512, buffer_->FlushBufferedFrames());
EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
@@ -789,7 +822,8 @@ TEST_F(StreamSequencerBufferTest, FlushBufferedFrames) {
EXPECT_TRUE(helper_->CheckBufferInvariants());
}
-class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
+class QuicStreamSequencerBufferRandomIOTest
+ : public QuicStreamSequencerBufferTest {
public:
typedef std::pair<QuicStreamOffset, size_t> OffsetSizePair;
@@ -842,7 +876,7 @@ class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
}
// Write the currently first chunk of data in the out-of-order stream into
- // StreamSequencerBuffer. If current chuck cannot be written into buffer
+ // QuicStreamSequencerBuffer. If current chuck cannot be written into buffer
// because it goes beyond current capacity, move it to the end of
// shuffled_buf_ and write it later.
void WriteNextChunkToBuffer() {
@@ -855,8 +889,9 @@ class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
}
base::StringPiece string_piece_w(write_buf.get(), num_to_write);
size_t written;
- auto result = buffer_->OnStreamData(offset, string_piece_w,
- clock_.ApproximateNow(), &written);
+ auto result =
+ buffer_->OnStreamData(offset, string_piece_w, clock_.ApproximateNow(),
+ &written, &error_details_);
if (result == QUIC_NO_ERROR) {
shuffled_buf_.pop_front();
total_bytes_written_ += num_to_write;
@@ -879,7 +914,7 @@ class StreamSequencerBufferRandomIOTest : public StreamSequencerBufferTest {
SimpleRandom rng_;
};
-TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
+TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
// Set kMaxReadSize larger than kBlockSizeBytes to test both small and large
// read.
const size_t kMaxReadSize = kBlockSizeBytes * 2;
@@ -939,7 +974,7 @@ TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
}
-TEST_F(StreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
+TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
// The value 4 is chosen such that the max write size is no larger than the
// maximum buffer capacity.
const size_t kMaxNumReads = 4;
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index ef3b333..b66bf1d 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -240,7 +240,7 @@ TEST_F(QuicStreamSequencerTest, BlockedThenFullFrameAndFinConsumed) {
TEST_F(QuicStreamSequencerTest, EmptyFrame) {
EXPECT_CALL(stream_,
- CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _));
+ CloseConnectionWithDetails(QUIC_EMPTY_STREAM_FRAME_NO_FIN, _));
OnFrame(0, "");
EXPECT_EQ(0u, NumBufferedBytes());
EXPECT_EQ(0u, sequencer_->NumBytesConsumed());
@@ -563,7 +563,11 @@ TEST_F(QuicStreamSequencerTest, DontAcceptOverlappingFrames) {
sequencer_->OnStreamFrame(frame1);
QuicStreamFrame frame2(kClientDataStreamId1, false, 2, StringPiece("hello"));
- EXPECT_CALL(stream_, CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _))
+ EXPECT_CALL(stream_, CloseConnectionWithDetails(
+ FLAGS_quic_consolidate_onstreamframe_errors
+ ? QUIC_OVERLAPPING_STREAM_DATA
+ : QUIC_EMPTY_STREAM_FRAME_NO_FIN,
+ _))
.Times(1);
sequencer_->OnStreamFrame(frame2);
}
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc
index d16bf72..0bf71c6 100644
--- a/net/quic/quic_utils.cc
+++ b/net/quic/quic_utils.cc
@@ -221,6 +221,7 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_MISSING_PAYLOAD);
RETURN_STRING_LITERAL(QUIC_INVALID_FEC_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_DATA);
+ RETURN_STRING_LITERAL(QUIC_OVERLAPPING_STREAM_DATA);
RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_STREAM_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_RST_STREAM_DATA);
RETURN_STRING_LITERAL(QUIC_INVALID_CONNECTION_CLOSE_DATA);
@@ -265,7 +266,7 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_PORT);
RETURN_STRING_LITERAL(QUIC_PACKET_WRITE_ERROR);
RETURN_STRING_LITERAL(QUIC_PACKET_READ_ERROR);
- RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_FRAME);
+ RETURN_STRING_LITERAL(QUIC_EMPTY_STREAM_FRAME_NO_FIN);
RETURN_STRING_LITERAL(QUIC_INVALID_HEADERS_STREAM_DATA);
RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA);
RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA);
diff --git a/net/quic/spdy_utils.cc b/net/quic/spdy_utils.cc
index 623637d..72f9ae6 100644
--- a/net/quic/spdy_utils.cc
+++ b/net/quic/spdy_utils.cc
@@ -35,7 +35,7 @@ string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) {
// static
bool SpdyUtils::ParseHeaders(const char* data,
uint32_t data_len,
- int* content_length,
+ int64_t* content_length,
SpdyHeaderBlock* headers) {
SpdyFramer framer(HTTP2);
if (!framer.ParseHeaderBlockInBuffer(data, data_len, headers) ||
diff --git a/net/quic/spdy_utils.h b/net/quic/spdy_utils.h
index cef1368..ba8fecb 100644
--- a/net/quic/spdy_utils.h
+++ b/net/quic/spdy_utils.h
@@ -30,7 +30,7 @@ class NET_EXPORT_PRIVATE SpdyUtils {
// Returns true on success, false if parsing fails, or invalid keys are found.
static bool ParseHeaders(const char* data,
uint32_t data_len,
- int* content_length,
+ int64_t* content_length,
SpdyHeaderBlock* headers);
// Parses |data| as a std::string containing serialized HTTP/2 HEADERS frame,
diff --git a/net/quic/spdy_utils_test.cc b/net/quic/spdy_utils_test.cc
index 191d184..c3ebf70 100644
--- a/net/quic/spdy_utils_test.cc
+++ b/net/quic/spdy_utils_test.cc
@@ -31,7 +31,7 @@ TEST(SpdyUtilsTest, SerializeAndParseHeaders) {
// Take the serialized header block, and parse back into SpdyHeaderBlock.
SpdyHeaderBlock output_headers;
- int content_length = -1;
+ int64_t content_length = -1;
ASSERT_TRUE(SpdyUtils::ParseHeaders(serialized_headers.data(),
serialized_headers.size(),
&content_length, &output_headers));
diff --git a/net/quic/test_tools/mock_quic_dispatcher.h b/net/quic/test_tools/mock_quic_dispatcher.h
index 3cb69e6..05c9c9b 100644
--- a/net/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/quic/test_tools/mock_quic_dispatcher.h
@@ -27,7 +27,7 @@ class MockQuicDispatcher : public QuicDispatcher {
MOCK_METHOD3(ProcessPacket,
void(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet));
+ const QuicReceivedPacket& packet));
private:
DISALLOW_COPY_AND_ASSIGN(MockQuicDispatcher);
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc
index 9600d3e..58e06c9 100644
--- a/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -33,7 +33,7 @@ void QuicTestPacketMaker::set_hostname(const std::string& host) {
host_.assign(host);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePingPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakePingPacket(
QuicPacketNumber num,
bool include_version) {
QuicPacketHeader header;
@@ -47,10 +47,10 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePingPacket(
header.fec_group = 0;
QuicPingFrame ping;
- return scoped_ptr<QuicEncryptedPacket>(MakePacket(header, QuicFrame(ping)));
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(ping)));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRstPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
@@ -58,7 +58,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRstPacket(
return MakeRstPacket(num, include_version, stream_id, error_code, 0);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRstPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
@@ -76,10 +76,10 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRstPacket(
QuicRstStreamFrame rst(stream_id, error_code, bytes_written);
DVLOG(1) << "Adding frame: " << QuicFrame(&rst);
- return scoped_ptr<QuicEncryptedPacket>(MakePacket(header, QuicFrame(&rst)));
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(&rst)));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
@@ -125,11 +125,11 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndRstPacket(
header.packet_number, *packet,
buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, QuicTime::Zero(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
-scoped_ptr<QuicEncryptedPacket>
+scoped_ptr<QuicReceivedPacket>
QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
QuicPacketNumber num,
bool include_version,
@@ -178,11 +178,11 @@ QuicTestPacketMaker::MakeAckAndConnectionClosePacket(
header.packet_number, *packet,
buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeConnectionClosePacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeConnectionClosePacket(
QuicPacketNumber num) {
QuicPacketHeader header;
header.public_header.connection_id = connection_id_;
@@ -197,10 +197,10 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeConnectionClosePacket(
QuicConnectionCloseFrame close;
close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
close.error_details = "Time to panic!";
- return scoped_ptr<QuicEncryptedPacket>(MakePacket(header, QuicFrame(&close)));
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(&close)));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeGoAwayPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeGoAwayPacket(
QuicPacketNumber num,
QuicErrorCode error_code,
std::string reason_phrase) {
@@ -218,13 +218,12 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeGoAwayPacket(
goaway.error_code = error_code;
goaway.last_good_stream_id = 0;
goaway.reason_phrase = reason_phrase;
- return scoped_ptr<QuicEncryptedPacket>(
- MakePacket(header, QuicFrame(&goaway)));
+ return scoped_ptr<QuicReceivedPacket>(MakePacket(header, QuicFrame(&goaway)));
}
// Sets both least_unacked fields in stop waiting frame and ack frame
// to be |least_unacked|.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked,
@@ -233,7 +232,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
least_unacked, send_feedback);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber ack_least_unacked,
@@ -271,12 +270,12 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckPacket(
header.packet_number, *packet,
buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
// Returns a newly created packet to send kData on stream 1.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeDataPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeDataPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -288,7 +287,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeDataPacket(
return MakePacket(header_, QuicFrame(&frame));
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
QuicPacketNumber packet_number,
bool include_version,
QuicStreamId stream_id,
@@ -317,7 +316,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeAckAndDataPacket(
return MakeMultipleFramesPacket(header_, frames);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -332,7 +331,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -377,7 +376,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeRequestHeadersPacket(
// Convenience method for calling MakeRequestHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
-scoped_ptr<QuicEncryptedPacket>
+scoped_ptr<QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
@@ -393,7 +392,7 @@ QuicTestPacketMaker::MakeRequestHeadersPacketWithOffsetTracking(
// If |offset| is provided, will use the value when creating the packet.
// Will also update the value after packet creation.
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -431,7 +430,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
}
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -445,7 +444,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeResponseHeadersPacket(
// Convenience method for calling MakeResponseHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
-scoped_ptr<QuicEncryptedPacket>
+scoped_ptr<QuicReceivedPacket>
QuicTestPacketMaker::MakeResponseHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
@@ -488,7 +487,7 @@ SpdyHeaderBlock QuicTestPacketMaker::GetResponseHeaders(
return headers;
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakePacket(
const QuicPacketHeader& header,
const QuicFrame& frame) {
QuicFrames frames;
@@ -496,7 +495,7 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakePacket(
return MakeMultipleFramesPacket(header, frames);
}
-scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeMultipleFramesPacket(
+scoped_ptr<QuicReceivedPacket> QuicTestPacketMaker::MakeMultipleFramesPacket(
const QuicPacketHeader& header,
const QuicFrames& frames) {
QuicFramer framer(SupportedVersions(version_), clock_->Now(),
@@ -508,8 +507,8 @@ scoped_ptr<QuicEncryptedPacket> QuicTestPacketMaker::MakeMultipleFramesPacket(
header.packet_number, *packet,
buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_size);
- QuicEncryptedPacket encrypted(buffer, encrypted_size, false);
- return scoped_ptr<QuicEncryptedPacket>(encrypted.Clone());
+ QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), false);
+ return scoped_ptr<QuicReceivedPacket>(encrypted.Clone());
}
void QuicTestPacketMaker::InitializeHeader(QuicPacketNumber packet_number,
diff --git a/net/quic/test_tools/quic_test_packet_maker.h b/net/quic/test_tools/quic_test_packet_maker.h
index 1b66cb8..3574ab7 100644
--- a/net/quic/test_tools/quic_test_packet_maker.h
+++ b/net/quic/test_tools/quic_test_packet_maker.h
@@ -30,22 +30,22 @@ class QuicTestPacketMaker {
~QuicTestPacketMaker();
void set_hostname(const std::string& host);
- scoped_ptr<QuicEncryptedPacket> MakePingPacket(QuicPacketNumber num,
- bool include_version);
- scoped_ptr<QuicEncryptedPacket> MakeRstPacket(
+ scoped_ptr<QuicReceivedPacket> MakePingPacket(QuicPacketNumber num,
+ bool include_version);
+ scoped_ptr<QuicReceivedPacket> MakeRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
QuicRstStreamErrorCode error_code);
- scoped_ptr<QuicEncryptedPacket> MakeRstPacket(
+ scoped_ptr<QuicReceivedPacket> MakeRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
QuicRstStreamErrorCode error_code,
size_t bytes_written);
- scoped_ptr<QuicEncryptedPacket> MakeAckAndRstPacket(
+ scoped_ptr<QuicReceivedPacket> MakeAckAndRstPacket(
QuicPacketNumber num,
bool include_version,
QuicStreamId stream_id,
@@ -54,7 +54,7 @@ class QuicTestPacketMaker {
QuicPacketNumber ack_least_unacked,
QuicPacketNumber stop_least_unacked,
bool send_feedback);
- scoped_ptr<QuicEncryptedPacket> MakeAckAndConnectionClosePacket(
+ scoped_ptr<QuicReceivedPacket> MakeAckAndConnectionClosePacket(
QuicPacketNumber num,
bool include_version,
QuicTime::Delta delta_time_largest_observed,
@@ -62,29 +62,29 @@ class QuicTestPacketMaker {
QuicPacketNumber least_unacked,
QuicErrorCode quic_error,
std::string& quic_error_details);
- scoped_ptr<QuicEncryptedPacket> MakeConnectionClosePacket(
+ scoped_ptr<QuicReceivedPacket> MakeConnectionClosePacket(
QuicPacketNumber num);
- scoped_ptr<QuicEncryptedPacket> MakeGoAwayPacket(QuicPacketNumber num,
- QuicErrorCode error_code,
- std::string reason_phrase);
- scoped_ptr<QuicEncryptedPacket> MakeAckPacket(
+ scoped_ptr<QuicReceivedPacket> MakeGoAwayPacket(QuicPacketNumber num,
+ QuicErrorCode error_code,
+ std::string reason_phrase);
+ scoped_ptr<QuicReceivedPacket> MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber least_unacked,
bool send_feedback);
- scoped_ptr<QuicEncryptedPacket> MakeAckPacket(
+ scoped_ptr<QuicReceivedPacket> MakeAckPacket(
QuicPacketNumber packet_number,
QuicPacketNumber largest_received,
QuicPacketNumber ack_least_unacked,
QuicPacketNumber stop_least_unacked,
bool send_feedback);
- scoped_ptr<QuicEncryptedPacket> MakeDataPacket(QuicPacketNumber packet_number,
- QuicStreamId stream_id,
- bool should_include_version,
- bool fin,
- QuicStreamOffset offset,
- base::StringPiece data);
- scoped_ptr<QuicEncryptedPacket> MakeAckAndDataPacket(
+ scoped_ptr<QuicReceivedPacket> MakeDataPacket(QuicPacketNumber packet_number,
+ QuicStreamId stream_id,
+ bool should_include_version,
+ bool fin,
+ QuicStreamOffset offset,
+ base::StringPiece data);
+ scoped_ptr<QuicReceivedPacket> MakeAckAndDataPacket(
QuicPacketNumber packet_number,
bool include_version,
QuicStreamId stream_id,
@@ -96,7 +96,7 @@ class QuicTestPacketMaker {
// If |spdy_headers_frame_length| is non-null, it will be set to the size of
// the SPDY headers frame created for this packet.
- scoped_ptr<QuicEncryptedPacket> MakeRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -105,7 +105,7 @@ class QuicTestPacketMaker {
const SpdyHeaderBlock& headers,
size_t* spdy_headers_frame_length);
- scoped_ptr<QuicEncryptedPacket> MakeRequestHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeRequestHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -117,7 +117,7 @@ class QuicTestPacketMaker {
// Convenience method for calling MakeRequestHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
- scoped_ptr<QuicEncryptedPacket> MakeRequestHeadersPacketWithOffsetTracking(
+ scoped_ptr<QuicReceivedPacket> MakeRequestHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -128,7 +128,7 @@ class QuicTestPacketMaker {
// If |spdy_headers_frame_length| is non-null, it will be set to the size of
// the SPDY headers frame created for this packet.
- scoped_ptr<QuicEncryptedPacket> MakeResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -137,7 +137,7 @@ class QuicTestPacketMaker {
size_t* spdy_headers_frame_length,
QuicStreamOffset* offset);
- scoped_ptr<QuicEncryptedPacket> MakeResponseHeadersPacket(
+ scoped_ptr<QuicReceivedPacket> MakeResponseHeadersPacket(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -147,7 +147,7 @@ class QuicTestPacketMaker {
// Convenience method for calling MakeResponseHeadersPacket with nullptr for
// |spdy_headers_frame_length|.
- scoped_ptr<QuicEncryptedPacket> MakeResponseHeadersPacketWithOffsetTracking(
+ scoped_ptr<QuicReceivedPacket> MakeResponseHeadersPacketWithOffsetTracking(
QuicPacketNumber packet_number,
QuicStreamId stream_id,
bool should_include_version,
@@ -164,9 +164,9 @@ class QuicTestPacketMaker {
const std::string& alt_svc);
private:
- scoped_ptr<QuicEncryptedPacket> MakePacket(const QuicPacketHeader& header,
- const QuicFrame& frame);
- scoped_ptr<QuicEncryptedPacket> MakeMultipleFramesPacket(
+ scoped_ptr<QuicReceivedPacket> MakePacket(const QuicPacketHeader& header,
+ const QuicFrame& frame);
+ scoped_ptr<QuicReceivedPacket> MakeMultipleFramesPacket(
const QuicPacketHeader& header,
const QuicFrames& frames);
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index bc9fbc4..3d9267a 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -545,6 +545,15 @@ QuicEncryptedPacket* ConstructEncryptedPacket(
return new QuicEncryptedPacket(buffer, encrypted_length, true);
}
+QuicReceivedPacket* ConstructReceivedPacket(
+ const QuicEncryptedPacket& encrypted_packet,
+ QuicTime receipt_time) {
+ char* buffer = new char[encrypted_packet.length()];
+ memcpy(buffer, encrypted_packet.data(), encrypted_packet.length());
+ return new QuicReceivedPacket(buffer, encrypted_packet.length(), receipt_time,
+ true);
+}
+
QuicEncryptedPacket* ConstructMisFramedEncryptedPacket(
QuicConnectionId connection_id,
bool version_flag,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 1f99831..ea2875d 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -109,6 +109,12 @@ QuicEncryptedPacket* ConstructEncryptedPacket(QuicConnectionId connection_id,
QuicPacketNumber packet_number,
const std::string& data);
+// Constructs a received packet for testing. The caller must take ownership of
+// the returned pointer.
+QuicReceivedPacket* ConstructReceivedPacket(
+ const QuicEncryptedPacket& encrypted_packet,
+ QuicTime receipt_time);
+
// Create an encrypted packet for testing whose data portion erroneous.
// The specific way the data portion is erroneous is not specified, but
// it is an error that QuicFramer detects.
@@ -377,7 +383,7 @@ class MockConnection : public QuicConnection {
MOCK_METHOD3(ProcessUdpPacket,
void(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet));
+ const QuicReceivedPacket& packet));
MOCK_METHOD1(SendConnectionClose, void(QuicErrorCode error));
MOCK_METHOD2(SendConnectionCloseWithDetails,
void(QuicErrorCode error, const std::string& details));
@@ -407,7 +413,7 @@ class MockConnection : public QuicConnection {
void ReallyProcessUdpPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
}
@@ -454,6 +460,8 @@ class MockQuicSpdySession : public QuicSpdySession {
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicSpdyStream*(SpdyPriority priority));
+ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
+ MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
MOCK_METHOD5(WritevData,
QuicConsumedData(QuicStreamId id,
QuicIOVector data,
@@ -547,6 +555,8 @@ class TestQuicSpdyClientSession : public QuicClientSessionBase {
MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
MOCK_METHOD1(CreateOutgoingDynamicStream,
QuicSpdyStream*(SpdyPriority priority));
+ MOCK_METHOD1(ShouldCreateIncomingDynamicStream, bool(QuicStreamId id));
+ MOCK_METHOD0(ShouldCreateOutgoingDynamicStream, bool());
QuicCryptoClientStream* GetCryptoStream() override;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 923808b..38bb4c4 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -1003,7 +1003,7 @@ TEST_P(EndToEndTest, DoNotSetResumeWriteAlarmIfConnectionFlowControlBlocked) {
// Make sure that the stream has data pending so that it will be marked as
// write blocked when it receives a stream level WINDOW_UPDATE.
- stream->SendBody("hello", false);
+ stream->WriteOrBufferBody("hello", false, nullptr);
// The stream now attempts to write, fails because it is still connection
// level flow control blocked, and is added to the write blocked list.
@@ -1505,7 +1505,7 @@ TEST_P(EndToEndTest, DifferentFlowControlWindows) {
// Open a data stream to make sure the stream level flow control is updated.
QuicSpdyClientStream* stream = client_->GetOrCreateStream();
- stream->SendBody("hello", false);
+ stream->WriteOrBufferBody("hello", false, nullptr);
// Client should have the right values for server's receive window.
EXPECT_EQ(kServerStreamIFCW,
@@ -1972,6 +1972,55 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory {
string response_body_;
};
+// A test server stream that drops all received body.
+class ServerStreamThatDropsBody : public QuicSimpleServerStream {
+ public:
+ ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session)
+ : QuicSimpleServerStream(id, session) {}
+
+ ~ServerStreamThatDropsBody() override {}
+
+ protected:
+ void OnDataAvailable() override {
+ while (HasBytesToRead()) {
+ struct iovec iov;
+ if (GetReadableRegions(&iov, 1) == 0) {
+ // No more data to read.
+ break;
+ }
+ DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream " << id();
+ MarkConsumed(iov.iov_len);
+ }
+
+ if (!sequencer()->IsClosed()) {
+ sequencer()->SetUnblocked();
+ return;
+ }
+
+ // If the sequencer is closed, then all the body, including the fin, has
+ // been consumed.
+ OnFinRead();
+
+ if (write_side_closed() || fin_buffered()) {
+ return;
+ }
+
+ SendResponse();
+ }
+};
+
+class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory {
+ public:
+ ServerStreamThatDropsBodyFactory() {}
+
+ ~ServerStreamThatDropsBodyFactory() override{};
+
+ QuicSimpleServerStream* CreateStream(QuicStreamId id,
+ QuicSpdySession* session) override {
+ return new ServerStreamThatDropsBody(id, session);
+ }
+};
+
TEST_P(EndToEndTest, EarlyResponseFinRecording) {
set_smaller_flow_control_receive_window();
@@ -2369,6 +2418,39 @@ TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
EXPECT_EQ(12u, client_->num_responses());
}
+// TODO(fayang): this test seems to cause net_unittests timeouts :|
+TEST_P(EndToEndTest, DISABLED_TestHugePost) {
+ // This test tests a huge post with body size greater than 4GB, making sure
+ // QUIC code does not broke for 32-bit builds.
+ ServerStreamThatDropsBodyFactory stream_factory;
+ SetSpdyStreamFactory(&stream_factory);
+ ASSERT_TRUE(Initialize());
+ // Set client's epoll server's time out to 0 to make this test be finished
+ // within a short time.
+ client_->epoll_server()->set_timeout_in_us(0);
+
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // To avoid storing the whole request body in memory, use a loop to repeatedly
+ // send body size of kSizeBytes until the whole request body size is reached.
+ const int kSizeBytes = 128 * 1024;
+ HTTPMessage request(HttpConstants::HTTP_1_1, HttpConstants::POST, "/foo");
+ // Request body size is 4G plus one more kSizeBytes.
+ int64_t request_body_size_bytes = pow(2, 32) + kSizeBytes;
+ request.AddHeader("content-length", IntToString(request_body_size_bytes));
+ request.set_has_complete_message(false);
+ string body;
+ test::GenerateBody(&body, kSizeBytes);
+
+ client_->SendMessage(request);
+ for (int i = 0; i < request_body_size_bytes / kSizeBytes; ++i) {
+ bool fin = (i == request_body_size_bytes - 1);
+ client_->SendData(string(body.data(), kSizeBytes), fin);
+ client_->client()->WaitForEvents();
+ }
+ VerifyCleanConnection(false);
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index b0815d3..07617bb 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -391,7 +391,8 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) {
bool more_to_read = true;
while (connected() && more_to_read) {
more_to_read = packet_reader_->ReadAndDispatchPackets(
- GetLatestFD(), QuicClient::GetLatestClientAddress().port(), this,
+ GetLatestFD(), QuicClient::GetLatestClientAddress().port(),
+ *helper()->GetClock(), this,
overflow_supported_ ? &packets_dropped_ : nullptr);
}
}
@@ -408,22 +409,22 @@ void QuicClient::OnClose(QuicSpdyStream* stream) {
DCHECK(stream != nullptr);
QuicSpdyClientStream* client_stream =
static_cast<QuicSpdyClientStream*>(stream);
- BalsaHeaders headers;
- SpdyBalsaUtils::SpdyHeadersToResponseHeaders(client_stream->headers(),
- &headers);
+ BalsaHeaders response_headers;
+ SpdyBalsaUtils::SpdyHeadersToResponseHeaders(
+ client_stream->response_headers(), &response_headers);
if (response_listener_.get() != nullptr) {
- response_listener_->OnCompleteResponse(stream->id(), headers,
+ response_listener_->OnCompleteResponse(stream->id(), response_headers,
client_stream->data());
}
// Store response headers and body.
if (store_response_) {
- latest_response_code_ = headers.parsed_response_code();
- headers.DumpHeadersToString(&latest_response_headers_);
+ latest_response_code_ = response_headers.parsed_response_code();
+ response_headers.DumpHeadersToString(&latest_response_headers_);
latest_response_body_ = client_stream->data();
latest_response_trailers_ =
- client_stream->response_trailers().DebugString();
+ client_stream->received_trailers().DebugString();
}
}
@@ -486,7 +487,7 @@ int QuicClient::GetLatestFD() const {
void QuicClient::ProcessPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
session()->connection()->ProcessUdpPacket(self_address, peer_address, packet);
}
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index ef6b711..1df8514 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -187,7 +187,7 @@ class QuicClient : public QuicClientBase,
// packet.
void ProcessPacket(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
- const QuicEncryptedPacket& packet) override;
+ const QuicReceivedPacket& packet) override;
QuicClientPushPromiseIndex* push_promise_index() {
return &push_promise_index_;
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h
index 2cbf236..651469d 100644
--- a/net/tools/quic/quic_client_session.h
+++ b/net/tools/quic/quic_client_session.h
@@ -60,6 +60,11 @@ class QuicClientSession : public QuicClientSessionBase {
protected:
// QuicSession methods:
QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override;
+ // If an outgoing stream can be created, return true.
+ bool ShouldCreateOutgoingDynamicStream() override;
+
+ // If an incoming stream can be created, return true.
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
// Create the crypto stream. Called by Initialize()
virtual QuicCryptoClientStreamBase* CreateQuicCryptoStream();
@@ -74,12 +79,6 @@ class QuicClientSession : public QuicClientSessionBase {
QuicCryptoClientConfig* crypto_config() { return crypto_config_; }
private:
- // If an outgoing stream can be created, return true.
- bool ShouldCreateOutgoingDynamicStream();
-
- // If an incoming stream can be created, return true.
- bool ShouldCreateIncomingDynamicStream(QuicStreamId id);
-
scoped_ptr<QuicCryptoClientStreamBase> crypto_stream_;
QuicServerId server_id_;
QuicCryptoClientConfig* crypto_config_;
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index f2aa9c0..2837ef4 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -248,14 +248,14 @@ TEST_P(QuicClientSessionTest, InvalidPacketReceived) {
EXPECT_CALL(*connection_, OnError(_)).Times(1);
// Verify that empty packets don't close the connection.
- QuicEncryptedPacket zero_length_packet(nullptr, 0, false);
+ QuicReceivedPacket zero_length_packet(nullptr, 0, QuicTime::Zero(), false);
EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
session_->ProcessUdpPacket(client_address, server_address,
zero_length_packet);
// Verifiy that small, invalid packets don't close the connection.
char buf[2] = {0x00, 0x01};
- QuicEncryptedPacket valid_packet(buf, 2, false);
+ QuicReceivedPacket valid_packet(buf, 2, QuicTime::Zero(), false);
// Close connection shouldn't be called.
EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
session_->ProcessUdpPacket(client_address, server_address, valid_packet);
@@ -264,11 +264,13 @@ TEST_P(QuicClientSessionTest, InvalidPacketReceived) {
QuicConnectionId connection_id = session_->connection()->connection_id();
scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
connection_id, false, false, false, kDefaultPathId, 100, "data"));
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*packet, QuicTime::Zero()));
// Change the last byte of the encrypted data.
- *(const_cast<char*>(packet->data() + packet->length() - 1)) += 1;
+ *(const_cast<char*>(received->data() + received->length() - 1)) += 1;
EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0);
EXPECT_CALL(*connection_, OnError(Truly(CheckForDecryptionError))).Times(1);
- session_->ProcessUdpPacket(client_address, server_address, *packet);
+ session_->ProcessUdpPacket(client_address, server_address, *received);
}
// A packet with invalid framing should cause a connection to be closed.
@@ -286,8 +288,10 @@ TEST_P(QuicClientSessionTest, InvalidFramedPacketReceived) {
scoped_ptr<QuicEncryptedPacket> packet(ConstructMisFramedEncryptedPacket(
connection_id, false, false, false, kDefaultPathId, 100, "data",
PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER, nullptr));
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*packet, QuicTime::Zero()));
EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(1);
- session_->ProcessUdpPacket(client_address, server_address, *packet);
+ session_->ProcessUdpPacket(client_address, server_address, *received);
}
TEST_P(QuicClientSessionTest, PushPromiseOnPromiseHeaders) {
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index f662ee3..1b145ef 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -74,7 +74,7 @@ void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) {
void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet) {
+ const QuicReceivedPacket& packet) {
current_server_address_ = server_address;
current_client_address_ = client_address;
current_packet_ = &packet;
diff --git a/net/tools/quic/quic_dispatcher.h b/net/tools/quic/quic_dispatcher.h
index 6ba8f2b..5ff52ce 100644
--- a/net/tools/quic/quic_dispatcher.h
+++ b/net/tools/quic/quic_dispatcher.h
@@ -63,7 +63,7 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// an existing session, or passing it to the time wait list.
void ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet) override;
+ const QuicReceivedPacket& packet) override;
// Called when the socket becomes writable to allow queued writes to happen.
void OnCanWrite() override;
@@ -182,7 +182,7 @@ class QuicDispatcher : public QuicServerSessionVisitor,
const IPEndPoint& current_server_address() { return current_server_address_; }
const IPEndPoint& current_client_address() { return current_client_address_; }
- const QuicEncryptedPacket& current_packet() { return *current_packet_; }
+ const QuicReceivedPacket& current_packet() { return *current_packet_; }
const QuicConfig& config() const { return config_; }
@@ -257,7 +257,7 @@ class QuicDispatcher : public QuicServerSessionVisitor,
// Information about the packet currently being handled.
IPEndPoint current_client_address_;
IPEndPoint current_server_address_;
- const QuicEncryptedPacket* current_packet_;
+ const QuicReceivedPacket* current_packet_;
QuicConnectionId current_connection_id_;
QuicFramer framer_;
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index 67fb2d6..1172d1f 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -229,9 +229,12 @@ class QuicDispatcherTest : public ::testing::Test {
scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
connection_id, has_version_flag, false, false, 0, packet_number, data,
connection_id_length, packet_number_length, &versions));
+ scoped_ptr<QuicReceivedPacket> received_packet(
+ ConstructReceivedPacket(*packet, helper_.GetClock()->Now()));
data_ = string(packet->data(), packet->length());
- dispatcher_.ProcessPacket(server_address_, client_address, *packet);
+ dispatcher_.ProcessPacket(server_address_, client_address,
+ *received_packet);
}
void ValidatePacket(const QuicEncryptedPacket& packet) {
@@ -353,6 +356,8 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
packet.nonce_proof = 132232;
scoped_ptr<QuicEncryptedPacket> encrypted(
QuicFramer::BuildPublicResetPacket(packet));
+ scoped_ptr<QuicReceivedPacket> received(
+ ConstructReceivedPacket(*encrypted, helper_.GetClock()->Now()));
EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET,
ConnectionCloseSource::FROM_PEER))
.Times(1)
@@ -364,7 +369,7 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
.WillOnce(
Invoke(reinterpret_cast<MockConnection*>(session1_->connection()),
&MockConnection::ReallyProcessUdpPacket));
- dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
+ dispatcher_.ProcessPacket(IPEndPoint(), client_address, *received);
EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
// Dispatcher forwards subsequent packets for this connection_id to the time
diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc
index 3f5f8c8..beba973 100644
--- a/net/tools/quic/quic_packet_reader.cc
+++ b/net/tools/quic/quic_packet_reader.cc
@@ -53,7 +53,7 @@ void QuicPacketReader::Initialize() {
hdr->msg_iovlen = 1;
hdr->msg_control = packets_[i].cbuf;
- hdr->msg_controllen = kSpaceForOverflowAndIp;
+ hdr->msg_controllen = QuicSocketUtils::kSpaceForCmsg;
}
#endif
}
@@ -63,18 +63,22 @@ QuicPacketReader::~QuicPacketReader() {}
bool QuicPacketReader::ReadAndDispatchPackets(
int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped) {
#if MMSG_MORE
- return ReadAndDispatchManyPackets(fd, port, processor, packets_dropped);
+ return ReadAndDispatchManyPackets(fd, port, clock, processor,
+ packets_dropped);
#else
- return ReadAndDispatchSinglePacket(fd, port, processor, packets_dropped);
+ return ReadAndDispatchSinglePacket(fd, port, clock, processor,
+ packets_dropped);
#endif
}
bool QuicPacketReader::ReadAndDispatchManyPackets(
int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped) {
#if MMSG_MORE
@@ -84,7 +88,7 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
hdr->msg_namelen = sizeof(sockaddr_storage);
DCHECK_EQ(1, hdr->msg_iovlen);
- hdr->msg_controllen = kSpaceForOverflowAndIp;
+ hdr->msg_controllen = QuicSocketUtils::kSpaceForCmsg;
}
int packets_read =
@@ -94,22 +98,42 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
return false; // recvmmsg failed.
}
+ QuicTime fallback_timestamp = QuicTime::Zero();
for (int i = 0; i < packets_read; ++i) {
if (mmsg_hdr_[i].msg_len == 0) {
continue;
}
+ if (mmsg_hdr_[i].msg_hdr.msg_controllen >= QuicSocketUtils::kSpaceForCmsg) {
+ QUIC_BUG << "Incorrectly set control length: "
+ << mmsg_hdr_[i].msg_hdr.msg_controllen << ", expected "
+ << QuicSocketUtils::kSpaceForCmsg;
+ continue;
+ }
+
IPEndPoint client_address = IPEndPoint(packets_[i].raw_address);
- IPAddressNumber server_ip =
- QuicSocketUtils::GetAddressFromMsghdr(&mmsg_hdr_[i].msg_hdr);
+ IPAddressNumber server_ip;
+ QuicTime packet_timestamp = QuicTime::Zero();
+ QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
+ &mmsg_hdr_[i].msg_hdr, &server_ip, &packet_timestamp);
if (!IsInitializedAddress(server_ip)) {
QUIC_BUG << "Unable to get server address.";
continue;
}
- QuicEncryptedPacket packet(
- reinterpret_cast<char*>(packets_[i].iov.iov_base), mmsg_hdr_[i].msg_len,
- false);
+ if (FLAGS_quic_use_socket_timestamp) {
+ if (packet_timestamp == QuicTime::Zero()) {
+ // This isn't particularly desirable, but not all platforms support
+ // socket timestamping.
+ if (fallback_timestamp == QuicTime::Zero()) {
+ fallback_timestamp = clock.Now();
+ }
+ packet_timestamp = fallback_timestamp;
+ }
+ }
+
+ QuicReceivedPacket packet(reinterpret_cast<char*>(packets_[i].iov.iov_base),
+ mmsg_hdr_[i].msg_len, packet_timestamp, false);
IPEndPoint server_address(server_ip, port);
processor->ProcessPacket(server_address, client_address, packet);
}
@@ -131,20 +155,33 @@ bool QuicPacketReader::ReadAndDispatchManyPackets(
bool QuicPacketReader::ReadAndDispatchSinglePacket(
int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped) {
char buf[kMaxPacketSize];
IPEndPoint client_address;
IPAddress server_ip;
- int bytes_read = QuicSocketUtils::ReadPacket(
- fd, buf, arraysize(buf), packets_dropped, &server_ip, &client_address);
+ QuicTime timestamp = QuicTime::Zero();
+ int bytes_read =
+ QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), packets_dropped,
+ &server_ip, &timestamp, &client_address);
if (bytes_read < 0) {
return false; // ReadPacket failed.
}
- QuicEncryptedPacket packet(buf, bytes_read, false);
+ if (server_ip.empty()) {
+ QUIC_BUG << "Unable to get server address.";
+ return false;
+ }
+ if (FLAGS_quic_use_socket_timestamp && timestamp == QuicTime::Zero()) {
+ // This isn't particularly desirable, but not all platforms support socket
+ // timestamping.
+ timestamp = clock.Now();
+ }
+
+ QuicReceivedPacket packet(buf, bytes_read, timestamp, false);
IPEndPoint server_address(server_ip, port);
processor->ProcessPacket(server_address, client_address, packet);
diff --git a/net/tools/quic/quic_packet_reader.h b/net/tools/quic/quic_packet_reader.h
index 6ffe26b..b388406 100644
--- a/net/tools/quic/quic_packet_reader.h
+++ b/net/tools/quic/quic_packet_reader.h
@@ -11,8 +11,10 @@
#include <sys/socket.h>
#include "base/macros.h"
+#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
#include "net/tools/quic/quic_process_packet_interface.h"
+#include "net/tools/quic/quic_socket_utils.h"
#define MMSG_MORE 0
@@ -21,9 +23,6 @@ namespace net {
#if MMSG_MORE
// Read in larger batches to minimize recvmmsg overhead.
const int kNumPacketsPerReadMmsgCall = 16;
-// Allocate space for in6_pktinfo as it's larger than in_pktinfo
-const int kSpaceForOverflowAndIp =
- CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo));
#endif
namespace test {
@@ -43,8 +42,11 @@ class QuicPacketReader {
// packets available on the socket.
// Populates |packets_dropped| if it is non-null and the socket is configured
// to track dropped packets and some packets are read.
+ // If the socket has timestamping enabled, the per packet timestamps will be
+ // passed to the processor. Otherwise, |clock| will be used.
virtual bool ReadAndDispatchPackets(int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped);
@@ -55,12 +57,14 @@ class QuicPacketReader {
// Reads and dispatches many packets using recvmmsg.
bool ReadAndDispatchManyPackets(int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped);
// Reads and dispatches a single packet using recvmsg.
static bool ReadAndDispatchSinglePacket(int fd,
int port,
+ const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* packets_dropped);
@@ -78,7 +82,7 @@ class QuicPacketReader {
// call on the packets.
struct sockaddr_storage raw_address;
// cbuf is used for ancillary data from the kernel on recvmmsg.
- char cbuf[kSpaceForOverflowAndIp];
+ char cbuf[QuicSocketUtils::kSpaceForCmsg];
// buf is used for the data read from the kernel on recvmmsg.
char buf[kMaxPacketSize];
};
diff --git a/net/tools/quic/quic_process_packet_interface.h b/net/tools/quic/quic_process_packet_interface.h
index cc5924a..aa1035d 100644
--- a/net/tools/quic/quic_process_packet_interface.h
+++ b/net/tools/quic/quic_process_packet_interface.h
@@ -17,7 +17,7 @@ class ProcessPacketInterface {
virtual ~ProcessPacketInterface() {}
virtual void ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
- const QuicEncryptedPacket& packet) = 0;
+ const QuicReceivedPacket& packet) = 0;
};
} // namespace net
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index 1c878f1..832c1b6 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -168,7 +168,7 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) {
bool more_to_read = true;
while (more_to_read) {
more_to_read = packet_reader_->ReadAndDispatchPackets(
- fd_, port_, dispatcher_.get(),
+ fd_, port_, QuicEpollClock(&epoll_server_), dispatcher_.get(),
overflow_supported_ ? &packets_dropped_ : nullptr);
}
}
diff --git a/net/tools/quic/quic_server_session_base.h b/net/tools/quic/quic_server_session_base.h
index a93fd9c..d14f02b 100644
--- a/net/tools/quic/quic_server_session_base.h
+++ b/net/tools/quic/quic_server_session_base.h
@@ -95,12 +95,12 @@ class QuicServerSessionBase : public QuicSpdySession {
// Return false when connection is closed or forward secure encryption hasn't
// established yet or number of server initiated streams already reaches the
// upper limit.
- virtual bool ShouldCreateOutgoingDynamicStream();
+ bool ShouldCreateOutgoingDynamicStream() override;
// If we should create an incoming stream, returns true. Otherwise
// does error handling, including communicating the error to the client and
// possibly closing the connection, and returns false.
- virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id);
+ bool ShouldCreateIncomingDynamicStream(QuicStreamId id) override;
virtual QuicCryptoServerStreamBase* CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc
index 1e55e23..d59bc70 100644
--- a/net/tools/quic/quic_server_test.cc
+++ b/net/tools/quic/quic_server_test.cc
@@ -32,7 +32,7 @@ class QuicServerDispatchPacketTest : public ::testing::Test {
dispatcher_.InitializeWithWriter(new QuicDefaultPacketWriter(1234));
}
- void DispatchPacket(const QuicEncryptedPacket& packet) {
+ void DispatchPacket(const QuicReceivedPacket& packet) {
IPEndPoint client_addr, server_addr;
dispatcher_.ProcessPacket(server_addr, client_addr, packet);
}
@@ -59,8 +59,9 @@ TEST_F(QuicServerDispatchPacketTest, DispatchPacket) {
0x00
};
// clang-format on
- QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
- arraysize(valid_packet), false);
+ QuicReceivedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
+ arraysize(valid_packet),
+ QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
DispatchPacket(encrypted_valid_packet);
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index b1dcf19..928481a 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -339,7 +339,8 @@ void QuicSimpleClient::OnClose(QuicSpdyStream* stream) {
QuicSpdyClientStream* client_stream =
static_cast<QuicSpdyClientStream*>(stream);
HttpResponseInfo response;
- SpdyHeadersToHttpResponse(client_stream->headers(), net::HTTP2, &response);
+ SpdyHeadersToHttpResponse(client_stream->response_headers(), net::HTTP2,
+ &response);
if (response_listener_.get() != nullptr) {
response_listener_->OnCompleteResponse(stream->id(), *response.headers,
client_stream->data());
@@ -388,7 +389,7 @@ void QuicSimpleClient::OnReadError(int result,
Disconnect();
}
-bool QuicSimpleClient::OnPacket(const QuicEncryptedPacket& packet,
+bool QuicSimpleClient::OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) {
session()->connection()->ProcessUdpPacket(local_address, peer_address,
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h
index 0ac0087..bcd0bda 100644
--- a/net/tools/quic/quic_simple_client.h
+++ b/net/tools/quic/quic_simple_client.h
@@ -130,7 +130,7 @@ class QuicSimpleClient : public QuicClientBase,
// QuicChromiumPacketReader::Visitor
void OnReadError(int result, const DatagramClientSocket* socket) override;
- bool OnPacket(const QuicEncryptedPacket& packet,
+ bool OnPacket(const QuicReceivedPacket& packet,
IPEndPoint local_address,
IPEndPoint peer_address) override;
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc
index 9e89a50..7713986 100644
--- a/net/tools/quic/quic_simple_server.cc
+++ b/net/tools/quic/quic_simple_server.cc
@@ -202,7 +202,8 @@ void QuicSimpleServer::OnReadComplete(int result) {
return;
}
- QuicEncryptedPacket packet(read_buffer_->data(), result, false);
+ QuicReceivedPacket packet(read_buffer_->data(), result,
+ helper_->GetClock()->Now(), false);
dispatcher_->ProcessPacket(server_address_, client_address_, packet);
StartReading();
diff --git a/net/tools/quic/quic_simple_server_stream.cc b/net/tools/quic/quic_simple_server_stream.cc
index b715574..e0a3c2f 100644
--- a/net/tools/quic/quic_simple_server_stream.cc
+++ b/net/tools/quic/quic_simple_server_stream.cc
@@ -58,7 +58,7 @@ void QuicSimpleServerStream::OnDataAvailable() {
body_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
if (content_length_ >= 0 &&
- static_cast<int>(body_.size()) > content_length_) {
+ body_.size() > static_cast<uint64_t>(content_length_)) {
DVLOG(1) << "Body size (" << body_.size() << ") > content length ("
<< content_length_ << ").";
SendErrorResponse();
@@ -86,7 +86,7 @@ void QuicSimpleServerStream::OnDataAvailable() {
}
if (content_length_ > 0 &&
- content_length_ != static_cast<int>(body_.size())) {
+ static_cast<uint64_t>(content_length_) != body_.size()) {
DVLOG(1) << "Content length (" << content_length_ << ") != body size ("
<< body_.size() << ").";
SendErrorResponse();
diff --git a/net/tools/quic/quic_simple_server_stream.h b/net/tools/quic/quic_simple_server_stream.h
index 90cb0dc..b88b847 100644
--- a/net/tools/quic/quic_simple_server_stream.h
+++ b/net/tools/quic/quic_simple_server_stream.h
@@ -73,7 +73,7 @@ class QuicSimpleServerStream : public QuicSpdyStream {
// The parsed headers received from the client.
SpdyHeaderBlock request_headers_;
- int content_length_;
+ int64_t content_length_;
std::string body_;
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerStream);
diff --git a/net/tools/quic/quic_simple_server_test.cc b/net/tools/quic/quic_simple_server_test.cc
index c63501c..3a7c54e 100644
--- a/net/tools/quic/quic_simple_server_test.cc
+++ b/net/tools/quic/quic_simple_server_test.cc
@@ -30,7 +30,7 @@ class QuicChromeServerDispatchPacketTest : public ::testing::Test {
dispatcher_.InitializeWithWriter(nullptr);
}
- void DispatchPacket(const QuicEncryptedPacket& packet) {
+ void DispatchPacket(const QuicReceivedPacket& packet) {
IPEndPoint client_addr, server_addr;
dispatcher_.ProcessPacket(server_addr, client_addr, packet);
}
@@ -51,8 +51,9 @@ TEST_F(QuicChromeServerDispatchPacketTest, DispatchPacket) {
0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12,
// private flags
0x00};
- QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
- arraysize(valid_packet), false);
+ QuicReceivedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
+ arraysize(valid_packet),
+ QuicTime::Zero(), false);
EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _)).Times(1);
DispatchPacket(encrypted_valid_packet);
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc
index 9c8cac7..1ef874c 100644
--- a/net/tools/quic/quic_socket_utils.cc
+++ b/net/tools/quic/quic_socket_utils.cc
@@ -5,6 +5,7 @@
#include "net/tools/quic/quic_socket_utils.h"
#include <errno.h>
+#include <linux/net_tstamp.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
@@ -12,6 +13,8 @@
#include <string>
#include "base/logging.h"
+#include "net/quic/quic_bug_tracker.h"
+#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
#ifndef SO_RXQ_OVFL
@@ -21,28 +24,36 @@
namespace net {
// static
-IPAddress QuicSocketUtils::GetAddressFromMsghdr(struct msghdr* hdr) {
+void QuicSocketUtils::GetAddressAndTimestampFromMsghdr(struct msghdr* hdr,
+ IPAddress* address,
+ QuicTime* timestamp) {
if (hdr->msg_controllen > 0) {
for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr;
cmsg = CMSG_NXTHDR(hdr, cmsg)) {
const uint8_t* addr_data = nullptr;
int len = 0;
if (cmsg->cmsg_type == IPV6_PKTINFO) {
- in6_pktinfo* info = reinterpret_cast<in6_pktinfo*> CMSG_DATA(cmsg);
+ in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg));
addr_data = reinterpret_cast<const uint8_t*>(&info->ipi6_addr);
len = sizeof(in6_addr);
+ *address = IPAddress(addr_data, len);
} else if (cmsg->cmsg_type == IP_PKTINFO) {
- in_pktinfo* info = reinterpret_cast<in_pktinfo*> CMSG_DATA(cmsg);
+ in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg));
addr_data = reinterpret_cast<const uint8_t*>(&info->ipi_addr);
len = sizeof(in_addr);
- } else {
- continue;
+ *address = IPAddress(addr_data, len);
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SO_TIMESTAMPING) {
+ LinuxTimestamping* lts =
+ reinterpret_cast<LinuxTimestamping*>(CMSG_DATA(cmsg));
+ timespec* ts = &lts->systime;
+ int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) +
+ (static_cast<int64_t>(ts->tv_nsec) / 1000);
+ *timestamp =
+ QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(usec));
}
- return IPAddress(addr_data, len);
}
}
- DCHECK(false) << "Unable to get address from msghdr";
- return IPAddress();
}
// static
@@ -74,6 +85,13 @@ int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) {
}
// static
+int QuicSocketUtils::SetGetSoftwareReceiveTimestamp(int fd) {
+ int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
+ return setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &timestamping,
+ sizeof(timestamping));
+}
+
+// static
bool QuicSocketUtils::SetSendBufferSize(int fd, size_t size) {
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) != 0) {
LOG(ERROR) << "Failed to set socket send size";
@@ -97,11 +115,10 @@ int QuicSocketUtils::ReadPacket(int fd,
size_t buf_len,
QuicPacketCount* dropped_packets,
IPAddress* self_address,
+ QuicTime* timestamp,
IPEndPoint* peer_address) {
DCHECK(peer_address != nullptr);
- const int kSpaceForOverflowAndIp =
- CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo));
- char cbuf[kSpaceForOverflowAndIp];
+ char cbuf[kSpaceForCmsg];
memset(cbuf, 0, arraysize(cbuf));
iovec iov = {buffer, buf_len};
@@ -130,13 +147,28 @@ int QuicSocketUtils::ReadPacket(int fd,
return -1;
}
+ if (hdr.msg_controllen >= arraysize(cbuf)) {
+ QUIC_BUG << "Incorrectly set control length: " << hdr.msg_controllen
+ << ", expected " << arraysize(cbuf);
+ return -1;
+ }
+
if (dropped_packets != nullptr) {
GetOverflowFromMsghdr(&hdr, dropped_packets);
}
- if (self_address != nullptr) {
- *self_address = QuicSocketUtils::GetAddressFromMsghdr(&hdr);
+
+ IPAddress stack_address;
+ if (self_address == nullptr) {
+ self_address = &stack_address;
+ }
+
+ QuicTime stack_timestamp = QuicTime::Zero();
+ if (timestamp == nullptr) {
+ timestamp = &stack_timestamp;
}
+ GetAddressAndTimestampFromMsghdr(&hdr, self_address, timestamp);
+
if (raw_address.ss_family == AF_INET) {
CHECK(peer_address->FromSockAddr(
reinterpret_cast<const sockaddr*>(&raw_address),
@@ -245,19 +277,28 @@ int QuicSocketUtils::CreateUDPSocket(const IPEndPoint& address,
*overflow_supported = true;
}
- if (!QuicSocketUtils::SetReceiveBufferSize(fd, kDefaultSocketReceiveBuffer)) {
+ if (!SetReceiveBufferSize(fd, kDefaultSocketReceiveBuffer)) {
return -1;
}
- if (!QuicSocketUtils::SetSendBufferSize(fd, kDefaultSocketReceiveBuffer)) {
+ if (!SetSendBufferSize(fd, kDefaultSocketReceiveBuffer)) {
return -1;
}
- rc = QuicSocketUtils::SetGetAddressInfo(fd, address_family);
+ rc = SetGetAddressInfo(fd, address_family);
if (rc < 0) {
LOG(ERROR) << "IP detection not supported" << strerror(errno);
return -1;
}
+
+ if (FLAGS_quic_use_socket_timestamp) {
+ rc = SetGetSoftwareReceiveTimestamp(fd);
+ if (rc < 0) {
+ LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: "
+ << strerror(errno);
+ }
+ }
+
return fd;
}
diff --git a/net/tools/quic/quic_socket_utils.h b/net/tools/quic/quic_socket_utils.h
index a464089..72e90f8 100644
--- a/net/tools/quic/quic_socket_utils.h
+++ b/net/tools/quic/quic_socket_utils.h
@@ -7,6 +7,7 @@
#ifndef NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
#define NET_TOOLS_QUIC_QUIC_SOCKET_UTILS_H_
+#include <netinet/in.h>
#include <stddef.h>
#include <sys/socket.h>
@@ -20,11 +21,37 @@
namespace net {
+// This is the structure that SO_TIMESTAMPING fills into the cmsg header. It is
+// well-defined, but does not have a definition in a public header. See
+// https://www.kernel.org/doc/Documentation/networking/timestamping.txt for more
+// information.
+struct LinuxTimestamping {
+ // The converted system time of the timestamp.
+ struct timespec systime;
+ // Deprecated; serves only as padding.
+ struct timespec hwtimetrans;
+ // The raw hardware timestamp.
+ struct timespec hwtimeraw;
+};
+
class QuicSocketUtils {
public:
- // If the msghdr contains IP_PKTINFO or IPV6_PKTINFO, this will return the
- // IPAddress in that header. Returns an empty IPAddress on failure.
- static IPAddress GetAddressFromMsghdr(struct msghdr* hdr);
+ // The first integer is for overflow. The in6_pktinfo is the larger of the
+ // address structures present. LinuxTimestamping is present for socket
+ // timestamping.
+ // The final int is a sentinel so the msg_controllen feedback
+ // can be used to detect larger control messages than there is space for.
+ static const int kSpaceForCmsg =
+ CMSG_SPACE(CMSG_LEN(sizeof(int)) + CMSG_LEN(sizeof(in6_pktinfo)) +
+ CMSG_LEN(sizeof(LinuxTimestamping)) +
+ CMSG_LEN(sizeof(int)));
+
+ // Fills in |address| if |hdr| contains IP_PKTINFO or IPV6_PKTINFO. Fills in
+ // |timestamp| if |hdr| contains |SO_TIMESTAMPING|. |address| and |timestamp|
+ // must not be null.
+ static void GetAddressAndTimestampFromMsghdr(struct msghdr* hdr,
+ IPAddress* address,
+ QuicTime* timestamp);
// If the msghdr contains an SO_RXQ_OVFL entry, this will set dropped_packets
// to the correct value and return true. Otherwise it will return false.
@@ -35,6 +62,10 @@ class QuicSocketUtils {
// address_family. Returns the return code from setsockopt.
static int SetGetAddressInfo(int fd, int address_family);
+ // Sets SO_TIMESTAMPING on the socket for software receive timestamping.
+ // Returns the return code from setsockopt.
+ static int SetGetSoftwareReceiveTimestamp(int fd);
+
// Sets the send buffer size to |size| and returns false if it fails.
static bool SetSendBufferSize(int fd, size_t size);
@@ -50,11 +81,17 @@ class QuicSocketUtils {
//
// If self_address is non-null, it will be set to the address the peer sent
// packets to, assuming a packet was read.
+ //
+ // If timestamp is non-null, it will be filled with the timestamp of the
+ // received packet, assuming a packet was read and the platform supports
+ // packet receipt timestamping. If the platform does not support packet
+ // receipt timestamping, timestamp will not be changed.
static int ReadPacket(int fd,
char* buffer,
size_t buf_len,
QuicPacketCount* dropped_packets,
IPAddress* self_address,
+ QuicTime* timestamp,
IPEndPoint* peer_address);
// Writes buf_len to the socket. If writing is successful, sets the result's
diff --git a/net/tools/quic/quic_spdy_client_stream.cc b/net/tools/quic/quic_spdy_client_stream.cc
index af9ad0b..0274ee7 100644
--- a/net/tools/quic/quic_spdy_client_stream.cc
+++ b/net/tools/quic/quic_spdy_client_stream.cc
@@ -79,7 +79,7 @@ void QuicSpdyClientStream::OnTrailingHeadersComplete(bool fin,
void QuicSpdyClientStream::OnPromiseHeadersComplete(QuicStreamId promised_id,
size_t frame_len) {
header_bytes_read_ += frame_len;
- int content_length = -1;
+ int64_t content_length = -1;
SpdyHeaderBlock promise_headers;
if (!SpdyUtils::ParseHeaders(decompressed_headers().data(),
decompressed_headers().length(), &content_length,
@@ -111,7 +111,7 @@ void QuicSpdyClientStream::OnDataAvailable() {
data_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
if (content_length_ >= 0 &&
- static_cast<int>(data_.size()) > content_length_) {
+ data_.size() > static_cast<uint64_t>(content_length_)) {
Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return;
}
@@ -139,14 +139,4 @@ size_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers,
return bytes_sent;
}
-void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
- SendBody(data, fin, nullptr);
-}
-
-void QuicSpdyClientStream::SendBody(const string& data,
- bool fin,
- QuicAckListenerInterface* listener) {
- WriteOrBufferData(data, fin, listener);
-}
-
} // namespace net
diff --git a/net/tools/quic/quic_spdy_client_stream.h b/net/tools/quic/quic_spdy_client_stream.h
index dcb8896..f225717 100644
--- a/net/tools/quic/quic_spdy_client_stream.h
+++ b/net/tools/quic/quic_spdy_client_stream.h
@@ -51,18 +51,11 @@ class QuicSpdyClientStream : public QuicSpdyStream {
base::StringPiece body,
bool fin);
- // Sends body data to the server, or buffers if it can't be sent immediately.
- void SendBody(const std::string& data, bool fin);
- // As above, but |delegate| will be notified once |data| is ACKed.
- void SendBody(const std::string& data,
- bool fin,
- QuicAckListenerInterface* listener);
-
// Returns the response data.
const std::string& data() { return data_; }
// Returns whatever headers have been received for this stream.
- const SpdyHeaderBlock& headers() { return response_headers_; }
+ const SpdyHeaderBlock& response_headers() { return response_headers_; }
size_t header_bytes_read() const { return header_bytes_read_; }
@@ -87,7 +80,7 @@ class QuicSpdyClientStream : public QuicSpdyStream {
SpdyHeaderBlock response_headers_;
// The parsed content-length, or -1 if none is specified.
- int content_length_;
+ int64_t content_length_;
int response_code_;
std::string data_;
size_t header_bytes_read_;
diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc
index 8b42df5..85452bf 100644
--- a/net/tools/quic/quic_spdy_client_stream_test.cc
+++ b/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -100,7 +100,7 @@ TEST_F(QuicSpdyClientStreamTest, TestFraming) {
stream_->OnStreamHeadersComplete(false, headers_string_.size());
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
- EXPECT_EQ("200", stream_->headers().find(":status")->second);
+ EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_EQ(body_, stream_->data());
}
@@ -110,7 +110,7 @@ TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) {
stream_->OnStreamHeadersComplete(false, headers_string_.size());
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_));
- EXPECT_EQ("200", stream_->headers().find(":status")->second);
+ EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_EQ(body_, stream_->data());
}
@@ -122,7 +122,7 @@ TEST_F(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) {
stream_->OnStreamHeadersComplete(false, headers_string_.size());
// The headers should parse successfully.
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
- EXPECT_EQ("200", stream_->headers().find(":status")->second);
+ EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
EXPECT_CALL(*connection_,
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 12cb7fb..0ddfb4f 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -278,8 +278,7 @@ TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) {
const int kRandomSequenceNumber = 1;
EXPECT_CALL(writer_,
WritePacket(_, _, server_address_.address(), client_address_, _))
- .With(Args<0, 1>(
- PublicResetPacketEq(connection_id_, kRandomSequenceNumber)))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id_, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
ProcessPacket(connection_id_, kRandomSequenceNumber);
@@ -380,14 +379,14 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
// Let first write through.
EXPECT_CALL(writer_,
WritePacket(_, _, server_address_.address(), client_address_, _))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id, packet_number)))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
ProcessPacket(connection_id, packet_number);
// write block for the next packet.
EXPECT_CALL(writer_,
WritePacket(_, _, server_address_.address(), client_address_, _))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id, packet_number)))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(DoAll(Assign(&writer_is_blocked_, true),
Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN))));
EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
@@ -412,12 +411,11 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
writer_is_blocked_ = false;
EXPECT_CALL(writer_,
WritePacket(_, _, server_address_.address(), client_address_, _))
- .With(Args<0, 1>(PublicResetPacketEq(connection_id, packet_number)))
+ .With(Args<0, 1>(PublicResetPacketEq(connection_id, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
EXPECT_CALL(writer_,
WritePacket(_, _, server_address_.address(), client_address_, _))
- .With(Args<0, 1>(
- PublicResetPacketEq(other_connection_id, other_packet_number)))
+ .With(Args<0, 1>(PublicResetPacketEq(other_connection_id, 0)))
.WillOnce(Return(WriteResult(WRITE_STATUS_OK, other_packet->length())));
time_wait_list_manager_.OnCanWrite();
}
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 7ce3621..97625d8 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -278,7 +278,7 @@ ssize_t QuicTestClient::GetOrCreateStreamAndSendRequest(
ret = stream->SendRequest(spdy_headers, body, fin);
++num_requests_;
} else {
- stream->SendBody(body.as_string(), fin, delegate);
+ stream->WriteOrBufferBody(body.as_string(), fin, delegate);
ret = body.length();
}
if (FLAGS_enable_quic_stateless_reject_support) {
@@ -463,7 +463,7 @@ void QuicTestClient::ClearPerRequestState() {
response_ = "";
response_complete_ = false;
response_headers_complete_ = false;
- headers_.Clear();
+ response_headers_.Clear();
bytes_read_ = 0;
bytes_written_ = 0;
response_header_size_ = 0;
@@ -531,10 +531,11 @@ bool QuicTestClient::response_headers_complete() const {
const BalsaHeaders* QuicTestClient::response_headers() const {
if (stream_ != nullptr) {
- SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_);
- return &headers_;
+ SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->response_headers(),
+ &response_headers_);
+ return &response_headers_;
} else {
- return &headers_;
+ return &response_headers_;
}
}
@@ -569,13 +570,14 @@ void QuicTestClient::OnClose(QuicSpdyStream* stream) {
}
response_complete_ = true;
response_headers_complete_ = stream_->headers_decompressed();
- SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->headers(), &headers_);
- response_trailers_ = stream_->response_trailers();
+ SpdyBalsaUtils::SpdyHeadersToResponseHeaders(stream_->response_headers(),
+ &response_headers_);
+ response_trailers_ = stream_->received_trailers();
stream_error_ = stream_->stream_error();
bytes_read_ = stream_->stream_bytes_read() + stream_->header_bytes_read();
bytes_written_ =
stream_->stream_bytes_written() + stream_->header_bytes_written();
- response_header_size_ = headers_.GetSizeForWriteBuffer();
+ response_header_size_ = response_headers_.GetSizeForWriteBuffer();
response_body_size_ = stream_->data().size();
stream_ = nullptr;
++num_responses_;
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 93cc385..b8530f4 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -240,7 +240,7 @@ class QuicTestClient : public test::SimpleClient,
bool response_complete_;
bool response_headers_complete_;
- mutable BalsaHeaders headers_;
+ mutable BalsaHeaders response_headers_;
// Parsed response trailers (if present), copied from the stream in OnClose.
SpdyHeaderBlock response_trailers_;