2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

checkpoint

This commit is contained in:
Michael Graff 1999-07-08 02:50:00 +00:00
parent 2b71bc3d51
commit 1ec39fc7a8
2 changed files with 474 additions and 59 deletions

View File

@ -35,6 +35,14 @@
#include "../isc/util.h" #include "../isc/util.h"
/*
* If we cannot send to this task, the application is broken.
*/
#define ISC_TASK_SEND(a, b) do { \
RUNTIME_CHECK(isc_task_send(a, b) == ISC_R_SUCCESS); \
} while (0)
struct dns_dispentry { struct dns_dispentry {
unsigned int magic; unsigned int magic;
dns_messageid_t id; dns_messageid_t id;
@ -43,8 +51,9 @@ struct dns_dispentry {
isc_task_t *task; isc_task_t *task;
isc_taskaction_t action; isc_taskaction_t action;
void *arg; void *arg;
isc_boolean_t item_out;
ISC_LIST(dns_dispatchevent_t) items; ISC_LIST(dns_dispatchevent_t) items;
ISC_LINK(dns_dispentry_t) link; ISC_LINK(dns_dispentry_t) link;
}; };
#define INVALID_BUCKET (0xffffdead) #define INVALID_BUCKET (0xffffdead)
@ -63,6 +72,12 @@ struct dns_dispatch {
isc_mempool_t *epool; /* memory pool for events */ isc_mempool_t *epool; /* memory pool for events */
isc_mempool_t *bpool; /* memory pool for buffers */ isc_mempool_t *bpool; /* memory pool for buffers */
isc_mempool_t *rpool; /* memory pool request/reply */ isc_mempool_t *rpool; /* memory pool request/reply */
dns_dispatchevent_t *failsafe_ev; /* failsafe cancel event */
unsigned int recvs; /* recv() calls outstanding */
unsigned int recvs_wanted; /* recv() calls wanted */
unsigned int shutting_down : 1,
shutdown_out : 1;
dns_result_t shutdown_why;
ISC_LIST(dns_dispentry_t) rq_handlers; /* request handler list */ ISC_LIST(dns_dispentry_t) rq_handlers; /* request handler list */
ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */ ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
isc_int32_t qid_state; /* state generator info */ isc_int32_t qid_state; /* state generator info */
@ -83,13 +98,93 @@ struct dns_dispatch {
/* /*
* statics. * statics.
*/ */
static dns_dispentry_t *bucket_search(dns_dispatch_t *, isc_sockaddr_t *, static dns_dispentry_t *
dns_messageid_t, unsigned int); bucket_search(dns_dispatch_t *, isc_sockaddr_t *,
static void destroy(dns_dispatch_t *); dns_messageid_t, unsigned int);
static void udp_recv(isc_task_t *, isc_event_t *);
static dns_result_t startrecv(dns_dispatch_t *); static void
static dns_messageid_t randomid(dns_dispatch_t *); destroy(dns_dispatch_t *);
static unsigned int hash(dns_dispatch_t *, isc_sockaddr_t *, dns_messageid_t);
static void
udp_recv(isc_task_t *, isc_event_t *);
static void
startrecv(dns_dispatch_t *);
static dns_messageid_t
randomid(dns_dispatch_t *);
static unsigned int
hash(dns_dispatch_t *, isc_sockaddr_t *, dns_messageid_t);
static void
free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
static void *
allocate_buffer(dns_dispatch_t *disp, unsigned int len);
static inline void
free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
static inline dns_dispatchevent_t *
allocate_event(dns_dispatch_t *disp);
static inline isc_boolean_t
ok_to_kill(dns_dispatch_t *disp);
static void
do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp);
static void
do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp);
static void
do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp);
static dns_dispentry_t *
linear_first(dns_dispatch_t *disp);
static dns_dispentry_t *
linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp);
static dns_dispentry_t *
linear_first(dns_dispatch_t *disp)
{
dns_dispentry_t *ret;
unsigned int bucket;
bucket = 0;
while (bucket < disp->qid_hashsize) {
ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
if (ret != NULL)
return (ret);
bucket++;
}
return (NULL);
}
static dns_dispentry_t *
linear_next(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispentry_t *ret;
unsigned int bucket;
ret = ISC_LIST_NEXT(resp, link);
if (ret != NULL)
return (ret);
bucket = resp->bucket;
while (bucket < disp->qid_hashsize) {
ret = ISC_LIST_HEAD(disp->qid_table[bucket]);
if (ret != NULL)
return (ret);
bucket++;
}
return (NULL);
}
/* /*
* Return a hash of the destination and message id. For now, just return * Return a hash of the destination and message id. For now, just return
@ -120,17 +215,45 @@ randomid(dns_dispatch_t *disp)
return ((dns_messageid_t)disp->qid_state); return ((dns_messageid_t)disp->qid_state);
} }
static inline isc_boolean_t
ok_to_kill(dns_dispatch_t *disp)
{
if (disp->recvs > 0)
return (ISC_FALSE);
if (disp->refcount > 0)
return (ISC_FALSE);
return (ISC_TRUE);
}
/* /*
* Called when refcount reaches 0 at any time. * Called when refcount reaches 0 at any time.
*/ */
static void static void
destroy(dns_dispatch_t *disp) destroy(dns_dispatch_t *disp)
{ {
dns_dispatchevent_t *ev;
disp->magic = 0; disp->magic = 0;
isc_task_detach(&disp->task); isc_task_detach(&disp->task);
isc_socket_detach(&disp->socket); isc_socket_detach(&disp->socket);
/*
* Final cleanup of packets on the request list.
*/
ev = ISC_LIST_HEAD(disp->rq_events);
while (ev != NULL) {
ISC_LIST_UNLINK(disp->rq_events, ev, link);
free_buffer(disp, ev->buffer.base, ev->buffer.length);
free_event(disp, ev);
ev = ISC_LIST_HEAD(disp->rq_events);
}
isc_mempool_put(disp->epool, disp->failsafe_ev);
disp->failsafe_ev = NULL;
isc_mempool_destroy(&disp->rpool); isc_mempool_destroy(&disp->rpool);
isc_mempool_destroy(&disp->bpool); isc_mempool_destroy(&disp->bpool);
isc_mempool_destroy(&disp->epool); isc_mempool_destroy(&disp->epool);
@ -158,6 +281,75 @@ bucket_search(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t id,
return (NULL); return (NULL);
} }
static void
free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len)
{
if (len == disp->buffersize)
isc_mempool_put(disp->bpool, buf);
else
isc_mem_put(disp->mctx, buf, len);
}
static void *
allocate_buffer(dns_dispatch_t *disp, unsigned int len)
{
void *temp;
INSIST(len > 0);
if (len == disp->buffersize)
temp = isc_mempool_get(disp->bpool);
else
temp = isc_mem_get(disp->mctx, len);
return (temp);
}
static inline void
free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev)
{
if (disp->failsafe_ev == ev) {
INSIST(disp->shutdown_out == 1);
disp->shutdown_out = 0;
return;
}
isc_mempool_put(disp->epool, ev);
}
static inline dns_dispatchevent_t *
allocate_event(dns_dispatch_t *disp)
{
dns_dispatchevent_t *ev;
ev = isc_mempool_get(disp->epool);
return (ev);
}
/*
* General flow:
*
* If I/O result == CANCELED, free the buffer and notify everyone as
* the various queues drain.
*
* If I/O is error (not canceled and not success) log it, free the buffer,
* and restart.
*
* If query:
* if no listeners: free the buffer, restart.
* if listener: allocate event, fill in details.
* If cannot allocate, free buffer, restart.
* if rq event queue is not empty, queue. else, send.
* restart.
*
* If response:
* Allocate event, fill in details.
* If cannot allocate, free buffer, restart.
* find target. If not found, free buffer, restart.
* if event queue is not empty, queue. else, send.
* restart.
*/
static void static void
udp_recv(isc_task_t *task, isc_event_t *ev_in) udp_recv(isc_task_t *task, isc_event_t *ev_in)
{ {
@ -167,19 +359,29 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in)
dns_result_t dres; dns_result_t dres;
isc_buffer_t source; isc_buffer_t source;
unsigned int flags; unsigned int flags;
dns_dispentry_t *resp;
dns_dispatchevent_t *rev;
unsigned int bucket;
(void)task; /* shut up compiler */ (void)task; /* shut up compiler */
LOCK(&disp->lock); LOCK(&disp->lock);
if (ev->result != ISC_R_SUCCESS) { if (ev->result != ISC_R_SUCCESS) {
/* /*
* If the recv() was canceled pass the word on. * If the recv() was canceled pass the word on.
* XXXMLG
*/ */
if (ev->result == ISC_R_CANCELED) { if (ev->result == ISC_R_CANCELED) {
free_buffer(disp, ev->region.base, ev->region.length);
isc_event_free(&ev_in); isc_event_free(&ev_in);
INSIST(disp->recvs > 0);
disp->recvs--;
if (disp->recvs == 0 && disp->shutting_down == 0) {
disp->shutdown_why = ISC_R_CANCELED;
disp->shutting_down = 1;
do_cancel(disp, NULL);
}
return; return;
} }
@ -187,6 +389,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in)
* otherwise, on strange error, log it and restart. * otherwise, on strange error, log it and restart.
* XXXMLG * XXXMLG
*/ */
free_buffer(disp, ev->region.base, ev->region.length);
goto restart; goto restart;
} }
@ -197,28 +400,52 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in)
ISC_BUFFERTYPE_BINARY); ISC_BUFFERTYPE_BINARY);
dres = dns_message_peekheader(&source, &id, &flags); dres = dns_message_peekheader(&source, &id, &flags);
if (dres != DNS_R_SUCCESS) { if (dres != DNS_R_SUCCESS) {
free_buffer(disp, ev->region.base, ev->region.length);
/* XXXMLG log something here... */ /* XXXMLG log something here... */
goto restart; goto restart;
} }
/*
* Allocate an event to send to the query or response client, and
* allocate a new buffer for our use.
*/
/* /*
* Look at flags. If query, check to see if we have someone handling * Look at flags. If query, check to see if we have someone handling
* them. If response, look to see where it goes. * them. If response, look to see where it goes.
*/ */
if ((flags & DNS_MESSAGEFLAG_QR) == 0) { if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
/* XXXLMG query */ resp = ISC_LIST_HEAD(disp->rq_handlers);
if (resp == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
rev = allocate_event(disp);
if (rev == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
/* query */
} else { } else {
/* XXXMLG response */ /* response */
rev = allocate_event(disp);
if (rev == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
bucket = hash(disp, &ev->address, id);
resp = bucket_search(disp, &ev->address, id, bucket);
if (resp == NULL) {
free_buffer(disp, ev->region.base, ev->region.length);
goto restart;
}
} }
/* /*
* Restart recv() to get the next packet. * Restart recv() to get the next packet.
*/ */
restart: restart:
dres = startrecv(disp); startrecv(disp);
if (dres != DNS_R_SUCCESS) {
/* XXXMLG kill all people listening, try again? */
}
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
@ -228,35 +455,46 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in)
/* /*
* disp must be locked * disp must be locked
*/ */
static dns_result_t static void
startrecv(dns_dispatch_t *disp) startrecv(dns_dispatch_t *disp)
{ {
isc_sockettype_t socktype; isc_sockettype_t socktype;
isc_result_t res; isc_result_t res;
isc_region_t region; isc_region_t region;
if (disp->shutting_down == 1)
return;
if (disp->recvs >= disp->recvs_wanted)
return;
socktype = isc_socket_gettype(disp->socket); socktype = isc_socket_gettype(disp->socket);
switch (socktype) { while (disp->recvs < disp->recvs_wanted) {
/* switch (socktype) {
* UDP reads are always maximal. /*
*/ * UDP reads are always maximal.
case isc_socket_udp: */
region.length = disp->buffersize; case isc_socket_udp:
region.base = isc_mempool_get(disp->bpool); region.length = disp->buffersize;
if (region.base == NULL) region.base = allocate_buffer(disp, disp->buffersize);
return (DNS_R_NOMEMORY); if (region.base == NULL)
res = isc_socket_recv(disp->socket, &region, ISC_TRUE, return;
disp->task, udp_recv, disp); res = isc_socket_recv(disp->socket, &region, ISC_TRUE,
if (res != ISC_R_SUCCESS) disp->task, udp_recv, disp);
return (res); if (res != ISC_R_SUCCESS) {
break; disp->shutdown_why = res;
case isc_socket_tcp: do_cancel(disp, NULL);
INSIST(1); /* XXXMLG */ return;
break; }
} disp->recvs++;
break;
return (DNS_R_SUCCESS); case isc_socket_tcp:
INSIST(1); /* XXXMLG */
break;
}
}
} }
/* /*
@ -298,6 +536,11 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
disp->socket = NULL; /* set below */ disp->socket = NULL; /* set below */
disp->buffersize = maxbuffersize; disp->buffersize = maxbuffersize;
disp->refcount = 1; disp->refcount = 1;
disp->recvs = 0;
disp->recvs_wanted = 1;
disp->shutting_down = 0;
disp->shutdown_out = 0;
disp->shutdown_why = ISC_R_UNEXPECTED;
ISC_LIST_INIT(disp->rq_handlers); ISC_LIST_INIT(disp->rq_handlers);
ISC_LIST_INIT(disp->rq_events); ISC_LIST_INIT(disp->rq_events);
@ -329,7 +572,6 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
res = DNS_R_NOMEMORY; res = DNS_R_NOMEMORY;
goto out4; goto out4;
} }
isc_mempool_setfreemax(disp->bpool, maxbuffers);
if (isc_mempool_create(mctx, sizeof(dns_dispentry_t), if (isc_mempool_create(mctx, sizeof(dns_dispentry_t),
&disp->rpool) != ISC_R_SUCCESS) { &disp->rpool) != ISC_R_SUCCESS) {
@ -337,9 +579,32 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
goto out5; goto out5;
} }
/*
* Keep some number of items around. This should be a config
* option. For now, keep 8, but later keep at least two even
* if the caller wants less. This allows us to ensure certain
* things, like an event can be "freed" and the next allocation
* will always succeed.
*
* Note that if limits are placed on anything here, we use one
* event internally, so the actual limit should be "wanted + 1."
*
* XXXMLG
*/
isc_mempool_setfreemax(disp->epool, 8);
isc_mempool_setfreemax(disp->bpool, 8);
isc_mempool_setfreemax(disp->rpool, 8);
disp->failsafe_ev = allocate_event(disp);
if (disp->failsafe_ev == NULL) {
res = DNS_R_NOMEMORY;
goto out6;
}
/* /*
* should initialize qid_state here XXXMLG * should initialize qid_state here XXXMLG
*/ */
disp->qid_state = (unsigned int)disp;
disp->magic = DISPATCH_MAGIC; disp->magic = DISPATCH_MAGIC;
@ -353,10 +618,8 @@ dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
/* /*
* error returns * error returns
*/ */
#if 0 /* enable when needed */
out6: out6:
isc_mempool_destroy(&disp->respool); isc_mempool_destroy(&disp->rpool);
#endif
out5: out5:
isc_mempool_destroy(&disp->bpool); isc_mempool_destroy(&disp->bpool);
out4: out4:
@ -382,14 +645,11 @@ dns_dispatch_destroy(dns_dispatch_t **dispp)
disp = *dispp; disp = *dispp;
*dispp = NULL; *dispp = NULL;
killit = ISC_FALSE;
LOCK(&disp->lock); LOCK(&disp->lock);
INSIST(disp->refcount > 0); INSIST(disp->refcount > 0);
disp->refcount--; disp->refcount--;
if (disp->refcount == 0) killit = ok_to_kill(disp);
killit = ISC_TRUE;
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
@ -451,6 +711,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
res->task = task; res->task = task;
res->action = action; res->action = action;
res->arg = arg; res->arg = arg;
res->item_out = ISC_FALSE;
ISC_LIST_INIT(res->items); ISC_LIST_INIT(res->items);
ISC_LINK_INIT(res, link); ISC_LINK_INIT(res, link);
ISC_LIST_APPEND(disp->qid_table[bucket], res, link); ISC_LIST_APPEND(disp->qid_table[bucket], res, link);
@ -460,6 +721,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
*idp = id; *idp = id;
*resp = res; *resp = res;
startrecv(disp);
return (DNS_R_SUCCESS); return (DNS_R_SUCCESS);
} }
@ -479,8 +742,6 @@ dns_dispatch_removeresponse(dns_dispatch_t *disp, dns_dispentry_t **resp,
res = *resp; res = *resp;
*resp = NULL; *resp = NULL;
killit = ISC_FALSE;
if (sockevent != NULL) { if (sockevent != NULL) {
REQUIRE(*sockevent != NULL); REQUIRE(*sockevent != NULL);
ev = *sockevent; ev = *sockevent;
@ -493,8 +754,7 @@ dns_dispatch_removeresponse(dns_dispatch_t *disp, dns_dispentry_t **resp,
INSIST(disp->refcount > 0); INSIST(disp->refcount > 0);
disp->refcount--; disp->refcount--;
if (disp->refcount == 0) killit = ok_to_kill(disp);
killit = ISC_TRUE;
res->magic = 0; res->magic = 0;
bucket = res->bucket; bucket = res->bucket;
@ -502,6 +762,14 @@ dns_dispatch_removeresponse(dns_dispatch_t *disp, dns_dispentry_t **resp,
ISC_LIST_UNLINK(disp->qid_table[bucket], res, link); ISC_LIST_UNLINK(disp->qid_table[bucket], res, link);
isc_mempool_put(disp->rpool, res); isc_mempool_put(disp->rpool, res);
if (ev != NULL) {
free_buffer(disp, ev->buffer.base, ev->buffer.length);
free_event(disp, ev);
}
if (disp->shutting_down == 1)
do_cancel(disp, NULL);
startrecv(disp);
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
@ -533,6 +801,7 @@ dns_dispatch_addrequest(dns_dispatch_t *disp,
res->task = task; res->task = task;
res->action = action; res->action = action;
res->arg = arg; res->arg = arg;
res->item_out = ISC_FALSE;
ISC_LIST_INIT(res->items); ISC_LIST_INIT(res->items);
ISC_LINK_INIT(res, link); ISC_LINK_INIT(res, link);
ISC_LIST_APPEND(disp->rq_handlers, res, link); ISC_LIST_APPEND(disp->rq_handlers, res, link);
@ -541,6 +810,8 @@ dns_dispatch_addrequest(dns_dispatch_t *disp,
*resp = res; *resp = res;
startrecv(disp);
return (DNS_R_SUCCESS); return (DNS_R_SUCCESS);
} }
@ -559,8 +830,6 @@ dns_dispatch_removerequest(dns_dispatch_t *disp, dns_dispentry_t **resp,
res = *resp; res = *resp;
*resp = NULL; *resp = NULL;
killit = ISC_FALSE;
if (sockevent != NULL) { if (sockevent != NULL) {
REQUIRE(*sockevent != NULL); REQUIRE(*sockevent != NULL);
ev = *sockevent; ev = *sockevent;
@ -573,17 +842,150 @@ dns_dispatch_removerequest(dns_dispatch_t *disp, dns_dispentry_t **resp,
INSIST(disp->refcount > 0); INSIST(disp->refcount > 0);
disp->refcount--; disp->refcount--;
if (disp->refcount == 0) killit = ok_to_kill(disp);
killit = ISC_TRUE;
res->magic = 0; res->magic = 0;
ISC_LIST_UNLINK(disp->rq_handlers, res, link); ISC_LIST_UNLINK(disp->rq_handlers, res, link);
isc_mempool_put(disp->rpool, res); isc_mempool_put(disp->rpool, res);
if (ev != NULL) {
if (ev->buffer.length != 0)
free_buffer(disp, ev->buffer.base, ev->buffer.length);
free_event(disp, ev);
}
startrecv(disp);
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
if (killit) if (killit)
destroy(disp); destroy(disp);
} }
void
dns_dispatch_freeevent(dns_dispatch_t *disp, dns_dispentry_t *resp,
dns_dispatchevent_t **sockevent)
{
dns_dispatchevent_t *ev;
isc_boolean_t response;
REQUIRE(VALID_DISPATCH(disp));
REQUIRE(sockevent != NULL && *sockevent != NULL);
ev = *sockevent;
*sockevent = NULL;
response = ISC_FALSE;
if (VALID_RESPONSE(resp)) {
response = ISC_TRUE;
} else {
REQUIRE(VALID_RESPONSE(resp) || VALID_REQUEST(resp));
}
LOCK(&disp->lock);
REQUIRE(ev != disp->failsafe_ev);
free_buffer(disp, ev->buffer.base, ev->buffer.length);
free_event(disp, ev);
if (response)
do_next_response(disp, resp);
else
do_next_request(disp, resp);
startrecv(disp);
UNLOCK(&disp->lock);
}
static void
do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispatchevent_t *ev;
INSIST(resp->item_out == ISC_FALSE);
ev = ISC_LIST_HEAD(resp->items);
if (ev == NULL) {
if (disp->shutting_down == 1)
do_cancel(disp, resp);
return;
}
ISC_LIST_UNLINK(disp->rq_events, ev, link);
ev->action = resp->action;
ev->arg = resp->arg;
ev->sender = resp;
resp->item_out = ISC_TRUE;
ISC_TASK_SEND(resp->task, (isc_event_t **)&ev);
}
static void
do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
dns_dispatchevent_t *ev;
INSIST(resp->item_out == ISC_FALSE);
ev = ISC_LIST_HEAD(disp->rq_events);
if (ev == NULL) {
if (disp->shutting_down == 1)
do_cancel(disp, resp);
return;
}
ISC_LIST_UNLINK(disp->rq_events, ev, link);
ev->action = resp->action;
ev->arg = resp->arg;
ev->sender = resp;
resp->item_out = ISC_TRUE;
ISC_TASK_SEND(resp->task, (isc_event_t **)&ev);
}
static void
do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp)
{
if (disp->shutdown_out == 1)
return;
/*
* If no target given, find the first request handler. If
* there are packets waiting for any handler, however, don't
* kill them.
*/
if (resp == NULL) {
resp = ISC_LIST_HEAD(disp->rq_handlers);
if (resp != NULL && resp->item_out == ISC_FALSE)
resp = NULL;
}
/*
* Search for the first responce handler without packets outstanding.
*/
if (resp == NULL) {
resp = linear_first(disp); /* no first item? */
if (resp == NULL)
return;
do {
if (resp->item_out == ISC_FALSE)
break;
resp = linear_next(disp, resp);
} while (resp != NULL);
/*
* No one to send the cancel event to, so nothing to do.
*/
if (resp == NULL)
return;
}
/*
* Send the shutdown failsafe event to this response critter IFF
* the queue is empty. If it is not empty, defer.
*/
}

View File

@ -67,17 +67,11 @@ struct dns_dispatchevent {
dns_result_t result; /* result code */ dns_result_t result; /* result code */
isc_int16_t id; /* message id */ isc_int16_t id; /* message id */
isc_sockaddr_t addr; /* address recv'd from */ isc_sockaddr_t addr; /* address recv'd from */
unsigned int lattributes; /* some private, some public */
isc_buffer_t buffer; /* data buffer */ isc_buffer_t buffer; /* data buffer */
}; };
typedef struct dns_dispentry dns_dispentry_t; typedef struct dns_dispentry dns_dispentry_t;
/*
* Private attributes of events
*/
#define DNS_DISPATCHATTR_MPOOL 0x00010000 /* allocated via mpool */
dns_result_t dns_result_t
dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, dns_dispatch_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
unsigned int maxbuffersize, unsigned int maxbuffersize,
@ -222,7 +216,8 @@ dns_dispatch_removerequest(dns_dispatch_t *disp, dns_dispentry_t **resp,
*/ */
void void
dns_dispatch_freeevent(dns_dispatch_t *disp, dns_dispatchevent_t **sockevent); dns_dispatch_freeevent(dns_dispatch_t *disp, dns_dispentry_t *resp,
dns_dispatchevent_t **sockevent);
/* /*
* Return a dispatchevent and associated buffer to the dispatch. This needs * Return a dispatchevent and associated buffer to the dispatch. This needs
* to be called if more events are desired but a particular event is fully * to be called if more events are desired but a particular event is fully
@ -242,12 +237,30 @@ void
dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp); dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
/* /*
* Attach to a dispatch handle. * Attach to a dispatch handle.
*
* Requires:
* < mumble >
*
* Ensures:
* < mumble >
*
* Returns:
* < mumble >
*/ */
void void
dns_dispatch_detach(dns_dispatch_t **dispp); dns_dispatch_detach(dns_dispatch_t **dispp);
/* /*
* Detach from a dispatch handle. * Detach from a dispatch handle.
*
* Requires:
* < mumble >
*
* Ensures:
* < mumble >
*
* Returns:
* < mumble >
*/ */
ISC_LANG_ENDDECLS ISC_LANG_ENDDECLS