From 5eb3bc6d5594fccfff26329a26225f999e971652 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Mon, 16 Apr 2007 19:08:42 +0000 Subject: first step forward to merge conntrackd and conntrack into the same building chain --- src/buffer.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/buffer.c (limited to 'src/buffer.c') diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..fa0b859 --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,136 @@ +/* + * (C) 2006-2007 by Pablo Neira Ayuso + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "buffer.h" + +struct buffer *buffer_create(size_t max_size) +{ + struct buffer *b; + + b = malloc(sizeof(struct buffer)); + if (b == NULL) + return NULL; + memset(b, 0, sizeof(struct buffer)); + + b->max_size = max_size; + INIT_LIST_HEAD(&b->head); + pthread_mutex_init(&b->lock, NULL); + + return b; +} + +void buffer_destroy(struct buffer *b) +{ + struct list_head *i, *tmp; + struct buffer_node *node; + + pthread_mutex_lock(&b->lock); + list_for_each_safe(i, tmp, &b->head) { + node = (struct buffer_node *) i; + list_del(i); + free(node); + } + pthread_mutex_unlock(&b->lock); + pthread_mutex_destroy(&b->lock); + free(b); +} + +static struct buffer_node *buffer_node_create(const void *data, size_t size) +{ + struct buffer_node *n; + + n = malloc(sizeof(struct buffer_node) + size); + if (n == NULL) + return NULL; + + INIT_LIST_HEAD(&n->head); + n->size = size; + memcpy(n->data, data, size); + + return n; +} + +int buffer_add(struct buffer *b, const void *data, size_t size) +{ + int ret = 0; + struct buffer_node *n; + + pthread_mutex_lock(&b->lock); + + /* does it fit this buffer? */ + if (size > b->max_size) { + errno = ENOSPC; + ret = -1; + goto err; + } + +retry: + /* buffer is full: kill the oldest entry */ + if (b->cur_size + size > b->max_size) { + n = (struct buffer_node *) b->head.prev; + list_del(b->head.prev); + b->cur_size -= n->size; + free(n); + goto retry; + } + + n = buffer_node_create(data, size); + if (n == NULL) { + ret = -1; + goto err; + } + + list_add(&n->head, &b->head); + b->cur_size += size; + +err: + pthread_mutex_unlock(&b->lock); + return ret; +} + +void __buffer_del(struct buffer *b, void *data) +{ + struct buffer_node *n = container_of(data, struct buffer_node, data); + + list_del(&n->head); + b->cur_size -= n->size; + free(n); +} + +void buffer_del(struct buffer *b, void *data) +{ + pthread_mutex_lock(&b->lock); + buffer_del(b, data); + pthread_mutex_unlock(&b->lock); +} + +void buffer_iterate(struct buffer *b, + void *data, + int (*iterate)(void *data1, void *data2)) +{ + struct list_head *i, *tmp; + struct buffer_node *n; + + pthread_mutex_lock(&b->lock); + list_for_each_safe(i, tmp, &b->head) { + n = (struct buffer_node *) i; + if (iterate(n->data, data)) + break; + } + pthread_mutex_unlock(&b->lock); +} -- cgit v1.2.3