Migrate IcmpReachable to use QuicEventLoop API.

This changes internal time precision of IcmpReachable from ns to us, but otherwise should be a no-op.

PiperOrigin-RevId: 469545543
diff --git a/quiche/quic/bindings/quic_libevent.h b/quiche/quic/bindings/quic_libevent.h
index d8aa493..b06ab4e 100644
--- a/quiche/quic/bindings/quic_libevent.h
+++ b/quiche/quic/bindings/quic_libevent.h
@@ -36,6 +36,7 @@
   bool ArtificiallyNotifyEvent(QuicUdpSocketFd fd,
                                QuicSocketEventMask events) override;
   void RunEventLoopOnce(QuicTime::Delta default_timeout) override;
+  const QuicClock* GetClock() override { return clock_; }
 
   // Can be called from another thread to wake up the event loop from a blocking
   // RunEventLoopOnce() call.
diff --git a/quiche/quic/core/io/quic_event_loop.h b/quiche/quic/core/io/quic_event_loop.h
index 1b09562..e02a0f0 100644
--- a/quiche/quic/core/io/quic_event_loop.h
+++ b/quiche/quic/core/io/quic_event_loop.h
@@ -75,6 +75,10 @@
   // Returns an alarm factory that allows alarms to be scheduled on this event
   // loop.
   virtual std::unique_ptr<QuicAlarmFactory> CreateAlarmFactory() = 0;
+
+  // Returns the clock that is used by the alarm factory that the event loop
+  // provides.
+  virtual const QuicClock* GetClock() = 0;
 };
 
 // A factory object for the event loop. Every implementation is expected to have
diff --git a/quiche/quic/core/io/quic_poll_event_loop.h b/quiche/quic/core/io/quic_poll_event_loop.h
index 4e19ff9..6b2ec49 100644
--- a/quiche/quic/core/io/quic_poll_event_loop.h
+++ b/quiche/quic/core/io/quic_poll_event_loop.h
@@ -51,6 +51,7 @@
       QuicUdpSocketFd fd, QuicSocketEventMask events) override;
   void RunEventLoopOnce(QuicTime::Delta default_timeout) override;
   std::unique_ptr<QuicAlarmFactory> CreateAlarmFactory() override;
+  const QuicClock* GetClock() override { return clock_; }
 
  protected:
   // Allows poll(2) calls to be mocked out in unit tests.
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable.cc b/quiche/quic/qbone/bonnet/icmp_reachable.cc
index fac964b..8f85190 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable.cc
+++ b/quiche/quic/qbone/bonnet/icmp_reachable.cc
@@ -8,16 +8,18 @@
 
 #include "absl/strings/string_view.h"
 #include "quiche/quic/core/crypto/quic_random.h"
+#include "quiche/quic/core/io/quic_event_loop.h"
 #include "quiche/quic/platform/api/quic_logging.h"
 #include "quiche/quic/platform/api/quic_mutex.h"
 #include "quiche/quic/qbone/platform/icmp_packet.h"
-#include "quiche/common/quiche_endian.h"
+#include "quiche/common/platform/api/quiche_logging.h"
 #include "quiche/common/quiche_text_utils.h"
 
 namespace quic {
 namespace {
 
-constexpr int kEpollFlags = EPOLLIN | EPOLLET;
+constexpr QuicSocketEventMask kEventMask =
+    kSocketEventReadable | kSocketEventWritable;
 constexpr size_t kMtu = 1280;
 
 constexpr size_t kIPv6AddrSize = sizeof(in6_addr);
@@ -28,13 +30,15 @@
 const char kNoSource[] = "N/A";
 
 IcmpReachable::IcmpReachable(QuicIpAddress source, QuicIpAddress destination,
-                             absl::Duration timeout, KernelInterface* kernel,
-                             QuicEpollServer* epoll_server,
-                             StatsInterface* stats)
+                             QuicTime::Delta timeout, KernelInterface* kernel,
+                             QuicEventLoop* event_loop, StatsInterface* stats)
     : timeout_(timeout),
+      event_loop_(event_loop),
+      clock_(event_loop->GetClock()),
+      alarm_factory_(event_loop->CreateAlarmFactory()),
       cb_(this),
+      alarm_(alarm_factory_->CreateAlarm(new AlarmCallback(this))),
       kernel_(kernel),
-      epoll_server_(epoll_server),
       stats_(stats),
       send_fd_(0),
       recv_fd_(0) {
@@ -50,9 +54,8 @@
     kernel_->close(send_fd_);
   }
   if (recv_fd_ > 0) {
-    if (!epoll_server_->ShutdownCalled()) {
-      epoll_server_->UnregisterFD(recv_fd_);
-    }
+    bool success = event_loop_->UnregisterSocket(recv_fd_);
+    QUICHE_DCHECK(success);
 
     kernel_->close(recv_fd_);
   }
@@ -93,8 +96,11 @@
     return false;
   }
 
-  epoll_server_->RegisterFD(recv_fd_, &cb_, kEpollFlags);
-  epoll_server_->RegisterAlarm(0, this);
+  if (!event_loop_->RegisterSocket(recv_fd_, kEventMask, &cb_)) {
+    QUIC_LOG(ERROR) << "Unable to register recv ICMP socket";
+    return false;
+  }
+  alarm_->Set(clock_->Now());
 
   QuicWriterMutexLock mu(&header_lock_);
   icmp_header_.icmp6_type = ICMP6_ECHO_REQUEST;
@@ -135,9 +141,8 @@
                  << " seq: " << icmp_header_.icmp6_seq;
     return true;
   }
-  end_ = absl::Now();
-  QUIC_VLOG(1) << "Received ping response in "
-               << absl::ToInt64Microseconds(end_ - start_) << "us.";
+  end_ = clock_->Now();
+  QUIC_VLOG(1) << "Received ping response in " << (end_ - start_);
 
   std::string source;
   QuicIpAddress source_ip;
@@ -152,14 +157,12 @@
   return true;
 }
 
-int64 /* allow-non-std-int */ IcmpReachable::OnAlarm() {
-  EpollAlarm::OnAlarm();
-
+void IcmpReachable::OnAlarm() {
   QuicWriterMutexLock mu(&header_lock_);
 
   if (end_ < start_) {
     QUIC_VLOG(1) << "Timed out on sequence: " << icmp_header_.icmp6_seq;
-    stats_->OnEvent({Status::UNREACHABLE, absl::ZeroDuration(), kNoSource});
+    stats_->OnEvent({Status::UNREACHABLE, QuicTime::Delta::Zero(), kNoSource});
   }
 
   icmp_header_.icmp6_seq++;
@@ -175,10 +178,10 @@
                      if (size < packet.size()) {
                        stats_->OnWriteError(errno);
                      }
-                     start_ = absl::Now();
+                     start_ = clock_->Now();
                    });
 
-  return absl::ToUnixMicros(absl::Now() + timeout_);
+  alarm_->Set(clock_->ApproximateNow() + timeout_);
 }
 
 absl::string_view IcmpReachable::StatusName(IcmpReachable::Status status) {
@@ -192,19 +195,15 @@
   }
 }
 
-void IcmpReachable::EpollCallback::OnEvent(int fd, QuicEpollEvent* event) {
+void IcmpReachable::EpollCallback::OnSocketEvent(QuicEventLoop* event_loop,
+                                                 QuicUdpSocketFd fd,
+                                                 QuicSocketEventMask events) {
   bool can_read_more = reachable_->OnEvent(fd);
   if (can_read_more) {
-    event->out_ready_mask |= EPOLLIN;
+    bool success =
+        event_loop->ArtificiallyNotifyEvent(fd, kSocketEventReadable);
+    QUICHE_DCHECK(success);
   }
 }
 
-void IcmpReachable::EpollCallback::OnShutdown(QuicEpollServer* eps, int fd) {
-  eps->UnregisterFD(fd);
-}
-
-std::string IcmpReachable::EpollCallback::Name() const {
-  return "ICMP Reachable";
-}
-
 }  // namespace quic
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable.h b/quiche/quic/qbone/bonnet/icmp_reachable.h
index a4ecdee..529ccc7 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable.h
+++ b/quiche/quic/qbone/bonnet/icmp_reachable.h
@@ -7,7 +7,14 @@
 
 #include <netinet/icmp6.h>
 
+#include <memory>
+
 #include "absl/strings/string_view.h"
+#include "quiche/quic/core/io/quic_event_loop.h"
+#include "quiche/quic/core/quic_alarm.h"
+#include "quiche/quic/core/quic_alarm_factory.h"
+#include "quiche/quic/core/quic_clock.h"
+#include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/platform/api/quic_ip_address.h"
 #include "quiche/quic/platform/api/quic_mutex.h"
 #include "quiche/quic/qbone/bonnet/icmp_reachable_interface.h"
@@ -29,7 +36,7 @@
 
   struct ReachableEvent {
     Status status;
-    absl::Duration response_time;
+    QuicTime::Delta response_time;
     std::string source;
   };
 
@@ -65,8 +72,8 @@
   // |stats| is not owned, but should outlive this instance. It will be called
   //         back on Echo Replies, timeouts, and I/O errors.
   IcmpReachable(QuicIpAddress source, QuicIpAddress destination,
-                absl::Duration timeout, KernelInterface* kernel,
-                QuicEpollServer* epoll_server, StatsInterface* stats);
+                QuicTime::Delta timeout, KernelInterface* kernel,
+                QuicEventLoop* event_loop, StatsInterface* stats);
 
   ~IcmpReachable() override;
 
@@ -74,13 +81,12 @@
   // |epoll_server|'s thread.
   bool Init() QUIC_LOCKS_EXCLUDED(header_lock_) override;
 
-  int64 /* allow-non-std-int */ OnAlarm()
-      QUIC_LOCKS_EXCLUDED(header_lock_) override;
+  void OnAlarm() QUIC_LOCKS_EXCLUDED(header_lock_);
 
   static absl::string_view StatusName(Status status);
 
  private:
-  class EpollCallback : public QuicEpollCallbackInterface {
+  class EpollCallback : public QuicSocketEventListener {
    public:
     explicit EpollCallback(IcmpReachable* reachable) : reachable_(reachable) {}
 
@@ -90,18 +96,18 @@
     EpollCallback(EpollCallback&&) = delete;
     EpollCallback& operator=(EpollCallback&&) = delete;
 
-    void OnRegistration(QuicEpollServer* eps, int fd,
-                        int event_mask) override{};
+    void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd,
+                       QuicSocketEventMask events) override;
 
-    void OnModification(int fd, int event_mask) override{};
+   private:
+    IcmpReachable* reachable_;
+  };
 
-    void OnEvent(int fd, QuicEpollEvent* event) override;
+  class AlarmCallback : public QuicAlarm::DelegateWithoutContext {
+   public:
+    explicit AlarmCallback(IcmpReachable* reachable) : reachable_(reachable) {}
 
-    void OnUnregistration(int fd, bool replaced) override{};
-
-    void OnShutdown(QuicEpollServer* eps, int fd) override;
-
-    std::string Name() const override;
+    void OnAlarm() override { reachable_->OnAlarm(); }
 
    private:
     IcmpReachable* reachable_;
@@ -109,15 +115,19 @@
 
   bool OnEvent(int fd) QUIC_LOCKS_EXCLUDED(header_lock_);
 
-  const absl::Duration timeout_;
+  const QuicTime::Delta timeout_;
+
+  QuicEventLoop* event_loop_;
+  const QuicClock* clock_;
+  std::unique_ptr<QuicAlarmFactory> alarm_factory_;
 
   EpollCallback cb_;
+  std::unique_ptr<QuicAlarm> alarm_;
 
   sockaddr_in6 src_{};
   sockaddr_in6 dst_{};
 
   KernelInterface* kernel_;
-  QuicEpollServer* epoll_server_;
 
   StatsInterface* stats_;
 
@@ -127,8 +137,8 @@
   QuicMutex header_lock_;
   icmp6_hdr icmp_header_ QUIC_GUARDED_BY(header_lock_){};
 
-  absl::Time start_ = absl::InfinitePast();
-  absl::Time end_ = absl::InfinitePast();
+  QuicTime start_ = QuicTime::Zero();
+  QuicTime end_ = QuicTime::Zero();
 };
 
 }  // namespace quic
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable_interface.h b/quiche/quic/qbone/bonnet/icmp_reachable_interface.h
index 20bf489..2426670 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable_interface.h
+++ b/quiche/quic/qbone/bonnet/icmp_reachable_interface.h
@@ -5,13 +5,12 @@
 #ifndef QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_INTERFACE_H_
 #define QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_INTERFACE_H_
 
-#include "quiche/quic/platform/api/quic_epoll.h"
-
 namespace quic {
 
-class IcmpReachableInterface : public QuicEpollAlarmBase {
+class IcmpReachableInterface {
  public:
   IcmpReachableInterface() = default;
+  virtual ~IcmpReachableInterface() = default;
 
   IcmpReachableInterface(const IcmpReachableInterface&) = delete;
   IcmpReachableInterface& operator=(const IcmpReachableInterface&) = delete;
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable_test.cc b/quiche/quic/qbone/bonnet/icmp_reachable_test.cc
index 7a0ebe6..ae48ddc 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable_test.cc
+++ b/quiche/quic/qbone/bonnet/icmp_reachable_test.cc
@@ -6,8 +6,12 @@
 
 #include <netinet/ip6.h>
 
+#include <memory>
+
 #include "absl/container/node_hash_map.h"
-#include "quiche/quic/platform/api/quic_epoll.h"
+#include "quiche/quic/core/io/quic_default_event_loop.h"
+#include "quiche/quic/core/io/quic_event_loop.h"
+#include "quiche/quic/core/quic_default_clock.h"
 #include "quiche/quic/platform/api/quic_ip_address.h"
 #include "quiche/quic/platform/api/quic_test.h"
 #include "quiche/quic/qbone/platform/mock_kernel.h"
@@ -79,7 +83,8 @@
 
 class IcmpReachableTest : public QuicTest {
  public:
-  IcmpReachableTest() {
+  IcmpReachableTest()
+      : event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())) {
     QUICHE_CHECK(source_.FromString(kSourceAddress));
     QUICHE_CHECK(destination_.FromString(kDestinationAddress));
 
@@ -113,13 +118,13 @@
   int read_src_fd_;
 
   StrictMock<MockKernel> kernel_;
-  QuicEpollServer epoll_server_;
+  std::unique_ptr<QuicEventLoop> event_loop_;
   StatsInterface stats_;
 };
 
 TEST_F(IcmpReachableTest, SendsPings) {
-  IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
-                          &epoll_server_, &stats_);
+  IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+                          &kernel_, event_loop_.get(), &stats_);
 
   SetFdExpectations();
   ASSERT_TRUE(reachable.Init());
@@ -133,15 +138,13 @@
         return len;
       }));
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_FALSE(stats_.HasWriteErrors());
-
-  epoll_server_.Shutdown();
 }
 
 TEST_F(IcmpReachableTest, HandlesUnreachableEvents) {
-  IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
-                          &epoll_server_, &stats_);
+  IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+                          &kernel_, event_loop_.get(), &stats_);
 
   SetFdExpectations();
   ASSERT_TRUE(reachable.Init());
@@ -152,20 +155,18 @@
                                 int flags, const struct sockaddr* dest_addr,
                                 socklen_t addrlen) { return len; }));
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_EQ(stats_.unreachable_count(), 0);
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_FALSE(stats_.HasWriteErrors());
   EXPECT_EQ(stats_.unreachable_count(), 1);
   EXPECT_EQ(stats_.current_source(), kNoSource);
-
-  epoll_server_.Shutdown();
 }
 
 TEST_F(IcmpReachableTest, HandlesReachableEvents) {
-  IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
-                          &epoll_server_, &stats_);
+  IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+                          &kernel_, event_loop_.get(), &stats_);
 
   SetFdExpectations();
   ASSERT_TRUE(reachable.Init());
@@ -193,7 +194,7 @@
             return read(sockfd, buf, len);
           }));
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_EQ(stats_.reachable_count(), 0);
 
   icmp6_hdr response = last_request_hdr;
@@ -202,18 +203,16 @@
   write(read_src_fd_, reinterpret_cast<const void*>(&response),
         sizeof(icmp6_hdr));
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_FALSE(stats_.HasReadErrors());
   EXPECT_FALSE(stats_.HasWriteErrors());
   EXPECT_EQ(stats_.reachable_count(), 1);
   EXPECT_EQ(stats_.current_source(), source_.ToString());
-
-  epoll_server_.Shutdown();
 }
 
 TEST_F(IcmpReachableTest, HandlesWriteErrors) {
-  IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
-                          &epoll_server_, &stats_);
+  IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+                          &kernel_, event_loop_.get(), &stats_);
 
   SetFdExpectations();
   ASSERT_TRUE(reachable.Init());
@@ -225,15 +224,13 @@
         return 0;
       }));
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_EQ(stats_.WriteErrorCount(EAGAIN), 1);
-
-  epoll_server_.Shutdown();
 }
 
 TEST_F(IcmpReachableTest, HandlesReadErrors) {
-  IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
-                          &epoll_server_, &stats_);
+  IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+                          &kernel_, event_loop_.get(), &stats_);
 
   SetFdExpectations();
   ASSERT_TRUE(reachable.Init());
@@ -255,11 +252,9 @@
   write(read_src_fd_, reinterpret_cast<const void*>(&response),
         sizeof(icmp6_hdr));
 
-  epoll_server_.WaitForEventsAndExecuteCallbacks();
+  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
   EXPECT_EQ(stats_.reachable_count(), 0);
   EXPECT_EQ(stats_.ReadErrorCount(EIO), 1);
-
-  epoll_server_.Shutdown();
 }
 
 }  // namespace