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