From 6221f8ba8272b25449f3c7aba514aef3d975bf05 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Wed, 14 May 2014 15:35:55 +0100 Subject: [PATCH] Implement systemd socket activation Use libsystemd-daemon and two unit files to provide socket activation for the default native unix socket ($XDG_RUNTIME_DIR/pulse/native) from the user manager. In the future this would allow to drop all the complex server location and autospawn code, and just rely on the user manager to do the right thing. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=78701 Tests: - compilation only v1: from Giovanni Campagna http://lists.freedesktop.org/archives/pulseaudio-discuss/2013-December/019662.html v2: from Javier Martinez Canillas Changes since v1 addresses all the concerns raised in: http://permalink.gmane.org/gmane.comp.audio.pulseaudio.general/19365 - Add SYSTEMD_DAEMON has a new configure option - Check for HAVE_SYSTEMD_DAEMON instead of HAVE_SYSTEMD - Wrap unused variables under #if defined(HAVE_SYSTEMD_DAEMON) to avoid compiler warnings when libsystemd-daemon is not available - Fix coding style issues - Add configure output for HAVE_SYSTEMD_DAEMON - Improve debug log message - Add missing pulseaudio.{service,socket} files v3: from Alban Crequy - rebased on git master - fix module_native_protocol_fd_la_CFLAGS - pulseaudio.service with WantedBy left empty? v4: from Alban Crequy - do not unlink socket files created by systemd --- configure.ac | 18 ++++++++++ src/Makefile.am | 59 +++++++++++++++++++-------------- src/daemon/main.c | 38 +++++++++++++++------ src/daemon/pulseaudio.service.in | 11 +++++++ src/daemon/pulseaudio.socket | 8 +++++ src/modules/module-protocol-stub.c | 67 ++++++++++++++++++++++++++++++++++++++ src/pulsecore/socket-server.c | 64 +++++++++++++++++++++++++++++++++--- src/pulsecore/socket-server.h | 3 ++ 8 files changed, 230 insertions(+), 38 deletions(-) create mode 100644 src/daemon/pulseaudio.service.in create mode 100644 src/daemon/pulseaudio.socket diff --git a/configure.ac b/configure.ac index e75973f..7d9597e 100644 --- a/configure.ac +++ b/configure.ac @@ -1184,6 +1184,22 @@ AC_SUBST(HAVE_SYSTEMD_JOURNAL) AM_CONDITIONAL([HAVE_SYSTEMD_JOURNAL], [test "x$HAVE_SYSTEMD_JOURNAL" = x1]) AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], AC_DEFINE([HAVE_JOURNAL], 1, [Have JOURNAL?])) +#### sd-daemon support (optional) #### + +AC_ARG_ENABLE([systemd-daemon], + AS_HELP_STRING([--disable-systemd-daemon],[Disable optional systemd daemon support])) + +AS_IF([test "x$enable_systemd_daemon" != "xno"], + [PKG_CHECK_MODULES(SYSTEMD_DAEMON, [ libsystemd-daemon ], HAVE_SYSTEMD_DAEMON=1, HAVE_SYSTEMD_DAEMON=0)], + HAVE_SYSTEMD_DAEMON=0) + +AS_IF([test "x$enable_systemd_daemon" = "xyes" && test "x$HAVE_SYSTEMD_DAEMON" = "x0"], + [AC_MSG_ERROR([*** Needed systemd daemon support not found])]) + +AC_SUBST(HAVE_SYSTEMD_DAEMON) +AM_CONDITIONAL([HAVE_SYSTEMD_DAEMON], [test "x$HAVE_SYSTEMD_DAEMON" = x1]) +AS_IF([test "x$HAVE_SYSTEMD_DAEMON" = "x1"], AC_DEFINE([HAVE_SYSTEMD_DAEMON], 1, [Have SYSTEMD_DAEMON?])) + #### Build and Install man pages #### AC_ARG_ENABLE([manpages], @@ -1428,6 +1444,7 @@ AS_IF([test "x$HAVE_DBUS" = "x1"], ENABLE_DBUS=yes, ENABLE_DBUS=no) AS_IF([test "x$HAVE_UDEV" = "x1"], ENABLE_UDEV=yes, ENABLE_UDEV=no) AS_IF([test "x$HAVE_SYSTEMD" = "x1"], ENABLE_SYSTEMD=yes, ENABLE_SYSTEMD=no) AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], ENABLE_SYSTEMD_JOURNAL=yes, ENABLE_SYSTEMD_JOURNAL=no) +AS_IF([test "x$HAVE_SYSTEMD_DAEMON" = "x1"], ENABLE_SYSTEMD_DAEMON=yes, ENABLE_SYSTEMD_DAEMON=no) AS_IF([test "x$HAVE_BLUEZ_4" = "x1"], ENABLE_BLUEZ_4=yes, ENABLE_BLUEZ_4=no) AS_IF([test "x$HAVE_BLUEZ_5" = "x1"], ENABLE_BLUEZ_5=yes, ENABLE_BLUEZ_5=no) AS_IF([test "x$HAVE_HAL_COMPAT" = "x1"], ENABLE_HAL_COMPAT=yes, ENABLE_HAL_COMPAT=no) @@ -1487,6 +1504,7 @@ echo " Enable HAL->udev compat: ${ENABLE_HAL_COMPAT} Enable systemd login: ${ENABLE_SYSTEMD} Enable systemd journal: ${ENABLE_SYSTEMD_JOURNAL} + Enable systemd daemon: ${ENABLE_SYSTEMD_DAEMON} Enable TCP Wrappers: ${ENABLE_TCPWRAP} Enable libsamplerate: ${ENABLE_LIBSAMPLERATE} Enable IPv6: ${ENABLE_IPV6} diff --git a/src/Makefile.am b/src/Makefile.am index 5c2d5bc..d288360 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -99,6 +99,8 @@ EXTRA_DIST = \ utils/qpaeq \ modules/module-defs.h.m4 \ daemon/pulseaudio.desktop.in \ + daemon/pulseaudio.service.in \ + daemon/pulseaudio.socket \ map-file \ daemon/pulseaudio-system.conf \ modules/echo-cancel/adrian-license.txt @@ -121,6 +123,15 @@ xdgautostart_DATA = $(xdgautostart_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ endif +if HAVE_SYSTEMD_DAEMON +systemduserunitdir = $(prefix)/lib/systemd/user +systemduserunit_DATA = \ + daemon/pulseaudio.service \ + daemon/pulseaudio.socket + +daemon/pulseaudio.service : daemon/pulseaudio.service.in + $(SED) -e "s|[@]bindir@|$(bindir)|" $< > $@ +endif ################################### # Includes # @@ -146,8 +157,8 @@ pulseaudio_SOURCES = \ daemon/ltdl-bind-now.c daemon/ltdl-bind-now.h \ daemon/main.c -pulseaudio_CFLAGS = $(AM_CFLAGS) $(CAP_CFLAGS) -pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la $(LIBLTDL) $(CAP_LIBS) +pulseaudio_CFLAGS = $(AM_CFLAGS) $(CAP_CFLAGS) $(SYSTEMD_DAEMON_CFLAGS) +pulseaudio_LDADD = $(AM_LDADD) libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la $(LIBLTDL) $(CAP_LIBS) $(SYSTEMD_DAEMON_LIBS) # This is needed because automake doesn't properly expand the foreach below pulseaudio_DEPENDENCIES = libpulsecore-@PA_MAJORMINOR@.la libpulsecommon-@PA_MAJORMINOR@.la libpulse.la $(PREOPEN_LIBS) @@ -1480,14 +1491,14 @@ builddirs: # Simple protocol module_simple_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) +module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_simple_protocol_tcp_la_LDFLAGS = $(MODULE_LDFLAGS) -module_simple_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) libprotocol-simple.la +module_simple_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-simple.la module_simple_protocol_unix_la_SOURCES = modules/module-protocol-stub.c -module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS) +module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_simple_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) -module_simple_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-simple.la +module_simple_protocol_unix_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-simple.la # CLI protocol @@ -1496,26 +1507,26 @@ module_cli_la_LDFLAGS = $(MODULE_LDFLAGS) module_cli_la_LIBADD = $(MODULE_LIBADD) libcli.la module_cli_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_cli_protocol_tcp_la_LDFLAGS = $(MODULE_LDFLAGS) -module_cli_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) libprotocol-cli.la +module_cli_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-cli.la module_cli_protocol_unix_la_SOURCES = modules/module-protocol-stub.c -module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS) +module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_cli_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) -module_cli_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-cli.la +module_cli_protocol_unix_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-cli.la # HTTP protocol module_http_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_http_protocol_tcp_la_LDFLAGS = $(MODULE_LDFLAGS) -module_http_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) libprotocol-http.la +module_http_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-http.la module_http_protocol_unix_la_SOURCES = modules/module-protocol-stub.c -module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS) +module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_http_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) -module_http_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-http.la +module_http_protocol_unix_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-http.la # D-Bus protocol @@ -1538,32 +1549,32 @@ module_dbus_protocol_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) # Native protocol module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_native_protocol_tcp_la_LDFLAGS = $(MODULE_LDFLAGS) -module_native_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) libprotocol-native.la +module_native_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-native.la module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c -module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS) +module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_native_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) -module_native_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-native.la +module_native_protocol_unix_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-native.la module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c -module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS) +module_native_protocol_fd_la_CFLAGS = $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_native_protocol_fd_la_LDFLAGS = $(MODULE_LDFLAGS) -module_native_protocol_fd_la_LIBADD = $(MODULE_LIBADD) libprotocol-native.la +module_native_protocol_fd_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-native.la # EsounD protocol if HAVE_ESOUND module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c -module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_esound_protocol_tcp_la_LDFLAGS = $(MODULE_LDFLAGS) -module_esound_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) libprotocol-esound.la +module_esound_protocol_tcp_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-esound.la module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c -module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS) +module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(SYSTEMD_DAEMON_CFLAGS) $(AM_CFLAGS) module_esound_protocol_unix_la_LDFLAGS = $(MODULE_LDFLAGS) -module_esound_protocol_unix_la_LIBADD = $(MODULE_LIBADD) libprotocol-esound.la +module_esound_protocol_unix_la_LIBADD = $(MODULE_LIBADD) $(SYSTEMD_DAEMON_LIBS) libprotocol-esound.la module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c module_esound_compat_spawnfd_la_LDFLAGS = $(MODULE_LDFLAGS) diff --git a/src/daemon/main.c b/src/daemon/main.c index 02a8ea6..fb85e08 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -58,6 +58,10 @@ #include #endif +#ifdef HAVE_SYSTEMD_DAEMON +#include +#endif + #include #ifdef HAVE_X11 #include @@ -405,6 +409,9 @@ int main(int argc, char *argv[]) { bool valid_pid_file = false; bool ltdl_init = false; int passed_fd = -1; +#ifdef HAVE_SYSTEMD_DAEMON + int systemd_fds = -1; +#endif const char *e; #ifdef HAVE_FORK int daemon_pipe[2] = { -1, -1 }; @@ -472,16 +479,27 @@ int main(int argc, char *argv[]) { passed_fd = -1; } - /* We might be autospawned, in which case have no idea in which - * context we have been started. Let's cleanup our execution - * context as good as possible */ - - pa_reset_personality(); - pa_drop_root(); - pa_close_all(passed_fd, -1); - pa_reset_sigs(-1); - pa_unblock_sigs(-1); - pa_reset_priority(); +#ifdef HAVE_SYSTEMD_DAEMON + systemd_fds = sd_listen_fds(false); + if (systemd_fds > 0 || + getenv("MANAGERPID") != NULL) { + /* We were spawned by systemd, so we know + the environment and process attributes are + clean */ + } else +#endif + { + /* We might be autospawned, in which case have no idea in which + * context we have been started. Let's cleanup our execution + * context as good as possible */ + + pa_reset_personality(); + pa_drop_root(); + pa_close_all(passed_fd, -1); + pa_reset_sigs(-1); + pa_unblock_sigs(-1); + pa_reset_priority(); + } setlocale(LC_ALL, ""); pa_init_i18n(); diff --git a/src/daemon/pulseaudio.service.in b/src/daemon/pulseaudio.service.in new file mode 100644 index 0000000..2f71da0 --- /dev/null +++ b/src/daemon/pulseaudio.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=Pulseaudio daemon for the user session + +[Service] +Type=dbus +BusName=org.pulseaudio.Server +ExecStart=@bindir@/pulseaudio --start --daemonize=no --disallow-exit --exit-idle-time=-1 +Restart=on-failure + +[Install] +WantedBy= diff --git a/src/daemon/pulseaudio.socket b/src/daemon/pulseaudio.socket new file mode 100644 index 0000000..e97af21 --- /dev/null +++ b/src/daemon/pulseaudio.socket @@ -0,0 +1,8 @@ +[Unit] +Description=Native PulseAudio socket + +[Socket] +ListenStream=%t/pulse/native + +[Install] +WantedBy=sockets.target diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c index 3218a01..9bff14b 100644 --- a/src/modules/module-protocol-stub.c +++ b/src/modules/module-protocol-stub.c @@ -32,6 +32,10 @@ #include #endif +#ifdef HAVE_SYSTEMD_DAEMON +#include +#endif + #include #include @@ -244,6 +248,10 @@ int pa__init(pa_module*m) { #else int r; #endif +#if defined(HAVE_SYSTEMD_DAEMON) + int inherited_fds; +#endif + #if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP) char t[256]; @@ -286,6 +294,61 @@ int pa__init(pa_module*m) { u->esound_options->module = m; #endif +#if defined(HAVE_SYSTEMD_DAEMON) + inherited_fds = sd_listen_fds(true); + if (inherited_fds > 0) { + int how_many, i; +#if defined(USE_TCP_SOCKETS) && defined(HAVE_IPV6) + how_many = 2; +#else + how_many = 1; +#endif + + if (inherited_fds > how_many) { + pa_log("Too many sockets passed by system manager."); + goto fail; + } + + for (i = 0; i < inherited_fds; i++) { +#if defined(USE_TCP_SOCKETS) +#ifdef HAVE_IPV6 + if (sd_is_socket_inet(SD_LISTEN_FDS_START + i, AF_INET6, SOCK_STREAM, -1, 0)) + u->socket_server_ipv6 = pa_socket_server_new_ipv6_adopt(m->core->mainloop, SD_LISTEN_FDS_START + i); +#endif + if (sd_is_socket_inet(SD_LISTEN_FDS_START + i, AF_INET, SOCK_STREAM, -1, 0)) + u->socket_server_ipv4 = pa_socket_server_new_ipv4_adopt(m->core->mainloop, SD_LISTEN_FDS_START + i); +#else + if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, SOCK_STREAM, -1, NULL, 0)) + u->socket_server_unix = pa_socket_server_new_unix_adopt (m->core->mainloop, SD_LISTEN_FDS_START + i); +#endif + } + +#if defined(USE_TCP_SOCKETS) +#ifdef HAVE_IPV6 + if (!u->socket_server_ipv4 && !u->socket_server_ipv6) +#else + if (!u->socket_server_ipv4) +#endif + goto fail; + + if (u->socket_server_ipv4) + pa_socket_server_set_callback(u->socket_server_ipv4, socket_server_on_connection_cb, u); +# ifdef HAVE_IPV6 + if (u->socket_server_ipv6) + pa_socket_server_set_callback(u->socket_server_ipv6, socket_server_on_connection_cb, u); +# endif + +#else + if (!u->socket_server_unix) + goto fail; + + pa_socket_server_set_callback(u->socket_server_unix, socket_server_on_connection_cb, u); +#endif + + goto success; + } +#endif + #if defined(USE_TCP_SOCKETS) if (pa_in_system_mode() || pa_modargs_get_value(ma, "port", NULL)) @@ -362,6 +425,10 @@ int pa__init(pa_module*m) { #endif +#if defined(HAVE_SYSTEMD_DAEMON) +success: +#endif + #if defined(USE_PROTOCOL_NATIVE) # if defined(USE_TCP_SOCKETS) if (u->socket_server_ipv4) diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c index ef77563..cb0f076 100644 --- a/src/pulsecore/socket-server.c +++ b/src/pulsecore/socket-server.c @@ -73,6 +73,7 @@ int deny_severity = LOG_WARNING; struct pa_socket_server { PA_REFCNT_DECLARE; int fd; + /* socket file created by PulseAudio */ char *filename; char *tcpwrap_service; @@ -221,12 +222,31 @@ fail: return NULL; } +pa_socket_server *pa_socket_server_new_unix_adopt(pa_mainloop_api *m, int fd) { + pa_socket_server *s; + + pa_make_socket_low_delay(fd); + pa_assert_se(s = pa_socket_server_new(m, fd)); + + /* Keep s->filename NULL when the socket file is not created by + * PulseAudio. + */ + + s->type = SOCKET_SERVER_UNIX; + + return s; +} + #else /* HAVE_SYS_UN_H */ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) { return NULL; } +pa_socket_server *pa_socket_server_new_unix_adopt(pa_mainloop_api *m, int fd) { + return NULL; +} + #endif /* HAVE_SYS_UN_H */ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, bool fallback, const char *tcpwrap_service) { @@ -290,6 +310,17 @@ fail: return NULL; } +pa_socket_server *pa_socket_server_new_ipv4_adopt(pa_mainloop_api *m, int fd) { + pa_socket_server *s; + + pa_make_tcp_socket_low_delay(fd); + pa_assert_se(s = pa_socket_server_new(m, fd)); + + s->type = SOCKET_SERVER_IPV4; + + return s; +} + #ifdef HAVE_IPV6 pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, bool fallback, const char *tcpwrap_service) { pa_socket_server *ss; @@ -358,6 +389,17 @@ fail: return NULL; } + +pa_socket_server *pa_socket_server_new_ipv6_adopt(pa_mainloop_api *m, int fd) { + pa_socket_server *s; + + pa_make_tcp_socket_low_delay(fd); + pa_assert_se(s = pa_socket_server_new(m, fd)); + + s->type = SOCKET_SERVER_IPV6; + + return s; +} #endif pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, bool fallback, const char *tcpwrap_service) { @@ -423,6 +465,9 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha static void socket_server_free(pa_socket_server*s) { pa_assert(s); + /* Only unlink the socket file when it is created by PulseAudio. When + * PulseAudio is socket activated by systemd, don't unlink the socket file + * managed by systemd. */ if (s->filename) { unlink(s->filename); pa_xfree(s->filename); @@ -538,14 +583,25 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) { case SOCKET_SERVER_UNIX: { char *id; - - if (!s->filename) - return NULL; + char *path; + struct sockaddr_un address; + socklen_t addr_len; + + path = s->filename; + if (!path) { + /* if the socket comes from socket activation, get the + * address now. */ + addr_len = sizeof(address); + if (getsockname(s->fd, &address, &addr_len) == 0) + path = address.sun_path; + else + return NULL; + } if (!(id = pa_machine_id())) return NULL; - pa_snprintf(c, l, "{%s}unix:%s", id, s->filename); + pa_snprintf(c, l, "{%s}unix:%s", id, path); pa_xfree(id); return c; } diff --git a/src/pulsecore/socket-server.h b/src/pulsecore/socket-server.h index a72bd9e..1bd9819 100644 --- a/src/pulsecore/socket-server.h +++ b/src/pulsecore/socket-server.h @@ -33,12 +33,15 @@ typedef struct pa_socket_server pa_socket_server; pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename); +pa_socket_server* pa_socket_server_new_unix_adopt(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, bool fallback, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv4_adopt(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, bool fallback, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, bool fallback, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, bool fallback, const char *tcpwrap_service); #ifdef HAVE_IPV6 pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, bool fallback, const char *tcpwrap_service); +pa_socket_server* pa_socket_server_new_ipv6_adopt(pa_mainloop_api *m, int fd); pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, bool fallback, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, bool fallback, const char *tcpwrap_service); pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, bool fallback, const char *tcpwrap_service); -- 1.8.5.3