From e5247ae65d9884c7c454b1cb641b66e2beb047ef Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Dec 2005 15:27:41 +0000 Subject: [PATCH] Added ares_getsock() to extract sockets to wait for action on, without being limited to select(). --- ares/Makefile.inc | 16 +++++----- ares/ares.h | 43 +++++++++++++++------------ ares/ares_getsock.3 | 56 +++++++++++++++++++++++++++++++++++ ares/ares_getsock.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 26 deletions(-) create mode 100644 ares/ares_getsock.3 create mode 100644 ares/ares_getsock.c diff --git a/ares/Makefile.inc b/ares/Makefile.inc index f8d9058b1..c90aae4b7 100644 --- a/ares/Makefile.inc +++ b/ares/Makefile.inc @@ -1,11 +1,11 @@ -CSOURCES = ares_fds.c ares_process.c ares_free_hostent.c ares_query.c \ -ares__close_sockets.c ares_free_string.c ares_search.c ares__get_hostent.c \ -ares_gethostbyaddr.c ares_send.c ares__read_line.c ares_gethostbyname.c \ -ares_strerror.c ares_cancel.c ares_init.c ares_timeout.c ares_destroy.c \ -ares_mkquery.c ares_version.c ares_expand_name.c ares_parse_a_reply.c \ -windows_port.c ares_expand_string.c ares_parse_ptr_reply.c \ -ares_parse_aaaa_reply.c ares_getnameinfo.c inet_net_pton.c bitncmp.c \ -inet_ntop.c +CSOURCES = ares_fds.c ares_getsock.c ares_process.c ares_free_hostent.c \ +ares_query.c ares__close_sockets.c ares_free_string.c ares_search.c \ +ares__get_hostent.c ares_gethostbyaddr.c ares_send.c ares__read_line.c \ +ares_gethostbyname.c ares_strerror.c ares_cancel.c ares_init.c \ +ares_timeout.c ares_destroy.c ares_mkquery.c ares_version.c \ +ares_expand_name.c ares_parse_a_reply.c windows_port.c \ +ares_expand_string.c ares_parse_ptr_reply.c ares_parse_aaaa_reply.c \ +ares_getnameinfo.c inet_net_pton.c bitncmp.c inet_ntop.c HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h \ nameser.h inet_net_pton.h inet_ntop.h ares_ipv6.h bitncmp.h diff --git a/ares/ares.h b/ares/ares.h index 7f76112f7..8e8da2847 100644 --- a/ares/ares.h +++ b/ares/ares.h @@ -70,8 +70,8 @@ extern "C" { #define ARES_EBADFLAGS 18 /* ares_getaddrinfo error codes */ -#define ARES_ENONAME 19 -#define ARES_EBADHINTS 20 +#define ARES_ENONAME 19 +#define ARES_EBADHINTS 20 /* Flag values */ #define ARES_FLAG_USEVC (1 << 0) @@ -108,27 +108,32 @@ extern "C" { #define ARES_NI_LOOKUPHOST (1 << 8) #define ARES_NI_LOOKUPSERVICE (1 << 9) /* Reserved for future use */ -#define ARES_NI_IDN (1 << 10) -#define ARES_NI_IDN_ALLOW_UNASSIGNED (1 << 11) +#define ARES_NI_IDN (1 << 10) +#define ARES_NI_IDN_ALLOW_UNASSIGNED (1 << 11) #define ARES_NI_IDN_USE_STD3_ASCII_RULES (1 << 12) /* Addrinfo flag values */ -#define ARES_AI_CANONNAME (1 << 0) -#define ARES_AI_NUMERICHOST (1 << 1) -#define ARES_AI_PASSIVE (1 << 2) -#define ARES_AI_NUMERICSERV (1 << 3) -#define ARES_AI_V4MAPPED (1 << 4) -#define ARES_AI_ALL (1 << 5) -#define ARES_AI_ADDRCONFIG (1 << 6) +#define ARES_AI_CANONNAME (1 << 0) +#define ARES_AI_NUMERICHOST (1 << 1) +#define ARES_AI_PASSIVE (1 << 2) +#define ARES_AI_NUMERICSERV (1 << 3) +#define ARES_AI_V4MAPPED (1 << 4) +#define ARES_AI_ALL (1 << 5) +#define ARES_AI_ADDRCONFIG (1 << 6) /* Reserved for future use */ -#define ARES_AI_IDN (1 << 10) -#define ARES_AI_IDN_ALLOW_UNASSIGNED (1 << 11) +#define ARES_AI_IDN (1 << 10) +#define ARES_AI_IDN_ALLOW_UNASSIGNED (1 << 11) #define ARES_AI_IDN_USE_STD3_ASCII_RULES (1 << 12) -#define ARES_AI_CANONIDN (1 << 13) +#define ARES_AI_CANONIDN (1 << 13) -#define ARES_AI_MASK (ARES_AI_CANONNAME|ARES_AI_NUMERICHOST|ARES_AI_PASSIVE| \ - ARES_AI_NUMERICSERV|ARES_AI_V4MAPPED|ARES_AI_ALL| \ - ARES_AI_ADDRCONFIG) +#define ARES_AI_MASK (ARES_AI_CANONNAME|ARES_AI_NUMERICHOST|ARES_AI_PASSIVE| \ + ARES_AI_NUMERICSERV|ARES_AI_V4MAPPED|ARES_AI_ALL| \ + ARES_AI_ADDRCONFIG) +#define ARES_GETSOCK_MAXNUM 16 /* ares_getsock() can return info about this + many sockets */ +#define ARES_GETSOCK_READABLE(bits,num) (bits & (1<< (num))) +#define ARES_GETSOCK_WRITABLE(bits,num) (bits & (1 << ((num) + \ + ARES_GETSOCK_MAXNUM))) struct ares_options { int flags; @@ -172,9 +177,11 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family, void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, int family, ares_host_callback callback, void *arg); void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, - socklen_t salen, int flags, ares_nameinfo_callback callback, + socklen_t salen, int flags, + ares_nameinfo_callback callback, void *arg); int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds); +int ares_getsock(ares_channel channel, int *socks, int numsocks); struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv, struct timeval *tv); void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds); diff --git a/ares/ares_getsock.3 b/ares/ares_getsock.3 new file mode 100644 index 000000000..301d8c244 --- /dev/null +++ b/ares/ares_getsock.3 @@ -0,0 +1,56 @@ +.\" $Id$ +.\" +.\" Copyright 1998 by Daniel Stenberg +.\" +.\" Permission to use, copy, modify, and distribute this +.\" software and its documentation for any purpose and without +.\" fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright +.\" notice and this permission notice appear in supporting +.\" documentation, and that the name of M.I.T. not be used in +.\" advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. +.\" M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" +.\" without express or implied warranty. +.\" +.TH ARES_GETSOCK 3 "22 December 2005" +.SH NAME +ares_getsock \- get file descriptors to wait on +.SH SYNOPSIS +.nf +.B #include +.PP +.B int ares_getsock(ares_channel \fIchannel\fP, int *\fIsocks\fP, +.B int \fInumsocks\fP); +.fi +.SH DESCRIPTION +The +.B ares_getsock +function retrieves the set of file descriptors which the calling +application should wait on for reading and/or writing for the +processing of name service queries pending on the name service channel +identified by +.IR channel . +File descriptors will be set in the integer array pointed to by +\fIsocks\fP. +\fInumsocks\fP is the size of the given array in number of ints. + +This function can only return information about up to 16 sockets. If more are +in use (however unlikely that is), they are simply not reported back. +.SH RETURN VALUES +\fBares_getsock\fP returns a bitmask for what actions to wait for on the +different sockets. The ares.h header file provides these convenience macros to +extract the information appropriately: + +.nf +#define ARES_GETSOCK_MAXNUM 16 /* ares_getsock() can return info about + this many sockets */ +#define ARES_GETSOCK_READABLE(bits,num) (bits & (1<< (num))) +#define ARES_GETSOCK_WRITABLE(bits,num) (bits & (1 << ((num) + \ + ARES_GETSOCK_MAXNUM))) +.fi +.SH SEE ALSO +.BR ares_timeout (3), +.BR ares_fds (3), +.BR ares_process (3) diff --git a/ares/ares_getsock.c b/ares/ares_getsock.c new file mode 100644 index 000000000..3c52a8367 --- /dev/null +++ b/ares/ares_getsock.c @@ -0,0 +1,71 @@ +/* $Id$ */ + +/* Copyright 2005 by Daniel Stenberg. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "setup.h" +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include "ares.h" +#include "ares_private.h" + +int ares_getsock(ares_channel channel, + int *s, + int numsocks) /* size of the 'socks' array */ +{ + struct server_state *server; + ares_socket_t nfds; + int i; + int sockindex=0; + int bitmap = 0; + unsigned int setbits = 0xffffffff; + + ares_socket_t *socks = (ares_socket_t *)s; + + /* No queries, no file descriptors. */ + if (!channel->queries) + return 0; + + nfds = 0; + for (i = 0; i < channel->nservers; i++) + { + server = &channel->servers[i]; + if (server->udp_socket != ARES_SOCKET_BAD) + { + if(sockindex >= numsocks) + break; + socks[sockindex] = server->udp_socket; + bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex); + sockindex++; + } + if (server->tcp_socket != ARES_SOCKET_BAD) + { + if(sockindex >= numsocks) + break; + socks[sockindex] = server->tcp_socket; + bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex); + sockindex++; + + if (server->qhead) { + /* then the tcp socket is also writable! */ + bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex-1); + } + + } + } + return (int)nfds; +}