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