1 /* MIT License
2 *
3 * Copyright (c) 1998 Massachusetts Institute of Technology
4 * Copyright (c) 2004 Daniel Stenberg
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 */
27
28 #include "ares_setup.h"
29
30 #include <assert.h>
31
32 #include "ares.h"
33 #include "ares_private.h"
34
ares_destroy(ares_channel_t * channel)35 void ares_destroy(ares_channel_t *channel)
36 {
37 size_t i;
38 ares__llist_node_t *node = NULL;
39
40 if (channel == NULL) {
41 return;
42 }
43
44 /* Lock because callbacks will be triggered */
45 ares__channel_lock(channel);
46
47 /* Destroy all queries */
48 node = ares__llist_node_first(channel->all_queries);
49 while (node != NULL) {
50 ares__llist_node_t *next = ares__llist_node_next(node);
51 struct query *query = ares__llist_node_claim(node);
52
53 query->node_all_queries = NULL;
54 query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0);
55 ares__free_query(query);
56
57 node = next;
58 }
59
60 ares_queue_notify_empty(channel);
61
62 #ifndef NDEBUG
63 /* Freeing the query should remove it from all the lists in which it sits,
64 * so all query lists should be empty now.
65 */
66 assert(ares__llist_len(channel->all_queries) == 0);
67 assert(ares__htable_szvp_num_keys(channel->queries_by_qid) == 0);
68 assert(ares__slist_len(channel->queries_by_timeout) == 0);
69 #endif
70
71 ares__destroy_servers_state(channel);
72
73 #ifndef NDEBUG
74 assert(ares__htable_asvp_num_keys(channel->connnode_by_socket) == 0);
75 #endif
76
77 /* No more callbacks will be triggered after this point, unlock */
78 ares__channel_unlock(channel);
79
80 /* Shut down the event thread */
81 if (channel->optmask & ARES_OPT_EVENT_THREAD) {
82 ares_event_thread_destroy(channel);
83 }
84
85 if (channel->domains) {
86 for (i = 0; i < channel->ndomains; i++) {
87 ares_free(channel->domains[i]);
88 }
89 ares_free(channel->domains);
90 }
91
92 ares__llist_destroy(channel->all_queries);
93 ares__slist_destroy(channel->queries_by_timeout);
94 ares__htable_szvp_destroy(channel->queries_by_qid);
95 ares__htable_asvp_destroy(channel->connnode_by_socket);
96
97 ares_free(channel->sortlist);
98 ares_free(channel->lookups);
99 ares_free(channel->resolvconf_path);
100 ares_free(channel->hosts_path);
101 ares__destroy_rand_state(channel->rand_state);
102
103 ares__hosts_file_destroy(channel->hf);
104
105 ares__qcache_destroy(channel->qcache);
106
107 ares__channel_threading_destroy(channel);
108
109 ares_free(channel);
110 }
111
ares__destroy_server(struct server_state * server)112 void ares__destroy_server(struct server_state *server)
113 {
114 if (server == NULL) {
115 return;
116 }
117
118 ares__close_sockets(server);
119 ares__llist_destroy(server->connections);
120 ares__buf_destroy(server->tcp_parser);
121 ares__buf_destroy(server->tcp_send);
122 ares_free(server);
123 }
124
ares__destroy_servers_state(ares_channel_t * channel)125 void ares__destroy_servers_state(ares_channel_t *channel)
126 {
127 ares__slist_node_t *node;
128
129 while ((node = ares__slist_node_first(channel->servers)) != NULL) {
130 struct server_state *server = ares__slist_node_claim(node);
131 ares__destroy_server(server);
132 }
133
134 ares__slist_destroy(channel->servers);
135 channel->servers = NULL;
136 }
137