#include #include #include #include "al.h" #include "sio.h" #include typedef struct { BIO *bio; size_t inputsize; al_label_t data_label; al_label_t eof_label; char eof; } private_t; /* * create stage * * allocate private instance data */ static sio_rc_t siobio_init(sio_t *sio, void **u) { private_t *my; my = (private_t *)malloc(sizeof(private_t)); if (my == NULL) return SIO_ERR_MEM; my->bio = NULL; my->eof = '\0'; sio_label(sio, SIO_LN_DATA, &my->data_label); sio_label(sio, SIO_LN_EOF, &my->eof_label); *u = my; return SIO_OK; } /* * configure stage * * pass two void pointers */ static sio_rc_t siobio_configure(sio_t *sio, void *u, void *obj, void *val) { private_t *my = (private_t *)u; const char *name = (const char *)obj; if (!strcmp(name, "bio")) { my->bio = (BIO *)val; } else if (!strcmp(name, "inputsize")) { my->inputsize = *(int *)val; } else { return SIO_ERR_ARG; } return SIO_OK; } /* * destroy stage */ static sio_rc_t siobio_cleanup(sio_t *sio, void *u) { private_t *my = (private_t *)u; free(my); return SIO_OK; } static sio_rc_t siobio_openr(sio_t *sio, al_t *al, void *u) { return SIO_OK; } static sio_rc_t siobio_closer(sio_t *sio, al_t *al, void *u) { return SIO_OK; } static sio_rc_t siobio_openw(sio_t *sio, al_t *al, void *u) { return SIO_OK; } static sio_rc_t siobio_closew(sio_t *sio, al_t *al, void *u) { return SIO_OK; } static void freebiobuf(char *p, size_t n, void *u) { free(p); } static sio_rc_t siobio_input(sio_t *sio, al_t *al, void *u) { private_t *my = (private_t *)u; char *p; int n; n = BIO_pending(my->bio); if (n == 0 || n > my->inputsize) n = my->inputsize; p = malloc(n); n = BIO_read(my->bio, p, n); if (n == 0 && !BIO_should_read(my->bio)) al_append_bytes(al, &my->eof, sizeof(my->eof), my->eof_label); else al_attach_buffer(al, p, n, my->data_label, freebiobuf, NULL); return SIO_SCHED_DOWN; } static al_rc_t siobio_write_chunk(al_chunk_t *alc, void *u) { private_t *my = (private_t *)u; if (al_same_label(alc, my->data_label)) BIO_write(my->bio, al_chunk_ptr(alc, 0), al_chunk_len(alc)); return AL_OK; } static sio_rc_t siobio_output(sio_t *sio, al_t *al, void *u) { private_t *my = (private_t *)u; al_traverse_cb(al, 0, al_bytes(al), AL_FORWARD, my->data_label, siobio_write_chunk, (void *)my); al_splice(al, 0, al_bytes(al), NULL, NULL); return SIO_SCHED_DOWN; } sio_module_t sio_module_bio = { "bio", siobio_init, siobio_configure, siobio_cleanup, siobio_openr, siobio_closer, siobio_openw, siobio_closew, siobio_input, siobio_output };