]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
bg query and result code.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 22 Jan 2008 14:17:44 +0000 (14:17 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 22 Jan 2008 14:17:44 +0000 (14:17 +0000)
git-svn-id: file:///svn/unbound/trunk@886 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
libunbound/context.c
libunbound/context.h
libunbound/unbound.c
libunbound/worker.c
libunbound/worker.h

index a5c90b5e8676eb5407c73776a00b9c72d322d5de..696f2b0bb157b14b4f1ccf1a8a4298fc85ee37c3 100644 (file)
@@ -2,6 +2,7 @@
        - library code for async in libunbound/unbound.c.
        - fix link testbound.
        - fixup exit bug in mini_event.
+       - background worker query enter and result functions.
 
 21 January 2008: Wouter
        - libworker work, netevent raw commpoints, write_msg, serialize.
index 0c0d8154ec5e6c929db74160a0f051e2a1a4229d..965a967a9a441be04b7e5a391e055ebc79ce620f 100644 (file)
@@ -95,6 +95,15 @@ int context_query_cmp(const void* a, const void* b)
        return 0;
 }
 
+void
+context_query_delete(struct ctx_query* q) 
+{
+       if(!q) return;
+       ub_val_result_free(q->res);
+       free(q->msg);
+       free(q);
+}
+
 /** How many times to try to find an unused query-id-number for async */
 #define NUM_ID_TRIES 100000
 /** find next useful id number of 0 on error */
@@ -242,7 +251,8 @@ context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
 }
 
 uint8_t* 
-context_serialize_answer(struct ctx_query* q, int err, uint32_t* len)
+context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt,
+       uint32_t* len)
 {
        /* answer format
         *      o uint32 cmd
@@ -252,15 +262,17 @@ context_serialize_answer(struct ctx_query* q, int err, uint32_t* len)
         *      o the remainder is the answer msg from resolver lookup.
         *        remainder can be length 0.
         */
+       size_t pkt_len = pkt?ldns_buffer_remaining(pkt):0;
        uint8_t* p;
-       *len = sizeof(uint32_t)*4 + q->msg_len;
+       *len = sizeof(uint32_t)*4 + pkt_len;
        p = (uint8_t*)malloc(*len);
        if(!p) return NULL;
        ldns_write_uint32(p, UB_LIBCMD_ANSWER);
        ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
        ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err);
        ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security);
-       memmove(p+4*sizeof(uint32_t), q->msg, q->msg_len);
+       if(pkt_len > 0)
+               memmove(p+4*sizeof(uint32_t), ldns_buffer_begin(pkt), pkt_len);
        return p;
 }
 
index 29a3a9db2b732224c665fb610569be38658ffa8a..6a57c32ca7d0001e6dfe27e26d3101fae6339081 100644 (file)
@@ -204,6 +204,12 @@ int context_finalize(struct ub_val_ctx* ctx);
 /** compare two ctx_query elements */
 int context_query_cmp(const void* a, const void* b);
 
+/** 
+ * delete context query
+ * @param q: query to delete, including message packet and prealloc result
+ */
+void context_query_delete(struct ctx_query* q);
+
 /**
  * Create new query in context, add to querynum list.
  * @param ctx: context
@@ -247,10 +253,12 @@ uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len);
  * As well as command code 'answer'.
  * @param q: context query
  * @param err: error code to pass to client.
+ * @param pkt: the packet to add, can be NULL.
  * @param len: the length of the allocation is returned.
  * @return: an alloc, or NULL on mem error.
  */
-uint8_t* context_serialize_answer(struct ctx_query* q, int err, uint32_t* len);
+uint8_t* context_serialize_answer(struct ctx_query* q, int err, 
+       ldns_buffer* pkt, uint32_t* len);
 
 /**
  * Serialize a query cancellation. Serializes query async id
index 1d0392e28e4f44a964ce32a3331a2404819e9579..9e1de576ec6f616bb6ea1d3a1950a2c596a95ab5 100644 (file)
@@ -105,16 +105,6 @@ ub_val_ctx_create()
        return ctx;
 }
 
-/** delete context query */
-static void
-context_query_delete(struct ctx_query* q) 
-{
-       if(!q) return;
-       ub_val_result_free(q->res);
-       free(q->msg);
-       free(q);
-}
-
 /** delete q */
 static void
 delq(rbnode_t* n, void* ATTR_UNUSED(arg))
index fe9fdefe26a9f9568133fe27e89e245878c84391..965eaa8b74e857dc2a67b767309474762f5d4156 100644 (file)
@@ -59,6 +59,7 @@
 #include "util/net_help.h"
 #include "util/data/dname.h"
 #include "util/data/msgreply.h"
+#include "util/data/msgencode.h"
 
 /** size of table used for random numbers. large to be more secure. */
 #define RND_STATE_SIZE 256
@@ -350,8 +351,7 @@ fill_res(struct ub_val_result* res, struct ub_packed_rrset_key* answer,
        if(query_dname_compare(rq->qname, answer->rk.dname) != 0) {
                if(!fill_canon(res, answer->rk.dname))
                        return 0; /* out of memory */
-       } else
-               res->canonname = res->qname;
+       } else  res->canonname = NULL;
        res->data = (char**)calloc(data->count+1, sizeof(char*));
        res->len = (int*)calloc(data->count+1, sizeof(int));
        if(!res->data || !res->len)
@@ -399,7 +399,7 @@ libworker_enter_result(struct ub_val_result* res, ldns_buffer* buf,
 static void
 libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
 {
-       struct libworker_fg_data* d = (struct libworker_fg_data*)arg;
+       struct libworker_cb_data* d = (struct libworker_cb_data*)arg;
        /* fg query is done; exit comm base */
        comm_base_exit(d->w->base);
 
@@ -454,7 +454,7 @@ int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q)
        uint16_t qflags, qid;
        struct query_info qinfo;
        struct edns_data edns;
-       struct libworker_fg_data d;
+       struct libworker_cb_data d;
        if(!w)
                return UB_INITFAIL;
        if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
@@ -471,6 +471,7 @@ int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q)
                libworker_fg_done_cb(&d, LDNS_RCODE_NOERROR, 
                        w->back->udp_buff, sec_status_insecure);
                libworker_delete(w);
+               free(qinfo.qname);
                return UB_NOERROR;
        }
        /* process new query */
@@ -488,16 +489,93 @@ int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q)
        return UB_NOERROR;
 }
 
+/** add result to the bg worker result queue */
+static void
+add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt, 
+       int err)
+{
+       uint8_t* msg = NULL;
+       uint32_t len = 0;
+       struct libworker_res_list* item;
+
+       /* serialize and delete unneeded q */
+       msg = context_serialize_answer(q, err, pkt, &len);
+       (void)rbtree_delete(&w->ctx->queries, q->node.key);
+       context_query_delete(q);
+
+       if(!msg) {
+               log_err("out of memory for async answer");
+               return;
+       }
+       item = (struct libworker_res_list*)malloc(sizeof(*item));
+       if(!item) {
+               free(msg);
+               log_err("out of memory for async answer");
+               return;
+       }
+       item->buf = msg;
+       item->len = len;
+       item->next = NULL;
+       /* add at back of list */
+       if(w->res_last)
+               w->res_last->next = item;
+       else    w->res_list = item;
+       w->res_last = item;
+       if(w->res_list == w->res_last) {
+               /* first added item, start the write process */
+               comm_point_start_listening(w->res_com, -1, -1);
+       }
+}
+
+/** callback with bg results */
+static void
+libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
+{
+       struct libworker_cb_data* d = (struct libworker_cb_data*)arg;
+
+       d->q->msg_security = s;
+       if(rcode != 0) {
+               error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
+       }
+       add_bg_result(d->w, d->q, buf, UB_NOERROR);
+}
+
+
 /** handle new query command for bg worker */
 static void
 handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
 {
+       uint16_t qflags, qid;
+       struct query_info qinfo;
+       struct edns_data edns;
+       struct libworker_cb_data d;
        struct ctx_query* q = context_deserialize_new_query(w->ctx, buf, len);
        if(!q) {
                log_err("failed to deserialize newq");
                return;
        }
-       /* TODO start new query in bg mode */
+       if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
+               add_bg_result(w, q, NULL, UB_SYNTAX);
+               return;
+       }
+       qid = 0;
+       qflags = BIT_RD;
+       d.q = q;
+       d.w = w;
+       /* see if there is a fixed answer */
+       if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns, 
+               w->back->udp_buff, w->env->scratch)) {
+               q->msg_security = sec_status_insecure;
+               add_bg_result(w, q, w->back->udp_buff, UB_NOERROR);
+               free(qinfo.qname);
+               return;
+       }
+       /* process new query */
+       if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 
+               w->back->udp_buff, qid, libworker_bg_done_cb, &d)) {
+               add_bg_result(w, q, NULL, UB_NOMEM);
+       }
+       free(qinfo.qname);
 }
 
 void libworker_alloc_cleanup(void* arg)
index e3950524b2bd9feab2c044359f687b8770f4205b..b7c1ffb6446b2776561fd97ac347a65e03ac4b30 100644 (file)
@@ -92,9 +92,9 @@ struct libworker {
 };
 
 /**
- * Foreground query cb struct
+ * Libworker query cb struct
  */
-struct libworker_fg_data {
+struct libworker_cb_data {
        /** the worker involved */
        struct libworker* w;
        /** the query involved */