X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fevent.c;h=db3dad68e776168a2c645aa14e801413cf837dd7;hb=e2632eb98754dfc14592e9fcf96fd3ba4a5f6bf9;hp=cd76707eff81f3cc1444c5dcd4427a8a299b0179;hpb=8e5b0abb4e5416f4bd244500d9ba8dd45788093e;p=adns.git diff --git a/src/event.c b/src/event.c index cd76707..db3dad6 100644 --- a/src/event.c +++ b/src/event.c @@ -1,4 +1,26 @@ -/**/ +/* + * event.c + * - event loop core + * - TCP connection management + * - user-visible check/wait and event-loop-related functions + */ +/* + * This file is part of adns, which is Copyright (C) 1997-1999 Ian Jackson + * + * 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 + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ #include #include @@ -17,7 +39,7 @@ void adns__tcp_broken(adns_state ads, const char *what, const char *why) { assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok); serv= ads->tcpserver; - adns__warn(ads,serv,"TCP connection lost: %s: %s",what,why); + adns__warn(ads,serv,0,"TCP connection lost: %s: %s",what,why); close(ads->tcpsocket); ads->tcpstate= server_disconnected; @@ -29,7 +51,7 @@ void adns__tcp_broken(adns_state ads, const char *what, const char *why) { qu->tcpfailed |= (1<tcpfailed == (1<nservers)-1) { LIST_UNLINK(ads->timew,qu); - adns__query_fail(ads,qu,adns_s_allservfail); + adns__query_fail(qu,adns_s_allservfail); } } @@ -40,13 +62,13 @@ void adns__tcp_broken(adns_state ads, const char *what, const char *why) { static void tcp_connected(adns_state ads, struct timeval now) { adns_query qu, nqu; - adns__debug(ads,ads->tcpserver,"TCP connected"); + adns__debug(ads,ads->tcpserver,0,"TCP connected"); ads->tcpstate= server_ok; for (qu= ads->timew.head; qu; qu= nqu) { nqu= qu->next; if (qu->state == query_udp) continue; assert (qu->state == query_tcpwait); - adns__query_tcp(ads,qu,now); + adns__query_tcp(qu,now); } } @@ -54,7 +76,6 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { int r, fd, tries; struct sockaddr_in addr; struct protoent *proto; - /* fixme: single TCP timeout, not once per server */ for (tries=0; triesnservers; tries++) { if (ads->tcpstate == server_connecting || ads->tcpstate == server_ok) return; @@ -63,15 +84,15 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { assert(!ads->tcprecv.used); proto= getprotobyname("tcp"); - if (!proto) { adns__diag(ads,-1,"unable to find protocol no. for TCP !"); return; } + if (!proto) { adns__diag(ads,-1,0,"unable to find protocol no. for TCP !"); return; } fd= socket(AF_INET,SOCK_STREAM,proto->p_proto); if (fd<0) { - adns__diag(ads,-1,"cannot create TCP socket: %s",strerror(errno)); + adns__diag(ads,-1,0,"cannot create TCP socket: %s",strerror(errno)); return; } r= adns__setnonblock(ads,fd); if (r) { - adns__diag(ads,-1,"cannot make TCP socket nonblocking: %s",strerror(r)); + adns__diag(ads,-1,0,"cannot make TCP socket nonblocking: %s",strerror(r)); close(fd); return; } @@ -103,16 +124,16 @@ static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf, } else { if (timercmp(rbuf,&maxto,>)) *rbuf= maxto; } -fprintf(stderr,"inter_maxto maxto=%ld.%06ld result=%ld.%06ld\n", - maxto.tv_sec,maxto.tv_usec,(**tv_io).tv_sec,(**tv_io).tv_usec); +/*fprintf(stderr,"inter_maxto maxto=%ld.%06ld result=%ld.%06ld\n", + maxto.tv_sec,maxto.tv_usec,(**tv_io).tv_sec,(**tv_io).tv_usec);*/ } static void inter_maxtoabs(struct timeval **tv_io, struct timeval *tvbuf, struct timeval now, struct timeval maxtime) { ldiv_t dr; -fprintf(stderr,"inter_maxtoabs now=%ld.%06ld maxtime=%ld.%06ld\n", - now.tv_sec,now.tv_usec,maxtime.tv_sec,maxtime.tv_usec); +/*fprintf(stderr,"inter_maxtoabs now=%ld.%06ld maxtime=%ld.%06ld\n", + now.tv_sec,now.tv_usec,maxtime.tv_sec,maxtime.tv_usec);*/ if (!tv_io) return; maxtime.tv_sec -= (now.tv_sec+2); maxtime.tv_usec -= (now.tv_usec-2000000); @@ -138,9 +159,9 @@ static void checktimeouts(adns_state ads, struct timeval now, if (timercmp(&now,&qu->timeout,>)) { LIST_UNLINK(ads->timew,qu); if (qu->state != query_udp) { - adns__query_fail(ads,qu,adns_s_timeout); + adns__query_fail(qu,adns_s_timeout); } else { - adns__query_udp(ads,qu,now); + adns__query_udp(qu,now); } } else { inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); @@ -155,11 +176,12 @@ void adns_interest(adns_state ads, int *maxfd, struct timeval tvto_lr; int r; -fprintf(stderr,"adns_interest\n"); +/*fprintf(stderr,"adns_interest\n");*/ -r= gettimeofday(&now,0); + r= gettimeofday(&now,0); if (r) { - adns__warn(ads,-1,"gettimeofday failed - will sleep for a bit: %s",strerror(errno)); + adns__warn(ads,-1,0,"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 { @@ -178,6 +200,7 @@ r= gettimeofday(&now,0); inter_addfd(maxfd,readfds,ads->tcpsocket); inter_addfd(maxfd,exceptfds,ads->tcpsocket); if (ads->tcpsend.used) inter_addfd(maxfd,writefds,ads->tcpsocket); + break; default: abort(); } @@ -207,7 +230,7 @@ static int internal_callback(adns_state ads, int maxfd, if (callb_checkfd(maxfd,writefds,ads->tcpsocket)) { count++; assert(ads->tcprecv.used==0); - adns__vbuf_ensure(&ads->tcprecv,1); + if (!adns__vbuf_ensure(&ads->tcprecv,1)) return -1; if (ads->tcprecv.buf) { r= read(ads->tcpsocket,&ads->tcprecv.buf,1); if (r==0 || (r<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) { @@ -240,8 +263,10 @@ static int internal_callback(adns_state ads, int maxfd, } ads->tcprecv.used -= skip; memmove(ads->tcprecv.buf,ads->tcprecv.buf+skip,ads->tcprecv.used); - adns__vbuf_ensure(&ads->tcprecv,want); - if (ads->tcprecv.used >= ads->tcprecv.avail) break; + skip= 0; + if (!adns__vbuf_ensure(&ads->tcprecv,want)) return -1; + assert(ads->tcprecv.used <= ads->tcprecv.avail); + if (ads->tcprecv.used == ads->tcprecv.avail) continue; r= read(ads->tcpsocket, ads->tcprecv.buf+ads->tcprecv.used, ads->tcprecv.avail-ads->tcprecv.used); @@ -259,7 +284,9 @@ static int internal_callback(adns_state ads, int maxfd, } else if (callb_checkfd(maxfd,exceptfds,ads->tcpsocket)) { adns__tcp_broken(ads,"select","exceptional condition detected"); } else if (ads->tcpsend.used && callb_checkfd(maxfd,writefds,ads->tcpsocket)) { + adns__sigpipe_protect(ads); r= write(ads->tcpsocket,ads->tcpsend.buf,ads->tcpsend.used); + adns__sigpipe_unprotect(ads); if (r<0) { if (errno!=EAGAIN && errno!=EWOULDBLOCK && errno!=ENOMEM && errno!=EINTR) { adns__tcp_broken(ads,"write",strerror(errno)); @@ -269,6 +296,7 @@ static int internal_callback(adns_state ads, int maxfd, memmove(ads->tcpsend.buf,ads->tcpsend.buf+r,ads->tcpsend.used); } } + break; default: abort(); } @@ -281,21 +309,21 @@ static int internal_callback(adns_state ads, int maxfd, if (r<0) { if (!(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR || errno == ENOMEM || errno == ENOBUFS)) - adns__warn(ads,-1,"datagram receive error: %s",strerror(errno)); + adns__warn(ads,-1,0,"datagram receive error: %s",strerror(errno)); break; } if (udpaddrlen != sizeof(udpaddr)) { - adns__diag(ads,-1,"datagram received with wrong address length %d (expected %d)", - udpaddrlen,sizeof(udpaddr)); + adns__diag(ads,-1,0,"datagram received with wrong address length %d" + " (expected %d)", udpaddrlen,sizeof(udpaddr)); continue; } if (udpaddr.sin_family != AF_INET) { - adns__diag(ads,-1,"datagram received with wrong protocol family" + adns__diag(ads,-1,0,"datagram received with wrong protocol family" " %u (expected %u)",udpaddr.sin_family,AF_INET); continue; } if (ntohs(udpaddr.sin_port) != DNS_PORT) { - adns__diag(ads,-1,"datagram received from wrong port %u (expected %u)", + adns__diag(ads,-1,0,"datagram received from wrong port %u (expected %u)", ntohs(udpaddr.sin_port),DNS_PORT); continue; } @@ -304,7 +332,7 @@ static int internal_callback(adns_state ads, int maxfd, ads->servers[serv].addr.s_addr != udpaddr.sin_addr.s_addr; serv++); if (serv >= ads->nservers) { - adns__warn(ads,-1,"datagram received from unknown nameserver %s", + adns__warn(ads,-1,0,"datagram received from unknown nameserver %s", inet_ntoa(udpaddr.sin_addr)); continue; } @@ -347,7 +375,7 @@ static int internal_check(adns_state ads, } LIST_UNLINK(ads->output,qu); *answer= qu->answer; - if (context_r) *context_r= qu->context.ext; + if (context_r) *context_r= qu->ctx.ext; free(qu); return 0; } @@ -367,7 +395,10 @@ int adns_wait(adns_state ads, FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); adns_interest(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf); rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp); - if (rsel==-1) return r; + if (rsel==-1) { + if (errno == EINTR && !(ads->iflags & adns_if_eintr)) continue; + return errno; + } rcb= adns_callback(ads,maxfd,&readfds,&writefds,&exceptfds); assert(rcb==rsel); }