2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-01 06:55:30 +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. * 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 */ /* 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); 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) { while ((buffer = ISC_LIST_HEAD(connection->input_buffers)) != NULL) {
ISC_LIST_UNLINK(connection->input_buffers, buffer, link); ISC_LIST_UNLINK(connection->input_buffers, buffer, link);
isc_buffer_free(&buffer); isc_buffer_free(&buffer);
@@ -104,37 +110,11 @@ free_connection(omapi_connection_object_t *connection) {
if (connection->socket != NULL) if (connection->socket != NULL)
isc_socket_detach(&connection->socket); isc_socket_detach(&connection->socket);
/* RUNTIME_CHECK(isc_mutex_destroy(&connection->mutex) == ISC_R_SUCCESS);
* It is possible the connection was abandoned while a message RUNTIME_CHECK(isc_mutex_destroy(&connection->recv_lock) ==
* 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); ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_destroy(&connection->waiter) == RUNTIME_CHECK(isc_condition_destroy(&connection->waiter) ==
ISC_R_SUCCESS); 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");
/* /*
* If whatever created us registered a signal handler, send it * 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); 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. * Finally, free the object itself.
*/ */
OBJECT_DEREF(&connection, "free_connection"); OBJECT_DEREF(&connection);
} }
static void 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. * 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. * 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); connection->events_pending);
if (connection->events_pending == 0) { if (connection->events_pending == 0) {
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); free_connection(connection);
return; 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); ISC_R_SUCCESS);
/* /*
@@ -208,7 +230,7 @@ connect_done(isc_task_t *task, isc_event_t *event) {
fprintf(stderr, "CONNECT_DONE\n"); 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); 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 * only in recv_done. I'm concerned that there might be some
* sort of logic window, however small, where that isn't true. * 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 && if (--connection->events_pending == 0 && connection->is_client &&
connection->state == omapi_connection_disconnecting) connection->state == omapi_connection_disconnecting)
FATAL_ERROR(__FILE__, __LINE__, 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); 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); RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
ENSURE(connection->events_pending > 0); INSIST(connection->events_pending > 0);
connection->events_pending--; connection->events_pending--;
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == ISC_R_SUCCESS); 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; 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 && while (connection->bytes_needed <= connection->in_bytes &&
connection->bytes_needed > 0) connection->bytes_needed > 0)
if (omapi_signal((omapi_object_t *)connection, "ready", if (omapi_signal((omapi_object_t *)connection, "ready",
connection) != connection) != ISC_R_SUCCESS)
ISC_R_SUCCESS)
goto abandon; goto abandon;
/* /*
* Queue up another recv request. If the bufferlist is empty, * Queue up another recv request. If the bufferlist is empty,
* then, something under omapi_signal already called * 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 * See if that was the last event the client was expecting, so
* that the connection can be freed. * that the connection can be freed. This test needs to be
* XXXDCL I don't *think* this has to be done in the * done, because it is possible omapi_connection_disconnect has
* send_done or connect_done handlers, because a normal * already been called, before the signal handler managed to
* termination will only happen * 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) { if (connection->is_client) {
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
if (connection->events_pending == 0 && if (connection->events_pending == 0 &&
connection->state == omapi_connection_disconnecting) { 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); end_connection(connection, event, ISC_R_SUCCESS);
return; return;
@@ -334,11 +415,15 @@ recv_done(isc_task_t *task, isc_event_t *event) {
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
} }
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock) ==
ISC_R_SUCCESS);
isc_event_free(&event); isc_event_free(&event);
return; return;
abandon: abandon:
RUNTIME_CHECK(isc_mutex_unlock(&connection->recv_lock) ==
ISC_R_SUCCESS);
end_connection(connection, event, socketevent->result); end_connection(connection, event, socketevent->result);
return; return;
} }
@@ -360,13 +445,13 @@ send_done(isc_task_t *task, isc_event_t *event) {
fprintf(stderr, "SEND_DONE, %d bytes\n", socketevent->n); 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 * 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 ... * 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 == socketevent->n ==
isc_bufferlist_usedcount(&socketevent->bufferlist)); 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 * only in recv_done. I'm concerned that there might be some
* sort of logic window, however small, where that isn't true. * 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 && if (--connection->events_pending == 0 && connection->is_client &&
connection->state == omapi_connection_disconnecting) connection->state == omapi_connection_disconnecting)
FATAL_ERROR(__FILE__, __LINE__, FATAL_ERROR(__FILE__, __LINE__,
@@ -421,7 +506,7 @@ connection_send(omapi_connection_object_t *connection) {
REQUIRE(connection->state == omapi_connection_connected); REQUIRE(connection->state == omapi_connection_connected);
if (connection->out_bytes > 0) { 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) == RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
@@ -473,12 +558,13 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
/* /*
* Create a new connection object. * 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)); omapi_type_connection, sizeof(*connection));
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto free_obuffer; goto free_obuffer;
connection->is_client = ISC_TRUE; connection->is_client = ISC_TRUE;
connection->waiting = ISC_FALSE;
connection->task = task; 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); ISC_LIST_APPEND(connection->output_buffers, obuffer, link);
RUNTIME_CHECK(isc_mutex_init(&connection->mutex) == ISC_R_SUCCESS); 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) == RUNTIME_CHECK(isc_condition_init(&connection->waiter) ==
ISC_R_SUCCESS); 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. * Tie the new connection object to the protocol object.
*/ */
OBJECT_REF(&protocol->outer, connection, "omapi_connection_toserver"); OBJECT_REF(&protocol->outer, connection);
OBJECT_REF(&connection->inner, protocol, "omapi_connection_toserver"); OBJECT_REF(&connection->inner, protocol);
/* /*
* Create a socket on which to communicate. * Create a socket on which to communicate.
@@ -522,7 +609,7 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
flag = 1; flag = 1;
if (setsockopt(connection->socket, SOL_SOCKET, SO_REUSEADDR, if (setsockopt(connection->socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof(flag)) < 0) { (char *)&flag, sizeof(flag)) < 0) {
OBJECT_DEREF(&connection, "omapi_connect"); OBJECT_DEREF(&connection);
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
} }
#endif #endif
@@ -541,8 +628,8 @@ omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
free_object: free_object:
OBJECT_DEREF(&connection, "omapi_connection_toserver"); OBJECT_DEREF(&connection);
OBJECT_DEREF(&protocol->outer, "omapi_connection_toserver"); OBJECT_DEREF(&protocol->outer);
return (result); return (result);
free_obuffer: free_obuffer:
@@ -694,6 +781,12 @@ omapi_connection_copyout(unsigned char *dst, omapi_object_t *generic,
* the protocol.) * the protocol.)
* *
* The client might or might not want to block on the disconnection. * 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 * Also, if the error is being thrown from the library, the client
* might *already* be waiting on (or intending to wait on) whatever messages * 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 * 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) == RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
INSIST(connection->state == omapi_connection_connected);
connection->state = omapi_connection_disconnecting;
connection->messages_expected++; connection->messages_expected++;
/* /*
* If there are no other messages expected for the socket, * If there are other messages expected for the socket,
* the end_connection can be done right now. Otherwise, * then set the state to disconnecting. Based on that
* when recv_done gets the last output from the server, * flag, when recv_done gets the last output from the server,
* then it will then end the connection. * 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) { if (connection->messages_expected > 1) {
connection->state = omapi_connection_disconnecting;
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
return; return;
} }
/* /*
* ... else fall through. * ... else fall through.
*/ */
INSIST(connection->events_pending == 0);
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
} }
@@ -777,23 +877,7 @@ omapi_connection_require(omapi_object_t *generic, unsigned int bytes) {
connection = (omapi_connection_object_t *)generic; connection = (omapi_connection_object_t *)generic;
/* INSIST(connection->state == omapi_connection_connected ||
* 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 ||
connection->state == omapi_connection_disconnecting); connection->state == omapi_connection_disconnecting);
connection->bytes_needed += bytes; 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); 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.
*/
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. * Queue the receive task.
* XXXDCL The "minimum" arg has not been fully thought out. * XXXDCL The "minimum" arg has not been fully thought out.
*/ */
connection->events_pending++; connection->events_pending++;
isc_socket_recvv(connection->socket, isc_socket_recvv(connection->socket, &connection->input_buffers,
&connection->input_buffers, connection->bytes_needed - connection->in_bytes,
(connection->bytes_needed -
connection->in_bytes),
connection->task, recv_done, connection); connection->task, recv_done, connection);
}
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) == RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS); 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. * those events can happen before omapi_connection_wait is ever called.
* So a counter needs to be set for every expected message, and this * So a counter needs to be set for every expected message, and this
* function can only return when that counter is 0. * 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 isc_result_t
omapi_connection_wait(omapi_object_t *object, omapi_connection_wait(omapi_object_t *object,
@@ -913,7 +982,7 @@ omapi_connection_wait(omapi_object_t *object,
* XXXDCL 'object' is not really used. * XXXDCL 'object' is not really used.
*/ */
omapi_connection_object_t *connection; 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(object != NULL && connection_handle != NULL);
REQUIRE(connection_handle->type == omapi_type_connection); 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. * This routine is not valid for server connections.
*/ */
REQUIRE(connection->is_client); INSIST(connection->is_client);
result = isc_mutex_lock(&connection->mutex); RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == ISC_R_SUCCESS);
if (result != ISC_R_SUCCESS) INSIST(connection->state == omapi_connection_connected);
return (result);
wait_result = ISC_R_SUCCESS; connection->waiting = ISC_TRUE;
while (connection->messages_expected > 0 && while (connection->messages_expected > 0 && result == ISC_R_SUCCESS)
wait_result == ISC_R_SUCCESS)
if (timeout == NULL) if (timeout == NULL)
wait_result = isc_condition_wait(&connection->waiter, result = isc_condition_wait(&connection->waiter,
&connection->mutex); &connection->mutex);
else else
wait_result = result = isc_condition_waituntil(&connection->waiter,
isc_condition_waituntil(&connection->waiter,
&connection->mutex, &connection->mutex,
timeout); timeout);
RUNTIME_CHECK(wait_result == ISC_R_SUCCESS || RUNTIME_CHECK(result == ISC_R_SUCCESS || result == ISC_R_TIMEDOUT);
wait_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
isc_result_t * free_connection called now that we're done looking
omapi_connection_setvalue(omapi_object_t *connection, omapi_object_t *id, * at connection->messages_expected.
omapi_data_string_t *name, omapi_typed_data_t *value) *
{ * XXXDCL something better to do with the result 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 free_connection(connection);
omapi_connection_stuffvalues(omapi_object_t *connection, omapi_object_t *id, else
omapi_object_t *handle) RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
{ ISC_R_SUCCESS);
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); 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. * 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 */ /* 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; new->u.buffer.len = val;
break; break;
case omapi_datatype_object: case omapi_datatype_object:
OBJECT_REF(&new->u.object, va_arg(l, omapi_object_t *), OBJECT_REF(&new->u.object, va_arg(l, omapi_object_t *));
"omapi_datatype_new");
break; break;
} }
new->type = type; new->type = type;
@@ -117,7 +116,7 @@ omapi_data_reference(omapi_typed_data_t **r, omapi_typed_data_t *h,
} }
void void
omapi_data_dereference(omapi_typed_data_t **h, const char *name) { omapi_data_dereference(omapi_typed_data_t **h) {
int length = 0; int length = 0;
@@ -138,7 +137,7 @@ omapi_data_dereference(omapi_typed_data_t **h, const char *name) {
(*h)->u.buffer.len; (*h)->u.buffer.len;
break; break;
case omapi_datatype_object: case omapi_datatype_object:
OBJECT_DEREF(&(*h)->u.object, name); OBJECT_DEREF(&(*h)->u.object);
length = OMAPI_TYPED_DATA_OBJECT_LEN; length = OMAPI_TYPED_DATA_OBJECT_LEN;
break; break;
default: default:
@@ -237,7 +236,7 @@ omapi_data_valuedereference(omapi_value_t **h, const char *name) {
if ((*h)->name != NULL) if ((*h)->name != NULL)
omapi_data_stringdereference(&(*h)->name, name); omapi_data_stringdereference(&(*h)->name, name);
if ((*h)->value != NULL) if ((*h)->value != NULL)
omapi_data_dereference(&(*h)->value, name); omapi_data_dereference(&(*h)->value);
isc_mem_put(omapi_mctx, *h, sizeof(*h)); isc_mem_put(omapi_mctx, *h, sizeof(*h));
} }
*h = NULL; *h = NULL;

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * 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 */ /* Principal Author: Ted Lemon */
@@ -39,64 +39,3 @@ omapi_dispatch(struct timeval *t) {
select(0, NULL, NULL, NULL, t ? t : NULL); select(0, NULL, NULL, NULL, t ? t : NULL);
return (ISC_R_SUCCESS); 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. * 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 */ /* Principal Author: Ted Lemon */
@@ -29,9 +29,10 @@
#include <omapi/private.h> #include <omapi/private.h>
#if 0
isc_result_t isc_result_t
omapi_generic_new(omapi_object_t **gen, const char *name) { omapi_generic_new(omapi_object_t **generic_handle, const char *name) {
omapi_generic_object_t *obj; omapi_generic_object_t *generic;
obj = isc_mem_get(omapi_mctx, sizeof(*obj)); obj = isc_mem_get(omapi_mctx, sizeof(*obj));
if (obj == NULL) if (obj == NULL)
@@ -40,13 +41,14 @@ omapi_generic_new(omapi_object_t **gen, const char *name) {
obj->refcnt = 0; obj->refcnt = 0;
obj->type = omapi_type_generic; obj->type = omapi_type_generic;
OBJECT_REF(gen, obj, name); OBJECT_REF(gen, obj);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
#endif
isc_result_t static isc_result_t
omapi_generic_set_value(omapi_object_t *h, omapi_object_t *id, generic_setvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value) omapi_data_string_t *name, omapi_typed_data_t *value)
{ {
omapi_generic_object_t *g; omapi_generic_object_t *g;
@@ -161,8 +163,8 @@ omapi_generic_set_value(omapi_object_t *h, omapi_object_t *id,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
isc_result_t static isc_result_t
omapi_generic_get_value(omapi_object_t *h, omapi_object_t *id, generic_getvalue(omapi_object_t *h, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value) omapi_data_string_t *name, omapi_value_t **value)
{ {
unsigned int i; unsigned int i;
@@ -196,8 +198,8 @@ omapi_generic_get_value(omapi_object_t *h, omapi_object_t *id,
PASS_GETVALUE(h); PASS_GETVALUE(h);
} }
void static void
omapi_generic_destroy(omapi_object_t *h, const char *name) { generic_destroy(omapi_object_t *h) {
omapi_generic_object_t *g; omapi_generic_object_t *g;
unsigned int i; unsigned int i;
@@ -209,7 +211,7 @@ omapi_generic_destroy(omapi_object_t *h, const char *name) {
for (i = 0; i < g->nvalues; i++) for (i = 0; i < g->nvalues; i++)
if (g->values[i] != NULL) if (g->values[i] != NULL)
omapi_data_valuedereference(&g->values[i], omapi_data_valuedereference(&g->values[i],
name); NULL);
isc_mem_put(omapi_mctx, g->values, isc_mem_put(omapi_mctx, g->values,
g->va_max * sizeof(*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 static isc_result_t
omapi_generic_signal_handler(omapi_object_t *h, const char *name, va_list ap) { generic_signalhandler(omapi_object_t *h, const char *name, va_list ap) {
REQUIRE(h != NULL && h->type == omapi_type_generic); REQUIRE(h != NULL && h->type == omapi_type_generic);
@@ -230,9 +232,8 @@ 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 * Write all the published values associated with the object through the
* specified connection. * specified connection.
*/ */
static isc_result_t
isc_result_t generic_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_generic_stuff_values(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *h) omapi_object_t *h)
{ {
omapi_generic_object_t *src; omapi_generic_object_t *src;
@@ -265,3 +266,15 @@ omapi_generic_stuff_values(omapi_object_t *connection, omapi_object_t *id,
PASS_STUFFVALUES(h); 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. * 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 */ /* Principal Author: Ted Lemon */
@@ -176,8 +176,7 @@ omapi_object_handle_in_table(omapi_handle_t h, omapi_handle_table_t *table,
* appropriate place. * appropriate place.
*/ */
if (table->leaf) { if (table->leaf) {
OBJECT_REF(&table->children[h - table->first].object, o, OBJECT_REF(&table->children[h - table->first].object, o);
"omapi_object_handle_in_table");
o->handle = h; o->handle = h;
return (ISC_R_SUCCESS); 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) if (table->children[h - table->first].object == NULL)
return (ISC_R_NOTFOUND); return (ISC_R_NOTFOUND);
OBJECT_REF(o, table->children[h - table->first].object, OBJECT_REF(o, table->children[h - table->first].object);
"omapi_handle_lookup_in");
return (ISC_R_SUCCESS); 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_data_string omapi_data_string_t;
typedef struct omapi_value omapi_value_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 \ #define OMAPI_OBJECT_PREAMBLE \
omapi_object_type_t * type; \ omapi_object_type_t * type; \
size_t object_size; \ size_t object_size; \
@@ -168,25 +173,11 @@ struct omapi_object_type {
/* /*
* For use with omapi_connection_disconnect(). * For use with omapi_connection_disconnect().
* XXXDCL rename
*/ */
#define OMAPI_FORCE_DISCONNECT ISC_TRUE #define OMAPI_FORCE_DISCONNECT ISC_TRUE
#define OMAPI_CLEAN_DISCONNECT ISC_FALSE #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. ***** Function Prototypes.
*****/ *****/
@@ -221,7 +212,7 @@ omapi_protocol_stuff_values(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *object); omapi_object_t *object);
void void
omapi_protocol_destroy(omapi_object_t *object, const char *name); omapi_protocol_destroy(omapi_object_t *object);
isc_result_t isc_result_t
omapi_protocol_send_message(omapi_object_t *protocol, 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); omapi_value_t **value);
void void
omapi_protocol_listener_destroy(omapi_object_t *object, const char *name); omapi_protocol_listener_destroy(omapi_object_t *object);
isc_result_t isc_result_t
omapi_protocol_listener_signal(omapi_object_t *protocol_listener, omapi_protocol_listener_signal(omapi_object_t *protocol_listener,
@@ -275,49 +266,12 @@ omapi_connection_toserver(omapi_object_t *connection, const char *server,
void void
omapi_connection_disconnect(omapi_object_t *connection, isc_boolean_t force); 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 isc_result_t
omapi_connection_require(omapi_object_t *connection, unsigned int bytes); omapi_connection_require(omapi_object_t *connection, unsigned int bytes);
isc_result_t 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_time_t *timeout);
isc_result_t isc_result_t
@@ -360,119 +314,22 @@ omapi_connection_puthandle(omapi_object_t *connection,
isc_result_t isc_result_t
omapi_listener_listen(omapi_object_t *listener, int port, int backlog); 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 * 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 isc_result_t
omapi_dispatch(struct timeval *timeout); 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 * message.c
*/ */
isc_result_t 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 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); omapi_message_register(omapi_object_t *message);
isc_result_t
omapi_message_unregister(omapi_object_t *message);
isc_result_t isc_result_t
omapi_message_process(omapi_object_t *message, omapi_object_t *protocol); omapi_message_process(omapi_object_t *message, omapi_object_t *protocol);
@@ -483,11 +340,10 @@ isc_result_t
omapi_init(isc_mem_t *mctx); omapi_init(isc_mem_t *mctx);
void void
omapi_shutdown(void); omapi_destroy(void);
isc_result_t isc_result_t
omapi_object_type_register(omapi_object_type_t **type, omapi_object_register(omapi_object_type_t **type, const char *name,
const char *name,
isc_result_t ((*set_value) isc_result_t ((*set_value)
(omapi_object_t *, (omapi_object_t *,
omapi_object_t *, omapi_object_t *,
@@ -501,8 +357,7 @@ omapi_object_type_register(omapi_object_type_t **type,
omapi_value_t **)), omapi_value_t **)),
void ((*destroy) void ((*destroy)
(omapi_object_t *, (omapi_object_t *)),
const char *)),
isc_result_t ((*signal_handler) isc_result_t ((*signal_handler)
(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_stuff_values(omapi_object_t *handle, omapi_object_t *id,
omapi_object_t *object); 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 isc_result_t
omapi_object_update(omapi_object_t *object, omapi_object_t *id, omapi_object_update(omapi_object_t *object, omapi_object_t *id,
omapi_object_t *source, omapi_handle_t handle); 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 * object.c
*/ */
isc_result_t 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); size_t size);
void void
omapi_object_reference(omapi_object_t **reference, omapi_object_t *object, omapi_object_reference(omapi_object_t **reference, omapi_object_t *object);
const char *name);
void void
omapi_object_dereference(omapi_object_t **reference, const char *name); omapi_object_dereference(omapi_object_t **reference);
/* /*
* data.c * data.c
@@ -649,7 +499,7 @@ omapi_data_reference(omapi_typed_data_t **reference, omapi_typed_data_t *data,
const char *name); const char *name);
void void
omapi_data_dereference(omapi_typed_data_t **reference, const char *name); omapi_data_dereference(omapi_typed_data_t **reference);
isc_result_t isc_result_t
omapi_data_newstring(omapi_data_string_t **string, unsigned int length, 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 { typedef struct omapi_connection_object {
OMAPI_OBJECT_PREAMBLE; OMAPI_OBJECT_PREAMBLE;
isc_mutex_t mutex; isc_mutex_t mutex;
isc_mutex_t recv_lock;
isc_socket_t *socket; /* Connection socket. */ isc_socket_t *socket; /* Connection socket. */
isc_task_t *task; isc_task_t *task;
unsigned int events_pending; /* socket events */ unsigned int events_pending; /* socket events */
unsigned int messages_expected; unsigned int messages_expected;
isc_boolean_t waiting;
isc_condition_t waiter; /* omapi_connection_wait() */ isc_condition_t waiter; /* omapi_connection_wait() */
omapi_connection_state_t state; omapi_connection_state_t state;
isc_sockaddr_t remote_addr; isc_sockaddr_t remote_addr;
@@ -96,15 +98,6 @@ typedef struct omapi_connection_object {
*/ */
isc_uint32_t out_bytes; isc_uint32_t out_bytes;
isc_bufferlist_t output_buffers; 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; isc_boolean_t is_client;
} omapi_connection_object_t; } omapi_connection_object_t;
@@ -121,6 +114,18 @@ typedef struct omapi_waiter_object {
isc_condition_t ready; isc_condition_t ready;
} omapi_waiter_object_t; } 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 * Everything needs a memory context. This will likely be made a parameter
* where needed rather than a single global context. XXXDCL * 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; extern isc_taskmgr_t *omapi_taskmgr;
/*
* XXXDCL comment, localize?
*/
extern isc_timermgr_t *omapi_timermgr;
/* /*
* XXXDCL comment, localize? * XXXDCL comment, localize?
*/ */
@@ -147,12 +147,12 @@ extern isc_boolean_t omapi_ipv6;
void void
connection_send(omapi_connection_object_t *connection); 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_reference((omapi_object_t **)objectp, \
(omapi_object_t *)object, where) (omapi_object_t *)object)
#define OBJECT_DEREF(objectp, where) \ #define OBJECT_DEREF(objectp) \
omapi_object_dereference((omapi_object_t **)objectp, where) omapi_object_dereference((omapi_object_t **)objectp)
#define PASS_CHECK(object, function) \ #define PASS_CHECK(object, function) \
(object->inner != NULL && object->inner->type->function != NULL) (object->inner != NULL && object->inner->type->function != NULL)
@@ -193,6 +193,18 @@ connection_send(omapi_connection_object_t *connection);
return (ISC_R_SUCCESS); \ return (ISC_R_SUCCESS); \
} while (0) } 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 ISC_LANG_ENDDECLS
#endif /* OMAPIP_OMAPIP_P_H */ #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. * Reader callback for a listener object. Accept an incoming connection.
*/ */
static void 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_result_t result;
isc_buffer_t *ibuffer, *obuffer; isc_buffer_t *ibuffer, *obuffer;
isc_task_t *connection_task = NULL; 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. * 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); event->arg);
/* /*
@@ -95,7 +95,7 @@ omapi_listener_accept(isc_task_t *task, isc_event_t *event) {
/* /*
* Create a new connection object. * 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)); omapi_type_connection, sizeof(*connection));
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto free_obuffer; 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); ISC_LIST_APPEND(connection->output_buffers, obuffer, link);
RUNTIME_CHECK(isc_mutex_init(&connection->mutex) == ISC_R_SUCCESS); 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. * 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 * reaped. The omapi_protocol_listener_signal function added a
* reference when it created a protocol object as connection->inner. * reference when it created a protocol object as connection->inner.
*/ */
OBJECT_DEREF(&connection, "omapi_listener_accept"); OBJECT_DEREF(&connection);
return; return;
free_object: free_object:
@@ -139,7 +140,7 @@ free_object:
* Destroy the connection. This will free everything created * Destroy the connection. This will free everything created
* in this function but the event. * in this function but the event.
*/ */
OBJECT_DEREF(&connection, "omapi_listener_accept"); OBJECT_DEREF(&connection);
return; return;
/* /*
@@ -189,8 +190,8 @@ omapi_listener_listen(omapi_object_t *caller, int port, int max) {
/* /*
* Tie the listener object to the calling object. * Tie the listener object to the calling object.
*/ */
OBJECT_REF(&caller->outer, listener, "omapi_protocol_listen"); OBJECT_REF(&caller->outer, listener);
OBJECT_REF(&listener->inner, caller, "omapi_protocol_listen"); OBJECT_REF(&listener->inner, caller);
/* /*
* Create a socket on which to listen. * 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 * because it has two refcnts, one for existing plus one
* for the tie to h->outer. This does not seem right to me. * for the tie to h->outer. This does not seem right to me.
*/ */
OBJECT_DEREF(&listener, "omapi_listen"); OBJECT_DEREF(&listener);
return (result); 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); result = isc_socket_bind(listener->socket, &listener->address);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&listener, "omapi_listen"); OBJECT_DEREF(&listener);
return (result); return (result);
} }
@@ -228,24 +229,24 @@ omapi_listener_listen(omapi_object_t *caller, int port, int max) {
*/ */
result = isc_socket_listen(listener->socket, max); result = isc_socket_listen(listener->socket, max);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&listener, "omapi_listen"); OBJECT_DEREF(&listener);
return (result); return (result);
} }
/* /*
* Queue up the first accept event. The listener object * 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, result = isc_socket_accept(listener->socket, task,
omapi_listener_accept, listener); listener_accept, listener);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
OBJECT_DEREF(&listener, "omapi_listen"); OBJECT_DEREF(&listener);
return (result); return (result);
} }
isc_result_t static isc_result_t
omapi_listener_setvalue(omapi_object_t *listener, omapi_object_t *id, listener_setvalue(omapi_object_t *listener, omapi_object_t *id,
omapi_data_string_t *name, omapi_typed_data_t *value) 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); PASS_SETVALUE(listener);
} }
isc_result_t static isc_result_t
omapi_listener_getvalue(omapi_object_t *listener, omapi_object_t *id, listener_getvalue(omapi_object_t *listener, omapi_object_t *id,
omapi_data_string_t *name, omapi_value_t **value) 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); PASS_GETVALUE(listener);
} }
void static void
omapi_listener_destroy(omapi_object_t *object, const char *name) { listener_destroy(omapi_object_t *object) {
omapi_listener_object_t *listener; omapi_listener_object_t *listener;
REQUIRE(object != NULL && object->type == omapi_type_listener); REQUIRE(object != NULL && object->type == omapi_type_listener);
(void)name; /* Unused. */
listener = (omapi_listener_object_t *)object; listener = (omapi_listener_object_t *)object;
if (listener->socket != NULL) { if (listener->socket != NULL) {
@@ -291,14 +290,13 @@ omapi_listener_destroy(omapi_object_t *object, const char *name) {
} }
} }
isc_result_t static isc_result_t
omapi_listener_signalhandler(omapi_object_t *listener, const char *name, listener_signalhandler(omapi_object_t *listener, const char *name, va_list ap)
va_list ap)
{ {
REQUIRE(listener != NULL && listener->type == omapi_type_listener); 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 * an omapi_signal of "connect" on the listener object. Nothing
* need be done here, but the object that originally requested * need be done here, but the object that originally requested
* the listen needs to signalled that a connection was made. * the listen needs to signalled that a connection was made.
@@ -314,8 +312,8 @@ omapi_listener_signalhandler(omapi_object_t *listener, const char *name,
* Write all the published values associated with the object through the * Write all the published values associated with the object through the
* specified connection. * specified connection.
*/ */
isc_result_t static isc_result_t
omapi_listener_stuffvalues(omapi_object_t *connection, omapi_object_t *id, listener_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
omapi_object_t *listener) omapi_object_t *listener)
{ {
REQUIRE(listener != NULL && listener->type == omapi_type_listener); REQUIRE(listener != NULL && listener->type == omapi_type_listener);
@@ -323,3 +321,14 @@ omapi_listener_stuffvalues(omapi_object_t *connection, omapi_object_t *id,
PASS_STUFFVALUES(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; omapi_message_object_t *omapi_registered_messages;
isc_result_t 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_message_object_t *message = NULL;
omapi_object_t *g; omapi_object_t *g;
isc_result_t result; isc_result_t result;
result = omapi_object_new((omapi_object_t **)&message, result = omapi_object_create((omapi_object_t **)&message,
omapi_type_message, sizeof(*message)); omapi_type_message, sizeof(*message));
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
g = NULL; g = NULL;
result = omapi_generic_new(&g, name); result = omapi_object_create(&g, NULL, 0);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message, "omapi_message_new"); OBJECT_DEREF(&message);
return (result); return (result);
} }
OBJECT_REF(&message->inner, g, name); OBJECT_REF(&message->inner, g);
OBJECT_REF(&g->outer, message, name); OBJECT_REF(&g->outer, message);
OBJECT_REF(o, message, name); OBJECT_REF(o, message);
OBJECT_DEREF(&message, name); OBJECT_DEREF(&message);
OBJECT_DEREF(&g, name); OBJECT_DEREF(&g);
return (result); 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 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_register(omapi_object_t *h) {
omapi_message_object_t *m; omapi_message_object_t *m;
@@ -272,20 +70,15 @@ omapi_message_register(omapi_object_t *h) {
omapi_registered_messages != m); omapi_registered_messages != m);
if (omapi_registered_messages != NULL) { if (omapi_registered_messages != NULL) {
OBJECT_REF(&m->next, omapi_registered_messages, OBJECT_REF(&m->next, omapi_registered_messages);
"omapi_message_register"); OBJECT_REF(&omapi_registered_messages->prev, m);
OBJECT_REF(&omapi_registered_messages->prev, m, OBJECT_DEREF(&omapi_registered_messages);
"omapi_message_register");
OBJECT_DEREF(&omapi_registered_messages,
"omapi_message_register");
} }
OBJECT_REF(&omapi_registered_messages, m, OBJECT_REF(&omapi_registered_messages, m);
"omapi_message_register");
return (ISC_R_SUCCESS);
} }
isc_result_t static void
omapi_message_unregister(omapi_object_t *h) { omapi_message_unregister(omapi_object_t *h) {
omapi_message_object_t *m; omapi_message_object_t *m;
omapi_message_object_t *n; omapi_message_object_t *n;
@@ -301,35 +94,31 @@ omapi_message_unregister(omapi_object_t *h) {
n = NULL; n = NULL;
if (m->next != NULL) { if (m->next != NULL) {
OBJECT_REF(&n, m->next, "omapi_message_unregister"); OBJECT_REF(&n, m->next);
OBJECT_DEREF(&m->next, "omapi_message_unregister"); OBJECT_DEREF(&m->next);
} }
if (m->prev != NULL) { if (m->prev != NULL) {
omapi_message_object_t *tmp = NULL; omapi_message_object_t *tmp = NULL;
OBJECT_REF(&tmp, m->prev, "omapi_message_register"); OBJECT_REF(&tmp, m->prev);
OBJECT_DEREF(&m->prev, "omapi_message_unregister"); OBJECT_DEREF(&m->prev);
if (tmp->next != NULL) if (tmp->next != NULL)
OBJECT_DEREF(&tmp->next, "omapi_message_unregister"); OBJECT_DEREF(&tmp->next);
if (n != NULL) 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 { } else {
OBJECT_DEREF(&omapi_registered_messages, OBJECT_DEREF(&omapi_registered_messages);
"omapi_message_unregister");
if (n != NULL) if (n != NULL)
OBJECT_REF(&omapi_registered_messages, n, OBJECT_REF(&omapi_registered_messages, n);
"omapi_message_unregister");
} }
if (n != NULL) if (n != NULL)
OBJECT_DEREF(&n, "omapi_message_unregister"); OBJECT_DEREF(&n);
return (ISC_R_SUCCESS);
} }
isc_result_t isc_result_t
@@ -492,7 +281,7 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
* return an error. * return an error.
*/ */
if (result == ISC_R_SUCCESS && create != 0 && exclusive != 0) { 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, return (omapi_protocol_send_status(po, NULL,
ISC_R_EXISTS, message->id, ISC_R_EXISTS, message->id,
"specified object already exists")); "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 we're creating the object, do it now.
*/ */
if (object == NULL) { 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) { if (result != ISC_R_SUCCESS) {
return (omapi_protocol_send_status(po, NULL, return (omapi_protocol_send_status(po, NULL,
result, message->id, result, message->id,
@@ -518,7 +309,7 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
message->object, message->object,
message->handle); message->handle);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&object, "omapi_message_process"); OBJECT_DEREF(&object);
return (omapi_protocol_send_status(po, NULL, return (omapi_protocol_send_status(po, NULL,
result, message->id, result, message->id,
"can't update object")); "can't update object"));
@@ -541,13 +332,12 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
send: send:
result = omapi_protocol_send_update(po, NULL, result = omapi_protocol_send_update(po, NULL,
message->id, object); message->id, object);
OBJECT_DEREF(&object, "omapi_message_process"); OBJECT_DEREF(&object);
return (result); return (result);
case OMAPI_OP_UPDATE: case OMAPI_OP_UPDATE:
if (m->object != NULL) { if (m->object != NULL) {
OBJECT_REF(&object, m->object, OBJECT_REF(&object, m->object);
"omapi_message_process");
} else { } else {
result = omapi_handle_lookup(&object, message->handle); result = omapi_handle_lookup(&object, message->handle);
if (result != ISC_R_SUCCESS) { 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, result = omapi_object_update(object, NULL, message->object,
message->handle); message->handle);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&object, "omapi_message_process"); OBJECT_DEREF(&object);
if (message->rid == 0) if (message->rid == 0)
return (omapi_protocol_send_status(po, NULL, return (omapi_protocol_send_status(po, NULL,
result, message->id, result, message->id,
@@ -627,10 +417,217 @@ omapi_message_process(omapi_object_t *mo, omapi_object_t *po) {
"no remove method for object")); "no remove method for object"));
result = (*(object->type->remove))(object, NULL); result = (*(object->type->remove))(object, NULL);
OBJECT_DEREF(&object, "omapi_message_process"); OBJECT_DEREF(&object);
return (omapi_protocol_send_status(po, NULL, result, return (omapi_protocol_send_status(po, NULL, result,
message->id, NULL)); message->id, NULL));
} }
return (ISC_R_NOTIMPLEMENTED); 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. * 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 */ /* Principal Author: Ted Lemon */
@@ -30,12 +30,18 @@
#include <omapi/private.h> #include <omapi/private.h>
isc_result_t 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) size_t size)
{ {
omapi_object_t *new; omapi_object_t *new;
REQUIRE(object != NULL && *object == NULL); 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); new = isc_mem_get(omapi_mctx, size);
if (new == NULL) if (new == NULL)
@@ -53,20 +59,16 @@ omapi_object_new(omapi_object_t **object, omapi_object_type_t *type,
} }
void void
omapi_object_reference(omapi_object_t **r, omapi_object_t *h, omapi_object_reference(omapi_object_t **r, omapi_object_t *h) {
const char *name)
{
REQUIRE(r != NULL && *r == NULL); REQUIRE(r != NULL && *r == NULL);
REQUIRE(h != NULL); REQUIRE(h != NULL);
(void)name; /* Unused. */
*r = h; *r = h;
h->refcnt++; h->refcnt++;
} }
void void
omapi_object_dereference(omapi_object_t **h, const char *name) { omapi_object_dereference(omapi_object_t **h) {
int outer_reference = 0; int outer_reference = 0;
int inner_reference = 0; int inner_reference = 0;
int handle_reference = 0; int handle_reference = 0;
@@ -83,7 +85,7 @@ omapi_object_dereference(omapi_object_t **h, const char *name) {
*/ */
/* /*
* XXXDCL my wording * 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 * only if the inner object's own outer pointer is not what is
* being dereferenced. * being dereferenced.
* (XXXDCL when does it happen that way ?) * (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 (extra_references == 0) {
if (inner_reference != 0) if (inner_reference != 0)
OBJECT_DEREF(&(*h)->inner->outer, name); OBJECT_DEREF(&(*h)->inner->outer);
if (outer_reference != 0) if (outer_reference != 0)
OBJECT_DEREF(&(*h)->outer->inner, name); OBJECT_DEREF(&(*h)->outer->inner);
if ((*h)->type->destroy != NULL) if ((*h)->type->destroy != NULL)
(*((*h)->type->destroy))(*h, name); (*((*h)->type->destroy))(*h, NULL);
isc_mem_put(omapi_mctx, *h, (*h)->object_size); isc_mem_put(omapi_mctx, *h, (*h)->object_size);
} }
} }
*h = NULL; *h = NULL;
} }

View File

@@ -78,22 +78,20 @@ omapi_protocol_connect(omapi_object_t *h, const char *server_name,
isc_result_t result; isc_result_t result;
omapi_protocol_object_t *obj; omapi_protocol_object_t *obj;
obj = isc_mem_get(omapi_mctx, sizeof(*obj)); obj = NULL;
if (obj == NULL) result = omapi_object_create((omapi_object_t **)&obj,
return (ISC_R_NOMEMORY); omapi_type_protocol, sizeof(*obj));
memset(obj, 0, sizeof(*obj)); if (result != ISC_R_SUCCESS)
obj->object_size = sizeof(*obj); return (result);
obj->refcnt = 1;
obj->type = omapi_type_protocol;
result = omapi_connection_toserver((omapi_object_t *)obj, result = omapi_connection_toserver((omapi_object_t *)obj,
server_name, port); server_name, port);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&obj, "omapi_protocol_connect"); OBJECT_DEREF(&obj);
return (result); return (result);
} }
OBJECT_REF(&h->outer, obj, "omapi_protocol_connect"); OBJECT_REF(&h->outer, obj);
OBJECT_REF(&obj->inner, h, "omapi_protocol_connect"); OBJECT_REF(&obj->inner, h);
/* /*
* Send the introductory message. * Send the introductory message.
@@ -102,13 +100,13 @@ omapi_protocol_connect(omapi_object_t *h, const char *server_name,
OMAPI_PROTOCOL_VERSION, OMAPI_PROTOCOL_VERSION,
sizeof(omapi_protocol_header_t)); sizeof(omapi_protocol_header_t));
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&obj, "omapi_protocol_connect"); OBJECT_DEREF(&obj);
return (result); return (result);
} }
if (authinfo) if (authinfo)
OBJECT_REF(&obj->authinfo, authinfo, "omapi_protocol_connect"); OBJECT_REF(&obj->authinfo, authinfo);
OBJECT_DEREF(&obj, "omapi_protocol_accept"); OBJECT_DEREF(&obj);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@@ -286,14 +284,54 @@ 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) { if (connection->is_client) {
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) == RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
ISC_R_SUCCESS); 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);
/*
* 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) == RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
} }
@@ -367,6 +405,12 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
goto disconnect; 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. * Signal omapi_connection_wait() to wake up.
* Only do this for the client side. * 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); ISC_R_SUCCESS);
/* /*
* Release the lock. Contrary to what you might think * If the driving program has already called
* from some documentation sources, it is necessary * omapi_protocol_send_message and the lock
* to do this for the waiting thread to unblock. * 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) == RUNTIME_CHECK(isc_mutex_unlock(&c->mutex) ==
ISC_R_SUCCESS); ISC_R_SUCCESS);
} }
to_header_wait: 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 * Register a need for the number of bytes in a header, and if
* header, and if we already have that many, process * that many are here already, process them immediately.
* 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)) result = omapi_connection_require(connection, p->header_size);
!= ISC_R_SUCCESS) if (result == OMAPI_R_NOTYET)
break; break;
/* else if (result != ISC_R_SUCCESS)
* If we already have the data, fall through. goto disconnect;
*/
/* FALLTHROUGH */
case omapi_protocol_header_wait: case omapi_protocol_header_wait:
result = omapi_message_new((omapi_object_t **)&p->message, result = omapi_message_new((omapi_object_t **)&p->message);
"omapi_protocol_signal_handler");
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto disconnect; 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. * 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; break;
/* else if (result != ISC_R_SUCCESS)
* If it's already here, fall through. goto disconnect;
*/
/* FALLTHROUGH */
case omapi_protocol_name_length_wait: case omapi_protocol_name_length_wait:
result = omapi_connection_getuint16(connection, &nlen); 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, * the authenticator. If we already have it,
* go read it in. * go read it in.
*/ */
if (omapi_connection_require(connection, result = omapi_connection_require(connection,
p->message->authlen) p->message->authlen);
== ISC_R_SUCCESS) if (result == OMAPI_R_NOTYET)
goto signature_wait;
break; break;
else if (result == ISC_R_SUCCESS)
goto signature_wait;
else
goto disconnect;
} }
/* /*
@@ -527,13 +593,13 @@ omapi_protocol_signal_handler(omapi_object_t *h, const char *name, va_list ap)
goto disconnect; goto disconnect;
p->state = omapi_protocol_name_wait; p->state = omapi_protocol_name_wait;
if (omapi_connection_require(connection, nlen) != result = omapi_connection_require(connection, nlen);
ISC_R_SUCCESS) if (result == OMAPI_R_NOTYET)
break; break;
else if (result != ISC_R_SUCCESS)
goto disconnect;
/* /* FALLTHROUGH */
* If it's already here, fall through.
* */
case omapi_protocol_name_wait: case omapi_protocol_name_wait:
result = omapi_connection_copyout(p->name->value, connection, result = omapi_connection_copyout(p->name->value, connection,
@@ -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; p->state = omapi_protocol_value_length_wait;
result = omapi_connection_require(connection, 4); result = omapi_connection_require(connection, 4);
if (result != ISC_R_SUCCESS) if (result == OMAPI_R_NOTYET)
break; break;
else if (result != ISC_R_SUCCESS)
goto disconnect;
/* /* FALLTHROUGH */
* If it's already here, fall through.
*/
case omapi_protocol_value_length_wait: case omapi_protocol_value_length_wait:
omapi_connection_getuint32(connection, &vlen); 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; p->state = omapi_protocol_value_wait;
result = omapi_connection_require(connection, vlen); result = omapi_connection_require(connection, vlen);
if (result != ISC_R_SUCCESS) if (result == OMAPI_R_NOTYET)
break; break;
else if (result != ISC_R_SUCCESS)
goto disconnect;
/* /*
* If it's already here, fall through. * 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 * We need a generic object to hang off of the
* incoming message. * incoming message.
*/ */
result = omapi_generic_new(&p->message->object, result =
"omapi_protocol_signal_handler"); omapi_object_create(&p->message->object,
NULL, 0);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto disconnect; 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_data_stringdereference(&p->name,
"omapi_protocol_signal_handler"); "omapi_protocol_signal_handler");
omapi_data_dereference(&p->value, omapi_data_dereference(&p->value);
"omapi_protocol_signal_handler");
goto need_name_length; goto need_name_length;
signature_wait: 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, result = omapi_message_process((omapi_object_t *)p->message,
h); 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. * Signal omapi_connection_wait() to wake up.
* XXXDCL duplicated from above. * 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) == RUNTIME_CHECK(isc_condition_signal(&c->waiter) ==
ISC_R_SUCCESS); 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) == RUNTIME_CHECK(isc_mutex_unlock(&c->mutex) ==
ISC_R_SUCCESS); 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 * XXXDCL these gotos could be cleared up with one
* more variable to control a loop around the switch. * more variable to control a loop around the switch.
*/ */
fprintf(stderr, "going to header_wait, events_pending = %d\n", fprintf(stderr, "going to header_wait, events_pending = %d"
c->events_pending); " messages_expected = %d\n", c->events_pending,
c->messages_expected);
goto to_header_wait; goto to_header_wait;
default: default:
@@ -712,7 +801,7 @@ omapi_protocol_get_value(omapi_object_t *h, omapi_object_t *id,
} }
void void
omapi_protocol_destroy(omapi_object_t *h, const char *name) { omapi_protocol_destroy(omapi_object_t *h) {
omapi_protocol_object_t *p; omapi_protocol_object_t *p;
REQUIRE(h != NULL && h->type == omapi_type_protocol); 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; p = (omapi_protocol_object_t *)h;
if (p->message != NULL) if (p->message != NULL)
OBJECT_DEREF(&p->message, name); OBJECT_DEREF(&p->message);
if (p->authinfo != NULL) 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->refcnt = 1;
obj->type = omapi_type_protocol_listener; obj->type = omapi_type_protocol_listener;
OBJECT_REF(&h->outer, obj, "omapi_protocol_listen"); OBJECT_REF(&h->outer, obj);
OBJECT_REF(&obj->inner, h, "omapi_protocol_listen"); OBJECT_REF(&obj->inner, h);
result = omapi_listener_listen((omapi_object_t *)obj, port, max); result = omapi_listener_listen((omapi_object_t *)obj, port, max);
OBJECT_DEREF(&obj, "omapi_protocol_listen"); OBJECT_DEREF(&obj);
return (result); return (result);
} }
@@ -800,8 +889,8 @@ omapi_protocol_listener_signal(omapi_object_t *h, const char *name, va_list ap)
* connection. * connection.
*/ */
obj = NULL; obj = NULL;
result = omapi_object_new((omapi_object_t **)&obj, omapi_type_protocol, result = omapi_object_create((omapi_object_t **)&obj,
sizeof(*obj)); omapi_type_protocol, sizeof(*obj));
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
/* /*
* When the unsuccessful return value is percolated back to * 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 * Tie the protocol object bidirectionally to the connection
* object, with the connection as the outer object. * object, with the connection as the outer object.
*/ */
OBJECT_REF(&obj->outer, c, "omapi_protocol_accept"); OBJECT_REF(&obj->outer, c);
OBJECT_REF(&c->inner, obj, "omapi_protocol_accept"); OBJECT_REF(&c->inner, obj);
/* /*
* Send the introductory message. * 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 * XXXDCL aigh, this is so confusing. I don't think the
* right thing is being done. * 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 * 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 * XXXDCL this is what ted did, but i'm not sure my explanation
* is correct. * is correct.
*/ */
OBJECT_DEREF(&obj, "omapi_protocol_accept"); OBJECT_DEREF(&obj);
return (result); return (result);
} }
@@ -867,10 +956,10 @@ omapi_protocol_listener_get_value(omapi_object_t *h, omapi_object_t *id,
} }
void 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); 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); 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) if (result != ISC_R_SUCCESS)
return (result); 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); result = omapi_set_string_value(message, NULL, "message", msg);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message, "omapi_protocol_send_status"); OBJECT_DEREF(&message);
return (result); 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); 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) if (result != ISC_R_SUCCESS)
return (result); return (result);
@@ -958,7 +1047,7 @@ omapi_protocol_send_update(omapi_object_t *po, omapi_object_t *id,
"object", object); "object", object);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message, "dhcpctl_open_object"); OBJECT_DEREF(&message);
return (result); return (result);
} }

View File

@@ -27,13 +27,9 @@
omapi_object_type_t *omapi_type_connection; omapi_object_type_t *omapi_type_connection;
omapi_object_type_t *omapi_type_listener; 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_generic;
omapi_object_type_t *omapi_type_protocol; omapi_object_type_t *omapi_type_protocol;
omapi_object_type_t *omapi_type_protocol_listener; 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_type_message;
omapi_object_type_t *omapi_object_types; omapi_object_type_t *omapi_object_types;
@@ -41,7 +37,6 @@ int omapi_object_type_count;
isc_mem_t *omapi_mctx; isc_mem_t *omapi_mctx;
isc_taskmgr_t *omapi_taskmgr; isc_taskmgr_t *omapi_taskmgr;
isc_timermgr_t *omapi_timermgr;
isc_socketmgr_t *omapi_socketmgr; isc_socketmgr_t *omapi_socketmgr;
isc_boolean_t omapi_ipv6 = ISC_FALSE; isc_boolean_t omapi_ipv6 = ISC_FALSE;
@@ -74,64 +69,27 @@ omapi_init(isc_mem_t *mctx) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); 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) if (isc_net_probeipv6() == ISC_R_SUCCESS)
omapi_ipv6 = ISC_TRUE; omapi_ipv6 = ISC_TRUE;
else else
omapi_ipv6 = ISC_FALSE; omapi_ipv6 = ISC_FALSE;
/* /*
* Register all the standard object types. * Initialize all the standard object types.
*/ */
result = omapi_object_type_register(&omapi_type_connection, result = omapi_generic_init();
"connection",
omapi_connection_setvalue,
omapi_connection_getvalue,
omapi_connection_destroy,
omapi_connection_signalhandler,
omapi_connection_stuffvalues,
0, 0, 0);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = omapi_object_type_register(&omapi_type_listener, result = omapi_listener_init();
"listener",
omapi_listener_setvalue,
omapi_listener_getvalue,
omapi_listener_destroy,
omapi_listener_signalhandler,
omapi_listener_stuffvalues,
0, 0, 0);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = omapi_object_type_register(&omapi_type_io_object, result = omapi_connection_init();
"io",
omapi_io_setvalue,
omapi_io_getvalue,
omapi_io_destroy,
omapi_io_signalhandler,
omapi_io_stuffvalues,
0, 0, 0);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = omapi_object_type_register(&omapi_type_generic, result = omapi_object_register(&omapi_type_protocol,
"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,
"protocol", "protocol",
omapi_protocol_set_value, omapi_protocol_set_value,
omapi_protocol_get_value, omapi_protocol_get_value,
@@ -142,7 +100,7 @@ omapi_init(isc_mem_t *mctx) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = omapi_object_type_register(&omapi_type_protocol_listener, result = omapi_object_register(&omapi_type_protocol_listener,
"protocol-listener", "protocol-listener",
omapi_protocol_listener_set_value, omapi_protocol_listener_set_value,
omapi_protocol_listener_get_value, omapi_protocol_listener_get_value,
@@ -153,45 +111,32 @@ omapi_init(isc_mem_t *mctx) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = omapi_object_type_register(&omapi_type_message, result = omapi_message_init();
"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);
return (result); 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 void
omapi_shutdown() { omapi_destroy() {
omapi_object_type_t *type, *next_type; omapi_object_type_t *type, *next_type;
isc_socketmgr_destroy(&omapi_socketmgr); isc_socketmgr_destroy(&omapi_socketmgr);
isc_taskmgr_destroy(&omapi_taskmgr); isc_taskmgr_destroy(&omapi_taskmgr);
isc_timermgr_destroy(&omapi_timermgr);
for (type = omapi_object_types; type != NULL; type = next_type) { for (type = omapi_object_types; type != NULL; type = next_type) {
next_type = type->next; next_type = type->next;
isc_mem_put(omapi_mctx, type, sizeof(*type)); isc_mem_put(omapi_mctx, type, sizeof(*type));
} }
} }
isc_result_t 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) isc_result_t (*set_value)
(omapi_object_t *, (omapi_object_t *,
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 **), omapi_value_t **),
void (*destroy) void (*destroy)
(omapi_object_t *, (omapi_object_t *),
const char *),
isc_result_t (*signal_handler) isc_result_t (*signal_handler)
(omapi_object_t *, (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); result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_boolean_value"); omapi_data_stringdereference(&n, "omapi_set_boolean_value");
omapi_data_dereference(&tv, "omapi_set_boolean_value"); omapi_data_dereference(&tv);
return (result); 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); result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_int_value"); omapi_data_stringdereference(&n, "omapi_set_int_value");
omapi_data_dereference(&tv, "omapi_set_int_value"); omapi_data_dereference(&tv);
return (result); 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); result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_object_value"); omapi_data_stringdereference(&n, "omapi_set_object_value");
omapi_data_dereference(&tv, "omapi_set_object_value"); omapi_data_dereference(&tv);
return (result); 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); result = omapi_set_value(h, id, n, tv);
omapi_data_stringdereference(&n, "omapi_set_string_value"); omapi_data_stringdereference(&n, "omapi_set_string_value");
omapi_data_dereference(&tv, "omapi_set_string_value"); omapi_data_dereference(&tv);
return (result); 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); 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 isc_result_t
omapi_object_update(omapi_object_t *obj, omapi_object_t *id, omapi_object_update(omapi_object_t *obj, omapi_object_t *id,
omapi_object_t *src, omapi_handle_t handle) omapi_object_t *src, omapi_handle_t handle)