echo-cancel-test: Enable debug log level
[platform/upstream/pulseaudio.git] / src / modules / module-protocol-stub.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 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 <errno.h>
28 #include <stdio.h>
29 #include <unistd.h>
30
31 #ifdef HAVE_NETINET_IN_H
32 #include <netinet/in.h>
33 #endif
34
35 #include <pulse/xmalloc.h>
36
37 #include <pulsecore/core-error.h>
38 #include <pulsecore/module.h>
39 #include <pulsecore/socket.h>
40 #include <pulsecore/socket-server.h>
41 #include <pulsecore/socket-util.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/modargs.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/native-common.h>
46 #include <pulsecore/creds.h>
47 #include <pulsecore/arpa-inet.h>
48
49 #ifdef USE_TCP_SOCKETS
50 #define SOCKET_DESCRIPTION "(TCP sockets)"
51 #define SOCKET_USAGE "port=<TCP port number> listen=<address to listen on>"
52 #else
53 #define SOCKET_DESCRIPTION "(UNIX sockets)"
54 #define SOCKET_USAGE "socket=<path to UNIX socket>"
55 #endif
56
57 #if defined(USE_PROTOCOL_SIMPLE)
58 #  include <pulsecore/protocol-simple.h>
59 #  define TCPWRAP_SERVICE "pulseaudio-simple"
60 #  define IPV4_PORT 4711
61 #  define UNIX_SOCKET "simple"
62 #  define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record",
63
64 #  if defined(USE_TCP_SOCKETS)
65 #    include "module-simple-protocol-tcp-symdef.h"
66 #  else
67 #    include "module-simple-protocol-unix-symdef.h"
68 #  endif
69
70   PA_MODULE_DESCRIPTION("Simple protocol "SOCKET_DESCRIPTION);
71   PA_MODULE_USAGE("rate=<sample rate> "
72                   "format=<sample format> "
73                   "channels=<number of channels> "
74                   "sink=<sink to connect to> "
75                   "source=<source to connect to> "
76                   "playback=<enable playback?> "
77                   "record=<enable record?> "
78                   SOCKET_USAGE);
79 #elif defined(USE_PROTOCOL_CLI)
80 #  include <pulsecore/protocol-cli.h>
81 #  define TCPWRAP_SERVICE "pulseaudio-cli"
82 #  define IPV4_PORT 4712
83 #  define UNIX_SOCKET "cli"
84 #  define MODULE_ARGUMENTS
85
86 #  ifdef USE_TCP_SOCKETS
87 #    include "module-cli-protocol-tcp-symdef.h"
88 #  else
89 #   include "module-cli-protocol-unix-symdef.h"
90 #  endif
91
92   PA_MODULE_DESCRIPTION("Command line interface protocol "SOCKET_DESCRIPTION);
93   PA_MODULE_USAGE(SOCKET_USAGE);
94 #elif defined(USE_PROTOCOL_HTTP)
95 #  include <pulsecore/protocol-http.h>
96 #  define TCPWRAP_SERVICE "pulseaudio-http"
97 #  define IPV4_PORT 4714
98 #  define UNIX_SOCKET "http"
99 #  define MODULE_ARGUMENTS
100
101 #  ifdef USE_TCP_SOCKETS
102 #    include "module-http-protocol-tcp-symdef.h"
103 #  else
104 #    include "module-http-protocol-unix-symdef.h"
105 #  endif
106
107   PA_MODULE_DESCRIPTION("HTTP "SOCKET_DESCRIPTION);
108   PA_MODULE_USAGE(SOCKET_USAGE);
109 #elif defined(USE_PROTOCOL_NATIVE)
110 #  include <pulsecore/protocol-native.h>
111 #  define TCPWRAP_SERVICE "pulseaudio-native"
112 #  define IPV4_PORT PA_NATIVE_DEFAULT_PORT
113 #  define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET
114 #  define MODULE_ARGUMENTS_COMMON "cookie", "auth-cookie", "auth-cookie-enabled", "auth-anonymous",
115
116 #  ifdef USE_TCP_SOCKETS
117 #    include "module-native-protocol-tcp-symdef.h"
118 #  else
119 #    include "module-native-protocol-unix-symdef.h"
120 #  endif
121
122 #  if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS)
123 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable",
124 #    define AUTH_USAGE "auth-group=<system group to allow access> auth-group-enable=<enable auth by UNIX group?> "
125 #  elif defined(USE_TCP_SOCKETS)
126 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
127 #    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
128 #  else
129 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
130 #    define AUTH_USAGE
131 #    endif
132
133   PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION);
134   PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> "
135                   "auth-cookie=<path to cookie file> "
136                   "auth-cookie-enabled=<enable cookie authentication?> "
137                   AUTH_USAGE
138                   SOCKET_USAGE);
139 #elif defined(USE_PROTOCOL_ESOUND)
140 #  include <pulsecore/protocol-esound.h>
141 #  include <pulsecore/esound.h>
142 #  define TCPWRAP_SERVICE "esound"
143 #  define IPV4_PORT ESD_DEFAULT_PORT
144 #  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled",
145
146 #  ifdef USE_TCP_SOCKETS
147 #    include "module-esound-protocol-tcp-symdef.h"
148 #  else
149 #    include "module-esound-protocol-unix-symdef.h"
150 #  endif
151
152 #  if defined(USE_TCP_SOCKETS)
153 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
154 #    define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
155 #  else
156 #    define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
157 #    define AUTH_USAGE
158 #  endif
159
160   PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION);
161   PA_MODULE_USAGE("sink=<sink to connect to> "
162                   "source=<source to connect to> "
163                   "auth-anonymous=<don't verify cookies?> "
164                   "auth-cookie=<path to cookie file> "
165                   "auth-cookie-enabled=<enable cookie authentication?> "
166                   AUTH_USAGE
167                   SOCKET_USAGE);
168 #else
169 #  error "Broken build system"
170 #endif
171
172 PA_MODULE_LOAD_ONCE(FALSE);
173 PA_MODULE_AUTHOR("Lennart Poettering");
174 PA_MODULE_VERSION(PACKAGE_VERSION);
175
176 static const char* const valid_modargs[] = {
177     MODULE_ARGUMENTS
178 #if defined(USE_TCP_SOCKETS)
179     "port",
180     "listen",
181 #else
182     "socket",
183 #endif
184     NULL
185 };
186
187 struct userdata {
188     pa_module *module;
189
190 #if defined(USE_PROTOCOL_SIMPLE)
191     pa_simple_protocol *simple_protocol;
192     pa_simple_options *simple_options;
193 #elif defined(USE_PROTOCOL_CLI)
194     pa_cli_protocol *cli_protocol;
195 #elif defined(USE_PROTOCOL_HTTP)
196     pa_http_protocol *http_protocol;
197 #elif defined(USE_PROTOCOL_NATIVE)
198     pa_native_protocol *native_protocol;
199     pa_native_options *native_options;
200 #else
201     pa_esound_protocol *esound_protocol;
202     pa_esound_options *esound_options;
203 #endif
204
205 #if defined(USE_TCP_SOCKETS)
206     pa_socket_server *socket_server_ipv4;
207 #  ifdef HAVE_IPV6
208     pa_socket_server *socket_server_ipv6;
209 #  endif
210 #else
211     pa_socket_server *socket_server_unix;
212     char *socket_path;
213 #endif
214 };
215
216 static void socket_server_on_connection_cb(pa_socket_server*s, pa_iochannel *io, void *userdata) {
217     struct userdata *u = userdata;
218
219     pa_assert(s);
220     pa_assert(io);
221     pa_assert(u);
222
223 #if defined(USE_PROTOCOL_SIMPLE)
224     pa_simple_protocol_connect(u->simple_protocol, io, u->simple_options);
225 #elif defined(USE_PROTOCOL_CLI)
226     pa_cli_protocol_connect(u->cli_protocol, io, u->module);
227 #elif defined(USE_PROTOCOL_HTTP)
228     pa_http_protocol_connect(u->http_protocol, io, u->module);
229 #elif defined(USE_PROTOCOL_NATIVE)
230     pa_native_protocol_connect(u->native_protocol, io, u->native_options);
231 #else
232     pa_esound_protocol_connect(u->esound_protocol, io, u->esound_options);
233 #endif
234 }
235
236 int pa__init(pa_module*m) {
237     pa_modargs *ma = NULL;
238     struct userdata *u = NULL;
239
240 #if defined(USE_TCP_SOCKETS)
241     uint32_t port = IPV4_PORT;
242     pa_bool_t port_fallback = TRUE;
243     const char *listen_on;
244 #else
245     int r;
246 #endif
247
248 #if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP)
249     char t[256];
250 #endif
251
252     pa_assert(m);
253
254     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
255         pa_log("Failed to parse module arguments");
256         goto fail;
257     }
258
259     m->userdata = u = pa_xnew0(struct userdata, 1);
260     u->module = m;
261
262 #if defined(USE_PROTOCOL_SIMPLE)
263     u->simple_protocol = pa_simple_protocol_get(m->core);
264
265     u->simple_options = pa_simple_options_new();
266     if (pa_simple_options_parse(u->simple_options, m->core, ma) < 0)
267         goto fail;
268     u->simple_options->module = m;
269 #elif defined(USE_PROTOCOL_CLI)
270     u->cli_protocol = pa_cli_protocol_get(m->core);
271 #elif defined(USE_PROTOCOL_HTTP)
272     u->http_protocol = pa_http_protocol_get(m->core);
273 #elif defined(USE_PROTOCOL_NATIVE)
274     u->native_protocol = pa_native_protocol_get(m->core);
275
276     u->native_options = pa_native_options_new();
277     if (pa_native_options_parse(u->native_options, m->core, ma) < 0)
278         goto fail;
279     u->native_options->module = m;
280 #else
281     u->esound_protocol = pa_esound_protocol_get(m->core);
282
283     u->esound_options = pa_esound_options_new();
284     if (pa_esound_options_parse(u->esound_options, m->core, ma) < 0)
285         goto fail;
286     u->esound_options->module = m;
287 #endif
288
289 #if defined(USE_TCP_SOCKETS)
290
291     if (pa_in_system_mode() || pa_modargs_get_value(ma, "port", NULL))
292         port_fallback = FALSE;
293
294     if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) {
295         pa_log("port= expects a numerical argument between 1 and 65535.");
296         goto fail;
297     }
298
299     listen_on = pa_modargs_get_value(ma, "listen", NULL);
300
301     if (listen_on) {
302 #  ifdef HAVE_IPV6
303         u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
304 #  endif
305         u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
306     } else {
307 #  ifdef HAVE_IPV6
308         u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
309 #  endif
310         u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE);
311     }
312
313 #  ifdef HAVE_IPV6
314     if (!u->socket_server_ipv4 && !u->socket_server_ipv6)
315 #  else
316     if (!u->socket_server_ipv4)
317 #  endif
318         goto fail;
319
320     if (u->socket_server_ipv4)
321         pa_socket_server_set_callback(u->socket_server_ipv4, socket_server_on_connection_cb, u);
322 #  ifdef HAVE_IPV6
323     if (u->socket_server_ipv6)
324         pa_socket_server_set_callback(u->socket_server_ipv6, socket_server_on_connection_cb, u);
325 #  endif
326
327 #else
328
329 #  if defined(USE_PROTOCOL_ESOUND)
330
331 #    if defined(USE_PER_USER_ESOUND_SOCKET)
332     u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid());
333 #    else
334     u->socket_path = pa_xstrdup("/tmp/.esd/socket");
335 #    endif
336
337     /* This socket doesn't reside in our own runtime dir but in
338      * /tmp/.esd/, hence we have to create the dir first */
339
340     if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755U : 0700U, (uid_t)-1, (gid_t)-1, FALSE) < 0) {
341         pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno));
342         goto fail;
343     }
344
345 #  else
346     if (!(u->socket_path = pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET)))) {
347         pa_log("Failed to generate socket path.");
348         goto fail;
349     }
350 #  endif
351
352     if ((r = pa_unix_socket_remove_stale(u->socket_path)) < 0) {
353         pa_log("Failed to remove stale UNIX socket '%s': %s", u->socket_path, pa_cstrerror(errno));
354         goto fail;
355     } else if (r > 0)
356         pa_log_info("Removed stale UNIX socket '%s'.", u->socket_path);
357
358     if (!(u->socket_server_unix = pa_socket_server_new_unix(m->core->mainloop, u->socket_path)))
359         goto fail;
360
361     pa_socket_server_set_callback(u->socket_server_unix, socket_server_on_connection_cb, u);
362
363 #endif
364
365 #if defined(USE_PROTOCOL_NATIVE)
366 #  if defined(USE_TCP_SOCKETS)
367     if (u->socket_server_ipv4)
368         if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
369             pa_native_protocol_add_server_string(u->native_protocol, t);
370
371 #    ifdef HAVE_IPV6
372     if (u->socket_server_ipv6)
373         if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
374             pa_native_protocol_add_server_string(u->native_protocol, t);
375 #    endif
376 #  else
377     if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
378         pa_native_protocol_add_server_string(u->native_protocol, t);
379
380 #  endif
381 #endif
382
383 #if defined(USE_PROTOCOL_HTTP)
384 #if defined(USE_TCP_SOCKETS)
385     if (u->socket_server_ipv4)
386         if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
387             pa_http_protocol_add_server_string(u->http_protocol, t);
388
389 #ifdef HAVE_IPV6
390     if (u->socket_server_ipv6)
391         if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
392             pa_http_protocol_add_server_string(u->http_protocol, t);
393 #endif /* HAVE_IPV6 */
394 #else /* USE_TCP_SOCKETS */
395     if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
396         pa_http_protocol_add_server_string(u->http_protocol, t);
397
398 #endif /* USE_TCP_SOCKETS */
399 #endif /* USE_PROTOCOL_HTTP */
400
401     if (ma)
402         pa_modargs_free(ma);
403
404     return 0;
405
406 fail:
407
408     if (ma)
409         pa_modargs_free(ma);
410
411     pa__done(m);
412
413     return -1;
414 }
415
416 void pa__done(pa_module*m) {
417     struct userdata *u;
418
419     pa_assert(m);
420
421     if (!(u = m->userdata))
422         return;
423
424 #if defined(USE_PROTOCOL_SIMPLE)
425     if (u->simple_protocol) {
426         pa_simple_protocol_disconnect(u->simple_protocol, u->module);
427         pa_simple_protocol_unref(u->simple_protocol);
428     }
429     if (u->simple_options)
430         pa_simple_options_unref(u->simple_options);
431 #elif defined(USE_PROTOCOL_CLI)
432     if (u->cli_protocol) {
433         pa_cli_protocol_disconnect(u->cli_protocol, u->module);
434         pa_cli_protocol_unref(u->cli_protocol);
435     }
436 #elif defined(USE_PROTOCOL_HTTP)
437     if (u->http_protocol) {
438         char t[256];
439
440 #if defined(USE_TCP_SOCKETS)
441         if (u->socket_server_ipv4)
442             if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
443                 pa_http_protocol_remove_server_string(u->http_protocol, t);
444
445 #ifdef HAVE_IPV6
446         if (u->socket_server_ipv6)
447             if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
448                 pa_http_protocol_remove_server_string(u->http_protocol, t);
449 #endif /* HAVE_IPV6 */
450 #else /* USE_TCP_SOCKETS */
451         if (u->socket_server_unix)
452             if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
453                 pa_http_protocol_remove_server_string(u->http_protocol, t);
454 #endif /* USE_PROTOCOL_HTTP */
455
456         pa_http_protocol_disconnect(u->http_protocol, u->module);
457         pa_http_protocol_unref(u->http_protocol);
458     }
459 #elif defined(USE_PROTOCOL_NATIVE)
460     if (u->native_protocol) {
461
462         char t[256];
463
464 #  if defined(USE_TCP_SOCKETS)
465         if (u->socket_server_ipv4)
466             if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t)))
467                 pa_native_protocol_remove_server_string(u->native_protocol, t);
468
469 #    ifdef HAVE_IPV6
470         if (u->socket_server_ipv6)
471             if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t)))
472                 pa_native_protocol_remove_server_string(u->native_protocol, t);
473 #    endif
474 #  else
475         if (u->socket_server_unix)
476             if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t)))
477                 pa_native_protocol_remove_server_string(u->native_protocol, t);
478 #  endif
479
480         pa_native_protocol_disconnect(u->native_protocol, u->module);
481         pa_native_protocol_unref(u->native_protocol);
482     }
483     if (u->native_options)
484         pa_native_options_unref(u->native_options);
485 #else
486     if (u->esound_protocol) {
487         pa_esound_protocol_disconnect(u->esound_protocol, u->module);
488         pa_esound_protocol_unref(u->esound_protocol);
489     }
490     if (u->esound_options)
491         pa_esound_options_unref(u->esound_options);
492 #endif
493
494 #if defined(USE_TCP_SOCKETS)
495     if (u->socket_server_ipv4)
496         pa_socket_server_unref(u->socket_server_ipv4);
497 #  ifdef HAVE_IPV6
498     if (u->socket_server_ipv6)
499         pa_socket_server_unref(u->socket_server_ipv6);
500 #  endif
501 #else
502     if (u->socket_server_unix)
503         pa_socket_server_unref(u->socket_server_unix);
504
505 # if defined(USE_PROTOCOL_ESOUND) && !defined(USE_PER_USER_ESOUND_SOCKET)
506     if (u->socket_path) {
507         char *p = pa_parent_dir(u->socket_path);
508         rmdir(p);
509         pa_xfree(p);
510     }
511 # endif
512
513     pa_xfree(u->socket_path);
514 #endif
515
516     pa_xfree(u);
517 }