From b6f553a33e751ad51abf036ab0ce7b01ee99e39a Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Wed, 14 Jul 2021 13:27:40 +0300 Subject: server: add systemd units + socket-activation support Signed-off-by: George Kiagiadakis --- lib/receiver.c | 83 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 21 deletions(-) (limited to 'lib/receiver.c') diff --git a/lib/receiver.c b/lib/receiver.c index 9b34494..e039ced 100644 --- a/lib/receiver.c +++ b/lib/receiver.c @@ -8,13 +8,20 @@ #include #include -#include #include #include #include +#include +#include +#include #include #include #include + +#ifdef HAVE_SYSTEMD +#include +#endif + #include "private.h" #include "receiver.h" #include "icipc.h" @@ -24,6 +31,7 @@ struct icipc_receiver { struct sockaddr_un addr; int socket_fd; + bool activated; uint8_t *buffer_read; size_t buffer_size; @@ -116,28 +124,60 @@ struct icipc_receiver *icipc_receiver_new( /* set address */ self->addr.sun_family = AF_LOCAL; - res = - icipc_construct_socket_path(path, self->addr.sun_path, - sizeof(self->addr.sun_path)); + res = icipc_construct_socket_path(path, self->addr.sun_path, + sizeof(self->addr.sun_path)); if (res < 0) goto error; - unlink(self->addr.sun_path); - - /* create socket */ - self->socket_fd = - socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (self->socket_fd < 0) - goto error; - - /* bind socket */ - if (bind(self->socket_fd, (struct sockaddr *)&self->addr, - sizeof(self->addr)) != 0) - goto error; - - /* listen socket */ - if (listen(self->socket_fd, MAX_SENDERS) != 0) - goto error; +#ifdef HAVE_SYSTEMD + { + int i, n = sd_listen_fds(0); + for (i = 0; i < n; ++i) { + if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, + SOCK_STREAM, 1, + self->addr.sun_path, 0) > 0) { + self->socket_fd = SD_LISTEN_FDS_START + i; + self->activated = true; + icipc_log_info("receiver %p: Found socket " + "activation socket for '%s'", + self, self->addr.sun_path); + break; + } + } + } +#endif + + if (self->socket_fd < 0) { + struct stat socket_stat; + + /* create socket */ + self->socket_fd = + socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (self->socket_fd < 0) + goto error; + + if (stat(self->addr.sun_path, &socket_stat) < 0) { + if (errno != ENOENT) { + res = -errno; + icipc_log_error("receiver %p: stat %s failed " + "with error: %m", + self, self->addr.sun_path); + goto error; + } + } else if (socket_stat.st_mode & S_IWUSR || + socket_stat.st_mode & S_IWGRP) { + unlink(self->addr.sun_path); + } + + /* bind socket */ + if (bind(self->socket_fd, (struct sockaddr *)&self->addr, + sizeof(self->addr)) != 0) + goto error; + + /* listen socket */ + if (listen(self->socket_fd, MAX_SENDERS) != 0) + goto error; + } /* alloc buffer read */ self->buffer_size = buffer_size; @@ -174,7 +214,8 @@ void icipc_receiver_free(struct icipc_receiver *self) { icipc_epoll_thread_destroy(&self->epoll_thread); free(self->buffer_read); close(self->socket_fd); - unlink(self->addr.sun_path); + if (!self->activated) + unlink(self->addr.sun_path); free(self); } -- cgit 1.2.3-korg