diff options
Diffstat (limited to 'libglouglou/sendbuf.c')
-rw-r--r-- | libglouglou/sendbuf.c | 95 |
1 files changed, 57 insertions, 38 deletions
diff --git a/libglouglou/sendbuf.c b/libglouglou/sendbuf.c index 078d6a6..7571cc4 100644 --- a/libglouglou/sendbuf.c +++ b/libglouglou/sendbuf.c @@ -1,32 +1,33 @@ +#include <stdlib.h> +#include <string.h> + #include "sendbuf.h" +static int flushbuf(struct sendbuf *); +static void cb_timer(evutil_socket_t, short, void *); + /* * Public */ /* * Create a sendbuf - * send_func should return the number of successfuly sent bytes */ struct sendbuf * -sendbuf_init(struct event_base *ev_base, int size, int sndbuf_max, int msec_max, - int (*send_func)(void *, int, void *), void *usrdata) +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; - struct timeval *tv; - void *buffer; - void *data; + struct event *ev_timer; sbuf = calloc(1, sizeof(struct sendbuf)); if (!sbuf) return NULL; sbuf->ev_base = ev_base; - sbuf->sndbuf_max = sndbuf_max; sbuf->msec_max = msec_max; - sbuf->usrdata = usrdata; + sbuf->buffer_size = buffer_size; sbuf->send_func = send_func; - sbuf->buffer_size = size; + sbuf->usrdata = usrdata; sbuf->buffer = malloc(sbuf->buffer_size); if (!sbuf->buffer) goto err; @@ -34,20 +35,20 @@ sendbuf_init(struct event_base *ev_base, int size, int sndbuf_max, int msec_max, 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, &sbuf->ev_timer_tv); + evtimer_add(ev_timer, &sbuf->ev_timer_tv); return sbuf; err: - sendbuf_shutdown(sbuf); + sendbuf_free(sbuf); return NULL; } void -sendbuf_shutdown(struct sendbuf *sbuf) +sendbuf_free(struct sendbuf *sbuf) { - if (sbuf->send_timer) - event_del(sbuf->send_timer); + if (sbuf->ev_timer) + event_del(sbuf->ev_timer); if (sbuf->buffer && sbuf->send_func) flushbuf(sbuf); if (sbuf->buffer) @@ -56,17 +57,41 @@ sendbuf_shutdown(struct sendbuf *sbuf) } /* - * Returns a buffer to write data to be sent + * 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 (flushbuf(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_getoken(struct sendbuf *sbuf, int size) +sendbuf_gettoken(struct sendbuf *sbuf, int size) { + void *token; + if (sbuf->buffer_pos + size >= sbuf->buffer_size) if (flushbuf(sbuf) == -1) return NULL; - return sbuf->buffer_pos; + token = sbuf->buffer + sbuf->buffer_pos; + sbuf->buffer_pos = sbuf->buffer_pos + size; + + return token; } /* @@ -77,36 +102,30 @@ sendbuf_getoken(struct sendbuf *sbuf, int size) * Note that you can still add data to the buffer even if flushing is in * progress */ -int +static int flushbuf(struct sendbuf *sbuf) { - int sent; - int sent_total; - int len; + int tosend, sent; sbuf->flushing = 1; - do { - pos = sbuf->buffer + sbuf->flushed_len; - if (sbuf->buffer_pos > sbuf->sndbuf_max) - tosend = sbuf->sndbuf_max; - else - tosend = sbuf->buffer_pos; - sent = sbuf->send_func(sbuf->buffer + pos, tosend, sbuf->usrdata); - sbuf->flushed_len = sbuf->flushed_len + sent; - if (sent == -1) { - // XXX handle erorr - } else if (sent < tosend) { - return -1; - } - } while (sbuf->flushed_len < sbuf->buffer_pos) + tosend = sbuf->buffer_size - 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->flushing = 0; - sbuf->flushed_len = 0; + sbuf->flushing_pos = 0; return 0; } -void +static void cb_timer(evutil_socket_t fd, short what, void *arg) { struct sendbuf *sbuf; |