xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/bindings/quic_libevent.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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_BINDINGS_QUIC_LIBEVENT_H_
6 #define QUICHE_QUIC_BINDINGS_QUIC_LIBEVENT_H_
7 
8 #include <memory>
9 
10 #include "absl/container/node_hash_map.h"
11 #include "event2/event.h"
12 #include "event2/event_struct.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_udp_socket.h"
17 
18 namespace quic {
19 
20 // Provides a libevent-based implementation of QuicEventLoop.  Since libevent
21 // uses relative time for all timeouts, the provided clock does not need to use
22 // the UNIX time.
23 class QUICHE_EXPORT LibeventQuicEventLoop : public QuicEventLoop {
24  public:
25   explicit LibeventQuicEventLoop(event_base* base, QuicClock* clock);
26 
27   // QuicEventLoop implementation.
SupportsEdgeTriggered()28   bool SupportsEdgeTriggered() const override { return edge_triggered_; }
CreateAlarmFactory()29   std::unique_ptr<QuicAlarmFactory> CreateAlarmFactory() override {
30     return std::make_unique<AlarmFactory>(this);
31   }
32   bool RegisterSocket(QuicUdpSocketFd fd, QuicSocketEventMask events,
33                       QuicSocketEventListener* listener) override;
34   bool UnregisterSocket(QuicUdpSocketFd fd) override;
35   bool RearmSocket(QuicUdpSocketFd fd, QuicSocketEventMask events) override;
36   bool ArtificiallyNotifyEvent(QuicUdpSocketFd fd,
37                                QuicSocketEventMask events) override;
38   void RunEventLoopOnce(QuicTime::Delta default_timeout) override;
GetClock()39   const QuicClock* GetClock() override { return clock_; }
40 
41   // Can be called from another thread to wake up the event loop from a blocking
42   // RunEventLoopOnce() call.
43   void WakeUp();
44 
base()45   event_base* base() { return base_; }
clock()46   QuicClock* clock() const { return clock_; }
47 
48  private:
49   class AlarmFactory : public QuicAlarmFactory {
50    public:
AlarmFactory(LibeventQuicEventLoop * loop)51     AlarmFactory(LibeventQuicEventLoop* loop) : loop_(loop) {}
52 
53     // QuicAlarmFactory interface.
54     QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
55     QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
56         QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
57         QuicConnectionArena* arena) override;
58 
59    private:
60     LibeventQuicEventLoop* loop_;
61   };
62 
63   class Registration {
64    public:
65     Registration(LibeventQuicEventLoop* loop, QuicUdpSocketFd fd,
66                  QuicSocketEventMask events, QuicSocketEventListener* listener);
67     ~Registration();
68 
69     void ArtificiallyNotify(QuicSocketEventMask events);
70     void Rearm(QuicSocketEventMask events);
71 
72    private:
73     LibeventQuicEventLoop* loop_;
74     QuicSocketEventListener* listener_;
75 
76     // Used for edge-triggered backends.
77     event both_events_;
78     // Used for level-triggered backends, since we may have to re-arm read
79     // events and write events separately.
80     event read_event_;
81     event write_event_;
82   };
83 
84   using RegistrationMap = absl::node_hash_map<QuicUdpSocketFd, Registration>;
85 
86   event_base* base_;
87   const bool edge_triggered_;
88   QuicClock* clock_;
89 
90   RegistrationMap registration_map_;
91 };
92 
93 // RAII-style wrapper around event_base.
94 class QUICHE_EXPORT LibeventLoop {
95  public:
LibeventLoop(struct event_base * base)96   LibeventLoop(struct event_base* base) : event_base_(base) {}
~LibeventLoop()97   ~LibeventLoop() { event_base_free(event_base_); }
98 
event_base()99   struct event_base* event_base() { return event_base_; }
100 
101  private:
102   struct event_base* event_base_;
103 };
104 
105 // A version of LibeventQuicEventLoop that owns the supplied `event_base`.  Note
106 // that the inheritance order here matters, since otherwise the `event_base` in
107 // question will be deleted before the LibeventQuicEventLoop object referencing
108 // it.
109 class QUICHE_EXPORT LibeventQuicEventLoopWithOwnership
110     : public LibeventLoop,
111       public LibeventQuicEventLoop {
112  public:
113   static std::unique_ptr<LibeventQuicEventLoopWithOwnership> Create(
114       QuicClock* clock, bool force_level_triggered = false);
115 
116   // Takes ownership of |base|.
LibeventQuicEventLoopWithOwnership(struct event_base * base,QuicClock * clock)117   explicit LibeventQuicEventLoopWithOwnership(struct event_base* base,
118                                               QuicClock* clock)
119       : LibeventLoop(base), LibeventQuicEventLoop(base, clock) {}
120 };
121 
122 class QUICHE_EXPORT QuicLibeventEventLoopFactory : public QuicEventLoopFactory {
123  public:
124   // Provides the preferred libevent backend.
Get()125   static QuicLibeventEventLoopFactory* Get() {
126     static QuicLibeventEventLoopFactory* factory =
127         new QuicLibeventEventLoopFactory(/*force_level_triggered=*/false);
128     return factory;
129   }
130 
131   // Provides the libevent backend that does not support edge-triggered
132   // notifications.  Those are useful for tests, since we can test
133   // level-triggered I/O even on platforms where edge-triggered is the default.
GetLevelTriggeredBackendForTests()134   static QuicLibeventEventLoopFactory* GetLevelTriggeredBackendForTests() {
135     static QuicLibeventEventLoopFactory* factory =
136         new QuicLibeventEventLoopFactory(/*force_level_triggered=*/true);
137     return factory;
138   }
139 
Create(QuicClock * clock)140   std::unique_ptr<QuicEventLoop> Create(QuicClock* clock) override {
141     return LibeventQuicEventLoopWithOwnership::Create(clock,
142                                                       force_level_triggered_);
143   }
GetName()144   std::string GetName() const override { return name_; }
145 
146  private:
147   explicit QuicLibeventEventLoopFactory(bool force_level_triggered);
148 
149   bool force_level_triggered_;
150   std::string name_;
151 };
152 
153 }  // namespace quic
154 
155 #endif  // QUICHE_QUIC_BINDINGS_QUIC_LIBEVENT_H_
156