diff options
| author | Egor Tensin <Egor.Tensin@gmail.com> | 2022-08-25 10:47:06 +0200 |
|---|---|---|
| committer | Egor Tensin <Egor.Tensin@gmail.com> | 2022-08-25 10:56:03 +0200 |
| commit | 08ee3cab641f367b642bc29f6540de6be85226bd (patch) | |
| tree | 887f517cbec643ab90c5647d76c26e7fb024b8cc /src/tcp_server.c | |
| parent | msg: add msg_dump_unknown (diff) | |
| download | cimple-08ee3cab641f367b642bc29f6540de6be85226bd.tar.gz cimple-08ee3cab641f367b642bc29f6540de6be85226bd.zip | |
net: rework API
First, rename all API functions so that they start with net_.
Second, abstract the basic TCP server functionality into tcp_server.c.
This includes reworking net_accept so that it's a simple blocking
operation, and putting the callback stuff to tcp_server.c. Also, the
server now uses detached threads instead of fork(), since I want
connection handlers to share memory.
Diffstat (limited to 'src/tcp_server.c')
| -rw-r--r-- | src/tcp_server.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/tcp_server.c b/src/tcp_server.c new file mode 100644 index 0000000..dc7d47b --- /dev/null +++ b/src/tcp_server.c @@ -0,0 +1,92 @@ +#include "tcp_server.h" +#include "log.h" +#include "net.h" + +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> + +int tcp_server_create(struct tcp_server *server, const char *port) +{ + server->fd = net_bind(port); + if (server->fd < 0) + return server->fd; + + return 0; +} + +void tcp_server_destroy(const struct tcp_server *server) +{ + close(server->fd); +} + +struct child_context { + int fd; + tcp_server_conn_handler handler; + void *arg; +}; + +static void *connection_thread(void *_ctx) +{ + struct child_context *ctx = (struct child_context *)_ctx; + ctx->handler(ctx->fd, ctx->arg); + close(ctx->fd); + free(ctx); + return NULL; +} + +int tcp_server_accept(const struct tcp_server *server, tcp_server_conn_handler handler, void *arg) +{ + struct child_context *ctx; + pthread_attr_t child_attr; + pthread_t child; + int conn_fd, ret = 0; + + ret = net_accept(server->fd); + if (ret < 0) { + print_errno("accept"); + return ret; + } + conn_fd = ret; + + ctx = malloc(sizeof(*ctx)); + if (!ctx) { + print_errno("malloc"); + ret = -1; + goto close_conn; + } + *ctx = (struct child_context){conn_fd, handler, arg}; + + ret = pthread_attr_init(&child_attr); + if (ret < 0) { + print_errno("pthread_attr_init"); + goto free_ctx; + } + + ret = pthread_attr_setdetachstate(&child_attr, PTHREAD_CREATE_DETACHED); + if (ret < 0) { + print_errno("pthread_attr_setdetachstate"); + goto destroy_attr; + } + + ret = pthread_create(&child, &child_attr, connection_thread, ctx); + if (ret < 0) { + print_errno("pthread_create"); + goto destroy_attr; + } + + pthread_attr_destroy(&child_attr); + + return ret; + +destroy_attr: + pthread_attr_destroy(&child_attr); + +free_ctx: + free(ctx); + +close_conn: + close(conn_fd); + + return ret; +} |
