+static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf,
+ struct timeval maxto) {
+ struct timeval rbuf;
+
+ rbuf= *tv_io;
+ if (!rbuf) { *tvbuf= maxto; *tv_io= tvbuf; return; }
+ if (timercmp(rbuf,&maxto,>)) *rbuf= maxto;
+}
+
+static void inter_maxtoabs(struct timeval **tv_io, struct timeval *tvbuf,
+ struct timeval now, struct timeval maxtime) {
+ ldiv_t dr;
+
+ maxtime.tv_sec -= (now.tv_sec-1);
+ maxtime.tv_usec += (1000-now.tv_usec);
+ dr= ldiv(maxtime.tv_usec,1000);
+ maxtime.tv_sec += dr.quot;
+ maxtime.tv_usec -= dr.rem;
+ inter_maxto(tv_io,tvbuf,maxtime);
+}
+
+static void localresourcerr(struct timeval **tv_io, struct timeval *tvbuf,
+ const char *syscall) {
+ struct timeval tvto_lr;
+
+ diag(ads,"local system resources scarce (during %s): %s",syscall,strerror(errno));
+ timerclear(&tvto_lr); timevaladd(&tvto_lr,LOCALRESOURCEMS);
+ inter_maxto(tv_io, tvbuf, tvto_lr);
+ return;
+}
+
+static inline void timevaladd(struct timeval *tv_io, long ms) {
+ struct timeval tmp;
+ assert(ms>=0);
+ tmp= *tv_io;
+ tmp.tv_usec += (ms%1000)*1000;
+ tmp.tv_sec += ms/1000;
+ if (tmp.tv_usec >= 1000) { tmp.tv_sec++; tmp.tv_usec -= 1000; }
+ *tv_io= tmp;
+}
+
+void adns_interest(adns_state ads, int *maxfd,
+ fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval **tv_io, struct timeval *tvbuf) {
+ struct timeval now;
+ adns_query qu;
+ int r;
+
+ r= gettimeofday(&now,0);
+ if (r) { localresourcerr(tv_io,tvbuf,"gettimeofday"); return; }
+
+ for (qu= ads->timew; qu; qu= nqu) {
+ nqu= qu->next;
+ if (timercmp(&now,qu->timeout,>)) {
+ DLIST_UNLINK(ads->timew,qu);
+ if (qu->nextudpserver == -1) {
+ query_fail(ads,qu,adns_s_notresponding);
+ } else {
+ DLIST_LINKTAIL(ads->tosend,qu);
+ }
+ } else {
+ inter_maxtoabs(tv_io,tvbuf,now,qu->timeout);
+ }
+ }
+
+ for (qu= ads->tosend; qu; qu= nqu) {
+ nqu= qu->next;
+ quproc_tosend(ads,qu,now);
+ }
+
+ for (qu= ads->timew; qu; qu= qu->next) {
+ if (qu->sentudp) {
+ inter_addfd(maxfd,readfds,ads->udpsocket);
+ break;
+ }
+ }
+ switch (ads->tcpstate) {
+ case server_disc:
+ break;
+ case server_connecting:
+ inter_addfd(maxfd,readfds,ads->tcpsocket);
+ inter_addfd(maxfd,writefds,ads->tcpsocket);
+ inter_addfd(maxfd,exceptfds,ads->tcpsocket);
+ break;
+ case server_connected:
+ inter_addfd(maxfd,readfds,ads->tcpsocket);
+ inter_addfd(maxfd,exceptfds,ads->tcpsocket);
+ if (ads->opbufused) inter_addfd(maxfd,writefds,ads->tcpsocket);
+ default:
+ abort();
+ }
+
+}
+