From f431fcb35f400be388a905ae0f7f50c1f5c4cd5d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 14 May 2011 19:15:04 +0200 Subject: [PATCH] Add simple buffer management code. 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 | 4 +- src/buffer.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ src/buffer.h | 17 +++++++++ 3 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/buffer.c create mode 100644 src/buffer.h diff --git a/src/Makefile.am b/src/Makefile.am index 3f5f84ff..5c2ab85d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 00000000..fc4fac0f --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,99 @@ +/* + buffer.c -- buffer management + Copyright (C) 2011 Guus Sliepen , + + 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 index 00000000..4d6f6726 --- /dev/null +++ b/src/buffer.h @@ -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 -- 2.20.1