aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/client.c2
-rw-r--r--src/msg.c8
-rw-r--r--src/net.c74
-rw-r--r--src/net.h19
-rw-r--r--src/server.c20
-rw-r--r--src/server.h4
-rw-r--r--src/tcp_server.c92
-rw-r--r--src/tcp_server.h14
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;
diff --git a/src/msg.c b/src/msg.c
index b87052c..fc0b93c 100644
--- a/src/msg.c
+++ b/src/msg.c
@@ -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;
diff --git a/src/net.c b/src/net.c
index e41d5ea..ceffba0 100644
--- a/src/net.c
+++ b/src/net.c
@@ -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;
diff --git a/src/net.h b/src/net.h
index 644520c..ce1c536 100644
--- a/src/net.h
+++ b/src/net.h
@@ -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