diff options
Diffstat (limited to 'src/libmowgli/linebuf')
-rw-r--r-- | src/libmowgli/linebuf/linebuf.c | 175 | ||||
-rw-r--r-- | src/libmowgli/linebuf/linebuf.h | 37 |
2 files changed, 159 insertions, 53 deletions
diff --git a/src/libmowgli/linebuf/linebuf.c b/src/libmowgli/linebuf/linebuf.c index 8b13040..0395680 100644 --- a/src/libmowgli/linebuf/linebuf.c +++ b/src/libmowgli/linebuf/linebuf.c @@ -28,9 +28,18 @@ static mowgli_heap_t *linebuf_heap = NULL; static void mowgli_linebuf_read_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata); static void mowgli_linebuf_write_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata); static void mowgli_linebuf_process(mowgli_linebuf_t *linebuf); +static void mowgli_linebuf_do_shutdown(mowgli_linebuf_t *linebuf); static int mowgli_linebuf_error(mowgli_vio_t *vio); +#ifdef NOTYET +static mowgli_vio_evops_t linebuf_evops = +{ + .read_cb = mowgli_linebuf_read_data, + .write_cb = mowgli_linebuf_write_data +}; +#endif + mowgli_linebuf_t * mowgli_linebuf_create(mowgli_linebuf_readline_cb_t *cb, void *userdata) { @@ -41,7 +50,8 @@ mowgli_linebuf_create(mowgli_linebuf_readline_cb_t *cb, void *userdata) linebuf = mowgli_heap_alloc(linebuf_heap); - linebuf->delim = "\r\n"; /* Sane default */ + /* Sane default */ + mowgli_linebuf_delim(linebuf, "\r\n", "\r\n"); linebuf->readline_cb = cb; linebuf->flags = 0; @@ -51,7 +61,9 @@ mowgli_linebuf_create(mowgli_linebuf_readline_cb_t *cb, void *userdata) mowgli_linebuf_setbuflen(&(linebuf->readbuf), 65536); mowgli_linebuf_setbuflen(&(linebuf->writebuf), 65536); - linebuf->return_normal_strings = true; /* This is generally what you want, but beware of malicious \0's in input data! */ + linebuf->eventloop = NULL; + + linebuf->return_normal_strings = true; /* This is generally what you want, but beware of malicious \0's in input data! */ linebuf->userdata = userdata; @@ -61,22 +73,43 @@ mowgli_linebuf_create(mowgli_linebuf_readline_cb_t *cb, void *userdata) } /* Attach the linebuf instance to the eventloop -- socket must be created first with VIO instance! */ -void mowgli_linebuf_attach_to_eventloop(mowgli_linebuf_t *linebuf, mowgli_eventloop_t *eventloop) +void +mowgli_linebuf_attach_to_eventloop(mowgli_linebuf_t *linebuf, mowgli_eventloop_t *eventloop) { return_if_fail(eventloop != NULL); return_if_fail(linebuf != NULL); return_if_fail(linebuf->vio != NULL); return_if_fail((linebuf->vio->flags & MOWGLI_VIO_FLAGS_ISCLOSED) == 0); - mowgli_vio_eventloop_attach(linebuf->vio, eventloop); - mowgli_pollable_setselect(eventloop, linebuf->vio->io, MOWGLI_EVENTLOOP_IO_READ, mowgli_linebuf_read_data); - mowgli_pollable_setselect(eventloop, linebuf->vio->io, MOWGLI_EVENTLOOP_IO_WRITE, mowgli_linebuf_write_data); +#ifdef NOTYET + mowgli_vio_eventloop_attach(linebuf->vio, eventloop, &linebuf_evops); +#else + mowgli_vio_eventloop_attach(linebuf->vio, eventloop, NULL); +#endif + mowgli_pollable_setselect(eventloop, linebuf->vio->io.e, MOWGLI_EVENTLOOP_IO_READ, mowgli_linebuf_read_data); + mowgli_pollable_setselect(eventloop, linebuf->vio->io.e, MOWGLI_EVENTLOOP_IO_WRITE, mowgli_linebuf_write_data); linebuf->eventloop = eventloop; } -void mowgli_linebuf_destroy(mowgli_linebuf_t *linebuf) +/* Detach the linebuf instance from the eventloop */ +void +mowgli_linebuf_detach_from_eventloop(mowgli_linebuf_t *linebuf) +{ + return_if_fail(linebuf != NULL); + return_if_fail(linebuf->eventloop != NULL); + mowgli_pollable_setselect(linebuf->eventloop, linebuf->vio->io.e, MOWGLI_EVENTLOOP_IO_READ, NULL); + mowgli_pollable_setselect(linebuf->eventloop, linebuf->vio->io.e, MOWGLI_EVENTLOOP_IO_WRITE, NULL); + mowgli_vio_eventloop_detach(linebuf->vio); + linebuf->eventloop = NULL; +} + +void +mowgli_linebuf_destroy(mowgli_linebuf_t *linebuf) { + if (linebuf->eventloop != NULL) + mowgli_linebuf_detach_from_eventloop(linebuf); + mowgli_vio_destroy(linebuf->vio); mowgli_free(linebuf->readbuf.buffer); @@ -84,18 +117,21 @@ void mowgli_linebuf_destroy(mowgli_linebuf_t *linebuf) mowgli_heap_free(linebuf_heap, linebuf); } -void mowgli_linebuf_setbuflen(mowgli_linebuf_buf_t *buffer, size_t buflen) +void +mowgli_linebuf_setbuflen(mowgli_linebuf_buf_t *buffer, size_t buflen) { return_if_fail(buffer != NULL); if (buffer->buffer == NULL) + { buffer->buffer = mowgli_alloc(buflen); + } else { char tmpbuf[buffer->maxbuflen]; if (buffer->buflen > 0) - memcpy(tmpbuf, buffer->buffer, buffer->maxbuflen); /* Copy into tmp buffer */ + memcpy(tmpbuf, buffer->buffer, buffer->maxbuflen); /* Copy into tmp buffer */ /* Free old buffer and reallocate */ mowgli_free(buffer->buffer); @@ -109,9 +145,22 @@ void mowgli_linebuf_setbuflen(mowgli_linebuf_buf_t *buffer, size_t buflen) buffer->maxbuflen = buflen; } -static void mowgli_linebuf_read_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata) +void +mowgli_linebuf_delim(mowgli_linebuf_t *linebuf, const char *delim, const char *endl) { - mowgli_linebuf_t *linebuf = (mowgli_linebuf_t *)userdata; + return_if_fail(linebuf != NULL); + return_if_fail(delim != NULL && *delim != '\0'); + return_if_fail(endl != NULL && *endl != '\0'); + + linebuf->delim = delim; + linebuf->endl = endl; + linebuf->endl_len = strlen(endl); +} + +static void +mowgli_linebuf_read_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata) +{ + mowgli_linebuf_t *linebuf = (mowgli_linebuf_t *) userdata; mowgli_linebuf_buf_t *buffer = &(linebuf->readbuf); void *bufpos; size_t offset; @@ -129,9 +178,12 @@ static void mowgli_linebuf_read_data(mowgli_eventloop_t *eventloop, mowgli_event if ((ret = mowgli_vio_read(linebuf->vio, bufpos, offset)) <= 0) { - if (linebuf->vio->error.code != MOWGLI_VIO_ERR_NONE) - /* Let's never come back here */ - mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_READ, NULL); + if (linebuf->vio->error.type == MOWGLI_VIO_ERR_NONE) + return; + + /* Let's never come back here */ + mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_READ, NULL); + mowgli_linebuf_do_shutdown(linebuf); return; } @@ -147,29 +199,43 @@ static void mowgli_linebuf_read_data(mowgli_eventloop_t *eventloop, mowgli_event mowgli_linebuf_process(linebuf); } -static void mowgli_linebuf_write_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata) +static void +mowgli_linebuf_write_data(mowgli_eventloop_t *eventloop, mowgli_eventloop_io_t *io, mowgli_eventloop_io_dir_t dir, void *userdata) { - mowgli_linebuf_t *linebuf = (mowgli_linebuf_t *)userdata; + mowgli_linebuf_t *linebuf = (mowgli_linebuf_t *) userdata; mowgli_linebuf_buf_t *buffer = &(linebuf->writebuf); int ret; if ((ret = mowgli_vio_write(linebuf->vio, buffer->buffer, buffer->buflen)) <= 0) - { if (linebuf->vio->error.code != MOWGLI_VIO_ERR_NONE) - /* If we have a genuine error, we shouldn't come back to this func + /* If we have a genuine error, we shouldn't come back to this func * Otherwise we'll try again. */ - mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_WRITE, NULL); - return; - } + if (ret != 0) + { + mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_WRITE, NULL); + mowgli_log("mowgli_vio_write returned error [%ld]: %s", linebuf->vio->error.code, linebuf->vio->error.string); + return; + } buffer->buflen -= ret; /* Anything else to write? */ if (buffer->buflen == 0) - mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_WRITE, NULL); + { + if (!mowgli_vio_hasflag(linebuf->vio, MOWGLI_VIO_FLAGS_NEEDWRITE)) + mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_WRITE, NULL); + + if ((linebuf->flags & MOWGLI_LINEBUF_SHUTTING_DOWN) != 0) + mowgli_linebuf_do_shutdown(linebuf); + } + else + { + mowgli_pollable_setselect(eventloop, io, MOWGLI_EVENTLOOP_IO_WRITE, mowgli_linebuf_write_data); + } } -void mowgli_linebuf_writef(mowgli_linebuf_t *linebuf, const char *format, ...) +void +mowgli_linebuf_writef(mowgli_linebuf_t *linebuf, const char *format, ...) { char buf[linebuf->writebuf.maxbuflen]; size_t len; @@ -182,34 +248,48 @@ void mowgli_linebuf_writef(mowgli_linebuf_t *linebuf, const char *format, ...) mowgli_linebuf_write(linebuf, buf, len); } -void mowgli_linebuf_write(mowgli_linebuf_t *linebuf, const char *data, int len) +void +mowgli_linebuf_write(mowgli_linebuf_t *linebuf, const char *data, int len) { char *ptr = linebuf->writebuf.buffer + linebuf->writebuf.buflen; - int delim_len = strlen(linebuf->delim); return_if_fail(len > 0); return_if_fail(data != NULL); - if (linebuf->writebuf.buflen + len + delim_len > linebuf->writebuf.maxbuflen) + if (linebuf->flags & MOWGLI_LINEBUF_SHUTTING_DOWN) + return; + + if (linebuf->writebuf.buflen + len + linebuf->endl_len > linebuf->writebuf.maxbuflen) { linebuf->flags |= MOWGLI_LINEBUF_ERR_WRITEBUF_FULL; mowgli_linebuf_error(linebuf->vio); return; } - memcpy((void *)ptr, data, len); - memcpy((void *)(ptr + len), linebuf->delim, delim_len); + memcpy((void *) ptr, data, len); + memcpy((void *) (ptr + len), linebuf->endl, linebuf->endl_len); - linebuf->writebuf.buflen += len + delim_len; + linebuf->writebuf.buflen += len + linebuf->endl_len; /* Schedule our write */ - mowgli_pollable_setselect(linebuf->eventloop, linebuf->vio->io, MOWGLI_EVENTLOOP_IO_WRITE, mowgli_linebuf_write_data); + mowgli_pollable_setselect(linebuf->eventloop, linebuf->vio->io.e, MOWGLI_EVENTLOOP_IO_WRITE, mowgli_linebuf_write_data); +} + +void +mowgli_linebuf_shut_down(mowgli_linebuf_t *linebuf) +{ + return_if_fail(linebuf != NULL); + + linebuf->flags |= MOWGLI_LINEBUF_SHUTTING_DOWN; + + if (linebuf->writebuf.buflen == 0) + mowgli_linebuf_do_shutdown(linebuf); } -static void mowgli_linebuf_process(mowgli_linebuf_t *linebuf) +static void +mowgli_linebuf_process(mowgli_linebuf_t *linebuf) { mowgli_linebuf_buf_t *buffer = &(linebuf->readbuf); - size_t delim_len = strlen(linebuf->delim); char *line_start; char *cptr; @@ -223,11 +303,12 @@ static void mowgli_linebuf_process(mowgli_linebuf_t *linebuf) while (len < buffer->buflen) { - if (memcmp((void *)cptr, linebuf->delim, delim_len) != 0) + if (!strchr(linebuf->delim, *cptr)) { if (*cptr == '\0') /* Warn about unexpected null chars in the string */ linebuf->flags |= MOWGLI_LINEBUF_LINE_HASNULLCHAR; + cptr++; len++; continue; @@ -239,20 +320,25 @@ static void mowgli_linebuf_process(mowgli_linebuf_t *linebuf) if (linebuf->return_normal_strings) *cptr = '\0'; - linebuf->readline_cb(linebuf, line_start, cptr - line_start, linebuf->userdata); + if ((linebuf->flags & MOWGLI_LINEBUF_SHUTTING_DOWN) == 0) + linebuf->readline_cb(linebuf, line_start, cptr - line_start, linebuf->userdata); /* Next line starts here; begin scanning and set the start of it */ - len += delim_len; - cptr += delim_len; + while (strchr(linebuf->delim, *cptr)) + { + len++; + cptr++; + } + line_start = cptr; /* Reset this for next line */ linebuf->flags &= ~MOWGLI_LINEBUF_LINE_HASNULLCHAR; } - if (linecount == 0 && (buffer->buflen == buffer->maxbuflen)) + if ((linecount == 0) && (buffer->buflen == buffer->maxbuflen)) { - /* No more chars will fit in the buffer and we don't have a line + /* No more chars will fit in the buffer and we don't have a line * We're really screwed, let's trigger an error. */ linebuf->flags |= MOWGLI_LINEBUF_ERR_READBUF_FULL; mowgli_linebuf_error(linebuf->vio); @@ -265,10 +351,20 @@ static void mowgli_linebuf_process(mowgli_linebuf_t *linebuf) memmove(buffer->buffer, line_start, cptr - line_start); } else + { buffer->buflen = 0; + } +} + +static void +mowgli_linebuf_do_shutdown(mowgli_linebuf_t *linebuf) +{ + if (linebuf && linebuf->shutdown_cb) + linebuf->shutdown_cb(linebuf, linebuf->userdata); } -static int mowgli_linebuf_error(mowgli_vio_t *vio) +static int +mowgli_linebuf_error(mowgli_vio_t *vio) { mowgli_linebuf_t *linebuf = vio->userdata; mowgli_vio_error_t *error = &(linebuf->vio->error); @@ -289,4 +385,3 @@ static int mowgli_linebuf_error(mowgli_vio_t *vio) /* Pass this up to higher callback */ return mowgli_vio_error(vio); } - diff --git a/src/libmowgli/linebuf/linebuf.h b/src/libmowgli/linebuf/linebuf.h index 17c45ea..e05629b 100644 --- a/src/libmowgli/linebuf/linebuf.h +++ b/src/libmowgli/linebuf/linebuf.h @@ -21,41 +21,52 @@ #ifndef __MOWGLI_LINEBUF_LINEBUF_H__ #define __MOWGLI_LINEBUF_LINEBUF_H__ -#include "eventloop/eventloop.h" -#include "vio/vio.h" - typedef struct _mowgli_linebuf_buf mowgli_linebuf_buf_t; -typedef void mowgli_linebuf_readline_cb_t(mowgli_linebuf_t *, char *, size_t, void *); +typedef void mowgli_linebuf_readline_cb_t (mowgli_linebuf_t *, char *, size_t, void *); +typedef void mowgli_linebuf_shutdown_cb_t (mowgli_linebuf_t *, void *); + +extern mowgli_linebuf_t *mowgli_linebuf_create(mowgli_linebuf_readline_cb_t *cb, void *userdata); -extern mowgli_linebuf_t * mowgli_linebuf_create(mowgli_linebuf_readline_cb_t *cb, void *userdata); +/* XXX these are unfortunately named and will change */ extern void mowgli_linebuf_attach_to_eventloop(mowgli_linebuf_t *linebuf, mowgli_eventloop_t *eventloop); +extern void mowgli_linebuf_detach_from_eventloop(mowgli_linebuf_t *linebuf); extern void mowgli_linebuf_destroy(mowgli_linebuf_t *linebuf); extern void mowgli_linebuf_setbuflen(mowgli_linebuf_buf_t *buffer, size_t buflen); +extern void mowgli_linebuf_delim(mowgli_linebuf_t *linebuf, const char *delim, const char *endl); extern void mowgli_linebuf_write(mowgli_linebuf_t *linebuf, const char *data, int len); extern void mowgli_linebuf_writef(mowgli_linebuf_t *linebuf, const char *format, ...); +extern void mowgli_linebuf_shut_down(mowgli_linebuf_t *linebuf); -struct _mowgli_linebuf_buf { +struct _mowgli_linebuf_buf +{ char *buffer; size_t buflen; size_t maxbuflen; }; /* Errors */ -#define MOWGLI_LINEBUF_ERR_NONE 0x0000 -#define MOWGLI_LINEBUF_ERR_READBUF_FULL 0x0001 -#define MOWGLI_LINEBUF_ERR_WRITEBUF_FULL 0x0002 +#define MOWGLI_LINEBUF_ERR_NONE 0x0000 +#define MOWGLI_LINEBUF_ERR_READBUF_FULL 0x0001 +#define MOWGLI_LINEBUF_ERR_WRITEBUF_FULL 0x0002 /* Informative */ -#define MOWGLI_LINEBUF_LINE_HASNULLCHAR 0x0004 +#define MOWGLI_LINEBUF_LINE_HASNULLCHAR 0x0004 -struct _mowgli_linebuf { +/* State */ +#define MOWGLI_LINEBUF_SHUTTING_DOWN 0x0100 + +struct _mowgli_linebuf +{ mowgli_linebuf_readline_cb_t *readline_cb; + mowgli_linebuf_shutdown_cb_t *shutdown_cb; mowgli_vio_t *vio; const char *delim; + const char *endl; + size_t endl_len; int flags; @@ -69,11 +80,11 @@ struct _mowgli_linebuf { void *userdata; }; -static inline mowgli_vio_t * mowgli_linebuf_get_vio(mowgli_linebuf_t *linebuf) +static inline mowgli_vio_t * +mowgli_linebuf_get_vio(mowgli_linebuf_t *linebuf) { return_val_if_fail(linebuf != NULL, NULL); return linebuf->vio; } #endif - |