Commit 3eab4110 authored by David Lawrence's avatar David Lawrence
Browse files

checkpoint

parent a928d619
......@@ -31,14 +31,14 @@ CDEFINES =
CWARNINGS =
# Alphabetically
OBJS = buffer.@O@ connection.@O@ data.@O@ dispatch.@O@ generic.@O@ \
handle.@O@ listener.@O@ message.@O@ object.@O@ protocol.@O@ \
support.@O@ version.@O@
OBJS = connection.@O@ data.@O@ dispatch.@O@ generic.@O@ \
handle.@O@ lib.@O@ listener.@O@ message.@O@ object.@O@ \
protocol.@O@ result.@O@ support.@O@ version.@O@
# Alphabetically
SRCS = buffer.c connection.c data.c dispatch.c generic.c \
handle.c listener.c message.c object.c protocol.c \
support.c version.c
SRCS = connection.c data.c dispatch.c generic.c \
handle.c lib.c listener.c message.c object.c \
protocol.c result.c support.c version.c
LIBS = @LIBS@
......
/*
* Copyright (C) 1996, 1997, 1998, 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/* $Id: buffer.c,v 1.3 2000/01/04 20:04:37 tale Exp $ */
/* Principal Author: Ted Lemon */
/*
* Buffer access functions for the object management protocol.
*/
#include <errno.h>
#include <stddef.h> /* NULL */
#include <unistd.h> /* read */
#include <isc/assertions.h>
#include <isc/error.h>
#include <isc/socket.h>
#include <omapi/private.h>
void
omapi_connection_read(isc_task_t *task, isc_event_t *event) {
isc_buffer_t *buffer;
isc_socket_t *socket;
isc_socketevent_t *socketevent;
omapi_connection_object_t *connection;
socket = event->sender;
socketevent = (isc_socketevent_t *)event;
connection = event->arg;
buffer = ISC_LIST_HEAD(socketevent->bufferlist);
if (socketevent->result != ISC_R_SUCCESS) {
/*
* Abandon this socket.
*/
isc_socket_detach(&socket);
/* XXXDCL nope, not right at all */
ISC_LIST_UNLINK(socketevent->bufferlist, buffer, link);
isc_buffer_free(&buffer);
isc_event_free(&event);
isc_task_shutdown(task);
return;
}
connection->in_bytes += socketevent->n;
/* XXXDCL more screwage */
while (buffer != NULL) {
ISC_LIST_APPEND(connection->input_buffers, buffer, link);
buffer = ISC_LIST_NEXT(buffer, link);
}
while (connection->bytes_needed <= connection->in_bytes)
omapi_signal(event->arg, "ready", connection);
/*
* Queue up another recv task.
*/
isc_socket_recvv(socket, &connection->input_buffers,
connection->bytes_needed - connection->in_bytes,
task, omapi_connection_read, connection);
isc_event_free(&event);
}
void
omapi_connection_written(isc_task_t *task, isc_event_t *event) {
isc_buffer_t *buffer;
isc_socket_t *socket;
isc_socketevent_t *socketevent;
omapi_connection_object_t *connection;
socket = event->sender;
socketevent = (isc_socketevent_t *)event;
connection = event->arg;
/* XXXDCL more screwage */
buffer = ISC_LIST_HEAD(socketevent->bufferlist);
while (buffer != NULL) {
ISC_LIST_ENQUEUE(connection->output_buffers, buffer, link);
buffer = ISC_LIST_NEXT(buffer, link);
}
buffer = ISC_LIST_HEAD(connection->output_buffers);
if (socketevent->result != ISC_R_SUCCESS) {
/*
* Abandon this socket.
*/
isc_socket_detach(&socket);
/* XXXDCL nope, not right at all */
ISC_LIST_UNLINK(connection->output_buffers, buffer, link);
isc_buffer_free(&buffer);
isc_event_free(&event);
isc_task_shutdown(task);
OBJECT_DEREF(&connection, "omapi_connection_written");
return;
}
connection->out_bytes -= socketevent->n;
isc_buffer_compact(buffer);
if (connection->out_bytes > 0)
isc_socket_sendv(socket, &connection->output_buffers, task,
omapi_connection_written, connection);
return;
}
/*
* Put some bytes into the output buffer for a connection.
*/
isc_result_t
omapi_connection_copyin(omapi_object_t *h, unsigned char *bufp,
unsigned int len)
{
omapi_connection_object_t *connection;
isc_buffer_t *obuffer;
REQUIRE(h != NULL && h->type == omapi_type_connection);
connection = (omapi_connection_object_t *)h;
obuffer = ISC_LIST_HEAD(connection->output_buffers);
/* XXXDCL check for space first */
isc_buffer_putmem(obuffer, bufp, len);
connection->out_bytes += len;
return (ISC_R_SUCCESS);
}
/*
* Copy some bytes from the input buffer, and advance the input buffer
* pointer beyond the bytes copied out.
*/
isc_result_t
omapi_connection_copyout(unsigned char *buf, omapi_object_t *h,
unsigned int size)
{
omapi_connection_object_t *connection;
isc_buffer_t *ibuffer;
REQUIRE(h != NULL && h->type == omapi_type_connection);
connection = (omapi_connection_object_t *)h;
if (size > connection->in_bytes)
return (ISC_R_NOMORE);
ibuffer = ISC_LIST_HEAD(connection->input_buffers);
(void)memcpy(buf, ibuffer->base, size);
isc_buffer_forward(ibuffer, size);
isc_buffer_compact(ibuffer);
connection->in_bytes -= size;
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_connection_get_uint32(omapi_object_t *c, isc_uint32_t *value) {
isc_uint32_t inbuf;
isc_result_t result;
result = omapi_connection_copyout((unsigned char *)&inbuf, c,
sizeof(inbuf));
if (result != ISC_R_SUCCESS)
return (result);
*value = ntohl(inbuf);
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_connection_put_uint32(omapi_object_t *c, isc_uint32_t value) {
isc_uint32_t inbuf;
inbuf = htonl(value);
return (omapi_connection_copyin(c, (unsigned char *)&inbuf,
sizeof(inbuf)));
}
isc_result_t
omapi_connection_get_uint16(omapi_object_t *c, isc_uint16_t *value) {
isc_uint16_t inbuf;
isc_result_t result;
result = omapi_connection_copyout((unsigned char *)&inbuf, c,
sizeof(inbuf));
if (result != ISC_R_SUCCESS)
return (result);
*value = ntohs (inbuf);
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_connection_put_uint16(omapi_object_t *c, isc_uint32_t value) {
isc_uint16_t inbuf;
REQUIRE(value < 65536);
inbuf = htons((isc_uint16_t)value);
return (omapi_connection_copyin(c, (unsigned char *)&inbuf,
sizeof(inbuf)));
}
isc_result_t
omapi_connection_write_typed_data(omapi_object_t *c, omapi_typed_data_t *data)
{
isc_result_t result;
omapi_handle_t handle;
REQUIRE(data != NULL &&
(data->type == omapi_datatype_int ||
data->type == omapi_datatype_string ||
data->type == omapi_datatype_data ||
data->type == omapi_datatype_object));
switch (data->type) {
case omapi_datatype_int:
result = omapi_connection_put_uint32(c, sizeof(isc_uint32_t));
if (result != ISC_R_SUCCESS)
return (result);
return (omapi_connection_put_uint32(c, ((isc_uint32_t)
(data->u.integer))));
case omapi_datatype_string:
case omapi_datatype_data:
result = omapi_connection_put_uint32(c, data->u.buffer.len);
if (result != ISC_R_SUCCESS)
return (result);
if (data->u.buffer.len > 0)
return (omapi_connection_copyin(c,
data->u.buffer.value,
data->u.buffer.len));
return (ISC_R_SUCCESS);
case omapi_datatype_object:
if (data->u.object != NULL) {
result = omapi_object_handle(&handle, data->u.object);
if (result != ISC_R_SUCCESS)
return (result);
} else
handle = 0;
result = omapi_connection_put_uint32(c, sizeof(handle));
if (result != ISC_R_SUCCESS)
return (result);
return (omapi_connection_put_uint32(c, handle));
}
UNEXPECTED_ERROR(__FILE__, __LINE__,
"unknown type in omapi_connection_write_typed_data: "
"%d\n", data->type);
return (ISC_R_UNEXPECTED);
}
isc_result_t
omapi_connection_put_name(omapi_object_t *c, const char *name) {
isc_result_t result;
unsigned int len = strlen(name);
if (len > 65535)
/* XXXDCL better error? */
return (ISC_R_FAILURE);
result = omapi_connection_put_uint16(c, len);
if (result != ISC_R_SUCCESS)
return (result);
return (omapi_connection_copyin(c, (char *)name, len));
}
isc_result_t
omapi_connection_put_string(omapi_object_t *c, const char *string) {
isc_result_t result;
unsigned int len;
if (string != NULL)
len = strlen(string);
else
len = 0;
result = omapi_connection_put_uint32(c, len);
if (result == ISC_R_SUCCESS && len > 0)
result = omapi_connection_copyin(c, (char *)string, len);
return (result);
}
isc_result_t
omapi_connection_put_handle(omapi_object_t *c, omapi_object_t *h) {
isc_result_t result;
omapi_handle_t handle;
if (h != NULL) {
result = omapi_object_handle(&handle, h);
if (result != ISC_R_SUCCESS)
return (result);
} else
handle = 0; /* The null handle. */
result = omapi_connection_put_uint32(c, sizeof(handle));
if (result == ISC_R_SUCCESS)
result = omapi_connection_put_uint32(c, handle);
return (result);
}
......@@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: connection.c,v 1.3 2000/01/04 20:04:37 tale Exp $ */
/* $Id: connection.c,v 1.4 2000/01/06 03:36:27 tale Exp $ */
/* Principal Author: Ted Lemon */
......@@ -23,16 +23,22 @@
* Subroutines for dealing with connections.
*/
#include <errno.h>
#include <fcntl.h> /* F_SETFL, O_NONBLOCK */
#include <stddef.h> /* NULL */
#include <string.h> /* memset */
#include <unistd.h> /* close */
#include <isc/assertions.h>
#include <isc/error.h>
#include <isc/netdb.h>
#include <omapi/private.h>
/*
* Forward declarations.
*/
void
connection_send(omapi_connection_object_t *connection);
/*
* Swiped from bin/tests/sdig.c.
*/
......@@ -71,39 +77,87 @@ get_address(const char *hostname, in_port_t port, isc_sockaddr_t *sockaddr) {
return (ISC_R_SUCCESS);
}
static void
abandon_connection(omapi_connection_object_t *connection,
isc_event_t *event, isc_result_t result)
{
isc_buffer_t *buffer;
if (event != NULL)
isc_event_free(&event);
if (connection->events_pending > 0) {
/*
* The only time CANCELED results should be generated is
* because this function already called isc_socket_cancel.
* If this isn't a CANCELED result, then the isc_socket_cancel
* needs to be done.
*/
if (result != ISC_R_CANCELED)
isc_socket_cancel(connection->socket, NULL,
ISC_SOCKCANCEL_ALL);
/*
* Technically not yet, but the end result is the same.
*/
connection->state = omapi_connection_unconnected;
return;
}
while ((buffer = ISC_LIST_HEAD(connection->input_buffers)) != NULL) {
ISC_LIST_UNLINK(connection->input_buffers, buffer, link);
isc_buffer_free(&buffer);
}
while ((buffer = ISC_LIST_HEAD(connection->output_buffers)) != NULL) {
ISC_LIST_UNLINK(connection->output_buffers, buffer, link);
isc_buffer_free(&buffer);
}
isc_task_destroy(&connection->task);
isc_socket_detach(&connection->socket);
OBJECT_DEREF(&connection, "abandon_connection");
return;
}
/*
* This is the function that is called when a CONNECT event is posted on
* This is the function that is called when a connect event is posted on
* the socket as a result of isc_socket_connect.
*/
static void
omapi_connection_connect(isc_task_t *task, isc_event_t *event) {
connect_done(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
isc_socket_connev_t *connect_event;
isc_socket_t *socket;
isc_socket_connev_t *connectevent;
omapi_connection_object_t *connection;
ENSURE(event->sender == connection->socket);
socket = event->sender;
connectevent = (isc_socket_connev_t *)event;
connection = event->arg;
connect_event = (isc_socket_connev_t *)event;
if (connect_event->result != ISC_R_SUCCESS) {
isc_socket_detach(&connection->socket);
isc_event_free(&event);
isc_task_shutdown(task);
ENSURE(socket == connection->socket && task == connection->task);
connection->events_pending--;
if (connectevent->result != ISC_R_SUCCESS) {
abandon_connection(connection, event, connectevent->result);
return;
}
connection = event->arg;
result = isc_socket_getpeername(connection->socket,
&connection->remote_addr);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&connection, "omapi_connection_connect");
abandon_connection(connection, event, connectevent->result);
return;
}
result = isc_socket_getsockname(connection->socket,
&connection->local_addr);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&connection, "omapi_connection_connect");
abandon_connection(connection, event, connectevent->result);
return;
}
......@@ -114,20 +168,132 @@ omapi_connection_connect(isc_task_t *task, isc_event_t *event) {
return;
}
/*
* This is the function that is called when a recv event is posted on
* the socket as a result of isc_socket_recv*.
*/
static void
recv_done(isc_task_t *task, isc_event_t *event) {
isc_buffer_t *buffer;
isc_socket_t *socket;
isc_socketevent_t *socketevent;
omapi_connection_object_t *connection;
socket = event->sender;
socketevent = (isc_socketevent_t *)event;
connection = event->arg;
ENSURE(socket == connection->socket && task == connection->task);
connection->events_pending--;
/*
* Restore the input buffers to the connection object.
*/
for (buffer = ISC_LIST_HEAD(socketevent->bufferlist);
buffer != NULL;
buffer = ISC_LIST_NEXT(buffer, link))
ISC_LIST_APPEND(connection->input_buffers, buffer, link);
if (socketevent->result != ISC_R_SUCCESS) {
abandon_connection(connection, event, socketevent->result);
return;
}
connection->in_bytes += socketevent->n;
while (connection->bytes_needed <= connection->in_bytes &&
connection->bytes_needed > 0)
omapi_signal(event->arg, "ready", connection);
#if 0
/*
* XXXDCL it may be the case that another recv task should be queued,
* but I haven't thought it through fully.
*/
if (connection->bytes_needed > 0)
isc_socket_recvv(socket, &connection->input_buffers,
connection->bytes_needed -
connection->in_bytes,
task, recv_done, connection);
#endif
isc_event_free(&event);
}
/*
* This is the function that is called when a send event is posted on
* the socket as a result of isc_socket_send*.
*/
static void
send_done(isc_task_t *task, isc_event_t *event) {
isc_buffer_t *buffer;
isc_socket_t *socket;
isc_socketevent_t *socketevent;
omapi_connection_object_t *connection;
socket = event->sender;
socketevent = (isc_socketevent_t *)event;
connection = event->arg;
ENSURE(socket == connection->socket && task == connection->task);
connection->events_pending--;
/*
* Restore the bufferlist into the connection object.
*/
for (buffer = ISC_LIST_HEAD(socketevent->bufferlist);
buffer != NULL;
buffer = ISC_LIST_NEXT(buffer, link))
ISC_LIST_APPEND(connection->output_buffers, buffer, link);
if (socketevent->result != ISC_R_SUCCESS) {
abandon_connection(connection, event, socketevent->result);
return;
}
connection->out_bytes -= socketevent->n;
/*
* If there is still data to be written, another send event is queued.
*/
connection_send(connection);
isc_event_free(&event);
return;
}
void
connection_send(omapi_connection_object_t *connection) {
REQUIRE(connection != NULL &&
connection->type == omapi_type_connection);
if (connection->out_bytes > 0) {
ENSURE(!ISC_LIST_EMPTY(connection->output_buffers));
isc_socket_sendv(connection->socket,
&connection->output_buffers, connection->task,
send_done, connection);
connection->events_pending++;
}
}
/*
* Make an outgoing connection to an OMAPI server.
*/
isc_result_t
omapi_connection_toserver(omapi_object_t *c, const char *server_name, int port)
omapi_connection_toserver(omapi_object_t *protocol, const char *server_name,
int port)
{
isc_result_t result;
isc_buffer_t *ibuffer, *obuffer;
isc_task_t *task;
isc_sockaddr_t sockaddr;
omapi_connection_object_t *obj;
#if 0 /*XXXDCL*/
int flag;
#endif
isc_buffer_t *ibuffer = NULL, *obuffer = NULL;
isc_task_t *task = NULL;
omapi_connection_object_t *connection = NULL;
result