chiark / gitweb /
Does further A lookups and uses answers.
authorian <ian>
Sun, 15 Nov 1998 21:22:29 +0000 (21:22 +0000)
committerian <ian>
Sun, 15 Nov 1998 21:22:29 +0000 (21:22 +0000)
src/adns.h
src/internal.h
src/query.c
src/types.c

index 938fb18..a87767a 100644 (file)
@@ -133,13 +133,13 @@ typedef struct {
     struct sockaddr sa;
     struct sockaddr_in inet;
   } addr;
-} adns_addr;
+} adns_rr_addr;
 
 typedef struct {
   char *host;
   adns_status astatus;
   int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */
-  adns_addr *addrs;
+  adns_rr_addr *addrs;
 } adns_rr_hostaddr;
 
 typedef struct {
@@ -176,7 +176,7 @@ typedef struct {
     unsigned char *bytes;
     char *(*str);                     /* ns_raw, cname, ptr, ptr_raw */
     adns_rr_intstr *(*manyistr);      /* txt (list of strings ends with i=-1, str=0) */
-    adns_addr *addr;                  /* addr */
+    adns_rr_addr *addr;               /* addr */
     struct in_addr *inaddr;           /* a */
     adns_rr_hostaddr *hostaddr;       /* ns */
     adns_rr_strpair *strpair;         /* hinfo ??fixme, rp, rp_raw */
index f1f4d96..33086f6 100644 (file)
@@ -77,7 +77,12 @@ typedef struct {
 
 typedef union {
   void *ext;
-  adns_rr_hostaddr *hostaddr;
+  struct {
+    void (*callback)(adns_query parent, adns_query child);
+    union {
+      adns_rr_hostaddr *hostaddr;
+    } info;
+  } intern;
 } qcontext;
 
 typedef struct {
@@ -125,7 +130,7 @@ typedef struct {
 } typeinfo;
 
 typedef struct allocnode {
-  struct allocnode *next;
+  struct allocnode *next, *back;
 } allocnode;
 
 union maxalign {
@@ -143,7 +148,7 @@ struct adns__query {
   adns_query back, next, parent;
   struct { adns_query head, tail; } children;
   struct { adns_query back, next; } siblings;
-  struct allocnode *allocations;
+  struct { allocnode *head, *tail; } allocations;
   int interim_allocd;
   void *final_allocspace;
   
@@ -358,6 +363,16 @@ void *adns__alloc_interim(adns_query qu, size_t sz);
  * but it will not necessarily return a distinct pointer each time.
  */
 
+void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz);
+/* Transfers an interim allocation from one query to another, so that
+ * the `to' query will have room for the data when we get to makefinal
+ * and so that the free will happen when the `to' query is freed
+ * rather than the `from' query.
+ *
+ * It is legal to call adns__transfer_interim with a null pointer; this
+ * has no effect.
+ */
+
 void *adns__alloc_mine(adns_query qu, size_t sz);
 /* Like _interim, but does not record the length for later
  * copying into the answer.  This just ensures that the memory
@@ -538,10 +553,10 @@ static inline int ctype_alpha(int c) {
 
 #define LIST_UNLINK_PART(list,node,part) \
   do { \
-    if ((node)->back) (node)->back->part next= (node)->part next; \
-      else                        (list).head= (node)->part next; \
-    if ((node)->next) (node)->next->part back= (node)->part back; \
-      else                        (list).tail= (node)->part back; \
+    if ((node)->part back) (node)->part back->part next= (node)->part next; \
+      else                                  (list).head= (node)->part next; \
+    if ((node)->part next) (node)->part next->part back= (node)->part back; \
+      else                                  (list).tail= (node)->part back; \
   } while(0)
 
 #define LIST_LINK_TAIL_PART(list,node,part) \
index 8c39caa..7c15a5b 100644 (file)
@@ -46,7 +46,7 @@ int adns__internal_submit(adns_state ads, adns_query *query_r,
   qu->back= qu->next= qu->parent= 0;
   LIST_INIT(qu->children);
   qu->siblings.next= qu->siblings.back= 0;
-  qu->allocations= 0;
+  LIST_INIT(qu->allocations);
   qu->interim_allocd= 0;
   qu->final_allocspace= 0;
 
@@ -160,8 +160,7 @@ static void *alloc_common(adns_query qu, size_t sz) {
   assert(!qu->final_allocspace);
   an= malloc(MEM_ROUND(MEM_ROUND(sizeof(*an)) + sz));
   if (!an) return 0;
-  an->next= qu->allocations;
-  qu->allocations= an;
+  LIST_LINK_TAIL(qu->allocations,an);
   return (byte*)an + MEM_ROUND(sizeof(*an));
 }
 
@@ -175,6 +174,22 @@ void *adns__alloc_mine(adns_query qu, size_t sz) {
   return alloc_common(qu,MEM_ROUND(sz));
 }
 
+void adns__transfer_interim(adns_query from, adns_query to, void *block, size_t sz) {
+  allocnode *an;
+
+  if (!block) return;
+  an= (void*)((byte*)block - MEM_ROUND(sizeof(*an)));
+
+  assert(!to->final_allocspace);
+  assert(!from->final_allocspace);
+  
+  LIST_UNLINK(from->allocations,an);
+  LIST_LINK_TAIL(to->allocations,an);
+
+  from->interim_allocd -= sz;
+  to->interim_allocd += sz;
+}
+
 void *adns__alloc_final(adns_query qu, size_t sz) {
   /* When we're in the _final stage, we _subtract_ from interim_alloc'd
    * each allocation, and use final_allocspace to point to the next free
@@ -207,7 +222,7 @@ static void free_query_allocs(adns_query qu) {
     ncqu= cqu->siblings.next;
     adns_cancel(cqu);
   }
-  for (an= qu->allocations; an; an= ann) { ann= an->next; free(an); }
+  for (an= qu->allocations.head; an; an= ann) { ann= an->next; free(an); }
   adns__vbuf_free(&qu->vb);
 }
 
@@ -229,26 +244,16 @@ void adns_cancel(adns_query qu) {
   free(qu->answer);
   free(qu);
 }
-  
-void adns__query_done(adns_query qu) {
+
+static void makefinal_query(adns_query qu) {
   adns_answer *ans;
   int rrn;
 
   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);
-      return;
-    }
+    if (!ans) goto x_nomem;
     qu->answer= ans;
   }
 
@@ -260,19 +265,45 @@ void adns__query_done(adns_query qu) {
 
     for (rrn=0; rrn<ans->nrrs; rrn++)
       qu->typei->makefinal(qu, ans->rrs.bytes + rrn*ans->rrsz);
-
-    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);
+  return;
   
+ x_nomem:
+  qu->answer->status= adns_s_nolocalmem;
+  qu->answer->cname= 0;
+  adns__reset_cnameonly(qu);
+  free_query_allocs(qu);
+}
+
+void adns__query_done(adns_query qu) {
+  adns_answer *ans;
+  adns_query parent;
+
   qu->id= -1;
-  LIST_LINK_TAIL(qu->ads->output,qu);
+  ans= qu->answer;
+
+  if (ans->nrrs && qu->typei->diff_needswap) {
+    if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
+      adns__query_fail(qu,adns_s_nolocalmem);
+      return;
+    }
+    adns__isort(ans->rrs.bytes, ans->nrrs, ans->rrsz,
+               qu->vb.buf, qu->typei->diff_needswap);
+  }
 
-  assert(!qu->parent);
-  /* fixme: do something with the answers to internally-generated queries. */
+  parent= qu->parent;
+  if (parent) {
+    LIST_UNLINK_PART(parent->children,qu,siblings.);
+    qu->context.intern.callback(parent,qu);
+    free_query_allocs(qu);
+    free(qu);
+    if (!parent->children.head) adns__query_done(parent);
+  } else {
+    makefinal_query(qu);
+    LIST_LINK_TAIL(qu->ads->output,qu);
+  }
 }
 
 void adns__query_fail(adns_query qu, adns_status stat) {
index e494ab3..0050b77 100644 (file)
@@ -228,7 +228,7 @@ static adns_status cs_inaddr(vbuf *vb, const void *datap) {
  */
 
 static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap) {
-  adns_addr *storeto= datap;
+  adns_rr_addr *storeto= datap;
   const byte *dgram= pai->dgram;
 
   if (max-cbyte != 4) return adns_s_invaliddata;
@@ -241,13 +241,13 @@ static adns_status pa_addr(const parseinfo *pai, int cbyte, int max, void *datap
 }
 
 static int di_addr(const void *datap_a, const void *datap_b) {
-  const adns_addr *ap= datap_a, *bp= datap_b;
+  const adns_rr_addr *ap= datap_a, *bp= datap_b;
 
   assert(ap->addr.sa.sa_family == AF_INET);
   return dip_inaddr(ap->addr.inet.sin_addr,bp->addr.inet.sin_addr);
 }
 
-static adns_status csp_addr(vbuf *vb, const adns_addr *rrp) {
+static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) {
   const char *ia;
   static char buf[30];
 
@@ -266,7 +266,7 @@ static adns_status csp_addr(vbuf *vb, const adns_addr *rrp) {
 }
 
 static adns_status cs_addr(vbuf *vb, const void *datap) {
-  const adns_addr *rrp= datap;
+  const adns_rr_addr *rrp= datap;
 
   return csp_addr(vb,rrp);
 }
@@ -312,7 +312,7 @@ static adns_status pa_host_raw(const parseinfo *pai, int cbyte, int max, void *d
 }
 
 /*
- * _hostaddr   (pap,pa,dip,di,mfp,mf,csp,cs +pap_findaddrs)
+ * _hostaddr   (pap,pa,dip,di,mfp,mf,csp,cs +icb_hostaddr, pap_findaddrs)
  */
 
 static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
@@ -332,23 +332,34 @@ static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
     if (naddrs == -1) {
       naddrs= 0;
     }
-    if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_addr))) R_NOMEM;
-    st= pa_addr(pai, rdstart,rdstart+rdlen, pai->qu->vb.buf + naddrs*sizeof(adns_addr));
+    if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_rr_addr))) R_NOMEM;
+    st= pa_addr(pai, rdstart,rdstart+rdlen,
+               pai->qu->vb.buf + naddrs*sizeof(adns_rr_addr));
     if (st) return st;
     naddrs++;
   }
   if (naddrs >= 0) {
-    ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_addr));
+    ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_rr_addr));
     if (!ha->addrs) R_NOMEM;
-    memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_addr));
+    memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_rr_addr));
     ha->naddrs= naddrs;
     ha->astatus= adns_s_ok;
 
-    adns__isort(ha->addrs, naddrs, sizeof(adns_addr), pai->qu->vb.buf, di_addr);
+    adns__isort(ha->addrs, naddrs, sizeof(adns_rr_addr), pai->qu->vb.buf, di_addr);
   }
   return adns_s_ok;
 }
 
+static void icb_hostaddr(adns_query parent, adns_query child) {
+  adns_rr_hostaddr *rrp= child->context.intern.info.hostaddr;
+  adns_answer *cans= child->answer;
+
+  rrp->astatus= cans->status;
+  rrp->naddrs= cans->nrrs;
+  rrp->addrs= cans->rrs.addr;
+  adns__transfer_interim(child, parent, rrp->addrs, rrp->naddrs*sizeof(adns_rr_addr));
+}
+
 static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
                                int max, adns_rr_hostaddr *rrp) {
   adns_status st;
@@ -381,8 +392,9 @@ static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
                            pai->dgram, pai->dglen, dmstart,
                            adns_r_addr, adns_qf_quoteok_query);
   if (st) return st;
-  
-  ctx.hostaddr= rrp;
+
+  ctx.intern.callback= icb_hostaddr;
+  ctx.intern.info.hostaddr= rrp;
   st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_addr),
                            &pai->qu->vb, id,
                            adns_qf_quoteok_query, pai->now, 0, &ctx);