@@ -5,7 +5,7 @@ layout: page
5
5
---
6
6
7
7
- [ Manpages] ( #manpages )
8
- - [ Example ] ( #example )
8
+ - [ Examples ] ( #examples )
9
9
10
10
c-ares provides a set of library functions, datatypes, and enumerations
11
11
which integrators will use for their implementations. When you install c-ares,
@@ -19,10 +19,11 @@ you get man pages which describe their use and meanings.
19
19
- [ {{ my_page.path | replace: "docs/", "" | replace: ".html", "" }}] (/{{ my_page.path }})
20
20
{% endfor -%}
21
21
22
- ## Example
23
- A simple name resolve might look like:
22
+ ## Examples
24
23
25
- ` example.c ` :
24
+ ### Event Thread example (recommended)
25
+
26
+ ` example_ev.c ` :
26
27
{% highlight C %}
27
28
#include <stdio.h>
28
29
#include <string.h>
@@ -110,8 +111,190 @@ int main(int argc, char **argv)
110
111
111
112
Compilation:
112
113
{% highlight bash %}
113
- cc -I/usr/local/include -o example example .c -Wl,-rpath /usr/local/lib -lcares
114
+ cc -I/usr/local/include -o example_ev example_ev .c -Wl,-rpath /usr/local/lib -lcares
114
115
{% endhighlight %}
115
116
117
+ ### Sock State Callback example
118
+
119
+ ` example_ss.c ` :
120
+ {% highlight C %}
121
+ #include <stdio.h>
122
+ #include <string.h>
123
+ #include <stdlib.h>
124
+ #include <poll.h>
125
+ #include <ares.h>
126
+
127
+ typedef struct {
128
+ ares_channel_t * channel;
129
+ struct pollfd * fds;
130
+ size_t nfds;
131
+ } dnsstate_t;
132
+
133
+ void sock_state_cb(void * data, ares_socket_t socket_fd, int readable, int writable)
134
+ {
135
+ dnsstate_t * state = data;
136
+ size_t idx;
137
+
138
+ /* Find match * /
139
+ for (idx=0; idx<state- >nfds; idx++) {
140
+ if (state->fds[ idx] .fd == socket_fd) {
141
+ break;
142
+ }
143
+ }
144
+
145
+ /* Not found * /
146
+ if (idx >= state->nfds) {
147
+ /* Do nothing * /
148
+ if (!readable && !writable) {
149
+ return;
150
+ }
151
+
152
+ /* Add */
153
+ state->nfds++;
154
+ state->fds = realloc(state->fds, sizeof(*state->fds) * state->nfds);
155
+ } else {
156
+ /* Remove * /
157
+ if (!readable && !writable) {
158
+ memmove(&state->fds[ idx] , &state->fds[ idx+1] ,
159
+ sizeof(* state->fds) * (state->nfds - idx - 1));
160
+ state->nfds--;
161
+ return;
162
+ }
163
+ }
164
+
165
+ state->fds[ idx] .fd = socket_fd;
166
+ state->fds[ idx] .events = 0;
167
+ if (readable) {
168
+ state->fds[ idx] .events |= POLL_IN;
169
+ }
170
+ if (writable) {
171
+ state->fds[ idx] .events |= POLLOUT;
172
+ }
173
+ }
174
+
175
+ void process(dnsstate_t * state)
176
+ {
177
+ struct timeval tv;
178
+
179
+ while (1) {
180
+ int rv;
181
+ int timeout;
182
+ size_t i;
183
+
184
+ /* Since we don't have any other program state to wait on, we'll just
185
+ * stop looping when we know there are no remaining queries, which is
186
+ * easily indicated by ares_timeout() returning NULL when maxtv is NULL */
187
+ if (ares_timeout(state->channel, NULL, &tv) == NULL) {
188
+ break;
189
+ }
190
+
191
+ timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
192
+
193
+ rv = poll(state->fds, state->nfds, timeout);
194
+ if (rv < 0) {
195
+ continue;
196
+ } else if (rv == 0) {
197
+ /* Process timeouts */
198
+ ares_process_fd(state->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
199
+ continue;
200
+ }
201
+
202
+ for (i=0; i<state->nfds; i++) {
203
+ if (state->fds[i].revents == 0) {
204
+ continue;
205
+ }
206
+
207
+ /* Notify about read/write events per FD */
208
+ ares_process_fd(state->channel,
209
+ (state->fds[i].revents & (POLLERR|POLLHUP|POLLIN))?
210
+ state->fds[i].fd:ARES_SOCKET_BAD,
211
+ (state->fds[i].revents & POLLOUT)?
212
+ state->fds[i].fd:ARES_SOCKET_BAD);
213
+ }
214
+ }
215
+ }
216
+
217
+ /* Callback that is called when DNS query is finished * /
218
+ static void addrinfo_cb(void * arg, int status, int timeouts,
219
+ struct ares_addrinfo * result)
220
+ {
221
+ (void)arg; /* Example does not use user context * /
222
+ printf("Result: %s, timeouts: %d\n", ares_strerror(status), timeouts);
223
+
224
+ if (result) {
225
+ struct ares_addrinfo_node * node;
226
+ for (node = result->nodes; node != NULL; node = node->ai_next) {
227
+ char addr_buf[ 64] = "";
228
+ const void * ptr = NULL;
229
+ if (node->ai_family == AF_INET) {
230
+ const struct sockaddr_in * in_addr =
231
+ (const struct sockaddr_in * )((void * )node->ai_addr);
232
+ ptr = &in_addr->sin_addr;
233
+ } else if (node->ai_family == AF_INET6) {
234
+ const struct sockaddr_in6 * in_addr =
235
+ (const struct sockaddr_in6 * )((void * )node->ai_addr);
236
+ ptr = &in_addr->sin6_addr;
237
+ } else {
238
+ continue;
239
+ }
240
+ ares_inet_ntop(node->ai_family, ptr, addr_buf, sizeof(addr_buf));
241
+ printf("Addr: %s\n", addr_buf);
242
+ }
243
+ }
244
+ ares_freeaddrinfo(result);
245
+ }
246
+
247
+ int main(int argc, char ** argv)
248
+ {
249
+ dnsstate_t state;
250
+ struct ares_options options;
251
+ int optmask = 0;
252
+ struct ares_addrinfo_hints hints;
253
+
254
+ memset(&state, 0, sizeof(state));
116
255
256
+ if (argc != 2) {
257
+ printf("Usage: %s domain\n", argv[ 0] );
258
+ return 1;
259
+ }
260
+
261
+ /* Initialize library * /
262
+ ares_library_init(ARES_LIB_INIT_ALL);
117
263
264
+ /* Enable sock state callbacks, we should not use ares_fds() or ares_getsock()
265
+ * in modern implementations. * /
266
+ memset(&options, 0, sizeof(options));
267
+ optmask |= ARES_OPT_SOCK_STATE_CB;
268
+ options.sock_state_cb = sock_state_cb;
269
+ options.sock_state_cb_data = &state;
270
+
271
+ /* Initialize channel to run queries, a single channel can accept unlimited
272
+ * queries * /
273
+ if (ares_init_options(&state.channel, &options, optmask) != ARES_SUCCESS) {
274
+ printf("c-ares initialization issue\n");
275
+ return 1;
276
+ }
277
+
278
+ /* Perform an IPv4 and IPv6 request for the provided domain name * /
279
+ memset(&hints, 0, sizeof(hints));
280
+ hints.ai_family = AF_UNSPEC;
281
+ hints.ai_flags = ARES_AI_CANONNAME;
282
+ ares_getaddrinfo(state.channel, argv[ 1] , NULL, &hints, addrinfo_cb,
283
+ NULL /* user context not specified * /);
284
+
285
+ /* Wait until no more requests are left to be processed * /
286
+ process(&state);
287
+
288
+ /* Cleanup * /
289
+ ares_destroy(state.channel);
290
+ free(state.fds);
291
+
292
+ ares_library_cleanup();
293
+ return 0;
294
+ }
295
+ {% endhighlight %}
296
+
297
+ Compilation:
298
+ {% highlight bash %}
299
+ cc -I/usr/local/include -o example_ss example_ss.c -Wl,-rpath /usr/local/lib -lcares
300
+ {% endhighlight %}
0 commit comments