]> code.delx.au - pulseaudio/commitdiff
Trying to listen on an IPv6 socket by default and only do IPv4 if that fails
authorPierre Ossman <ossman@cendio.se>
Tue, 7 Mar 2006 16:02:34 +0000 (16:02 +0000)
committerPierre Ossman <ossman@cendio.se>
Tue, 7 Mar 2006 16:02:34 +0000 (16:02 +0000)
(which it doesn't most of the time) is terribly confusing. What the user
most likely wants is for it to listen to both IPv4 and IPv6 and gracefully
continue if only of them succeed.

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@633 fefdeb5f-60dc-0310-8127-8f9354f1896f

src/modules/module-protocol-stub.c
src/polypcore/socket-server.c
src/polypcore/socket-server.h

index b02b968858e56f5bae8afc1c5ec8db4643455180..71e17cbcff359e5c7ad6a654576fd9e5f4c8f33f 100644 (file)
@@ -49,6 +49,7 @@
 #include <polypcore/modargs.h>
 #include <polypcore/log.h>
 #include <polypcore/native-common.h>
+#include <polypcore/xmalloc.h>
 
 #ifdef USE_TCP_SOCKETS
 #define SOCKET_DESCRIPTION "(TCP sockets)"
@@ -162,41 +163,71 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) {
-    pa_socket_server *s;
+struct userdata {
+#if defined(USE_TCP_SOCKETS)
+    void *protocol_ipv4;
+    void *protocol_ipv6;
+#else
+    void *protocol_unix;
+#endif
+};
+
+int pa__init(pa_core *c, pa_module*m) {
+    pa_modargs *ma = NULL;
+    int ret = -1;
+
+    struct userdata *u = NULL;
+
 #if defined(USE_TCP_SOCKETS)
+    pa_socket_server *s_ipv4 = NULL;
+    pa_socket_server *s_ipv6 = NULL;
     int loopback = 1;
     uint32_t port = IPV4_PORT;
     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_TCP_SOCKETS)
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log(__FILE__": Failed to parse module arguments");
+        goto finish;
+    }
 
     if (pa_modargs_get_value_boolean(ma, "loopback", &loopback) < 0) {
         pa_log(__FILE__": loopback= expects a boolean argument.");
-        return NULL;
+        goto fail;
     }
 
     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.");
-        return NULL;
+        goto fail;
     }
 
     listen_on = pa_modargs_get_value(ma, "listen", NULL);
 
     if (listen_on) {
-        if (!(s = pa_socket_server_new_ip_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE)))
-            return NULL;
+        s_ipv4 = pa_socket_server_new_ipv4_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE);
+        s_ipv6 = pa_socket_server_new_ipv6_string(c->mainloop, listen_on, port, TCPWRAP_SERVICE);
+        if (!s_ipv4 && !s_ipv6)
+            goto fail;
     } else if (loopback) {
-        if (!(s = pa_socket_server_new_ip_loopback(c->mainloop, port, TCPWRAP_SERVICE)))
-            return NULL;
+        s_ipv4 = pa_socket_server_new_ipv4_loopback(c->mainloop, port, TCPWRAP_SERVICE);
+        s_ipv6 = pa_socket_server_new_ipv6_loopback(c->mainloop, port, TCPWRAP_SERVICE);
+        if (!s_ipv4 && !s_ipv6)
+            goto fail;
     } else {
-        if (!(s = pa_socket_server_new_ip_any(c->mainloop, port, TCPWRAP_SERVICE)))
-            return NULL;
+        s_ipv4 = pa_socket_server_new_ipv4_any(c->mainloop, port, TCPWRAP_SERVICE);
+        s_ipv6 = pa_socket_server_new_ipv6_any(c->mainloop, port, TCPWRAP_SERVICE);
+        if (!s_ipv4 && !s_ipv6)
+            goto fail;
     }
-    
 #else
-    int r;
-    const char *v;
-    char tmp[PATH_MAX];
-
     v = pa_modargs_get_value(ma, "socket", UNIX_SOCKET);
     assert(v);
 
@@ -204,43 +235,43 @@ static pa_socket_server *create_socket_server(pa_core *c, pa_modargs *ma) {
 
     if (pa_make_secure_parent_dir(tmp) < 0) {
         pa_log(__FILE__": Failed to create secure socket directory.");
-        return NULL;
+        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));
-        return NULL;
+        goto fail;
     }
     
     if (r)
         pa_log(__FILE__": Removed stale UNIX socket '%s'.", tmp);
     
     if (!(s = pa_socket_server_new_unix(c->mainloop, tmp)))
-        return NULL;
-    
+        goto fail;
 #endif
-    return s;
-}
 
-int pa__init(pa_core *c, pa_module*m) {
-    pa_socket_server *s;
-    pa_modargs *ma = NULL;
-    int ret = -1;
-    assert(c && m);
+    u = pa_xmalloc0(sizeof(struct userdata));
 
-    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
-        pa_log(__FILE__": Failed to parse module arguments");
-        goto finish;
+#if defined(USE_TCP_SOCKETS)
+    if (s_ipv4) {
+        u->protocol_ipv4 = protocol_new(c, s_ipv4, m, ma);
+        if (!u->protocol_ipv4)
+            pa_socket_server_unref(s_ipv4);
     }
 
-    if (!(s = create_socket_server(c, ma)))
-        goto finish;
-
-    if (!(m->userdata = protocol_new(c, s, m, ma))) {
-        pa_socket_server_unref(s);
-        goto finish;
+    if (s_ipv6) {
+        u->protocol_ipv6 = protocol_new(c, s_ipv4, m, ma);
+        if (!u->protocol_ipv6)
+            pa_socket_server_unref(s_ipv6);
     }
 
+    if (!u->protocol_ipv4 && !u->protocol_ipv6)
+        goto fail;
+#else
+    if (!(u->protocol_unix = protocol_new(c, s, m, ma)))
+        goto fail;
+#endif
+
     ret = 0;
 
 finish:
@@ -248,9 +279,36 @@ finish:
         pa_modargs_free(ma);
 
     return ret;
+
+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);
+#endif
+        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
+    }
+
+    goto finish;
 }
 
 void pa__done(pa_core *c, pa_module*m) {
+    struct userdata *u;
     assert(c && m);
 
 #if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS)
@@ -260,5 +318,18 @@ void pa__done(pa_core *c, pa_module*m) {
                pa_log("%s: Failed to remove %s : %s.", __FILE__, ESD_UNIX_SOCKET_DIR, strerror (errno));
 #endif
 
-    protocol_free(m->userdata);
+    u = m->userdata;
+    assert(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);
+#endif
+
+    pa_xfree(u);
 }
index d457d626a6eb5e805a4a3ae8d9325456ce0a4454..baa31e687cc4eb15b13483242560222744797367 100644 (file)
@@ -314,45 +314,56 @@ fail:
     return NULL;
 }
 
-pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
-    pa_socket_server *s;
-    
+pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
     assert(m);
     assert(port > 0);
-    
-    if (!(s = pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service)))
-        s = pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service);
 
-    return s;
+    return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service);
 }
 
-pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
-    pa_socket_server *s;
-    
+pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
+    assert(m);
+    assert(port > 0);
+
+    return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service);
+}
+
+pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
     assert(m);
     assert(port > 0);
     
-    if (!(s = pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service)))
-        s = pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service);
+    return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service);
+}
 
-    return s;
+pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
+    assert(m);
+    assert(port > 0);
+    
+    return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service);
 }
 
-pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
-    struct in6_addr ipv6;
+pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
     struct in_addr ipv4;
     
     assert(m);
     assert(name);
     assert(port > 0);
 
-    if (inet_pton(AF_INET6, name, &ipv6) > 0)
-        return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, tcpwrap_service);
-
     if (inet_pton(AF_INET, name, &ipv4) > 0)
         return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service);
 
-    pa_log_warn(__FILE__": failed to parse '%s'.", name);
+    return NULL;
+}
+
+pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
+    struct in6_addr ipv6;
+    
+    assert(m);
+    assert(name);
+    assert(port > 0);
+
+    if (inet_pton(AF_INET6, name, &ipv6) > 0)
+        return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, tcpwrap_service);
 
     return NULL;
 }
index 3babbc1402fd8411ae339e6107ae8f1805ef7731..cd3276ad809048a612085a3e799fb7e87f37955d 100644 (file)
@@ -34,9 +34,12 @@ 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_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service);
 pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, const char *tcpwrap_service);
-pa_socket_server* pa_socket_server_new_ip_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service);
-pa_socket_server* pa_socket_server_new_ip_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service);
-pa_socket_server* pa_socket_server_new_ip_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service);
+pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service);
+pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service);
+pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service);
+pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service);
+pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service);
+pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service);
 
 void pa_socket_server_unref(pa_socket_server*s);
 pa_socket_server* pa_socket_server_ref(pa_socket_server *s);