]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/socket-server.c
win32: Avoid some compiler warnings when cross-compiling for mingw32
[pulseaudio] / src / pulsecore / socket-server.c
index e660700cbe2ab249e2b6c97aa94f79374dfe1452..0b0b2a5ce0e2605249957df890132313b24da4b5 100644 (file)
@@ -32,9 +32,6 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
 #ifndef SUN_LEN
     ((size_t)(((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
 #endif
 #endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 
 #ifdef HAVE_LIBWRAP
 #include <tcpd.h>
-#endif
 
-#ifndef HAVE_INET_NTOP
-#include "inet_ntop.h"
+/* Solaris requires that the allow_severity and deny_severity variables be
+ * defined in the client program. */
+#ifdef __sun
+#include <syslog.h>
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
 #endif
 
-#ifndef HAVE_INET_PTON
-#include "inet_pton.h"
-#endif
-
-#include "winsock.h"
+#endif /* HAVE_LIBWRAP */
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
 
+#include <pulsecore/socket.h>
 #include <pulsecore/socket-util.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/refcnt.h>
+#include <pulsecore/arpa-inet.h>
 
 #include "socket-server.h"
 
@@ -86,7 +81,12 @@ struct pa_socket_server {
 
     pa_io_event *io_event;
     pa_mainloop_api *mainloop;
-    enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type;
+    enum {
+        SOCKET_SERVER_GENERIC,
+        SOCKET_SERVER_IPV4,
+        SOCKET_SERVER_UNIX,
+        SOCKET_SERVER_IPV6
+    } type;
 };
 
 static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
@@ -104,13 +104,11 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_ev
 
     pa_socket_server_ref(s);
 
-    if ((nfd = accept(fd, NULL, NULL)) < 0) {
+    if ((nfd = pa_accept_cloexec(fd, NULL, NULL)) < 0) {
         pa_log("accept(): %s", pa_cstrerror(errno));
         goto finish;
     }
 
-    pa_make_fd_cloexec(nfd);
-
     if (!s->on_connection) {
         pa_close(nfd);
         goto finish;
@@ -152,15 +150,11 @@ pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
     pa_assert(m);
     pa_assert(fd >= 0);
 
-    s = pa_xnew(pa_socket_server, 1);
+    s = pa_xnew0(pa_socket_server, 1);
     PA_REFCNT_INIT(s);
     s->fd = fd;
-    s->filename = NULL;
-    s->on_connection = NULL;
-    s->userdata = NULL;
-    s->tcpwrap_service = NULL;
-
     s->mainloop = m;
+
     pa_assert_se(s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s));
 
     s->type = SOCKET_SERVER_GENERIC;
@@ -186,13 +180,11 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
     pa_assert(m);
     pa_assert(filename);
 
-    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(fd);
-
     memset(&sa, 0, sizeof(sa));
     sa.sun_family = AF_UNIX;
     pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
@@ -237,7 +229,7 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
 
 #endif /* HAVE_SYS_UN_H */
 
-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_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     pa_socket_server *ss;
     int fd = -1;
     struct sockaddr_in sa;
@@ -246,15 +238,13 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address
     pa_assert(m);
     pa_assert(port);
 
-    if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_INET, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(PF_INET): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(fd);
-
 #ifdef SO_REUSEADDR
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0)
         pa_log("setsockopt(): %s", pa_cstrerror(errno));
 #endif
 
@@ -266,8 +256,19 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address
     sa.sin_addr.s_addr = htonl(address);
 
     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+
+        if (errno == EADDRINUSE && fallback) {
+            sa.sin_port = 0;
+
+            if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
+                goto good;
+        }
+
         pa_log("bind(): %s", pa_cstrerror(errno));
         goto fail;
+
+    good:
+        ;
     }
 
     if (listen(fd, 5) < 0) {
@@ -290,7 +291,7 @@ fail:
 }
 
 #ifdef HAVE_IPV6
-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_ipv6(pa_mainloop_api *m, const uint8_t address[16], uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     pa_socket_server *ss;
     int fd = -1;
     struct sockaddr_in6 sa;
@@ -299,22 +300,20 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
     pa_assert(m);
     pa_assert(port > 0);
 
-    if ((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) {
+    if ((fd = pa_socket_cloexec(PF_INET6, SOCK_STREAM, 0)) < 0) {
         pa_log("socket(PF_INET6): %s", pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_make_fd_cloexec(fd);
-
 #ifdef IPV6_V6ONLY
     on = 1;
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &on, sizeof(on)) < 0)
         pa_log("setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno));
 #endif
 
 #ifdef SO_REUSEADDR
     on = 1;
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0)
         pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno));
 #endif
 
@@ -326,8 +325,19 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
     memcpy(sa.sin6_addr.s6_addr, address, 16);
 
     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+
+        if (errno == EADDRINUSE && fallback) {
+            sa.sin6_port = 0;
+
+            if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
+                goto good;
+        }
+
         pa_log("bind(): %s", pa_cstrerror(errno));
         goto fail;
+
+    good:
+        ;
     }
 
     if (listen(fd, 5) < 0) {
@@ -350,39 +360,39 @@ fail:
 }
 #endif
 
-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_ipv4_loopback(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     pa_assert(m);
     pa_assert(port > 0);
 
-    return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, tcpwrap_service);
+    return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, fallback, tcpwrap_service);
 }
 
 #ifdef HAVE_IPV6
-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_ipv6_loopback(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     pa_assert(m);
     pa_assert(port > 0);
 
-    return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, tcpwrap_service);
+    return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, fallback, tcpwrap_service);
 }
 #endif
 
-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_ipv4_any(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     pa_assert(m);
     pa_assert(port > 0);
 
-    return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service);
+    return pa_socket_server_new_ipv4(m, INADDR_ANY, port, fallback, tcpwrap_service);
 }
 
 #ifdef HAVE_IPV6
-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_ipv6_any(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     pa_assert(m);
     pa_assert(port > 0);
 
-    return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service);
+    return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, fallback, tcpwrap_service);
 }
 #endif
 
-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_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     struct in_addr ipv4;
 
     pa_assert(m);
@@ -390,13 +400,13 @@ pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const cha
     pa_assert(port > 0);
 
     if (inet_pton(AF_INET, name, &ipv4) > 0)
-        return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, tcpwrap_service);
+        return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, fallback, tcpwrap_service);
 
     return NULL;
 }
 
 #ifdef HAVE_IPV6
-pa_socket_server* pa_socket_server_new_ipv6_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, pa_bool_t fallback, const char *tcpwrap_service) {
     struct in6_addr ipv6;
 
     pa_assert(m);
@@ -404,7 +414,7 @@ pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const cha
     pa_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 pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, fallback, tcpwrap_service);
 
     return NULL;
 }