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.
This commit is contained in:
Guus Sliepen 2011-05-14 19:15:04 +02:00
parent 3794e551c7
commit f431fcb35f
3 changed files with 118 additions and 2 deletions

View 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@

99
src/buffer.c Normal file
View file

@ -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;
}

17
src/buffer.h Normal file
View file

@ -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