X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fevent.c;h=684759a727f2cfa5c2e390978950ec49f6b7ac21;hb=73eb26037c46bebeaa30ba38eba887216f0e9a6e;hp=885ab81032747cb4ba478c84723375fa2791f73c;hpb=4fad263db72b6e675e82c84b56d81333240a7475;p=adns.git diff --git a/src/event.c b/src/event.c index 885ab81..684759a 100644 --- a/src/event.c +++ b/src/event.c @@ -6,10 +6,10 @@ */ /* * This file is - * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1997-2000 Ian Jackson * * It is part of adns, which is - * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1997-2000 Ian Jackson * Copyright (C) 1999 Tony Finch * * 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(); } @@ -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