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 : : }
|