/src/c-ares/src/lib/event/ares_event_select.c
Line | Count | Source |
1 | | /* MIT License |
2 | | * |
3 | | * Copyright (c) 2024 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 | | |
27 | | /* Some systems might default to something low like 256 (NetBSD), lets define |
28 | | * this to assist. Really, no one should be using select, but lets be safe |
29 | | * anyhow */ |
30 | | #define FD_SETSIZE 4096 |
31 | | |
32 | | #include "ares_private.h" |
33 | | #include "ares_event.h" |
34 | | |
35 | | /* All systems have select(), but not all have a way to wake, so we require |
36 | | * pipe() to wake the select() */ |
37 | | #if defined(HAVE_PIPE) && defined(CARES_THREADS) |
38 | | |
39 | | #ifdef HAVE_SYS_SELECT_H |
40 | | # include <sys/select.h> |
41 | | #endif |
42 | | |
43 | | static ares_bool_t ares_evsys_select_init(ares_event_thread_t *e) |
44 | 0 | { |
45 | 0 | e->ev_signal = ares_pipeevent_create(e); |
46 | 0 | if (e->ev_signal == NULL) { |
47 | 0 | return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */ |
48 | 0 | } |
49 | 0 | return ARES_TRUE; |
50 | 0 | } |
51 | | |
52 | | static void ares_evsys_select_destroy(ares_event_thread_t *e) |
53 | 0 | { |
54 | 0 | (void)e; |
55 | 0 | } |
56 | | |
57 | | static ares_bool_t ares_evsys_select_event_add(ares_event_t *event) |
58 | 0 | { |
59 | 0 | (void)event; |
60 | 0 | return ARES_TRUE; |
61 | 0 | } |
62 | | |
63 | | static void ares_evsys_select_event_del(ares_event_t *event) |
64 | 0 | { |
65 | 0 | (void)event; |
66 | 0 | } |
67 | | |
68 | | static void ares_evsys_select_event_mod(ares_event_t *event, |
69 | | ares_event_flags_t new_flags) |
70 | 0 | { |
71 | 0 | (void)event; |
72 | 0 | (void)new_flags; |
73 | 0 | } |
74 | | |
75 | | static size_t ares_evsys_select_wait(ares_event_thread_t *e, |
76 | | unsigned long timeout_ms) |
77 | 0 | { |
78 | 0 | size_t num_fds = 0; |
79 | 0 | ares_socket_t *fdlist = ares_htable_asvp_keys(e->ev_sock_handles, &num_fds); |
80 | 0 | int rv; |
81 | 0 | size_t cnt = 0; |
82 | 0 | size_t i; |
83 | 0 | fd_set read_fds; |
84 | 0 | fd_set write_fds; |
85 | 0 | fd_set except_fds; |
86 | 0 | int nfds = 0; |
87 | 0 | struct timeval tv; |
88 | 0 | struct timeval *tout = NULL; |
89 | |
|
90 | 0 | FD_ZERO(&read_fds); |
91 | 0 | FD_ZERO(&write_fds); |
92 | 0 | FD_ZERO(&except_fds); |
93 | |
|
94 | 0 | for (i = 0; i < num_fds; i++) { |
95 | 0 | const ares_event_t *ev = |
96 | 0 | ares_htable_asvp_get_direct(e->ev_sock_handles, fdlist[i]); |
97 | 0 | if (ev->flags & ARES_EVENT_FLAG_READ) { |
98 | 0 | FD_SET(ev->fd, &read_fds); |
99 | 0 | } |
100 | 0 | if (ev->flags & ARES_EVENT_FLAG_WRITE) { |
101 | 0 | FD_SET(ev->fd, &write_fds); |
102 | 0 | } |
103 | 0 | FD_SET(ev->fd, &except_fds); |
104 | 0 | if (ev->fd + 1 > nfds) { |
105 | 0 | nfds = ev->fd + 1; |
106 | 0 | } |
107 | 0 | } |
108 | |
|
109 | 0 | if (timeout_ms) { |
110 | 0 | tv.tv_sec = (int)(timeout_ms / 1000); |
111 | 0 | tv.tv_usec = (int)((timeout_ms % 1000) * 1000); |
112 | 0 | tout = &tv; |
113 | 0 | } |
114 | |
|
115 | 0 | rv = select(nfds, &read_fds, &write_fds, &except_fds, tout); |
116 | 0 | if (rv > 0) { |
117 | 0 | for (i = 0; i < num_fds; i++) { |
118 | 0 | ares_event_t *ev; |
119 | 0 | ares_event_flags_t flags = 0; |
120 | |
|
121 | 0 | ev = ares_htable_asvp_get_direct(e->ev_sock_handles, fdlist[i]); |
122 | 0 | if (ev == NULL || ev->cb == NULL) { |
123 | 0 | continue; /* LCOV_EXCL_LINE: DefensiveCoding */ |
124 | 0 | } |
125 | | |
126 | 0 | if (FD_ISSET(fdlist[i], &read_fds) || FD_ISSET(fdlist[i], &except_fds)) { |
127 | 0 | flags |= ARES_EVENT_FLAG_READ; |
128 | 0 | } |
129 | |
|
130 | 0 | if (FD_ISSET(fdlist[i], &write_fds)) { |
131 | 0 | flags |= ARES_EVENT_FLAG_WRITE; |
132 | 0 | } |
133 | |
|
134 | 0 | if (flags == 0) { |
135 | 0 | continue; |
136 | 0 | } |
137 | | |
138 | 0 | cnt++; |
139 | |
|
140 | 0 | ev->cb(e, fdlist[i], ev->data, flags); |
141 | 0 | } |
142 | 0 | } |
143 | |
|
144 | 0 | ares_free(fdlist); |
145 | |
|
146 | 0 | return cnt; |
147 | 0 | } |
148 | | |
149 | | const ares_event_sys_t ares_evsys_select = { |
150 | | "select", |
151 | | ares_evsys_select_init, |
152 | | ares_evsys_select_destroy, /* NoOp */ |
153 | | ares_evsys_select_event_add, /* NoOp */ |
154 | | ares_evsys_select_event_del, /* NoOp */ |
155 | | ares_evsys_select_event_mod, /* NoOp */ |
156 | | ares_evsys_select_wait |
157 | | }; |
158 | | |
159 | | #endif |