dbus: Fix connection idxset freeing when unloading the module.
[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_dbus_wrap_connection_free(c->wrap_conn);
109     pa_xfree(c);
110 }
111
112 /* Called from pa_client_kill(). */
113 static void client_kill_cb(pa_client *c) {
114     struct connection *conn;
115
116     pa_assert(c);
117     pa_assert(c->userdata);
118
119     conn = c->userdata;
120     connection_free(conn);
121     c->userdata = NULL;
122
123     pa_log_info("Connection killed.");
124 }
125
126 /* Called from pa_client_send_event(). */
127 static void client_send_event_cb(pa_client *c, const char *name, pa_proplist *data) {
128     struct connection *conn = NULL;
129     DBusMessage *signal_msg = NULL;
130     DBusMessageIter msg_iter;
131
132     pa_assert(c);
133     pa_assert(name);
134     pa_assert(data);
135     pa_assert(c->userdata);
136
137     conn = c->userdata;
138
139     pa_assert_se(signal_msg = dbus_message_new_signal(pa_dbusiface_core_get_client_path(conn->server->userdata->core_iface, c),
140                                                       PA_DBUSIFACE_CLIENT_INTERFACE,
141                                                       "ClientEvent"));
142     dbus_message_iter_init_append(signal_msg, &msg_iter);
143     pa_assert_se(dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &name));
144     pa_dbus_append_proplist(&msg_iter, data);
145
146     pa_assert_se(dbus_connection_send(pa_dbus_wrap_connection_get(conn->wrap_conn), signal_msg, NULL));
147     dbus_message_unref(signal_msg);
148 }
149
150 /* Called by D-Bus at the authentication phase. */
151 static dbus_bool_t user_check_cb(DBusConnection *connection, unsigned long uid, void *data) {
152     pa_log_debug("Allowing connection by user %lu.", uid);
153
154     return TRUE;
155 }
156
157 static DBusHandlerResult disconnection_filter_cb(DBusConnection *connection, DBusMessage *message, void *user_data) {
158     struct connection *c = user_data;
159
160     pa_assert(connection);
161     pa_assert(message);
162     pa_assert(c);
163
164     if (dbus_message_is_signal(message, "org.freedesktop.DBus.Local", "Disconnected")) {
165         /* The connection died. Now we want to free the connection object, but
166          * let's wait until this message is fully processed, in case someone
167          * else is interested in this signal too. */
168         c->server->userdata->module->core->mainloop->defer_enable(c->server->userdata->cleanup_event, 1);
169     }
170
171     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
172 }
173
174 /* Called by D-Bus when a new client connection is received. */
175 static void connection_new_cb(DBusServer *dbus_server, DBusConnection *new_connection, void *data) {
176     struct server *s = data;
177     struct connection *c;
178     pa_client_new_data new_data;
179     pa_client *client;
180
181     pa_assert(new_connection);
182     pa_assert(s);
183
184     pa_client_new_data_init(&new_data);
185     new_data.module = s->userdata->module;
186     new_data.driver = __FILE__;
187     pa_proplist_sets(new_data.proplist, PA_PROP_APPLICATION_NAME, "D-Bus client");
188     client = pa_client_new(s->userdata->module->core, &new_data);
189     pa_client_new_data_done(&new_data);
190
191     if (!client) {
192         dbus_connection_close(new_connection);
193         return;
194     }
195
196     if (s->type == SERVER_TYPE_TCP || s->userdata->module->core->server_type == PA_SERVER_TYPE_SYSTEM) {
197         /* FIXME: Here we allow anyone from anywhere to access the server,
198          * anonymously. Access control should be configurable. */
199         dbus_connection_set_unix_user_function(new_connection, user_check_cb, NULL, NULL);
200         dbus_connection_set_allow_anonymous(new_connection, TRUE);
201     }
202
203     c = pa_xnew(struct connection, 1);
204     c->server = s;
205     c->wrap_conn = pa_dbus_wrap_connection_new_from_existing(s->userdata->module->core->mainloop, TRUE, new_connection);
206     c->client = client;
207
208     c->client->kill = client_kill_cb;
209     c->client->send_event = client_send_event_cb;
210     c->client->userdata = c;
211
212     pa_assert_se(dbus_connection_add_filter(new_connection, disconnection_filter_cb, c, NULL));
213
214     pa_idxset_put(s->userdata->connections, c, NULL);
215
216     pa_assert_se(pa_dbus_protocol_register_connection(s->userdata->dbus_protocol, new_connection, c->client) >= 0);
217 }
218
219 /* Called by PA mainloop when a D-Bus fd watch event needs handling. */
220 static void io_event_cb(pa_mainloop_api *mainloop, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata) {
221     unsigned int flags = 0;
222     DBusWatch *watch = userdata;
223
224 #if HAVE_DBUS_WATCH_GET_UNIX_FD
225     pa_assert(fd == dbus_watch_get_unix_fd(watch));
226 #else
227     pa_assert(fd == dbus_watch_get_fd(watch));
228 #endif
229
230     if (!dbus_watch_get_enabled(watch)) {
231         pa_log_warn("Asked to handle disabled watch: %p %i", (void*) watch, fd);
232         return;
233     }
234
235     if (events & PA_IO_EVENT_INPUT)
236         flags |= DBUS_WATCH_READABLE;
237     if (events & PA_IO_EVENT_OUTPUT)
238         flags |= DBUS_WATCH_WRITABLE;
239     if (events & PA_IO_EVENT_HANGUP)
240         flags |= DBUS_WATCH_HANGUP;
241     if (events & PA_IO_EVENT_ERROR)
242         flags |= DBUS_WATCH_ERROR;
243
244     dbus_watch_handle(watch, flags);
245 }
246
247 /* Called by PA mainloop when a D-Bus timer event needs handling. */
248 static void time_event_cb(pa_mainloop_api *mainloop, pa_time_event* e, const struct timeval *tv, void *userdata) {
249     DBusTimeout *timeout = userdata;
250
251     if (dbus_timeout_get_enabled(timeout)) {
252         struct timeval next = *tv;
253         dbus_timeout_handle(timeout);
254
255         /* restart it for the next scheduled time */
256         pa_timeval_add(&next, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
257         mainloop->time_restart(e, &next);
258     }
259 }
260
261 /* Translates D-Bus fd watch event flags to PA IO event flags. */
262 static pa_io_event_flags_t get_watch_flags(DBusWatch *watch) {
263     unsigned int flags;
264     pa_io_event_flags_t events = 0;
265
266     pa_assert(watch);
267
268     flags = dbus_watch_get_flags(watch);
269
270     /* no watch flags for disabled watches */
271     if (!dbus_watch_get_enabled(watch))
272         return PA_IO_EVENT_NULL;
273
274     if (flags & DBUS_WATCH_READABLE)
275         events |= PA_IO_EVENT_INPUT;
276     if (flags & DBUS_WATCH_WRITABLE)
277         events |= PA_IO_EVENT_OUTPUT;
278
279     return events | PA_IO_EVENT_HANGUP | PA_IO_EVENT_ERROR;
280 }
281
282 /* Called by D-Bus when a D-Bus fd watch event is added. */
283 static dbus_bool_t watch_add_cb(DBusWatch *watch, void *data) {
284     struct server *s = data;
285     pa_mainloop_api *mainloop;
286     pa_io_event *ev;
287
288     pa_assert(watch);
289     pa_assert(s);
290
291     mainloop = s->userdata->module->core->mainloop;
292
293     ev = mainloop->io_new(
294             mainloop,
295 #if HAVE_DBUS_WATCH_GET_UNIX_FD
296             dbus_watch_get_unix_fd(watch),
297 #else
298             dbus_watch_get_fd(watch),
299 #endif
300             get_watch_flags(watch), io_event_cb, watch);
301
302     dbus_watch_set_data(watch, ev, NULL);
303
304     return TRUE;
305 }
306
307 /* Called by D-Bus when a D-Bus fd watch event is removed. */
308 static void watch_remove_cb(DBusWatch *watch, void *data) {
309     struct server *s = data;
310     pa_io_event *ev;
311
312     pa_assert(watch);
313     pa_assert(s);
314
315     if ((ev = dbus_watch_get_data(watch)))
316         s->userdata->module->core->mainloop->io_free(ev);
317 }
318
319 /* Called by D-Bus when a D-Bus fd watch event is toggled. */
320 static void watch_toggled_cb(DBusWatch *watch, void *data) {
321     struct server *s = data;
322     pa_io_event *ev;
323
324     pa_assert(watch);
325     pa_assert(s);
326
327     pa_assert_se(ev = dbus_watch_get_data(watch));
328
329     /* get_watch_flags() checks if the watch is enabled */
330     s->userdata->module->core->mainloop->io_enable(ev, get_watch_flags(watch));
331 }
332
333 /* Called by D-Bus when a D-Bus timer event is added. */
334 static dbus_bool_t timeout_add_cb(DBusTimeout *timeout, void *data) {
335     struct server *s = data;
336     pa_mainloop_api *mainloop;
337     pa_time_event *ev;
338     struct timeval tv;
339
340     pa_assert(timeout);
341     pa_assert(s);
342
343     if (!dbus_timeout_get_enabled(timeout))
344         return FALSE;
345
346     mainloop = s->userdata->module->core->mainloop;
347
348     pa_gettimeofday(&tv);
349     pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
350
351     ev = mainloop->time_new(mainloop, &tv, time_event_cb, timeout);
352
353     dbus_timeout_set_data(timeout, ev, NULL);
354
355     return TRUE;
356 }
357
358 /* Called by D-Bus when a D-Bus timer event is removed. */
359 static void timeout_remove_cb(DBusTimeout *timeout, void *data) {
360     struct server *s = data;
361     pa_time_event *ev;
362
363     pa_assert(timeout);
364     pa_assert(s);
365
366     if ((ev = dbus_timeout_get_data(timeout)))
367         s->userdata->module->core->mainloop->time_free(ev);
368 }
369
370 /* Called by D-Bus when a D-Bus timer event is toggled. */
371 static void timeout_toggled_cb(DBusTimeout *timeout, void *data) {
372     struct server *s = data;
373     pa_mainloop_api *mainloop;
374     pa_time_event *ev;
375
376     pa_assert(timeout);
377     pa_assert(s);
378
379     mainloop = s->userdata->module->core->mainloop;
380
381     pa_assert_se(ev = dbus_timeout_get_data(timeout));
382
383     if (dbus_timeout_get_enabled(timeout)) {
384         struct timeval tv;
385
386         pa_gettimeofday(&tv);
387         pa_timeval_add(&tv, (pa_usec_t) dbus_timeout_get_interval(timeout) * 1000);
388
389         mainloop->time_restart(ev, &tv);
390     } else
391         mainloop->time_restart(ev, NULL);
392 }
393
394 static void server_free(struct server *s) {
395     pa_assert(s);
396
397     if (s->dbus_server) {
398         dbus_server_disconnect(s->dbus_server);
399         dbus_server_unref(s->dbus_server);
400     }
401
402     pa_xfree(s);
403 }
404
405 static struct server *start_server(struct userdata *u, const char *address, enum server_type type) {
406     /* XXX: We assume that when we unref the DBusServer instance at module
407      * shutdown, nobody else holds any references to it. If we stop assuming
408      * that someday, dbus_server_set_new_connection_function,
409      * dbus_server_set_watch_functions and dbus_server_set_timeout_functions
410      * calls should probably register free callbacks, instead of providing NULL
411      * as they do now. */
412
413     struct server *s = NULL;
414     DBusError error;
415
416     pa_assert(u);
417     pa_assert(address);
418
419     dbus_error_init(&error);
420
421     s = pa_xnew0(struct server, 1);
422     s->userdata = u;
423     s->type = type;
424     s->dbus_server = dbus_server_listen(address, &error);
425
426     if (dbus_error_is_set(&error)) {
427         pa_log("dbus_server_listen() failed: %s: %s", error.name, error.message);
428         goto fail;
429     }
430
431     dbus_server_set_new_connection_function(s->dbus_server, connection_new_cb, s, NULL);
432
433     if (!dbus_server_set_watch_functions(s->dbus_server, watch_add_cb, watch_remove_cb, watch_toggled_cb, s, NULL)) {
434         pa_log("dbus_server_set_watch_functions() ran out of memory.");
435         goto fail;
436     }
437
438     if (!dbus_server_set_timeout_functions(s->dbus_server, timeout_add_cb, timeout_remove_cb, timeout_toggled_cb, s, NULL)) {
439         pa_log("dbus_server_set_timeout_functions() ran out of memory.");
440         goto fail;
441     }
442
443     return s;
444
445 fail:
446     if (s)
447         server_free(s);
448
449     dbus_error_free(&error);
450
451     return NULL;
452 }
453
454 static struct server *start_local_server(struct userdata *u) {
455     struct server *s = NULL;
456     char *address = NULL;
457
458     pa_assert(u);
459
460     address = pa_get_dbus_address_from_server_type(u->module->core->server_type);
461
462     s = start_server(u, address, SERVER_TYPE_LOCAL); /* May return NULL */
463
464     pa_xfree(address);
465
466     return s;
467 }
468
469 static struct server *start_tcp_server(struct userdata *u) {
470     struct server *s = NULL;
471     char *address = NULL;
472
473     pa_assert(u);
474
475     address = pa_sprintf_malloc("tcp:host=%s,port=%u", u->tcp_listen, u->tcp_port);
476
477     s = start_server(u, address, SERVER_TYPE_TCP); /* May return NULL */
478
479     pa_xfree(address);
480
481     return s;
482 }
483
484 static int get_access_arg(pa_modargs *ma, pa_bool_t *local_access, pa_bool_t *remote_access) {
485     const char *value = NULL;
486
487     pa_assert(ma);
488     pa_assert(local_access);
489     pa_assert(remote_access);
490
491     if (!(value = pa_modargs_get_value(ma, "access", NULL)))
492         return 0;
493
494     if (!strcmp(value, "local")) {
495         *local_access = TRUE;
496         *remote_access = FALSE;
497     } else if (!strcmp(value, "remote")) {
498         *local_access = FALSE;
499         *remote_access = TRUE;
500     } else if (!strcmp(value, "local,remote")) {
501         *local_access = TRUE;
502         *remote_access = TRUE;
503     } else
504         return -1;
505
506     return 0;
507 }
508
509 /* Frees dead client connections. */
510 static void cleanup_cb(pa_mainloop_api *a, pa_defer_event *e, void *userdata) {
511     struct userdata *u = userdata;
512     struct connection *conn = NULL;
513     uint32_t idx;
514
515     PA_IDXSET_FOREACH(conn, u->connections, idx) {
516         if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn))) {
517             pa_idxset_remove_by_data(u->connections, conn, NULL);
518             connection_free(conn);
519         }
520     }
521
522     u->module->core->mainloop->defer_enable(e, 0);
523 }
524
525 int pa__init(pa_module *m) {
526     struct userdata *u = NULL;
527     pa_modargs *ma = NULL;
528
529     pa_assert(m);
530
531     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
532         pa_log("Failed to parse module arguments.");
533         goto fail;
534     }
535
536     m->userdata = u = pa_xnew0(struct userdata, 1);
537     u->module = m;
538     u->local_access = TRUE;
539     u->remote_access = FALSE;
540     u->tcp_port = PA_DBUS_DEFAULT_PORT;
541
542     if (get_access_arg(ma, &u->local_access, &u->remote_access) < 0) {
543         pa_log("Invalid access argument: '%s'", pa_modargs_get_value(ma, "access", NULL));
544         goto fail;
545     }
546
547     if (pa_modargs_get_value_u32(ma, "tcp_port", &u->tcp_port) < 0 || u->tcp_port < 1 || u->tcp_port > 49150) {
548         pa_log("Invalid tcp_port argument: '%s'", pa_modargs_get_value(ma, "tcp_port", NULL));
549         goto fail;
550     }
551
552     u->tcp_listen = pa_xstrdup(pa_modargs_get_value(ma, "tcp_listen", "0.0.0.0"));
553
554     if (u->local_access && !(u->local_server = start_local_server(u))) {
555         pa_log("Starting the local D-Bus server failed.");
556         goto fail;
557     }
558
559     if (u->remote_access && !(u->tcp_server = start_tcp_server(u))) {
560         pa_log("Starting the D-Bus server for remote connections failed.");
561         goto fail;
562     }
563
564     u->connections = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
565
566     u->cleanup_event = m->core->mainloop->defer_new(m->core->mainloop, cleanup_cb, u);
567     m->core->mainloop->defer_enable(u->cleanup_event, 0);
568
569     u->dbus_protocol = pa_dbus_protocol_get(m->core);
570     u->core_iface = pa_dbusiface_core_new(m->core);
571
572     return 0;
573
574 fail:
575     if (ma)
576         pa_modargs_free(ma);
577
578     pa__done(m);
579
580     return -1;
581 }
582
583 void pa__done(pa_module *m) {
584     struct userdata *u;
585     struct connection *c;
586
587     pa_assert(m);
588
589     if (!(u = m->userdata))
590         return;
591
592     if (u->core_iface)
593         pa_dbusiface_core_free(u->core_iface);
594
595     if (u->cleanup_event)
596         m->core->mainloop->defer_free(u->cleanup_event);
597
598     while ((c = pa_idxset_steal_first(u->connections, NULL)))
599         connection_free(c);
600
601     pa_idxset_free(u->connections, NULL, NULL);
602
603     if (u->tcp_server)
604         server_free(u->tcp_server);
605
606     if (u->local_server)
607         server_free(u->local_server);
608
609     if (u->dbus_protocol)
610         pa_dbus_protocol_unref(u->dbus_protocol);
611
612     pa_xfree(u->tcp_listen);
613     pa_xfree(u);
614     m->userdata = NULL;
615 }