From: Wouter Wijngaards Date: Tue, 22 Jan 2008 14:17:44 +0000 (+0000) Subject: bg query and result code. X-Git-Tag: release-0.9~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3adebc8721d1f76e4b9cb4d3df2896b2ae08d2af;p=thirdparty%2Funbound.git bg query and result code. git-svn-id: file:///svn/unbound/trunk@886 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index a5c90b5e8..696f2b0bb 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/libunbound/context.c b/libunbound/context.c index 0c0d8154e..965a967a9 100644 --- a/libunbound/context.c +++ b/libunbound/context.c @@ -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; } diff --git a/libunbound/context.h b/libunbound/context.h index 29a3a9db2..6a57c32ca 100644 --- a/libunbound/context.h +++ b/libunbound/context.h @@ -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 diff --git a/libunbound/unbound.c b/libunbound/unbound.c index 1d0392e28..9e1de576e 100644 --- a/libunbound/unbound.c +++ b/libunbound/unbound.c @@ -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)) diff --git a/libunbound/worker.c b/libunbound/worker.c index fe9fdefe2..965eaa8b7 100644 --- a/libunbound/worker.c +++ b/libunbound/worker.c @@ -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) diff --git a/libunbound/worker.h b/libunbound/worker.h index e3950524b..b7c1ffb64 100644 --- a/libunbound/worker.h +++ b/libunbound/worker.h @@ -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 */