diff --git a/net/quic/quic_chromium_packet_reader.cc b/net/quic/quic_chromium_packet_reader.cc index 1a6de07bb902..23f6e1c6da88 100644 --- a/net/quic/quic_chromium_packet_reader.cc +++ b/net/quic/quic_chromium_packet_reader.cc @@ -21,6 +21,8 @@ const size_t kReadBufferSize = static_cast(quic::kMaxIncomingPacketSize + 1); } // namespace +bool QuicChromiumPacketReader::avoid_read_multi_ = false; + QuicChromiumPacketReader::QuicChromiumPacketReader( DatagramClientSocket* socket, const quic::QuicClock* clock, @@ -49,10 +51,22 @@ void QuicChromiumPacketReader::StartReading() { CHECK(socket_); read_pending_ = true; - int rv = - socket_->Read(read_buffer_.get(), read_buffer_->size(), - base::BindOnce(&QuicChromiumPacketReader::OnReadComplete, - weak_factory_.GetWeakPtr())); + int rv = OK; + if (!avoid_read_multi_) { + rv = socket_->ReadMulti( + read_buffer_.get(), read_buffer_->size(), + base::BindOnce(&QuicChromiumPacketReader::OnReadComplete, + weak_factory_.GetWeakPtr())); + if (rv == ERR_NOT_IMPLEMENTED) + avoid_read_multi_ = true; + } + if (avoid_read_multi_) { + rv = socket_->Read( + read_buffer_.get(), read_buffer_->size(), + base::BindOnce(&QuicChromiumPacketReader::OnReadComplete, + weak_factory_.GetWeakPtr())); + } + UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING); if (rv == ERR_IO_PENDING) { num_packets_read_ = 0; diff --git a/net/quic/quic_chromium_packet_reader.h b/net/quic/quic_chromium_packet_reader.h index 2caf8c8aea68..eb4370157d50 100644 --- a/net/quic/quic_chromium_packet_reader.h +++ b/net/quic/quic_chromium_packet_reader.h @@ -75,6 +75,10 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketReader { NetLogWithSource net_log_; base::WeakPtrFactory weak_factory_{this}; + + // Static flag to remember when ReadMulti has ever returned + // ERR_NOT_IMPLEMENTED + static bool avoid_read_multi_; }; } // namespace net diff --git a/net/socket/socket.cc b/net/socket/socket.cc index 143516c572ed..16079a71f2de 100644 --- a/net/socket/socket.cc +++ b/net/socket/socket.cc @@ -14,6 +14,12 @@ Socket::Socket() = default; Socket::~Socket() = default; +int Socket::ReadMulti(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + return ERR_NOT_IMPLEMENTED; +} + int Socket::ReadIfReady(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { diff --git a/net/socket/socket.h b/net/socket/socket.h index 64e08182d664..570645a8ba9a 100644 --- a/net/socket/socket.h +++ b/net/socket/socket.h @@ -38,6 +38,9 @@ class NET_EXPORT Socket { virtual int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) = 0; + virtual int ReadMulti(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback); // Reads data, up to |buf_len| bytes, into |buf| without blocking. Default // implementation returns ERR_READ_IF_READY_NOT_IMPLEMENTED. Caller should diff --git a/net/socket/udp_client_socket.cc b/net/socket/udp_client_socket.cc index 8645f1fc5126..a05afc053e00 100644 --- a/net/socket/udp_client_socket.cc +++ b/net/socket/udp_client_socket.cc @@ -110,6 +110,12 @@ void UDPClientSocket::ApplySocketTag(const SocketTag& tag) { socket_.ApplySocketTag(tag); } +int UDPClientSocket::ReadMulti(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + return socket_.ReadMulti(buf, buf_len, std::move(callback)); +} + int UDPClientSocket::Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { diff --git a/net/socket/udp_client_socket.h b/net/socket/udp_client_socket.h index fc695b7cd2a2..6bf0463b9384 100644 --- a/net/socket/udp_client_socket.h +++ b/net/socket/udp_client_socket.h @@ -53,6 +53,10 @@ class NET_EXPORT_PRIVATE UDPClientSocket : public DatagramClientSocket { int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) override; + int ReadMulti(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback, diff --git a/net/socket/udp_socket_starboard.cc b/net/socket/udp_socket_starboard.cc index c13eb2c8a737..f4c9958c5ef2 100644 --- a/net/socket/udp_socket_starboard.cc +++ b/net/socket/udp_socket_starboard.cc @@ -159,6 +159,13 @@ int UDPSocketStarboard::GetLocalAddress(IPEndPoint* address) const { return OK; } +int UDPSocketStarboard::ReadMulti(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + LOG(WARNING) << __FUNCTION__ << " ReadMulti not implemented"; + return ERR_NOT_IMPLEMENTED; +} + int UDPSocketStarboard::Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback) { diff --git a/net/socket/udp_socket_starboard.h b/net/socket/udp_socket_starboard.h index 905964eccc67..1588d15b9ba1 100644 --- a/net/socket/udp_socket_starboard.h +++ b/net/socket/udp_socket_starboard.h @@ -147,6 +147,7 @@ class NET_EXPORT UDPSocketStarboard // Reads from the socket. // Only usable from the client-side of a UDP socket, after the socket // has been connected. + int ReadMulti(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); // Writes to the socket.