chiark / gitweb /
Change DISTVERSION to pre-1.0-1
[adns.git] / src / event.c
index 885ab81032747cb4ba478c84723375fa2791f73c..f1d22dc7d9a95b6853583e008d4184c7099c3c7d 100644 (file)
@@ -6,11 +6,11 @@
  */
 /*
  *  This file is
- *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
  *
  *  It is part of adns, which is
- *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
- *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *    Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1999-2000 Tony Finch <dot@dotat.at>
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -54,11 +54,18 @@ static void tcp_close(adns_state ads) {
 
 void adns__tcp_broken(adns_state ads, const char *what, const char *why) {
   int serv;
+  adns_query qu;
   
   assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok);
   serv= ads->tcpserver;
   if (what) adns__warn(ads,serv,0,"TCP connection failed: %s: %s",what,why);
 
+  if (ads->tcpstate == server_connecting) {
+    /* Counts as a retry for all the queries waiting for TCP. */
+    for (qu= ads->tcpw.head; qu; qu= qu->next)
+      qu->retries++;
+  }
+
   tcp_close(ads);
   ads->tcpstate= server_broken;
   ads->tcpserver= (serv+1)%ads->nservers;
@@ -304,6 +311,7 @@ int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]) {
 
   switch (ads->tcpstate) {
   case server_disconnected:
+  case server_broken:
     return 1;
   case server_connecting:
     pollfds_buf[1].events= POLLOUT;
@@ -327,12 +335,13 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
 
   switch (ads->tcpstate) {
   case server_disconnected:
+  case server_broken:
   case server_connecting:
     break;
   case server_ok:
     if (fd != ads->tcpsocket) break;
     assert(!ads->tcprecv_skip);
-    for (;;) {
+    do {
       if (ads->tcprecv.used >= ads->tcprecv_skip+2) {
        dgramlen= ((ads->tcprecv.buf[ads->tcprecv_skip]<<8) |
                   ads->tcprecv.buf[ads->tcprecv_skip+1]);
@@ -366,9 +375,9 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
          if (errno_resources(errno)) { r= errno; goto xit; }
        }
        adns__tcp_broken(ads,"read",r?strerror(errno):"closed");
-       r= 0; goto xit;
       }
-    } /* never reached */
+    } while (ads->tcpstate == server_ok);
+    r= 0; goto xit;
   default:
     abort();
   }
@@ -386,7 +395,8 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
       }
       if (udpaddrlen != sizeof(udpaddr)) {
        adns__diag(ads,-1,0,"datagram received with wrong address length %d"
-                  " (expected %d)", udpaddrlen,sizeof(udpaddr));
+                  " (expected %lu)", udpaddrlen,
+                  (unsigned long)sizeof(udpaddr));
        continue;
       }
       if (udpaddr.sin_family != AF_INET) {
@@ -424,6 +434,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) {
 
   switch (ads->tcpstate) {
   case server_disconnected:
+  case server_broken:
     break;
   case server_connecting:
     if (fd != ads->tcpsocket) break;
@@ -446,8 +457,8 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) {
       r= 0; goto xit;
     } /* not reached */
   case server_ok:
-    if (!(ads->tcpsend.used && fd == ads->tcpsocket)) break;
-    for (;;) {
+    if (fd != ads->tcpsocket) break;
+    while (ads->tcpsend.used) {
       adns__sigpipe_protect(ads);
       r= write(ads->tcpsocket,ads->tcpsend.buf,ads->tcpsend.used);
       adns__sigpipe_unprotect(ads);
@@ -461,7 +472,9 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) {
        ads->tcpsend.used -= r;
        memmove(ads->tcpsend.buf,ads->tcpsend.buf+r,ads->tcpsend.used);
       }
-    } /* not reached */
+    }
+    r= 0;
+    goto xit;
   default:
     abort();
   }
@@ -475,6 +488,7 @@ int adns_processexceptional(adns_state ads, int fd, const struct timeval *now) {
   adns__consistency(ads,0,cc_entex);
   switch (ads->tcpstate) {
   case server_disconnected:
+  case server_broken:
     break;
   case server_connecting:
   case server_ok:
@@ -540,8 +554,8 @@ void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io,
   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) { inter_immed(tv_mod,tv_iobuf); goto xit; }
-    adns__timeouts(ads, 1, tv_mod,tv_tobuf, *now);
+    if (!now) { inter_immed(tv_mod,tv_tobuf); goto xit; }
+    adns__timeouts(ads, 0, tv_mod,tv_tobuf, *now);
   }
 
   npollfds= adns__pollfds(ads,pollfds);
@@ -595,6 +609,7 @@ void adns_globalsystemfailure(adns_state ads) {
     adns__tcp_broken(ads,0,0);
     break;
   case server_disconnected:
+  case server_broken:
     break;
   default:
     abort();
@@ -618,7 +633,7 @@ int adns_processany(adns_state ads) {
    * likely just to want to do a read on one or two fds anyway.
    */
   npollfds= adns__pollfds(ads,pollfds);
-  for (i=0; i<npollfds; i++) pollfds[i].revents= pollfds[i].events;
+  for (i=0; i<npollfds; i++) pollfds[i].revents= pollfds[i].events & ~POLLPRI;
   adns__fdevents(ads,
                 pollfds,npollfds,
                 0,0,0,0,
@@ -665,7 +680,7 @@ int adns_wait(adns_state ads,
              void **context_r) {
   int r, maxfd, rsel;
   fd_set readfds, writefds, exceptfds;
-  struct timeval *now, nowbuf, tvbuf, *tvp;
+  struct timeval tvbuf, *tvp;
   
   adns__consistency(ads,*query_io,cc_entex);
   for (;;) {