chiark / gitweb /
+ * Referrals with RD+RA set, or RCODE=Refused, don't generate warnings,
[adns.git] / src / event.c
index b82b5de397d9a9e7eeb9f007cc01c41a0d7fe33d..29d50a0cf6e8817476d4a300f400e1a99e85e1b0 100644 (file)
@@ -6,10 +6,10 @@
  */
 /*
  *  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) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk>
  *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
  *  
  *  This program is free software; you can redistribute it and/or modify
@@ -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();
   }
@@ -424,6 +433,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 +456,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 +471,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 +487,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:
@@ -541,7 +554,7 @@ void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io,
     /* The caller is planning to sleep. */
     adns__must_gettimeofday(ads,&now,&tv_nowbuf);
     if (!now) { inter_immed(tv_mod,tv_tobuf); goto xit; }
-    adns__timeouts(ads, 1, tv_mod,tv_tobuf, *now);
+    adns__timeouts(ads, 0, tv_mod,tv_tobuf, *now);
   }
 
   npollfds= adns__pollfds(ads,pollfds);
@@ -595,6 +608,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 +632,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,
@@ -673,9 +687,7 @@ int adns_wait(adns_state ads,
     if (r != EAGAIN) break;
     maxfd= 0; tvp= 0;
     FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
-    ads->bug_if_query_done_now= 1;
     adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf,0);
-    ads->bug_if_query_done_now= 0;
     assert(tvp);
     rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp);
     if (rsel==-1) {