#define ARES_GETSOCK_WRITABLE(bits,num) (bits & (1 << ((num) + \
ARES_GETSOCK_MAXNUM)))
+
+/*
+ * Typedef our socket type
+ */
+
+#ifndef ares_socket_typedef
+#ifdef WIN32
+typedef SOCKET ares_socket_t;
+#define ARES_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int ares_socket_t;
+#define ARES_SOCKET_BAD -1
+#endif
+#define ares_socket_typedef
+#endif /* ares_socket_typedef */
+
#ifdef WIN32
typedef void (*ares_sock_state_cb)(void *data,
SOCKET socket,
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);
+void ares_process_fd(ares_channel channel, ares_socket_t read_fd,
+ ares_socket_t write_fd);
int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
int rd, unsigned char **buf, int *buflen);
.B void ares_process(ares_channel \fIchannel\fP, fd_set *\fIread_fds\fP,
.B fd_set *\fIwrite_fds\fP)
.fi
+.PP
+.B void ares_process_fd(ares_channel \fIchannel\fP,
+.B ares_socket_t \fIread_fd\fP,
+.B ares_socket_t \fIwrite_fd\fP)
+.fi
.SH DESCRIPTION
-The
-.B ares_process
-function handles input/output events and timeouts associated with
-queries pending on the name service channel identified by
+The \fBares_process(3)\fP function handles input/output events and timeouts
+associated with queries pending on the name service channel identified by
.IR channel .
-The file descriptor sets pointed to by
-.I read_fds
-and
-.I write_fds
+The file descriptor sets pointed to by \fIread_fds\fP and \fIwrite_fds\fP
should have file descriptors set in them according to whether the file
descriptors specified by \fIares_fds(3)\fP are ready for reading and writing.
(The easiest way to determine this information is to invoke
.B ares_process
function will invoke callbacks for pending queries if they complete
successfully or fail.
+
+\fBares_process_fd(3)\fP works the same way but acts and operates only on the
+specific file descriptors (sockets) you pass in to the function. Use
+ARES_SOCKET_BAD for "no action". This function is of course provided to allow
+users of c-ares to void select() in their applications and within c-ares.
.SS EXAMPLE
The following code fragment waits for all pending queries on a channel
to complete:
static int try_again(int errnum);
static void write_tcp_data(ares_channel channel, fd_set *write_fds,
- time_t now);
-static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now);
+ ares_socket_t write_fd, time_t now);
+static void read_tcp_data(ares_channel channel, fd_set *read_fds,
+ ares_socket_t read_fd, time_t now);
static void read_udp_packets(ares_channel channel, fd_set *read_fds,
- time_t now);
+ ares_socket_t read_fd, time_t now);
static void process_timeouts(ares_channel channel, time_t now);
static void process_answer(ares_channel channel, unsigned char *abuf,
int alen, int whichserver, int tcp, int now);
time_t now;
time(&now);
- write_tcp_data(channel, write_fds, now);
- read_tcp_data(channel, read_fds, now);
- read_udp_packets(channel, read_fds, now);
+ write_tcp_data(channel, write_fds, ARES_SOCKET_BAD, now);
+ read_tcp_data(channel, read_fds, ARES_SOCKET_BAD, now);
+ read_udp_packets(channel, read_fds, ARES_SOCKET_BAD, now);
process_timeouts(channel, now);
}
+/* Something interesting happened on the wire, or there was a timeout.
+ * See what's up and respond accordingly.
+ */
+void ares_process_fd(ares_channel channel,
+ ares_socket_t read_fd, /* use ARES_SOCKET_BAD or valid
+ file descriptors */
+ ares_socket_t write_fd)
+{
+ time_t now;
+
+ time(&now);
+ write_tcp_data(channel, NULL, write_fd, now);
+ read_tcp_data(channel, NULL, read_fd, now);
+ read_udp_packets(channel, NULL, read_fd, now);
+ process_timeouts(channel, now);
+}
+
+
/* Return 1 if the specified error number describes a readiness error, or 0
* otherwise. This is mostly for HP-UX, which could return EAGAIN or
* EWOULDBLOCK. See this man page
/* If any TCP sockets select true for writing, write out queued data
* we have for them.
*/
-static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
+static void write_tcp_data(ares_channel channel,
+ fd_set *write_fds,
+ ares_socket_t write_fd,
+ time_t now)
{
struct server_state *server;
struct send_request *sendreq;
ssize_t wcount;
size_t n;
+ if(!write_fds && (write_fd == ARES_SOCKET_BAD))
+ /* no possible action */
+ return;
+
for (i = 0; i < channel->nservers; i++)
{
- /* Make sure server has data to send and is selected in write_fds. */
+ /* Make sure server has data to send and is selected in write_fds or
+ write_fd. */
server = &channel->servers[i];
- if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD
- || !FD_ISSET(server->tcp_socket, write_fds))
+ if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD)
continue;
+ if(write_fds) {
+ if(!FD_ISSET(server->tcp_socket, write_fds))
+ continue;
+ }
+ else {
+ if(server->tcp_socket != write_fd)
+ continue;
+ }
+
/* Count the number of send queue items. */
n = 0;
for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
* allocate a buffer if we finish reading the length word, and process
* a packet if we finish reading one.
*/
-static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
+static void read_tcp_data(ares_channel channel, fd_set *read_fds,
+ ares_socket_t read_fd, time_t now)
{
struct server_state *server;
int i;
ssize_t count;
+ if(!read_fds && (read_fd == ARES_SOCKET_BAD))
+ /* no possible action */
+ return;
+
for (i = 0; i < channel->nservers; i++)
{
/* Make sure the server has a socket and is selected in read_fds. */
server = &channel->servers[i];
- if (server->tcp_socket == ARES_SOCKET_BAD ||
- !FD_ISSET(server->tcp_socket, read_fds))
+ if (server->tcp_socket == ARES_SOCKET_BAD)
continue;
+ if(read_fds) {
+ if(!FD_ISSET(server->tcp_socket, read_fds))
+ continue;
+ }
+ else {
+ if(server->tcp_socket != read_fd)
+ continue;
+ }
+
if (server->tcp_lenbuf_pos != 2)
{
/* We haven't yet read a length word, so read that (or
/* If any UDP sockets select true for reading, process them. */
static void read_udp_packets(ares_channel channel, fd_set *read_fds,
- time_t now)
+ ares_socket_t read_fd, time_t now)
{
struct server_state *server;
int i;
ssize_t count;
unsigned char buf[PACKETSZ + 1];
+ if(!read_fds && (read_fd == ARES_SOCKET_BAD))
+ /* no possible action */
+ return;
+
for (i = 0; i < channel->nservers; i++)
{
/* Make sure the server has a socket and is selected in read_fds. */
server = &channel->servers[i];
- if (server->udp_socket == ARES_SOCKET_BAD ||
- !FD_ISSET(server->udp_socket, read_fds))
+ if (server->udp_socket == ARES_SOCKET_BAD)
continue;
+ if(read_fds) {
+ if(!FD_ISSET(server->udp_socket, read_fds))
+ continue;
+ }
+ else {
+ if(server->udp_socket != read_fd)
+ continue;
+ }
+
count = sread(server->udp_socket, buf, sizeof(buf));
if (count == -1 && try_again(SOCKERRNO))
continue;