#include #include #include #include #include #include struct client { bool connected, received; const char *expected; struct transport_handle h; struct io { FILE *in, *out; } io; }; struct server { struct transport_handle h; struct io io; const char *expected; bool received; }; static int io_write(const void *const buf, const size_t n, const struct io *const io) { FILE *const f = io->out; const size_t w = fwrite(buf, 1, n, f); return ferror(f) ? -1 : w; } static int io_read(void *const buf, const size_t n, const struct io *const io) { FILE *const f = io->in; const size_t w = fread(buf, 1, n, f); return ferror(f) ? -1 : w; } static int client_write(const void *const buf, const size_t n, void *const arg) { struct client *const c = arg; return io_write(buf, n, &c->io); } static int client_read(void *const buf, const size_t n, void *const arg) { struct client *const c = arg; return io_read(buf, n, &c->io); } static void client_received(const struct transport_event *const ev, void *const arg) { struct client *const c = arg; if (ev->common.type == TRANSPORT_EVENT_TYPE_CONNECT) c->connected = true; else if (ev->common.type == TRANSPORT_EVENT_TYPE_DATA) { const struct transport_event_data *const d = &ev->u.data; if (!strncmp(d->buf, c->expected, d->n)) c->received = true; } } static int server_write(const void *const buf, const size_t n, void *const arg) { struct server *const s = arg; return io_write(buf, n, &s->io); } static int server_read(void *const buf, const size_t n, void *const arg) { struct server *const s = arg; return io_read(buf, n, &s->io); } static void server_received(const struct transport_event *const ev, void *const arg) { struct server *const s = arg; if (ev->common.type == TRANSPORT_EVENT_TYPE_DATA) { const struct transport_event_data *const d = &ev->u.data; if (!strncmp(d->buf, s->expected, d->n)) s->received = true; } } static int loop(struct server *const s, struct client *const c) { if (transport_update(&s->h) || !freopen("client", "w+b", s->io.in)) return -1; rewind(s->io.out); if (transport_update(&c->h) || !freopen("server", "w+b", c->io.in)) return -1; rewind(c->io.out); return 0; } int main(void) { int ret = EXIT_FAILURE; FILE *const cf = fopen("client", "w+b"), *const sf = fopen("server", "w+b"); if (!cf) { perror("fopen(3) client"); goto end; } else if (!sf) { perror("fopen(3) server"); goto end; } struct client c = { .h = { .cfg = { .arg = &c, .read = client_read, .write = client_write, .received = client_received } }, .io = { .in = sf, .out = cf }, .expected = "hi there!" }; struct server s = { .h = { .cfg = { .arg = &s, .read = server_read, .write = server_write, .received = server_received, } }, .io = { .in = cf, .out = sf }, .expected = "hello" }; if (transport_connect(&c.h)) goto end; while (!c.connected) if (loop(&s, &c)) goto end; if (transport_send(&c.h, s.expected, strlen(s.expected))) goto end; while (!s.received) if (loop(&s, &c)) goto end; if (transport_send(&s.h, c.expected, strlen(c.expected))) goto end; while (!c.received) if (loop(&s, &c)) goto end; ret = EXIT_SUCCESS; end: if (cf) fclose(cf); if (sf) fclose(sf); return ret; }