diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/client.c | 2 | ||||
-rw-r--r-- | src/msg.c | 8 | ||||
-rw-r--r-- | src/net.c | 74 | ||||
-rw-r--r-- | src/net.h | 19 | ||||
-rw-r--r-- | src/server.c | 20 | ||||
-rw-r--r-- | src/server.h | 4 | ||||
-rw-r--r-- | src/tcp_server.c | 92 | ||||
-rw-r--r-- | src/tcp_server.h | 14 |
9 files changed, 148 insertions, 89 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dcf1ba1..69b7690 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,5 +12,7 @@ add_compile_definitions(_GNU_SOURCE) add_compile_definitions(VERSION="${PROJECT_VERSION}") -add_executable(server server_main.c server.c msg.c net.c) +add_executable(server server_main.c server.c msg.c net.c tcp_server.c) add_executable(client client_main.c client.c msg.c net.c) + +target_link_libraries(server PRIVATE pthread) diff --git a/src/client.c b/src/client.c index 0391784..972ebbd 100644 --- a/src/client.c +++ b/src/client.c @@ -6,7 +6,7 @@ int client_create(struct client *client, const struct settings *settings) { - client->fd = connect_to_host(settings->host, settings->port); + client->fd = net_connect(settings->host, settings->port); if (client->fd < 0) return client->fd; @@ -104,7 +104,7 @@ int msg_send(int fd, const struct msg *msg) } arr_pack(buf, msg->argc, msg->argv); - ret = send_buf(fd, buf, len); + ret = net_send_buf(fd, buf, len); if (ret < 0) goto free_buf; @@ -122,7 +122,7 @@ int msg_send_and_wait_for_result(int fd, const struct msg *msg, int *result) if (ret < 0) return ret; - ret = recv_static(fd, result, sizeof(*result)); + ret = net_recv_static(fd, result, sizeof(*result)); if (ret < 0) return ret; @@ -135,7 +135,7 @@ int msg_recv(int fd, struct msg *msg) size_t len; int ret = 0; - ret = recv_buf(fd, &buf, &len); + ret = net_recv_buf(fd, &buf, &len); if (ret < 0) return ret; @@ -174,7 +174,7 @@ int msg_recv_and_send_result(int fd, msg_handler handler, void *arg) result = handler(&msg, arg); - ret = send_buf(fd, &result, sizeof(result)); + ret = net_send_buf(fd, &result, sizeof(result)); if (ret < 0) goto free_msg; @@ -2,7 +2,6 @@ #include "log.h" #include <netdb.h> -#include <signal.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> @@ -11,28 +10,7 @@ #define gai_print_errno(ec) print_error("getaddrinfo: %s\n", gai_strerror(ec)) -static int ignore_signal(int signum) -{ - int ret = 0; - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_handler = SIG_IGN; - - ret = sigaction(signum, &act, NULL); - if (ret < 0) { - print_errno("sigaction"); - return ret; - } - - return ret; -} - -static int ignore_sigchld() -{ - return ignore_signal(SIGCHLD); -} - -int bind_to_port(const char *port) +int net_bind(const char *port) { struct addrinfo *result, *it = NULL; struct addrinfo hints; @@ -87,12 +65,6 @@ int bind_to_port(const char *port) goto fail; } - /* Don't make zombies. The alternative is wait()ing for the child in - * the signal handler. */ - ret = ignore_sigchld(); - if (ret < 0) - goto fail; - return socket_fd; fail: @@ -101,38 +73,20 @@ fail: return ret; } -int accept_connection(int fd, connection_handler handler, void *arg) +int net_accept(int fd) { - int conn_fd, ret = 0; + int ret = 0; ret = accept4(fd, NULL, NULL, SOCK_CLOEXEC); if (ret < 0) { print_errno("accept"); return ret; } - conn_fd = ret; - - pid_t child_pid = fork(); - if (child_pid < 0) { - print_errno("fork"); - ret = -1; - goto close_conn; - } - - if (!child_pid) { - close(fd); - ret = handler(conn_fd, arg); - close(conn_fd); - exit(ret); - } - -close_conn: - close(conn_fd); return ret; } -int connect_to_host(const char *host, const char *port) +int net_connect(const char *host, const char *port) { struct addrinfo *result, *it = NULL; struct addrinfo hints; @@ -176,7 +130,7 @@ int connect_to_host(const char *host, const char *port) return socket_fd; } -int send_all(int fd, const void *buf, size_t len) +int net_send_all(int fd, const void *buf, size_t len) { size_t sent_total = 0; @@ -194,7 +148,7 @@ int send_all(int fd, const void *buf, size_t len) return 0; } -ssize_t recv_all(int fd, void *buf, size_t len) +ssize_t net_recv_all(int fd, void *buf, size_t len) { ssize_t read_total = 0; @@ -214,26 +168,26 @@ ssize_t recv_all(int fd, void *buf, size_t len) return read_total; } -int send_buf(int fd, const void *buf, size_t len) +int net_send_buf(int fd, const void *buf, size_t len) { int ret = 0; - ret = send_all(fd, &len, sizeof(len)); + ret = net_send_all(fd, &len, sizeof(len)); if (ret < 0) return ret; - ret = send_all(fd, buf, len); + ret = net_send_all(fd, buf, len); if (ret < 0) return ret; return ret; } -int recv_buf(int fd, void **buf, size_t *len) +int net_recv_buf(int fd, void **buf, size_t *len) { ssize_t nb = 0; - nb = recv_all(fd, len, sizeof(*len)); + nb = net_recv_all(fd, len, sizeof(*len)); if (nb < 0) goto fail; @@ -248,7 +202,7 @@ int recv_buf(int fd, void **buf, size_t *len) goto fail; } - nb = recv_all(fd, *buf, *len); + nb = net_recv_all(fd, *buf, *len); if (nb < 0) goto free_buf; @@ -266,13 +220,13 @@ fail: return -1; } -int recv_static(int fd, void *buf, size_t len) +int net_recv_static(int fd, void *buf, size_t len) { void *actual_buf; size_t actual_len; int ret = 0; - ret = recv_buf(fd, &actual_buf, &actual_len); + ret = net_recv_buf(fd, &actual_buf, &actual_len); if (ret < 0) return ret; @@ -3,18 +3,15 @@ #include <stdlib.h> -int bind_to_port(const char *port); +int net_bind(const char *port); +int net_accept(int fd); +int net_connect(const char *host, const char *port); -typedef int (*connection_handler)(int fd, void *arg); -int accept_connection(int fd, connection_handler, void *arg); +int net_send_all(int fd, const void *, size_t); +int net_send_buf(int fd, const void *, size_t); -int connect_to_host(const char *host, const char *port); - -int send_all(int fd, const void *, size_t); -int send_buf(int fd, const void *, size_t); - -ssize_t recv_all(int fd, void *, size_t); -int recv_buf(int fd, void **, size_t *); -int recv_static(int fd, void *, size_t); +ssize_t net_recv_all(int fd, void *, size_t); +int net_recv_buf(int fd, void **, size_t *); +int net_recv_static(int fd, void *, size_t); #endif diff --git a/src/server.c b/src/server.c index 9604bd6..00789d5 100644 --- a/src/server.c +++ b/src/server.c @@ -1,22 +1,25 @@ #include "server.h" #include "msg.h" #include "net.h" +#include "tcp_server.h" #include <stdio.h> #include <unistd.h> int server_create(struct server *server, const struct settings *settings) { - server->fd = bind_to_port(settings->port); - if (server->fd < 0) - return server->fd; + int ret = 0; + + ret = tcp_server_create(&server->tcp_server, settings->port); + if (ret < 0) + return ret; return 0; } void server_destroy(const struct server *server) { - close(server->fd); + tcp_server_destroy(&server->tcp_server); } static int msg_handle(const struct msg *msg, void *) @@ -24,22 +27,17 @@ static int msg_handle(const struct msg *msg, void *) return msg_dump_unknown(msg); } -static int server_handle(int fd, void *) +static int server_conn_handler(int fd, void *) { return msg_recv_and_send_result(fd, msg_handle, NULL); } -static int server_accept(const struct server *server) -{ - return accept_connection(server->fd, server_handle, NULL); -} - int server_main(const struct server *server) { int ret = 0; while (1) { - ret = server_accept(server); + ret = tcp_server_accept(&server->tcp_server, server_conn_handler, NULL); if (ret < 0) return ret; } diff --git a/src/server.h b/src/server.h index 8a46314..11c409b 100644 --- a/src/server.h +++ b/src/server.h @@ -1,12 +1,14 @@ #ifndef __SERVER_H__ #define __SERVER_H__ +#include "tcp_server.h" + struct settings { const char *port; }; struct server { - int fd; + struct tcp_server tcp_server; }; int server_create(struct server *, const struct settings *); 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; +} diff --git a/src/tcp_server.h b/src/tcp_server.h new file mode 100644 index 0000000..12a819d --- /dev/null +++ b/src/tcp_server.h @@ -0,0 +1,14 @@ +#ifndef __TCP_SERVER_H__ +#define __TCP_SERVER_H__ + +struct tcp_server { + int fd; +}; + +int tcp_server_create(struct tcp_server *, const char *port); +void tcp_server_destroy(const struct tcp_server *); + +typedef int (*tcp_server_conn_handler)(int conn_fd, void *arg); +int tcp_server_accept(const struct tcp_server *, tcp_server_conn_handler, void *arg); + +#endif |