summaryrefslogtreecommitdiffstats
path: root/libasyncns
diff options
context:
space:
mode:
Diffstat (limited to 'libasyncns')
-rw-r--r--libasyncns/asyncns-test.c56
-rw-r--r--libasyncns/asyncns.c80
-rw-r--r--libasyncns/asyncns.h94
3 files changed, 188 insertions, 42 deletions
diff --git a/libasyncns/asyncns-test.c b/libasyncns/asyncns-test.c
index 18f5aaf..6eb0a0d 100644
--- a/libasyncns/asyncns-test.c
+++ b/libasyncns/asyncns-test.c
@@ -1,3 +1,24 @@
+/* $Id$ */
+
+/***
+ This file is part of libasyncns.
+
+ libasyncns is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ libasyncns is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with libasyncns; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -14,31 +35,39 @@ int main(int argc, char *argv[]) {
struct sockaddr_in sa;
char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
if (!(asyncns = asyncns_new(5))) {
fprintf(stderr, "asyncns_new() failed\n");
goto fail;
}
+ /* Make a name -> address query */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ q1 = asyncns_getaddrinfo(asyncns, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);
+
+
+ /* Make an address -> name query */
+
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = inet_addr("192.168.50.1");
+ sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
sa.sin_port = htons(80);
- q1 = asyncns_getaddrinfo(asyncns, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);
q2 = asyncns_getnameinfo(asyncns, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1);
+
+ /* Wait until the two queries are completed */
+
while (!asyncns_isdone(asyncns, q1) || !asyncns_isdone(asyncns, q2)) {
if (asyncns_wait(asyncns, 1) < 0)
goto fail;
}
- ret = asyncns_getaddrinfo_done(asyncns, q1, &ai);
-
- if (ret)
+ /* Interpret the result of the name -> addr query */
+ if ((ret = asyncns_getaddrinfo_done(asyncns, q1, &ai)))
fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
else {
struct addrinfo *i;
@@ -58,14 +87,11 @@ int main(int argc, char *argv[]) {
asyncns_freeaddrinfo(ai);
}
- ret = asyncns_getnameinfo_done(asyncns, q2, host, sizeof(host), serv, sizeof(serv));
-
- if (ret)
+ /* Interpret the result of the addr -> name query */
+ if ((ret = asyncns_getnameinfo_done(asyncns, q2, host, sizeof(host), serv, sizeof(serv))))
fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
- else {
+ else
printf("%s -- %s\n", host, serv);
- }
-
r = 0;
diff --git a/libasyncns/asyncns.c b/libasyncns/asyncns.c
index 409de2c..fd74133 100644
--- a/libasyncns/asyncns.c
+++ b/libasyncns/asyncns.c
@@ -1,5 +1,27 @@
-#define HAVE_PR_SET_PDEATHSIG
-#define HAVE_SETRESUID
+/* $Id$ */
+
+/***
+ This file is part of libasyncns.
+
+ libasyncns is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ libasyncns is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with libasyncns; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <assert.h>
#include <fcntl.h>
@@ -14,7 +36,7 @@
#include <sys/types.h>
#include <pwd.h>
-#ifdef HAVE_PR_SET_PDEATHSIG
+#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
@@ -143,9 +165,9 @@ static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *leng
}
static int send_addrinfo_reply(int out_fd, unsigned id, int ret, struct addrinfo *ai) {
- assert(out_fd >= 0);
uint8_t data[BUFSIZE];
addrinfo_response_t *resp = (addrinfo_response_t*) data;
+ assert(out_fd >= 0);
resp->header.type = RESPONSE_ADDRINFO;
resp->header.id = id;
@@ -165,11 +187,12 @@ static int send_addrinfo_reply(int out_fd, unsigned id, int ret, struct addrinfo
}
static int send_nameinfo_reply(int out_fd, unsigned id, int ret, const char *host, const char *serv) {
- assert(out_fd >= 0);
uint8_t data[BUFSIZE];
size_t hl, sl;
nameinfo_response_t *resp = (nameinfo_response_t*) data;
+ assert(out_fd >= 0);
+
sl = serv ? strlen(serv)+1 : 0;
hl = host ? strlen(host)+1 : 0;
@@ -257,6 +280,7 @@ static int handle_request(int out_fd, const rheader_t *req, size_t length) {
static int worker(int in_fd, int out_fd) {
int r = 0;
+ int have_death_sig = 0;
assert(in_fd > 2);
assert(out_fd > 2);
@@ -293,29 +317,31 @@ static int worker(int in_fd, int out_fd) {
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
-#ifdef HAVE_PR_SET_PDEATHSIG
- prctl(PR_SET_PDEATHSIG, SIGTERM);
-#else
- fd_nonblock(in_fd);
+#ifdef PR_SET_PDEATHSIG
+ if (prctl(PR_SET_PDEATHSIG, SIGTERM) >= 0)
+ have_death_sig = 1;
#endif
+
+ if (!have_death_sig)
+ fd_nonblock(in_fd);
- while (getppid() != 1) { /* if the parent PID is 1 our parent process died. */
+ while (getppid() > 1) { /* if the parent PID is 1 our parent process died. */
char buf[BUFSIZE];
ssize_t length;
-#ifndef HAVE_PR_SET_PDEATHSIG
- fd_set fds;
- struct timeval tv = { 0, 500000 } ;
-
- FD_ZERO(&fds);
- FD_SET(in_fd, &fds);
-
- if (select(in_fd+1, &fds, NULL, NULL, &tv) < 0)
- goto fail;
-
- if (getppid() == 1)
- break;
-#endif
+ if (!have_death_sig) {
+ fd_set fds;
+ struct timeval tv = { 0, 500000 } ;
+
+ FD_ZERO(&fds);
+ FD_SET(in_fd, &fds);
+
+ if (select(in_fd+1, &fds, NULL, NULL, &tv) < 0)
+ goto fail;
+
+ if (getppid() == 1)
+ break;
+ }
if ((length = recv(in_fd, buf, sizeof(buf), 0)) <= 0) {
@@ -578,6 +604,7 @@ static int handle_response(asyncns_t *asyncns, rheader_t *resp, size_t length) {
}
int asyncns_wait(asyncns_t *asyncns, int block) {
+ int handled = 0;
assert(asyncns);
for (;;) {
@@ -590,7 +617,7 @@ int asyncns_wait(asyncns_t *asyncns, int block) {
if (errno != EAGAIN)
return -1;
- if (!block)
+ if (!block || handled)
return 0;
FD_ZERO(&fds);
@@ -603,7 +630,10 @@ int asyncns_wait(asyncns_t *asyncns, int block) {
}
- return handle_response(asyncns, (rheader_t*) buf, (size_t) l);
+ if (handle_response(asyncns, (rheader_t*) buf, (size_t) l) < 0)
+ return -1;
+
+ handled = 1;
}
}
diff --git a/libasyncns/asyncns.h b/libasyncns/asyncns.h
index 28c70d1..6efcccc 100644
--- a/libasyncns/asyncns.h
+++ b/libasyncns/asyncns.h
@@ -1,37 +1,127 @@
#ifndef fooasyncnshfoo
#define fooasyncnshfoo
+/* $Id$ */
+
+/***
+ This file is part of libasyncns.
+
+ libasyncns is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ libasyncns is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with libasyncns; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
-struct asyncns;
+/** \mainpage
+ *
+ * \section moo Method of operation
+ *
+ * To use libasyncns allocate an asyncns_t object with
+ * asyncns_new(). This will spawn a number of worker processes which
+ * are subsequently used to process the queries the controlling
+ * program issues via asyncns_getaddrinfo() and
+ * asyncns_getnameinfo(). Use asyncns_free() to shut down the worker
+ * processes.
+ *
+ * Since libasyncns forks off new processes you have to make sure that
+ * your program is not irritated by spurious SIGCHLD signals.
+ */
+
+/** \example asyncns-test.c
+ * An example program */
+
+/** An opaque libasyncns session structure */
typedef struct asyncns asyncns_t;
-struct asyncns_query;
+/** An opaque libasyncns query structure */
typedef struct asyncns_query asyncns_query_t;
+/** Allocate a new libasyncns session with n_proc worker processes */
asyncns_t* asyncns_new(int n_proc);
+
+/** Free a libasyncns session. This destroys all attached
+ * asyncns_query_t objects automatically */
void asyncns_free(asyncns_t *asyncns);
+
+/** Return the UNIX file descriptor to select() for readability
+ * on. Use this function to integrate libasyncns with your custom main
+ * loop. */
int asyncns_fd(asyncns_t *asyncns);
+
+/** Process pending responses. If block is non-zero wait until at
+ * least one response has been processed. If block is zero, process
+ * all pending responses and return. */
int asyncns_wait(asyncns_t *asyncns, int block);
+/** Issue a name to address query on the specified session. The
+ * arguments are compatible with the ones of libc's
+ * getaddrinfo(3). The function returns a new query object. When the
+ * query is completed you may retrieve the results using
+ * asyncns_getaddrinfo_done().*/
asyncns_query_t* asyncns_getaddrinfo(asyncns_t *asyncns, const char *node, const char *service, const struct addrinfo *hints);
+
+/** Retrieve the results of a preceding asyncns_getaddrinfo()
+ * call. Returns a addrinfo structure and a return value compatible
+ * with libc's getaddrinfo(3). The query object q is destroyed by this
+ * call and may not be used any further. Make sure to free the
+ * returned addrinfo structure with asyncns_freeaddrinfo() and not
+ * libc's freeaddrinfo(3)! If the query is not completed yet EAI_AGAIN
+ * is returned.*/
int asyncns_getaddrinfo_done(asyncns_t *asyncns, asyncns_query_t* q, struct addrinfo **ret_res);
+/** Issue an address to name query on the specified session. The
+arguments are compatible with the ones of libc's getnameinfo(3). The
+function returns a new query object. When the query is completed you
+may retrieve the results using asyncns_getnameinfo_done(). Set gethost
+(resp. getserv) to non-zero if you want to query the hostname
+(resp. the service name). */
asyncns_query_t* asyncns_getnameinfo(asyncns_t *asyncns, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv);
+
+/** Retrieve the results of a preceding asyncns_getnameinfo)(
+ * call. Returns the hostname and the service name in ret_host and
+ * ret_serv. The query object q is destroyed by this call and may not
+ * be used any further. If the query is not completed yet EAI_AGAIN is
+ * returned. */
int asyncns_getnameinfo_done(asyncns_t *asyncns, asyncns_query_t* q, char *ret_host, size_t hostlen, char *ret_serv, size_t servlen);
+/** Return the next completed query object. If no query has been completed yet, return NULL */
asyncns_query_t* asyncns_getnext(asyncns_t *asyncns);
+
+/** Return the number of query objects (completed or not) attached to this session */
int asyncns_getnqueries(asyncns_t *asyncns);
+/** Cancel a currently running query. q is is destroyed by this call
+ * and may not be used any futher. */
void asyncns_cancel(asyncns_t *asyncns, asyncns_query_t* q);
+/** Free the addrinfo structure as returned by
+asyncns_getaddrinfo_done(). Make sure to use this functions instead of
+the libc's freeaddrinfo()! */
void asyncns_freeaddrinfo(struct addrinfo *ai);
+/** Returns non-zero when the query operation specified by q has been completed */
int asyncns_isdone(asyncns_t *asyncns, asyncns_query_t*q);
+/** Assign some opaque userdata with a query object */
void asyncns_setuserdata(asyncns_t *asyncns, asyncns_query_t *q, void *userdata);
+
+/** Return userdata assigned to a query object. Use
+ * asyncns_setuserdata() to set this data. If no data has been set
+ * prior to this call it returns NULL. */
void* asyncns_getuserdata(asyncns_t *asyncns, asyncns_query_t *q);
#endif