xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/qbone/bonnet/icmp_reachable.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_
6 #define QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_
7 
8 #include <netinet/icmp6.h>
9 
10 #include <memory>
11 
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/io/quic_event_loop.h"
14 #include "quiche/quic/core/quic_alarm.h"
15 #include "quiche/quic/core/quic_alarm_factory.h"
16 #include "quiche/quic/core/quic_clock.h"
17 #include "quiche/quic/core/quic_time.h"
18 #include "quiche/quic/platform/api/quic_ip_address.h"
19 #include "quiche/quic/platform/api/quic_mutex.h"
20 #include "quiche/quic/qbone/bonnet/icmp_reachable_interface.h"
21 #include "quiche/quic/qbone/platform/kernel_interface.h"
22 
23 namespace quic {
24 
25 extern const char kUnknownSource[];
26 extern const char kNoSource[];
27 
28 // IcmpReachable schedules itself with an EpollServer, periodically sending
29 // ICMPv6 Echo Requests to the given |destination| on the interface that the
30 // given |source| is bound to. Echo Requests are sent once every |timeout|.
31 // On Echo Replies, timeouts, and I/O errors, the given |stats| object will
32 // be called back with details of the event.
33 class IcmpReachable : public IcmpReachableInterface {
34  public:
35   enum Status { REACHABLE, UNREACHABLE };
36 
37   struct ReachableEvent {
38     Status status;
39     QuicTime::Delta response_time;
40     std::string source;
41   };
42 
43   class StatsInterface {
44    public:
45     StatsInterface() = default;
46 
47     StatsInterface(const StatsInterface&) = delete;
48     StatsInterface& operator=(const StatsInterface&) = delete;
49 
50     StatsInterface(StatsInterface&&) = delete;
51     StatsInterface& operator=(StatsInterface&&) = delete;
52 
53     virtual ~StatsInterface() = default;
54 
55     virtual void OnEvent(ReachableEvent event) = 0;
56 
57     virtual void OnReadError(int error) = 0;
58 
59     virtual void OnWriteError(int error) = 0;
60   };
61 
62   // |source| is the IPv6 address bound to the interface that IcmpReachable will
63   //          send Echo Requests on.
64   // |destination| is the IPv6 address of the destination of the Echo Requests.
65   // |timeout| is the duration IcmpReachable will wait between Echo Requests.
66   //           If no Echo Response is received by the next Echo Request, it will
67   //           be considered a timeout.
68   // |kernel| is not owned, but should outlive this instance.
69   // |epoll_server| is not owned, but should outlive this instance.
70   //                IcmpReachable's Init() must be called from within the Epoll
71   //                Server's thread.
72   // |stats| is not owned, but should outlive this instance. It will be called
73   //         back on Echo Replies, timeouts, and I/O errors.
74   IcmpReachable(QuicIpAddress source, QuicIpAddress destination,
75                 QuicTime::Delta timeout, KernelInterface* kernel,
76                 QuicEventLoop* event_loop, StatsInterface* stats);
77 
78   ~IcmpReachable() override;
79 
80   // Initializes this reachability probe. Must be called from within the
81   // |epoll_server|'s thread.
82   bool Init() QUIC_LOCKS_EXCLUDED(header_lock_) override;
83 
84   void OnAlarm() QUIC_LOCKS_EXCLUDED(header_lock_);
85 
86   static absl::string_view StatusName(Status status);
87 
88  private:
89   class EpollCallback : public QuicSocketEventListener {
90    public:
EpollCallback(IcmpReachable * reachable)91     explicit EpollCallback(IcmpReachable* reachable) : reachable_(reachable) {}
92 
93     EpollCallback(const EpollCallback&) = delete;
94     EpollCallback& operator=(const EpollCallback&) = delete;
95 
96     EpollCallback(EpollCallback&&) = delete;
97     EpollCallback& operator=(EpollCallback&&) = delete;
98 
99     void OnSocketEvent(QuicEventLoop* event_loop, SocketFd fd,
100                        QuicSocketEventMask events) override;
101 
102    private:
103     IcmpReachable* reachable_;
104   };
105 
106   class AlarmCallback : public QuicAlarm::DelegateWithoutContext {
107    public:
AlarmCallback(IcmpReachable * reachable)108     explicit AlarmCallback(IcmpReachable* reachable) : reachable_(reachable) {}
109 
OnAlarm()110     void OnAlarm() override { reachable_->OnAlarm(); }
111 
112    private:
113     IcmpReachable* reachable_;
114   };
115 
116   bool OnEvent(int fd) QUIC_LOCKS_EXCLUDED(header_lock_);
117 
118   const QuicTime::Delta timeout_;
119 
120   QuicEventLoop* event_loop_;
121   const QuicClock* clock_;
122   std::unique_ptr<QuicAlarmFactory> alarm_factory_;
123 
124   EpollCallback cb_;
125   std::unique_ptr<QuicAlarm> alarm_;
126 
127   sockaddr_in6 src_{};
128   sockaddr_in6 dst_{};
129 
130   KernelInterface* kernel_;
131 
132   StatsInterface* stats_;
133 
134   int send_fd_;
135   int recv_fd_;
136 
137   QuicMutex header_lock_;
QUIC_GUARDED_BY(header_lock_)138   icmp6_hdr icmp_header_ QUIC_GUARDED_BY(header_lock_){};
139 
140   QuicTime start_ = QuicTime::Zero();
141   QuicTime end_ = QuicTime::Zero();
142 };
143 
144 }  // namespace quic
145 
146 #endif  // QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_H_
147