LCOV - code coverage report
Current view: top level - pulsecore - socket-server.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 0 219 0.0 %
Date: 2012-07-17 Functions: 0 16 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 202 0.0 %

           Branch data     Line data    Source code
       1                 :            : /***
       2                 :            :   This file is part of PulseAudio.
       3                 :            : 
       4                 :            :   Copyright 2004-2006 Lennart Poettering
       5                 :            :   Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
       6                 :            : 
       7                 :            :   PulseAudio is free software; you can redistribute it and/or modify
       8                 :            :   it under the terms of the GNU Lesser General Public License as published
       9                 :            :   by the Free Software Foundation; either version 2.1 of the License,
      10                 :            :   or (at your option) any later version.
      11                 :            : 
      12                 :            :   PulseAudio is distributed in the hope that it will be useful, but
      13                 :            :   WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      15                 :            :   General Public License for more details.
      16                 :            : 
      17                 :            :   You should have received a copy of the GNU Lesser General Public License
      18                 :            :   along with PulseAudio; if not, write to the Free Software
      19                 :            :   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      20                 :            :   USA.
      21                 :            : ***/
      22                 :            : 
      23                 :            : #ifdef HAVE_CONFIG_H
      24                 :            : #include <config.h>
      25                 :            : #endif
      26                 :            : 
      27                 :            : #include <stdlib.h>
      28                 :            : #include <errno.h>
      29                 :            : #include <string.h>
      30                 :            : #include <sys/types.h>
      31                 :            : #include <stdio.h>
      32                 :            : #include <unistd.h>
      33                 :            : #include <sys/stat.h>
      34                 :            : 
      35                 :            : #ifdef HAVE_SYS_UN_H
      36                 :            : #include <sys/un.h>
      37                 :            : #ifndef SUN_LEN
      38                 :            : #define SUN_LEN(ptr) \
      39                 :            :     ((size_t)(((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
      40                 :            : #endif
      41                 :            : #endif
      42                 :            : #ifdef HAVE_NETINET_IN_H
      43                 :            : #include <netinet/in.h>
      44                 :            : #endif
      45                 :            : 
      46                 :            : #ifdef HAVE_LIBWRAP
      47                 :            : #include <tcpd.h>
      48                 :            : 
      49                 :            : /* Solaris requires that the allow_severity and deny_severity variables be
      50                 :            :  * defined in the client program. */
      51                 :            : #ifdef __sun
      52                 :            : #include <syslog.h>
      53                 :            : int allow_severity = LOG_INFO;
      54                 :            : int deny_severity = LOG_WARNING;
      55                 :            : #endif
      56                 :            : 
      57                 :            : #endif /* HAVE_LIBWRAP */
      58                 :            : 
      59                 :            : #include <pulse/xmalloc.h>
      60                 :            : #include <pulse/util.h>
      61                 :            : 
      62                 :            : #include <pulsecore/socket.h>
      63                 :            : #include <pulsecore/socket-util.h>
      64                 :            : #include <pulsecore/core-util.h>
      65                 :            : #include <pulsecore/log.h>
      66                 :            : #include <pulsecore/macro.h>
      67                 :            : #include <pulsecore/core-error.h>
      68                 :            : #include <pulsecore/refcnt.h>
      69                 :            : #include <pulsecore/arpa-inet.h>
      70                 :            : 
      71                 :            : #include "socket-server.h"
      72                 :            : 
      73                 :            : struct pa_socket_server {
      74                 :            :     PA_REFCNT_DECLARE;
      75                 :            :     int fd;
      76                 :            :     char *filename;
      77                 :            :     char *tcpwrap_service;
      78                 :            : 
      79                 :            :     pa_socket_server_on_connection_cb_t on_connection;
      80                 :            :     void *userdata;
      81                 :            : 
      82                 :            :     pa_io_event *io_event;
      83                 :            :     pa_mainloop_api *mainloop;
      84                 :            :     enum {
      85                 :            :         SOCKET_SERVER_GENERIC,
      86                 :            :         SOCKET_SERVER_IPV4,
      87                 :            :         SOCKET_SERVER_UNIX,
      88                 :            :         SOCKET_SERVER_IPV6
      89                 :            :     } type;
      90                 :            : };
      91                 :            : 
      92                 :          0 : static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
      93                 :          0 :     pa_socket_server *s = userdata;
      94                 :            :     pa_iochannel *io;
      95                 :            :     int nfd;
      96                 :            : 
      97         [ #  # ]:          0 :     pa_assert(s);
      98         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
      99         [ #  # ]:          0 :     pa_assert(s->mainloop == mainloop);
     100         [ #  # ]:          0 :     pa_assert(s->io_event == e);
     101         [ #  # ]:          0 :     pa_assert(e);
     102         [ #  # ]:          0 :     pa_assert(fd >= 0);
     103         [ #  # ]:          0 :     pa_assert(fd == s->fd);
     104                 :            : 
     105                 :          0 :     pa_socket_server_ref(s);
     106                 :            : 
     107         [ #  # ]:          0 :     if ((nfd = pa_accept_cloexec(fd, NULL, NULL)) < 0) {
     108                 :          0 :         pa_log("accept(): %s", pa_cstrerror(errno));
     109                 :          0 :         goto finish;
     110                 :            :     }
     111                 :            : 
     112         [ #  # ]:          0 :     if (!s->on_connection) {
     113                 :          0 :         pa_close(nfd);
     114                 :          0 :         goto finish;
     115                 :            :     }
     116                 :            : 
     117                 :            : #ifdef HAVE_LIBWRAP
     118                 :            : 
     119         [ #  # ]:          0 :     if (s->tcpwrap_service) {
     120                 :            :         struct request_info req;
     121                 :            : 
     122                 :          0 :         request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL);
     123                 :          0 :         fromhost(&req);
     124         [ #  # ]:          0 :         if (!hosts_access(&req)) {
     125                 :          0 :             pa_log_warn("TCP connection refused by tcpwrap.");
     126                 :          0 :             pa_close(nfd);
     127                 :          0 :             goto finish;
     128                 :            :         }
     129                 :            : 
     130                 :          0 :         pa_log_info("TCP connection accepted by tcpwrap.");
     131                 :            :     }
     132                 :            : #endif
     133                 :            : 
     134                 :            :     /* There should be a check for socket type here */
     135         [ #  # ]:          0 :     if (s->type == SOCKET_SERVER_IPV4)
     136                 :          0 :         pa_make_tcp_socket_low_delay(fd);
     137                 :            :     else
     138                 :          0 :         pa_make_socket_low_delay(fd);
     139                 :            : 
     140         [ #  # ]:          0 :     pa_assert_se(io = pa_iochannel_new(s->mainloop, nfd, nfd));
     141                 :          0 :     s->on_connection(s, io, s->userdata);
     142                 :            : 
     143                 :            : finish:
     144                 :          0 :     pa_socket_server_unref(s);
     145                 :          0 : }
     146                 :            : 
     147                 :          0 : pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
     148                 :            :     pa_socket_server *s;
     149                 :            : 
     150         [ #  # ]:          0 :     pa_assert(m);
     151         [ #  # ]:          0 :     pa_assert(fd >= 0);
     152                 :            : 
     153                 :          0 :     s = pa_xnew0(pa_socket_server, 1);
     154                 :          0 :     PA_REFCNT_INIT(s);
     155                 :          0 :     s->fd = fd;
     156                 :          0 :     s->mainloop = m;
     157                 :            : 
     158         [ #  # ]:          0 :     pa_assert_se(s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s));
     159                 :            : 
     160                 :          0 :     s->type = SOCKET_SERVER_GENERIC;
     161                 :            : 
     162                 :          0 :     return s;
     163                 :            : }
     164                 :            : 
     165                 :          0 : pa_socket_server* pa_socket_server_ref(pa_socket_server *s) {
     166         [ #  # ]:          0 :     pa_assert(s);
     167         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     168                 :            : 
     169                 :          0 :     PA_REFCNT_INC(s);
     170                 :          0 :     return s;
     171                 :            : }
     172                 :            : 
     173                 :            : #ifdef HAVE_SYS_UN_H
     174                 :            : 
     175                 :          0 : pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) {
     176                 :          0 :     int fd = -1;
     177                 :            :     struct sockaddr_un sa;
     178                 :            :     pa_socket_server *s;
     179                 :            : 
     180         [ #  # ]:          0 :     pa_assert(m);
     181         [ #  # ]:          0 :     pa_assert(filename);
     182                 :            : 
     183         [ #  # ]:          0 :     if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
     184                 :          0 :         pa_log("socket(): %s", pa_cstrerror(errno));
     185                 :          0 :         goto fail;
     186                 :            :     }
     187                 :            : 
     188                 :            :     memset(&sa, 0, sizeof(sa));
     189                 :          0 :     sa.sun_family = AF_UNIX;
     190                 :          0 :     pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
     191                 :            : 
     192                 :          0 :     pa_make_socket_low_delay(fd);
     193                 :            : 
     194         [ #  # ]:          0 :     if (bind(fd, (struct sockaddr*) &sa, (socklen_t) SUN_LEN(&sa)) < 0) {
     195                 :          0 :         pa_log("bind(): %s", pa_cstrerror(errno));
     196                 :          0 :         goto fail;
     197                 :            :     }
     198                 :            : 
     199                 :            :     /* Allow access from all clients. Sockets like this one should
     200                 :            :      * always be put inside a directory with proper access rights,
     201                 :            :      * because not all OS check the access rights on the socket
     202                 :            :      * inodes. */
     203                 :          0 :     chmod(filename, 0777);
     204                 :            : 
     205         [ #  # ]:          0 :     if (listen(fd, 5) < 0) {
     206                 :          0 :         pa_log("listen(): %s", pa_cstrerror(errno));
     207                 :          0 :         goto fail;
     208                 :            :     }
     209                 :            : 
     210         [ #  # ]:          0 :     pa_assert_se(s = pa_socket_server_new(m, fd));
     211                 :            : 
     212                 :          0 :     s->filename = pa_xstrdup(filename);
     213                 :          0 :     s->type = SOCKET_SERVER_UNIX;
     214                 :            : 
     215                 :          0 :     return s;
     216                 :            : 
     217                 :            : fail:
     218         [ #  # ]:          0 :     if (fd >= 0)
     219                 :          0 :         pa_close(fd);
     220                 :            : 
     221                 :            :     return NULL;
     222                 :            : }
     223                 :            : 
     224                 :            : #else /* HAVE_SYS_UN_H */
     225                 :            : 
     226                 :            : pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) {
     227                 :            :     return NULL;
     228                 :            : }
     229                 :            : 
     230                 :            : #endif /* HAVE_SYS_UN_H */
     231                 :            : 
     232                 :          0 : 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) {
     233                 :            :     pa_socket_server *ss;
     234                 :          0 :     int fd = -1;
     235                 :            :     struct sockaddr_in sa;
     236                 :          0 :     int on = 1;
     237                 :            : 
     238         [ #  # ]:          0 :     pa_assert(m);
     239         [ #  # ]:          0 :     pa_assert(port);
     240                 :            : 
     241         [ #  # ]:          0 :     if ((fd = pa_socket_cloexec(PF_INET, SOCK_STREAM, 0)) < 0) {
     242                 :          0 :         pa_log("socket(PF_INET): %s", pa_cstrerror(errno));
     243                 :          0 :         goto fail;
     244                 :            :     }
     245                 :            : 
     246                 :            : #ifdef SO_REUSEADDR
     247         [ #  # ]:          0 :     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0)
     248                 :          0 :         pa_log("setsockopt(): %s", pa_cstrerror(errno));
     249                 :            : #endif
     250                 :            : 
     251                 :          0 :     pa_make_tcp_socket_low_delay(fd);
     252                 :            : 
     253                 :            :     memset(&sa, 0, sizeof(sa));
     254                 :          0 :     sa.sin_family = AF_INET;
     255         [ #  # ]:          0 :     sa.sin_port = htons(port);
     256         [ #  # ]:          0 :     sa.sin_addr.s_addr = htonl(address);
     257                 :            : 
     258         [ #  # ]:          0 :     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
     259                 :            : 
     260 [ #  # ][ #  # ]:          0 :         if (errno == EADDRINUSE && fallback) {
     261                 :          0 :             sa.sin_port = 0;
     262                 :            : 
     263         [ #  # ]:          0 :             if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
     264                 :            :                 goto good;
     265                 :            :         }
     266                 :            : 
     267                 :          0 :         pa_log("bind(): %s", pa_cstrerror(errno));
     268                 :          0 :         goto fail;
     269                 :            : 
     270                 :            :     good:
     271                 :            :         ;
     272                 :            :     }
     273                 :            : 
     274         [ #  # ]:          0 :     if (listen(fd, 5) < 0) {
     275                 :          0 :         pa_log("listen(): %s", pa_cstrerror(errno));
     276                 :          0 :         goto fail;
     277                 :            :     }
     278                 :            : 
     279         [ #  # ]:          0 :     if ((ss = pa_socket_server_new(m, fd))) {
     280                 :          0 :         ss->type = SOCKET_SERVER_IPV4;
     281                 :          0 :         ss->tcpwrap_service = pa_xstrdup(tcpwrap_service);
     282                 :            :     }
     283                 :            : 
     284                 :            :     return ss;
     285                 :            : 
     286                 :            : fail:
     287         [ #  # ]:          0 :     if (fd >= 0)
     288                 :          0 :         pa_close(fd);
     289                 :            : 
     290                 :            :     return NULL;
     291                 :            : }
     292                 :            : 
     293                 :            : #ifdef HAVE_IPV6
     294                 :          0 : 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) {
     295                 :            :     pa_socket_server *ss;
     296                 :          0 :     int fd = -1;
     297                 :            :     struct sockaddr_in6 sa;
     298                 :            :     int on;
     299                 :            : 
     300         [ #  # ]:          0 :     pa_assert(m);
     301         [ #  # ]:          0 :     pa_assert(port > 0);
     302                 :            : 
     303         [ #  # ]:          0 :     if ((fd = pa_socket_cloexec(PF_INET6, SOCK_STREAM, 0)) < 0) {
     304                 :          0 :         pa_log("socket(PF_INET6): %s", pa_cstrerror(errno));
     305                 :          0 :         goto fail;
     306                 :            :     }
     307                 :            : 
     308                 :            : #ifdef IPV6_V6ONLY
     309                 :          0 :     on = 1;
     310         [ #  # ]:          0 :     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &on, sizeof(on)) < 0)
     311                 :          0 :         pa_log("setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno));
     312                 :            : #endif
     313                 :            : 
     314                 :            : #ifdef SO_REUSEADDR
     315                 :          0 :     on = 1;
     316         [ #  # ]:          0 :     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0)
     317                 :          0 :         pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno));
     318                 :            : #endif
     319                 :            : 
     320                 :          0 :     pa_make_tcp_socket_low_delay(fd);
     321                 :            : 
     322                 :            :     memset(&sa, 0, sizeof(sa));
     323                 :          0 :     sa.sin6_family = AF_INET6;
     324         [ #  # ]:          0 :     sa.sin6_port = htons(port);
     325                 :          0 :     memcpy(sa.sin6_addr.s6_addr, address, 16);
     326                 :            : 
     327         [ #  # ]:          0 :     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
     328                 :            : 
     329 [ #  # ][ #  # ]:          0 :         if (errno == EADDRINUSE && fallback) {
     330                 :          0 :             sa.sin6_port = 0;
     331                 :            : 
     332         [ #  # ]:          0 :             if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
     333                 :            :                 goto good;
     334                 :            :         }
     335                 :            : 
     336                 :          0 :         pa_log("bind(): %s", pa_cstrerror(errno));
     337                 :          0 :         goto fail;
     338                 :            : 
     339                 :            :     good:
     340                 :            :         ;
     341                 :            :     }
     342                 :            : 
     343         [ #  # ]:          0 :     if (listen(fd, 5) < 0) {
     344                 :          0 :         pa_log("listen(): %s", pa_cstrerror(errno));
     345                 :          0 :         goto fail;
     346                 :            :     }
     347                 :            : 
     348         [ #  # ]:          0 :     if ((ss = pa_socket_server_new(m, fd))) {
     349                 :          0 :         ss->type = SOCKET_SERVER_IPV6;
     350                 :          0 :         ss->tcpwrap_service = pa_xstrdup(tcpwrap_service);
     351                 :            :     }
     352                 :            : 
     353                 :            :     return ss;
     354                 :            : 
     355                 :            : fail:
     356         [ #  # ]:          0 :     if (fd >= 0)
     357                 :          0 :         pa_close(fd);
     358                 :            : 
     359                 :            :     return NULL;
     360                 :            : }
     361                 :            : #endif
     362                 :            : 
     363                 :          0 : pa_socket_server* pa_socket_server_new_ipv4_loopback(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     364         [ #  # ]:          0 :     pa_assert(m);
     365         [ #  # ]:          0 :     pa_assert(port > 0);
     366                 :            : 
     367                 :          0 :     return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, fallback, tcpwrap_service);
     368                 :            : }
     369                 :            : 
     370                 :            : #ifdef HAVE_IPV6
     371                 :          0 : pa_socket_server* pa_socket_server_new_ipv6_loopback(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     372         [ #  # ]:          0 :     pa_assert(m);
     373         [ #  # ]:          0 :     pa_assert(port > 0);
     374                 :            : 
     375                 :          0 :     return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, fallback, tcpwrap_service);
     376                 :            : }
     377                 :            : #endif
     378                 :            : 
     379                 :          0 : pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     380         [ #  # ]:          0 :     pa_assert(m);
     381         [ #  # ]:          0 :     pa_assert(port > 0);
     382                 :            : 
     383                 :          0 :     return pa_socket_server_new_ipv4(m, INADDR_ANY, port, fallback, tcpwrap_service);
     384                 :            : }
     385                 :            : 
     386                 :            : #ifdef HAVE_IPV6
     387                 :          0 : pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, pa_bool_t fallback, const char *tcpwrap_service) {
     388         [ #  # ]:          0 :     pa_assert(m);
     389         [ #  # ]:          0 :     pa_assert(port > 0);
     390                 :            : 
     391                 :          0 :     return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, fallback, tcpwrap_service);
     392                 :            : }
     393                 :            : #endif
     394                 :            : 
     395                 :          0 : 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) {
     396                 :            :     struct in_addr ipv4;
     397                 :            : 
     398         [ #  # ]:          0 :     pa_assert(m);
     399         [ #  # ]:          0 :     pa_assert(name);
     400         [ #  # ]:          0 :     pa_assert(port > 0);
     401                 :            : 
     402         [ #  # ]:          0 :     if (inet_pton(AF_INET, name, &ipv4) > 0)
     403         [ #  # ]:          0 :         return pa_socket_server_new_ipv4(m, ntohl(ipv4.s_addr), port, fallback, tcpwrap_service);
     404                 :            : 
     405                 :            :     return NULL;
     406                 :            : }
     407                 :            : 
     408                 :            : #ifdef HAVE_IPV6
     409                 :          0 : 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) {
     410                 :            :     struct in6_addr ipv6;
     411                 :            : 
     412         [ #  # ]:          0 :     pa_assert(m);
     413         [ #  # ]:          0 :     pa_assert(name);
     414         [ #  # ]:          0 :     pa_assert(port > 0);
     415                 :            : 
     416         [ #  # ]:          0 :     if (inet_pton(AF_INET6, name, &ipv6) > 0)
     417                 :          0 :         return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, fallback, tcpwrap_service);
     418                 :            : 
     419                 :            :     return NULL;
     420                 :            : }
     421                 :            : #endif
     422                 :            : 
     423                 :          0 : static void socket_server_free(pa_socket_server*s) {
     424         [ #  # ]:          0 :     pa_assert(s);
     425                 :            : 
     426         [ #  # ]:          0 :     if (s->filename) {
     427                 :          0 :         unlink(s->filename);
     428                 :          0 :         pa_xfree(s->filename);
     429                 :            :     }
     430                 :            : 
     431                 :          0 :     pa_close(s->fd);
     432                 :            : 
     433                 :          0 :     pa_xfree(s->tcpwrap_service);
     434                 :            : 
     435                 :          0 :     s->mainloop->io_free(s->io_event);
     436                 :          0 :     pa_xfree(s);
     437                 :          0 : }
     438                 :            : 
     439                 :          0 : void pa_socket_server_unref(pa_socket_server *s) {
     440         [ #  # ]:          0 :     pa_assert(s);
     441         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     442                 :            : 
     443         [ #  # ]:          0 :     if (PA_REFCNT_DEC(s) <= 0)
     444                 :          0 :         socket_server_free(s);
     445                 :          0 : }
     446                 :            : 
     447                 :          0 : void pa_socket_server_set_callback(pa_socket_server*s, pa_socket_server_on_connection_cb_t on_connection, void *userdata) {
     448         [ #  # ]:          0 :     pa_assert(s);
     449         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     450                 :            : 
     451                 :          0 :     s->on_connection = on_connection;
     452                 :          0 :     s->userdata = userdata;
     453                 :          0 : }
     454                 :            : 
     455                 :          0 : char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
     456         [ #  # ]:          0 :     pa_assert(s);
     457         [ #  # ]:          0 :     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     458         [ #  # ]:          0 :     pa_assert(c);
     459         [ #  # ]:          0 :     pa_assert(l > 0);
     460                 :            : 
     461   [ #  #  #  # ]:          0 :     switch (s->type) {
     462                 :            : #ifdef HAVE_IPV6
     463                 :            :         case SOCKET_SERVER_IPV6: {
     464                 :            :             struct sockaddr_in6 sa;
     465                 :          0 :             socklen_t sa_len = sizeof(sa);
     466                 :            : 
     467         [ #  # ]:          0 :             if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
     468                 :          0 :                 pa_log("getsockname(): %s", pa_cstrerror(errno));
     469                 :          0 :                 return NULL;
     470                 :            :             }
     471                 :            : 
     472         [ #  # ]:          0 :             if (memcmp(&in6addr_any, &sa.sin6_addr, sizeof(in6addr_any)) == 0) {
     473                 :            :                 char fqdn[256];
     474         [ #  # ]:          0 :                 if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
     475                 :            :                     return NULL;
     476                 :            : 
     477         [ #  # ]:          0 :                 pa_snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port));
     478                 :            : 
     479         [ #  # ]:          0 :             } else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) {
     480                 :            :                 char *id;
     481                 :            : 
     482         [ #  # ]:          0 :                 if (!(id = pa_machine_id()))
     483                 :            :                     return NULL;
     484                 :            : 
     485         [ #  # ]:          0 :                 pa_snprintf(c, l, "{%s}tcp6:localhost:%u", id, (unsigned) ntohs(sa.sin6_port));
     486                 :          0 :                 pa_xfree(id);
     487                 :            :             } else {
     488                 :            :                 char ip[INET6_ADDRSTRLEN];
     489                 :            : 
     490         [ #  # ]:          0 :                 if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) {
     491                 :          0 :                     pa_log("inet_ntop(): %s", pa_cstrerror(errno));
     492                 :          0 :                     return NULL;
     493                 :            :                 }
     494                 :            : 
     495         [ #  # ]:          0 :                 pa_snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port));
     496                 :            :             }
     497                 :            : 
     498                 :            :             return c;
     499                 :            :         }
     500                 :            : #endif
     501                 :            : 
     502                 :            :         case SOCKET_SERVER_IPV4: {
     503                 :            :             struct sockaddr_in sa;
     504                 :          0 :             socklen_t sa_len = sizeof(sa);
     505                 :            : 
     506         [ #  # ]:          0 :             if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
     507                 :          0 :                 pa_log("getsockname(): %s", pa_cstrerror(errno));
     508                 :          0 :                 return NULL;
     509                 :            :             }
     510                 :            : 
     511         [ #  # ]:          0 :             if (sa.sin_addr.s_addr == INADDR_ANY) {
     512                 :            :                 char fqdn[256];
     513         [ #  # ]:          0 :                 if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
     514                 :            :                     return NULL;
     515                 :            : 
     516         [ #  # ]:          0 :                 pa_snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port));
     517         [ #  # ]:          0 :             } else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) {
     518                 :            :                 char *id;
     519                 :            : 
     520         [ #  # ]:          0 :                 if (!(id = pa_machine_id()))
     521                 :            :                     return NULL;
     522                 :            : 
     523         [ #  # ]:          0 :                 pa_snprintf(c, l, "{%s}tcp:localhost:%u", id, (unsigned) ntohs(sa.sin_port));
     524                 :          0 :                 pa_xfree(id);
     525                 :            :             } else {
     526                 :            :                 char ip[INET_ADDRSTRLEN];
     527                 :            : 
     528         [ #  # ]:          0 :                 if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) {
     529                 :          0 :                     pa_log("inet_ntop(): %s", pa_cstrerror(errno));
     530                 :          0 :                     return NULL;
     531                 :            :                 }
     532                 :            : 
     533         [ #  # ]:          0 :                 pa_snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
     534                 :            :             }
     535                 :            : 
     536                 :            :             return c;
     537                 :            :         }
     538                 :            : 
     539                 :            :         case SOCKET_SERVER_UNIX: {
     540                 :            :             char *id;
     541                 :            : 
     542         [ #  # ]:          0 :             if (!s->filename)
     543                 :            :                 return NULL;
     544                 :            : 
     545         [ #  # ]:          0 :             if (!(id = pa_machine_id()))
     546                 :            :                 return NULL;
     547                 :            : 
     548                 :          0 :             pa_snprintf(c, l, "{%s}unix:%s", id, s->filename);
     549                 :          0 :             pa_xfree(id);
     550                 :          0 :             return c;
     551                 :            :         }
     552                 :            : 
     553                 :            :         default:
     554                 :            :             return NULL;
     555                 :            :     }
     556                 :            : }

Generated by: LCOV version 1.9