aboutsummaryrefslogtreecommitdiffstats
path: root/v3/libsendbuf
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2013-08-26 13:13:51 +0200
committerLaurent Ghigonis <laurent@p1sec.com>2013-08-26 13:13:51 +0200
commit379a407d2318b84c620490d0c820700a5841f94d (patch)
tree9e178df3e3336a87032e0422802b0f06ed67d4cb /v3/libsendbuf
parentWIP, permissions (diff)
downloadglouglou-379a407d2318b84c620490d0c820700a5841f94d.tar.xz
glouglou-379a407d2318b84c620490d0c820700a5841f94d.zip
WIP
Diffstat (limited to 'v3/libsendbuf')
-rw-r--r--v3/libsendbuf/Makefile32
-rw-r--r--v3/libsendbuf/libsendbuf.c142
-rw-r--r--v3/libsendbuf/libsendbuf.h24
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 *);