chiark / gitweb /
General improvements; add cancel routine.
authorian <ian>
Sat, 14 Nov 1998 15:24:55 +0000 (15:24 +0000)
committerian <ian>
Sat, 14 Nov 1998 15:24:55 +0000 (15:24 +0000)
src/Makefile
src/Makefile.in
src/adns.h
src/event.c
src/general.c
src/internal.h
src/query.c
src/reply.c
src/types.c

index acce334c08d992c0ae8a056c88de962b1eb183c0..7c36a847a87d0fd93776c0141d488dabd077bed9 100644 (file)
@@ -21,7 +21,7 @@ WARNS=        -Wall -Wmissing-prototypes -Wwrite-strings -Wstrict-prototypes \
        -Wcast-qual -Wpointer-arith
 WERROR=-Werror
 
-LIBOBJS=       event.o query.o setup.o transmit.o general.o reply.o parse.o types.o
+LIBOBJS=       event.o types.o reply.o query.o setup.o transmit.o parse.o general.o
 ALLOBJS=       $(LIBOBJS) dtest.o
 
 all:           dtest
@@ -31,5 +31,5 @@ dtest:                $(ALLOBJS)
 clean:
                rm -f dtest *.o
 
-dtest.o:       adns.h
 $(LIBOBJS):    adns.h internal.h
+dtest.o:       adns.h
index acce334c08d992c0ae8a056c88de962b1eb183c0..7c36a847a87d0fd93776c0141d488dabd077bed9 100644 (file)
@@ -21,7 +21,7 @@ WARNS=        -Wall -Wmissing-prototypes -Wwrite-strings -Wstrict-prototypes \
        -Wcast-qual -Wpointer-arith
 WERROR=-Werror
 
-LIBOBJS=       event.o query.o setup.o transmit.o general.o reply.o parse.o types.o
+LIBOBJS=       event.o types.o reply.o query.o setup.o transmit.o parse.o general.o
 ALLOBJS=       $(LIBOBJS) dtest.o
 
 all:           dtest
@@ -31,5 +31,5 @@ dtest:                $(ALLOBJS)
 clean:
                rm -f dtest *.o
 
-dtest.o:       adns.h
 $(LIBOBJS):    adns.h internal.h
+dtest.o:       adns.h
index afcb6b4ba577047d04f1e59b58b4e8e21a0e321b..5b7aa037991aad716b1fa79b1cafd84a1daafc54 100644 (file)
@@ -39,6 +39,7 @@ typedef enum {
   adns_if_noserverwarn= 0x0004, /* do not warn to stderr about duff nameservers etc */
   adns_if_debug=        0x0008, /* enable all output to stderr plus debug msgs */
   adns_if_noautosys=    0x0010, /* do not make syscalls at every opportunity */
+  adns_if_eintr=        0x0020, /* allow _wait and _synchronous to return EINTR */
 } adns_initflags;
 
 typedef enum {
@@ -215,7 +216,6 @@ int adns_synchronous(adns_state ads,
                     adns_rrtype type,
                     adns_queryflags flags,
                     adns_answer **answer_r);
-/* Will not return EINTR. */
 
 /* NB: if you set adns_if_noautosys then _submit and _check do not
  * make any system calls; you must use adns_callback (possibly after
@@ -238,7 +238,6 @@ int adns_wait(adns_state ads,
              adns_query *query_io,
              adns_answer **answer_r,
              void **context_r);
-/* Might return EINTR - if so, try again */
 
 void adns_cancel(adns_query query);
 
index a61b8dd61893c7136cad52243f23dd2bea1ab61a..8f3fb4c1b7ff354de827bfe33dbc31c1fd23bfd7 100644 (file)
@@ -394,7 +394,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);
   }
index 8311dd7d5eb1d0f3559475c15c93f546fce6e18f..211b6d20586a520aef2c672d4421912c17708d5c 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include <arpa/inet.h>
 
@@ -238,3 +239,19 @@ const char *adns_strerror(adns_status st) {
   snprintf(buf,sizeof(buf),"code %d",st);
   return buf;
 }
+
+void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
+                int (*needswap)(const void *a, const void *b)) {
+  byte *data= array;
+  int i, place;
+
+  for (i=0; i<nobjs; i++) {
+    for (place= i; place>0 && needswap(data + (place-1)*sz, data + i*sz); place--);
+
+    if (place != i) {
+      memcpy(tempbuf, data + i*sz, sz);
+      memmove(data + (place+1)*sz, data + place*sz, (i-place)*sz);
+      memcpy(data + place*sz, tempbuf, sz);
+    }
+  }
+}
index 19adb4fcf379ab5f44a9a3bc95ec0bfefde60a75..09ba2fefd77b78f4559e6c2856b603183415783c 100644 (file)
@@ -99,7 +99,7 @@ typedef struct {
 
   adns_status (*parse)(adns_query qu, int serv,
                       const byte *dgram, int dglen, int cbyte, int max,
-                      void *store_r);
+                      int nsstart, int *arstart_io, void *store_r);
   /* Parse one RR, in dgram of length dglen, starting at cbyte and
    * extending until at most max.
    *
@@ -107,10 +107,14 @@ typedef struct {
    *
    * If there is an overrun which might indicate truncation, it should set
    * *rdstart to -1; otherwise it may set it to anything else positive.
+   *
+   * nsstart is the offset of the authority section; *arstart_io is
+   * -1 or the offset of the additional section; if it is -1 then
+   * parse may set it to the correct offset.
    */
 
   int (*diff_needswap)(const void *datap_a, const void *datap_b);
-  /* Returns >0 if RR a should be strictly after RR b in the sort order,
+  /* Returns !0 if RR a should be strictly after RR b in the sort order,
    * 0 otherwise.  Must not fail.
    */
 } typeinfo;
@@ -271,6 +275,14 @@ const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
  * vb before using the return value.
  */
   
+void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
+                int (*needswap)(const void *a, const void *b));
+/* Does an insertion sort of array which must contain nobjs objects
+ * each sz bytes long.  tempbuf must point to a buffer at least
+ * sz bytes long.  needswap should return !0 if a>b (strictly, ie
+ * wrong order) 0 if a<=b (ie, order is fine).
+ */
+  
 /* From transmit.c: */
 
 adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
index 41aaf5f58cd34009573a714225a6aea9ef396529..9c7fffe52626f853e974ebe11b5298cc3ff8ee08 100644 (file)
@@ -147,15 +147,10 @@ int adns_synchronous(adns_state ads,
   r= adns_submit(ads,owner,type,flags,0,&qu);
   if (r) return r;
 
-  do {
-    r= adns_wait(ads,&qu,answer_r,0);
-  } while (r==EINTR);
+  r= adns_wait(ads,&qu,answer_r,0);
   if (r) adns_cancel(qu);
-  return r;
-}
 
-void adns_cancel(adns_query query) {
-  abort(); /* fixme */
+  return r;
 }
 
 static void *alloc_common(adns_query qu, size_t sz) {
@@ -197,22 +192,58 @@ void *adns__alloc_final(adns_query qu, size_t sz) {
 }
 
 void adns__reset_cnameonly(adns_query qu) {
+  /* fixme: cancel children */
   assert(!qu->final_allocspace);
   qu->answer->nrrs= 0;
   qu->answer->rrs= 0;
   qu->interim_allocd= qu->answer->cname ? MEM_ROUND(strlen(qu->answer->cname)+1) : 0;
 }
 
+static void free_query_allocs(adns_query qu) {
+  allocnode *an, *ann;
+  adns_query cqu, ncqu;
+
+  for (cqu= qu->children.head; cqu; cqu= ncqu) {
+    ncqu= cqu->siblings.next;
+    adns_cancel(cqu);
+  }
+  for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); }
+  adns__vbuf_free(&qu->vb);
+}
+
+void adns_cancel(adns_query query) {
+  switch (qu->state) {
+  case query_udp: case query_tcpwait: case query_tcpsent:
+    LIST_UNLINK(ads->timew,qu);
+    break;
+  case query_child:
+    LIST_UNLINK(ads->childw,qu);
+    break;
+  case query_done:
+    LIST_UNLINK(ads->output,qu);
+    break;
+  default:
+    abort();
+  }
+  free_query_allocs(qu);
+  free(qu->answer);
+  free(qu);
+}
+  
 void adns__query_done(adns_query qu) {
   adns_answer *ans;
-  allocnode *an, *ann;
-  int i;
+  int rrn;
 
-  if (qu->answer->status == adns_s_nolocalmem && !qu->interim_allocd) {
-    ans= qu->answer;
-  } else {
-    ans= realloc(qu->answer,
-                MEM_ROUND(MEM_ROUND(sizeof(*ans)) + qu->interim_allocd));
+  ans= qu->answer;
+  
+  if (qu->interim_allocd) {
+    if (qu->answer->nrrs && qu->typei->diff_needswap) {
+      if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
+       adns__query_fail(qu,adns_s_nolocalmem);
+       return;
+      }
+    }
+    ans= realloc(qu->answer, MEM_ROUND(MEM_ROUND(sizeof(*ans)) + qu->interim_allocd));
     if (!ans) {
       qu->answer->cname= 0;
       adns__query_fail(qu, adns_s_nolocalmem);
@@ -220,18 +251,22 @@ void adns__query_done(adns_query qu) {
     }
     qu->answer= ans;
   }
-  qu->final_allocspace= (byte*)ans + MEM_ROUND(sizeof(*ans));
 
+  qu->final_allocspace= (byte*)ans + MEM_ROUND(sizeof(*ans));
   adns__makefinal_str(qu,&ans->cname);
+  
   if (ans->nrrs) {
-    adns__makefinal_block(qu,&ans->rrs.untyped,ans->rrsz*ans->nrrs);
-    for (i=0; i<ans->nrrs; i++)
-      qu->typei->makefinal(qu,ans->rrs.bytes+ans->rrsz*i);
-  }
+    adns__makefinal_block(qu, &ans->rrs.untyped, ans->nrrs*ans->rrsz);
 
-  for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); }
+    for (rrn=0; rrn<ans->nrrs; rrn++)
+      qu->typei->makefinal(qu, ans->rrs.bytes + rrn*ans->rrsz);
 
-  adns__vbuf_free(&qu->vb);
+    if (qu->typei->diff_needswap)
+      adns__isort(ans->rrs.bytes, ans->nrrs, ans->rrsz,
+                 qu->vb.buf, qu->typei->diff_needswap);
+  }
+
+  free_query_allocs(qu);
   
   qu->id= -1;
   LIST_LINK_TAIL(qu->ads->output,qu);
@@ -264,4 +299,3 @@ void adns__makefinal_block(adns_query qu, void **blpp, size_t sz) {
   memcpy(after,before,sz);
   *blpp= after;
 }
-
index 3b46e21358490b5fbfd37e2bac03be697e0db9f0..c0772b9aa509ecb44e3bd2964490160f51d939a2 100644 (file)
@@ -32,7 +32,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
   int flg_ra, flg_rd, flg_tc, flg_qr, opcode;
   int rrtype, rrclass, rdlength, rdstart;
   int anstart, nsstart, arstart;
-  int ownermatched, l, nrrs, place;
+  int ownermatched, l, nrrs;
   const typeinfo *typei;
   adns_query qu, nqu;
   dns_rcode rcode;
@@ -99,6 +99,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
     return;
   }
   anstart= qu->query_dglen;
+  arstart= -1;
 
   LIST_UNLINK(ads->timew,qu);
   /* We're definitely going to do something with this query now */
@@ -256,17 +257,9 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
 
   typei= qu->typei;
   cbyte= anstart;
-  arstart= -1;
   rrsdata= qu->answer->rrs.bytes;
   
-  if (typei->diff_needswap) {
-    if (!adns__vbuf_ensure(&qu->vb,typei->rrsz)) {
-      adns__query_fail(qu,adns_s_nolocalmem);
-      return;
-    }
-  }
   nrrs= 0;
-  
   for (rri=0; rri<ancount; rri++) {
     st= adns__findrr(qu,serv, dgram,dglen,&cbyte,
                     &rrtype,&rrclass,&rdlength,&rdstart,
@@ -277,23 +270,9 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
        !ownermatched)
       continue;
     st= typei->parse(qu,serv, dgram,dglen, rdstart,rdstart+rdlength,
-                    rrsdata+nrrs*typei->rrsz);
+                    nsstart,&arstart, rrsdata+nrrs*typei->rrsz);
     if (st) { adns__query_fail(qu,st); return; }
     if (rdstart==-1) goto x_truncated;
-
-    if (typei->diff_needswap) {
-      for (place= nrrs;
-          place>0 && typei->diff_needswap(rrsdata+(place-1)*typei->rrsz,
-                                          rrsdata+nrrs*typei->rrsz);
-          place--);
-      if (place != nrrs) {
-       memcpy(qu->vb.buf,rrsdata+nrrs*typei->rrsz,typei->rrsz);
-       memmove(rrsdata+(place+1)*typei->rrsz,
-               rrsdata+place*typei->rrsz,
-               (nrrs-place)*typei->rrsz);
-       memcpy(rrsdata+place*typei->rrsz,qu->vb.buf,typei->rrsz);
-      }
-    }
     nrrs++;
   }
   assert(nrrs==wantedrrs);
index 94b79d2f164a2d2b37c7325e3010546a74a83100..0f5e5470e7c1e8cac5f4c2c213fb51d73c498c77 100644 (file)
@@ -34,7 +34,7 @@ static int dip_inaddr(struct in_addr a, struct in_addr b) {
 
 static adns_status pa_inaddr(adns_query qu, int serv,
                             const byte *dgram, int dglen, int cbyte, int max,
-                            void *datap) {
+                            int nsstart, int *arstart_io, void *datap) {
   struct in_addr *storeto= datap;
   
   if (max-cbyte != 4) return adns_s_invaliddata;
@@ -58,7 +58,7 @@ static adns_status cs_inaddr(vbuf *vb, const void *datap) {
 
 static adns_status pa_addr(adns_query qu, int serv,
                           const byte *dgram, int dglen, int cbyte, int max,
-                          void *datap) {
+                          int nsstart, int *arstart_io, void *datap) {
   adns_addr *storeto= datap;
   
   if (max-cbyte != 4) return adns_s_invaliddata;
@@ -117,7 +117,7 @@ static adns_status pap_domain(adns_query qu, int serv, parsedomain_flags flags,
 
 static adns_status pa_host_raw(adns_query qu, int serv,
                               const byte *dgram, int dglen, int cbyte, int max,
-                              void *datap) {
+                              int nsstart, int *arstart_io, void *datap) {
   char **rrp= datap;
   adns_status st;
 
@@ -132,7 +132,7 @@ static adns_status pa_host_raw(adns_query qu, int serv,
 
 static adns_status pa_mx_raw(adns_query qu, int serv,
                             const byte *dgram, int dglen, int cbyte, int max,
-                            void *datap) {
+                            int nsstart, int *arstart_io, void *datap) {
   adns_rr_intstr *rrp= datap;
   adns_status st;
   int pref;
@@ -159,7 +159,7 @@ static int di_mx_raw(const void *datap_a, const void *datap_b) {
 
 static adns_status pa_txt(adns_query qu, int serv,
                          const byte *dgram, int dglen, int startbyte, int max,
-                         void *datap) {
+                         int nsstart, int *arstart_io, void *datap) {
   adns_rr_intstr **rrp= datap, *table, *te;
   int ti, tc, cbyte, l;
 
@@ -320,8 +320,8 @@ static const typeinfo typeinfos[] = {
                                                                           
 #endif
 #if 0 /*fixme*/
-  { adns_r_soa,     "SOA",  "822",   DEEP_MEMB(soa),       pa_soa,        0          },
-  { adns_r_rp,      "RP",   "822",   DEEP_MEMB(strpair),   pa_rp,         0          },
+  { adns_r_soa,     "SOA","822",     DEEP_MEMB(soa),       pa_soa,        0          },
+  { adns_r_rp,      "RP", "822",     DEEP_MEMB(strpair),   pa_rp,         0          },
 #endif
 };