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