chiark / gitweb /
Some more fiddlings.
authorian <ian>
Sat, 3 Oct 1998 23:28:13 +0000 (23:28 +0000)
committerian <ian>
Sat, 3 Oct 1998 23:28:13 +0000 (23:28 +0000)
src/adns.h
src/event.c
src/internal.h
src/query.c
src/setup.c

index 23c71efc49ab0a0f410fb2dd56c9a9a10e50e891..ae0a7425dbf87b01e86c214f0927ff9fae52f82c 100644 (file)
@@ -64,6 +64,7 @@ typedef enum {
   adns_s_timeout,
   adns_s_unknownqtype,
   adns_s_nolocalmem,
+  adns_s_connlost,
   adns_s_max_tempfail= 99,
   adns_s_inconsistent, /* PTR gives domain whose A does not match */
   adns_s_badcname, /* CNAME found where actual record expected */
index 68abb3ca4b86a97feac10201f9c7944176d12d05..3007a95fdacd582fc290d040a6fda8624db65af7 100644 (file)
@@ -12,14 +12,55 @@ static int callb_checkfd(int maxfd, const fd_set *fds, int fd) {
          fd<maxfd && FD_ISSET(fd,fds);
 }
 
-static void tcpserver_broken(adns_state ads, const char *what, const char *why) {
-  assert(ads->tcpstate == server_connecting || ads->tcpstate == server_connected);
+void adns__tcp_broken(adns_state ads, const char *what, const char *why) {
+  int serv;
+  
+  assert(ads->tcpstate == server_connecting || ads->tcpstate == server_ok);
   warn("nameserver %s TCP connection lost: %s: %s",
        inet_ntoa(ads->servers[tcpserver].addr,what,why));
   close(ads->tcpsocket);
   ads->tcpstate= server_disconnected;
+  serv= ads->tcpserver;
   
-       
+  for (qu= ads->timew; qu; qu= nqu) {
+    nqu= qu->next;
+    if (qu->senttcpserver == -1) continue;
+    assert(qu->senttcpserver == serv);
+    DLIST_UNLINK(ads->timew,qu);
+    adns__query_fail(ads,qu,adns_s_connlost); /* wishlist: send to other servers ? */
+  }
+
+  ads->tcpbuf.used= 0;
+  ads->tcpserver= (serv+1)%ads->nservers;
+}
+
+void adns__tcp_tryconnect(adns_state ads) {
+  int r, fd, tries;
+  sockaddr_in addr;
+
+  for (tries=0; tries<ads->nservers; tries++) {
+    if (ads->tcpstate == server_connecting || ads->tcpstate == server_ok) return;
+    assert(ads->tcpstate == server_disconnected);
+    assert(!ads->tcpbuf.used);
+
+    proto= getprotobyname("tcp");
+    if (!proto) { diag(ads,"unable to find protocol number for TCP !",-1); return; }
+    fd= socket(AF_INET,SOCK_STREAM,proto->p_proto);
+    if (fd<0) { diag(ads,"cannot create TCP socket: %s",-1,strerror(errno)); return; }
+    if (!adns__setnonblock(fd)) return;
+    memset(&addr,0,sizeof(addr));
+    addr.sin_family= AF_INET;
+    addr.sin_port= htons(NSPORT);
+    addr.sin_addr= ads->servers[ads->tcpserver].addr;
+    r= connect(fd,&addr,sizeof(addr));
+    ads->tcpsocket= fd;
+    ads->tcpstate= server_connecting;
+    if (r==0) { ads->tcpstate= server_ok; return; }
+    if (errno == EWOULDBLOCK || errno == EINPROGRESS) return;
+    tcpserver_broken(ads,"connect",strerror(errno));
+  }
+}
+
 int adns_callback(adns_state ads, int maxfd,
                  const fd_set *readfds, const fd_set *writefds,
                  const fd_set *exceptfds) {
@@ -45,7 +86,7 @@ int adns_callback(adns_state ads, int maxfd,
        } else if (r>0) {
          tcpserver_broken(ads,"connect/read","sent data before first request");
        } else if (errno!=EINTR) {
-         tcpserver_broken(ads,"connect",strerror(errno));
+         tcpserver_broken(ads,"connect/read",strerror(errno));
        }
       }
     }
index 2cdafbf9117bda31d5dc7b1e0d93d2d626dd543a..eb8cd5d25be6a1e5500e7b6b170598f3b7826f3e 100644 (file)
@@ -38,8 +38,8 @@ struct adns__query {
   adns_answer *answer;
   size_t ansalloc; ansused;
   int id, flags, udpretries; /* udpretries==-1 => _f_usevc or too big for UDP */
-  int nextudpserver;
-  unsigned long sentudp, senttcp; /* bitmaps indexed by server */
+  int nextudpserver, senttcpserver;
+  unsigned long sentudp; /* bitmap indexed by server */
   struct timeval timeout;
   void *context;
   unsigned char *querymsg;
@@ -67,7 +67,7 @@ struct adns__state {
   int nextid, udpsocket;
   adns_vbuf rqbuf, tcpsend, tcprecv;
   int nservers, tcpserver;
-  enum adns__tcpstate { server_disc, server_connecting, server_ok } tcpstate;
+  enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate;
   int tcpsocket;
   struct timeval tcptimeout;
   struct server {
@@ -79,9 +79,9 @@ struct adns__state {
 
 void adns__vdiag(adns_state ads, adns_initflags prevent, const char *pfx,
                 int serv, const char *fmt, va_list al);
-void adns__debug(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(2,3);
-void adns__warn(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(2,3);
-void adns__diag(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(2,3);
+void adns__debug(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(3,4);
+void adns__warn(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(3,4);
+void adns__diag(adns_state ads, int serv, const char *fmt, ...) PRINTFFORMAT(3,4);
 
 /* From submit.c: */
 
@@ -89,7 +89,11 @@ void adns__query_fail(adns_state ads, adns_query qu, adns_status stat);
 
 /* From query.c: */
 
-void adns__quproc_tosend(adns_state ads, adns_query qu, struct timeval now) {
+void adns__quproc_tosend(adns_state ads, adns_query qu, struct timeval now);
+
+/* From event.c: */
+void adns__tcp_broken(adns_state ads, const char *what, const char *why);
+void adns__tcp_tryconnect(adns_state ads);
 
 /* Useful static inline functions: */
 
index c9ad8fd862f8edf39fe8eba94e05a49617c46e2b..81acb6181ec2617c0b1d3e3d0495880a9e3ea158 100644 (file)
@@ -108,6 +108,8 @@ void adns__quproc_tosend(adns_state ads, adns_query qu, struct timeval now) {
 
   /* fixme: TCP queries preceded by length */
   for (;;) {
+    adns__tcp_tryconnect(ads);
+    /* fixme: make this work properly */
     serv= tcpserver_get(ads);
     if (serv<0) { r=0; break; }
     if (ads->opbufused) { r=0; break; }
index 8939ac63f0cc19bf997f441174806af39f86d96f..7daea9bb9149ba0244721cb3b39cf4804b211e57 100644 (file)
@@ -230,13 +230,11 @@ int adns_init(adns_state *ads_r, adns_initflags flags) {
 
   proto= getprotobyname("udp"); if (!proto) { r= ENOPROTOOPT; goto x_free; }
   ads->udpsocket= socket(AF_INET,SOCK_DGRAM,proto->p_proto);
-  if (!ads->udpsocket) { r= errno; goto x_closeudp; }
+  if (ads->udpsocket<0) { r= errno; goto x_free; }
   
   *ads_r= ads;
   return 0;
 
- x_closeudp:
-  close(ads->udpsocket);
  x_free:
   free(ads);
   return r;