callbacks via module specific function for walk_supers.

part of a move towards multiple modules for meshes.


git-svn-id: file:///svn/unbound/trunk@471 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-08-01 14:01:34 +00:00
parent 56916e48fb
commit 2122b961d3
4 changed files with 84 additions and 21 deletions

View file

@ -215,10 +215,12 @@ error_response(struct module_qstate* qstate, int id, int rcode)
verbose(VERB_DETAIL, "return error response %s",
ldns_lookup_by_id(ldns_rcodes, rcode)?
ldns_lookup_by_id(ldns_rcodes, rcode)->name:"??");
qstate->return_rcode = rcode;
qstate->return_msg = NULL;
/* tell clients that we failed */
(*qstate->env->query_done)(qstate, rcode, NULL);
/* tell our parents that we failed */
(*qstate->env->walk_supers)(qstate, id, &error_supers);
(*qstate->env->walk_supers)(qstate, id, NULL);
qstate->ext_state[id] = module_finished;
return 0;
}
@ -1179,17 +1181,13 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
static void
prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq)
{
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id];
struct delegpt* dp = NULL;
enum response_type type = response_type_from_server(iq->response,
&iq->qchase, iq->dp);
log_assert(qstate->is_priming || foriq->wait_priming_stub);
if(type == RESPONSE_TYPE_ANSWER) {
/* Convert our response to a delegation point */
dp = delegpt_from_message(iq->response, forq->region);
}
log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR);
/* Convert our response to a delegation point */
dp = delegpt_from_message(qstate->return_msg, forq->region);
if(!dp) {
/* if there is no convertable delegation point, then
* the ANSWER type was (presumably) a negative answer. */
@ -1200,10 +1198,10 @@ prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq)
return;
}
log_query_info(VERB_DETAIL, "priming successful for", &iq->qchase);
log_query_info(VERB_DETAIL, "priming successful for", &qstate->qinfo);
delegpt_log(dp);
foriq->dp = dp;
foriq->deleg_msg = dns_copy_msg(iq->response, forq->region);
foriq->deleg_msg = dns_copy_msg(qstate->return_msg, forq->region);
if(!foriq->deleg_msg) {
log_err("copy prime response: out of memory");
foriq->dp = NULL;
@ -1235,6 +1233,17 @@ prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq)
static int
processPrimeResponse(struct module_qstate* qstate, int id)
{
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
enum response_type type = response_type_from_server(iq->response,
&iq->qchase, iq->dp);
if(type == RESPONSE_TYPE_ANSWER) {
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
} else {
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
qstate->return_msg = NULL;
}
/* This event is finished. */
qstate->ext_state[id] = module_finished;
@ -1242,7 +1251,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
* bugger off (and retry) */
(*qstate->env->query_done)(qstate, LDNS_RCODE_SERVFAIL, NULL);
/* tell interested supers that priming is done */
(*qstate->env->walk_supers)(qstate, id, &prime_supers);
(*qstate->env->walk_supers)(qstate, id, NULL);
return 0;
}
@ -1267,6 +1276,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id];
struct ub_packed_rrset_key* rrset;
struct delegpt_ns* dpns;
log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR);
foriq->state = QUERYTARGETS_STATE;
@ -1293,7 +1303,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
* the original event.
* NOTE: we could only look for the AnswerRRset if the
* response type was ANSWER. */
rrset = reply_find_answer_rrset(&iq->qchase, iq->response->rep);
rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep);
if(rrset) {
/* if CNAMEs have been followed - add new NS to delegpt. */
/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */
@ -1363,13 +1373,36 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
/* use server supplied upper/lower case */
qstate->qinfo.qname = iq->response->qinfo.qname;
}
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
(*qstate->env->query_done)(qstate, LDNS_RCODE_NOERROR,
iq->response->rep);
(*qstate->env->walk_supers)(qstate, id, &processTargetResponse);
(*qstate->env->walk_supers)(qstate, id, NULL);
return 0;
}
/**
* Return priming query results to interestes super querystates.
*
* Sets the delegation point and delegation message (not nonRD queries).
* This is a callback from walk_supers.
*
* @param qstate: query state that finished.
* @param id: module id.
* @param super: the qstate to inform.
*/
static void
iter_inform_super(struct module_qstate* qstate, int id,
struct module_qstate* super)
{
if(qstate->return_rcode != LDNS_RCODE_NOERROR)
error_supers(qstate, id, super);
if(qstate->is_priming)
prime_supers(qstate, id, super);
else processTargetResponse(qstate, id, super);
}
/**
* Handle iterator state.
* Handle events. This is the real processing loop for events, responsible
@ -1567,7 +1600,8 @@ iter_clear(struct module_qstate* qstate, int id)
*/
static struct module_func_block iter_block = {
"iterator",
&iter_init, &iter_deinit, &iter_operate, &iter_clear
&iter_init, &iter_deinit, &iter_operate, &iter_inform_super,
&iter_clear
};
struct module_func_block*

View file

@ -231,7 +231,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
mstate->s.reply = NULL;
mstate->s.region = region;
mstate->s.curmod = 0;
mstate->s.return_rep = 0;
mstate->s.return_msg = 0;
mstate->s.return_rcode = LDNS_RCODE_NOERROR;
mstate->s.env = env;
mstate->s.mesh_info = mstate;
@ -483,12 +483,14 @@ void mesh_walk_supers(struct module_qstate* qstate, int id,
struct mesh_state_ref* ref;
log_assert(!(m->debug_flags&2)); /* not twice! */
m->debug_flags |= 2;
(void)cb;
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->super_set)
{
/* make super runnable */
(void)rbtree_insert(&mesh->run, &ref->s->run_node);
/* callback */
(*cb)(qstate, id, &ref->s->s);
/* callback the function to inform super of result */
(*mesh->modfunc[ref->s->s.curmod]->inform_super)(qstate,
id, &ref->s->s);
}
}

View file

@ -276,9 +276,9 @@ struct module_qstate {
/** comm_reply contains server replies */
struct comm_reply* reply;
/** the reply info, with message for client, calling module */
struct reply_info* return_rep;
/** the rcode, in case of error, instead of a reply info message */
/** the reply message, with message for client and calling module */
struct dns_msg* return_msg;
/** the rcode, in case of error, instead of a reply message */
int return_rcode;
/** region for this query. Cleared when query process finishes. */
struct region* region;
@ -339,6 +339,19 @@ struct module_func_block {
*/
void (*operate)(struct module_qstate* qstate, enum module_ev event,
int id, struct outbound_entry* outbound);
/**
* inform super querystate about the results from this subquerystate.
* Is called when the querystate is finished.
* @param qstate: the query state that is finished.
* Examine return_rcode and return_reply in the qstate.
* @param id: module id for this module.
* This coincides with the current module for the super qstate.
* @param super: the super querystate that needs to be informed.
*/
void (*inform_super)(struct module_qstate* qstate, int id,
struct module_qstate* super);
/**
* clear module specific data
*/

View file

@ -89,6 +89,20 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
(void)outbound;
}
/**
* inform validator super.
*
* @param qstate: query state that finished.
* @param id: module id.
* @param super: the qstate to inform.
*/
static void
val_inform_super(struct module_qstate* qstate, int id,
struct module_qstate* super)
{
}
/** validator cleanup query state */
static void
val_clear(struct module_qstate* qstate, int id)
@ -104,7 +118,7 @@ val_clear(struct module_qstate* qstate, int id)
*/
static struct module_func_block val_block = {
"validator",
&val_init, &val_deinit, &val_operate, &val_clear
&val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear
};
struct module_func_block*