Index: ossp-pkg/sio/sio.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio.c,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/sio/sio.c,v' 2>/dev/null --- sio.c 2002/10/24 07:46:01 1.3 +++ sio.c 2002/11/05 13:23:36 1.4 @@ -58,6 +58,8 @@ NODE(sio_halfduplex_t) hd; sio_stage_t *stage; sio_halfduplex_t *cross; + const char *tag; + sio_rc_t rc_with_data, rc_no_data; al_t *al; sio_rc_t (*func)(sio_t *, al_t *, void *); }; @@ -99,15 +101,28 @@ * call stage and direct data upstream/downstream * according to response code * + * if stage directs SIO_OK, chose default direction + * depending on data in assembly line + * * if we the stage does not return a direction, * simply end the code * * if we drop off the chain, simply result SIO_OK * */ - h = chain; + rc = SIO_UPSTREAM; + h = chain; while (h != NULL) { rc = h->func(sio, h->al, h->stage->userdata); + + /* chose default direction */ + if (rc == SIO_OK) { + if (al_bytes(h->al) > 0) + rc = h->rc_with_data; + else + rc = h->rc_no_data; + } + if (rc == SIO_UPSTREAM) h = NEXT(h,hd); else if (rc == SIO_DOWNSTREAM) @@ -176,17 +191,28 @@ NODEINIT(&sios->reader,hd); NODEINIT(&sios->writer,hd); + sios->module = siom; + sios->userdata = NULL; sios->rw = SIO_MODE_INVALID; - sios->reader.func = siom->input; + sios->reader.func = sios->module->input; sios->reader.stage = sios; - sios->writer.func = siom->output; + sios->writer.func = sios->module->output; sios->writer.stage = sios; sios->reader.cross = &sios->writer; sios->writer.cross = &sios->reader; + sios->reader.tag = "reader"; + sios->writer.tag = "writer"; + + /* default rules */ + sios->reader.rc_with_data = SIO_DOWNSTREAM; + sios->reader.rc_no_data = SIO_UPSTREAM; + sios->writer.rc_with_data = SIO_UPSTREAM; + sios->writer.rc_no_data = SIO_DOWNSTREAM; + rc = sios->module->init(sio, &sios->userdata); if (rc != SIO_OK) { free(sios); Index: ossp-pkg/sio/sio_hello.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_hello.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/sio_hello.c,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio_hello.c' 2>/dev/null --- ossp-pkg/sio/sio_hello.c +++ - 2024-05-11 17:36:39.072278115 +0200 @@ -0,0 +1,302 @@ + +#include +#include +#include + +#include "al.h" +#include "sio.h" +#include "sio_module.h" + +#define PROMPT "Login: " +#define NPROMPT (sizeof(PROMPT)-1) + +#define PASSWD "Geheim\r\n" +#define NPASS (sizeof(PASSWD)-1) + +/* + * protocol states + */ +typedef enum { + INIT, /* setting up protocol, save output or switch to writer */ + PROMPTING, /* sending prompt string as writer */ + PROMPTED, /* continue sending, switch to reader when done */ + WAIT, /* gather password as reader, flush buffer if good */ + GOOD, /* default null operation */ + BAD /* drop output, return eof on input */ +} state_t; + +typedef struct { + al_t *al_in, *al_out; /* cache input and output stream */ + state_t state; + char passwd[NPASS]; /* input buffer */ + int npass; /* characters in input buffer */ + al_t *pre; /* saved output during protocol */ + int isoutput; /* remember originator of protocol */ + void *data_label; /* al labels used by SIO */ + void *eof_label; + char eof; /* eof label buffer */ +} private_t; + +/***********************************************************************/ + +/* + * create stage + * + * allocate private instance data + */ +static +sio_rc_t hello_init(sio_t *sio, void **u) +{ + private_t *my; + + my = (private_t *)malloc(sizeof(private_t)); + if (my == NULL) + return SIO_ERR_MEM; + + sio_label(sio, SIO_LN_DATA, &my->data_label); + sio_label(sio, SIO_LN_EOF, &my->eof_label); + + my->eof = '\0'; + + *u = my; + + return SIO_OK; +} + +/* + * configure stage + * + * pass two void pointers + */ +static +sio_rc_t hello_configure(sio_t *sio, void *u, void *obj, void *val) +{ + return SIO_ERR_ARG; +} + +/* + * destroy stage + */ +static +sio_rc_t hello_cleanup(sio_t *sio, void *u) +{ + private_t *my = (private_t *)u; + + al_destroy(my->pre); + + free(my); + + return SIO_OK; +} + +static +void hello_setup(sio_t *sio, private_t *my) +{ + my->state = INIT; + my->npass = 0; +} + +static +sio_rc_t hello_openr(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + + hello_setup(sio,my); + my->al_in = al; + + return SIO_OK; +} + +static +sio_rc_t hello_closer(sio_t *sio, al_t *al, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t hello_openw(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + + hello_setup(sio,my); + al_create(&my->pre); + my->al_out = al; + + return SIO_OK; +} + +static +sio_rc_t hello_closew(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + + al_destroy(my->pre); + my->pre = NULL; + + return SIO_OK; +} + +/************************************************************************/ + +static +void hello_clearinput(private_t *my) +{ + al_splice(my->al_in, 0, al_bytes(my->al_in), NULL, NULL); +} + +static +void hello_clearoutput(private_t *my) +{ + al_splice(my->al_out, 0, al_bytes(my->al_out), NULL, NULL); +} + +/* + * gather input in password buffer + * return true if enough bytes or if no more data follows + */ +static +int hello_readpasswd(private_t *my) +{ + size_t actual; + + al_flatten(my->al_in, 0, NPASS - my->npass, AL_FORWARD_SPAN, my->data_label, + my->passwd, &actual); + al_splice(my->al_in, 0, actual, NULL, NULL); + my->npass += actual; + + /* flush input when buffer full or labels are switching */ + return my->npass == NPASS || al_bytes(my->al_in) > 0; +} + +/* + * write eof token to input stream + */ +static +void hello_writeeof(private_t *my) +{ + hello_clearinput(my); + al_append_bytes(my->al_in, &my->eof, sizeof(my->eof), my->eof_label); +} + +/* + * defer initial output until protocol is done + */ +static +void hello_saveoutput(private_t *my) +{ + al_splice(my->pre, al_bytes(my->pre), 0, my->al_out, NULL); +} + +/* + * restore saved output after handshake completed successfully + */ +static +void hello_restoreoutput(private_t *my) +{ + al_splice(my->al_out, 0, 0, my->pre, NULL); +} + +/* + * write prompt string to output + */ +static +void hello_sendprompt(private_t *my) +{ + al_prepend_bytes(my->al_out, PROMPT, NPROMPT, my->data_label); +} + +/************************************************************************/ + +#define GOTO(s, c) do { my->state = (s); rc = (c); } while(0) + +static +sio_rc_t hello_protocol(sio_t *sio, private_t *my, int isoutput) +{ + sio_rc_t rc = SIO_ERR_INT; + int good; + + switch (my->state) { + case INIT: + if (isoutput) { + my->isoutput = 1; + hello_saveoutput(my); + GOTO(PROMPTING, SIO_UPSTREAM); + } else { + my->isoutput = 0; + GOTO(PROMPTING, SIO_XSTREAM); + } + break; + case PROMPTING: + assert(isoutput == 1); + hello_sendprompt(my); + GOTO(PROMPTED, SIO_UPSTREAM); + break; + case PROMPTED: + assert(isoutput == 1); + GOTO(WAIT, SIO_XSTREAM); + break; + case WAIT: + assert(isoutput == 0); + if (!hello_readpasswd(my)) + GOTO(WAIT, SIO_UPSTREAM); + else { + good = my->npass == NPASS && + memcmp(my->passwd, PASSWD, NPASS) == 0; + if (!good) { + if (my->isoutput) + GOTO(BAD, SIO_XSTREAM); + else { + hello_writeeof(my); + GOTO(BAD, SIO_DOWNSTREAM); + } + } else if (my->isoutput) { + hello_restoreoutput(my); + GOTO(GOOD, SIO_XSTREAM); + } else + GOTO(GOOD, SIO_OK); + } + + break; + case GOOD: + GOTO(GOOD, SIO_OK); /* default action */ + break; + case BAD: + if (isoutput) + hello_clearoutput(my); + else + hello_writeeof(my); + + GOTO(BAD, SIO_DOWNSTREAM); + break; + } + + return rc; +} + +/************************************************************************/ + +static +sio_rc_t hello_input(sio_t *sio, al_t *al, void *u) +{ + return hello_protocol(sio, (private_t *)u, 0); +} + +static +sio_rc_t hello_output(sio_t *sio, al_t *al, void *u) +{ + return hello_protocol(sio, (private_t *)u, 1); +} + +sio_module_t sio_module_hello = { + "hello", + hello_init, + hello_configure, + hello_cleanup, + hello_openr, + hello_closer, + hello_openw, + hello_closew, + hello_input, + hello_output +}; + Index: ossp-pkg/sio/sio_hole.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_hole.c,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/sio/sio_hole.c,v' 2>/dev/null --- sio_hole.c 2002/10/23 17:05:10 1.1 +++ sio_hole.c 2002/11/05 13:23:36 1.2 @@ -6,6 +6,7 @@ #include "sio_module.h" typedef struct { + int dummy; } private_t; /* @@ -78,15 +79,10 @@ static sio_rc_t hole_input(sio_t *sio, al_t *al, void *u) { - size_t feed = al_bytes(al); - /* drop all data into the bit bucket */ - if (feed > 0) { - al_splice(al, 0, feed, NULL, NULL); - return SIO_DOWNSTREAM; - } + al_splice(al, 0, al_bytes(al), NULL, NULL); - return SIO_UPSTREAM; + return SIO_DOWNSTREAM; } static Index: ossp-pkg/sio/sio_null.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_null.c,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/sio/sio_null.c,v' 2>/dev/null --- sio_null.c 2002/10/23 17:05:10 1.2 +++ sio_null.c 2002/11/05 13:23:36 1.3 @@ -89,13 +89,13 @@ static sio_rc_t null_input(sio_t *sio, al_t *al, void *u) { - return SIO_DOWNSTREAM; + return SIO_OK; } static sio_rc_t null_output(sio_t *sio, al_t *al, void *u) { - return SIO_UPSTREAM; + return SIO_OK; } sio_module_t sio_module_null = { Index: ossp-pkg/sio/sio_sa.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_sa.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/sio_sa.c,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio_sa.c' 2>/dev/null --- ossp-pkg/sio/sio_sa.c +++ - 2024-05-11 17:36:39.082942706 +0200 @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include + +#include "al.h" +#include "sio.h" +#include "sio_module.h" + +#include "sa.h" + +typedef struct { + char *mem; + size_t size; +} buffer_t; + +typedef struct { + sa_t *sa; + buffer_t input; + size_t written; + void *label_data; + void *label_error; + void *label_eof; + char eof; + char error; +} private_t; + +/* + * create stage + * + * allocate private instance data + */ +static +sio_rc_t sa_init(sio_t *sio, void **u) +{ + private_t *my; + + my = (private_t *)malloc(sizeof(private_t)); + if (my == NULL) + return SIO_ERR_MEM; + + my->sa = NULL; + + my->input.mem = NULL; + my->input.size = 0; + + sio_label(sio, SIO_LN_DATA, &my->label_data); + sio_label(sio, SIO_LN_ERROR, &my->label_error); + sio_label(sio, SIO_LN_EOF, &my->label_eof); + + my->eof = '\0'; + my->error = '\0'; + + *u = my; + + return SIO_OK; +} + +/* + * configure stage + * + */ +static +sio_rc_t sa_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, "sa")) { + my->sa = (sa_t *)val; + } else if (!strcmp(name, "buflen")) { + my->input.size = *(size_t *)val; + } else { + return SIO_ERR_ARG; + } + + return SIO_OK; +} + +/* + * destroy stage + */ +static +sio_rc_t sa_cleanup(sio_t *sio, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t sa_openr(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + buffer_t *buf = &my->input; + char *p; + size_t n; + + n = buf->size; + p = realloc(buf->mem, n); + if (p != NULL) + buf->mem = p; + + if (buf->mem == NULL) + return SIO_ERR_MEM; + + return SIO_OK; +} + +static +sio_rc_t sa_closer(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + buffer_t *buf = &my->input; + + if (buf->mem != NULL) { + free(buf->mem); + buf->mem = NULL; + } + + return SIO_OK; +} + +static +sio_rc_t sa_openw(sio_t *sio, al_t *al, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t sa_closew(sio_t *sio, al_t *al, void *u) +{ + return SIO_OK; +} + +static +void sa_writeeof(al_t *al, private_t *my) +{ + al_splice(al, 0, al_bytes(al), NULL, NULL); + al_append_bytes(al, &my->eof, sizeof(my->eof), my->label_eof); +} + +static +void sa_writeerror(al_t *al, private_t *my) +{ + al_splice(al, 0, al_bytes(al), NULL, NULL); + al_append_bytes(al, &my->error, sizeof(my->error), my->label_error); +} + +static +sio_rc_t sa_input(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + buffer_t *buf = &my->input; + size_t actual; + sa_rc_t src; + + src = sa_read(my->sa, buf->mem, buf->size, &actual); + if (src != SA_OK) { + sa_writeerror(al, my); + return SIO_DOWNSTREAM; + } else if (src == SA_ERR_EOF) { + sa_writeeof(al, my); + return SIO_DOWNSTREAM; + } + + al_append_bytes(al, buf->mem, actual, my->label_data); + + return SIO_DOWNSTREAM; +} + +static +al_rc_t sa_output_chunk(al_chunk_t *alc, void *u) +{ + private_t *my = (private_t *)u; + char *p; + size_t n, actual; + sa_rc_t src; + + p = al_chunk_ptr(alc, 0); + n = al_chunk_len(alc); + + src = sa_write(my->sa, p, n, &actual); + if (src != SA_OK) + return AL_ERR_EOF; + + my->written += actual; /* XXX not used */ + + return AL_OK; +} + +static +sio_rc_t sa_output(sio_t *sio, al_t *al, void *u) +{ + private_t *my = (private_t *)u; + al_rc_t arc; + size_t n = al_bytes(al); + + my->written = 0; + + arc = al_traverse_cb(al, 0, n, AL_FORWARD, my->label_data, + sa_output_chunk, u); + if (arc != AL_OK) return SIO_ERR_INT; + + arc = al_splice(al, 0, al_bytes(al), NULL, NULL); + if (arc != AL_OK) return SIO_ERR_INT; + + return SIO_DOWNSTREAM; +} + +sio_module_t sio_module_sa = { + "sa", + sa_init, + sa_configure, + sa_cleanup, + sa_openr, + sa_closer, + sa_openw, + sa_closew, + sa_input, + sa_output +}; + + Index: ossp-pkg/sio/sio_test.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_test.c,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/sio/sio_test.c,v' 2>/dev/null --- sio_test.c 2002/10/23 17:05:10 1.1 +++ sio_test.c 2002/11/05 13:23:36 1.2 @@ -3,44 +3,85 @@ #include "al.h" #include "sio.h" -extern sio_module_t sio_module_fd; +#include "sa.h" + +extern sio_module_t sio_module_sa; +extern sio_module_t sio_module_hello; extern sio_module_t sio_module_buffer; #define e(f) rc = f; printf("%s = %s\n",#f, sio_error(rc)); fflush(stdout); +#define s(f) src = f; printf("%s = %s\n",#f, sa_error(src)); fflush(stdout); int main(int argc, char *argv[]) { sio_rc_t rc; sio_t *sio; - sio_stage_t *sios_fd, *sios_buffer; - int fd; + sio_stage_t *sios_sa, *sios_hello, *sios_buffer; + + sa_rc_t src; + sa_addr_t *saa; + sa_t *msa, *sa; + char *uri; + char buf[] = "Hello world\n"; + size_t actual; - size_t buflen = 1000; + size_t buflen; - fd = fileno(stdout); + s(sa_create(&msa)); + s(sa_option(msa, SA_OPTION_REUSEADDR, 1)); - e(sio_create(&sio)); + s(sa_addr_create(&saa)); + uri = "inet://localhost:25001#tcp"; + s(sa_addr_u2a(saa, uri)); + s(sa_bind(msa,saa)); + s(sa_addr_destroy(saa)); + uri = NULL; + e(sio_create(&sio)); + e(sio_create_stage(sio, &sio_module_sa, &sios_sa)); + e(sio_create_stage(sio, &sio_module_hello, &sios_hello)); e(sio_create_stage(sio, &sio_module_buffer, &sios_buffer)); + + buflen = 256; + e(sio_configure_stage(sio, sios_sa, "buflen", &buflen)); + + buflen = 1000; e(sio_configure_stage(sio, sios_buffer, "outputsize", &buflen)); - e(sio_create_stage(sio, &sio_module_fd, &sios_fd)); - e(sio_configure_stage(sio, sios_fd, "fd", &fd)); - e(sio_attach(sio, sios_buffer, SIO_MODE_WRITE)); - e(sio_attach(sio, sios_fd, SIO_MODE_WRITE)); + s(sa_listen(msa, 5)); + + for(;;) { + + s(sa_accept(msa, &saa, &sa)); + s(sa_addr_a2u(saa, &uri)); + printf("Connection from %s\n",uri); + s(sa_addr_destroy(saa)); + + e(sio_configure_stage(sio, sios_sa, "sa", sa)); - e(sio_write(sio, buf, sizeof(buf)-1, &actual)); + e(sio_attach(sio, sios_buffer, SIO_MODE_WRITE)); + e(sio_attach(sio, sios_hello, SIO_MODE_READWRITE)); + e(sio_attach(sio, sios_sa, SIO_MODE_READWRITE)); - e(sio_push(sio)); + e(sio_write(sio, buf, sizeof(buf)-1, &actual)); + e(sio_push(sio)); + + e(sio_detach(sio, sios_sa)); + e(sio_detach(sio, sios_hello)); + e(sio_detach(sio, sios_buffer)); + + sa_destroy(sa); + } - e(sio_detach(sio, sios_fd)); - e(sio_detach(sio, sios_buffer)); - e(sio_destroy_stage(sio, sios_fd)); e(sio_destroy_stage(sio, sios_buffer)); + e(sio_destroy_stage(sio, sios_hello)); + e(sio_destroy_stage(sio, sios_sa)); e(sio_destroy(sio)); + sa_destroy(msa); + return 0; }