summaryrefslogtreecommitdiff
path: root/omapip/buffer.c
diff options
context:
space:
mode:
authorTed Lemon <source@isc.org>1999-09-02 00:32:56 +0000
committerTed Lemon <source@isc.org>1999-09-02 00:32:56 +0000
commit61b844bfd7641a62d681a1f70d3b6dbc485ce4b6 (patch)
tree01e4c19e3b1025eade692fb7f5d6748099f96b01 /omapip/buffer.c
parenta40cbc2b969af1eeb0bdd1912040c3a829a5b220 (diff)
downloadisc-dhcp-61b844bfd7641a62d681a1f70d3b6dbc485ce4b6.tar.gz
Omapi library, initial checkin
Diffstat (limited to 'omapip/buffer.c')
-rw-r--r--omapip/buffer.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/omapip/buffer.c b/omapip/buffer.c
new file mode 100644
index 00000000..6bd2c946
--- /dev/null
+++ b/omapip/buffer.c
@@ -0,0 +1,396 @@
+/* buffer.c
+
+ Buffer access functions for the object management protocol... */
+
+/*
+ * Copyright (c) 1996-1999 Internet Software Consortium.
+ * Use is subject to license terms which appear in the file named
+ * ISC-LICENSE that should have accompanied this file when you
+ * received it. If a file named ISC-LICENSE did not accompany this
+ * file, or you are not sure the one you have is correct, you may
+ * obtain an applicable copy of the license at:
+ *
+ * http://www.isc.org/isc-license-1.0.html.
+ *
+ * This file is part of the ISC DHCP distribution. The documentation
+ * associated with this file is listed in the file DOCUMENTATION,
+ * included in the top-level directory of this release.
+ *
+ * Support and other services are available for ISC products - see
+ * http://www.isc.org for more information.
+ */
+
+#include <omapip/omapip.h>
+
+/* Make sure that at least len bytes are in the input buffer, and if not,
+ read enough bytes to make up the difference. */
+
+isc_result_t omapi_connection_reader (omapi_object_t *h)
+{
+ omapi_buffer_t *buffer;
+ isc_result_t status;
+ int read_len, read_status;
+ omapi_connection_object_t *c;
+ int bytes_to_read;
+
+ if (!h || h -> type != omapi_type_connection)
+ return ISC_R_INVALIDARG;
+ c = (omapi_connection_object_t *)h;
+
+ /* Make sure c -> bytes_needed is valid. */
+ if (c -> bytes_needed < 0)
+ return ISC_R_INVALIDARG;
+
+ /* See if there are enough bytes. */
+ if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
+ c -> in_bytes > c -> bytes_needed)
+ return ISC_R_SUCCESS;
+
+ if (c -> inbufs) {
+ for (buffer = c -> inbufs; buffer -> next;
+ buffer = buffer -> next)
+ ;
+ if (!BUFFER_BYTES_AVAIL (buffer)) {
+ status = omapi_buffer_new (&buffer -> next,
+ "omapi_private_read");
+ if (status != ISC_R_SUCCESS)
+ return status;
+ buffer = buffer -> next;
+ }
+ } else {
+ status = omapi_buffer_new (&c -> inbufs,
+ "omapi_private_read");
+ if (status != ISC_R_SUCCESS)
+ return status;
+ buffer = c -> inbufs;
+ }
+
+ bytes_to_read = BUFFER_BYTES_AVAIL (buffer);
+
+ while (bytes_to_read) {
+ if (buffer -> tail >= buffer -> head)
+ read_len = sizeof (buffer -> buf) - buffer -> tail - 1;
+ else
+ read_len = buffer -> tail - buffer -> head - 1;
+
+ read_status = read (c -> socket,
+ &buffer -> buf [buffer -> tail], read_len);
+ if (read_status < 0) {
+ if (errno == EWOULDBLOCK)
+ return ISC_R_NOMORE;
+ else if (errno == EIO)
+ return ISC_R_IOERROR;
+ else if (errno == EINVAL)
+ return ISC_R_INVALIDARG;
+ else if (errno == ECONNRESET) {
+ omapi_disconnect (h, 0);
+ return ISC_R_SHUTTINGDOWN;
+ } else
+ return ISC_R_UNEXPECTED;
+ }
+ if (read_status == 0) {
+ omapi_disconnect (h, 0);
+ return ISC_R_SHUTTINGDOWN;
+ }
+ buffer -> tail += read_status;
+ c -> in_bytes += read_status;
+ if (buffer -> tail == sizeof buffer -> buf)
+ buffer -> tail = 0;
+ if (read_status < read_len)
+ break;
+ bytes_to_read -= read_status;
+ }
+
+ if (c -> bytes_needed >= c -> in_bytes) {
+ omapi_signal (h, "ready", c);
+ }
+ return ISC_R_SUCCESS;
+}
+
+/* Put some bytes into the output buffer for a connection. */
+
+isc_result_t omapi_connection_copyin (omapi_object_t *h,
+ unsigned char *bufp,
+ int len)
+{
+ omapi_buffer_t *buffer;
+ isc_result_t status;
+ int bytes_copied = 0;
+ int copy_len;
+ omapi_connection_object_t *c;
+
+ /* Make sure len is valid. */
+ if (len < 0)
+ return ISC_R_INVALIDARG;
+ if (!h || h -> type != omapi_type_connection)
+ return ISC_R_INVALIDARG;
+ c = (omapi_connection_object_t *)h;
+
+ if (c -> outbufs) {
+ for (buffer = c -> outbufs;
+ buffer -> next; buffer = buffer -> next)
+ ;
+ } else {
+ status = omapi_buffer_new (&c -> outbufs,
+ "omapi_private_buffer_copyin");
+ if (status != ISC_R_SUCCESS)
+ return status;
+ buffer = c -> outbufs;
+ }
+
+ while (bytes_copied < len) {
+ /* If there is no space available in this buffer,
+ allocate a new one. */
+ if (!BUFFER_BYTES_AVAIL (buffer)) {
+ status = (omapi_buffer_new
+ (&buffer -> next,
+ "omapi_private_buffer_copyin"));
+ if (status != ISC_R_SUCCESS)
+ return status;
+ buffer = buffer -> next;
+ }
+
+ if (buffer -> tail < buffer -> head)
+ copy_len = buffer -> tail - buffer -> head - 1;
+ else
+ copy_len = sizeof (buffer -> buf) - buffer -> tail - 1;
+ if (copy_len > (len - bytes_copied))
+ copy_len = len - bytes_copied;
+
+ memcpy (&buffer -> buf [buffer -> tail],
+ &bufp [bytes_copied], copy_len);
+ buffer -> tail += copy_len;
+ c -> out_bytes += copy_len;
+ bytes_copied += copy_len;
+ if (buffer -> tail == sizeof buffer -> buf)
+ buffer -> tail = 0;
+ }
+ return ISC_R_SUCCESS;
+}
+
+/* Copy some bytes from the input buffer, and advance the input buffer
+ pointer beyond the bytes copied out. */
+
+u_int32_t omapi_connection_copyout (unsigned char *buf,
+ omapi_object_t *h,
+ int size)
+{
+ int bytes_remaining;
+ int bytes_this_copy;
+ omapi_buffer_t *buffer;
+ unsigned char *bufp;
+ omapi_connection_object_t *c;
+
+ if (!h || h -> type != omapi_type_connection)
+ return ISC_R_INVALIDARG;
+ c = (omapi_connection_object_t *)h;
+
+ if (size > c -> in_bytes)
+ return ISC_R_NOMORE;
+ bufp = buf;
+ bytes_remaining = size;
+ buffer = c -> inbufs;
+
+ while (bytes_remaining) {
+ if (!buffer)
+ return ISC_R_UNEXPECTED;
+ if (buffer -> head != buffer -> tail) {
+ if (buffer -> head > buffer -> tail) {
+ bytes_this_copy = (sizeof buffer -> buf -
+ buffer -> head);
+ } else {
+ bytes_this_copy =
+ buffer -> tail - buffer -> head;
+ }
+ if (bytes_this_copy > bytes_remaining)
+ bytes_this_copy = bytes_remaining;
+ if (bufp) {
+ memcpy (bufp, &buffer -> buf [buffer -> head],
+ bytes_this_copy);
+ bufp += bytes_this_copy;
+ }
+ bytes_remaining -= bytes_this_copy;
+ buffer -> head += bytes_this_copy;
+ if (buffer -> head == sizeof buffer -> buf)
+ buffer -> head = 0;
+ c -> in_bytes -= bytes_this_copy;
+ }
+
+ if (buffer -> head == buffer -> tail)
+ buffer = buffer -> next;
+ }
+
+ /* Get rid of any input buffers that we emptied. */
+ buffer = (omapi_buffer_t *)0;
+ while (c -> inbufs &&
+ c -> inbufs -> head == c -> inbufs -> tail) {
+ if (c -> inbufs -> next) {
+ omapi_buffer_reference
+ (&buffer,
+ c -> inbufs -> next,
+ "omapi_private_buffer_copyout");
+ omapi_buffer_dereference
+ (&c -> inbufs -> next,
+ "omapi_private_buffer_copyout");
+ }
+ omapi_buffer_dereference (&c -> inbufs,
+ "omapi_private_buffer_copyout");
+ omapi_buffer_reference (&c -> inbufs,
+ buffer,
+ "omapi_private_buffer_copyout");
+ omapi_buffer_dereference (&buffer,
+ "omapi_private_buffer_copyout");
+ }
+ return ISC_R_SUCCESS;
+}
+
+u_int32_t omapi_connection_writer (omapi_object_t *h)
+{
+ int bytes_this_write;
+ int bytes_written;
+ omapi_buffer_t *buffer;
+ unsigned char *bufp;
+ omapi_connection_object_t *c;
+
+ if (!h || h -> type != omapi_type_connection)
+ return ISC_R_INVALIDARG;
+ c = (omapi_connection_object_t *)h;
+
+ /* Already flushed... */
+ if (!c -> out_bytes)
+ return ISC_R_SUCCESS;
+
+ buffer = c -> outbufs;
+
+ while (c -> out_bytes) {
+ if (!buffer)
+ return ISC_R_UNEXPECTED;
+ if (buffer -> head != buffer -> tail) {
+ if (buffer -> head > buffer -> tail) {
+ bytes_this_write = (sizeof buffer -> buf -
+ buffer -> head);
+ } else {
+ bytes_this_write =
+ (buffer -> tail - buffer -> head);
+ }
+ bytes_written = write (c -> socket,
+ &buffer -> buf [buffer -> head],
+ bytes_this_write);
+ /* If the write failed with EWOULDBLOCK or we wrote
+ zero bytes, a further write would block, so we have
+ flushed as much as we can for now. Other errors
+ are really errors. */
+ if (bytes_written < 0) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
+ return ISC_R_SUCCESS;
+ else if (errno == EPIPE)
+ return ISC_R_NOCONN;
+ else if (errno == EFBIG || errno == EDQUOT)
+ return ISC_R_NORESOURCES;
+ else if (errno == ENOSPC)
+ return ISC_R_NOSPACE;
+ else if (errno == EIO)
+ return ISC_R_IOERROR;
+ else if (errno == EINVAL)
+ return ISC_R_INVALIDARG;
+ else if (errno == ECONNRESET)
+ return ISC_R_SHUTTINGDOWN;
+ else
+ return ISC_R_UNEXPECTED;
+ }
+ if (bytes_written == 0)
+ return ISC_R_SUCCESS;
+
+ buffer -> head += bytes_written;
+ if (buffer -> head == sizeof buffer -> buf)
+ buffer -> head = 0;
+ c -> out_bytes -= bytes_written;
+
+ /* If we didn't finish out the write, we filled the
+ O.S. output buffer and a further write would block,
+ so stop trying to flush now. */
+ if (bytes_written != bytes_this_write)
+ return ISC_R_SUCCESS;
+ }
+
+ if (buffer -> head == buffer -> tail)
+ buffer = buffer -> next;
+ }
+
+ /* Get rid of any output buffers we emptied. */
+ buffer = (omapi_buffer_t *)0;
+ while (c -> outbufs &&
+ c -> outbufs -> head == c -> outbufs -> tail) {
+ if (c -> outbufs -> next) {
+ omapi_buffer_reference
+ (&buffer, c -> outbufs -> next,
+ "omapi_private_flush");
+ omapi_buffer_dereference
+ (&c -> outbufs -> next, "omapi_private_flush");
+ }
+ omapi_buffer_dereference (&c -> outbufs,
+ "omapi_private_flush");
+ if (buffer) {
+ omapi_buffer_reference (&c -> outbufs, buffer,
+ "omapi_private_flush");
+ omapi_buffer_dereference (&buffer,
+ "omapi_private_flush");
+ }
+ }
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t omapi_connection_get_uint32 (omapi_object_t *c,
+ u_int32_t *result)
+{
+ u_int32_t inbuf;
+ isc_result_t status;
+
+ status = omapi_connection_copyout ((unsigned char *)&inbuf,
+ c, sizeof inbuf);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ *result = ntohl (inbuf);
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t omapi_connection_put_uint32 (omapi_object_t *c,
+ u_int32_t value)
+{
+ u_int32_t inbuf;
+ isc_result_t status;
+
+ inbuf = htonl (value);
+
+ return omapi_connection_copyin (c, (unsigned char *)&inbuf,
+ sizeof inbuf);
+}
+
+isc_result_t omapi_connection_get_uint16 (omapi_object_t *c,
+ u_int16_t *result)
+{
+ u_int16_t inbuf;
+ isc_result_t status;
+
+ status = omapi_connection_copyout ((unsigned char *)&inbuf,
+ c, sizeof inbuf);
+ if (status != ISC_R_SUCCESS)
+ return status;
+
+ *result = ntohs (inbuf);
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t omapi_connection_put_uint16 (omapi_object_t *c,
+ u_int16_t value)
+{
+ u_int16_t inbuf;
+ isc_result_t status;
+
+ inbuf = htons (value);
+
+ return omapi_connection_copyin (c, (unsigned char *)&inbuf,
+ sizeof inbuf);
+}
+