1 /* MIT License
2 *
3 * Copyright (c) 2005 Daniel Stenberg
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 #include "ares_private.h"
28
ares_getsock(const ares_channel_t * channel,ares_socket_t * socks,int numsocks)29 int ares_getsock(const ares_channel_t *channel, ares_socket_t *socks,
30 int numsocks) /* size of the 'socks' array */
31 {
32 ares_slist_node_t *snode;
33 size_t sockindex = 0;
34 unsigned int bitmap = 0;
35 unsigned int setbits = 0xffffffff;
36
37 /* Are there any active queries? */
38 size_t active_queries;
39
40 if (channel == NULL || numsocks <= 0) {
41 return 0;
42 }
43
44 ares_channel_lock(channel);
45
46 active_queries = ares_llist_len(channel->all_queries);
47
48 for (snode = ares_slist_node_first(channel->servers); snode != NULL;
49 snode = ares_slist_node_next(snode)) {
50 ares_server_t *server = ares_slist_node_val(snode);
51 ares_llist_node_t *node;
52
53 for (node = ares_llist_node_first(server->connections); node != NULL;
54 node = ares_llist_node_next(node)) {
55 const ares_conn_t *conn = ares_llist_node_val(node);
56
57 if (sockindex >= (size_t)numsocks || sockindex >= ARES_GETSOCK_MAXNUM) {
58 break;
59 }
60
61 /* We only need to register interest in UDP sockets if we have
62 * outstanding queries.
63 */
64 if (!active_queries && !(conn->flags & ARES_CONN_FLAG_TCP)) {
65 continue;
66 }
67
68 socks[sockindex] = conn->fd;
69
70 if (active_queries || conn->flags & ARES_CONN_FLAG_TCP) {
71 bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex);
72 }
73
74 if (conn->state_flags & ARES_CONN_STATE_WRITE) {
75 /* then the tcp socket is also writable! */
76 bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex);
77 }
78
79 sockindex++;
80 }
81 }
82
83 ares_channel_unlock(channel);
84 return (int)bitmap;
85 }
86