From 665710cf961adaf56b448ee09729eafd1adb3ed4 Mon Sep 17 00:00:00 2001 From: Thomas Lindner Date: Wed, 19 Oct 2022 18:38:37 +0200 Subject: [PATCH] add connection read/write methods --- src/main.c | 2 +- src/network.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index 42a5cd4..ef3cfd9 100644 --- a/src/main.c +++ b/src/main.c @@ -9,7 +9,7 @@ int main(int argc, char **argv) { tls_init(); config = tls_config_new(); connection_init(EV_DEFAULT_ & connection, config); - ev_run(EV_DEFAULT_UC_ 0); tls_config_free(config); + ev_run(EV_DEFAULT_UC_ 0); return 0; } diff --git a/src/network.c b/src/network.c index e65336c..ebf9a95 100644 --- a/src/network.c +++ b/src/network.c @@ -1,3 +1,4 @@ +#include #include #include @@ -6,21 +7,104 @@ #include #include +typedef void (*ConnectionCallback)(EV_P_ Connection *); + struct Connection { ev_io watcher; struct tls *ctx; + ConnectionCallback success_cb; + ConnectionCallback failure_cb; + Buffer read_buf; + Buffer write_buf; +}; + +struct Buffer { + size_t size; + char data[4096]; }; #endif void connection_init(EV_P_ Connection *connection, struct tls_config *config) { - ev_io_init(&connection->watcher, connection_cb, STDIN_FILENO, EV_READ); - ev_io_start(EV_A_ & connection->watcher); + ev_io_init(&connection->watcher, NULL, STDIN_FILENO, 0); connection->ctx = tls_client(); tls_configure(connection->ctx, config); } -static void connection_cb(EV_P_ ev_io *w, int revents) { - ev_io_stop(EV_A_ w); - ev_break(EV_A_ EVBREAK_ALL); +#define connection_set_failure_cb(connection, callback) \ + do { \ + (connection)->failure_cb = callback; \ + } while (0) + +#define connection_set_cb(connection, callback) \ + do { \ + (connection)->success_cb = callback; \ + } while (0) + +#define connection_read_buf(connection) &((connection)->read_buf) +#define connection_write_buf(connection) &((connection)->write_buf) + +void connection_read_some(EV_P_ Connection *connection) { + assert(connection->success_cb && connection->failure_cb); + ev_set_cb(&connection->watcher, connection_read_some_cb); + ev_invoke(EV_A_ & connection->watcher, 0); +} + +static void connection_read_some_cb(EV_P_ ev_io *watcher, int revents) { + Connection *connection = (Connection *)watcher; + ssize_t n; + + (void)revents; + ev_io_stop(EV_A_ watcher); + n = tls_read(connection->ctx, + &connection->read_buf.data[connection->read_buf.size], + sizeof(connection->read_buf.data) - connection->read_buf.size); + if (n == TLS_WANT_POLLIN) { + ev_io_modify(watcher, EV_READ); + ev_io_start(EV_A_ watcher); + } else if (n == TLS_WANT_POLLOUT) { + ev_io_modify(watcher, EV_WRITE); + ev_io_start(EV_A_ watcher); + } else if (n == -1) { + connection->failure_cb(EV_A_ connection); + } else { + connection->read_buf.size += n; + connection->success_cb(EV_A_ connection); + } +} + +void connection_write_some(EV_P_ Connection *connection) { + assert(connection->success_cb && connection->failure_cb); + ev_set_cb(&connection->watcher, connection_write_some_cb); + ev_invoke(EV_A_ & connection->watcher, 0); +} + +static void connection_write_some_cb(EV_P_ ev_io *watcher, int revents) { + Connection *connection = (Connection *)watcher; + ssize_t n; + + (void)revents; + ev_io_stop(EV_A_ watcher); + n = tls_write(connection->ctx, connection->write_buf.data, + connection->write_buf.size); + if (n == TLS_WANT_POLLIN) { + ev_io_modify(watcher, EV_READ); + ev_io_start(EV_A_ watcher); + } else if (n == TLS_WANT_POLLOUT) { + ev_io_modify(watcher, EV_WRITE); + ev_io_start(EV_A_ watcher); + } else if (n == -1) { + connection->failure_cb(EV_A_ connection); + } else { + connection->write_buf.size -= n; + memmove(connection->write_buf.data, &connection->write_buf.data[n], + connection->write_buf.size); + connection->success_cb(EV_A_ connection); + } +} + +void connection_stop(EV_P_ Connection *connection) { + ev_io_stop(EV_A_ & connection->watcher); + close(connection->watcher.fd); + tls_free(connection->ctx); }