+/* `Interest' functions - find out which fd's we might be interested in,
+ * and when we want to be called back for a timeout.
+ */
+
+static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf,
+ struct timeval maxto) {
+ struct timeval *rbuf;
+
+ if (!tv_io) return;
+ 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;
+
+ if (!tv_io) return;
+ 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 inter_addfd(int *maxfd, fd_set *fds, int fd) {
+ if (!maxfd || !fds) return;
+ if (fd>=*maxfd) *maxfd= fd+1;
+ FD_SET(fd,fds);
+}
+
+static void checktimeouts(adns_state ads, struct timeval now,
+ struct timeval **tv_io, struct timeval *tvbuf) {
+ adns_query qu, nqu;
+
+ for (qu= ads->timew.head; qu; qu= nqu) {
+ nqu= qu->next;
+ if (timercmp(&now,&qu->timeout,>)) {
+ LIST_UNLINK(ads->timew,qu);
+ if (qu->state != query_udp) {
+ adns__query_fail(ads,qu,adns_s_timeout);
+ } else {
+ adns__query_udp(ads,qu,now);
+ }
+ } else {
+ inter_maxtoabs(tv_io,tvbuf,now,qu->timeout);
+ }
+ }
+}
+
+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;
+ struct timeval tvto_lr;
+ int r;
+
+ r= gettimeofday(&now,0);
+ if (r) {
+ adns__warn(ads,-1,"gettimeofday failed - will sleep for a bit: %s",strerror(errno));
+ timerclear(&tvto_lr); timevaladd(&tvto_lr,LOCALRESOURCEMS);
+ inter_maxto(tv_io, tvbuf, tvto_lr);
+ } 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);
+ default:
+ abort();
+ }
+}
+