Don't crash the qbone client when getting a read/write failure but the socket isn't blocked. PiperOrigin-RevId: 378237431
diff --git a/quic/qbone/qbone_packet_exchanger.cc b/quic/qbone/qbone_packet_exchanger.cc index 5ee52e1..b87fde6 100644 --- a/quic/qbone/qbone_packet_exchanger.cc +++ b/quic/qbone/qbone_packet_exchanger.cc
@@ -14,7 +14,7 @@ std::string error; std::unique_ptr<QuicData> packet = ReadPacket(&blocked, &error); if (packet == nullptr) { - if (!blocked) { + if (!blocked && visitor_) { visitor_->OnReadError(error); } return false; @@ -31,11 +31,11 @@ if (WritePacket(packet, size, &blocked, &error)) { return; } - if (!blocked) { + if (blocked) { + write_blocked_ = true; + } else if (visitor_) { visitor_->OnWriteError(error); - return; } - write_blocked_ = true; } // Drop the packet on the floor if the queue if full. @@ -58,7 +58,7 @@ packet_queue_.front()->length(), &blocked, &error)) { packet_queue_.pop_front(); } else { - if (!blocked) { + if (!blocked && visitor_) { visitor_->OnWriteError(error); } write_blocked_ = blocked;
diff --git a/quic/qbone/qbone_packet_exchanger_test.cc b/quic/qbone/qbone_packet_exchanger_test.cc index a2b502f..5db8753 100644 --- a/quic/qbone/qbone_packet_exchanger_test.cc +++ b/quic/qbone/qbone_packet_exchanger_test.cc
@@ -251,5 +251,21 @@ ASSERT_TRUE(exchanger.packets_written().empty()); } +TEST(QbonePacketExchangerTest, NullVisitorDoesntCrash) { + FakeQbonePacketExchanger exchanger(nullptr, kMaxPendingPackets); + MockQboneClient client; + std::string packet = "data"; + + // Force read error. + std::string io_error = "I/O error"; + exchanger.SetReadError(io_error); + EXPECT_FALSE(exchanger.ReadAndDeliverPacket(&client)); + + // Force write error + exchanger.ForceWriteFailure(false, io_error); + exchanger.WritePacketToNetwork(packet.data(), packet.length()); + EXPECT_TRUE(exchanger.packets_written().empty()); +} + } // namespace } // namespace quic