summaryrefslogtreecommitdiff
path: root/ares_process.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-05-30 12:58:47 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-05-30 12:58:47 +0000
commit8c35c65fc7c746d5803a48151e82e0435c20a84c (patch)
tree1292033b628847625ec96fbf2f431cc1c2c8895e /ares_process.c
parent557aad7b0271e96ab76a9eaf59dab3f52289ba0e (diff)
downloadc-ares-8c35c65fc7c746d5803a48151e82e0435c20a84c.tar.gz
c-ares-8c35c65fc7c746d5803a48151e82e0435c20a84c.tar.bz2
c-ares-8c35c65fc7c746d5803a48151e82e0435c20a84c.zip
added ares_process_fd() to allow applications to ask for processing on
specific sockets and thus avoiding select() and associated functions/macros. This function will be used by upcoming libcurl releases for this very reason. It also made me export the ares_socket_t type in the public ares.h header file, since ares_process_fd() uses that type for two of the arguments.
Diffstat (limited to 'ares_process.c')
-rw-r--r--ares_process.c92
1 files changed, 76 insertions, 16 deletions
diff --git a/ares_process.c b/ares_process.c
index 8cb51c3..efc462a 100644
--- a/ares_process.c
+++ b/ares_process.c
@@ -56,10 +56,11 @@
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);
@@ -80,12 +81,30 @@ void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
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
@@ -114,7 +133,10 @@ static int try_again(int errnum)
/* 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;
@@ -124,14 +146,27 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
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)
@@ -218,20 +253,33 @@ static void write_tcp_data(ares_channel channel, fd_set *write_fds, time_t now)
* 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
@@ -294,22 +342,34 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, time_t now)
/* 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;