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.
This commit is contained in:
Родитель
b6820b2674
Коммит
670273968c
10
ares/CHANGES
10
ares/CHANGES
|
@ -1,6 +1,16 @@
|
|||
Changelog for the c-ares project
|
||||
|
||||
* May 30 2007
|
||||
|
||||
- Daniel S 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.
|
||||
|
||||
* May 25 2007
|
||||
|
||||
- Ravi Pratap fixed a flaw in the init_by_resolv_conf() function for windows
|
||||
that could cause it to return a bad return code.
|
||||
|
||||
|
|
18
ares/ares.h
18
ares/ares.h
|
@ -136,6 +136,22 @@ extern "C" {
|
|||
#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,
|
||||
|
@ -200,6 +216,8 @@ 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);
|
||||
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);
|
||||
|
|
|
@ -24,16 +24,16 @@ ares_process \- Process events for name resolution
|
|||
.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
|
||||
|
@ -44,6 +44,11 @@ The
|
|||
.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:
|
||||
|
|
|
@ -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;
|
||||
|
|
14
ares/setup.h
14
ares/setup.h
|
@ -3,7 +3,7 @@
|
|||
|
||||
/* $Id$ */
|
||||
|
||||
/* Copyright (C) 2004 - 2005 by Daniel Stenberg et al
|
||||
/* Copyright (C) 2004 - 2007 by Daniel Stenberg et al
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted, provided
|
||||
|
@ -117,18 +117,6 @@
|
|||
#undef VERSION
|
||||
#undef PACKAGE
|
||||
|
||||
/*
|
||||
* Typedef our socket type
|
||||
*/
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
typedef SOCKET ares_socket_t;
|
||||
#define ARES_SOCKET_BAD INVALID_SOCKET
|
||||
#else
|
||||
typedef int ares_socket_t;
|
||||
#define ARES_SOCKET_BAD -1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assume a few thing unless they're set by configure
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче