modules: Add null/dummy echo canceller
[pulseaudio-raopUDP/pulseaudio-raop-alac.git] / src / modules / module-protocol-stub.c
blob1b7f6ed154dd4bcb30b7a64af71f2177d5bda33f
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <errno.h>
28 #include <stdio.h>
29 #include <unistd.h>
31 #ifdef HAVE_NETINET_IN_H
32 #include <netinet/in.h>
33 #endif
35 #include <pulse/xmalloc.h>
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>
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
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",
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
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
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
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
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
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",
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
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
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",
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
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
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
172 PA_MODULE_LOAD_ONCE(FALSE);
173 PA_MODULE_AUTHOR("Lennart Poettering");
174 PA_MODULE_VERSION(PACKAGE_VERSION);
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
187 struct userdata {
188 pa_module *module;
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
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
216 static void socket_server_on_connection_cb(pa_socket_server*s, pa_iochannel *io, void *userdata) {
217 struct userdata *u = userdata;
219 pa_assert(s);
220 pa_assert(io);
221 pa_assert(u);
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
236 int pa__init(pa_module*m) {
237 pa_modargs *ma = NULL;
238 struct userdata *u = NULL;
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
248 #if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP)
249 char t[256];
250 #endif
252 pa_assert(m);
254 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
255 pa_log("Failed to parse module arguments");
256 goto fail;
259 m->userdata = u = pa_xnew0(struct userdata, 1);
260 u->module = m;
262 #if defined(USE_PROTOCOL_SIMPLE)
263 u->simple_protocol = pa_simple_protocol_get(m->core);
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);
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);
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
289 #if defined(USE_TCP_SOCKETS)
291 if (pa_in_system_mode() || pa_modargs_get_value(ma, "port", NULL))
292 port_fallback = FALSE;
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;
299 listen_on = pa_modargs_get_value(ma, "listen", NULL);
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);
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;
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
327 #else
329 # if defined(USE_PROTOCOL_ESOUND)
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
337 /* This socket doesn't reside in our own runtime dir but in
338 * /tmp/.esd/, hence we have to create the dir first */
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;
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;
350 # endif
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);
358 if (!(u->socket_server_unix = pa_socket_server_new_unix(m->core->mainloop, u->socket_path)))
359 goto fail;
361 pa_socket_server_set_callback(u->socket_server_unix, socket_server_on_connection_cb, u);
363 #endif
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);
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);
380 # endif
381 #endif
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);
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);
398 #endif /* USE_TCP_SOCKETS */
399 #endif /* USE_PROTOCOL_HTTP */
401 if (ma)
402 pa_modargs_free(ma);
404 return 0;
406 fail:
408 if (ma)
409 pa_modargs_free(ma);
411 pa__done(m);
413 return -1;
416 void pa__done(pa_module*m) {
417 struct userdata *u;
419 pa_assert(m);
421 if (!(u = m->userdata))
422 return;
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);
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);
436 #elif defined(USE_PROTOCOL_HTTP)
437 if (u->http_protocol) {
438 char t[256];
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);
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 */
456 pa_http_protocol_disconnect(u->http_protocol, u->module);
457 pa_http_protocol_unref(u->http_protocol);
459 #elif defined(USE_PROTOCOL_NATIVE)
460 if (u->native_protocol) {
462 char t[256];
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);
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
480 pa_native_protocol_disconnect(u->native_protocol, u->module);
481 pa_native_protocol_unref(u->native_protocol);
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);
490 if (u->esound_options)
491 pa_esound_options_unref(u->esound_options);
492 #endif
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);
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);
511 # endif
513 pa_xfree(u->socket_path);
514 #endif
516 pa_xfree(u);