bg query and result code.

git-svn-id: file:///svn/unbound/trunk@886 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-01-22 14:17:44 +00:00
parent 1a4fadaf00
commit 3adebc8721
6 changed files with 110 additions and 21 deletions

View 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.

View 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;
}

View 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

View 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))

View 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)

View 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 */