• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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