Add simple buffer management code.
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 14 May 2011 17:15:04 +0000 (19:15 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 14 May 2011 17:15:04 +0000 (19:15 +0200)
Libevent 2.0's buffer code is not completely backward compatible with 1.4's.
In order to not (mis)use it anymore, we implement it ourselves. The buffers
are automatically expanding when necessary. When consuming data from the
buffer, no memmove()s are performed. Only when adding to the buffer would
write past the end do we shift everything back to the start.

src/Makefile.am
src/buffer.c [new file with mode: 0644]
src/buffer.h [new file with mode: 0644]

index 3f5f84ff8e92f763199b68d75d433b9a5a39c98b..5c2ab85d2767a1811dd3c139f50ec82118244572 100644 (file)
@@ -6,7 +6,7 @@ EXTRA_DIST = linux bsd solaris cygwin mingw raw_socket uml_socket openssl gcrypt
 
 tincd_SOURCES = \
        xmalloc.c utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c \
-       cipher.c conf.c connection.c control.c crypto.c digest.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
+       buffer.c cipher.c conf.c connection.c control.c crypto.c digest.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
        net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
        protocol_key.c protocol_subnet.c route.c rsa.c subnet.c tincd.c
 
@@ -26,7 +26,7 @@ INCLUDES = @INCLUDES@ -I$(top_builddir)
 
 noinst_HEADERS = \
        xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \
-       cipher.h conf.h connection.h control.h control_common.h crypto.h device.h digest.h edge.h graph.h logger.h meta.h net.h netutl.h node.h process.h \
+       buffer.h cipher.h conf.h connection.h control.h control_common.h crypto.h device.h digest.h edge.h graph.h logger.h meta.h net.h netutl.h node.h process.h \
        protocol.h route.h rsa.h rsagen.h subnet.h bsd/tunemu.h
 
 LIBS = @LIBS@ @LIBGCRYPT_LIBS@
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644 (file)
index 0000000..fc4fac0
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+    buffer.c -- buffer management
+    Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>,
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "system.h"
+
+#include "buffer.h"
+#include "xalloc.h"
+
+// Make sure we can add size bytes to the buffer, and return a pointer to the start of those bytes.
+
+char *buffer_prepare(buffer_t *buffer, int size) {
+       if(!buffer->data) {
+               buffer->maxlen = size;
+               buffer->data = xmalloc(size);
+       } else {
+               if(buffer->offset && buffer->len + size > buffer->maxlen) {
+                       memmove(buffer->data, buffer->data + buffer->offset, buffer->len - buffer->offset);
+                       buffer->len -= buffer->offset;
+                       buffer->offset = 0;
+               }
+
+               if(buffer->len + size > buffer->maxlen) {
+                       buffer->maxlen = buffer->len + size;
+                       buffer->data = xrealloc(buffer->data, buffer->maxlen);
+               }
+       }
+
+       buffer->len += size;
+       return buffer->data + buffer->offset;
+}
+
+// Copy data into the buffer.
+                       
+char *buffer_add(buffer_t *buffer, const char *data, int size) {
+       memcpy(buffer_prepare(buffer, size), data, size);
+}
+
+// Remove given number of bytes from the buffer, return a pointer to the start of them.
+
+static char *buffer_consume(buffer_t *buffer, int size) {
+       char *start = buffer->data + buffer->offset;
+
+       buffer->offset += size;
+
+       if(buffer->offset >= buffer->len) {
+               buffer->offset = 0;
+               buffer->len = 0;
+       } else {
+               buffer->offset += size;
+       }
+
+       return start;
+}
+
+// Check if there is a complete line in the buffer, and if so, return it NULL-terminated.
+
+char *buffer_readline(buffer_t *buffer) {
+       char *newline = memchr(buffer->data + buffer->offset, '\n', buffer->len - buffer->offset);
+
+       if(!newline)
+               return NULL;
+
+       int len = newline + 1 - buffer->data + buffer->offset;
+       *newline = 0;
+       return buffer_consume(buffer, len);
+}
+
+// Check if we have enough bytes in the buffer, and if so, return a pointer to the start of them.
+
+char *buffer_read(buffer_t *buffer, int size) {
+       if(buffer->len - buffer->offset < size)
+               return NULL;
+
+       return buffer_consume(buffer, size);
+}
+
+void buffer_clear(buffer_t *buffer) {
+       free(buffer->data);
+       buffer->data = 0;
+       buffer->maxlen = 0;
+       buffer->len = 0;
+       buffer->offset = 0;
+}
diff --git a/src/buffer.h b/src/buffer.h
new file mode 100644 (file)
index 0000000..4d6f672
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __TINC_BUFFER_H__
+#define __TINC_BUFFER_H__
+
+typedef struct buffer_t {
+       char *data;
+       int maxlen;
+       int len;
+       int offset;
+} buffer_t;
+
+extern char *buffer_prepare(buffer_t *buffer, int size);
+extern char *buffer_add(buffer_t *buffer, const char *data, int size);
+extern char *buffer_readline(buffer_t *buffer);
+extern char *buffer_read(buffer_t *buffer, int size);
+extern void buffer_clear(buffer_t *buffer);
+
+#endif