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 #include "ares_setup.h" 30 31 struct ares_event; 32 typedef struct ares_event ares_event_t; 33 34 typedef enum { 35 ARES_EVENT_FLAG_NONE = 0, 36 ARES_EVENT_FLAG_READ = 1 << 0, 37 ARES_EVENT_FLAG_WRITE = 1 << 1, 38 ARES_EVENT_FLAG_OTHER = 1 << 2 39 } ares_event_flags_t; 40 41 typedef void (*ares_event_cb_t)(ares_event_thread_t *e, ares_socket_t fd, 42 void *data, ares_event_flags_t flags); 43 44 typedef void (*ares_event_free_data_t)(void *data); 45 46 typedef void (*ares_event_signal_cb_t)(const ares_event_t *event); 47 48 struct ares_event { 49 /*! Registered event thread this event is bound to */ 50 ares_event_thread_t *e; 51 /*! Flags to monitor. OTHER is only allowed if the socket is ARES_SOCKET_BAD. 52 */ 53 ares_event_flags_t flags; 54 /*! Callback to be called when event is triggered */ 55 ares_event_cb_t cb; 56 /*! Socket to monitor, allowed to be ARES_SOCKET_BAD if not monitoring a 57 * socket. */ 58 ares_socket_t fd; 59 /*! Data associated with event handle that will be passed to the callback. 60 * Typically OS/event subsystem specific data. 61 * Optional, may be NULL. */ 62 /*! Data to be passed to callback. Optional, may be NULL. */ 63 void *data; 64 /*! When cleaning up the registered event (either when removed or during 65 * shutdown), this function will be called to clean up the user-supplied 66 * data. Optional, May be NULL. */ 67 ares_event_free_data_t free_data_cb; 68 /*! Callback to call to trigger an event. */ 69 ares_event_signal_cb_t signal_cb; 70 }; 71 72 typedef struct { 73 const char *name; 74 ares_bool_t (*init)(ares_event_thread_t *e); 75 void (*destroy)(ares_event_thread_t *e); 76 ares_bool_t (*event_add)(ares_event_t *event); 77 void (*event_del)(ares_event_t *event); 78 void (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags); 79 size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms); 80 } ares_event_sys_t; 81 82 struct ares_event_thread { 83 /*! Whether the event thread should be online or not. Checked on every wake 84 * event before sleeping. */ 85 ares_bool_t isup; 86 /*! Handle to the thread for joining during shutdown */ 87 ares__thread_t *thread; 88 /*! Lock to protect the data contained within the event thread itself */ 89 ares__thread_mutex_t *mutex; 90 /*! Reference to the ares channel, for being able to call things like 91 * ares_timeout() and ares_process_fd(). */ 92 ares_channel_t *channel; 93 /*! Not-yet-processed event handle updates. These will get enqueued by a 94 * thread other than the event thread itself. The event thread will then 95 * be woken then process these updates itself */ 96 ares__llist_t *ev_updates; 97 /*! Registered event handles. */ 98 ares__htable_asvp_t *ev_handles; 99 /*! Pointer to the event handle which is used to signal and wake the event 100 * thread itself. This is needed to be able to do things like update the 101 * file descriptors being waited on and to wake the event subsystem during 102 * shutdown */ 103 ares_event_t *ev_signal; 104 /* Event subsystem callbacks */ 105 const ares_event_sys_t *ev_sys; 106 /* Event subsystem private data */ 107 void *ev_sys_data; 108 }; 109 110 /*! Queue an update for the event handle. 111 * 112 * Will search by the fd passed if not ARES_SOCKET_BAD to find a match and 113 * perform an update or delete (depending on flags). Otherwise will add. 114 * Do not use the event handle returned if its not guaranteed to be an add 115 * operation. 116 * 117 * \param[out] event Event handle. Optional, can be NULL. This handle 118 * will be invalidate quickly if the result of the 119 * operation is not an ADD. 120 * \param[in] e pointer to event thread handle 121 * \param[in] flags flags for the event handle. Use 122 * ARES_EVENT_FLAG_NONE if removing a socket from 123 * queue (not valid if socket is ARES_SOCKET_BAD). 124 * Non-socket events cannot be removed, and must have 125 * ARES_EVENT_FLAG_OTHER set. 126 * \param[in] cb Callback to call when 127 * event is triggered. Required. Not allowed to be 128 * changed, ignored on modification. 129 * \param[in] fd File descriptor/socket to monitor. May 130 * be ARES_SOCKET_BAD if not monitoring file 131 * descriptor. 132 * \param[in] data Optional. Caller-supplied data to be passed to 133 * callback. Only allowed on initial add, cannot be 134 * modified later, ignored on modification. 135 * \param[in] free_data_cb Optional. Callback to clean up caller-supplied 136 * data. Only allowed on initial add, cannot be 137 * modified later, ignored on modification. 138 * \param[in] signal_cb Optional. Callback to call to trigger an event. 139 * \return ARES_SUCCESS on success 140 */ 141 ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e, 142 ares_event_flags_t flags, ares_event_cb_t cb, 143 ares_socket_t fd, void *data, 144 ares_event_free_data_t free_data_cb, 145 ares_event_signal_cb_t signal_cb); 146 147 148 #ifdef HAVE_PIPE 149 ares_event_t *ares_pipeevent_create(ares_event_thread_t *e); 150 #endif 151 152 #ifdef HAVE_POLL 153 extern const ares_event_sys_t ares_evsys_poll; 154 #endif 155 156 #ifdef HAVE_KQUEUE 157 extern const ares_event_sys_t ares_evsys_kqueue; 158 #endif 159 160 #ifdef HAVE_EPOLL 161 extern const ares_event_sys_t ares_evsys_epoll; 162 #endif 163 164 #ifdef _WIN32 165 extern const ares_event_sys_t ares_evsys_win32; 166 #endif 167 168 /* All systems have select(), but not all have a way to wake, so we require 169 * pipe() to wake the select() */ 170 #ifdef HAVE_PIPE 171 extern const ares_event_sys_t ares_evsys_select; 172 #endif 173 174 #endif 175