mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-02-04 04:06:29 -05:00
Implement socket activation without libsystemd
Socket activation uses sd_listen_fds from libsystemd, and can only be compiled on systems with systemd. This is an issue for Alpine / postmarketOS, where upstream has no systemd package, but downstream depends on upstream's pipewire package and wants to rely on socket activation. This also prevents using socket-activation on other non-systemd distributions, including non-Linux. Implement equivalent functionality without a dependency on libsystemd.
This commit is contained in:
parent
2c0988ab4c
commit
57efceeb02
4 changed files with 82 additions and 30 deletions
|
|
@ -276,10 +276,6 @@ pipewire_module_link_factory = shared_library('pipewire-module-link-factory',
|
||||||
|
|
||||||
pipewire_module_protocol_deps = [mathlib, dl_lib, pipewire_dep]
|
pipewire_module_protocol_deps = [mathlib, dl_lib, pipewire_dep]
|
||||||
|
|
||||||
if systemd_dep.found()
|
|
||||||
pipewire_module_protocol_deps += systemd_dep
|
|
||||||
endif
|
|
||||||
|
|
||||||
if selinux_dep.found()
|
if selinux_dep.found()
|
||||||
pipewire_module_protocol_deps += selinux_dep
|
pipewire_module_protocol_deps += selinux_dep
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,6 @@
|
||||||
#include <spa/utils/json.h>
|
#include <spa/utils/json.h>
|
||||||
#include <spa/debug/log.h>
|
#include <spa/debug/log.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
|
||||||
#include <systemd/sd-daemon.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -45,6 +41,7 @@
|
||||||
#include <pipewire/impl.h>
|
#include <pipewire/impl.h>
|
||||||
#include <pipewire/extensions/protocol-native.h>
|
#include <pipewire/extensions/protocol-native.h>
|
||||||
|
|
||||||
|
#include "network-utils.h"
|
||||||
#include "pipewire/private.h"
|
#include "pipewire/private.h"
|
||||||
|
|
||||||
#include "modules/module-protocol-native/connection.h"
|
#include "modules/module-protocol-native/connection.h"
|
||||||
|
|
@ -909,13 +906,12 @@ static int add_socket(struct pw_protocol *protocol, struct server *s, struct soc
|
||||||
int fd = -1, res;
|
int fd = -1, res;
|
||||||
bool activated = false;
|
bool activated = false;
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
|
||||||
{
|
{
|
||||||
int i, n = sd_listen_fds(0);
|
int i, n = listen_fd();
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, SOCK_STREAM,
|
if (is_socket_unix(LISTEN_FDS_START + i, SOCK_STREAM,
|
||||||
1, s->addr.sun_path, 0) > 0) {
|
s->addr.sun_path) > 0) {
|
||||||
fd = SD_LISTEN_FDS_START + i;
|
fd = LISTEN_FDS_START + i;
|
||||||
activated = true;
|
activated = true;
|
||||||
pw_log_info("server %p: Found socket activation socket for '%s'",
|
pw_log_info("server %p: Found socket activation socket for '%s'",
|
||||||
s, s->addr.sun_path);
|
s, s->addr.sun_path);
|
||||||
|
|
@ -923,7 +919,6 @@ static int add_socket(struct pw_protocol *protocol, struct server *s, struct soc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
struct stat socket_stat;
|
struct stat socket_stat;
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
|
||||||
#include <systemd/sd-daemon.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <spa/utils/cleanup.h>
|
#include <spa/utils/cleanup.h>
|
||||||
#include <spa/utils/defs.h>
|
#include <spa/utils/defs.h>
|
||||||
|
|
@ -577,26 +574,19 @@ static bool is_stale_socket(int fd, const struct sockaddr_un *addr_un)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
static int check_socket_activation(const char *path)
|
||||||
static int check_systemd_activation(const char *path)
|
|
||||||
{
|
{
|
||||||
const int n = sd_listen_fds(0);
|
const int n = listen_fd();
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
const int fd = SD_LISTEN_FDS_START + i;
|
const int fd = LISTEN_FDS_START + i;
|
||||||
|
|
||||||
if (sd_is_socket_unix(fd, SOCK_STREAM, 1, path, 0) > 0)
|
if (is_socket_unix(fd, SOCK_STREAM, path) > 0)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static inline int check_systemd_activation(SPA_UNUSED const char *path)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int start_unix_server(struct server *server, const struct sockaddr_storage *addr)
|
static int start_unix_server(struct server *server, const struct sockaddr_storage *addr)
|
||||||
{
|
{
|
||||||
|
|
@ -606,10 +596,10 @@ static int start_unix_server(struct server *server, const struct sockaddr_storag
|
||||||
|
|
||||||
spa_assert(addr_un->sun_family == AF_UNIX);
|
spa_assert(addr_un->sun_family == AF_UNIX);
|
||||||
|
|
||||||
fd = check_systemd_activation(addr_un->sun_path);
|
fd = check_socket_activation(addr_un->sun_path);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
server->activated = true;
|
server->activated = true;
|
||||||
pw_log_info("server %p: found systemd socket activation socket for '%s'",
|
pw_log_info("server %p: found socket activation socket for '%s'",
|
||||||
server, addr_un->sun_path);
|
server, addr_un->sun_path);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,12 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#include <spa/utils/string.h>
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define ifr_ifindex ifr_index
|
#define ifr_ifindex ifr_index
|
||||||
|
|
@ -131,5 +137,70 @@ static inline bool pw_net_addr_is_any(struct sockaddr_storage *addr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef LISTEN_FDS_START
|
||||||
|
#define LISTEN_FDS_START 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns the number of file descriptors passed for socket activation.
|
||||||
|
* Returns 0 if none, -1 on error. */
|
||||||
|
static inline int listen_fd(void)
|
||||||
|
{
|
||||||
|
uint32_t n;
|
||||||
|
int i, flags;
|
||||||
|
|
||||||
|
if (!spa_atou32(getenv("LISTEN_FDS"), &n, 10) || n > INT_MAX - LISTEN_FDS_START) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < (int)n; i++) {
|
||||||
|
flags = fcntl(LISTEN_FDS_START + i, F_GETFD);
|
||||||
|
if (flags == -1)
|
||||||
|
return -1;
|
||||||
|
if (fcntl(LISTEN_FDS_START + i, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsetenv("LISTEN_FDS");
|
||||||
|
|
||||||
|
return (int)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the fd is a listening unix socket of the given type,
|
||||||
|
* optionally bound to the given path. */
|
||||||
|
static inline int is_socket_unix(int fd, int type, const char *path)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
int val;
|
||||||
|
socklen_t len = sizeof(val);
|
||||||
|
|
||||||
|
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &val, &len) < 0)
|
||||||
|
return -errno;
|
||||||
|
if (val != type)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &val, &len) < 0)
|
||||||
|
return -errno;
|
||||||
|
if (!val)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
len = sizeof(addr);
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
if (getsockname(fd, (struct sockaddr *)&addr, &len) < 0)
|
||||||
|
return -errno;
|
||||||
|
if (addr.sun_family != AF_UNIX)
|
||||||
|
return 0;
|
||||||
|
size_t length = strlen(path);
|
||||||
|
if (length > 0) {
|
||||||
|
if (len < offsetof(struct sockaddr_un, sun_path) + length)
|
||||||
|
return 0;
|
||||||
|
if (memcmp(addr.sun_path, path, length) != 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* NETWORK_UTILS_H */
|
#endif /* NETWORK_UTILS_H */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue