+static void fd_event(adns_state ads, int fd,
+ int revent, int pollflag,
+ int maxfd, const fd_set *fds,
+ int (*func)(adns_state, int fd, const struct timeval *now),
+ struct timeval now, int *r_r) {
+ int r;
+
+ if (!(revent & pollflag)) return;
+ if (fds && !(fd<maxfd && FD_ISSET(fd,fds))) return;
+ r= func(ads,fd,&now);
+ if (r) {
+ if (r_r) {
+ *r_r= r;
+ } else {
+ adns__diag(ads,-1,0,"process fd failed after select: %s",strerror(errno));
+ adns_globalsystemfailure(ads);
+ }
+ }
+}
+
+void adns__fdevents(adns_state ads,
+ const struct pollfd *pollfds, int npollfds,
+ int maxfd, const fd_set *readfds,
+ const fd_set *writefds, const fd_set *exceptfds,
+ struct timeval now, int *r_r) {
+ int i, fd, revents;
+
+ for (i=0; i<npollfds; i++) {
+ fd= pollfds[i].fd;
+ if (fd >= maxfd) maxfd= fd+1;
+ revents= pollfds[i].revents;
+ fd_event(ads,fd, revents,POLLIN, maxfd,readfds, adns_processreadable,now,r_r);
+ fd_event(ads,fd, revents,POLLOUT, maxfd,writefds, adns_processwriteable,now,r_r);
+ fd_event(ads,fd, revents,POLLPRI, maxfd,exceptfds, adns_processexceptional,now,r_r);
+ }
+}
+
+/* Wrappers for select(2). */
+
+void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io,
+ fd_set *writefds_io, fd_set *exceptfds_io,
+ struct timeval **tv_mod, struct timeval *tv_tobuf,
+ const struct timeval *now) {
+ struct timeval tv_nowbuf;
+ struct pollfd pollfds[MAX_POLLFDS];
+ int i, fd, maxfd, npollfds;
+
+ if (tv_mod && (!*tv_mod || (*tv_mod)->tv_sec || (*tv_mod)->tv_usec)) {
+ /* The caller is planning to sleep. */
+ adns__must_gettimeofday(ads,&now,&tv_nowbuf);
+ if (!now) return;
+ adns__timeouts(ads, 1, tv_mod,tv_tobuf, *now);
+ }
+
+ npollfds= adns__pollfds(ads,pollfds);
+ maxfd= *maxfd_io;
+ for (i=0; i<npollfds; i++) {
+ fd= pollfds[i].fd;
+ if (fd >= maxfd) maxfd= fd+1;
+ if (pollfds[i].events & POLLIN) FD_SET(fd,readfds_io);
+ if (pollfds[i].events & POLLOUT) FD_SET(fd,writefds_io);
+ if (pollfds[i].events & POLLPRI) FD_SET(fd,exceptfds_io);
+ }
+ *maxfd_io= maxfd;
+}
+
+void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds,
+ const fd_set *writefds, const fd_set *exceptfds,
+ const struct timeval *now) {
+ struct pollfd pollfds[MAX_POLLFDS];
+ int npollfds;
+
+ adns_processtimeouts(ads,now);
+
+ npollfds= adns__pollfds(ads,pollfds);
+ adns__fdevents(ads,
+ pollfds,npollfds,
+ maxfd,readfds,writefds,exceptfds,
+ *now, 0);
+}
+
+/* General helpful functions. */
+
+void adns_globalsystemfailure(adns_state ads) {
+ while (ads->timew.head) {
+ adns__query_fail(ads->timew.head, adns_s_systemfail);
+ }
+
+ switch (ads->tcpstate) {
+ case server_connecting:
+ case server_ok:
+ adns__tcp_closenext(ads);
+ break;
+ case server_disconnected:
+ break;
+ default:
+ abort();
+ }