mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Work on fake events.
git-svn-id: file:///svn/unbound/trunk@89 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
71f1b12009
commit
25b2781885
3 changed files with 199 additions and 1 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
12 February 2007: Wouter
|
||||||
|
- work on fake events.
|
||||||
|
|
||||||
9 February 2007: Wouter
|
9 February 2007: Wouter
|
||||||
- replay file reading.
|
- replay file reading.
|
||||||
- fake event setup, it creates fake structures, and teardowns,
|
- fake event setup, it creates fake structures, and teardowns,
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
#include "services/outside_network.h"
|
#include "services/outside_network.h"
|
||||||
#include "testcode/replay.h"
|
#include "testcode/replay.h"
|
||||||
#include "testcode/ldns-testpkts.h"
|
#include "testcode/ldns-testpkts.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
/** Global variable: the scenario. Saved here for when event_init is done. */
|
/** Global variable: the scenario. Saved here for when event_init is done. */
|
||||||
static struct replay_scenario* saved_scenario = NULL;
|
static struct replay_scenario* saved_scenario = NULL;
|
||||||
|
|
@ -68,6 +69,27 @@ fake_event_cleanup()
|
||||||
saved_scenario = NULL;
|
saved_scenario = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** delete a fake pending */
|
||||||
|
static void
|
||||||
|
delete_fake_pending(struct fake_pending* pend)
|
||||||
|
{
|
||||||
|
if(!pend)
|
||||||
|
return;
|
||||||
|
ldns_buffer_free(pend->buffer);
|
||||||
|
ldns_pkt_free(pend->pkt);
|
||||||
|
free(pend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** delete a replay answer */
|
||||||
|
static void
|
||||||
|
delete_replay_answer(struct replay_answer* a)
|
||||||
|
{
|
||||||
|
if(!a)
|
||||||
|
return;
|
||||||
|
ldns_buffer_free(a->buf);
|
||||||
|
free(a);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return: true if pending query matches the now event.
|
* return: true if pending query matches the now event.
|
||||||
*/
|
*/
|
||||||
|
|
@ -86,6 +108,31 @@ pending_matches_current(struct replay_runtime* runtime)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the range that matches this pending message.
|
||||||
|
* @param runtime: runtime with current moment, and range list.
|
||||||
|
* @param entry: returns the pointer to entry that matches.
|
||||||
|
* @param pend: the pending that the entry must match.
|
||||||
|
* @return: true if a match is found.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pending_find_match(struct replay_runtime* runtime, struct entry** entry,
|
||||||
|
struct fake_pending* pend)
|
||||||
|
{
|
||||||
|
int timenow = runtime->now->time_step;
|
||||||
|
struct replay_range* p = runtime->scenario->range_list;
|
||||||
|
while(p) {
|
||||||
|
if(p->start_step <= timenow && timenow <= p->end_step &&
|
||||||
|
(*entry = find_match(p->match, pend->pkt, pend->transport))) {
|
||||||
|
log_info("matched query time %d in range [%d, %d]",
|
||||||
|
timenow, p->start_step, p->end_step);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p = p->next_range;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See if outgoing pending query matches an entry.
|
* See if outgoing pending query matches an entry.
|
||||||
* @param runtime: runtime.
|
* @param runtime: runtime.
|
||||||
|
|
@ -97,6 +144,16 @@ static int
|
||||||
pending_matches_range(struct replay_runtime* runtime,
|
pending_matches_range(struct replay_runtime* runtime,
|
||||||
struct entry** entry, struct fake_pending** pend)
|
struct entry** entry, struct fake_pending** pend)
|
||||||
{
|
{
|
||||||
|
struct fake_pending* p = runtime->pending_list;
|
||||||
|
/* slow, O(N*N), but it works as advertised with weird matching */
|
||||||
|
while(p) {
|
||||||
|
if(pending_find_match(runtime, entry, p)) {
|
||||||
|
*pend = p;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -111,6 +168,42 @@ answer_callback_from_entry(struct replay_runtime* runtime,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create commpoint (as return address) for a fake incoming query.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fake_front_query(struct replay_runtime* runtime)
|
||||||
|
{
|
||||||
|
struct comm_reply repinfo;
|
||||||
|
ldns_status status;
|
||||||
|
memset(&repinfo, 0, sizeof(repinfo));
|
||||||
|
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
|
||||||
|
repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
|
||||||
|
repinfo.c->buffer = ldns_buffer_new(runtime->bufsize);
|
||||||
|
if(!runtime->now->match->reply_list->reply) {
|
||||||
|
ldns_buffer_write(repinfo.c->buffer,
|
||||||
|
ldns_buffer_begin(runtime->now->match->reply_list->
|
||||||
|
reply_from_hex),
|
||||||
|
ldns_buffer_limit(runtime->now->match->reply_list->
|
||||||
|
reply_from_hex));
|
||||||
|
ldns_buffer_flip(repinfo.c->buffer);
|
||||||
|
} else {
|
||||||
|
status = ldns_pkt2buffer_wire(repinfo.c->buffer,
|
||||||
|
runtime->now->match->reply_list->reply);
|
||||||
|
if(status != LDNS_STATUS_OK) {
|
||||||
|
fatal_exit("could not parse incoming query pkt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* call the callback for incoming queries */
|
||||||
|
if((*runtime->callback_query)(repinfo.c, runtime->cb_arg,
|
||||||
|
NETEVENT_NOERROR, &repinfo)) {
|
||||||
|
/* send immediate reply */
|
||||||
|
comm_point_send_reply(&repinfo);
|
||||||
|
}
|
||||||
|
/* clear it again, in case copy not done properly */
|
||||||
|
memset(&repinfo, 0, sizeof(repinfo));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform actions or checks determined by the moment.
|
* Perform actions or checks determined by the moment.
|
||||||
*/
|
*/
|
||||||
|
|
@ -119,6 +212,50 @@ do_moment(struct replay_runtime* runtime)
|
||||||
{
|
{
|
||||||
if(!runtime->now)
|
if(!runtime->now)
|
||||||
return;
|
return;
|
||||||
|
switch(runtime->now->evt_type) {
|
||||||
|
case repevt_nothing:
|
||||||
|
break;
|
||||||
|
case repevt_front_query:
|
||||||
|
/* call incoming query callback */
|
||||||
|
fake_front_query(runtime);
|
||||||
|
break;
|
||||||
|
case repevt_front_reply:
|
||||||
|
fatal_exit("testbound: query answer not matched");
|
||||||
|
break;
|
||||||
|
case repevt_timeout:
|
||||||
|
/* callback reply routine with timeout */
|
||||||
|
break;
|
||||||
|
case repevt_back_reply:
|
||||||
|
/* callback the reply routine */
|
||||||
|
break;
|
||||||
|
case repevt_back_query:
|
||||||
|
fatal_exit("testbound: back query not matched");
|
||||||
|
break;
|
||||||
|
case repevt_error:
|
||||||
|
/* callback reply routine with error */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal_exit("testbound: unknown event type %d",
|
||||||
|
runtime->now->evt_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string describing the event type.
|
||||||
|
*/
|
||||||
|
static const char*
|
||||||
|
repevt_string(enum replay_event_type t)
|
||||||
|
{
|
||||||
|
switch(t) {
|
||||||
|
case repevt_nothing: return "NOTHING";
|
||||||
|
case repevt_front_query: return "QUERY";
|
||||||
|
case repevt_front_reply: return "CHECK_ANSWER";
|
||||||
|
case repevt_timeout: return "TIMEOUT";
|
||||||
|
case repevt_back_reply: return "REPLY";
|
||||||
|
case repevt_back_query: return "CHECK_OUT_QUERY";
|
||||||
|
case repevt_error: return "ERROR";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -130,6 +267,12 @@ advance_moment(struct replay_runtime* runtime)
|
||||||
if(!runtime->now)
|
if(!runtime->now)
|
||||||
runtime->now = runtime->scenario->mom_first;
|
runtime->now = runtime->scenario->mom_first;
|
||||||
else runtime->now = runtime->now->mom_next;
|
else runtime->now = runtime->now->mom_next;
|
||||||
|
|
||||||
|
if(runtime->now)
|
||||||
|
log_info("testbound: advancing to STEP %d %s",
|
||||||
|
runtime->now->time_step,
|
||||||
|
repevt_string(runtime->now->evt_type));
|
||||||
|
else log_info("testbound: advancing to step: The End.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** run the scenario in event callbacks */
|
/** run the scenario in event callbacks */
|
||||||
|
|
@ -152,6 +295,7 @@ run_scenario(struct replay_runtime* runtime)
|
||||||
advance_moment(runtime);
|
advance_moment(runtime);
|
||||||
}
|
}
|
||||||
} while(runtime->now);
|
} while(runtime->now);
|
||||||
|
log_info("testbound: exiting event loop (success).");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********** Dummy routines ***********/
|
/*********** Dummy routines ***********/
|
||||||
|
|
@ -176,6 +320,7 @@ listen_create(struct comm_base* base,
|
||||||
}
|
}
|
||||||
runtime->callback_query = cb;
|
runtime->callback_query = cb;
|
||||||
runtime->cb_arg = cb_arg;
|
runtime->cb_arg = cb_arg;
|
||||||
|
runtime->bufsize = bufsize;
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,6 +345,23 @@ struct comm_base* comm_base_create()
|
||||||
void comm_base_delete(struct comm_base* b)
|
void comm_base_delete(struct comm_base* b)
|
||||||
{
|
{
|
||||||
struct replay_runtime* runtime = (struct replay_runtime*)b;
|
struct replay_runtime* runtime = (struct replay_runtime*)b;
|
||||||
|
struct fake_pending* p, *np;
|
||||||
|
struct replay_answer* a, *na;
|
||||||
|
if(!runtime)
|
||||||
|
return;
|
||||||
|
runtime->scenario= NULL;
|
||||||
|
p = runtime->pending_list;
|
||||||
|
while(p) {
|
||||||
|
np = p->next;
|
||||||
|
delete_fake_pending(p);
|
||||||
|
p = np;
|
||||||
|
}
|
||||||
|
a = runtime->answer_list;
|
||||||
|
while(a) {
|
||||||
|
na = a->next;
|
||||||
|
delete_replay_answer(a);
|
||||||
|
a = na;
|
||||||
|
}
|
||||||
free(runtime);
|
free(runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,12 +401,14 @@ void
|
||||||
comm_point_send_reply(struct comm_reply* repinfo)
|
comm_point_send_reply(struct comm_reply* repinfo)
|
||||||
{
|
{
|
||||||
/* TODO see if this is checked */
|
/* TODO see if this is checked */
|
||||||
|
log_info("comm_point_send_reply fake");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
comm_point_drop_reply(struct comm_reply* repinfo)
|
comm_point_drop_reply(struct comm_reply* repinfo)
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
log_info("comm_point_drop_reply fake");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct outside_network*
|
struct outside_network*
|
||||||
|
|
@ -278,7 +442,33 @@ void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
|
||||||
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
|
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
|
||||||
comm_point_callback_t* callback, void* callback_arg)
|
comm_point_callback_t* callback, void* callback_arg)
|
||||||
{
|
{
|
||||||
/* TODO create it */
|
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||||
|
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||||
|
sizeof(struct fake_pending));
|
||||||
|
ldns_status status;
|
||||||
|
log_assert(pend);
|
||||||
|
pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet));
|
||||||
|
ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet),
|
||||||
|
ldns_buffer_limit(packet));
|
||||||
|
ldns_buffer_flip(pend->buffer);
|
||||||
|
memcpy(&pend->addr, addr, addrlen);
|
||||||
|
pend->addrlen = addrlen;
|
||||||
|
pend->callback = callback;
|
||||||
|
pend->cb_arg = callback_arg;
|
||||||
|
pend->timeout = timeout;
|
||||||
|
pend->transport = transport_udp;
|
||||||
|
pend->pkt = NULL;
|
||||||
|
status = ldns_buffer2pkt_wire(&pend->pkt, packet);
|
||||||
|
if(status != LDNS_STATUS_OK) {
|
||||||
|
log_err("ldns error parsing udp output packet: %s",
|
||||||
|
ldns_get_errorstr_by_id(status));
|
||||||
|
fatal_exit("Sending unparseable DNS packets to servers!");
|
||||||
|
}
|
||||||
|
log_info("testbound: created fake pending");
|
||||||
|
|
||||||
|
/* add to list */
|
||||||
|
pend->next = runtime->pending_list;
|
||||||
|
runtime->pending_list = pend;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********** End of Dummy routines ***********/
|
/*********** End of Dummy routines ***********/
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,9 @@ struct replay_runtime {
|
||||||
void (*sig_cb)(int, void*);
|
void (*sig_cb)(int, void*);
|
||||||
/** signal handler user arg */
|
/** signal handler user arg */
|
||||||
void *sig_cb_arg;
|
void *sig_cb_arg;
|
||||||
|
|
||||||
|
/** size of buffers */
|
||||||
|
size_t bufsize;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -228,6 +231,8 @@ struct fake_pending {
|
||||||
comm_point_callback_t* callback;
|
comm_point_callback_t* callback;
|
||||||
/** callback user argument */
|
/** callback user argument */
|
||||||
void* cb_arg;
|
void* cb_arg;
|
||||||
|
/** original timeout in seconds from 'then' */
|
||||||
|
int timeout;
|
||||||
|
|
||||||
/** next in pending list */
|
/** next in pending list */
|
||||||
struct fake_pending* next;
|
struct fake_pending* next;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue