OSDN Git Service

e415adc59623f3bcef5eb55958d0459cd5af07d2
[linuxjm/LDP_man-pages.git] / original / man3 / getaddrinfo_a.3
1 .\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
2 .\" and clean-ups and additions (C) 2010 Michael Kerrisk <mtk.manpages@gmail.com>
3 .\"
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
8 .\"
9 .\" Permission is granted to copy and distribute modified versions of this
10 .\" manual under the conditions for verbatim copying, provided that the
11 .\" entire resulting derived work is distributed under the terms of a
12 .\" permission notice identical to this one.
13 .\"
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
16 .\" responsibility for errors or omissions, or for damages resulting from
17 .\" the use of the information contained herein.  The author(s) may not
18 .\" have taken the same level of care in the production of this manual,
19 .\" which is licensed free of charge, as they might when working
20 .\" professionally.
21 .\"
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" %%%LICENSE_END
25 .\"
26 .\" References: http://people.redhat.com/drepper/asynchnl.pdf,
27 .\"     http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
28 .\"
29 .TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual"
30 .SH NAME
31 getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
32 network address and service translation
33 .SH SYNOPSIS
34 .nf
35 .BR "#define _GNU_SOURCE" "         /* See feature_test_macros(7) */"
36 .B #include <netdb.h>
37 .sp
38 .BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" ,
39 .BI "                int " "nitems" ", struct sigevent *" "sevp" );
40 .sp
41 .BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" ,
42 .BI "                struct timespec *" "timeout" );
43 .sp
44 .BI "int gai_error(struct gaicb *" "req" );
45 .sp
46 .BI "int gai_cancel(struct gaicb *" "req" );
47 .sp
48 Link with \fI\-lanl\fP.
49 .fi
50 .SH DESCRIPTION
51 The
52 .BR getaddrinfo_a ()
53 function performs the same task as
54 .BR getaddrinfo (3),
55 but allows multiple name look-ups to be performed asynchronously,
56 with optional notification on completion of look-up operations.
57
58 The
59 .I mode
60 argument has one of the following values:
61 .TP
62 .B GAI_WAIT
63 Perform the look-ups synchronously.
64 The call blocks until the look-ups have completed.
65 .TP
66 .B GAI_NOWAIT
67 Perform the look-ups asynchronously.
68 The call returns immediately,
69 and the requests are resolved in the background.
70 See the discussion of the
71 .I sevp
72 argument below.
73 .PP
74 The array
75 .I list
76 specifies the look-up requests to process.
77 The
78 .I nitems
79 argument specifies the number of elements in
80 .IR list .
81 The requested look-up operations are started in parallel.
82 NULL elements in
83 .I list
84 are ignored.
85 Each request is described by a
86 .I gaicb
87 structure, defined as follows:
88 .sp
89 .in +4n
90 .nf
91 struct gaicb {
92     const char            *ar_name;
93     const char            *ar_service;
94     const struct addrinfo *ar_request;
95     struct addrinfo       *ar_result;
96 };
97 .fi
98 .in
99
100 The elements of this structure correspond to the arguments of
101 .BR getaddrinfo (3).
102 Thus,
103 .I ar_name
104 corresponds to the
105 .I node
106 argument and
107 .I ar_service
108 to the
109 .I service
110 argument, identifying an Internet host and a service.
111 The
112 .I ar_request
113 element corresponds to the
114 .I hints
115 argument, specifying the criteria for selecting
116 the returned socket address structures.
117 Finally,
118 .I ar_result
119 corresponds to the
120 .I res
121 argument; you do not need to initialize this element,
122 it will be automatically set when the request
123 is resolved.
124 The
125 .I addrinfo
126 structure referenced by the last two elements is described in
127 .BR getaddrinfo (3).
128
129 When
130 .I mode
131 is specified as
132 .BR GAI_NOWAIT ,
133 notifications about resolved requests
134 can be obtained by employing the
135 .I sigevent
136 structure pointed to by the
137 .I sevp
138 argument.
139 For the definition and general details of this structure, see
140 .BR sigevent (7).
141 The
142 .I sevp\->sigev_notify
143 field can have the following values:
144 .TP
145 .BR SIGEV_NONE
146 Don't provide any notification.
147 .TP
148 .BR SIGEV_SIGNAL
149 When a look-up completes, generate the signal
150 .I sigev_signo
151 for the process.
152 See
153 .BR sigevent (7)
154 for general details.
155 The
156 .I si_code
157 field of the
158 .I siginfo_t
159 structure will be set to
160 .BR SI_ASYNCNL .
161 .\" si_pid and si_uid are also set, to the values of the calling process,
162 .\" which doesn't provide useful information, so we'll skip mentioning it.
163 .TP
164 .BR SIGEV_THREAD
165 When a look-up completes, invoke
166 .I sigev_notify_function
167 as if it were the start function of a new thread.
168 See
169 .BR sigevent (7)
170 for details.
171 .PP
172 For
173 .BR SIGEV_SIGNAL
174 and
175 .BR SIGEV_THREAD ,
176 it may be useful to point
177 .IR sevp\->sigev_value.sival_ptr
178 to
179 .IR list .
180
181 The
182 .BR gai_suspend ()
183 function suspends execution of the calling thread,
184 waiting for the completion of one or more requests in the array
185 .IR list .
186 The
187 .I nitems
188 argument specifies the size of the array
189 .IR list .
190 The call blocks until one of the following occurs:
191 .IP * 3
192 One or more of the operations in
193 .I list
194 completes.
195 .IP *
196 The call is interrupted by a signal that is caught.
197 .IP *
198 The time interval specified in
199 .I timeout
200 elapses.
201 This argument specifies a timeout in seconds plus nanoseconds (see
202 .BR nanosleep (2)
203 for details of the
204 .I timespec
205 structure).
206 If
207 .I timeout
208 is NULL, then the call blocks indefinitely
209 (until one of the events above occurs).
210 .PP
211 No explicit indication of which request was completed is given;
212 you must determine which request(s) have completed by iterating with
213 .BR gai_error ()
214 over the list of requests.
215
216 The
217 .BR gai_error ()
218 function returns the status of the request
219 .IR req :
220 either
221 .B EAI_INPROGRESS
222 if the request was not completed yet,
223 0 if it was handled successfully,
224 or an error code if the request could not be resolved.
225
226 The
227 .BR gai_cancel ()
228 function cancels the request
229 .IR req .
230 If the request has been canceled successfully,
231 the error status of the request will be set to
232 .B EAI_CANCELLED
233 and normal asynchronous notification will be performed.
234 The request cannot be canceled if it is currently being processed;
235 in that case, it will be handled as if
236 .BR gai_cancel ()
237 has never been called.
238 If
239 .I req
240 is NULL, an attempt is made to cancel all outstanding requests
241 that the process has made.
242 .SH RETURN VALUE
243 The
244 .BR getaddrinfo_a ()
245 function returns 0 if all of the requests have been enqueued successfully,
246 or one of the following nonzero error codes:
247 .TP
248 .B EAI_AGAIN
249 The resources necessary to enqueue the look-up requests were not available.
250 The application may check the error status of each
251 request to determine which ones failed.
252 .TP
253 .B EAI_MEMORY
254 Out of memory.
255 .TP
256 .B EAI_SYSTEM
257 .I mode
258 is invalid.
259 .PP
260 The
261 .BR gai_suspend ()
262 function returns 0 if at least one of the listed requests has been completed.
263 Otherwise, it returns one of the following nonzero error codes:
264 .TP
265 .B EAI_AGAIN
266 The given timeout expired before any of the requests could be completed.
267 .TP
268 .B EAI_ALLDONE
269 There were no actual requests given to the function.
270 .TP
271 .B EAI_INTR
272 A signal has interrupted the function.
273 Note that this interruption might have been
274 caused by signal notification of some completed look-up request.
275 .PP
276 The
277 .BR gai_error ()
278 function can return
279 .B EAI_INPROGRESS
280 for an unfinished look-up request,
281 0 for a successfully completed look-up
282 (as described above), one of the error codes that could be returned by
283 .BR getaddrinfo (3),
284 or the error code
285 .B EAI_CANCELLED
286 if the request has been canceled explicitly before it could be finished.
287
288 The
289 .BR gai_cancel ()
290 function can return one of these values:
291 .TP
292 .B EAI_CANCELLED
293 The request has been canceled successfully.
294 .TP
295 .B EAI_NOTCANCELLED
296 The request has not been canceled.
297 .TP
298 .B EAI_ALLDONE
299 The request has already completed.
300 .PP
301 The
302 .BR gai_strerror (3)
303 function translates these error codes to a human readable string,
304 suitable for error reporting.
305 .SH CONFORMING TO
306 These functions are GNU extensions;
307 they first appeared in glibc in version 2.2.3.
308 .SH NOTES
309 The interface of
310 .BR getaddrinfo_a ()
311 was modeled after the
312 .BR lio_listio (3)
313 interface.
314 .SH EXAMPLE
315 Two examples are provided: a simple example that resolves
316 several requests in parallel synchronously, and a complex example
317 showing some of the asynchronous capabilities.
318 .SS Synchronous example
319 The program below simply resolves several hostnames in parallel,
320 giving a speed-up compared to resolving the hostnames sequentially using
321 .BR getaddrinfo (3).
322 The program might be used like this:
323 .in +4n
324 .nf
325
326 $ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
327 ftp.us.kernel.org: 128.30.2.36
328 enoent.linuxfoundation.org: Name or service not known
329 gnu.cz: 87.236.197.13
330 .fi
331 .in
332 .PP
333 Here is the program source code
334 .nf
335
336 #define _GNU_SOURCE
337 #include <netdb.h>
338 #include <stdio.h>
339 #include <stdlib.h>
340 #include <string.h>
341
342 int
343 main(int argc, char *argv[])
344 {
345     int i, ret;
346     struct gaicb *reqs[argc \- 1];
347     char host[NI_MAXHOST];
348     struct addrinfo *res;
349
350     if (argc < 2) {
351         fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
352         exit(EXIT_FAILURE);
353     }
354
355     for (i = 0; i < argc \- 1; i++) {
356         reqs[i] = malloc(sizeof(*reqs[0]));
357         if (reqs[i] == NULL) {
358             perror("malloc");
359             exit(EXIT_FAILURE);
360         }
361         memset(reqs[i], 0, sizeof(*reqs[0]));
362         reqs[i]\->ar_name = argv[i + 1];
363     }
364
365     ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
366     if (ret != 0) {
367         fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
368                 gai_strerror(ret));
369         exit(EXIT_FAILURE);
370     }
371
372     for (i = 0; i < argc \- 1; i++) {
373         printf("%s: ", reqs[i]\->ar_name);
374         ret = gai_error(reqs[i]);
375         if (ret == 0) {
376             res = reqs[i]\->ar_result;
377
378             ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
379                     host, sizeof(host),
380                     NULL, 0, NI_NUMERICHOST);
381             if (ret != 0) {
382                 fprintf(stderr, "getnameinfo() failed: %s\\n",
383                         gai_strerror(ret));
384                 exit(EXIT_FAILURE);
385             }
386             puts(host);
387
388         } else {
389             puts(gai_strerror(ret));
390         }
391     }
392     exit(EXIT_SUCCESS);
393 }
394 .fi
395 .SS Asynchronous example
396 This example shows a simple interactive
397 .BR getaddrinfo_a ()
398 front-end.
399 The notification facility is not demonstrated.
400 .PP
401 An example session might look like this:
402 .in +4n
403 .nf
404
405 $ \fB./a.out\fP
406 > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
407 > c 2
408 [2] gnu.cz: Request not canceled
409 > w 0 1
410 [00] ftp.us.kernel.org: Finished
411 > l
412 [00] ftp.us.kernel.org: 216.165.129.139
413 [01] enoent.linuxfoundation.org: Processing request in progress
414 [02] gnu.cz: 87.236.197.13
415 > l
416 [00] ftp.us.kernel.org: 216.165.129.139
417 [01] enoent.linuxfoundation.org: Name or service not known
418 [02] gnu.cz: 87.236.197.13
419 .fi
420 .in
421 .PP
422 The program source is as follows:
423
424 .nf
425 #define _GNU_SOURCE
426 #include <netdb.h>
427 #include <stdio.h>
428 #include <stdlib.h>
429 #include <string.h>
430
431 static struct gaicb **reqs = NULL;
432 static int nreqs = 0;
433
434 static char *
435 getcmd(void)
436 {
437     static char buf[256];
438
439     fputs("> ", stdout); fflush(stdout);
440     if (fgets(buf, sizeof(buf), stdin) == NULL)
441         return NULL;
442
443     if (buf[strlen(buf) \- 1] == \(aq\\n\(aq)
444         buf[strlen(buf) \- 1] = 0;
445
446     return buf;
447 }
448
449 /* Add requests for specified hostnames */
450 static void
451 add_requests(void)
452 {
453     int nreqs_base = nreqs;
454     char *host;
455     int ret;
456
457     while ((host = strtok(NULL, " "))) {
458         nreqs++;
459         reqs = realloc(reqs, nreqs * sizeof(reqs[0]));
460
461         reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
462         reqs[nreqs \- 1]\->ar_name = strdup(host);
463     }
464
465     /* Queue nreqs_base..nreqs requests. */
466
467     ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
468                         nreqs \- nreqs_base, NULL);
469     if (ret) {
470         fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
471                 gai_strerror(ret));
472         exit(EXIT_FAILURE);
473     }
474 }
475
476 /* Wait until at least one of specified requests completes */
477 static void
478 wait_requests(void)
479 {
480     char *id;
481     int i, ret, n;
482     struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
483                 /* NULL elements are ignored by gai_suspend(). */
484
485     while ((id = strtok(NULL, " ")) != NULL) {
486         n = atoi(id);
487
488         if (n >= nreqs) {
489             printf("Bad request number: %s\\n", id);
490             return;
491         }
492
493         wait_reqs[n] = reqs[n];
494     }
495
496     ret = gai_suspend(wait_reqs, nreqs, NULL);
497     if (ret) {
498         printf("gai_suspend(): %s\\n", gai_strerror(ret));
499         return;
500     }
501
502     for (i = 0; i < nreqs; i++) {
503         if (wait_reqs[i] == NULL)
504             continue;
505
506         ret = gai_error(reqs[i]);
507         if (ret == EAI_INPROGRESS)
508             continue;
509
510         printf("[%02d] %s: %s\\n", i, reqs[i]\->ar_name,
511                ret == 0 ? "Finished" : gai_strerror(ret));
512     }
513 }
514
515 /* Cancel specified requests */
516 static void
517 cancel_requests(void)
518 {
519     char *id;
520     int ret, n;
521
522     while ((id = strtok(NULL, " ")) != NULL) {
523         n = atoi(id);
524
525         if (n >= nreqs) {
526             printf("Bad request number: %s\\n", id);
527             return;
528         }
529
530         ret = gai_cancel(reqs[n]);
531         printf("[%s] %s: %s\\n", id, reqs[atoi(id)]\->ar_name,
532                gai_strerror(ret));
533     }
534 }
535
536 /* List all requests */
537 static void
538 list_requests(void)
539 {
540     int i, ret;
541     char host[NI_MAXHOST];
542     struct addrinfo *res;
543
544     for (i = 0; i < nreqs; i++) {
545         printf("[%02d] %s: ", i, reqs[i]\->ar_name);
546         ret = gai_error(reqs[i]);
547
548         if (!ret) {
549             res = reqs[i]\->ar_result;
550
551             ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
552                               host, sizeof(host),
553                               NULL, 0, NI_NUMERICHOST);
554             if (ret) {
555                 fprintf(stderr, "getnameinfo() failed: %s\\n",
556                         gai_strerror(ret));
557                 exit(EXIT_FAILURE);
558             }
559             puts(host);
560         } else {
561             puts(gai_strerror(ret));
562         }
563     }
564 }
565
566 int
567 main(int argc, char *argv[])
568 {
569     char *cmdline;
570     char *cmd;
571
572     while ((cmdline = getcmd()) != NULL) {
573         cmd = strtok(cmdline, " ");
574
575         if (cmd == NULL) {
576             list_requests();
577         } else {
578             switch (cmd[0]) {
579             case \(aqa\(aq:
580                 add_requests();
581                 break;
582             case \(aqw\(aq:
583                 wait_requests();
584                 break;
585             case \(aqc\(aq:
586                 cancel_requests();
587                 break;
588             case \(aql\(aq:
589                 list_requests();
590                 break;
591             default:
592                 fprintf(stderr, "Bad command: %c\\n", cmd[0]);
593                 break;
594             }
595         }
596     }
597     exit(EXIT_SUCCESS);
598 }
599 .fi
600 .SH SEE ALSO
601 .BR getaddrinfo (3),
602 .BR inet (3),
603 .BR lio_listio (3),
604 .BR hostname (7),
605 .BR ip (7),
606 .BR sigevent (7)
607 .SH COLOPHON
608 This page is part of release 3.67 of the Linux
609 .I man-pages
610 project.
611 A description of the project,
612 information about reporting bugs,
613 and the latest version of this page,
614 can be found at
615 \%http://www.kernel.org/doc/man\-pages/.