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

checkpoint

This commit is contained in:
David Lawrence 2000-01-17 18:02:11 +00:00
parent 9ff3698b6d
commit eb421ff1a1
12 changed files with 857 additions and 928 deletions

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: connection.c,v 1.8 2000/01/14 23:10:01 tale Exp $ */
/* $Id: connection.c,v 1.9 2000/01/17 18:02:04 tale Exp $ */
/* Principal Author: Ted Lemon */
@ -88,6 +88,12 @@ free_connection(omapi_connection_object_t *connection) {
*/
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS);
/*
* This one is locked too, unlock it so it can be destroyed.
*/
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock) ==
ISC_R_SUCCESS);
while ((buffer = ISC_LIST_HEAD(connection->input_buffers)) != NULL) {
ISC_LIST_UNLINK(connection->input_buffers, buffer, link);
isc_buffer_free(&buffer);
@ -104,37 +110,11 @@ free_connection(omapi_connection_object_t *connection) {
if (connection->socket != NULL)
isc_socket_detach(&connection->socket);
/*
* It is possible the connection was abandoned while a message
* was being assembled. That thread needs to be unblocked.
* Make sure that when it is awakened, it exits the loop by
* setting messages_expected to 0.
*/
if (connection->is_client) {
connection->messages_expected = 0;
REQUIRE(isc_condition_signal(&connection->waiter) ==
ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_destroy(&connection->waiter) ==
ISC_R_SUCCESS);
}
/* XXXDCL ok, but what happens when omapi_connection_wait
* awakens and then tries to unlock the mutex, which is possibly
* being destroyed right here. i don't think relocking is
* a guarantee that isc_condition_wait exited and the mutex was
* unlocked in omapi_connection_wait. still, it's worth a shot.
*/
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_destroy(&connection->mutex) == ISC_R_SUCCESS);
/*
* Disconnect from I/O object, if any.
*/
if (connection->outer != NULL)
OBJECT_DEREF(&connection->outer,
"omapi_connection_disconnect");
RUNTIME_CHECK(isc_mutex_destroy(&connection->recv_lock) ==
ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_destroy(&connection->waiter) ==
ISC_R_SUCCESS);
/*
* If whatever created us registered a signal handler, send it
@ -142,10 +122,20 @@ free_connection(omapi_connection_object_t *connection) {
*/
omapi_signal((omapi_object_t *)connection, "disconnect", connection);
#if 0
/*
* Free the inner generic object via the protocol object.
* XXXDCL wildass stab in the dark
*/
OBJECT_DEREF(&connection->inner->inner);
#endif
/*
* Finally, free the object itself.
*/
OBJECT_DEREF(&connection, "free_connection");
OBJECT_DEREF(&connection);
}
static void
@ -161,6 +151,12 @@ end_connection(omapi_connection_object_t *connection, isc_event_t *event,
* think this can be done with the connection as the object.
*/
/*
* Don't proceed until recv_done() has finished whatever
* it was doing that decremented events_pending to 0.
*/
RUNTIME_CHECK(isc_mutex_lock(&connection->recv_lock) == ISC_R_SUCCESS);
/*
* Lock the connection's mutex to examine connection->events_pending.
*/
@ -170,11 +166,37 @@ end_connection(omapi_connection_object_t *connection, isc_event_t *event,
connection->events_pending);
if (connection->events_pending == 0) {
free_connection(connection);
if (connection->waiting) {
/*
* This must have been an error, since
* omapi_connection_wait can't be called after
* omapi_connection_disconnect is called for
* a normal close.
*
* Signal omapi_connection_wait and have it do the
* cleanup. free_connection can't be called
* directly here because it can't be sure
* that the mutex has been finished being touched
* by omapi_connection_wait even if it
* free_connection signals it. (Nasty little
* race condition with the lock.)
*
* Make sure that when it is awakened, it exits its
* wait loop by setting messages_expected to 0.
*/
connection->state = omapi_connection_closed;
connection->messages_expected = 0;
RUNTIME_CHECK(isc_condition_signal(&connection->waiter)
== ISC_R_SUCCESS);
} else
free_connection(connection);
return;
}
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock) ==
ISC_R_SUCCESS);
/*
@ -208,7 +230,7 @@ connect_done(isc_task_t *task, isc_event_t *event) {
fprintf(stderr, "CONNECT_DONE\n");
ENSURE(socket == connection->socket && task == connection->task);
INSIST(socket == connection->socket && task == connection->task);
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
/*
@ -217,7 +239,7 @@ connect_done(isc_task_t *task, isc_event_t *event) {
* only in recv_done. I'm concerned that there might be some
* sort of logic window, however small, where that isn't true.
*/
ENSURE(connection->events_pending > 0);
INSIST(connection->events_pending > 0);
if (--connection->events_pending == 0 && connection->is_client &&
connection->state == omapi_connection_disconnecting)
FATAL_ERROR(__FILE__, __LINE__,
@ -273,10 +295,40 @@ recv_done(isc_task_t *task, isc_event_t *event) {
fprintf(stderr, "RECV_DONE, %d bytes\n", socketevent->n);
ENSURE(socket == connection->socket && task == connection->task);
INSIST(socket == connection->socket && task == connection->task);
/*
* XXXDCL This recv_lock is a dirty, ugly, nasty hack and I
* am ashamed for it. I have struggled for days with how to
* prevent the driving progam's call of omapi_connection_disconnect
* from conflicting with the execution of the task thread
* (this one, where recv_done is being called).
*
* Basically, most of the real work happens in the task thread,
* all kicked off by signalling "ready" a few lines below. If
* this recv_done() is processing the last expected bytes of a message,
* then it will wake up the driving program, and the driving program
* can go ahead and issue a disconnect. Since there are neither
* events_pending nor messages_expected, end_connecton goes ahead
* and frees the connection. But that can happen before this
* very function can go finish up what it is doing with the
* connection structure, which is clearly a bad thing.
*
* The regular mutex in the connection (the one named "mutex") is
* being used throughout the code in a much more localized fashion,
* and while it might be possible to more broadly scope it so that
* it essentially does the job that recv_lock is doing, I honestly
* have not yet fully thought that out and I have already burned
* so much time trying other approaches before I struck on this
* recv_lock idea. My gut reaction is I don't like how long
* a lock on 'mutex' would be held, and I am not entirely sure
* that there aren't deadlock situations. I have to think about it
* ... LATER.
*/
RUNTIME_CHECK(isc_mutex_lock(&connection->recv_lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
ENSURE(connection->events_pending > 0);
INSIST(connection->events_pending > 0);
connection->events_pending--;
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS);
@ -295,13 +347,25 @@ recv_done(isc_task_t *task, isc_event_t *event) {
original_bytes_needed = connection->bytes_needed;
/*
* Signal omapi_protocol_signal_handler that the bytes it requested
* are present.
*
* XXXDCL it will then isc_condition_signal the driving thread,
* which is free to go ahead and call omapi_connection_disconnect.
* since there are possibly no more events pending and no more messages
* expected at that point, the driving thread may end up freeing the
* connection before this routine is done manipulating it.
* what a big, ugly, pain in the rump.
*/
while (connection->bytes_needed <= connection->in_bytes &&
connection->bytes_needed > 0)
if (omapi_signal((omapi_object_t *)connection, "ready",
connection) !=
ISC_R_SUCCESS)
connection) != ISC_R_SUCCESS)
goto abandon;
/*
* Queue up another recv request. If the bufferlist is empty,
* then, something under omapi_signal already called
@ -313,20 +377,37 @@ recv_done(isc_task_t *task, isc_event_t *event) {
/*
* See if that was the last event the client was expecting, so
* that the connection can be freed.
* XXXDCL I don't *think* this has to be done in the
* send_done or connect_done handlers, because a normal
* termination will only happen
* that the connection can be freed. This test needs to be
* done, because it is possible omapi_connection_disconnect has
* already been called, before the signal handler managed to
* decrement messages_expected. That means that _disconnect
* set the state to disconnecting but didn't call the
* end_connection routine. If this was the last event,
* no more events are going to come in and call recv_done again,
* so this is the only time that it can be identified that
* the conditions for finally freeing the connection are all true.
*
* XXXDCL I don't *think* this has to be done in the send_done or
* connect_done handlers, because a normal termination (one defined as
* "omapi_connection_disconnect called by the client with 'force' as
* false") will only happen after the last of the expected data is
* received.
*/
if (connection->is_client) {
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS);
if (connection->events_pending == 0 &&
connection->state == omapi_connection_disconnecting) {
ENSURE(connection->messages_expected == 1);
INSIST(connection->messages_expected == 1);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
/*
* omapi_connection_disconnect was called, but
* end_connection has not been. Call it now.
*/
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex)
== ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock)
== ISC_R_SUCCESS);
end_connection(connection, event, ISC_R_SUCCESS);
return;
@ -334,11 +415,15 @@ recv_done(isc_task_t *task, isc_event_t *event) {
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
}
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock) ==
ISC_R_SUCCESS);
isc_event_free(&event);
return;
abandon:
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock) ==
ISC_R_SUCCESS);
end_connection(connection, event, socketevent->result);
return;
}
@ -360,13 +445,13 @@ send_done(isc_task_t *task, isc_event_t *event) {
fprintf(stderr, "SEND_DONE, %d bytes\n", socketevent->n);
ENSURE(socket == connection->socket && task == connection->task);
INSIST(socket == connection->socket && task == connection->task);
/*
* XXXDCL I am assuming that partial writes are not done. I hope this
* does not prove to be incorrect. But the assumption can be tested ...
*/
ENSURE(socketevent->n == connection->out_bytes &&
INSIST(socketevent->n == connection->out_bytes &&
socketevent->n ==
isc_bufferlist_usedcount(&socketevent->bufferlist));
@ -377,7 +462,7 @@ send_done(isc_task_t *task, isc_event_t *event) {
* only in recv_done. I'm concerned that there might be some
* sort of logic window, however small, where that isn't true.
*/
ENSURE(connection->events_pending > 0);
INSIST(connection->events_pending > 0);
if (--connection->events_pending == 0 && connection->is_client &&
connection->state == omapi_connection_disconnecting)
FATAL_ERROR(__FILE__, __LINE__,
@ -421,7 +506,7 @@ connection_send(omapi_connection_object_t *connection) {
REQUIRE(connection->state == omapi_connection_connected);
if (connection->out_bytes > 0) {
ENSURE(!ISC_LIST_EMPTY(connection->output_buffers));
INSIST(!ISC_LIST_EMPTY(connection->output_buffers));
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS);
@ -473,12 +558,13 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
/*
* Create a new connection object.
*/
result = omapi_object_new((omapi_object_t **)&connection,
result = omapi_object_create((omapi_object_t **)&connection,
omapi_type_connection, sizeof(*connection));
if (result != ISC_R_SUCCESS)
goto free_obuffer;
connection->is_client = ISC_TRUE;
connection->waiting = ISC_FALSE;
connection->task = task;
@ -488,6 +574,7 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
ISC_LIST_APPEND(connection->output_buffers, obuffer, link);
RUNTIME_CHECK(isc_mutex_init(&connection->mutex) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&connection->recv_lock) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_init(&connection->waiter) ==
ISC_R_SUCCESS);
@ -503,8 +590,8 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
/*
* Tie the new connection object to the protocol object.
*/
OBJECT_REF(&protocol->outer, connection, "omapi_connection_toserver");
OBJECT_REF(&connection->inner, protocol, "omapi_connection_toserver");
OBJECT_REF(&protocol->outer, connection);
OBJECT_REF(&connection->inner, protocol);
/*
* Create a socket on which to communicate.
@ -522,7 +609,7 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
flag = 1;
if (setsockopt(connection->socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof(flag)) < 0) {
OBJECT_DEREF(&connection, "omapi_connect");
OBJECT_DEREF(&connection);
return (ISC_R_UNEXPECTED);
}
#endif
@ -541,8 +628,8 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
return (ISC_R_SUCCESS);
free_object:
OBJECT_DEREF(&connection, "omapi_connection_toserver");
OBJECT_DEREF(&protocol->outer, "omapi_connection_toserver");
OBJECT_DEREF(&connection);
OBJECT_DEREF(&protocol->outer);
return (result);
free_obuffer:
@ -694,6 +781,12 @@ omapi_connection_copyout(unsigned char *dst, omapi_object_t *generic,
* the protocol.)
*
* The client might or might not want to block on the disconnection.
* Currently the way to accomplish this is to call omapi_connection_wait
* before calling this function. A more complex method could be developed,
* but after spending (too much) time thinking about it, it hardly seems to
* be worth the effort when it is easy to just insist that the
* omapi_connection_wait be done.
*
* Also, if the error is being thrown from the library, the client
* might *already* be waiting on (or intending to wait on) whatever messages
* it has already sent, so it needs to be awakened. That will be handled
@ -733,24 +826,31 @@ omapi_connection_disconnect(omapi_object_t *generic, isc_boolean_t force) {
*/
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS);
INSIST(connection->state == omapi_connection_connected);
connection->state = omapi_connection_disconnecting;
connection->messages_expected++;
/*
* If there are no other messages expected for the socket,
* the end_connection can be done right now. Otherwise,
* when recv_done gets the last output from the server,
* then it will then end the connection.
* If there are other messages expected for the socket,
* then set the state to disconnecting. Based on that
* flag, when recv_done gets the last output from the server,
* it will then end the connection. The reason the state
* is set to disconnecting only here and not while falling
* through to end_connection below is that it is the
* flag which says whether end_connection has been called or
* not.
*/
if (connection->messages_expected > 1) {
connection->state = omapi_connection_disconnecting;
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
return;
}
/*
* ... else fall through.
*/
INSIST(connection->events_pending == 0);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
}
@ -777,23 +877,7 @@ omapi_connection_require(omapi_object_t *generic, unsigned int bytes) {
connection = (omapi_connection_object_t *)generic;
/*
* There is a race condition here that is really, REALLY
* irritating me. Here's the latest attempt at fixing the
* whole dang disconnect problem. It is doomed to fail ...
* but maybe it will do the job for now.
* XXXDCL
*/
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
if (connection->state == omapi_connection_disconnecting &&
connection->messages_expected == 1) {
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
return (OMAPI_R_NOTYET);
}
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS);
ENSURE(connection->state == omapi_connection_connected ||
INSIST(connection->state == omapi_connection_connected ||
connection->state == omapi_connection_disconnecting);
connection->bytes_needed += bytes;
@ -857,38 +941,15 @@ omapi_connection_require(omapi_object_t *generic, unsigned int bytes) {
}
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
/*
* Don't queue any more read requests if the connection is
* disconnecting and no more messages are expected. This situation
* can happen when omapi_connection_disconnect is called before
* omapi_protocol_signal_handler has had a chance to go back to
* its omapi_protocol_header_wait condition where it calls
* omapi_connection_require. It is possible the isc_socket_cancel
* was already done.
* Queue the receive task.
* XXXDCL The "minimum" arg has not been fully thought out.
*/
if (connection->state == omapi_connection_disconnecting &&
connection->messages_expected == 0) {
/*
* Test the above comment's claim that this only happens
* when requesting to wait for the header of the next message.
* XXXDCL
* (omapi_protocol_object_t *)p->inner->header_size should
* be what is checked against, but at the present time
* the protocol_object_t exists only in protocol.c
*/
ENSURE(bytes == 24);
} else {
/*
* Queue the receive task.
* XXXDCL The "minimum" arg has not been fully thought out.
*/
connection->events_pending++;
isc_socket_recvv(connection->socket,
&connection->input_buffers,
(connection->bytes_needed -
connection->in_bytes),
connection->task, recv_done, connection);
}
connection->events_pending++;
isc_socket_recvv(connection->socket, &connection->input_buffers,
connection->bytes_needed - connection->in_bytes,
connection->task, recv_done, connection);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
@ -903,6 +964,14 @@ omapi_connection_require(omapi_object_t *generic, unsigned int bytes) {
* those events can happen before omapi_connection_wait is ever called.
* So a counter needs to be set for every expected message, and this
* function can only return when that counter is 0.
*
* XXXDCL ICK. There is a problem. What if an error that causes disconnection
* is happens before it is detected by the driving program, before this
* function has ever been called, but after all of the connection data
* has been freed.
*
* Actually, that seems to be a problem throughout this WHOLE LIBRARY. It
* really needs to be handled somehow.
*/
isc_result_t
omapi_connection_wait(omapi_object_t *object,
@ -913,7 +982,7 @@ omapi_connection_wait(omapi_object_t *object,
* XXXDCL 'object' is not really used.
*/
omapi_connection_object_t *connection;
isc_result_t result, wait_result;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(object != NULL && connection_handle != NULL);
REQUIRE(connection_handle->type == omapi_type_connection);
@ -922,90 +991,41 @@ omapi_connection_wait(omapi_object_t *object,
/*
* This routine is not valid for server connections.
*/
REQUIRE(connection->is_client);
INSIST(connection->is_client);
result = isc_mutex_lock(&connection->mutex);
if (result != ISC_R_SUCCESS)
return (result);
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
INSIST(connection->state == omapi_connection_connected);
connection->waiting = ISC_TRUE;
wait_result = ISC_R_SUCCESS;
while (connection->messages_expected > 0 &&
wait_result == ISC_R_SUCCESS)
while (connection->messages_expected > 0 && result == ISC_R_SUCCESS)
if (timeout == NULL)
wait_result = isc_condition_wait(&connection->waiter,
&connection->mutex);
result = isc_condition_wait(&connection->waiter,
&connection->mutex);
else
wait_result =
isc_condition_waituntil(&connection->waiter,
&connection->mutex,
timeout);
result = isc_condition_waituntil(&connection->waiter,
&connection->mutex,
timeout);
RUNTIME_CHECK(wait_result == ISC_R_SUCCESS ||
wait_result == ISC_R_TIMEDOUT);
RUNTIME_CHECK(result == ISC_R_SUCCESS || result == ISC_R_TIMEDOUT);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS);
connection->waiting = ISC_FALSE;
return (wait_result);
}
if (connection->state == omapi_connection_closed)
/*
* An error occurred and end_connection needs to have
* free_connection called now that we're done looking
* at connection->messages_expected.
*
* XXXDCL something better to do with the result value?
*/
free_connection(connection);
else
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
isc_result_t
omapi_connection_setvalue(omapi_object_t *connection, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_SETVALUE(connection);
}
isc_result_t
omapi_connection_getvalue(omapi_object_t *connection, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_GETVALUE(connection);
}
void
omapi_connection_destroy(omapi_object_t *handle, const char *name) {
omapi_connection_object_t *connection;
REQUIRE(handle != NULL && handle->type == omapi_type_connection);
(void)name;
connection = (omapi_connection_object_t *)handle;
if (connection->state == omapi_connection_connected)
omapi_connection_disconnect(handle, OMAPI_FORCE_DISCONNECT);
}
isc_result_t
omapi_connection_signalhandler(omapi_object_t *connection, const char *name,
va_list ap)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_SIGNAL(connection);
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
isc_result_t
omapi_connection_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *handle)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_STUFFVALUES(handle);
return (result);
}
/*
@ -1163,3 +1183,71 @@ omapi_connection_puthandle(omapi_object_t *c, omapi_object_t *h) {
return (result);
}
static isc_result_t
connection_setvalue(omapi_object_t *connection, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_SETVALUE(connection);
}
static isc_result_t
connection_getvalue(omapi_object_t *connection, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_GETVALUE(connection);
}
static void
connection_destroy(omapi_object_t *handle) {
omapi_connection_object_t *connection;
REQUIRE(handle != NULL && handle->type == omapi_type_connection);
connection = (omapi_connection_object_t *)handle;
if (connection->state == omapi_connection_connected)
omapi_connection_disconnect(handle, OMAPI_FORCE_DISCONNECT);
}
static isc_result_t
connection_signalhandler(omapi_object_t *connection, const char *name,
va_list ap)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_SIGNAL(connection);
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
static isc_result_t
connection_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *handle)
{
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
PASS_STUFFVALUES(handle);
}
isc_result_t
omapi_connection_init(void) {
return (omapi_object_register(&omapi_type_connection,
"connection",
connection_setvalue,
connection_getvalue,
connection_destroy,
connection_signalhandler,
connection_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: data.c,v 1.2 2000/01/13 06:13:21 tale Exp $ */
/* $Id: data.c,v 1.3 2000/01/17 18:02:05 tale Exp $ */
/* Principal Author: Ted Lemon */
@ -93,8 +93,7 @@ omapi_data_new(omapi_typed_data_t **t, omapi_datatype_t type, ...) {
new->u.buffer.len = val;
break;
case omapi_datatype_object:
OBJECT_REF(&new->u.object, va_arg(l, omapi_object_t *),
"omapi_datatype_new");
OBJECT_REF(&new->u.object, va_arg(l, omapi_object_t *));
break;
}
new->type = type;
@ -117,7 +116,7 @@ omapi_data_reference(omapi_typed_data_t **r, omapi_typed_data_t *h,
}
void
omapi_data_dereference(omapi_typed_data_t **h, const char *name) {
omapi_data_dereference(omapi_typed_data_t **h) {
int length = 0;
@ -138,7 +137,7 @@ omapi_data_dereference(omapi_typed_data_t **h, const char *name) {
(*h)->u.buffer.len;
break;
case omapi_datatype_object:
OBJECT_DEREF(&(*h)->u.object, name);
OBJECT_DEREF(&(*h)->u.object);
length = OMAPI_TYPED_DATA_OBJECT_LEN;
break;
default:
@ -237,7 +236,7 @@ omapi_data_valuedereference(omapi_value_t **h, const char *name) {
if ((*h)->name != NULL)
omapi_data_stringdereference(&(*h)->name, name);
if ((*h)->value != NULL)
omapi_data_dereference(&(*h)->value, name);
omapi_data_dereference(&(*h)->value);
isc_mem_put(omapi_mctx, *h, sizeof(*h));
}
*h = NULL;

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: dispatch.c,v 1.7 2000/01/13 06:13:22 tale Exp $ */
/* $Id: dispatch.c,v 1.8 2000/01/17 18:02:05 tale Exp $ */
/* Principal Author: Ted Lemon */
@ -39,64 +39,3 @@ omapi_dispatch(struct timeval *t) {
select(0, NULL, NULL, NULL, t ? t : NULL);
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;
fprintf(stderr, "omapi_waiter_signal_handler\n");
REQUIRE(h != NULL && h->type == omapi_type_waiter);
if (strcmp(name, "ready") == 0) {
fprintf(stderr, "unblocking waiter\n");
waiter = (omapi_waiter_object_t *)h;
isc_condition_signal(&waiter->ready);
return (ISC_R_SUCCESS);
}
PASS_SIGNAL(h);
}

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: generic.c,v 1.6 2000/01/13 06:13:22 tale Exp $ */
/* $Id: generic.c,v 1.7 2000/01/17 18:02:06 tale Exp $ */
/* Principal Author: Ted Lemon */
@ -29,9 +29,10 @@
#include <omapi/private.h>
#if 0
isc_result_t
omapi_generic_new(omapi_object_t **gen, const char *name) {
omapi_generic_object_t *obj;
omapi_generic_new(omapi_object_t **generic_handle, const char *name) {
omapi_generic_object_t *generic;
obj = isc_mem_get(omapi_mctx, sizeof(*obj));
if (obj == NULL)
@ -40,14 +41,15 @@ omapi_generic_new(omapi_object_t **gen, const char *name) {
obj->refcnt = 0;
obj->type = omapi_type_generic;
OBJECT_REF(gen, obj, name);
OBJECT_REF(gen, obj);
return (ISC_R_SUCCESS);
}
#endif
isc_result_t
omapi_generic_set_value(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
static isc_result_t
generic_setvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
{
omapi_generic_object_t *g;
omapi_value_t *new;
@ -161,9 +163,9 @@ omapi_generic_set_value(omapi_object_t *h, omapi_object_t *id,
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_generic_get_value(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
static isc_result_t
generic_getvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
{
unsigned int i;
omapi_generic_object_t *g;
@ -196,8 +198,8 @@ omapi_generic_get_value(omapi_object_t *h, omapi_object_t *id,
PASS_GETVALUE(h);
}
void
omapi_generic_destroy(omapi_object_t *h, const char *name) {
static void
generic_destroy(omapi_object_t *h) {
omapi_generic_object_t *g;
unsigned int i;
@ -209,7 +211,7 @@ omapi_generic_destroy(omapi_object_t *h, const char *name) {
for (i = 0; i < g->nvalues; i++)
if (g->values[i] != NULL)
omapi_data_valuedereference(&g->values[i],
name);
NULL);
isc_mem_put(omapi_mctx, g->values,
g->va_max * sizeof(*g->values));
@ -218,8 +220,8 @@ omapi_generic_destroy(omapi_object_t *h, const char *name) {
}
}
isc_result_t
omapi_generic_signal_handler(omapi_object_t *h, const char *name, va_list ap) {
static isc_result_t
generic_signalhandler(omapi_object_t *h, const char *name, va_list ap) {
REQUIRE(h != NULL && h->type == omapi_type_generic);
@ -230,10 +232,9 @@ omapi_generic_signal_handler(omapi_object_t *h, const char *name, va_list ap) {
* Write all the published values associated with the object through the
* specified connection.
*/
isc_result_t
omapi_generic_stuff_values(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *h)
static isc_result_t
generic_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *h)
{
omapi_generic_object_t *src;
unsigned int i;
@ -265,3 +266,15 @@ omapi_generic_stuff_values(omapi_object_t *connection, omapi_object_t *id,
PASS_STUFFVALUES(h);
}
isc_result_t
omapi_generic_init(void) {
return (omapi_object_register(&omapi_type_generic,
"generic",
generic_setvalue,
generic_getvalue,
generic_destroy,
generic_signalhandler,
generic_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: handle.c,v 1.4 2000/01/13 06:13:23 tale Exp $ */
/* $Id: handle.c,v 1.5 2000/01/17 18:02:06 tale Exp $ */
/* Principal Author: Ted Lemon */
@ -176,8 +176,7 @@ omapi_object_handle_in_table(omapi_handle_t h, omapi_handle_table_t *table,
* appropriate place.
*/
if (table->leaf) {
OBJECT_REF(&table->children[h - table->first].object, o,
"omapi_object_handle_in_table");
OBJECT_REF(&table->children[h - table->first].object, o);
o->handle = h;
return (ISC_R_SUCCESS);
}
@ -296,8 +295,7 @@ omapi_handle_lookup_in(omapi_object_t **o, omapi_handle_t h,
if (table->children[h - table->first].object == NULL)
return (ISC_R_NOTFOUND);
OBJECT_REF(o, table->children[h - table->first].object,
"omapi_handle_lookup_in");
OBJECT_REF(o, table->children[h - table->first].object);
return (ISC_R_SUCCESS);
}

View File

@ -52,6 +52,11 @@ typedef struct omapi_typed_data omapi_typed_data_t;
typedef struct omapi_data_string omapi_data_string_t;
typedef struct omapi_value omapi_value_t;
/*
* This preamble is common to all objects manipulated by libomapi.a,
* including specials objects created by external users of the library.
* It needs to be at the start of every struct that gets used as an object.
*/
#define OMAPI_OBJECT_PREAMBLE \
omapi_object_type_t * type; \
size_t object_size; \
@ -168,25 +173,11 @@ struct omapi_object_type {
/*
* For use with omapi_connection_disconnect().
* XXXDCL rename
*/
#define OMAPI_FORCE_DISCONNECT ISC_TRUE
#define OMAPI_CLEAN_DISCONNECT ISC_FALSE
/*****
***** Global Variables.
*****/
extern omapi_object_type_t *omapi_type_connection;
extern omapi_object_type_t *omapi_type_listener;
extern omapi_object_type_t *omapi_type_io_object;
extern omapi_object_type_t *omapi_type_generic;
extern omapi_object_type_t *omapi_type_protocol;
extern omapi_object_type_t *omapi_type_protocol_listener;
extern omapi_object_type_t *omapi_type_waiter;
extern omapi_object_type_t *omapi_type_remote;
extern omapi_object_type_t *omapi_type_message;
extern omapi_object_type_t *omapi_object_types;
/*****
***** Function Prototypes.
*****/
@ -221,7 +212,7 @@ omapi_protocol_stuff_values(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *object);
void
omapi_protocol_destroy(omapi_object_t *object, const char *name);
omapi_protocol_destroy(omapi_object_t *object);
isc_result_t
omapi_protocol_send_message(omapi_object_t *protocol,
@ -243,7 +234,7 @@ omapi_protocol_listener_get_value(omapi_object_t *object, omapi_object_t *id,
omapi_value_t **value);
void
omapi_protocol_listener_destroy(omapi_object_t *object, const char *name);
omapi_protocol_listener_destroy(omapi_object_t *object);
isc_result_t
omapi_protocol_listener_signal(omapi_object_t *protocol_listener,
@ -275,49 +266,12 @@ omapi_connection_toserver(omapi_object_t *connection, const char *server,
void
omapi_connection_disconnect(omapi_object_t *connection, isc_boolean_t force);
int
omapi_connection_readfd(omapi_object_t *connection);
int
omapi_connection_writefd(omapi_object_t *connection);
void
omapi_connection_read(isc_task_t *task, isc_event_t *event);
isc_result_t
omapi_connection_reader(omapi_object_t *connection);
isc_result_t
omapi_connection_writer(omapi_object_t *connection);
isc_result_t
omapi_connection_reaper(omapi_object_t *connection);
isc_result_t
omapi_connection_setvalue(omapi_object_t *connection, omapi_object_t *id,
omapi_data_string_t *name,
omapi_typed_data_t *value);
isc_result_t
omapi_connection_getvalue(omapi_object_t *connection, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value);
void
omapi_connection_destroy(omapi_object_t *connection, const char *name);
isc_result_t
omapi_connection_signalhandler(omapi_object_t *connection, const char *name,
va_list args);
isc_result_t
omapi_connection_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *object);
isc_result_t
omapi_connection_require(omapi_object_t *connection, unsigned int bytes);
isc_result_t
omapi_connection_wait(omapi_object_t *object, omapi_object_t *connection_handle,
omapi_connection_wait(omapi_object_t *object,
omapi_object_t *connection_handle,
isc_time_t *timeout);
isc_result_t
@ -360,119 +314,22 @@ omapi_connection_puthandle(omapi_object_t *connection,
isc_result_t
omapi_listener_listen(omapi_object_t *listener, int port, int backlog);
isc_result_t
omapi_listener_setvalue(omapi_object_t *listener, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value);
isc_result_t
omapi_listener_getvalue(omapi_object_t *listener, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value);
void
omapi_listener_destroy(omapi_object_t *listener, const char *name);
isc_result_t
omapi_listener_signalhandler(omapi_object_t *listener, const char *name,
va_list args);
isc_result_t
omapi_listener_stuffvalues(omapi_object_t *listener, omapi_object_t *id,
omapi_object_t *object);
/*
* dispatch.c
*/
isc_result_t
omapi_register_io_object(omapi_object_t *object,
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 *));
isc_result_t
omapi_dispatch(struct timeval *timeout);
isc_result_t
omapi_wait_for_completion(omapi_object_t *io, struct timeval *timeout);
isc_result_t
omapi_one_dispatch(omapi_object_t *waiter, struct timeval *timeout);
isc_result_t
omapi_io_setvalue(omapi_object_t *io, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value);
isc_result_t
omapi_io_getvalue(omapi_object_t *io, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value);
void
omapi_io_destroy(omapi_object_t *io, const char *name);
isc_result_t
omapi_io_signalhandler(omapi_object_t *io, const char *name, va_list args);
isc_result_t
omapi_io_stuffvalues(omapi_object_t *io, omapi_object_t *id,
omapi_object_t *object);
isc_result_t
omapi_waiter_signal_handler(omapi_object_t *waiter, const char *name,
va_list args);
/*
* generic.c
*/
isc_result_t
omapi_generic_new(omapi_object_t **generic, const char *name);
isc_result_t
omapi_generic_set_value(omapi_object_t *generic, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value);
isc_result_t
omapi_generic_get_value(omapi_object_t *generic, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value);
void
omapi_generic_destroy(omapi_object_t *generic, const char *name);
isc_result_t
omapi_generic_signal_handler(omapi_object_t *generic, const char *name,
va_list args);
isc_result_t
omapi_generic_stuff_values(omapi_object_t *generic, omapi_object_t *id,
omapi_object_t *object);
/*
* message.c
*/
isc_result_t
omapi_message_new(omapi_object_t **message, const char *name);
omapi_message_new(omapi_object_t **message);
isc_result_t
omapi_message_setvalue(omapi_object_t *message, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value);
isc_result_t
omapi_message_getvalue(omapi_object_t *message, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value);
void
omapi_message_destroy(omapi_object_t *message, const char *name);
isc_result_t
omapi_message_signalhandler(omapi_object_t *message, const char *name,
va_list args);
isc_result_t
omapi_message_stuffvalues(omapi_object_t *message, omapi_object_t *id,
omapi_object_t *object);
isc_result_t
omapi_message_register(omapi_object_t *message);
isc_result_t
omapi_message_unregister(omapi_object_t *message);
isc_result_t
omapi_message_process(omapi_object_t *message, omapi_object_t *protocol);
@ -483,47 +340,45 @@ isc_result_t
omapi_init(isc_mem_t *mctx);
void
omapi_shutdown(void);
omapi_destroy(void);
isc_result_t
omapi_object_type_register(omapi_object_type_t **type,
const char *name,
isc_result_t ((*set_value)
omapi_object_register(omapi_object_type_t **type, const char *name,
isc_result_t ((*set_value)
(omapi_object_t *,
omapi_object_t *,
omapi_data_string_t *,
omapi_typed_data_t *)),
isc_result_t ((*get_value)
isc_result_t ((*get_value)
(omapi_object_t *,
omapi_object_t *,
omapi_data_string_t *,
omapi_value_t **)),
void ((*destroy)
(omapi_object_t *,
const char *)),
void ((*destroy)
(omapi_object_t *)),
isc_result_t ((*signal_handler)
isc_result_t ((*signal_handler)
(omapi_object_t *,
const char *,
va_list)),
isc_result_t ((*stuff_values)
isc_result_t ((*stuff_values)
(omapi_object_t *,
omapi_object_t *,
omapi_object_t *)),
isc_result_t ((*lookup)
isc_result_t ((*lookup)
(omapi_object_t **,
omapi_object_t *,
omapi_object_t *)),
isc_result_t ((*create)
isc_result_t ((*create)
(omapi_object_t **,
omapi_object_t *)),
isc_result_t ((*remove)
isc_result_t ((*remove)
(omapi_object_t *,
omapi_object_t *)));
@ -569,10 +424,6 @@ isc_result_t
omapi_stuff_values(omapi_object_t *handle, omapi_object_t *id,
omapi_object_t *object);
isc_result_t
omapi_object_create(omapi_object_t **object, omapi_object_t *id,
omapi_object_type_t *type);
isc_result_t
omapi_object_update(omapi_object_t *object, omapi_object_t *id,
omapi_object_t *source, omapi_handle_t handle);
@ -627,15 +478,14 @@ omapi_handle_td_lookup(omapi_object_t **object, omapi_typed_data_t *data);
* object.c
*/
isc_result_t
omapi_object_new(omapi_object_t **object, omapi_object_type_t *type,
omapi_object_create(omapi_object_t **object, omapi_object_type_t *type,
size_t size);
void
omapi_object_reference(omapi_object_t **reference, omapi_object_t *object,
const char *name);
omapi_object_reference(omapi_object_t **reference, omapi_object_t *object);
void
omapi_object_dereference(omapi_object_t **reference, const char *name);
omapi_object_dereference(omapi_object_t **reference);
/*
* data.c
@ -649,7 +499,7 @@ omapi_data_reference(omapi_typed_data_t **reference, omapi_typed_data_t *data,
const char *name);
void
omapi_data_dereference(omapi_typed_data_t **reference, const char *name);
omapi_data_dereference(omapi_typed_data_t **reference);
isc_result_t
omapi_data_newstring(omapi_data_string_t **string, unsigned int length,

View File

@ -70,10 +70,12 @@ typedef struct omapi_message_object {
typedef struct omapi_connection_object {
OMAPI_OBJECT_PREAMBLE;
isc_mutex_t mutex;
isc_mutex_t recv_lock;
isc_socket_t *socket; /* Connection socket. */
isc_task_t *task;
unsigned int events_pending; /* socket events */
unsigned int messages_expected;
isc_boolean_t waiting;
isc_condition_t waiter; /* omapi_connection_wait() */
omapi_connection_state_t state;
isc_sockaddr_t remote_addr;
@ -96,23 +98,14 @@ typedef struct omapi_connection_object {
*/
isc_uint32_t out_bytes;
isc_bufferlist_t output_buffers;
#if 0
/*
* Listener that accepted this connection.
* XXXDCL This appears to not be needed.
* ... well, now it is. but it could just be an isc_boolean_t
* that indicates whether this is a server side connection or client.
*/
omapi_object_t * listener;
#endif
isc_boolean_t is_client;
} omapi_connection_object_t;
typedef struct omapi_generic_object {
OMAPI_OBJECT_PREAMBLE;
omapi_value_t ** values;
unsigned int nvalues;
unsigned int va_max;
omapi_value_t ** values;
unsigned int nvalues;
unsigned int va_max;
} omapi_generic_object_t;
typedef struct omapi_waiter_object {
@ -121,6 +114,18 @@ typedef struct omapi_waiter_object {
isc_condition_t ready;
} omapi_waiter_object_t;
/*****
***** Global Variables.
*****/
extern omapi_object_type_t *omapi_type_connection;
extern omapi_object_type_t *omapi_type_listener;
extern omapi_object_type_t *omapi_type_generic;
extern omapi_object_type_t *omapi_type_protocol;
extern omapi_object_type_t *omapi_type_protocol_listener;
extern omapi_object_type_t *omapi_type_message;
extern omapi_object_type_t *omapi_object_types;
/*
* Everything needs a memory context. This will likely be made a parameter
* where needed rather than a single global context. XXXDCL
@ -132,11 +137,6 @@ extern isc_mem_t *omapi_mctx;
*/
extern isc_taskmgr_t *omapi_taskmgr;
/*
* XXXDCL comment, localize?
*/
extern isc_timermgr_t *omapi_timermgr;
/*
* XXXDCL comment, localize?
*/
@ -147,12 +147,12 @@ extern isc_boolean_t omapi_ipv6;
void
connection_send(omapi_connection_object_t *connection);
#define OBJECT_REF(objectp, object, where) \
#define OBJECT_REF(objectp, object) \
omapi_object_reference((omapi_object_t **)objectp, \
(omapi_object_t *)object, where)
(omapi_object_t *)object)
#define OBJECT_DEREF(objectp, where) \
omapi_object_dereference((omapi_object_t **)objectp, where)
#define OBJECT_DEREF(objectp) \
omapi_object_dereference((omapi_object_t **)objectp)
#define PASS_CHECK(object, function) \
(object->inner != NULL && object->inner->type->function != NULL)
@ -193,6 +193,18 @@ connection_send(omapi_connection_object_t *connection);
return (ISC_R_SUCCESS); \
} while (0)
isc_result_t
omapi_connection_init(void);
isc_result_t
omapi_listener_init(void);
isc_result_t
omapi_generic_init(void);
isc_result_t
omapi_message_init(void);
ISC_LANG_ENDDECLS
#endif /* OMAPIP_OMAPIP_P_H */

View File

@ -40,7 +40,7 @@ typedef struct omapi_listener_object {
* Reader callback for a listener object. Accept an incoming connection.
*/
static void
omapi_listener_accept(isc_task_t *task, isc_event_t *event) {
listener_accept(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
isc_buffer_t *ibuffer, *obuffer;
isc_task_t *connection_task = NULL;
@ -58,7 +58,7 @@ omapi_listener_accept(isc_task_t *task, isc_event_t *event) {
/*
* Set up another listen task for the socket.
*/
isc_socket_accept(event->sender, task, omapi_listener_accept,
isc_socket_accept(event->sender, task, listener_accept,
event->arg);
/*
@ -95,7 +95,7 @@ omapi_listener_accept(isc_task_t *task, isc_event_t *event) {
/*
* Create a new connection object.
*/
result = omapi_object_new((omapi_object_t **)&connection,
result = omapi_object_create((omapi_object_t **)&connection,
omapi_type_connection, sizeof(*connection));
if (result != ISC_R_SUCCESS)
goto free_obuffer;
@ -118,6 +118,7 @@ omapi_listener_accept(isc_task_t *task, isc_event_t *event) {
ISC_LIST_APPEND(connection->output_buffers, obuffer, link);
RUNTIME_CHECK(isc_mutex_init(&connection->mutex) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&connection->recv_lock) == ISC_R_SUCCESS);
/*
* Notify the listener object that a connection was made.
@ -131,7 +132,7 @@ omapi_listener_accept(isc_task_t *task, isc_event_t *event) {
* reaped. The omapi_protocol_listener_signal function added a
* reference when it created a protocol object as connection->inner.
*/
OBJECT_DEREF(&connection, "omapi_listener_accept");
OBJECT_DEREF(&connection);
return;
free_object:
@ -139,7 +140,7 @@ free_object:
* Destroy the connection. This will free everything created
* in this function but the event.
*/
OBJECT_DEREF(&connection, "omapi_listener_accept");
OBJECT_DEREF(&connection);
return;
/*
@ -189,8 +190,8 @@ omapi_listener_listen(omapi_object_t *caller, int port, int max) {
/*
* Tie the listener object to the calling object.
*/
OBJECT_REF(&caller->outer, listener, "omapi_protocol_listen");
OBJECT_REF(&listener->inner, caller, "omapi_protocol_listen");
OBJECT_REF(&caller->outer, listener);
OBJECT_REF(&listener->inner, caller);
/*
* Create a socket on which to listen.
@ -203,7 +204,7 @@ omapi_listener_listen(omapi_object_t *caller, int port, int max) {
* because it has two refcnts, one for existing plus one
* for the tie to h->outer. This does not seem right to me.
*/
OBJECT_DEREF(&listener, "omapi_listen");
OBJECT_DEREF(&listener);
return (result);
}
@ -219,7 +220,7 @@ omapi_listener_listen(omapi_object_t *caller, int port, int max) {
*/
result = isc_socket_bind(listener->socket, &listener->address);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&listener, "omapi_listen");
OBJECT_DEREF(&listener);
return (result);
}
@ -228,24 +229,24 @@ omapi_listener_listen(omapi_object_t *caller, int port, int max) {
*/
result = isc_socket_listen(listener->socket, max);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&listener, "omapi_listen");
OBJECT_DEREF(&listener);
return (result);
}
/*
* Queue up the first accept event. The listener object
* will be passed to omapi_listener_accept() when it is called.
* will be passed to listener_accept() when it is called.
*/
result = isc_socket_accept(listener->socket, task,
omapi_listener_accept, listener);
listener_accept, listener);
if (result != ISC_R_SUCCESS)
OBJECT_DEREF(&listener, "omapi_listen");
OBJECT_DEREF(&listener);
return (result);
}
isc_result_t
omapi_listener_setvalue(omapi_object_t *listener, omapi_object_t *id,
static isc_result_t
listener_setvalue(omapi_object_t *listener, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
{
/*
@ -257,8 +258,8 @@ omapi_listener_setvalue(omapi_object_t *listener, omapi_object_t *id,
PASS_SETVALUE(listener);
}
isc_result_t
omapi_listener_getvalue(omapi_object_t *listener, omapi_object_t *id,
static isc_result_t
listener_getvalue(omapi_object_t *listener, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
{
/*
@ -270,14 +271,12 @@ omapi_listener_getvalue(omapi_object_t *listener, omapi_object_t *id,
PASS_GETVALUE(listener);
}
void
omapi_listener_destroy(omapi_object_t *object, const char *name) {
static void
listener_destroy(omapi_object_t *object) {
omapi_listener_object_t *listener;
REQUIRE(object != NULL && object->type == omapi_type_listener);
(void)name; /* Unused. */
listener = (omapi_listener_object_t *)object;
if (listener->socket != NULL) {
@ -291,14 +290,13 @@ omapi_listener_destroy(omapi_object_t *object, const char *name) {
}
}
isc_result_t
omapi_listener_signalhandler(omapi_object_t *listener, const char *name,
va_list ap)
static isc_result_t
listener_signalhandler(omapi_object_t *listener, const char *name, va_list ap)
{
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
/*
* This function is reached when omapi_listener_accept does
* This function is reached when listener_accept does
* an omapi_signal of "connect" on the listener object. Nothing
* need be done here, but the object that originally requested
* the listen needs to signalled that a connection was made.
@ -314,12 +312,23 @@ omapi_listener_signalhandler(omapi_object_t *listener, const char *name,
* Write all the published values associated with the object through the
* specified connection.
*/
isc_result_t
omapi_listener_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *listener)
static isc_result_t
listener_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *listener)
{
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
PASS_STUFFVALUES(listener);
}
isc_result_t
omapi_listener_init(void) {
return (omapi_object_register(&omapi_type_listener,
"listener",
listener_setvalue,
listener_getvalue,
listener_destroy,
listener_signalhandler,
listener_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -28,236 +28,34 @@
omapi_message_object_t *omapi_registered_messages;
isc_result_t
omapi_message_new(omapi_object_t **o, const char *name) {
omapi_message_new(omapi_object_t **o) {
omapi_message_object_t *message = NULL;
omapi_object_t *g;
isc_result_t result;
result = omapi_object_new((omapi_object_t **)&message,
omapi_type_message, sizeof(*message));
result = omapi_object_create((omapi_object_t **)&message,
omapi_type_message, sizeof(*message));
if (result != ISC_R_SUCCESS)
return (result);
g = NULL;
result = omapi_generic_new(&g, name);
result = omapi_object_create(&g, NULL, 0);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message, "omapi_message_new");
OBJECT_DEREF(&message);
return (result);
}
OBJECT_REF(&message->inner, g, name);
OBJECT_REF(&g->outer, message, name);
OBJECT_REF(o, message, name);
OBJECT_REF(&message->inner, g);
OBJECT_REF(&g->outer, message);
OBJECT_REF(o, message);
OBJECT_DEREF(&message, name);
OBJECT_DEREF(&g, name);
OBJECT_DEREF(&message);
OBJECT_DEREF(&g);
return (result);
}
isc_result_t
omapi_message_setvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name,
omapi_typed_data_t *value)
{
omapi_message_object_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_object_t *)h;
/*
* Can't set authlen.
*/
/*
* Can set authenticator, but the value must be typed data.
*/
if (omapi_ds_strcmp(name, "authenticator") == 0) {
if (m->authenticator != NULL)
omapi_data_dereference(&m->authenticator,
"omapi_message_set_value");
omapi_data_reference(&m->authenticator, value,
"omapi_message_set_value");
return (ISC_R_SUCCESS);
} else if (omapi_ds_strcmp(name, "object") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_object);
if (m->object != NULL)
OBJECT_DEREF(&m->object, "omapi_message_set_value");
OBJECT_REF(&m->object, value->u.object,
"omapi_message_set_value");
return (ISC_R_SUCCESS);
} else if (omapi_ds_strcmp(name, "notify-object") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_object);
if (m->notify_object != NULL)
OBJECT_DEREF(&m->notify_object,
"omapi_message_set_value");
OBJECT_REF(&m->notify_object, value->u.object,
"omapi_message_set_value");
return (ISC_R_SUCCESS);
/*
* Can set authid, but it has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "authid") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->authid = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Can set op, but it has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "op") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->op = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Handle also has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "handle") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->h = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Transaction ID has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "id") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->id = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Remote transaction ID has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "rid") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->rid = value->u.integer;
return (ISC_R_SUCCESS);
}
/*
* Try to find some inner object that can take the value.
*/
PASS_SETVALUE(h);
}
isc_result_t
omapi_message_getvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name,
omapi_value_t **value)
{
omapi_message_object_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_object_t *)h;
/*
* Look for values that are in the message data structure.
*/
if (omapi_ds_strcmp(name, "authlen") == 0)
return (omapi_make_int_value(value, name, (int)m->authlen,
"omapi_message_get_value"));
else if (omapi_ds_strcmp(name, "authenticator") == 0) {
if (m->authenticator != NULL)
return (omapi_make_value(value, name, m->authenticator,
"omapi_message_get_value"));
else
return (ISC_R_NOTFOUND);
} else if (omapi_ds_strcmp(name, "authid") == 0) {
return (omapi_make_int_value(value, name, (int)m->authid,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "op") == 0) {
return (omapi_make_int_value(value, name, (int)m->op,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "handle") == 0) {
return (omapi_make_int_value(value, name, (int)m->handle,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "id") == 0) {
return (omapi_make_int_value(value, name, (int)m->id,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "rid") == 0) {
return (omapi_make_int_value(value, name, (int)m->rid,
"omapi_message_get_value"));
}
/*
* See if there's an inner object that has the value.
*/
PASS_GETVALUE(h);
}
void
omapi_message_destroy(omapi_object_t *handle, const char *name) {
omapi_message_object_t *message;
REQUIRE(handle != NULL && handle->type == omapi_type_message);
message = (omapi_message_object_t *)handle;
if (message->authenticator != NULL)
omapi_data_dereference(&message->authenticator, name);
if (message->prev == NULL && omapi_registered_messages != message)
omapi_message_unregister(handle);
if (message->prev != NULL)
OBJECT_DEREF(&message->prev, name);
if (message->next != NULL)
OBJECT_DEREF(&message->next, name);
if (message->id_object != NULL)
OBJECT_DEREF(&message->id_object, name);
if (message->object != NULL)
OBJECT_DEREF(&message->object, name);
}
isc_result_t
omapi_message_signalhandler(omapi_object_t *handle, const char *name,
va_list ap) {
omapi_message_object_t *message;
REQUIRE(handle != NULL && handle->type == omapi_type_message);
message = (omapi_message_object_t *)handle;
if (strcmp(name, "status") == 0 &&
(message->object != NULL || message->notify_object != NULL)) {
if (message->object != NULL)
return ((message->object->type->signal_handler))
(message->object, name, ap);
else
return ((message->notify_object->type->signal_handler))
(message->notify_object, name, ap);
}
PASS_SIGNAL(handle);
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
isc_result_t
omapi_message_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *message)
{
REQUIRE(message != NULL && message->type == omapi_type_message);
PASS_STUFFVALUES(message);
}
isc_result_t
omapi_message_register(omapi_object_t *h) {
omapi_message_object_t *m;
@ -272,20 +70,15 @@ omapi_message_register(omapi_object_t *h) {
omapi_registered_messages != m);
if (omapi_registered_messages != NULL) {
OBJECT_REF(&m->next, omapi_registered_messages,
"omapi_message_register");
OBJECT_REF(&omapi_registered_messages->prev, m,
"omapi_message_register");
OBJECT_DEREF(&omapi_registered_messages,
"omapi_message_register");
OBJECT_REF(&m->next, omapi_registered_messages);
OBJECT_REF(&omapi_registered_messages->prev, m);
OBJECT_DEREF(&omapi_registered_messages);
}
OBJECT_REF(&omapi_registered_messages, m,
"omapi_message_register");
return (ISC_R_SUCCESS);
OBJECT_REF(&omapi_registered_messages, m);
}
isc_result_t
static void
omapi_message_unregister(omapi_object_t *h) {
omapi_message_object_t *m;
omapi_message_object_t *n;
@ -301,35 +94,31 @@ omapi_message_unregister(omapi_object_t *h) {
n = NULL;
if (m->next != NULL) {
OBJECT_REF(&n, m->next, "omapi_message_unregister");
OBJECT_DEREF(&m->next, "omapi_message_unregister");
OBJECT_REF(&n, m->next);
OBJECT_DEREF(&m->next);
}
if (m->prev != NULL) {
omapi_message_object_t *tmp = NULL;
OBJECT_REF(&tmp, m->prev, "omapi_message_register");
OBJECT_DEREF(&m->prev, "omapi_message_unregister");
OBJECT_REF(&tmp, m->prev);
OBJECT_DEREF(&m->prev);
if (tmp->next != NULL)
OBJECT_DEREF(&tmp->next, "omapi_message_unregister");
OBJECT_DEREF(&tmp->next);
if (n != NULL)
OBJECT_REF(&tmp->next, n, "omapi_message_unregister");
OBJECT_REF(&tmp->next, n);
OBJECT_DEREF(&tmp, "omapi_message_unregister");
OBJECT_DEREF(&tmp);
} else {
OBJECT_DEREF(&omapi_registered_messages,
"omapi_message_unregister");
OBJECT_DEREF(&omapi_registered_messages);
if (n != NULL)
OBJECT_REF(&omapi_registered_messages, n,
"omapi_message_unregister");
OBJECT_REF(&omapi_registered_messages, n);
}
if (n != NULL)
OBJECT_DEREF(&n, "omapi_message_unregister");
return (ISC_R_SUCCESS);
OBJECT_DEREF(&n);
}
isc_result_t
@ -492,7 +281,7 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
* return an error.
*/
if (result == ISC_R_SUCCESS && create != 0 && exclusive != 0) {
OBJECT_DEREF(&object, "omapi_message_process");
OBJECT_DEREF(&object);
return (omapi_protocol_send_status(po, NULL,
ISC_R_EXISTS, message->id,
"specified object already exists"));
@ -502,7 +291,9 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
* If we're creating the object, do it now.
*/
if (object == NULL) {
result = omapi_object_create(&object, NULL, type);
if (type->create == NULL)
return (ISC_R_NOTIMPLEMENTED);
result = (*(type->create))(&object, NULL);
if (result != ISC_R_SUCCESS) {
return (omapi_protocol_send_status(po, NULL,
result, message->id,
@ -518,7 +309,7 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
message->object,
message->handle);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&object, "omapi_message_process");
OBJECT_DEREF(&object);
return (omapi_protocol_send_status(po, NULL,
result, message->id,
"can't update object"));
@ -541,13 +332,12 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
send:
result = omapi_protocol_send_update(po, NULL,
message->id, object);
OBJECT_DEREF(&object, "omapi_message_process");
OBJECT_DEREF(&object);
return (result);
case OMAPI_OP_UPDATE:
if (m->object != NULL) {
OBJECT_REF(&object, m->object,
"omapi_message_process");
OBJECT_REF(&object, m->object);
} else {
result = omapi_handle_lookup(&object, message->handle);
if (result != ISC_R_SUCCESS) {
@ -560,7 +350,7 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
result = omapi_object_update(object, NULL, message->object,
message->handle);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&object, "omapi_message_process");
OBJECT_DEREF(&object);
if (message->rid == 0)
return (omapi_protocol_send_status(po, NULL,
result, message->id,
@ -627,10 +417,217 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
"no remove method for object"));
result = (*(object->type->remove))(object, NULL);
OBJECT_DEREF(&object, "omapi_message_process");
OBJECT_DEREF(&object);
return (omapi_protocol_send_status(po, NULL, result,
message->id, NULL));
}
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
message_setvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value)
{
omapi_message_object_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_object_t *)h;
/*
* Can't set authlen.
*/
/*
* Can set authenticator, but the value must be typed data.
*/
if (omapi_ds_strcmp(name, "authenticator") == 0) {
if (m->authenticator != NULL)
omapi_data_dereference(&m->authenticator);
omapi_data_reference(&m->authenticator, value,
"omapi_message_set_value");
return (ISC_R_SUCCESS);
} else if (omapi_ds_strcmp(name, "object") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_object);
if (m->object != NULL)
OBJECT_DEREF(&m->object);
OBJECT_REF(&m->object, value->u.object);
return (ISC_R_SUCCESS);
} else if (omapi_ds_strcmp(name, "notify-object") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_object);
if (m->notify_object != NULL)
OBJECT_DEREF(&m->notify_object);
OBJECT_REF(&m->notify_object, value->u.object);
return (ISC_R_SUCCESS);
/*
* Can set authid, but it has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "authid") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->authid = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Can set op, but it has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "op") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->op = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Handle also has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "handle") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->h = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Transaction ID has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "id") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->id = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Remote transaction ID has to be an integer.
*/
} else if (omapi_ds_strcmp(name, "rid") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->rid = value->u.integer;
return (ISC_R_SUCCESS);
}
/*
* Try to find some inner object that can take the value.
*/
PASS_SETVALUE(h);
}
static isc_result_t
message_getvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value)
{
omapi_message_object_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_object_t *)h;
/*
* Look for values that are in the message data structure.
*/
if (omapi_ds_strcmp(name, "authlen") == 0)
return (omapi_make_int_value(value, name, (int)m->authlen,
"omapi_message_get_value"));
else if (omapi_ds_strcmp(name, "authenticator") == 0) {
if (m->authenticator != NULL)
return (omapi_make_value(value, name, m->authenticator,
"omapi_message_get_value"));
else
return (ISC_R_NOTFOUND);
} else if (omapi_ds_strcmp(name, "authid") == 0) {
return (omapi_make_int_value(value, name, (int)m->authid,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "op") == 0) {
return (omapi_make_int_value(value, name, (int)m->op,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "handle") == 0) {
return (omapi_make_int_value(value, name, (int)m->handle,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "id") == 0) {
return (omapi_make_int_value(value, name, (int)m->id,
"omapi_message_get_value"));
} else if (omapi_ds_strcmp(name, "rid") == 0) {
return (omapi_make_int_value(value, name, (int)m->rid,
"omapi_message_get_value"));
}
/*
* See if there's an inner object that has the value.
*/
PASS_GETVALUE(h);
}
static void
message_destroy(omapi_object_t *handle) {
omapi_message_object_t *message;
REQUIRE(handle != NULL && handle->type == omapi_type_message);
message = (omapi_message_object_t *)handle;
if (message->authenticator != NULL)
omapi_data_dereference(&message->authenticator);
if (message->prev == NULL && omapi_registered_messages != message)
omapi_message_unregister(handle);
if (message->prev != NULL)
OBJECT_DEREF(&message->prev);
if (message->next != NULL)
OBJECT_DEREF(&message->next);
if (message->id_object != NULL)
OBJECT_DEREF(&message->id_object);
if (message->object != NULL)
OBJECT_DEREF(&message->object);
}
static isc_result_t
message_signalhandler(omapi_object_t *handle, const char *name,
va_list ap) {
omapi_message_object_t *message;
REQUIRE(handle != NULL && handle->type == omapi_type_message);
message = (omapi_message_object_t *)handle;
if (strcmp(name, "status") == 0 &&
(message->object != NULL || message->notify_object != NULL)) {
if (message->object != NULL)
return ((message->object->type->signal_handler))
(message->object, name, ap);
else
return ((message->notify_object->type->signal_handler))
(message->notify_object, name, ap);
}
PASS_SIGNAL(handle);
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
static isc_result_t
message_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *message)
{
REQUIRE(message != NULL && message->type == omapi_type_message);
PASS_STUFFVALUES(message);
}
isc_result_t
omapi_message_init(void) {
return (omapi_object_register(&omapi_type_message,
"message",
message_setvalue,
message_getvalue,
message_destroy,
message_signalhandler,
message_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: object.c,v 1.4 2000/01/14 23:10:03 tale Exp $ */
/* $Id: object.c,v 1.5 2000/01/17 18:02:08 tale Exp $ */
/* Principal Author: Ted Lemon */
@ -30,12 +30,18 @@
#include <omapi/private.h>
isc_result_t
omapi_object_new(omapi_object_t **object, omapi_object_type_t *type,
omapi_object_create(omapi_object_t **object, omapi_object_type_t *type,
size_t size)
{
omapi_object_t *new;
REQUIRE(object != NULL && *object == NULL);
REQUIRE(size > 0 || type == NULL);
if (type == NULL) {
type = omapi_type_generic;
size = sizeof(omapi_generic_object_t);
}
new = isc_mem_get(omapi_mctx, size);
if (new == NULL)
@ -53,20 +59,16 @@ omapi_object_new(omapi_object_t **object, omapi_object_type_t *type,
}
void
omapi_object_reference(omapi_object_t **r, omapi_object_t *h,
const char *name)
{
omapi_object_reference(omapi_object_t **r, omapi_object_t *h) {
REQUIRE(r != NULL && *r == NULL);
REQUIRE(h != NULL);
(void)name; /* Unused. */
*r = h;
h->refcnt++;
}
void
omapi_object_dereference(omapi_object_t **h, const char *name) {
omapi_object_dereference(omapi_object_t **h) {
int outer_reference = 0;
int inner_reference = 0;
int handle_reference = 0;
@ -83,7 +85,7 @@ omapi_object_dereference(omapi_object_t **h, const char *name) {
*/
/*
* XXXDCL my wording
* Note whether the object being dereference has an inner object, but
* Note whether the object being dereferenced has an inner object, but
* only if the inner object's own outer pointer is not what is
* being dereferenced.
* (XXXDCL when does it happen that way ?)
@ -153,13 +155,14 @@ omapi_object_dereference(omapi_object_t **h, const char *name) {
if (extra_references == 0) {
if (inner_reference != 0)
OBJECT_DEREF(&(*h)->inner->outer, name);
OBJECT_DEREF(&(*h)->inner->outer);
if (outer_reference != 0)
OBJECT_DEREF(&(*h)->outer->inner, name);
OBJECT_DEREF(&(*h)->outer->inner);
if ((*h)->type->destroy != NULL)
(*((*h)->type->destroy))(*h, name);
(*((*h)->type->destroy))(*h, NULL);
isc_mem_put(omapi_mctx, *h, (*h)->object_size);
}
}
*h = NULL;
}

View File

@ -78,22 +78,20 @@ omapi_protocol_connect(omapi_object_t *h, const char *server_name,
isc_result_t result;
omapi_protocol_object_t *obj;
obj = isc_mem_get(omapi_mctx, sizeof(*obj));
if (obj == NULL)
return (ISC_R_NOMEMORY);
memset(obj, 0, sizeof(*obj));
obj->object_size = sizeof(*obj);
obj->refcnt = 1;
obj->type = omapi_type_protocol;
obj = NULL;
result = omapi_object_create((omapi_object_t **)&obj,
omapi_type_protocol, sizeof(*obj));
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_connection_toserver((omapi_object_t *)obj,
server_name, port);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&obj, "omapi_protocol_connect");
OBJECT_DEREF(&obj);
return (result);
}
OBJECT_REF(&h->outer, obj, "omapi_protocol_connect");
OBJECT_REF(&obj->inner, h, "omapi_protocol_connect");
OBJECT_REF(&h->outer, obj);
OBJECT_REF(&obj->inner, h);
/*
* Send the introductory message.
@ -102,13 +100,13 @@ omapi_protocol_connect(omapi_object_t *h, const char *server_name,
OMAPI_PROTOCOL_VERSION,
sizeof(omapi_protocol_header_t));
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&obj, "omapi_protocol_connect");
OBJECT_DEREF(&obj);
return (result);
}
if (authinfo)
OBJECT_REF(&obj->authinfo, authinfo, "omapi_protocol_connect");
OBJECT_DEREF(&obj, "omapi_protocol_accept");
OBJECT_REF(&obj->authinfo, authinfo);
OBJECT_DEREF(&obj);
return (ISC_R_SUCCESS);
}
@ -286,16 +284,56 @@ omapi_protocol_send_message(omapi_object_t *po, omapi_object_t *id,
/*
* When the client sends a message, it expects a reply.
* When the client sends a message, it expects a reply. Increment
* the count of messages_expected and make sure an isc_socket_recv
* gets queued.
*
* If the connection is in the disconnecting state, connection_send
* will note it, with an abort :-), in just a moment. In any event, it
* is decreed to be a fatal error for the client program to call this
* function after having asked to disconnect, so going ahead with the
* omapi_connection_require call here in the driving thread (rather
* than in the task thread, where omapi_protocol_signal_handler
* normally does things) is ok. It is also known that if this is the
* only message being sent right now, then there should be no other
* recv_done() results coming in until after the
* omapi_connection_require(), so some error is not going to be blowing
* away the connection.
*/
if (connection->is_client) {
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS);
connection->messages_expected++;
if (++connection->messages_expected == 1) {
/*
* omapi_connection_require() needs an unlocked mutex.
*/
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
result = omapi_connection_require(c, p->header_size);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
/*
* How could there possibly be that amount of bytes
* waiting if no other messages were outstanding?
* Answer: it shouldn't be possible. Make sure.
*/
ENSURE(result != ISC_R_SUCCESS);
if (result != OMAPI_R_NOTYET)
goto disconnect;
} else
/*
* If messages_expected > 1, then the code after the
* call to omapi_message_process() in the
* omapi_protocol_signal_handler function has not yet
* been done, so it will handle the call to
* omapi_connection_require while messages_expected
* remains non-zero. (This check also happens at
* the end of the block that processes the intro
* message.)
*/
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS);
}
connection_send(connection);
@ -367,6 +405,12 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
goto disconnect;
}
/*
* The next thing that shows up on incoming connections
* should be a message header.
*/
p->state = omapi_protocol_header_wait;
/*
* Signal omapi_connection_wait() to wake up.
* Only do this for the client side.
@ -383,36 +427,53 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
ISC_R_SUCCESS);
/*
* Release the lock. Contrary to what you might think
* from some documentation sources, it is necessary
* to do this for the waiting thread to unblock.
* If the driving program has already called
* omapi_protocol_send_message and the lock
* was acquired in that function, then since
* messages_expected would have been >= 2 at
* the critical test, the omapi_connection_require
* would not have been done yet, and will need
* to be. Since messages_expected was decremented,
* drop through to the connection_require only if
* messages_expected is >= 1
*/
if (c->messages_expected == 0) {
RUNTIME_CHECK(isc_mutex_unlock(&c->mutex) ==
ISC_R_SUCCESS);
break;
}
/*
* Proceed to the omapi_connection_require
* for the first "real" message's header.
*/
RUNTIME_CHECK(isc_mutex_unlock(&c->mutex) ==
ISC_R_SUCCESS);
}
to_header_wait:
/*
* The next thing we're expecting is a message header.
*/
p->state = omapi_protocol_header_wait;
/*
* Register a need for the number of bytes in a
* header, and if we already have that many, process
* them immediately.
* Register a need for the number of bytes in a header, and if
* that many are here already, process them immediately.
*
* XXXDCL there is a miniscule but non-zero chance that
* omapi_connection_require will return ISC_R_NOMEMORY
* from omapi_connection_require. If that happens,
* as things are currently written the client will likely
* just hang. no recv was queued, so no recv_done will get
* called, so this signal handler never gets called again.
*/
if ((omapi_connection_require(connection, p->header_size))
!= ISC_R_SUCCESS)
result = omapi_connection_require(connection, p->header_size);
if (result == OMAPI_R_NOTYET)
break;
/*
* If we already have the data, fall through.
*/
else if (result != ISC_R_SUCCESS)
goto disconnect;
/* FALLTHROUGH */
case omapi_protocol_header_wait:
result = omapi_message_new((omapi_object_t **)&p->message,
"omapi_protocol_signal_handler");
result = omapi_message_new((omapi_object_t **)&p->message);
if (result != ISC_R_SUCCESS)
goto disconnect;
@ -464,11 +525,13 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
/*
* Wait for a 16-bit length.
*/
if (omapi_connection_require(connection, 2) != ISC_R_SUCCESS)
result = omapi_connection_require(connection, 2);
if (result == OMAPI_R_NOTYET)
break;
/*
* If it's already here, fall through.
*/
else if (result != ISC_R_SUCCESS)
goto disconnect;
/* FALLTHROUGH */
case omapi_protocol_name_length_wait:
result = omapi_connection_getuint16(connection, &nlen);
@ -511,11 +574,14 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
* the authenticator. If we already have it,
* go read it in.
*/
if (omapi_connection_require(connection,
p->message->authlen)
== ISC_R_SUCCESS)
result = omapi_connection_require(connection,
p->message->authlen);
if (result == OMAPI_R_NOTYET)
break;
else if (result == ISC_R_SUCCESS)
goto signature_wait;
break;
else
goto disconnect;
}
/*
@ -527,14 +593,14 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
goto disconnect;
p->state = omapi_protocol_name_wait;
if (omapi_connection_require(connection, nlen) !=
ISC_R_SUCCESS)
result = omapi_connection_require(connection, nlen);
if (result == OMAPI_R_NOTYET)
break;
else if (result != ISC_R_SUCCESS)
goto disconnect;
/* FALLTHROUGH */
/*
* If it's already here, fall through.
* */
case omapi_protocol_name_wait:
result = omapi_connection_copyout(p->name->value, connection,
p->name->len);
@ -546,12 +612,12 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
*/
p->state = omapi_protocol_value_length_wait;
result = omapi_connection_require(connection, 4);
if (result != ISC_R_SUCCESS)
if (result == OMAPI_R_NOTYET)
break;
else if (result != ISC_R_SUCCESS)
goto disconnect;
/*
* If it's already here, fall through.
*/
/* FALLTHROUGH */
case omapi_protocol_value_length_wait:
omapi_connection_getuint32(connection, &vlen);
@ -571,8 +637,10 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
p->state = omapi_protocol_value_wait;
result = omapi_connection_require(connection, vlen);
if (result != ISC_R_SUCCESS)
if (result == OMAPI_R_NOTYET)
break;
else if (result != ISC_R_SUCCESS)
goto disconnect;
/*
* If it's already here, fall through.
*/
@ -595,8 +663,9 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
* We need a generic object to hang off of the
* incoming message.
*/
result = omapi_generic_new(&p->message->object,
"omapi_protocol_signal_handler");
result =
omapi_object_create(&p->message->object,
NULL, 0);
if (result != ISC_R_SUCCESS)
goto disconnect;
}
@ -611,8 +680,7 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
omapi_data_stringdereference(&p->name,
"omapi_protocol_signal_handler");
omapi_data_dereference(&p->value,
"omapi_protocol_signal_handler");
omapi_data_dereference(&p->value);
goto need_name_length;
signature_wait:
@ -639,6 +707,18 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
result = omapi_message_process((omapi_object_t *)p->message,
h);
/* XXXTL unbind the authenticator. */
/*
* Free the message object.
*/
OBJECT_DEREF(&p->message);
/*
* The next thing the protocol reads will be a new message.
*/
p->state = omapi_protocol_header_wait;
/*
* Signal omapi_connection_wait() to wake up.
* XXXDCL duplicated from above.
@ -653,23 +733,32 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
RUNTIME_CHECK(isc_condition_signal(&c->waiter) ==
ISC_R_SUCCESS);
/*
* If there are no more messages expected, exit
* the signal handler.
*/
if (c->messages_expected == 0) {
RUNTIME_CHECK(isc_mutex_unlock(&c->mutex) ==
ISC_R_SUCCESS);
break;
}
RUNTIME_CHECK(isc_mutex_unlock(&c->mutex) ==
ISC_R_SUCCESS);
}
/* XXXTL unbind the authenticator. */
/*
* Free the message object.
* Proceed to the omapi_connection_require for the next
* message's header.
*/
OBJECT_DEREF(&p->message, "omapi_protocol_signal_handler");
/*
* XXXDCL these gotos could be cleared up with one
* more variable to control a loop around the switch.
*/
fprintf(stderr, "going to header_wait, events_pending = %d\n",
c->events_pending);
fprintf(stderr, "going to header_wait, events_pending = %d"
" messages_expected = %d\n", c->events_pending,
c->messages_expected);
goto to_header_wait;
default:
@ -712,7 +801,7 @@ omapi_protocol_get_value(omapi_object_t *h, omapi_object_t *id,
}
void
omapi_protocol_destroy(omapi_object_t *h, const char *name) {
omapi_protocol_destroy(omapi_object_t *h) {
omapi_protocol_object_t *p;
REQUIRE(h != NULL && h->type == omapi_type_protocol);
@ -720,10 +809,10 @@ omapi_protocol_destroy(omapi_object_t *h, const char *name) {
p = (omapi_protocol_object_t *)h;
if (p->message != NULL)
OBJECT_DEREF(&p->message, name);
OBJECT_DEREF(&p->message);
if (p->authinfo != NULL)
OBJECT_DEREF(&p->authinfo, name);
OBJECT_DEREF(&p->authinfo);
}
/*
@ -758,12 +847,12 @@ omapi_protocol_listen(omapi_object_t *h, int port, int max) {
obj->refcnt = 1;
obj->type = omapi_type_protocol_listener;
OBJECT_REF(&h->outer, obj, "omapi_protocol_listen");
OBJECT_REF(&obj->inner, h, "omapi_protocol_listen");
OBJECT_REF(&h->outer, obj);
OBJECT_REF(&obj->inner, h);
result = omapi_listener_listen((omapi_object_t *)obj, port, max);
OBJECT_DEREF(&obj, "omapi_protocol_listen");
OBJECT_DEREF(&obj);
return (result);
}
@ -800,8 +889,8 @@ omapi_protocol_listener_signal(omapi_object_t *h, const char *name, va_list ap)
* connection.
*/
obj = NULL;
result = omapi_object_new((omapi_object_t **)&obj, omapi_type_protocol,
sizeof(*obj));
result = omapi_object_create((omapi_object_t **)&obj,
omapi_type_protocol, sizeof(*obj));
if (result != ISC_R_SUCCESS)
/*
* When the unsuccessful return value is percolated back to
@ -814,8 +903,8 @@ omapi_protocol_listener_signal(omapi_object_t *h, const char *name, va_list ap)
* Tie the protocol object bidirectionally to the connection
* object, with the connection as the outer object.
*/
OBJECT_REF(&obj->outer, c, "omapi_protocol_accept");
OBJECT_REF(&c->inner, obj, "omapi_protocol_accept");
OBJECT_REF(&obj->outer, c);
OBJECT_REF(&c->inner, obj);
/*
* Send the introductory message.
@ -833,7 +922,7 @@ omapi_protocol_listener_signal(omapi_object_t *h, const char *name, va_list ap)
* XXXDCL aigh, this is so confusing. I don't think the
* right thing is being done.
*/
OBJECT_DEREF(&c->inner, "omapi_protocol_accept");
OBJECT_DEREF(&c->inner);
/*
* Remove one of the references to the object, so it will be
@ -841,7 +930,7 @@ omapi_protocol_listener_signal(omapi_object_t *h, const char *name, va_list ap)
* XXXDCL this is what ted did, but i'm not sure my explanation
* is correct.
*/
OBJECT_DEREF(&obj, "omapi_protocol_accept");
OBJECT_DEREF(&obj);
return (result);
}
@ -867,10 +956,10 @@ omapi_protocol_listener_get_value(omapi_object_t *h, omapi_object_t *id,
}
void
omapi_protocol_listener_destroy(omapi_object_t *h, const char *name) {
omapi_protocol_listener_destroy(omapi_object_t *h) {
REQUIRE(h != NULL && h->type == omapi_type_protocol_listener);
(void)name; /* Unused. */
/* XXXDCL currently NOTHING */
}
/*
@ -898,7 +987,7 @@ omapi_protocol_send_status(omapi_object_t *po, omapi_object_t *id,
REQUIRE(po != NULL && po->type == omapi_type_protocol);
result = omapi_message_new(&message, "omapi_protocol_send_status");
result = omapi_message_new(&message);
if (result != ISC_R_SUCCESS)
return (result);
@ -918,7 +1007,7 @@ omapi_protocol_send_status(omapi_object_t *po, omapi_object_t *id,
result = omapi_set_string_value(message, NULL, "message", msg);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message, "omapi_protocol_send_status");
OBJECT_DEREF(&message);
return (result);
}
@ -934,7 +1023,7 @@ omapi_protocol_send_update(omapi_object_t *po, omapi_object_t *id,
REQUIRE(po != NULL && po->type == omapi_type_protocol);
result = omapi_message_new(&message, "omapi_protocol_send_update");
result = omapi_message_new(&message);
if (result != ISC_R_SUCCESS)
return (result);
@ -958,7 +1047,7 @@ omapi_protocol_send_update(omapi_object_t *po, omapi_object_t *id,
"object", object);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message, "dhcpctl_open_object");
OBJECT_DEREF(&message);
return (result);
}

View File

@ -27,13 +27,9 @@
omapi_object_type_t *omapi_type_connection;
omapi_object_type_t *omapi_type_listener;
omapi_object_type_t *omapi_type_io_object;
omapi_object_type_t *omapi_type_datagram;
omapi_object_type_t *omapi_type_generic;
omapi_object_type_t *omapi_type_protocol;
omapi_object_type_t *omapi_type_protocol_listener;
omapi_object_type_t *omapi_type_waiter;
omapi_object_type_t *omapi_type_remote;
omapi_object_type_t *omapi_type_message;
omapi_object_type_t *omapi_object_types;
@ -41,7 +37,6 @@ int omapi_object_type_count;
isc_mem_t *omapi_mctx;
isc_taskmgr_t *omapi_taskmgr;
isc_timermgr_t *omapi_timermgr;
isc_socketmgr_t *omapi_socketmgr;
isc_boolean_t omapi_ipv6 = ISC_FALSE;
@ -74,64 +69,27 @@ omapi_init(isc_mem_t *mctx) {
if (result != ISC_R_SUCCESS)
return (result);
omapi_timermgr = NULL;
result = isc_timermgr_create(omapi_mctx, &omapi_timermgr);
if (result != ISC_R_SUCCESS)
return (result);
if (isc_net_probeipv6() == ISC_R_SUCCESS)
omapi_ipv6 = ISC_TRUE;
else
omapi_ipv6 = ISC_FALSE;
/*
* Register all the standard object types.
* Initialize all the standard object types.
*/
result = omapi_object_type_register(&omapi_type_connection,
"connection",
omapi_connection_setvalue,
omapi_connection_getvalue,
omapi_connection_destroy,
omapi_connection_signalhandler,
omapi_connection_stuffvalues,
0, 0, 0);
result = omapi_generic_init();
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_listener,
"listener",
omapi_listener_setvalue,
omapi_listener_getvalue,
omapi_listener_destroy,
omapi_listener_signalhandler,
omapi_listener_stuffvalues,
0, 0, 0);
result = omapi_listener_init();
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_io_object,
"io",
omapi_io_setvalue,
omapi_io_getvalue,
omapi_io_destroy,
omapi_io_signalhandler,
omapi_io_stuffvalues,
0, 0, 0);
result = omapi_connection_init();
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_generic,
"generic",
omapi_generic_set_value,
omapi_generic_get_value,
omapi_generic_destroy,
omapi_generic_signal_handler,
omapi_generic_stuff_values,
0, 0, 0);
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_protocol,
result = omapi_object_register(&omapi_type_protocol,
"protocol",
omapi_protocol_set_value,
omapi_protocol_get_value,
@ -142,7 +100,7 @@ omapi_init(isc_mem_t *mctx) {
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_protocol_listener,
result = omapi_object_register(&omapi_type_protocol_listener,
"protocol-listener",
omapi_protocol_listener_set_value,
omapi_protocol_listener_get_value,
@ -153,45 +111,32 @@ omapi_init(isc_mem_t *mctx) {
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_message,
"message",
omapi_message_setvalue,
omapi_message_getvalue,
omapi_message_destroy,
omapi_message_signalhandler,
omapi_message_stuffvalues,
0, 0, 0);
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_type_register(&omapi_type_waiter,
"waiter",
0,
0,
0,
omapi_waiter_signal_handler, 0,
0, 0, 0);
result = omapi_message_init();
return (result);
}
/*
* This does not free connections and other in-use objects, only the
* things created by omapi_init(). It is the callers responsibility to
* free the other things (as via omapi_connection_disconnect or
* omapi_object_dereference).
*/
void
omapi_shutdown() {
omapi_destroy() {
omapi_object_type_t *type, *next_type;
isc_socketmgr_destroy(&omapi_socketmgr);
isc_taskmgr_destroy(&omapi_taskmgr);
isc_timermgr_destroy(&omapi_timermgr);
for (type = omapi_object_types; type != NULL; type = next_type) {
next_type = type->next;
isc_mem_put(omapi_mctx, type, sizeof(*type));
}
}
isc_result_t
omapi_object_type_register(omapi_object_type_t **type, const char *name,
omapi_object_register(omapi_object_type_t **type, const char *name,
isc_result_t (*set_value)
(omapi_object_t *,
omapi_object_t *,
@ -205,8 +150,7 @@ omapi_object_type_register(omapi_object_type_t **type, const char *name,
omapi_value_t **),
void (*destroy)
(omapi_object_t *,
const char *),
(omapi_object_t *),
isc_result_t (*signal_handler)
(omapi_object_t *,
@ -341,7 +285,7 @@ omapi_set_boolean_value(omapi_object_t *h, omapi_object_t *id,
result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_boolean_value");
omapi_data_dereference(&tv, "omapi_set_boolean_value");
omapi_data_dereference(&tv);
return (result);
}
@ -367,7 +311,7 @@ omapi_set_int_value(omapi_object_t *h, omapi_object_t *id,
result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_int_value");
omapi_data_dereference(&tv, "omapi_set_int_value");
omapi_data_dereference(&tv);
return (result);
}
@ -393,7 +337,7 @@ omapi_set_object_value(omapi_object_t *h, omapi_object_t *id,
result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_object_value");
omapi_data_dereference(&tv, "omapi_set_object_value");
omapi_data_dereference(&tv);
return (result);
}
@ -419,7 +363,7 @@ omapi_set_string_value(omapi_object_t *h, omapi_object_t *id,
result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_string_value");
omapi_data_dereference(&tv, "omapi_set_string_value");
omapi_data_dereference(&tv);
return (result);
}
@ -469,18 +413,6 @@ omapi_stuff_values(omapi_object_t *c, omapi_object_t *id, omapi_object_t *o) {
return (ISC_R_NOTFOUND);
}
isc_result_t
omapi_object_create(omapi_object_t **obj, omapi_object_t *id,
omapi_object_type_t *type)
{
REQUIRE(type != NULL);
if (type->create == NULL)
return (ISC_R_NOTIMPLEMENTED);
return ((*(type->create))(obj, id));
}
isc_result_t
omapi_object_update(omapi_object_t *obj, omapi_object_t *id,
omapi_object_t *src, omapi_handle_t handle)