From a8768e80b11709ee11b70a769f0ea86964988e3b Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 11 Apr 1999 18:13:28 +0000 Subject: [PATCH] adns_pollfds and struct pollfd support - on branch, because it's difficult and I can't be bothered to finish and test it now. --- src/adns.h | 29 ++++++++++++++++ src/event.c | 91 ++++++++++++++++++++++++++++++++++++++++---------- src/internal.h | 1 + 3 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/adns.h b/src/adns.h index a234cda..d3ab7ed 100644 --- a/src/adns.h +++ b/src/adns.h @@ -303,6 +303,35 @@ void adns_interest(adns_state, int *maxfd_io, fd_set *readfds_io, * readfds, writefds, exceptfds and maxfd may not be 0. */ +struct pollfd *adns_pollfds(adns_state, struct pollfd *buf, int *len_io, int *timeout); +/* Like adns_interest, but for use with poll(2). The return value + * will be a pointer to an array of struct pollfd, one for each of + * adns's fds, and *len_io will be set to the number of file + * descriptors. + * + * Each descriptor's entry will have a revents==0, and events will be + * a combination of one or more of POLLIN, POLLOUT and POLLERR. + * + * *timeout will be adjusted to ensure that it is no more than the + * desired timeout (with the usual rule for poll that <0 stands for + * infinity). *timeout may be 0 in which case no timeout information + * will be returned. + * + * If *len_io is nonnegative then adns_pollfds will write to buffer + * provided by the caller in buf. If it is too small then *len_io + * will be updated to say how large it would have needed to be and + * adns_pollfds will fail with ENOSPC. + * + * If *len_io is -1 then buf should be 0, and adns_pollfds will use some + * memory belonging to the adns_state, which may be overwritten on subsequent + * calls. + * + * When you come out of poll(2), you should probably call adns_callback + * with maxfd==-1. + * + * On systems without poll(2) this function will return ENOSYS. + */ + /* Example expected/legal calling sequences: * adns_init * adns_submit 1 diff --git a/src/event.c b/src/event.c index 5041f8c..983e266 100644 --- a/src/event.c +++ b/src/event.c @@ -167,7 +167,79 @@ static void checktimeouts(adns_state ads, struct timeval now, inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); } } -} +} + +static void checkfds(adns_state ads, int *maxfd, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + int avail, struct pollfd *buf, int *count_r) { + int count; + + count= 0; + inter_addfd(ads->udpsocket,maxfd,readfds); + poll_addfd(ads->udpsocket,avail,buf,&count,POLLIN); + + switch (ads->tcpstate) { + case server_disconnected: + break; + case server_connecting: + inter_addfd(ads->tcpsocket,maxfd,writefds); + poll_addfd(ads->tcpsocket,avail,buf,&count,POLLOUT); + break; + case server_ok: + inter_addfd(ads->tcpsocket,maxfd,readfds); + inter_addfd(ads->tcpsocket,maxfd,exceptfds); + if (ads->tcpsend.used) inter_addfd(ads->tcpsocket,maxfd,writefds); + poll_addfd(ads->tcpsocket,avail,buf,&count, + ads->tcpsend.used ? POLLIN|POLLOUT : POLLIN); + break; + default: + abort(); + } +} + +struct pollfd *adns_pollfds(adns_state ads, struct pollfd *buf, + int *len_io, int *timeout_io) { + struct timeval now, tvbuf, *tvp; + int timeout; + + r= gettimeofday(&now,0); + if (r) return 0; + + timeout= *timeout_io; + if (timeout < 0) { + tvtop= 0; + } else { + tvbuf.tv_sec= now.tv_sec + (timeout/1000); + tvbuf.tv_usec= now.tv_usec + (timeout%1000)*1000; + if (tvbuf.tv_sec >= 1000000) { + tvbuf.tv_sec += 1; + tvbuf.tv_usec -= 1000000; + } + tvp= &tvbuf; + } + checktimouts(ads,now,&tvp,&tvbuf); + + if (tvp) { + assert(tvbuf.tv_sectv_sec - now.tv_sec)*1000 + (tvp->tv_usec - now.tv_usec)/1000; + } else { + *timeout_io= -1; + } + + avail= *len_io; + if (avail == -1) { + buf= ads->pollfdsbuf; + avail= 2; + if (!buf) { + buf= ads->pollfdsbuf= malloc(sizeof(struct pollfd)*avail); + if (!buf) return 0; + } + } + checkfds(ads, 0,0,0,0, avail,buf,len_io); + if (*len_io > avail) { errno= ENOSPC; return 0; } + + return buf; +} void adns_interest(adns_state ads, int *maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, @@ -187,23 +259,8 @@ void adns_interest(adns_state ads, int *maxfd, } else { checktimeouts(ads,now,tv_io,tvbuf); } - - inter_addfd(maxfd,readfds,ads->udpsocket); - switch (ads->tcpstate) { - case server_disconnected: - break; - case server_connecting: - inter_addfd(maxfd,writefds,ads->tcpsocket); - break; - case server_ok: - inter_addfd(maxfd,readfds,ads->tcpsocket); - inter_addfd(maxfd,exceptfds,ads->tcpsocket); - if (ads->tcpsend.used) inter_addfd(maxfd,writefds,ads->tcpsocket); - break; - default: - abort(); - } + checkfds(ads, maxfd,readfds,writefds,exceptfds, 0,0,0); } /* Callback procedures - these do the real work of reception and timeout, etc. */ diff --git a/src/internal.h b/src/internal.h index 5e59a12..94b8b20 100644 --- a/src/internal.h +++ b/src/internal.h @@ -249,6 +249,7 @@ struct adns__state { int nservers, nsortlist, tcpserver; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; struct timeval tcptimeout; + struct pollfd *pollfdsbuf; /* fixme: init and cleanup */ struct server { struct in_addr addr; } servers[MAXSERVERS]; -- 2.30.2