diff options
author | jokulik <jokulik@chromium.org> | 2016-03-24 15:35:30 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-24 22:37:10 +0000 |
commit | f2bd55c5ab99300b7df0a97b3d0ef16c9a2e584a (patch) | |
tree | a075e02a5d98fce698e53b975674271b17673b3b /net/tools/quic | |
parent | ef26d8f77ba056704780199893f1ebaf518136de (diff) | |
download | chromium_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/tools/quic')
28 files changed, 318 insertions, 121 deletions
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, ×tamp, &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 = <s->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, ×tamping, + 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_; |