aboutsummaryrefslogtreecommitdiffstats
path: root/man3/gai_error.3
diff options
context:
space:
mode:
authorPetr Baudis <pasky@suse.cz>2010-09-27 07:45:28 +0200
committerMichael Kerrisk <mtk.manpages@gmail.com>2010-09-27 07:52:54 +0200
commitb5ae78a107cdee34bd8387c51eab8e538b86c16c (patch)
tree63c1432b209616b8aa2daca36852ca3201f62ce7 /man3/gai_error.3
parent0f848cbcde20faeecdc86d597df8412c08111859 (diff)
downloadman-pages-b5ae78a107cdee34bd8387c51eab8e538b86c16c.tar.gz
gai_cancel.3, gai_error.3, gai_suspend.3: New links to new getaddrinfo_a.3 page
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Diffstat (limited to 'man3/gai_error.3')
-rw-r--r--man3/gai_error.3606
1 files changed, 606 insertions, 0 deletions
diff --git a/man3/gai_error.3 b/man3/gai_error.3
new file mode 100644
index 0000000000..b39fd07ebe
--- /dev/null
+++ b/man3/gai_error.3
@@ -0,0 +1,606 @@
+.\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
+.\" and clean-ups and additions (C) 2010 Michael Kerrisk <mtk.manpages@gmail.com>
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.\" References: http://people.redhat.com/drepper/asynchnl.pdf,
+.\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
+.\"
+.TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual"
+.SH NAME
+getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
+network address and service translation
+.SH SYNOPSIS
+.nf
+.B #define _GNU_SOURCE
+.B #include <netdb.h>
+.sp
+.BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" ,
+.BI " int " "nitems" ", struct sigevent *" "sevp" );
+.sp
+.BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" ,
+.BI " struct timespec *" "timeout" );
+.sp
+.BI "int gai_error(struct gaicb *" "req" );
+.sp
+.BI "int gai_cancel(struct gaicb *" "req" );
+.sp
+Link with \fI\-lanl\fP.
+.fi
+.SH DESCRIPTION
+The
+.BR getaddrinfo_a ()
+function performs the same task as
+.BR getaddrinfo (3),
+but allows multiple name look-ups to be performed asynchronously,
+with optional notification on completion of look-up operations.
+
+The
+.I mode
+argument has one of the following values:
+.TP
+.B GAI_WAIT
+Perform the look-ups synchronously;
+the call blocks until the look-ups have completed.
+.TP
+.B GAI_NOWAIT
+Perform the look-ups asynchronously.
+The call returns immediately,
+and the requests are resolved in the background.
+See the discussion of the
+.I sevp
+argument below.
+.PP
+The array
+.I list
+specifies the look-up requests to process.
+The
+.I nitems
+argument specifies the number of elements in
+.IR list .
+The requested look-up operations are started in parallel.
+NULL elements in
+.I list
+are ignored.
+Each request is described by a
+.I gaicb
+structure, defined as follows:
+.sp
+.in +4n
+.nf
+struct gaicb {
+ const char *ar_name;
+ const char *ar_service;
+ const struct addrinfo *ar_request;
+ struct addrinfo *ar_result;
+};
+.fi
+.in
+
+The elements of this structure correspond to the arguments of
+.BR getaddrinfo (3).
+Thus,
+.I ar_name
+corresponds to the
+.I node
+argument and
+.I ar_service
+to the
+.I service
+argument, identifying an Internet host and a service.
+The
+.I ar_request
+element corresponds to the
+.I hints
+argument, specifying the criteria for selecting
+the returned socket address structures.
+Finally,
+.I ar_result
+corresponds to the
+.I res
+argument; you do not need to initialize this element,
+it will be automatically set when the request
+is resolved.
+The
+.I addrinfo
+structure referenced by the last two elements is described in
+.BR getaddrinfo (3).
+
+When
+.I mode
+is specified as
+.BR GAI_NOWAIT,
+notifications about resolved requests
+can be obtained by employing the
+.I sigevent
+structure pointed to by the
+.I sevp
+argument.
+For the definition and general details of this structure, see
+.BR sigevent (7).
+The
+.I sevp\->sigev_notify
+field can have the following values:
+.TP
+.BR SIGEV_NONE
+Don't provide any notification.
+.TP
+.BR SIGEV_SIGNAL
+When a look-up completes, generate the signal
+.I sigev_signo
+for the process.
+See
+.BR sigevent (7)
+for general details.
+The
+.I si_code
+field of the
+.I siginfo_t
+structure will be set to
+.BR SI_ASYNCNL .
+.\" si_pid and si_uid are also set, to the values of the calling process,
+.\" which doesn't provide useful information, so we'll skip mentioning it.
+.TP
+.BR SIGEV_THREAD
+When a look-up completes, invoke
+.I sigev_notify_function
+as if it were the start function of a new thread.
+See
+.BR sigevent (7)
+for details.
+.PP
+For
+.BR SIGEV_SIGNAL
+and
+.BR SIGEV_THREAD ,
+it may be useful to point
+.IR sevp\->sigev_value.sival_ptr
+to
+.IR list .
+
+The
+.BR gai_suspend ()
+function suspends execution of the calling thread,
+waiting for the completion of one or more requests in the array
+.ID list .
+The
+.I nitems
+argument specifies the size of the array
+.IR list .
+The call blocks until one of the following occurs:
+.IP * 3
+One or more of the operations in
+.I list
+completes.
+.IP *
+The call is interrupted by a signal that is caught.
+.IP *
+The time interval specified in
+.I timeout
+elapses.
+This argument specifies a timeout in seconds plus nanoseconds (see
+.BR nanosleep (2)
+for details of the
+.I timespec
+structure).
+If
+.I timeout
+is NULL, then the call blocks indefinitely
+(until one of the events above occurs).
+.PP
+No explicit indication of which request was completed is given;
+you must determine which request(s) have completed by iterating with
+.BR gai_error ()
+over the list of requests.
+
+The
+.BR gai_error ()
+function returns the status of the request
+.IR req :
+either
+.B EAI_INPROGRESS
+if the request was not completed yet,
+0 if it was handled successfully,
+or an error code if the request could not be resolved.
+
+The
+.BR gai_cancel ()
+function cancels the request
+.IR req .
+If the request has been canceled successfully,
+the error status of the request will be set to
+.B EAI_CANCELLED
+and normal asynchronous notification will be performed.
+The request cannot be canceled if it is currently being processed;
+in that case, it will be handled as if
+.BR gai_cancel ()
+has never been called.
+If
+.I req
+is NULL, an attempt is made to cancel all outstanding requests
+that the process has made.
+.SH "RETURN VALUE"
+The
+.BR getaddrinfo_a ()
+function returns 0 if all of the requests have been enqueued successfully,
+or one of the following nonzero error codes:
+.TP
+.B EAI_AGAIN
+The resources necessary to enqueue the look-up requests were not available.
+The application may check the error status of each
+request to determine which ones failed.
+.TP
+.B EAI_MEMORY
+Out of memory.
+.TP
+.B EAI_SYSTEM
+.I mode
+is invalid.
+.PP
+The
+.BR gai_suspend ()
+function returns 0 if at least one of the listed requests has been completed.
+Otherwise, it returns one of the following nonzero error codes:
+.TP
+.B EAI_AGAIN
+The given timeout expired before any of the requests could be completed.
+.TP
+.B EAI_ALLDONE
+There were no actual requests given to the function.
+.TP
+.B EAI_INTR
+A signal has interrupted the function.
+Note that this interruption might have been
+caused by signal notification of some completed look-up request.
+.PP
+The
+.BR gai_error ()
+function can return
+.B EAI_INPROGRESS
+for an unfinished look-up request,
+0 for a successfully completed look-up
+(as described above), one of the error codes that could be returned by
+.BR getaddrinfo (3),
+or the error code
+.B EAI_CANCELLED
+if the request has been canceled explicitly before it could be finished.
+
+The
+.BR gai_cancel ()
+function can return one of these values:
+.TP
+.B EAI_CANCELLED
+The request has been canceled successfully.
+.TP
+.B EAI_NOTCANCELLED
+The request has not been canceled.
+.TP
+.B EAI_ALLDONE
+The request has already completed.
+.PP
+The
+.BR gai_strerror (3)
+function translates these error codes to a human readable string,
+suitable for error reporting.
+.SH "CONFORMING TO"
+These functions are GNU extensions;
+they first appeared in glibc in version 2.2.3.
+.SH NOTES
+The interface of
+.BR getaddrinfo_a ()
+was modeled after the
+.BR lio_listio (3)
+interface.
+.SH EXAMPLE
+Two examples are provided: a simple example that resolves
+several requests in parallel synchronously, and a complex example
+showing some of the asynchronous capabilities.
+.SS Synchronous Example
+The program below simply resolves several hostnames in parallel,
+giving a speed-up compared to resolving the hostnames sequentially using
+.BR getaddrinfo (3).
+The program might be used like this:
+.in +4n
+.nf
+
+$ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
+ftp.us.kernel.org: 128.30.2.36
+enoent.linuxfoundation.org: Name or service not known
+gnu.cz: 87.236.197.13
+.fi
+.in
+.PP
+Here is the program source code
+.nf
+
+#define _GNU_SOURCE
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char *argv[])
+{
+ int i, ret;
+ struct gaicb *reqs[argc \- 1];
+ char host[NI_MAXHOST];
+ struct addrinfo *res;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < argc \- 1; i++) {
+ reqs[i] = malloc(sizeof(*reqs[0]));
+ if (reqs[i] == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ memset(reqs[i], 0, sizeof(*reqs[0]));
+ reqs[i]\->ar_name = argv[i + 1];
+ }
+
+ ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
+ if (ret != 0) {
+ fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
+ gai_strerror(ret));
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < argc \- 1; i++) {
+ printf("%s: ", reqs[i]\->ar_name);
+ ret = gai_error(reqs[i]);
+ if (ret == 0) {
+ res = reqs[i]\->ar_result;
+
+ ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
+ host, sizeof(host),
+ NULL, 0, NI_NUMERICHOST);
+ if (ret != 0) {
+ fprintf(stderr, "getnameinfo() failed: %s\\n",
+ gai_strerror(ret));
+ exit(EXIT_FAILURE);
+ }
+ puts(host);
+
+ } else {
+ puts(gai_strerror(ret));
+ }
+ }
+ exit(EXIT_SUCCESS);
+}
+.fi
+
+.SS Asynchronous Example
+This example shows a simple interactive
+.BR getaddrinfo_a ()
+front-end.
+The notification facility is not demonstrated.
+.PP
+An example session might look like like this:
+.in +4n
+.nf
+
+$ \fB./a.out\fP
+> a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
+> c 2
+[2] gnu.cz: Request not canceled
+> w 0 1
+[00] ftp.us.kernel.org: Finished
+> l
+[00] ftp.us.kernel.org: 216.165.129.139
+[01] enoent.linuxfoundation.org: Processing request in progress
+[02] gnu.cz: 87.236.197.13
+> l
+[00] ftp.us.kernel.org: 216.165.129.139
+[01] enoent.linuxfoundation.org: Name or service not known
+[02] gnu.cz: 87.236.197.13
+.fi
+.in
+.PP
+The program source goes as follows:
+
+\&
+.nf
+#define _GNU_SOURCE
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct gaicb **reqs = NULL;
+static int nreqs = 0;
+
+static char *
+getcmd(void)
+{
+ static char buf[256];
+
+ fputs("> ", stdout); fflush(stdout);
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ return NULL;
+
+ if (buf[strlen(buf) \- 1] == \(aq\\n\(aq)
+ buf[strlen(buf) \- 1] = 0;
+
+ return buf;
+}
+
+/* Add requests for specified hostnames */
+static void
+add_requests(void)
+{
+ int nreqs_base = nreqs;
+ char *host;
+ int ret;
+
+ while ((host = strtok(NULL, " "))) {
+ nreqs++;
+ reqs = realloc(reqs, nreqs * sizeof(reqs[0]));
+
+ reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
+ reqs[nreqs \- 1]\->ar_name = strdup(host);
+ }
+
+ /* Queue nreqs_base..nreqs requests. */
+
+ ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
+ nreqs \- nreqs_base, NULL);
+ if (ret) {
+ fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
+ gai_strerror(ret));
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* Wait until at least one of specified requests completes */
+static void
+wait_requests(void)
+{
+ char *id;
+ int i, ret, n;
+ struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
+ /* NULL elements are ignored by gai_suspend(). */
+
+ while ((id = strtok(NULL, " ")) != NULL) {
+ n = atoi(id);
+
+ if (n >= nreqs) {
+ printf("Bad request number: %s\\n", id);
+ return;
+ }
+
+ wait_reqs[n] = reqs[n];
+ }
+
+ ret = gai_suspend(wait_reqs, nreqs, NULL);
+ if (ret) {
+ printf("gai_suspend(): %s\\n", gai_strerror(ret));
+ return;
+ }
+
+ for (i = 0; i < nreqs; i++) {
+ if (wait_reqs[i] == NULL)
+ continue;
+
+ ret = gai_error(reqs[i]);
+ if (ret == EAI_INPROGRESS)
+ continue;
+
+ printf("[%02d] %s: %s\\n", i, reqs[i]\->ar_name,
+ ret == 0 ? "Finished" : gai_strerror(ret));
+ }
+}
+
+/* Cancel specified requests */
+static void
+cancel_requests(void)
+{
+ char *id;
+ int ret, n;
+
+ while ((id = strtok(NULL, " ")) != NULL) {
+ n = atoi(id);
+
+ if (n >= nreqs) {
+ printf("Bad request number: %s\\n", id);
+ return;
+ }
+
+ ret = gai_cancel(reqs[n]);
+ printf("[%s] %s: %s\\n", id, reqs[atoi(id)]\->ar_name,
+ gai_strerror(ret));
+ }
+}
+
+/* List all requests */
+static void
+list_requests(void)
+{
+ int i, ret;
+ char host[NI_MAXHOST];
+ struct addrinfo *res;
+
+ for (i = 0; i < nreqs; i++) {
+ printf("[%02d] %s: ", i, reqs[i]\->ar_name);
+ ret = gai_error(reqs[i]);
+
+ if (!ret) {
+ res = reqs[i]\->ar_result;
+
+ ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
+ host, sizeof(host),
+ NULL, 0, NI_NUMERICHOST);
+ if (ret) {
+ fprintf(stderr, "getnameinfo() failed: %s\\n",
+ gai_strerror(ret));
+ exit(EXIT_FAILURE);
+ }
+ puts(host);
+ } else {
+ puts(gai_strerror(ret));
+ }
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *cmdline;
+ char *cmd;
+
+ while ((cmdline = getcmd()) != NULL) {
+ cmd = strtok(cmdline, " ");
+
+ if (cmd == NULL) {
+ list_requests();
+ } else {
+ switch (cmd[0]) {
+ case \(aqa\(aq:
+ add_requests();
+ break;
+ case \(aqw\(aq:
+ wait_requests();
+ break;
+ case \(aqc\(aq:
+ cancel_requests();
+ break;
+ case \(aql\(aq:
+ list_requests();
+ break;
+ default:
+ fprintf(stderr, "Bad command: %c\\n", cmd[0]);
+ break;
+ }
+ }
+ }
+ exit(EXIT_SUCCESS);
+}
+.fi
+.SH "SEE ALSO"
+.BR getaddrinfo (3),
+.BR inet (3),
+.BR lio_listio (3),
+.BR hostname (7),
+.BR ip (7),
+.BR sigevent (7)