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