aa11cdfcf58f2a748fa0ef367d0b78920e9b355f
[profile/ivi/pulseaudio-panda.git] / src / modules / dbus / module-dbus-protocol.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2009 Tanu Kaskinen
5   Copyright 2006 Lennart Poettering
6   Copyright 2006 Shams E. King
7
8   PulseAudio is free software; you can redistribute it and/or modify
9   it under the terms of the GNU Lesser General Public License as published
10   by the Free Software Foundation; either version 2.1 of the License,
11   or (at your option) any later version.
12
13   PulseAudio is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with PulseAudio; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21   USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <dbus/dbus.h>
29
30 #include <pulse/mainloop-api.h>
31 #include <pulse/timeval.h>
32 #include <pulse/xmalloc.h>
33
34 #include <pulsecore/client.h>
35 #include <pulsecore/core-util.h>
36 #include <pulsecore/dbus-util.h>
37 #include <pulsecore/idxset.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/modargs.h>
40 #include <pulsecore/module.h>
41 #include <pulsecore/protocol-dbus.h>
42
43 #include "iface-client.h"
44 #include "iface-core.h"
45
46 #include "module-dbus-protocol-symdef.h"
47
48 PA_MODULE_DESCRIPTION("D-Bus interface");
49 PA_MODULE_USAGE(
50         "access=local|remote|local,remote "
51         "tcp_port=<port number> "
52         "tcp_listen=<hostname>");
53 PA_MODULE_LOAD_ONCE(TRUE);
54 PA_MODULE_AUTHOR("Tanu Kaskinen");
55 PA_MODULE_VERSION(PACKAGE_VERSION);
56
57 enum server_type {
58     SERVER_TYPE_LOCAL,
59     SERVER_TYPE_TCP
60 };
61
62 struct server;
63 struct connection;
64
65 struct userdata {
66     pa_module *module;
67     pa_bool_t local_access;
68     pa_bool_t remote_access;
69     uint32_t tcp_port;
70     char *tcp_listen;
71
72     struct server *local_server;
73     struct server *tcp_server;
74
75     pa_idxset *connections;
76
77     pa_defer_event *cleanup_event;
78
79     pa_dbus_protocol *dbus_protocol;
80     pa_dbusiface_core *core_iface;
81 };
82
83 struct server {
84     struct userdata *userdata;
85     enum server_type type;
86     DBusServer *dbus_server;
87 };
88
89 struct connection {
90     struct server *server;
91     pa_dbus_wrap_connection *wrap_conn;
92     pa_client *client;
93 };
94
95 static const char* const valid_modargs[] = {
96     "access",
97     "tcp_port",
98     "tcp_listen",
99     NULL
100 };
101
102 static void connection_free(struct connection *c) {
103     pa_assert(c);
104
105     pa_assert_se(pa_dbus_protocol_unregister_connection(c->server->userdata->dbus_protocol, pa_dbus_wrap_connection_get(c->wrap_conn)) >= 0);
106
107     pa_client_free(c->client);
108     pa_assert_se(pa_idxset_remove_by_data(c->server->userdata->connections, c, NULL));
109     pa_dbus_wrap_connection_free(c->wrap_conn);
110     pa_xfree(c);
111 }
112
113 /* Called from pa_client_kill(). */
114 static void client_kill_cb(pa_client *c) {
115     struct connection *conn;
116
117     pa_assert(c);
118     pa_assert(c->userdata);
119
120     conn = c->userdata;
121     connection_free(conn);
122     c->userdata = NULL;
123
124     pa_log_info("Connection killed.");
125 }
126
127 /* Called from pa_client_send_event(). */
128 static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *data) {
129     struct connection *conn = NULL;
130     DBusMessage *signal_msg = NULL;
131     DBusMessageIter msg_iter;
132
133     pa_assert(c);
134     pa_assert(name);
135     pa_assert(data);
136     pa_assert(c->userdata);
137
138     conn = c->userdata;
139
140     pa_assert_se(signal_msg = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c),
141                                                       PA_DBUSIFACE_CLIENT_INTERFACE,
142                                                       "ClientEvent"));
143     dbus_message_iter_init_append(signal_msg, &msg_iter);
144     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
145     pa_dbus_append_proplist(&msg_iter, data);
146
147     pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal_msg, NULL));
148     dbus_message_unref(signal_msg);
149 }
150
151 /* Called by D-Bus at the authentication phase. */
152 static dbus_bool_t user_check_cb(DBusConnection *connection, unsigned long uid, void *data) {
153     pa_log_debug("Allowing connection by user %lu.", uid);
154
155     return TRUE;
156 }
157
158 static DBusHandlerResult disconnection_filter_cb(DBusConnection *connection, DBusMessage *message, void *user_data) {
159     struct connection *c = user_data;
160
161     pa_assert(connection);
162     pa_assert(message);
163     pa_assert(c);
164
165     if (dbus_message_is_signal(message, "org.freedesktop.DBus.Local", "Disconnected")) {
166         /* The connection died. Now we want to free the connection object, but
167          * let's wait until this message is fully processed, in case someone
168          * else is interested in this signal too. */
169         c->server->userdata->module->core->mainloop->defer_enable(c->server->userdata->cleanup_event, 1);
170     }
171
172     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
173 }
174
175 /* Called by D-Bus when a new client connection is received. */
176 static void connection_new_cb(DBusServer *dbus_server, DBusConnection *new_connection, void *data) {
177     struct server *s = data;
178     struct connection *c;
179     pa_client_new_data new_data;
180     pa_client *client;
181
182     pa_assert(new_connection);
183     pa_assert(s);
184
185     pa_client_new_data_init(&new_data);
186     new_data.module = s->userdata->module;
187     new_data.driver = __FILE__;
188     pa_proplist_sets(new_data.proplist, PA_PROP_APPLICATION_NAME, "D-Bus client");
189     client = pa_client_new(s->userdata->module->core, &new_data);
190     pa_client_new_data_done(&new_data);
191
192     if (!client) {
193         dbus_connection_close(new_connection);
194         return;
195     }
196
197     if (s->type == SERVER_TYPE_TCP || s->userdata->module->core->server_type == PA_SERVER_TYPE_SYSTEM) {
198         /* FIXME: Here we allow anyone from anywhere to access the server,
199          * anonymously. Access control should be configurable. */
200         dbus_connection_set_unix_user_function(new_connection, user_check_cb, NULL, NULL);
201         dbus_connection_set_allow_anonymous(new_connection, TRUE);
202     }
203
204     c = pa_xnew(struct connection, 1);
205     c->server = s;
206     c->wrap_conn = pa_dbus_wrap_connection_new_from_existing(s->userdata->module->core->mainloop, TRUE, new_connection);
207     c->client = client;
208
209     c->client->kill = client_kill_cb;
210     c->client->send_event = client_send_event_cb;
211     c->client->userdata = c;
212
213     pa_assert_se(dbus_connection_add_filter(new_connection, disconnection_filter_cb, c, NULL));
214
215     pa_idxset_put(s->userdata->connections, c, NULL);
216
217     pa_assert_se(pa_dbus_protocol_register_connection(s->userdata->dbus_protocol, new_connection, c->client) >= 0);
218 }
219
220 /* Called by PA mainloop when a D-Bus fd watch event needs handling. */
221 static void io_event_cb(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
222     unsigned int flags = 0;
223     DBusWatch *watch = userdata;
224
225 #if HAVE_DBUS_WATCH_GET_UNIX_FD
226     pa_assert(fd == dbus_watch_get_unix_fd(watch));
227 #else
228     pa_assert(fd == dbus_watch_get_fd(watch));
229 #endif
230
231     if (!dbus_watch_get_enabled(watch)) {
232         pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd);
233         return;
234     }
235
236     if (events & PA_IO_EVENT_INPUT)
237         flags |= DBUS_WATCH_READABLE;
238     if (events & PA_IO_EVENT_OUTPUT)
239         flags |= DBUS_WATCH_WRITABLE;
240     if (events & PA_IO_EVENT_HANGUP)
241         flags |= DBUS_WATCH_HANGUP;
242     if (events & PA_IO_EVENT_ERROR)
243         flags |= DBUS_WATCH_ERROR;
244
245     dbus_watch_handle(watch, flags);
246 }
247
248 /* Called by PA mainloop when a D-Bus timer event needs handling. */
249 static void time_event_cb(pa_mainloop_api *mainloop, pa_time_event* e, const struct timeval *tv, void *userdata) {
250     DBusTimeout *timeout = userdata;
251
252     if (dbus_timeout_get_enabled(timeout)) {
253         struct timeval next = *tv;
254         dbus_timeout_handle(timeout);
255
256         /* restart it for the next scheduled time */
257         pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
258         mainloop->time_restart(e, &next);
259     }
260 }
261
262 /* Translates D-Bus fd watch event flags to PA IO event flags. */
263 static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) {
264     unsigned int flags;
265     pa_io_event_flags_t events = 0;
266
267     pa_assert(watch);
268
269     flags = dbus_watch_get_flags(watch);
270
271     /* no watch flags for disabled watches */
272     if (!dbus_watch_get_enabled(watch))
273         return PA_IO_EVENT_NULL;
274
275     if (flags & DBUS_WATCH_READABLE)
276         events |= PA_IO_EVENT_INPUT;
277     if (flags & DBUS_WATCH_WRITABLE)
278         events |= PA_IO_EVENT_OUTPUT;
279
280     return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR;
281 }
282
283 /* Called by D-Bus when a D-Bus fd watch event is added. */
284 static dbus_bool_t watch_add_cb(DBusWatch *watch, void *data) {
285     struct server *s = data;
286     pa_mainloop_api *mainloop;
287     pa_io_event *ev;
288
289     pa_assert(watch);
290     pa_assert(s);
291
292     mainloop = s->userdata->module->core->mainloop;
293
294     ev = mainloop->io_new(
295             mainloop,
296 #if HAVE_DBUS_WATCH_GET_UNIX_FD
297             dbus_watch_get_unix_fd(watch),
298 #else
299             dbus_watch_get_fd(watch),
300 #endif
301             get_watch_flags(watch), io_event_cb, watch);
302
303     dbus_watch_set_data(watch, ev, NULL);
304
305     return TRUE;
306 }
307
308 /* Called by D-Bus when a D-Bus fd watch event is removed. */
309 static void watch_remove_cb(DBusWatch *watch, void *data) {
310     struct server *s = data;
311     pa_io_event *ev;
312
313     pa_assert(watch);
314     pa_assert(s);
315
316     if ((ev = dbus_watch_get_data(watch)))
317         s->userdata->module->core->mainloop->io_free(ev);
318 }
319
320 /* Called by D-Bus when a D-Bus fd watch event is toggled. */
321 static void watch_toggled_cb(DBusWatch *watch, void *data) {
322     struct server *s = data;
323     pa_io_event *ev;
324
325     pa_assert(watch);
326     pa_assert(s);
327
328     pa_assert_se(ev = dbus_watch_get_data(watch));
329
330     /* get_watch_flags() checks if the watch is enabled */
331     s->userdata->module->core->mainloop->io_enable(ev, get_watch_flags(watch));
332 }
333
334 /* Called by D-Bus when a D-Bus timer event is added. */
335 static dbus_bool_t timeout_add_cb(DBusTimeout *timeout, void *data) {
336     struct server *s = data;
337     pa_mainloop_api *mainloop;
338     pa_time_event *ev;
339     struct timeval tv;
340
341     pa_assert(timeout);
342     pa_assert(s);
343
344     if (!dbus_timeout_get_enabled(timeout))
345         return FALSE;
346
347     mainloop = s->userdata->module->core->mainloop;
348
349     pa_gettimeofday(&tv);
350     pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
351
352     ev = mainloop->time_new(mainloop, &tv, time_event_cb, timeout);
353
354     dbus_timeout_set_data(timeout, ev, NULL);
355
356     return TRUE;
357 }
358
359 /* Called by D-Bus when a D-Bus timer event is removed. */
360 static void timeout_remove_cb(DBusTimeout *timeout, void *data) {
361     struct server *s = data;
362     pa_time_event *ev;
363
364     pa_assert(timeout);
365     pa_assert(s);
366
367     if ((ev = dbus_timeout_get_data(timeout)))
368         s->userdata->module->core->mainloop->time_free(ev);
369 }
370
371 /* Called by D-Bus when a D-Bus timer event is toggled. */
372 static void timeout_toggled_cb(DBusTimeout *timeout, void *data) {
373     struct server *s = data;
374     pa_mainloop_api *mainloop;
375     pa_time_event *ev;
376
377     pa_assert(timeout);
378     pa_assert(s);
379
380     mainloop = s->userdata->module->core->mainloop;
381
382     pa_assert_se(ev = dbus_timeout_get_data(timeout));
383
384     if (dbus_timeout_get_enabled(timeout)) {
385         struct timeval tv;
386
387         pa_gettimeofday(&tv);
388         pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
389
390         mainloop->time_restart(ev, &tv);
391     } else
392         mainloop->time_restart(ev, NULL);
393 }
394
395 static void server_free(struct server *s) {
396     pa_assert(s);
397
398     if (s->dbus_server) {
399         dbus_server_disconnect(s->dbus_server);
400         dbus_server_unref(s->dbus_server);
401     }
402
403     pa_xfree(s);
404 }
405
406 static struct server *start_server(struct userdata *u, const char *address, enum server_type type) {
407     /* XXX: We assume that when we unref the DBusServer instance at module
408      * shutdown, nobody else holds any references to it. If we stop assuming
409      * that someday, dbus_server_set_new_connection_function,
410      * dbus_server_set_watch_functions and dbus_server_set_timeout_functions
411      * calls should probably register free callbacks, instead of providing NULL
412      * as they do now. */
413
414     struct server *s = NULL;
415     DBusError error;
416
417     pa_assert(u);
418     pa_assert(address);
419
420     dbus_error_init(&error);
421
422     s = pa_xnew0(struct server, 1);
423     s->userdata = u;
424     s->type = type;
425     s->dbus_server = dbus_server_listen(address, &error);
426
427     if (dbus_error_is_set(&error)) {
428         pa_log("dbus_server_listen() failed: %s: %s", error.name, error.message);
429         goto fail;
430     }
431
432     dbus_server_set_new_connection_function(s->dbus_server, connection_new_cb, s, NULL);
433
434     if (!dbus_server_set_watch_functions(s->dbus_server, watch_add_cb, watch_remove_cb, watch_toggled_cb, s, NULL)) {
435         pa_log("dbus_server_set_watch_functions() ran out of memory.");
436         goto fail;
437     }
438
439     if (!dbus_server_set_timeout_functions(s->dbus_server, timeout_add_cb, timeout_remove_cb, timeout_toggled_cb, s, NULL)) {
440         pa_log("dbus_server_set_timeout_functions() ran out of memory.");
441         goto fail;
442     }
443
444     return s;
445
446 fail:
447     if (s)
448         server_free(s);
449
450     dbus_error_free(&error);
451
452     return NULL;
453 }
454
455 static struct server *start_local_server(struct userdata *u) {
456     struct server *s = NULL;
457     char *address = NULL;
458
459     pa_assert(u);
460
461     address = pa_get_dbus_address_from_server_type(u->module->core->server_type);
462
463     s = start_server(u, address, SERVER_TYPE_LOCAL); /* May return NULL */
464
465     pa_xfree(address);
466
467     return s;
468 }
469
470 static struct server *start_tcp_server(struct userdata *u) {
471     struct server *s = NULL;
472     char *address = NULL;
473
474     pa_assert(u);
475
476     address = pa_sprintf_malloc("tcp:host=%s,port=%u", u->tcp_listen, u->tcp_port);
477
478     s = start_server(u, address, SERVER_TYPE_TCP); /* May return NULL */
479
480     pa_xfree(address);
481
482     return s;
483 }
484
485 static int get_access_arg(pa_modargs *ma, pa_bool_t *local_access, pa_bool_t *remote_access) {
486     const char *value = NULL;
487
488     pa_assert(ma);
489     pa_assert(local_access);
490     pa_assert(remote_access);
491
492     if (!(value = pa_modargs_get_value(ma, "access", NULL)))
493         return 0;
494
495     if (!strcmp(value, "local")) {
496         *local_access = TRUE;
497         *remote_access = FALSE;
498     } else if (!strcmp(value, "remote")) {
499         *local_access = FALSE;
500         *remote_access = TRUE;
501     } else if (!strcmp(value, "local,remote")) {
502         *local_access = TRUE;
503         *remote_access = TRUE;
504     } else
505         return -1;
506
507     return 0;
508 }
509
510 /* Frees dead client connections. */
511 static void cleanup_cb(pa_mainloop_api *a, pa_defer_event *e, void *userdata) {
512     struct userdata *u = userdata;
513     struct connection *conn = NULL;
514     uint32_t idx;
515
516     PA_IDXSET_FOREACH(conn, u->connections, idx) {
517         if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn)))
518             connection_free(conn);
519     }
520
521     u->module->core->mainloop->defer_enable(e, 0);
522 }
523
524 int pa__init(pa_module *m) {
525     struct userdata *u = NULL;
526     pa_modargs *ma = NULL;
527
528     pa_assert(m);
529
530     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
531         pa_log("Failed to parse module arguments.");
532         goto fail;
533     }
534
535     m->userdata = u = pa_xnew0(struct userdata, 1);
536     u->module = m;
537     u->local_access = TRUE;
538     u->remote_access = FALSE;
539     u->tcp_port = PA_DBUS_DEFAULT_PORT;
540
541     if (get_access_arg(ma, &u->local_access, &u->remote_access) < 0) {
542         pa_log("Invalid access argument: '%s'", pa_modargs_get_value(ma, "access", NULL));
543         goto fail;
544     }
545
546     if (pa_modargs_get_value_u32(ma, "tcp_port", &u->tcp_port) < 0 || u->tcp_port < 1 || u->tcp_port > 49150) {
547         pa_log("Invalid tcp_port argument: '%s'", pa_modargs_get_value(ma, "tcp_port", NULL));
548         goto fail;
549     }
550
551     u->tcp_listen = pa_xstrdup(pa_modargs_get_value(ma, "tcp_listen", "0.0.0.0"));
552
553     if (u->local_access && !(u->local_server = start_local_server(u))) {
554         pa_log("Starting the local D-Bus server failed.");
555         goto fail;
556     }
557
558     if (u->remote_access && !(u->tcp_server = start_tcp_server(u))) {
559         pa_log("Starting the D-Bus server for remote connections failed.");
560         goto fail;
561     }
562
563     u->connections = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
564
565     u->cleanup_event = m->core->mainloop->defer_new(m->core->mainloop, cleanup_cb, u);
566     m->core->mainloop->defer_enable(u->cleanup_event, 0);
567
568     u->dbus_protocol = pa_dbus_protocol_get(m->core);
569     u->core_iface = pa_dbusiface_core_new(m->core);
570
571     return 0;
572
573 fail:
574     if (ma)
575         pa_modargs_free(ma);
576
577     pa__done(m);
578
579     return -1;
580 }
581
582 /* Called by idxset when the connection set is freed. */
583 static void connection_free_cb(void *p, void *userdata) {
584     struct connection *conn = p;
585
586     pa_assert(conn);
587
588     connection_free(conn);
589 }
590
591 void pa__done(pa_module *m) {
592     struct userdata *u;
593
594     pa_assert(m);
595
596     if (!(u = m->userdata))
597         return;
598
599     if (u->core_iface)
600         pa_dbusiface_core_free(u->core_iface);
601
602     if (u->cleanup_event)
603         m->core->mainloop->defer_free(u->cleanup_event);
604
605     if (u->connections)
606         pa_idxset_free(u->connections, connection_free_cb, NULL);
607
608     if (u->tcp_server)
609         server_free(u->tcp_server);
610
611     if (u->local_server)
612         server_free(u->local_server);
613
614     if (u->dbus_protocol)
615         pa_dbus_protocol_unref(u->dbus_protocol);
616
617     pa_xfree(u->tcp_listen);
618     pa_xfree(u);
619     m->userdata = NULL;
620 }