gfe-relnote: (n/a) Change the return value of QuicUdpSocketApi::ReadMultiplePackets from number of good packets to number of total packets read. Code not used yet. PiperOrigin-RevId: 290802895 Change-Id: I44a83c052ac1fc20b67d8f5708575b2d40cb1cb0
diff --git a/quic/core/quic_udp_socket.h b/quic/core/quic_udp_socket.h index 86972d1..b60386f 100644 --- a/quic/core/quic_udp_socket.h +++ b/quic/core/quic_udp_socket.h
@@ -199,6 +199,8 @@ using ReadPacketResults = std::vector<ReadPacketResult>; // Read up to |results->size()| packets from |fd|. The meaning of each element // in |*results| has been documented on top of |ReadPacket|. + // Return the number of elements populated into |*results|, note it is + // possible for some of the populated elements to have ok=false. size_t ReadMultiplePackets(QuicUdpSocketFd fd, BitMask64 packet_info_interested, ReadPacketResults* results);
diff --git a/quic/core/quic_udp_socket_posix.cc b/quic/core/quic_udp_socket_posix.cc index f62dbe8..6a5f2d9 100644 --- a/quic/core/quic_udp_socket_posix.cc +++ b/quic/core/quic_udp_socket_posix.cc
@@ -471,7 +471,6 @@ return 0; } - size_t num_good_packets = 0; for (int i = 0; i < packets_read; ++i) { if (hdrs[i].msg_len == 0) { continue; @@ -493,7 +492,6 @@ continue; } - ++num_good_packets; (*results)[i].ok = true; (*results)[i].packet_buffer.buffer_len = hdrs[i].msg_len; @@ -511,15 +509,16 @@ } } } - return num_good_packets; + return packets_read; #else size_t num_packets = 0; for (ReadPacketResult& result : *results) { result.ok = false; } for (ReadPacketResult& result : *results) { + errno = 0; ReadPacket(fd, packet_info_interested, &result); - if (!result.ok) { + if (!result.ok && errno == EAGAIN) { break; } ++num_packets;
diff --git a/quic/core/quic_udp_socket_test.cc b/quic/core/quic_udp_socket_test.cc index 697e5e9..eaa9f4c 100644 --- a/quic/core/quic_udp_socket_test.cc +++ b/quic/core/quic_udp_socket_test.cc
@@ -9,6 +9,13 @@ namespace quic { namespace test { +namespace { +// Used by ReadMultiplePackets tests. +struct ReadBuffers { + char control_buffer[512]; + char packet_buffer[1536]; +}; +} // namespace class QuicUdpSocketTest : public QuicTest { protected: @@ -95,6 +102,17 @@ return memcmp(client_packet_buffer_, server_packet_buffer_, packet_size); } + bool VerifyBufferIsFilledWith(const char* buffer, + size_t buffer_length, + char c) { + for (size_t i = 0; i < buffer_length; ++i) { + if (buffer[i] != c) { + return false; + } + } + return true; + } + QuicUdpSocketApi api_; QuicUdpSocketFd fd_client_; QuicUdpSocketFd fd_server_; @@ -250,5 +268,122 @@ EXPECT_EQ(13, read_result.packet_info.ttl()); } +TEST_F(QuicUdpSocketTest, ReadMultiplePackets) { + const QuicUdpPacketInfoBit self_ip_bit = + (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP + : QuicUdpPacketInfoBit::V6_SELF_IP; + const size_t kPacketSize = kDefaultMaxPacketSize; + const size_t kNumPackets = 90; + for (size_t i = 0; i < kNumPackets; ++i) { + memset(client_packet_buffer_, ' ' + i, kPacketSize); + ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize), + SendPacketFromClient(kPacketSize)); + } + + const size_t kNumPacketsPerRead = 16; + size_t total_packets_read = 0; + while (total_packets_read < kNumPackets) { + std::unique_ptr<ReadBuffers[]> read_buffers = + std::make_unique<ReadBuffers[]>(kNumPacketsPerRead); + QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead); + for (size_t i = 0; i < kNumPacketsPerRead; ++i) { + results[i].packet_buffer.buffer = read_buffers[i].packet_buffer; + results[i].packet_buffer.buffer_len = + sizeof(read_buffers[i].packet_buffer); + + results[i].control_buffer.buffer = read_buffers[i].control_buffer; + results[i].control_buffer.buffer_len = + sizeof(read_buffers[i].control_buffer); + } + size_t packets_read = + api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results); + if (packets_read == 0) { + ASSERT_TRUE( + api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5))); + packets_read = api_.ReadMultiplePackets(fd_server_, + BitMask64(self_ip_bit), &results); + ASSERT_GT(packets_read, 0u); + } + + for (size_t i = 0; i < packets_read; ++i) { + const auto& result = results[i]; + ASSERT_TRUE(result.ok); + ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len); + ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer, + result.packet_buffer.buffer_len, + ' ' + total_packets_read)); + ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit)); + EXPECT_EQ(Loopback(), (address_family_ == AF_INET) + ? result.packet_info.self_v4_ip() + : result.packet_info.self_v6_ip()); + total_packets_read++; + } + } +} + +TEST_F(QuicUdpSocketTest, ReadMultiplePacketsSomeTruncated) { + const QuicUdpPacketInfoBit self_ip_bit = + (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP + : QuicUdpPacketInfoBit::V6_SELF_IP; + const size_t kPacketSize = kDefaultMaxPacketSize; + const size_t kNumPackets = 90; + for (size_t i = 0; i < kNumPackets; ++i) { + memset(client_packet_buffer_, ' ' + i, kPacketSize); + ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize), + SendPacketFromClient(kPacketSize)); + } + + const size_t kNumPacketsPerRead = 16; + size_t total_packets_read = 0; // Including truncated packets. + while (total_packets_read < kNumPackets) { + std::unique_ptr<ReadBuffers[]> read_buffers = + std::make_unique<ReadBuffers[]>(kNumPacketsPerRead); + QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead); + // Use small packet buffer for all even-numbered packets and expect them to + // be truncated. + auto is_truncated = [total_packets_read](size_t i) { + return ((total_packets_read + i) % 2) == 1; + }; + + for (size_t i = 0; i < kNumPacketsPerRead; ++i) { + results[i].packet_buffer.buffer = read_buffers[i].packet_buffer; + results[i].packet_buffer.buffer_len = + is_truncated(i) ? kPacketSize - 1 + : sizeof(read_buffers[i].packet_buffer); + + results[i].control_buffer.buffer = read_buffers[i].control_buffer; + results[i].control_buffer.buffer_len = + sizeof(read_buffers[i].control_buffer); + } + size_t packets_read = + api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results); + if (packets_read == 0) { + ASSERT_TRUE( + api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5))); + packets_read = api_.ReadMultiplePackets(fd_server_, + BitMask64(self_ip_bit), &results); + ASSERT_GT(packets_read, 0u); + } + + for (size_t i = 0; i < packets_read; ++i) { + const auto& result = results[i]; + if (is_truncated(i)) { + ASSERT_FALSE(result.ok); + } else { + ASSERT_TRUE(result.ok); + ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len); + ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer, + result.packet_buffer.buffer_len, + ' ' + total_packets_read)); + ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit)); + EXPECT_EQ(Loopback(), (address_family_ == AF_INET) + ? result.packet_info.self_v4_ip() + : result.packet_info.self_v6_ip()); + } + total_packets_read++; + } + } +} + } // namespace test } // namespace quic