diff options
author | George Kiagiadakis <george.kiagiadakis@collabora.com> | 2021-07-14 13:27:40 +0300 |
---|---|---|
committer | George Kiagiadakis <george.kiagiadakis@collabora.com> | 2021-07-28 13:19:02 +0300 |
commit | b6f553a33e751ad51abf036ab0ce7b01ee99e39a (patch) | |
tree | cde6ad9709084103d826ba57b4ba2a84f0060275 /lib/receiver.c | |
parent | 4ad92cc00f6beb6e29c36b7c8316df9b7360903d (diff) |
server: add systemd units + socket-activation support
Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com>
Diffstat (limited to 'lib/receiver.c')
-rw-r--r-- | lib/receiver.c | 83 |
1 files changed, 62 insertions, 21 deletions
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 <stdlib.h> #include <stdio.h> -#include <unistd.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/epoll.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include <string.h> #include <errno.h> #include <assert.h> + +#ifdef HAVE_SYSTEMD +#include <systemd/sd-daemon.h> +#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); } |