summaryrefslogtreecommitdiffstats
path: root/src/buffio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffio.c')
-rw-r--r--src/buffio.c100
1 files changed, 74 insertions, 26 deletions
diff --git a/src/buffio.c b/src/buffio.c
index 1e13b4d..2c3a7fb 100644
--- a/src/buffio.c
+++ b/src/buffio.c
@@ -15,13 +15,16 @@ struct buffio buffio_new(int fd) {
memset(b, 0, sizeof(struct buffio));
b->fd = fd;
- b->input_buf = malloc(BUFSIZE);
+
+ b->input_buf = malloc(b->input_max_length = BUFSIZE);
assert(b->input_buf);
- b->input_buf_len = 0;
-
- b->output_buf = malloc(BUFSIZE);
+ b->input_buf_len = b->input_index = 0;
+ b->input_watermark = 2; /* Read some more data if 2 or less bytes are in the input buffer */
+
+ b->output_buf = malloc(b->output_max_length = BUFSIZE);
assert(b->output_buf);
- b->output_buf_len = 0;
+ b->output_length = b->output_index = 0;
+ b->output_watermark = 1; /* Write some data if 1 or more bytes are in the output buffer */
buffio_set_callbacks(b);
@@ -56,15 +59,15 @@ static void* buffio_read_cb(oop_source *source, int fd, oop_event event, void *u
struct buffio *b = user;
assert(source && b && b->fd == fd && event == OOP_READ);
- if (b->input_length < BUFSIZE) {
+ if (b->input_length < b->input_max_length) {
ssize_t s;
size_t m, l;
- i = (b->input_index + b->input_length) % BUFSIZE;
+ i = (b->input_index + b->input_length) % b->input_max_length;
- m = BUFSIZE-b->input_length;
- if (m > BUFSIZE-i)
- m = BUFSIZE-i;
+ m = b->input_max_length-b->input_length;
+ if (m > b->input_max_length-i)
+ m = b->input_max_length-i;
if ((s = read(fd, b->input_buf+i, m)) < 0) {
daemon_log(LOG_ERR, "Failed to read from file descriptor: %s", strerror(errno));
@@ -82,7 +85,12 @@ static void* buffio_read_cb(oop_source *source, int fd, oop_event event, void *u
b->input_length += s;
}
- buffio_set_callbacks(b);
+ buffio_normalize(b);
+ buffio_set_input_callbacks(b);
+
+ if (b->input_length && b->input_ready_cb)
+ b->input_ready_cb(b, b->user);
+
return OOP_CONTINUE;
}
@@ -95,8 +103,8 @@ static void* buffio_write_cb(oop_source *source, int fd, oop_event event, void *
size_t m;
m = b->output_length;
- if (m > BUFSIZE-b->output_index)
- m = BUFSIZE-b->output_index;
+ if (m > b->output_max_length-b->output_index)
+ m = b->output_max_length-b->output_index;
if ((s = write(fd, b->output_buf+b->output_index, m)) < 0) {
daemon_log(LOG_ERR, "Failed to write to file descriptor: %s", strerror(errno));
@@ -111,19 +119,24 @@ static void* buffio_write_cb(oop_source *source, int fd, oop_event event, void *
}
assert(s <= m);
- b->output_index = (b->output_index + s) % BUFSIZE;
+ b->output_index = (b->output_index + s) % b->output_max_length;
b->ouput_length -= s;
}
+
+ buffio_normalize(b);
+ buffio_set_output_callbacks(b);
+
+ if (!b->output_length && b->output_empty_cb)
+ b->output_empty_cb(b, b->user);
- buffio_set_callbacks(b);
return OOP_CONTINUE;
}
-static void buffio_set_callbacks(struct buffio *b) {
+static void buffio_set_input_callbacks(struct buffio *b) {
assert(b && b->fd >= 0 && event_source);
- if (b->input_length < BUFSIZE) {
+ if (b->input_length <= b->input_watermark) {
if (!b->b_read_cb) { /* Enable the callback */
event_source->on_fd(event_source, b->fd, OOP_READ, buffio_read_cb, b);
b->b_read_cb = 1;
@@ -134,8 +147,12 @@ static void buffio_set_callbacks(struct buffio *b) {
b->read_cb = 0;
}
}
+}
- if (b->output_length > 0) {
+static void buffio_set_output_callbacks(struct buffio *b) {
+ assert(b && b->fd >= 0 && event_source);
+
+ if (b->output_length >= b->output_watermark) {
if (!b->b_write_cb) { /* Enable the callback */
event_source->on_fd(event_source, b->fd, OOP_WRITE, buffio_write_cb, b);
b->b_write_cb = 1;
@@ -146,24 +163,23 @@ static void buffio_set_callbacks(struct buffio *b) {
b->b_write_cb = 0;
}
}
-
}
int buffio_write(struct buffio *b, const uint8_t *d, size_t l) {
assert(b && s && l);
- if (l < BUFFSIZE - b->output_length) {
+ if (l < b->output_max_length - b->output_length) {
daemon_log(LOG_ERR, "buffio_write() with too much data called");
return -1;
}
while (l >= 0) {
- i = (b->ouput_index + b->ouput_length) % BUFSIZE;
+ i = (b->ouput_index + b->ouput_length) % b->ouput_max_length;
- m = BUFSIZE-b->output_length;
- if (m > BUFSIZE-i)
- m = BUFSIZE-i;
+ m = b->ouput_max_length-b->output_length;
+ if (m > b->output_max_length-i)
+ m = b->output_max_length-i;
memcpy(b->output_buf+i, d, m);
@@ -171,7 +187,8 @@ int buffio_write(struct buffio *b, const uint8_t *d, size_t l) {
b->output_length += m;
}
- buffio_set_callbacks(b);
+ buffio_set_output_callbacks(b);
+ buffio_normalize();
return 0;
}
@@ -195,8 +212,39 @@ void buffio_flush_input(struct buffio *b) {
buffio_set_callbacks(b);
}
+
+static void buffio_normalize(struct buffio *b) {
+ assert(b);
+
+ assert(b->input_index < b->input_max_length);
+ assert(b->input_length <= b->input_max_length);
+
+ if (!b->input_length) /* This will optimize throughput a bit */
+ b->input_index = 0;
+}
+
int buffio_find_input(struct buffio *b, const char *c) {
- assert(b && c);
+ size_t l, cl, j;
+ assert(b && c && *c);
+ cl = strlen(c);
+
+ for (i = b->input_index, l = b->input_length; l >= cl; i = (i+1) % b->input_max_length, l--) {
+ char *p;
+ size_t i;
+
+ for (j = i, p = c; *p && *p == b->input_buf[j]; p++, j = (j+1) % b->input_max_length);
+
+ if (!*p) { /* Found! */
+ b->input_index = j;
+ b->input_length = l-cl;
+
+ buffio_normalize(b);
+ return 1;
+ }
+ }
+
+ return 0;
}
+