summaryrefslogtreecommitdiff
path: root/src/libmowgli/linebuf
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmowgli/linebuf')
-rw-r--r--src/libmowgli/linebuf/linebuf.c175
-rw-r--r--src/libmowgli/linebuf/linebuf.h37
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
-