mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
bg query and result code.
git-svn-id: file:///svn/unbound/trunk@886 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
1a4fadaf00
commit
3adebc8721
6 changed files with 110 additions and 21 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue