[pulseaudio-discuss] [PATCH] Implement systemd socket activation

Giovanni Campagna scampa.giovanni at gmail.com
Mon Dec 30 05:48:28 PST 2013


From: Giovanni Campagna <gcampagna at src.gnome.org>

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.

Note: this was tested on Fedora 20, with systemd-208-9 as the system
manager and systemd v208-1386-g0faaadf as the user manager.
SELinux was turned to permissive (it blocks pulseaudio from talking
to rtkit) and the .desktop file from the regular package was removed
(causes a race condition at startup)

---
 configure.ac                       |  3 +-
 src/Makefile.am                    | 61 ++++++++++++++++++++++--------------
 src/daemon/main.c                  | 36 +++++++++++++++------
 src/modules/module-protocol-stub.c | 64 ++++++++++++++++++++++++++++++++++++++
 src/pulsecore/socket-server.c      | 43 +++++++++++++++++++++++++
 src/pulsecore/socket-server.h      |  3 ++
 6 files changed, 176 insertions(+), 34 deletions(-)

diff --git a/configure.ac b/configure.ac
index 64ab9fa..0fc37e7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1158,7 +1158,8 @@ AC_ARG_ENABLE([systemd],
     AS_HELP_STRING([--disable-systemd],[Disable optional systemd support]))
 
 AS_IF([test "x$enable_systemd" != "xno"],
-    [PKG_CHECK_MODULES(SYSTEMD, [ libsystemd-login ], HAVE_SYSTEMD=1, HAVE_SYSTEMD=0)],
+    [PKG_CHECK_MODULES(SYSTEMD, [ libsystemd-login ], HAVE_SYSTEMD=1, HAVE_SYSTEMD=0)
+    PKG_CHECK_MODULES(SYSTEMD_DAEMON, [ libsystemd-daemon ], HAVE_SYSTEMD_DAEMON=1, HAVE_SYSTEMD_DAEMON=0)],
     HAVE_SYSTEMD=0)
 
 AS_IF([test "x$enable_systemd" = "xyes" && test "x$HAVE_SYSTEMD" = "x0"],
diff --git a/src/Makefile.am b/src/Makefile.am
index c89cd6d..278a10e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -101,6 +101,8 @@ EXTRA_DIST = \
 		modules/module-defs.h.m4 \
 		daemon/pulseaudio.desktop.in \
 		daemon/pulseaudio-kde.desktop.in \
+                daemon/pulseaudio.service.in \
+	        daemon/pulseaudio.socket \
 		map-file \
 		daemon/pulseaudio-system.conf \
 		modules/echo-cancel/adrian-license.txt
@@ -117,13 +119,24 @@ dbuspolicy_DATA = \
 endif
 
 if HAVE_X11
+if !HAVE_SYSTEMD
 xdgautostart_in_files = \
 		daemon/pulseaudio.desktop.in \
 		daemon/pulseaudio-kde.desktop.in
 xdgautostart_DATA = $(xdgautostart_in_files:.desktop.in=.desktop)
 @INTLTOOL_DESKTOP_RULE@
 endif
+endif
 
+if HAVE_SYSTEMD
+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               #
@@ -149,8 +162,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- at PA_MAJORMINOR@.la libpulsecommon- at PA_MAJORMINOR@.la libpulse.la $(LIBLTDL) $(CAP_LIBS)
+pulseaudio_CFLAGS = $(AM_CFLAGS) $(CAP_CFLAGS) $(SYSTEMD_DAEMON_CFLAGS)
+pulseaudio_LDADD = $(AM_LDADD) libpulsecore- at PA_MAJORMINOR@.la libpulsecommon- at 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- at PA_MAJORMINOR@.la libpulsecommon- at PA_MAJORMINOR@.la libpulse.la $(PREOPEN_LIBS)
 
@@ -192,8 +205,10 @@ endif
 
 if HAVE_X11
 bin_PROGRAMS += pax11publish
+if !HAVE_SYSTEMD
 bin_SCRIPTS += start-pulseaudio-x11 start-pulseaudio-kde
 endif
+endif
 
 pacat_SOURCES = utils/pacat.c
 pacat_LDADD = $(AM_LDADD) libpulse.la libpulsecommon- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
@@ -1478,14 +1493,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
 
@@ -1494,26 +1509,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
 
@@ -1536,32 +1551,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_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 e01371e..6098277 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -58,6 +58,10 @@
 #include <dbus/dbus.h>
 #endif
 
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include <pulse/client-conf.h>
 #ifdef HAVE_X11
 #include <pulse/client-conf-x11.h>
@@ -405,6 +409,7 @@ int main(int argc, char *argv[]) {
     bool valid_pid_file = false;
     bool ltdl_init = false;
     int passed_fd = -1;
+    int systemd_fds = -1;
     const char *e;
 #ifdef HAVE_FORK
     int daemon_pipe[2] = { -1, -1 };
@@ -472,16 +477,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
+    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/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 3218a01..d8db913 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -32,6 +32,10 @@
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/core-error.h>
@@ -244,6 +248,9 @@ int pa__init(pa_module*m) {
 #else
     int r;
 #endif
+#if defined(HAVE_SYSTEMD)
+    int inherited_fds;
+#endif
 
 #if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP)
     char t[256];
@@ -286,6 +293,61 @@ int pa__init(pa_module*m) {
     u->esound_options->module = m;
 #endif
 
+#if defined(HAVE_SYSTEMD)
+    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.");
+            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 +424,8 @@ int pa__init(pa_module*m) {
 
 #endif
 
+success:
+
 #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..3d1d533 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -221,12 +221,33 @@ fail:
     return NULL;
 }
 
+pa_socket_server *pa_socket_server_new_unix_adopt(pa_mainloop_api *m, int fd) {
+    pa_socket_server *s;
+    struct sockaddr_un address;
+    socklen_t addr_len;
+
+    pa_make_socket_low_delay(fd);
+    pa_assert_se(s = pa_socket_server_new(m, fd));
+
+    addr_len = sizeof address;
+    if (getsockname(fd, &address, &addr_len) == 0)
+        s->filename = pa_xstrdup(address.sun_path);
+
+    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 +311,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 +390,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) {
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.4.2



More information about the pulseaudio-discuss mailing list