1 /* MIT License 2 * 3 * Copyright (c) 2023 Brad House 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * SPDX-License-Identifier: MIT 25 */ 26 #ifndef __ARES__EVENT_H 27 #define __ARES__EVENT_H 28 29 struct ares_event; 30 typedef struct ares_event ares_event_t; 31 32 typedef enum { 33 ARES_EVENT_FLAG_NONE = 0, 34 ARES_EVENT_FLAG_READ = 1 << 0, 35 ARES_EVENT_FLAG_WRITE = 1 << 1, 36 ARES_EVENT_FLAG_OTHER = 1 << 2 37 } ares_event_flags_t; 38 39 typedef void (*ares_event_cb_t)(ares_event_thread_t *e, ares_socket_t fd, 40 void *data, ares_event_flags_t flags); 41 42 typedef void (*ares_event_free_data_t)(void *data); 43 44 typedef void (*ares_event_signal_cb_t)(const ares_event_t *event); 45 46 struct ares_event { 47 /*! Registered event thread this event is bound to */ 48 ares_event_thread_t *e; 49 /*! Flags to monitor. OTHER is only allowed if the socket is ARES_SOCKET_BAD. 50 */ 51 ares_event_flags_t flags; 52 /*! Callback to be called when event is triggered */ 53 ares_event_cb_t cb; 54 /*! Socket to monitor, allowed to be ARES_SOCKET_BAD if not monitoring a 55 * socket. */ 56 ares_socket_t fd; 57 /*! Data associated with event handle that will be passed to the callback. 58 * Typically OS/event subsystem specific data. 59 * Optional, may be NULL. */ 60 /*! Data to be passed to callback. Optional, may be NULL. */ 61 void *data; 62 /*! When cleaning up the registered event (either when removed or during 63 * shutdown), this function will be called to clean up the user-supplied 64 * data. Optional, May be NULL. */ 65 ares_event_free_data_t free_data_cb; 66 /*! Callback to call to trigger an event. */ 67 ares_event_signal_cb_t signal_cb; 68 }; 69 70 typedef struct { 71 const char *name; 72 ares_bool_t (*init)(ares_event_thread_t *e); 73 void (*destroy)(ares_event_thread_t *e); 74 ares_bool_t (*event_add)(ares_event_t *event); 75 void (*event_del)(ares_event_t *event); 76 void (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags); 77 size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms); 78 } ares_event_sys_t; 79 80 struct ares_event_configchg; 81 typedef struct ares_event_configchg ares_event_configchg_t; 82 83 ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg, 84 ares_event_thread_t *e); 85 86 void ares_event_configchg_destroy(ares_event_configchg_t *configchg); 87 88 struct ares_event_thread { 89 /*! Whether the event thread should be online or not. Checked on every wake 90 * event before sleeping. */ 91 ares_bool_t isup; 92 /*! Handle to the thread for joining during shutdown */ 93 ares_thread_t *thread; 94 /*! Lock to protect the data contained within the event thread itself */ 95 ares_thread_mutex_t *mutex; 96 /*! Reference to the ares channel, for being able to call things like 97 * ares_timeout() and ares_process_fd(). */ 98 ares_channel_t *channel; 99 /*! Whether or not on the next loop we should process a pending write */ 100 ares_bool_t process_pending_write; 101 /*! Not-yet-processed event handle updates. These will get enqueued by a 102 * thread other than the event thread itself. The event thread will then 103 * be woken then process these updates itself */ 104 ares_llist_t *ev_updates; 105 /*! Registered socket event handles */ 106 ares_htable_asvp_t *ev_sock_handles; 107 /*! Registered custom event handles. Typically used for external triggering. 108 */ 109 ares_htable_vpvp_t *ev_cust_handles; 110 /*! Pointer to the event handle which is used to signal and wake the event 111 * thread itself. This is needed to be able to do things like update the 112 * file descriptors being waited on and to wake the event subsystem during 113 * shutdown */ 114 ares_event_t *ev_signal; 115 /*! Handle for configuration change monitoring */ 116 ares_event_configchg_t *configchg; 117 /* Event subsystem callbacks */ 118 const ares_event_sys_t *ev_sys; 119 /* Event subsystem private data */ 120 void *ev_sys_data; 121 }; 122 123 /*! Queue an update for the event handle. 124 * 125 * Will search by the fd passed if not ARES_SOCKET_BAD to find a match and 126 * perform an update or delete (depending on flags). Otherwise will add. 127 * Do not use the event handle returned if its not guaranteed to be an add 128 * operation. 129 * 130 * \param[out] event Event handle. Optional, can be NULL. This handle 131 * will be invalidate quickly if the result of the 132 * operation is not an ADD. 133 * \param[in] e pointer to event thread handle 134 * \param[in] flags flags for the event handle. Use 135 * ARES_EVENT_FLAG_NONE if removing a socket from 136 * queue (not valid if socket is ARES_SOCKET_BAD). 137 * Non-socket events cannot be removed, and must have 138 * ARES_EVENT_FLAG_OTHER set. 139 * \param[in] cb Callback to call when 140 * event is triggered. Required if flags is not 141 * ARES_EVENT_FLAG_NONE. Not allowed to be 142 * changed, ignored on modification. 143 * \param[in] fd File descriptor/socket to monitor. May 144 * be ARES_SOCKET_BAD if not monitoring file 145 * descriptor. 146 * \param[in] data Optional. Caller-supplied data to be passed to 147 * callback. Only allowed on initial add, cannot be 148 * modified later, ignored on modification. 149 * \param[in] free_data_cb Optional. Callback to clean up caller-supplied 150 * data. Only allowed on initial add, cannot be 151 * modified later, ignored on modification. 152 * \param[in] signal_cb Optional. Callback to call to trigger an event. 153 * \return ARES_SUCCESS on success 154 */ 155 ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e, 156 ares_event_flags_t flags, ares_event_cb_t cb, 157 ares_socket_t fd, void *data, 158 ares_event_free_data_t free_data_cb, 159 ares_event_signal_cb_t signal_cb); 160 161 162 #ifdef CARES_THREADS 163 # ifdef HAVE_PIPE 164 ares_event_t *ares_pipeevent_create(ares_event_thread_t *e); 165 # endif 166 167 # ifdef HAVE_POLL 168 extern const ares_event_sys_t ares_evsys_poll; 169 # endif 170 171 # ifdef HAVE_KQUEUE 172 extern const ares_event_sys_t ares_evsys_kqueue; 173 # endif 174 175 # ifdef HAVE_EPOLL 176 extern const ares_event_sys_t ares_evsys_epoll; 177 # endif 178 179 # ifdef _WIN32 180 extern const ares_event_sys_t ares_evsys_win32; 181 # endif 182 183 /* All systems have select(), but not all have a way to wake, so we require 184 * pipe() to wake the select() */ 185 # ifdef HAVE_PIPE 186 extern const ares_event_sys_t ares_evsys_select; 187 # endif 188 189 #endif 190 191 #endif 192