diff options
author | Laurent Ghigonis <laurent@p1sec.com> | 2013-08-26 13:13:51 +0200 |
---|---|---|
committer | Laurent Ghigonis <laurent@p1sec.com> | 2013-08-26 13:13:51 +0200 |
commit | 379a407d2318b84c620490d0c820700a5841f94d (patch) | |
tree | 9e178df3e3336a87032e0422802b0f06ed67d4cb /v3/libsendbuf | |
parent | WIP, permissions (diff) | |
download | glouglou-379a407d2318b84c620490d0c820700a5841f94d.tar.xz glouglou-379a407d2318b84c620490d0c820700a5841f94d.zip |
WIP
Diffstat (limited to 'v3/libsendbuf')
-rw-r--r-- | v3/libsendbuf/Makefile | 32 | ||||
-rw-r--r-- | v3/libsendbuf/libsendbuf.c | 142 | ||||
-rw-r--r-- | v3/libsendbuf/libsendbuf.h | 24 |
3 files changed, 198 insertions, 0 deletions
diff --git a/v3/libsendbuf/Makefile b/v3/libsendbuf/Makefile new file mode 100644 index 0000000..1f4849a --- /dev/null +++ b/v3/libsendbuf/Makefile @@ -0,0 +1,32 @@ +#CFLAGS += -Wall -O2 -fPIC -shared -g +CFLAGS += -Wall -O0 -fPIC -shared -g + +PREFIX=/usr/local +INCLUDEDIR=$(PREFIX)/include +LIBDIR=$(PREFIX)/lib +LIBNAME=libsendbuf + +TARGET = ${LIBNAME}.so +SOURCES = libsendbuf.c +HEADERS = libsendbuf.h +OBJECTS = $(SOURCES:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) + +install: + @echo "installation of $(LIBNAME)" + mkdir -p $(LIBDIR) + mkdir -p $(INCLUDEDIR) + install -m 0644 $(TARGET) $(LIBDIR) + install -m 0644 $(HEADERS) $(INCLUDEDIR) + +tests: + $(MAKE) -C tests run + +clean: + rm -f $(TARGET) $(OBJECTS) + +.PHONY: tests diff --git a/v3/libsendbuf/libsendbuf.c b/v3/libsendbuf/libsendbuf.c new file mode 100644 index 0000000..12dc95b --- /dev/null +++ b/v3/libsendbuf/libsendbuf.c @@ -0,0 +1,142 @@ +#include <stdlib.h> +#include <string.h> + +#include "libsendbuf.h" + +static void cb_timer(evutil_socket_t, short, void *); + +/* + * Public + */ + +/* + * Create a sendbuf + */ +struct sendbuf * +sendbuf_new(struct event_base *ev_base, int buffer_size, int msec_max, + int (*send_func)(void *, int, void *), void *usrdata) +{ + struct sendbuf *sbuf = NULL; + struct event *ev_timer; + + sbuf = calloc(1, sizeof(struct sendbuf)); + if (!sbuf) + return NULL; + sbuf->ev_base = ev_base; + sbuf->msec_max = msec_max; + sbuf->buffer_size = buffer_size; + sbuf->send_func = send_func; + sbuf->usrdata = usrdata; + sbuf->buffer = malloc(sbuf->buffer_size); + if (!sbuf->buffer) + goto err; + + ev_timer = evtimer_new(ev_base, cb_timer, sbuf); + sbuf->ev_timer = ev_timer; + sbuf->ev_timer_tv.tv_usec = msec_max * 1000; + evtimer_add(ev_timer, &sbuf->ev_timer_tv); + + return sbuf; + +err: + sendbuf_free(sbuf); + return NULL; +} + +void +sendbuf_free(struct sendbuf *sbuf) +{ + if (sbuf->ev_timer) + event_del(sbuf->ev_timer); + if (sbuf->buffer && sbuf->send_func) + sendbuf_flush(sbuf); + if (sbuf->buffer) + free(sbuf->buffer); + free(sbuf); +} + +/* + * Append to the token buffer data to be sent + * uses a memcpy, in contrary to sendbuf_gettoken(). + * return size on success, -1 on error + */ +int +sendbuf_append(struct sendbuf *sbuf, void *token, int size) +{ + if (sbuf->buffer_pos + size >= sbuf->buffer_size) + if (sendbuf_flush(sbuf) == -1) + return -1; + + memcpy(sbuf->buffer + sbuf->buffer_pos, token, size); + sbuf->buffer_pos = sbuf->buffer_pos + size; + + return size; +} + +/* + * Returns a token buffer to write data to be sent + * avoids memcpy, in contrary to sendbuf_append(). + * might return NULL if the sendbuf is temporary full + */ +void * +sendbuf_gettoken(struct sendbuf *sbuf, int size) +{ + void *token; + + if (sbuf->buffer_pos + size >= sbuf->buffer_size) + if (sendbuf_flush(sbuf) == -1) + return NULL; + + token = sbuf->buffer + sbuf->buffer_pos; + sbuf->buffer_pos = sbuf->buffer_pos + size; + + return token; +} + +/* + * Send buffer immediatly + * Note that you can still add data to the buffer even if flushing is in + * progress + * returns 0 on success or -1 on error + */ +int +sendbuf_flush(struct sendbuf *sbuf) +{ + int tosend, sent; + + if (sbuf->buffer_pos == 0) + return 0; + + sbuf->flushing = 1; + + tosend = sbuf->buffer_pos - sbuf->flushing_pos; + sent = sbuf->send_func(sbuf->buffer + sbuf->flushing_pos, + tosend, sbuf->usrdata); + if (sent == -1) { + // XXX handle error + return -1; + } else if (sent < tosend) { + sbuf->flushing_pos = sbuf->flushing_pos + sent; + return -1; + } + sbuf->buffer_pos = 0; + + sbuf->flushing = 0; + sbuf->flushing_pos = 0; + return 0; +} + + +/* + * Private + */ + +static void +cb_timer(evutil_socket_t fd, short what, void *arg) +{ + struct sendbuf *sbuf; + + sbuf = arg; + sendbuf_flush(sbuf); + evtimer_add(sbuf->ev_timer, &sbuf->ev_timer_tv); +} diff --git a/v3/libsendbuf/libsendbuf.h b/v3/libsendbuf/libsendbuf.h new file mode 100644 index 0000000..f0a7689 --- /dev/null +++ b/v3/libsendbuf/libsendbuf.h @@ -0,0 +1,24 @@ +#include <event.h> +#include <sys/queue.h> + +struct sendbuf { + struct event_base *ev_base; + struct event *ev_timer; + struct timeval ev_timer_tv; + int msec_max; + int buffer_size; + void *buffer; + int buffer_pos; /* next to use in buffer */ + int flushing; + int flushing_pos; /* next to send in buffer */ + int (*send_func)(void *, int, void *); + void *usrdata; +}; + +struct sendbuf *sendbuf_new(struct event_base *, int, int, + int (*send_func)(void *, int, void *), + void *); +void sendbuf_free(struct sendbuf *); +int sendbuf_append(struct sendbuf *, void *, int); +void *sendbuf_gettoken(struct sendbuf *, int); +int sendbuf_flush(struct sendbuf *); |