2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-07 01:55:21 +00:00
Files
bind/lib/omapi/dispatch.c
David Lawrence 904f1ab394 checkpoint
2000-01-06 23:56:51 +00:00

334 lines
7.9 KiB
C

/*
* Copyright (C) 1996, 1997, 1998, 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/* $Id: dispatch.c,v 1.5 2000/01/06 23:52:59 tale Exp $ */
/* Principal Author: Ted Lemon */
/*
* I/O dispatcher.
*/
#include <stddef.h> /* NULL */
#include <string.h> /* memset */
#include <isc/assertions.h>
#include <isc/int.h>
#include <omapi/private.h>
typedef struct omapi_io_object {
OMAPI_OBJECT_PREAMBLE;
struct omapi_io_object * next;
int (*readfd) (omapi_object_t *);
int (*writefd)(omapi_object_t *);
isc_result_t (*reader) (omapi_object_t *);
isc_result_t (*writer) (omapi_object_t *);
isc_result_t (*reaper) (omapi_object_t *);
} omapi_io_object_t;
typedef struct omapi_waiter_object {
OMAPI_OBJECT_PREAMBLE;
struct omapi_waiter_object * next;
int ready;
} omapi_waiter_object_t;
static omapi_io_object_t omapi_io_states;
isc_uint32_t cur_time;
isc_result_t
omapi_dispatch(struct timeval *t) {
/*
* XXXDCL sleep forever? The socket thread will be doing all the work.
*/
select(0, NULL, NULL, NULL, t ? t : NULL);
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_wait_for_completion(omapi_object_t *object, struct timeval *t) {
isc_result_t result;
omapi_waiter_object_t *waiter;
omapi_object_t *inner;
if (object != NULL) {
result = omapi_object_new((omapi_object_t **)&waiter,
omapi_type_waiter, sizeof(*waiter));
if (result != ISC_R_SUCCESS)
return (result);
/*
* Paste the waiter object onto the inner object we're
* waiting on.
*/
for (inner = object; inner->inner != NULL;
inner = inner->inner)
;
OBJECT_REF(&waiter->outer, inner, "omapi_wait_for_completion");
OBJECT_REF(&inner->inner, waiter, "omapi_wait_for_completion");
} else
waiter = NULL;
do {
result = omapi_one_dispatch((omapi_object_t *)waiter, t);
if (result != ISC_R_SUCCESS)
return (result);
} while (waiter == NULL || waiter->ready == 0);
if (waiter->outer != NULL) {
if (waiter->outer->inner != NULL) {
OBJECT_DEREF(&waiter->outer->inner,
"omapi_wait_for_completion");
if (waiter->inner != NULL)
OBJECT_REF(&waiter->outer->inner, waiter->inner,
"omapi_wait_for_completion");
}
OBJECT_DEREF(&waiter->outer, "omapi_wait_for_completion");
}
if (waiter->inner != NULL)
OBJECT_DEREF(&waiter->inner, "omapi_wait_for_completion");
OBJECT_DEREF(&waiter, "omapi_wait_for_completion");
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_one_dispatch(omapi_object_t *wo, struct timeval *t) {
fd_set r, w, x;
int count;
int desc;
int max = 0;
struct timeval now, to;
omapi_io_object_t *io, *prev;
isc_result_t result;
omapi_waiter_object_t *waiter;
if (wo == NULL || wo->type != omapi_type_waiter)
waiter = NULL;
else
waiter = (omapi_waiter_object_t *)wo;
FD_ZERO(&r);
FD_ZERO(&w);
FD_ZERO(&x);
/*
* First, see if the timeout has expired, and if so return.
*/
if (t != NULL) {
gettimeofday(&now, NULL);
cur_time = now.tv_sec;
if (now.tv_sec > t->tv_sec ||
(now.tv_sec == t->tv_sec && now.tv_usec >= t->tv_usec))
return (ISC_R_TIMEDOUT);
/*
* We didn't time out, so figure out how long until we do.
*/
to.tv_sec = t->tv_sec - now.tv_sec;
to.tv_usec = t->tv_usec - now.tv_usec;
if (to.tv_usec < 0) {
to.tv_usec += 1000000;
to.tv_sec--;
}
}
/*
* If the object we're waiting on has reached completion,
* return now.
*/
if (waiter != NULL && waiter->ready != 0)
return (ISC_R_SUCCESS);
/*
* If we have no I/O state, we can't proceed.
*/
io = omapi_io_states.next;
if (io == NULL)
return (ISC_R_NOMORE);
/*
* Set up the read and write masks.
*/
for (; io != NULL; io = io->next) {
/*
* Check for a read socket. If we shouldn't be
* trying to read for this I/O object, either there
* won't be a readfd function, or it'll return -1.
*/
if (io->readfd != NULL) {
desc = (*(io->readfd))(io->inner);
FD_SET(desc, &r);
if (desc > max)
max = desc;
}
/*
* Same deal for write fdsets.
*/
if (io->writefd != NULL) {
desc = (*(io->writefd))(io->inner);
FD_SET(desc, &w);
if (desc > max)
max = desc;
}
}
/*
* Wait for a packet or a timeout. XXXTL
*/
count = select(max + 1, &r, &w, &x, t ? &to : NULL);
/*
* Get the current time.
*/
gettimeofday(&now, NULL);
cur_time = now.tv_sec;
/*
* Not likely to be transitory.
*/
if (count < 0)
return (ISC_R_UNEXPECTED);
for (io = omapi_io_states.next; io != NULL; io = io->next) {
/*
* Check for a read descriptor, and if there is one,
* see if we got input on that socket.
*/
if (io->readfd != NULL &&
(desc = (*(io->readfd))(io->inner)) >= 0) {
if (FD_ISSET(desc, &r))
result = (*(io->reader))(io->inner);
/* XXXTL what to do with result? */
}
/*
* Same deal for write descriptors.
*/
if (io->writefd != NULL &&
(desc = (*(io->writefd))(io->inner)) >= 0) {
if (FD_ISSET(desc, &w))
result = (*(io->writer))(io->inner);
/* XXX what to do with result? */
}
}
/*
* Now check for I/O handles that are no longer valid,
* and remove them from the list.
*/
prev = NULL;
for (io = omapi_io_states.next; io != NULL; io = io->next) {
if (io->reaper != NULL) {
result = (*(io->reaper))(io->inner);
if (result != ISC_R_SUCCESS) {
omapi_io_object_t *tmp = NULL;
/*
* Save a reference to the next
* pointer, if there is one.
*/
if (io->next != NULL)
OBJECT_REF(&tmp, io->next, "omapi_wfc");
if (prev != NULL) {
OBJECT_DEREF(&prev->next, "omapi_wfc");
if (tmp != NULL)
OBJECT_REF(&prev->next, tmp,
"omapi_wfc");
} else {
OBJECT_DEREF(&omapi_io_states.next,
"omapi_wfc");
if (tmp != NULL)
OBJECT_REF(&omapi_io_states.next,
tmp, "omapi_wfc");
else
omapi_signal_in
((omapi_object_t *)
&omapi_io_states,
"ready");
}
if (tmp != NULL)
OBJECT_DEREF(&tmp, "omapi_wfc");
}
}
prev = io;
}
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_io_setvalue(omapi_object_t *io, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
{
REQUIRE(io != NULL && io->type == omapi_type_io_object);
PASS_SETVALUE(io);
}
isc_result_t
omapi_io_getvalue(omapi_object_t *io, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
{
REQUIRE(io != NULL && io->type == omapi_type_io_object);
PASS_GETVALUE(io);
}
void
omapi_io_destroy(omapi_object_t *io, const char *name) {
REQUIRE(io != NULL && io->type == omapi_type_io_object);
(void)name; /* Unused. */
}
isc_result_t
omapi_io_signalhandler(omapi_object_t *io, const char *name, va_list ap)
{
REQUIRE(io != NULL && io->type == omapi_type_io_object);
PASS_SIGNAL(io);
}
isc_result_t
omapi_io_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *io)
{
REQUIRE(io != NULL && io->type == omapi_type_io_object);
PASS_STUFFVALUES(io);
}
isc_result_t
omapi_waiter_signal_handler(omapi_object_t *h, const char *name, va_list ap) {
omapi_waiter_object_t *waiter;
REQUIRE(h != NULL && h->type == omapi_type_waiter);
if (strcmp(name, "ready") == 0) {
waiter = (omapi_waiter_object_t *)h;
waiter->ready = 1;
return (ISC_R_SUCCESS);
}
PASS_SIGNAL(h);
}