]> code.delx.au - pulseaudio/blobdiff - src/modules/module-protocol-stub.c
Use <pulsecore/socket.h> instead of <sys/socket.h>
[pulseaudio] / src / modules / module-protocol-stub.c
index cfe661a38c4b0983b4b457f46e17f6d217248753..7ba540543b41356671fe3229c75c233814b920fc 100644 (file)
@@ -1,20 +1,21 @@
-/* $Id$ */
-
 /***
-  This file is part of polypaudio.
-  polypaudio is free software; you can redistribute it and/or modify
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
+
+  PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
-  polypaudio is distributed in the hope that it will be useful, but
+
+  PulseAudio is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.
+
   You should have received a copy of the GNU Lesser General Public License
-  along with polypaudio; if not, write to the Free Software
+  along with PulseAudio; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA.
 ***/
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
-#include <assert.h>
 #include <unistd.h>
 #include <limits.h>
 
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
 #include <netinet/in.h>
 #endif
 
-#include "../polypcore/winsock.h"
+#include <pulse/xmalloc.h>
 
-#include <polyp/xmalloc.h>
-
-#include <polypcore/module.h>
-#include <polypcore/socket-server.h>
-#include <polypcore/socket-util.h>
-#include <polypcore/core-util.h>
-#include <polypcore/modargs.h>
-#include <polypcore/log.h>
-#include <polypcore/native-common.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/module.h>
+#include <pulsecore/socket.h>
+#include <pulsecore/socket-server.h>
+#include <pulsecore/socket-util.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/native-common.h>
+#include <pulsecore/creds.h>
 
 #ifdef USE_TCP_SOCKETS
 #define SOCKET_DESCRIPTION "(TCP sockets)"
-#define SOCKET_USAGE "port=<TCP port number> loopback=<listen on loopback device only?> listen=<address to listen on>"
+#define SOCKET_USAGE "port=<TCP port number> listen=<address to listen on>"
 #else
 #define SOCKET_DESCRIPTION "(UNIX sockets)"
 #define SOCKET_USAGE "socket=<path to UNIX socket>"
 #endif
 
 #if defined(USE_PROTOCOL_SIMPLE)
-  #include <polypcore/protocol-simple.h>
-  #define protocol_new pa_protocol_simple_new
-  #define protocol_free pa_protocol_simple_free
-  #define TCPWRAP_SERVICE "polypaudio-simple"
-  #define IPV4_PORT 4711
-  #define UNIX_SOCKET "simple"
-  #define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record",
-  #if defined(USE_TCP_SOCKETS)
-    #include "module-simple-protocol-tcp-symdef.h"
-  #else
-    #include "module-simple-protocol-unix-symdef.h"
-  #endif
-  PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE("rate=<sample rate> format=<sample format> channels=<number of channels> sink=<sink to connect to> source=<source to connect to> playback=<enable playback?> record=<enable record?> "SOCKET_USAGE)
+#  include <pulsecore/protocol-simple.h>
+#  define TCPWRAP_SERVICE "pulseaudio-simple"
+#  define IPV4_PORT 4711
+#  define UNIX_SOCKET "simple"
+#  define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record",
+
+#  if defined(USE_TCP_SOCKETS)
+#    include "module-simple-protocol-tcp-symdef.h"
+#  else
+#    include "module-simple-protocol-unix-symdef.h"
+#  endif
+
+  PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION);
+  PA_MODULE_USAGE("rate=<sample rate> "
+                  "format=<sample format> "
+                  "channels=<number of channels> "
+                  "sink=<sink to connect to> "
+                  "source=<source to connect to> "
+                  "playback=<enable playback?> "
+                  "record=<enable record?> "
+                  SOCKET_USAGE);
 #elif defined(USE_PROTOCOL_CLI)
-  #include <polypcore/protocol-cli.h> 
-  #define protocol_new pa_protocol_cli_new
-  #define protocol_free pa_protocol_cli_free
-  #define TCPWRAP_SERVICE "polypaudio-cli"
-  #define IPV4_PORT 4712
-  #define UNIX_SOCKET "cli"
-  #define MODULE_ARGUMENTS 
-  #ifdef USE_TCP_SOCKETS
-    #include "module-cli-protocol-tcp-symdef.h"
-  #else
-    #include "module-cli-protocol-unix-symdef.h"
-  #endif
-  PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE(SOCKET_USAGE)
+#  include <pulsecore/protocol-cli.h>
+#  define TCPWRAP_SERVICE "pulseaudio-cli"
+#  define IPV4_PORT 4712
+#  define UNIX_SOCKET "cli"
+#  define MODULE_ARGUMENTS
+
+#  ifdef USE_TCP_SOCKETS
+#    include "module-cli-protocol-tcp-symdef.h"
+#  else
+#   include "module-cli-protocol-unix-symdef.h"
+#  endif
+
+  PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION);
+  PA_MODULE_USAGE(SOCKET_USAGE);
 #elif defined(USE_PROTOCOL_HTTP)
-  #include <polypcore/protocol-http.h>
-  #define protocol_new pa_protocol_http_new
-  #define protocol_free pa_protocol_http_free
-  #define TCPWRAP_SERVICE "polypaudio-http"
-  #define IPV4_PORT 4714
-  #define UNIX_SOCKET "http"
-  #define MODULE_ARGUMENTS 
-  #ifdef USE_TCP_SOCKETS
-    #include "module-http-protocol-tcp-symdef.h"
-  #else
-    #include "module-http-protocol-unix-symdef.h"
-  #endif
-  PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE(SOCKET_USAGE)
+#  include <pulsecore/protocol-http.h>
+#  define TCPWRAP_SERVICE "pulseaudio-http"
+#  define IPV4_PORT 4714
+#  define UNIX_SOCKET "http"
+#  define MODULE_ARGUMENTS
+
+#  ifdef USE_TCP_SOCKETS
+#    include "module-http-protocol-tcp-symdef.h"
+#  else
+#    include "module-http-protocol-unix-symdef.h"
+#  endif
+
+  PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION);
+  PA_MODULE_USAGE(SOCKET_USAGE);
 #elif defined(USE_PROTOCOL_NATIVE)
-  #include <polypcore/protocol-native.h>
-  #define protocol_new pa_protocol_native_new
-  #define protocol_free pa_protocol_native_free
-  #define TCPWRAP_SERVICE "polypaudio-native"
-  #define IPV4_PORT PA_NATIVE_DEFAULT_PORT
-  #define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET
-  #define MODULE_ARGUMENTS_COMMON "cookie", "auth-anonymous",
-  #ifdef USE_TCP_SOCKETS
-    #include "module-native-protocol-tcp-symdef.h"
-  #else
-    #include "module-native-protocol-unix-symdef.h"
-  #endif
-
-  #if defined(SCM_CREDENTIALS) && !defined(USE_TCP_SOCKETS)
-    #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group",
-    #define AUTH_USAGE "auth-group=<local group to allow access>"
-  #else
-    #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
-    #define AUTH_USAGE
-  #endif
-  
-  PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> cookie=<path to cookie file> "AUTH_USAGE SOCKET_USAGE)
+#  include <pulsecore/protocol-native.h>
+#  define TCPWRAP_SERVICE "pulseaudio-native"
+#  define IPV4_PORT PA_NATIVE_DEFAULT_PORT
+#  define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET
+#  define MODULE_ARGUMENTS_COMMON "cookie", "auth-cookie", "auth-cookie-enabled", "auth-anonymous",
+
+#  ifdef USE_TCP_SOCKETS
+#    include "module-native-protocol-tcp-symdef.h"
+#  else
+#    include "module-native-protocol-unix-symdef.h"
+#  endif
+
+#  if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS)
+#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable",
+#    define AUTH_USAGE "auth-group=<system group to allow access> auth-group-enable=<enable auth by UNIX group?> "
+#  elif defined(USE_TCP_SOCKETS)
+#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
+#    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
+#  else
+#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
+#    define AUTH_USAGE
+#    endif
+
+  PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION);
+  PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> "
+                  "auth-cookie=<path to cookie file> "
+                  "auth-cookie-enabled=<enable cookie authentification? "
+                  AUTH_USAGE
+                  SOCKET_USAGE);
 #elif defined(USE_PROTOCOL_ESOUND)
-  #include <polypcore/protocol-esound.h>
-  #include <polypcore/esound.h>
-  #define protocol_new pa_protocol_esound_new
-  #define protocol_free pa_protocol_esound_free
-  #define TCPWRAP_SERVICE "esound"
-  #define IPV4_PORT ESD_DEFAULT_PORT
-  #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME
-  #define MODULE_ARGUMENTS "sink", "source", "auth-anonymous", "cookie",
-  #ifdef USE_TCP_SOCKETS
-    #include "module-esound-protocol-tcp-symdef.h"
-  #else
-    #include "module-esound-protocol-unix-symdef.h"
-  #endif
-  PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION)
-  PA_MODULE_USAGE("sink=<sink to connect to> source=<source to connect to> auth-anonymous=<don't check for cookies?> cookie=<path to cookie file> "SOCKET_USAGE)
+#  include <pulsecore/protocol-esound.h>
+#  include <pulsecore/esound.h>
+#  define TCPWRAP_SERVICE "esound"
+#  define IPV4_PORT ESD_DEFAULT_PORT
+#  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled",
+
+#  ifdef USE_TCP_SOCKETS
+#    include "module-esound-protocol-tcp-symdef.h"
+#  else
+#    include "module-esound-protocol-unix-symdef.h"
+#  endif
+
+#  if defined(USE_TCP_SOCKETS)
+#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
+#    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
+#  else
+#    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
+#    define AUTH_USAGE
+#  endif
+
+  PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION);
+  PA_MODULE_USAGE("sink=<sink to connect to> "
+                  "source=<source to connect to> "
+                  "auth-anonymous=<don't verify cookies?> "
+                  "auth-cookie=<path to cookie file> "
+                  "auth-cookie-enabled=<enable cookie authentification? "
+                  AUTH_USAGE
+                  SOCKET_USAGE);
 #else
-  #error "Broken build system" 
+#  error "Broken build system"
 #endif
 
-PA_MODULE_AUTHOR("Lennart Poettering")
-PA_MODULE_VERSION(PACKAGE_VERSION)
+PA_MODULE_LOAD_ONCE(FALSE);
+PA_MODULE_AUTHOR("Lennart Poettering");
+PA_MODULE_VERSION(PACKAGE_VERSION);
 
 static const char* const valid_modargs[] = {
     MODULE_ARGUMENTS
 #if defined(USE_TCP_SOCKETS)
     "port",
-    "loopback",
     "listen",
 #else
     "socket",
@@ -165,176 +189,332 @@ static const char* const valid_modargs[] = {
 };
 
 struct userdata {
+    pa_module *module;
+
+#if defined(USE_PROTOCOL_SIMPLE)
+    pa_simple_protocol *simple_protocol;
+    pa_simple_options *simple_options;
+#elif defined(USE_PROTOCOL_CLI)
+    pa_cli_protocol *cli_protocol;
+#elif defined(USE_PROTOCOL_HTTP)
+    pa_http_protocol *http_protocol;
+#elif defined(USE_PROTOCOL_NATIVE)
+    pa_native_protocol *native_protocol;
+    pa_native_options *native_options;
+#else
+    pa_esound_protocol *esound_protocol;
+    pa_esound_options *esound_options;
+#endif
+
 #if defined(USE_TCP_SOCKETS)
-    void *protocol_ipv4;
-    void *protocol_ipv6;
+    pa_socket_server *socket_server_ipv4;
+#  ifdef HAVE_IPV6
+    pa_socket_server *socket_server_ipv6;
+#  endif
 #else
-    void *protocol_unix;
+    pa_socket_server *socket_server_unix;
     char *socket_path;
 #endif
 };
 
-int pa__init(pa_core *c, pa_module*m) {
-    pa_modargs *ma = NULL;
-    int ret = -1;
+static void socket_server_on_connection_cb(pa_socket_server*s, pa_iochannel *io, void *userdata) {
+    struct userdata *u = userdata;
 
+    pa_assert(s);
+    pa_assert(io);
+    pa_assert(u);
+
+#if defined(USE_PROTOCOL_SIMPLE)
+    pa_simple_protocol_connect(u->simple_protocol, io, u->simple_options);
+#elif defined(USE_PROTOCOL_CLI)
+    pa_cli_protocol_connect(u->cli_protocol, io, u->module);
+#elif defined(USE_PROTOCOL_HTTP)
+    pa_http_protocol_connect(u->http_protocol, io, u->module);
+#elif defined(USE_PROTOCOL_NATIVE)
+    pa_native_protocol_connect(u->native_protocol, io, u->native_options);
+#else
+    pa_esound_protocol_connect(u->esound_protocol, io, u->esound_options);
+#endif
+}
+
+int pa__init(pa_module*m) {
+    pa_modargs *ma = NULL;
     struct userdata *u = NULL;
 
 #if defined(USE_TCP_SOCKETS)
-    pa_socket_server *s_ipv4 = NULL, *s_ipv6 = NULL;
-    int loopback = 1;
     uint32_t port = IPV4_PORT;
+    pa_bool_t port_fallback = TRUE;
     const char *listen_on;
 #else
-    pa_socket_server *s;
     int r;
-    const char *v;
-    char tmp[PATH_MAX];
 #endif
 
-    assert(c && m);
+#if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP)
+    char t[256];
+#endif
+
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
-        pa_log(__FILE__": Failed to parse module arguments");
-        goto finish;
+        pa_log("Failed to parse module arguments");
+        goto fail;
     }
 
-    u = pa_xnew0(struct userdata, 1);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->module = m;
 
-#if defined(USE_TCP_SOCKETS)
-    if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) {
-        pa_log(__FILE__": loopback= expects a boolean argument.");
+#if defined(USE_PROTOCOL_SIMPLE)
+    u->simple_protocol = pa_simple_protocol_get(m->core);
+
+    u->simple_options = pa_simple_options_new();
+    if (pa_simple_options_parse(u->simple_options, m->core, ma) < 0)
         goto fail;
-    }
+    u->simple_options->module = m;
+#elif defined(USE_PROTOCOL_CLI)
+    u->cli_protocol = pa_cli_protocol_get(m->core);
+#elif defined(USE_PROTOCOL_HTTP)
+    u->http_protocol = pa_http_protocol_get(m->core);
+#elif defined(USE_PROTOCOL_NATIVE)
+    u->native_protocol = pa_native_protocol_get(m->core);
+
+    u->native_options = pa_native_options_new();
+    if (pa_native_options_parse(u->native_options, m->core, ma) < 0)
+        goto fail;
+    u->native_options->module = m;
+#else
+    u->esound_protocol = pa_esound_protocol_get(m->core);
+
+    u->esound_options = pa_esound_options_new();
+    if (pa_esound_options_parse(u->esound_options, m->core, ma) < 0)
+        goto fail;
+    u->esound_options->module = m;
+#endif
+
+#if defined(USE_TCP_SOCKETS)
+
+    if (pa_in_system_mode() || pa_modargs_get_value(ma, "port", NULL))
+        port_fallback = FALSE;
 
     if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) {
-        pa_log(__FILE__": port= expects a numerical argument between 1 and 65535.");
+        pa_log("port= expects a numerical argument between 1 and 65535.");
         goto fail;
     }
 
     listen_on = pa_modargs_get_value(ma, "listen", NULL);
 
     if (listen_on) {
-        s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE);
-        s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE);
-    } else if (loopback) {
-        s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE);
-        s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE);
+#  ifdef HAVE_IPV6
+        u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
+#  endif
+        u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
     } else {
-        s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE);
-        s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE);
+#  ifdef HAVE_IPV6
+        u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
+#  endif
+        u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
     }
 
-    if (!s_ipv4 && !s_ipv6)
+#  ifdef HAVE_IPV6
+    if (!u->socket_server_ipv4 && !u->socket_server_ipv6)
+#  else
+    if (!u->socket_server_ipv4)
+#  endif
         goto fail;
 
-    if (s_ipv4)
-        if (!(u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma)))
-            pa_socket_server_unref(s_ipv4);
+    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 (s_ipv6)
-        if (!(u->protocol_ipv6 = protocol_new(c, s_ipv6, m, ma)))
-            pa_socket_server_unref(s_ipv6);
+#  if defined(USE_PROTOCOL_ESOUND)
 
-    if (!u->protocol_ipv4 && !u->protocol_ipv6)
-        goto fail;
+#    if defined(USE_PER_USER_ESOUND_SOCKET)
+    u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid());
+#    else
+    u->socket_path = pa_xstrdup("/tmp/.esd/socket");
+#    endif
 
-#else
-    v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET);
-    pa_runtime_path(v, tmp, sizeof(tmp));
-    u->socket_path = pa_xstrdup(tmp);
+    /* This socket doesn't reside in our own runtime dir but in
+     * /tmp/.esd/, hence we have to create the dir first */
 
-    if (pa_make_secure_parent_dir(tmp) < 0) {
-        pa_log(__FILE__": Failed to create secure socket directory.");
+    if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755U : 0700U, (uid_t)-1, (gid_t)-1) < 0) {
+        pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno));
         goto fail;
     }
 
-    if ((r = pa_unix_socket_remove_stale(tmp)) < 0) {
-        pa_log(__FILE__": Failed to remove stale UNIX socket '%s': %s", tmp, strerror(errno));
+#  else
+    if (!(u->socket_path = pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET)))) {
+        pa_log("Failed to generate socket path.");
         goto fail;
     }
-    
-    if (r)
-        pa_log(__FILE__": Removed stale UNIX socket '%s'.", tmp);
-    
-    if (!(s = pa_socket_server_new_unix(c->mainloop, tmp)))
+#  endif
+
+    if ((r = pa_unix_socket_remove_stale(u->socket_path)) < 0) {
+        pa_log("Failed to remove stale UNIX socket '%s': %s", u->socket_path, pa_cstrerror(errno));
         goto fail;
+    } else if (r > 0)
+        pa_log_info("Removed stale UNIX socket '%s'.", u->socket_path);
 
-    if (!(u->protocol_unix = protocol_new(c, s, m, ma)))
+    if (!(u->socket_server_unix = pa_socket_server_new_unix(m->core->mainloop, u->socket_path)))
         goto fail;
 
+    pa_socket_server_set_callback(u->socket_server_unix, socket_server_on_connection_cb, u);
+
 #endif
 
-    m->userdata = u;
+#if defined(USE_PROTOCOL_NATIVE)
+#  if defined(USE_TCP_SOCKETS)
+    if (u->socket_server_ipv4)
+        if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
+            pa_native_protocol_add_server_string(u->native_protocol, t);
+
+#    ifdef HAVE_IPV6
+    if (u->socket_server_ipv6)
+        if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
+            pa_native_protocol_add_server_string(u->native_protocol, t);
+#    endif
+#  else
+    if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
+        pa_native_protocol_add_server_string(u->native_protocol, t);
+
+#  endif
+#endif
 
-    ret = 0;
+#if defined(USE_PROTOCOL_HTTP)
+#if defined(USE_TCP_SOCKETS)
+    if (u->socket_server_ipv4)
+        if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
+            pa_http_protocol_add_server_string(u->http_protocol, t);
+
+#ifdef HAVE_IPV6
+    if (u->socket_server_ipv6)
+        if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
+            pa_http_protocol_add_server_string(u->http_protocol, t);
+#endif /* HAVE_IPV6 */
+#else /* USE_TCP_SOCKETS */
+    if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
+        pa_http_protocol_add_server_string(u->http_protocol, t);
+
+#endif /* USE_TCP_SOCKETS */
+#endif /* USE_PROTOCOL_HTTP */
 
-finish:
     if (ma)
         pa_modargs_free(ma);
 
-    return ret;
+    return 0;
 
 fail:
-    if (u) {
-#if defined(USE_TCP_SOCKETS)
-        if (u->protocol_ipv4)
-            protocol_free(u->protocol_ipv4);
-        if (u->protocol_ipv6)
-            protocol_free(u->protocol_ipv6);
-#else
-        if (u->protocol_unix)
-            protocol_free(u->protocol_unix);
 
-        if (u->socket_path)
-            pa_xfree(u->socket_path);
-#endif
+    if (ma)
+        pa_modargs_free(ma);
 
-        pa_xfree(u);
-    } else {
-#if defined(USE_TCP_SOCKETS)
-        if (s_ipv4)
-            pa_socket_server_unref(s_ipv4);
-        if (s_ipv6)
-            pa_socket_server_unref(s_ipv6);
-#else
-        if (s)
-            pa_socket_server_unref(s);
-#endif
-    }
+    pa__done(m);
 
-    goto finish;
+    return -1;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
+void pa__done(pa_module*m) {
     struct userdata *u;
-    
-    assert(c);
-    assert(m);
 
-    u = m->userdata;
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+#if defined(USE_PROTOCOL_SIMPLE)
+    if (u->simple_protocol) {
+        pa_simple_protocol_disconnect(u->simple_protocol, u->module);
+        pa_simple_protocol_unref(u->simple_protocol);
+    }
+    if (u->simple_options)
+        pa_simple_options_unref(u->simple_options);
+#elif defined(USE_PROTOCOL_CLI)
+    if (u->cli_protocol) {
+        pa_cli_protocol_disconnect(u->cli_protocol, u->module);
+        pa_cli_protocol_unref(u->cli_protocol);
+    }
+#elif defined(USE_PROTOCOL_HTTP)
+    if (u->http_protocol) {
+        char t[256];
+
+#if defined(USE_TCP_SOCKETS)
+        if (u->socket_server_ipv4)
+            if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
+                pa_http_protocol_remove_server_string(u->http_protocol, t);
+
+#ifdef HAVE_IPV6
+        if (u->socket_server_ipv6)
+            if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
+                pa_http_protocol_remove_server_string(u->http_protocol, t);
+#endif /* HAVE_IPV6 */
+#else /* USE_TCP_SOCKETS */
+        if (u->socket_server_unix)
+            if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
+                pa_http_protocol_remove_server_string(u->http_protocol, t);
+#endif /* USE_PROTOCOL_HTTP */
+
+        pa_http_protocol_disconnect(u->http_protocol, u->module);
+        pa_http_protocol_unref(u->http_protocol);
+    }
+#elif defined(USE_PROTOCOL_NATIVE)
+    if (u->native_protocol) {
+
+        char t[256];
+
+#  if defined(USE_TCP_SOCKETS)
+        if (u->socket_server_ipv4)
+            if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
+                pa_native_protocol_remove_server_string(u->native_protocol, t);
+
+#    ifdef HAVE_IPV6
+        if (u->socket_server_ipv6)
+            if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
+                pa_native_protocol_remove_server_string(u->native_protocol, t);
+#    endif
+#  else
+        if (u->socket_server_unix)
+            if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
+                pa_native_protocol_remove_server_string(u->native_protocol, t);
+#  endif
+
+        pa_native_protocol_disconnect(u->native_protocol, u->module);
+        pa_native_protocol_unref(u->native_protocol);
+    }
+    if (u->native_options)
+        pa_native_options_unref(u->native_options);
+#else
+    if (u->esound_protocol) {
+        pa_esound_protocol_disconnect(u->esound_protocol, u->module);
+        pa_esound_protocol_unref(u->esound_protocol);
+    }
+    if (u->esound_options)
+        pa_esound_options_unref(u->esound_options);
+#endif
 
 #if defined(USE_TCP_SOCKETS)
-    if (u->protocol_ipv4)
-        protocol_free(u->protocol_ipv4);
-    if (u->protocol_ipv6)
-        protocol_free(u->protocol_ipv6);
+    if (u->socket_server_ipv4)
+        pa_socket_server_unref(u->socket_server_ipv4);
+#  ifdef HAVE_IPV6
+    if (u->socket_server_ipv6)
+        pa_socket_server_unref(u->socket_server_ipv6);
+#  endif
 #else
-    if (u->protocol_unix)
-        protocol_free(u->protocol_unix);
+    if (u->socket_server_unix)
+        pa_socket_server_unref(u->socket_server_unix);
 
+# if defined(USE_PROTOCOL_ESOUND) && !defined(USE_PER_USER_ESOUND_SOCKET)
     if (u->socket_path) {
-        char *p;
-        
-        if ((p = pa_parent_dir(u->socket_path))) {
-            if (rmdir(p) < 0 && errno != ENOENT && errno != ENOTEMPTY)
-                pa_log(__FILE__": Failed to remove %s: %s.", u->socket_path, strerror(errno));
-
-            pa_xfree(p);
-        }
-
-        pa_xfree(u->socket_path);
+        char *p = pa_parent_dir(u->socket_path);
+        rmdir(p);
+        pa_xfree(p);
     }
+# endif
+
+    pa_xfree(u->socket_path);
 #endif
 
     pa_xfree(u);