Revert "resamplers: Optimize trivial resampler"
[profile/ivi/pulseaudio-panda.git] / src / pulsecore / socket-server.c
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 static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
93     pa_socket_server *s = userdata;
94     pa_iochannel *io;
95     int nfd;
96
97     pa_assert(s);
98     pa_assert(PA_REFCNT_VALUE(s) >= 1);
99     pa_assert(s->mainloop == mainloop);
100     pa_assert(s->io_event == e);
101     pa_assert(e);
102     pa_assert(fd >= 0);
103     pa_assert(fd == s->fd);
104
105     pa_socket_server_ref(s);
106
107     if ((nfd = pa_accept_cloexec(fd, NULL, NULL)) < 0) {
108         pa_log("accept(): %s", pa_cstrerror(errno));
109         goto finish;
110     }
111
112     if (!s->on_connection) {
113         pa_close(nfd);
114         goto finish;
115     }
116
117 #ifdef HAVE_LIBWRAP
118
119     if (s->tcpwrap_service) {
120         struct request_info req;
121
122         request_init(&req, RQ_DAEMON, s->tcpwrap_service, RQ_FILE, nfd, NULL);
123         fromhost(&req);
124         if (!hosts_access(&req)) {
125             pa_log_warn("TCP connection refused by tcpwrap.");
126             pa_close(nfd);
127             goto finish;
128         }
129
130         pa_log_info("TCP connection accepted by tcpwrap.");
131     }
132 #endif
133
134     /* There should be a check for socket type here */
135     if (s->type == SOCKET_SERVER_IPV4)
136         pa_make_tcp_socket_low_delay(fd);
137     else
138         pa_make_socket_low_delay(fd);
139
140     pa_assert_se(io = pa_iochannel_new(s->mainloop, nfd, nfd));
141     s->on_connection(s, io, s->userdata);
142
143 finish:
144     pa_socket_server_unref(s);
145 }
146
147 pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
148     pa_socket_server *s;
149
150     pa_assert(m);
151     pa_assert(fd >= 0);
152
153     s = pa_xnew0(pa_socket_server, 1);
154     PA_REFCNT_INIT(s);
155     s->fd = fd;
156     s->mainloop = m;
157
158     pa_assert_se(s->io_event = m->io_new(m, fd, PA_IO_EVENT_INPUT, callback, s));
159
160     s->type = SOCKET_SERVER_GENERIC;
161
162     return s;
163 }
164
165 pa_socket_server* pa_socket_server_ref(pa_socket_server *s) {
166     pa_assert(s);
167     pa_assert(PA_REFCNT_VALUE(s) >= 1);
168
169     PA_REFCNT_INC(s);
170     return s;
171 }
172
173 #ifdef HAVE_SYS_UN_H
174
175 pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *filename) {
176     int fd = -1;
177     struct sockaddr_un sa;
178     pa_socket_server *s;
179
180     pa_assert(m);
181     pa_assert(filename);
182
183     if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
184         pa_log("socket(): %s", pa_cstrerror(errno));
185         goto fail;
186     }
187
188     memset(&sa, 0, sizeof(sa));
189     sa.sun_family = AF_UNIX;
190     pa_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
191
192     pa_make_socket_low_delay(fd);
193
194     if (bind(fd, (struct sockaddr*) &sa, (socklen_t) SUN_LEN(&sa)) < 0) {
195         pa_log("bind(): %s", pa_cstrerror(errno));
196         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     chmod(filename, 0777);
204
205     if (listen(fd, 5) < 0) {
206         pa_log("listen(): %s", pa_cstrerror(errno));
207         goto fail;
208     }
209
210     pa_assert_se(s = pa_socket_server_new(m, fd));
211
212     s->filename = pa_xstrdup(filename);
213     s->type = SOCKET_SERVER_UNIX;
214
215     return s;
216
217 fail:
218     if (fd >= 0)
219         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 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     int fd = -1;
235     struct sockaddr_in sa;
236     int on = 1;
237
238     pa_assert(m);
239     pa_assert(port);
240
241     if ((fd = pa_socket_cloexec(PF_INET, SOCK_STREAM, 0)) < 0) {
242         pa_log("socket(PF_INET): %s", pa_cstrerror(errno));
243         goto fail;
244     }
245
246 #ifdef SO_REUSEADDR
247     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0)
248         pa_log("setsockopt(): %s", pa_cstrerror(errno));
249 #endif
250
251     pa_make_tcp_socket_low_delay(fd);
252
253     memset(&sa, 0, sizeof(sa));
254     sa.sin_family = AF_INET;
255     sa.sin_port = htons(port);
256     sa.sin_addr.s_addr = htonl(address);
257
258     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
259
260         if (errno == EADDRINUSE && fallback) {
261             sa.sin_port = 0;
262
263             if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
264                 goto good;
265         }
266
267         pa_log("bind(): %s", pa_cstrerror(errno));
268         goto fail;
269
270     good:
271         ;
272     }
273
274     if (listen(fd, 5) < 0) {
275         pa_log("listen(): %s", pa_cstrerror(errno));
276         goto fail;
277     }
278
279     if ((ss = pa_socket_server_new(m, fd))) {
280         ss->type = SOCKET_SERVER_IPV4;
281         ss->tcpwrap_service = pa_xstrdup(tcpwrap_service);
282     }
283
284     return ss;
285
286 fail:
287     if (fd >= 0)
288         pa_close(fd);
289
290     return NULL;
291 }
292
293 #ifdef HAVE_IPV6
294 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     int fd = -1;
297     struct sockaddr_in6 sa;
298     int on;
299
300     pa_assert(m);
301     pa_assert(port > 0);
302
303     if ((fd = pa_socket_cloexec(PF_INET6, SOCK_STREAM, 0)) < 0) {
304         pa_log("socket(PF_INET6): %s", pa_cstrerror(errno));
305         goto fail;
306     }
307
308 #ifdef IPV6_V6ONLY
309     on = 1;
310     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &on, sizeof(on)) < 0)
311         pa_log("setsockopt(IPPROTO_IPV6, IPV6_V6ONLY): %s", pa_cstrerror(errno));
312 #endif
313
314 #ifdef SO_REUSEADDR
315     on = 1;
316     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0)
317         pa_log("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %s", pa_cstrerror(errno));
318 #endif
319
320     pa_make_tcp_socket_low_delay(fd);
321
322     memset(&sa, 0, sizeof(sa));
323     sa.sin6_family = AF_INET6;
324     sa.sin6_port = htons(port);
325     memcpy(sa.sin6_addr.s6_addr, address, 16);
326
327     if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
328
329         if (errno == EADDRINUSE && fallback) {
330             sa.sin6_port = 0;
331
332             if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
333                 goto good;
334         }
335
336         pa_log("bind(): %s", pa_cstrerror(errno));
337         goto fail;
338
339     good:
340         ;
341     }
342
343     if (listen(fd, 5) < 0) {
344         pa_log("listen(): %s", pa_cstrerror(errno));
345         goto fail;
346     }
347
348     if ((ss = pa_socket_server_new(m, fd))) {
349         ss->type = SOCKET_SERVER_IPV6;
350         ss->tcpwrap_service = pa_xstrdup(tcpwrap_service);
351     }
352
353     return ss;
354
355 fail:
356     if (fd >= 0)
357         pa_close(fd);
358
359     return NULL;
360 }
361 #endif
362
363 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     pa_assert(m);
365     pa_assert(port > 0);
366
367     return pa_socket_server_new_ipv4(m, INADDR_LOOPBACK, port, fallback, tcpwrap_service);
368 }
369
370 #ifdef HAVE_IPV6
371 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     pa_assert(m);
373     pa_assert(port > 0);
374
375     return pa_socket_server_new_ipv6(m, in6addr_loopback.s6_addr, port, fallback, tcpwrap_service);
376 }
377 #endif
378
379 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     pa_assert(m);
381     pa_assert(port > 0);
382
383     return pa_socket_server_new_ipv4(m, INADDR_ANY, port, fallback, tcpwrap_service);
384 }
385
386 #ifdef HAVE_IPV6
387 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     pa_assert(m);
389     pa_assert(port > 0);
390
391     return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, fallback, tcpwrap_service);
392 }
393 #endif
394
395 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     pa_assert(m);
399     pa_assert(name);
400     pa_assert(port > 0);
401
402     if (inet_pton(AF_INET, name, &ipv4) > 0)
403         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 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     pa_assert(m);
413     pa_assert(name);
414     pa_assert(port > 0);
415
416     if (inet_pton(AF_INET6, name, &ipv6) > 0)
417         return pa_socket_server_new_ipv6(m, ipv6.s6_addr, port, fallback, tcpwrap_service);
418
419     return NULL;
420 }
421 #endif
422
423 static void socket_server_free(pa_socket_server*s) {
424     pa_assert(s);
425
426     if (s->filename) {
427         unlink(s->filename);
428         pa_xfree(s->filename);
429     }
430
431     pa_close(s->fd);
432
433     pa_xfree(s->tcpwrap_service);
434
435     s->mainloop->io_free(s->io_event);
436     pa_xfree(s);
437 }
438
439 void pa_socket_server_unref(pa_socket_server *s) {
440     pa_assert(s);
441     pa_assert(PA_REFCNT_VALUE(s) >= 1);
442
443     if (PA_REFCNT_DEC(s) <= 0)
444         socket_server_free(s);
445 }
446
447 void pa_socket_server_set_callback(pa_socket_server*s, pa_socket_server_on_connection_cb_t on_connection, void *userdata) {
448     pa_assert(s);
449     pa_assert(PA_REFCNT_VALUE(s) >= 1);
450
451     s->on_connection = on_connection;
452     s->userdata = userdata;
453 }
454
455 char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
456     pa_assert(s);
457     pa_assert(PA_REFCNT_VALUE(s) >= 1);
458     pa_assert(c);
459     pa_assert(l > 0);
460
461     switch (s->type) {
462 #ifdef HAVE_IPV6
463         case SOCKET_SERVER_IPV6: {
464             struct sockaddr_in6 sa;
465             socklen_t sa_len = sizeof(sa);
466
467             if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
468                 pa_log("getsockname(): %s", pa_cstrerror(errno));
469                 return NULL;
470             }
471
472             if (memcmp(&in6addr_any, &sa.sin6_addr, sizeof(in6addr_any)) == 0) {
473                 char fqdn[256];
474                 if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
475                     return NULL;
476
477                 pa_snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port));
478
479             } else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) {
480                 char *id;
481
482                 if (!(id = pa_machine_id()))
483                     return NULL;
484
485                 pa_snprintf(c, l, "{%s}tcp6:localhost:%u", id, (unsigned) ntohs(sa.sin6_port));
486                 pa_xfree(id);
487             } else {
488                 char ip[INET6_ADDRSTRLEN];
489
490                 if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) {
491                     pa_log("inet_ntop(): %s", pa_cstrerror(errno));
492                     return NULL;
493                 }
494
495                 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             socklen_t sa_len = sizeof(sa);
505
506             if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
507                 pa_log("getsockname(): %s", pa_cstrerror(errno));
508                 return NULL;
509             }
510
511             if (sa.sin_addr.s_addr == INADDR_ANY) {
512                 char fqdn[256];
513                 if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
514                     return NULL;
515
516                 pa_snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port));
517             } else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) {
518                 char *id;
519
520                 if (!(id = pa_machine_id()))
521                     return NULL;
522
523                 pa_snprintf(c, l, "{%s}tcp:localhost:%u", id, (unsigned) ntohs(sa.sin_port));
524                 pa_xfree(id);
525             } else {
526                 char ip[INET_ADDRSTRLEN];
527
528                 if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) {
529                     pa_log("inet_ntop(): %s", pa_cstrerror(errno));
530                     return NULL;
531                 }
532
533                 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             if (!s->filename)
543                 return NULL;
544
545             if (!(id = pa_machine_id()))
546                 return NULL;
547
548             pa_snprintf(c, l, "{%s}unix:%s", id, s->filename);
549             pa_xfree(id);
550             return c;
551         }
552
553         default:
554             return NULL;
555     }
556 }