From c94e7421aad58c7714f6e26f20642c51af17cc4d Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Wed, 3 Jun 2009 15:21:50 +0300 Subject: Create module-dbus-protocol with "Hello, world!" functionality. --- src/daemon/default.pa.in | 3 +++ src/daemon/system.pa.in | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src/daemon') diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in index fa0683e1..ba8e3c80 100755 --- a/src/daemon/default.pa.in +++ b/src/daemon/default.pa.in @@ -66,6 +66,9 @@ load-module module-bluetooth-discover .ifexists module-esound-protocol-unix@PA_SOEXT@ load-module module-esound-protocol-unix .endif +.ifexists module-dbus-protocol@PA_SOEXT@ +load-module module-dbus-protocol +.endif load-module module-native-protocol-unix ### Network access (may be configured with paprefs, so leave this commented diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in index 27e42815..5541bbe4 100755 --- a/src/daemon/system.pa.in +++ b/src/daemon/system.pa.in @@ -32,6 +32,9 @@ load-module module-detect .ifexists module-esound-protocol-unix@PA_SOEXT@ load-module module-esound-protocol-unix .endif +.ifexists module-dbus-protocol@PA_SOEXT@ +load-module module-dbus-protocol +.endif load-module module-native-protocol-unix ### Automatically restore the volume of streams and devices -- cgit From 5babbaafb26ac4f83db0d8bca53006a843472b8f Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Fri, 12 Jun 2009 07:16:05 +0300 Subject: daemon: Implement the DBus server lookup service. --- src/daemon/daemon-conf.c | 48 ++++++++ src/daemon/daemon-conf.h | 9 ++ src/daemon/daemon.conf.in | 1 + src/daemon/main.c | 136 ++++++++++++++++------ src/daemon/server-lookup.c | 277 +++++++++++++++++++++++++++++++++++++++++++++ src/daemon/server-lookup.h | 42 +++++++ 6 files changed, 480 insertions(+), 33 deletions(-) create mode 100644 src/daemon/server-lookup.c create mode 100644 src/daemon/server-lookup.h (limited to 'src/daemon') diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c index ac6cc8aa..e6fa8c64 100644 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@ -83,6 +83,9 @@ static const pa_daemon_conf default_conf = { .config_file = NULL, .use_pid_file = TRUE, .system_instance = FALSE, +#ifdef HAVE_DBUS + .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */ +#endif .no_cpu_limit = FALSE, .disable_shm = FALSE, .default_n_fragments = 4, @@ -203,6 +206,22 @@ int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) { return 0; } +int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string) { + pa_assert(c); + pa_assert(string); + + if (!strcmp(string, "user")) + c->local_server_type = PA_SERVER_TYPE_USER; + else if (!strcmp(string, "system")) { + c->local_server_type = PA_SERVER_TYPE_SYSTEM; + } else if (!strcmp(string, "none")) { + c->local_server_type = PA_SERVER_TYPE_NONE; + } else + return -1; + + return 0; +} + static int parse_log_target(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { pa_daemon_conf *c = data; @@ -430,6 +449,22 @@ static int parse_rtprio(const char *filename, unsigned line, const char *section return 0; } +static int parse_server_type(const char *filename, unsigned line, const char *section, const char *lvalue, const char *rvalue, void *data, void *userdata) { + pa_daemon_conf *c = data; + + pa_assert(filename); + pa_assert(lvalue); + pa_assert(rvalue); + pa_assert(data); + + if (pa_daemon_conf_set_local_server_type(c, rvalue) < 0) { + pa_log(_("[%s:%u] Invalid server type '%s'."), filename, line, rvalue); + return -1; + } + + return 0; +} + int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { int r = -1; FILE *f = NULL; @@ -443,6 +478,9 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) { { "disallow-exit", pa_config_parse_bool, &c->disallow_exit, NULL }, { "use-pid-file", pa_config_parse_bool, &c->use_pid_file, NULL }, { "system-instance", pa_config_parse_bool, &c->system_instance, NULL }, +#ifdef HAVE_DBUS + { "local-server-type", parse_server_type, c, NULL }, +#endif { "no-cpu-limit", pa_config_parse_bool, &c->no_cpu_limit, NULL }, { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, { "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL }, @@ -604,6 +642,13 @@ static const char* const log_level_to_string[] = { [PA_LOG_ERROR] = "error" }; +static const char* const server_type_to_string[] = { + [PA_SERVER_TYPE_UNSET] = "!!UNSET!!", + [PA_SERVER_TYPE_USER] = "user", + [PA_SERVER_TYPE_SYSTEM] = "system", + [PA_SERVER_TYPE_NONE] = "none" +}; + char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf *s; char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; @@ -627,6 +672,9 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) { pa_strbuf_printf(s, "disallow-exit = %s\n", pa_yes_no(c->disallow_exit)); pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); +#ifdef HAVE_DBUS + pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]); +#endif pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit)); pa_strbuf_printf(s, "disable-shm = %s\n", pa_yes_no(c->disable_shm)); pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 9cec189f..98db8641 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -48,6 +48,13 @@ typedef enum pa_daemon_conf_cmd { PA_CMD_CLEANUP_SHM } pa_daemon_conf_cmd_t; +typedef enum pa_daemon_conf_server_type { + PA_SERVER_TYPE_UNSET, + PA_SERVER_TYPE_USER, + PA_SERVER_TYPE_SYSTEM, + PA_SERVER_TYPE_NONE +} pa_daemon_conf_server_type_t; + #ifdef HAVE_SYS_RESOURCE_H typedef struct pa_rlimit { rlim_t value; @@ -74,6 +81,7 @@ typedef struct pa_daemon_conf { log_meta, log_time, flat_volumes; + pa_daemon_conf_server_type_t local_server_type; int exit_idle_time, scache_idle_time, auto_log_target, @@ -151,6 +159,7 @@ int pa_daemon_conf_env(pa_daemon_conf *c); int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string); int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string); int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string); +int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string); const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c); FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c); diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in index fcd2513a..ecdb3a64 100644 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@ -25,6 +25,7 @@ ; disallow-exit = no ; use-pid-file = yes ; system-instance = no +; local-server-type = user ; disable-shm = no ; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB diff --git a/src/daemon/main.c b/src/daemon/main.c index 3e50baad..1b6ed793 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -99,6 +99,7 @@ #include "caps.h" #include "ltdl-bind-now.h" #include "polkit.h" +#include "server-lookup.h" #ifdef HAVE_LIBWRAP /* Only one instance of these variables */ @@ -335,33 +336,31 @@ static void set_all_rlimits(const pa_daemon_conf *conf) { #endif #ifdef HAVE_DBUS -static pa_dbus_connection *register_dbus(pa_core *c) { +static pa_dbus_connection *register_dbus_name(pa_core *c, DBusBusType bus, const char* name) { DBusError error; pa_dbus_connection *conn; dbus_error_init(&error); - if (!(conn = pa_dbus_bus_get(c, pa_in_system_mode() ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { + if (!(conn = pa_dbus_bus_get(c, bus, &error)) || dbus_error_is_set(&error)) { pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message); goto fail; } - if (dbus_bus_request_name(pa_dbus_connection_get(conn), "org.pulseaudio.Server", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - pa_log_debug("Got org.pulseaudio.Server!"); + if (dbus_bus_request_name(pa_dbus_connection_get(conn), name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + pa_log_debug("Got %s!", name); return conn; } if (dbus_error_is_set(&error)) - pa_log_warn("Failed to acquire org.pulseaudio.Server: %s: %s", error.name, error.message); + pa_log_error("Failed to acquire %s: %s: %s", name, error.name, error.message); else - pa_log_warn("D-Bus name org.pulseaudio.Server already taken. Weird shit!"); + pa_log_error("D-Bus name %s already taken. Weird shit!", name); /* PA cannot be started twice by the same user and hence we can - * ignore mostly the case that org.pulseaudio.Server is already - * taken. */ + * ignore mostly the case that a name is already taken. */ fail: - if (conn) pa_dbus_connection_unref(conn); @@ -393,7 +392,10 @@ int main(int argc, char *argv[]) { int autospawn_fd = -1; pa_bool_t autospawn_locked = FALSE; #ifdef HAVE_DBUS - pa_dbus_connection *dbus = NULL; + pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */ + pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */ + pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */ + pa_bool_t start_server; #endif pa_log_set_ident("pulseaudio"); @@ -486,8 +488,45 @@ int main(int argc, char *argv[]) { pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET); pa_log_set_show_backtrace(conf->log_backtrace); +#ifdef HAVE_DBUS + /* conf->system_instance and conf->local_server_type control almost the + * same thing; make them agree about what is requested. */ + switch (conf->local_server_type) { + case PA_SERVER_TYPE_UNSET: + conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER; + break; + case PA_SERVER_TYPE_USER: + case PA_SERVER_TYPE_NONE: + conf->system_instance = FALSE; + break; + case PA_SERVER_TYPE_SYSTEM: + conf->system_instance = TRUE; + break; + default: + pa_assert_not_reached(); + } + + start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (real_root && conf->local_server_type == PA_SERVER_TYPE_SYSTEM); + + if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) { + pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service.")); + conf->system_instance = FALSE; + } +#endif + pa_log_debug("Started as real root: %s, suid root: %s", pa_yes_no(real_root), pa_yes_no(suid_root)); +#ifdef HAVE_DBUS + /* XXX: Uhh, goto programming... as if this wasn't hard enough to follow + * already. But if we won't start the full server, we want to just skip all + * the capability stuff. */ + if (!start_server) { + if (!real_root && pa_have_caps()) + pa_drop_caps(); + goto after_caps_setup; + } +#endif + if (!real_root && pa_have_caps()) { #ifdef HAVE_SYS_RESOURCE_H struct rlimit rl; @@ -628,6 +667,10 @@ int main(int argc, char *argv[]) { conf->realtime_scheduling = FALSE; } +#ifdef HAVE_DBUS +after_caps_setup: +#endif + pa_log_debug("Can realtime: %s, can high-priority: %s", pa_yes_no(pa_can_realtime()), pa_yes_no(pa_can_high_priority())); LTDL_SET_PRELOADED_SYMBOLS(); @@ -716,10 +759,12 @@ int main(int argc, char *argv[]) { if (real_root && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); +#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */ else if (!real_root && conf->system_instance) { pa_log(_("Root privileges required.")); goto finish; } +#endif if (conf->cmd == PA_CMD_START && conf->system_instance) { pa_log(_("--start not supported for system instances.")); @@ -1007,34 +1052,47 @@ int main(int argc, char *argv[]) { pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0); buf = pa_strbuf_new(); - if (conf->load_default_script_file) { - FILE *f; - if ((f = pa_daemon_conf_open_default_script_file(conf))) { - r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); - fclose(f); +#ifdef HAVE_DBUS + if (start_server) { +#endif + if (conf->load_default_script_file) { + FILE *f; + + if ((f = pa_daemon_conf_open_default_script_file(conf))) { + r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); + fclose(f); + } } - } - if (r >= 0) - r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); + if (r >= 0) + r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); - pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); - pa_xfree(s); + pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); + pa_xfree(s); - /* We completed the initial module loading, so let's disable it - * from now on, if requested */ - c->disallow_module_loading = !!conf->disallow_module_loading; + if (r < 0 && conf->fail) { + pa_log(_("Failed to initialize daemon.")); + goto finish; + } - if (r < 0 && conf->fail) { - pa_log(_("Failed to initialize daemon.")); - goto finish; + if (!c->modules || pa_idxset_size(c->modules) == 0) { + pa_log(_("Daemon startup without any loaded modules, refusing to work.")); + goto finish; + } +#ifdef HAVE_DBUS + } else { + /* When we just provide the D-Bus server lookup service, we don't want + * any modules to be loaded. We haven't loaded any so far, so one might + * think there's no way to contact the server, but receiving certain + * signals could still cause modules to load. */ + conf->disallow_module_loading = TRUE; } +#endif - if (!c->modules || pa_idxset_size(c->modules) == 0) { - pa_log(_("Daemon startup without any loaded modules, refusing to work.")); - goto finish; - } + /* We completed the initial module loading, so let's disable it + * from now on, if requested */ + c->disallow_module_loading = !!conf->disallow_module_loading; #ifdef HAVE_FORK if (daemon_pipe[1] >= 0) { @@ -1046,7 +1104,15 @@ int main(int argc, char *argv[]) { #endif #ifdef HAVE_DBUS - dbus = register_dbus(c); + if (!conf->system_instance) { + if (!(server_lookup = pa_dbusobj_server_lookup_new(c, conf->local_server_type))) + goto finish; + if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.pulseaudio.PulseAudio"))) + goto finish; + } + + if (start_server && !(server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server"))) + goto finish; #endif pa_log_info(_("Daemon startup complete.")); @@ -1059,8 +1125,12 @@ int main(int argc, char *argv[]) { finish: #ifdef HAVE_DBUS - if (dbus) - pa_dbus_connection_unref(dbus); + if (server_bus) + pa_dbus_connection_unref(server_bus); + if (lookup_service_bus) + pa_dbus_connection_unref(lookup_service_bus); + if (server_lookup) + pa_dbusobj_server_lookup_free(server_lookup); #endif if (autospawn_fd >= 0) { diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c new file mode 100644 index 00000000..867c3a1c --- /dev/null +++ b/src/daemon/server-lookup.c @@ -0,0 +1,277 @@ +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include + +#include +#include +#include + +#include "server-lookup.h" + +struct pa_dbusobj_server_lookup { + pa_dbus_connection *conn; + pa_bool_t path_registered; + pa_daemon_conf_server_type_t server_type; +}; + +static const char introspection[] = + DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "" + " \n" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +static void unregister_cb(DBusConnection *conn, void *user_data) { + pa_dbusobj_server_lookup *sl = user_data; + + pa_assert(sl); + pa_assert(sl->path_registered); + + sl->path_registered = FALSE; +} + +static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + const char *i = introspection; + DBusMessage *reply = NULL; + + pa_assert(conn); + pa_assert(msg); + + if (!(reply = dbus_message_new_method_return(msg))) + goto fail; + + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &i, DBUS_TYPE_INVALID)) + goto fail; + + if (!dbus_connection_send(conn, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + +fail: + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +oom: + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +/* Caller frees the string. */ +static char *get_dbus_server_from_type(pa_daemon_conf_server_type_t server_type) { + char *server_string = NULL; + char *runtime_dir = NULL; + + switch (server_type) { + case PA_SERVER_TYPE_USER: + runtime_dir = pa_get_runtime_dir(); + + if (!runtime_dir) + return NULL; + + server_string = pa_sprintf_malloc("unix:path=%s/dbus_socket", runtime_dir); + break; + + case PA_SERVER_TYPE_SYSTEM: + server_string = pa_xstrdup("unix:path=/var/run/pulse/dbus_socket"); + break; + + case PA_SERVER_TYPE_NONE: + server_string = pa_xnew0(char, 1); + break; + + default: + pa_assert_not_reached(); + } + + return server_string; +} + +static DBusHandlerResult handle_get_dbus_servers(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusMessage *reply = NULL; + pa_client_conf *conf = NULL; + char *server_string = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + conf = pa_client_conf_new(); + + if (pa_client_conf_load(conf, NULL) < 0) { + if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) + goto fail; + if (!dbus_connection_send(conn, reply, NULL)) + goto oom; + return DBUS_HANDLER_RESULT_HANDLED; + } + + server_string = pa_xstrdup(conf->default_dbus_server); + + pa_client_conf_free(conf); + + if (!server_string) { + if (!(server_string = get_dbus_server_from_type(sl->server_type))) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "get_dbus_server_from_type() failed."))) + goto fail; + if (!dbus_connection_send(conn, reply, NULL)) + goto oom; + return DBUS_HANDLER_RESULT_HANDLED; + } + } + + if (!(reply = dbus_message_new_method_return(msg))) + goto oom; + + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &server_string, DBUS_TYPE_INVALID)) + goto fail; + + if (!dbus_connection_send(conn, reply, NULL)) + goto oom; + + pa_log("Sent reply with server_string '%s'.", server_string); + + pa_xfree(server_string); + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + +fail: + if (conf) + pa_client_conf_free(conf); + + pa_xfree(server_string); + + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +oom: + if (conf) + pa_client_conf_free(conf); + + pa_xfree(server_string); + + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; +} + +static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) { + pa_dbusobj_server_lookup *sl = user_data; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + /* pa_log("Got message! type = %s path = %s iface = %s member = %s dest = %s", dbus_message_type_to_string(dbus_message_get_type(msg)), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), dbus_message_get_destination(msg)); */ + + if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) + return handle_introspect(conn, msg, sl); + + if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetDBusServers")) + return handle_get_dbus_servers(conn, msg, sl); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable vtable = { + .unregister_function = unregister_cb, + .message_function = message_cb, + .dbus_internal_pad1 = NULL, + .dbus_internal_pad2 = NULL, + .dbus_internal_pad3 = NULL, + .dbus_internal_pad4 = NULL +}; + +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c, pa_daemon_conf_server_type_t server_type) { + pa_dbusobj_server_lookup *sl; + DBusError error; + + dbus_error_init(&error); + + sl = pa_xnew(pa_dbusobj_server_lookup, 1); + sl->path_registered = FALSE; + sl->server_type = server_type; + + if (!(sl->conn = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { + pa_log("Unable to contact D-Bus: %s: %s", error.name, error.message); + goto fail; + } + + if (!dbus_connection_register_object_path(pa_dbus_connection_get(sl->conn), "/org/pulseaudio/server_lookup", &vtable, sl)) { + pa_log("dbus_connection_register_object_path() failed for /org/pulseaudio/server_lookup."); + goto fail; + } + + sl->path_registered = TRUE; + + return sl; + +fail: + dbus_error_free(&error); + + pa_dbusobj_server_lookup_free(sl); + + return NULL; +} + +void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl) { + pa_assert(sl); + + if (sl->path_registered) { + pa_assert(sl->conn); + if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(sl->conn), "/org/pulseaudio/server_lookup")) + pa_log_debug("dbus_connection_unregister_object_path() failed for /org/pulseaudio/server_lookup."); + } + + if (sl->conn) + pa_dbus_connection_unref(sl->conn); + + pa_xfree(sl); +} \ No newline at end of file diff --git a/src/daemon/server-lookup.h b/src/daemon/server-lookup.h new file mode 100644 index 00000000..69fdacdd --- /dev/null +++ b/src/daemon/server-lookup.h @@ -0,0 +1,42 @@ +#ifndef fooserverlookuphfoo +#define fooserverlookuphfoo + +/*** + This file is part of PulseAudio. + + Copyright 2009 Tanu Kaskinen + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +/* This object implements the D-Bus object at path + * /org/pulseaudio/server_lookup. Implemented interfaces + * are org.pulseaudio.ServerLookup and org.freedesktop.DBus.Introspectable. + * + * See http://pulseaudio.org/wiki/DBusInterface for the ServerLookup interface + * documentation. + */ + +#include + +#include "daemon-conf.h" + +typedef struct pa_dbusobj_server_lookup pa_dbusobj_server_lookup; + +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c, pa_daemon_conf_server_type_t server_type); +void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl); + +#endif \ No newline at end of file -- cgit From c8d819a5adbe32e14d7f03a252bca6f7df01d795 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Tue, 16 Jun 2009 19:03:22 +0300 Subject: dbus-protocol: Connection handling for local connections. --- src/daemon/daemon-conf.h | 10 ++----- src/daemon/main.c | 3 +- src/daemon/server-lookup.c | 69 ++++++++++++++-------------------------------- src/daemon/server-lookup.h | 6 ++-- 4 files changed, 27 insertions(+), 61 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h index 98db8641..c4f78cbe 100644 --- a/src/daemon/daemon-conf.h +++ b/src/daemon/daemon-conf.h @@ -28,6 +28,7 @@ #include #include +#include #include #ifdef HAVE_SYS_RESOURCE_H @@ -48,13 +49,6 @@ typedef enum pa_daemon_conf_cmd { PA_CMD_CLEANUP_SHM } pa_daemon_conf_cmd_t; -typedef enum pa_daemon_conf_server_type { - PA_SERVER_TYPE_UNSET, - PA_SERVER_TYPE_USER, - PA_SERVER_TYPE_SYSTEM, - PA_SERVER_TYPE_NONE -} pa_daemon_conf_server_type_t; - #ifdef HAVE_SYS_RESOURCE_H typedef struct pa_rlimit { rlim_t value; @@ -81,7 +75,7 @@ typedef struct pa_daemon_conf { log_meta, log_time, flat_volumes; - pa_daemon_conf_server_type_t local_server_type; + pa_server_type_t local_server_type; int exit_idle_time, scache_idle_time, auto_log_target, diff --git a/src/daemon/main.c b/src/daemon/main.c index 1b6ed793..62214a56 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -1028,6 +1028,7 @@ after_caps_setup: c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; c->flat_volumes = conf->flat_volumes; + c->server_type = conf->local_server_type; pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); @@ -1105,7 +1106,7 @@ after_caps_setup: #ifdef HAVE_DBUS if (!conf->system_instance) { - if (!(server_lookup = pa_dbusobj_server_lookup_new(c, conf->local_server_type))) + if (!(server_lookup = pa_dbusobj_server_lookup_new(c))) goto finish; if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.pulseaudio.PulseAudio"))) goto finish; diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c index 867c3a1c..b53fda76 100644 --- a/src/daemon/server-lookup.c +++ b/src/daemon/server-lookup.c @@ -28,16 +28,18 @@ #include #include +#include #include +#include #include #include #include "server-lookup.h" struct pa_dbusobj_server_lookup { + pa_core *core; pa_dbus_connection *conn; pa_bool_t path_registered; - pa_daemon_conf_server_type_t server_type; }; static const char introspection[] = @@ -46,7 +48,7 @@ static const char introspection[] = " \n" " " - " " + " " " " " " " " @@ -99,40 +101,10 @@ oom: return DBUS_HANDLER_RESULT_NEED_MEMORY; } -/* Caller frees the string. */ -static char *get_dbus_server_from_type(pa_daemon_conf_server_type_t server_type) { - char *server_string = NULL; - char *runtime_dir = NULL; - - switch (server_type) { - case PA_SERVER_TYPE_USER: - runtime_dir = pa_get_runtime_dir(); - - if (!runtime_dir) - return NULL; - - server_string = pa_sprintf_malloc("unix:path=%s/dbus_socket", runtime_dir); - break; - - case PA_SERVER_TYPE_SYSTEM: - server_string = pa_xstrdup("unix:path=/var/run/pulse/dbus_socket"); - break; - - case PA_SERVER_TYPE_NONE: - server_string = pa_xnew0(char, 1); - break; - - default: - pa_assert_not_reached(); - } - - return server_string; -} - -static DBusHandlerResult handle_get_dbus_servers(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { +static DBusHandlerResult handle_get_dbus_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { DBusMessage *reply = NULL; pa_client_conf *conf = NULL; - char *server_string = NULL; + char *address = NULL; pa_assert(conn); pa_assert(msg); @@ -148,12 +120,13 @@ static DBusHandlerResult handle_get_dbus_servers(DBusConnection *conn, DBusMessa return DBUS_HANDLER_RESULT_HANDLED; } - server_string = pa_xstrdup(conf->default_dbus_server); - pa_client_conf_free(conf); - if (!server_string) { - if (!(server_string = get_dbus_server_from_type(sl->server_type))) { + if (conf->default_dbus_server) { + if (!(address = dbus_address_escape_value(conf->default_dbus_server))) + goto oom; + } else { + if (!(address = pa_get_dbus_address_from_server_type(sl->core->server_type))) { if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "get_dbus_server_from_type() failed."))) goto fail; if (!dbus_connection_send(conn, reply, NULL)) @@ -165,15 +138,15 @@ static DBusHandlerResult handle_get_dbus_servers(DBusConnection *conn, DBusMessa if (!(reply = dbus_message_new_method_return(msg))) goto oom; - if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &server_string, DBUS_TYPE_INVALID)) + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) goto fail; if (!dbus_connection_send(conn, reply, NULL)) goto oom; - pa_log("Sent reply with server_string '%s'.", server_string); + pa_log_debug("handle_get_dbus_address(): Sent reply with address '%s'.", address); - pa_xfree(server_string); + pa_xfree(address); dbus_message_unref(reply); @@ -183,7 +156,7 @@ fail: if (conf) pa_client_conf_free(conf); - pa_xfree(server_string); + pa_xfree(address); if (reply) dbus_message_unref(reply); @@ -194,7 +167,7 @@ oom: if (conf) pa_client_conf_free(conf); - pa_xfree(server_string); + pa_xfree(address); if (reply) dbus_message_unref(reply); @@ -214,8 +187,8 @@ static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) return handle_introspect(conn, msg, sl); - if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetDBusServers")) - return handle_get_dbus_servers(conn, msg, sl); + if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetDBusAddress")) + return handle_get_dbus_address(conn, msg, sl); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -229,15 +202,15 @@ static DBusObjectPathVTable vtable = { .dbus_internal_pad4 = NULL }; -pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c, pa_daemon_conf_server_type_t server_type) { +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c) { pa_dbusobj_server_lookup *sl; DBusError error; dbus_error_init(&error); sl = pa_xnew(pa_dbusobj_server_lookup, 1); + sl->core = c; sl->path_registered = FALSE; - sl->server_type = server_type; if (!(sl->conn = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) { pa_log("Unable to contact D-Bus: %s: %s", error.name, error.message); @@ -274,4 +247,4 @@ void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl) { pa_dbus_connection_unref(sl->conn); pa_xfree(sl); -} \ No newline at end of file +} diff --git a/src/daemon/server-lookup.h b/src/daemon/server-lookup.h index 69fdacdd..c930d5b7 100644 --- a/src/daemon/server-lookup.h +++ b/src/daemon/server-lookup.h @@ -32,11 +32,9 @@ #include -#include "daemon-conf.h" - typedef struct pa_dbusobj_server_lookup pa_dbusobj_server_lookup; -pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c, pa_daemon_conf_server_type_t server_type); +pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c); void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl); -#endif \ No newline at end of file +#endif -- cgit From 123c6a3c6ffc9903c0855e38445fc3b6588311ce Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Fri, 19 Jun 2009 10:28:08 +0300 Subject: dbus-common: Implement infrastructure for registering D-Bus objects on all client connections and for receiving method calls from clients. --- src/daemon/server-lookup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c index b53fda76..2d2d8ce6 100644 --- a/src/daemon/server-lookup.c +++ b/src/daemon/server-lookup.c @@ -48,7 +48,7 @@ static const char introspection[] = " \n" " " - " " + " " " " " " " " @@ -101,7 +101,7 @@ oom: return DBUS_HANDLER_RESULT_NEED_MEMORY; } -static DBusHandlerResult handle_get_dbus_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { +static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { DBusMessage *reply = NULL; pa_client_conf *conf = NULL; char *address = NULL; @@ -187,8 +187,8 @@ static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) return handle_introspect(conn, msg, sl); - if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetDBusAddress")) - return handle_get_dbus_address(conn, msg, sl); + if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetAddress")) + return handle_get_address(conn, msg, sl); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -- cgit From 3c6a0acc98a8326ad7a19c29005bba353396a88b Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Fri, 19 Jun 2009 15:17:57 +0300 Subject: dbus-protocol: Implement TCP server startup. --- src/daemon/server-lookup.c | 11 +++-------- src/daemon/system.pa.in | 3 ++- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c index 2d2d8ce6..33d6b24c 100644 --- a/src/daemon/server-lookup.c +++ b/src/daemon/server-lookup.c @@ -120,14 +120,11 @@ static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *m return DBUS_HANDLER_RESULT_HANDLED; } - pa_client_conf_free(conf); - if (conf->default_dbus_server) { - if (!(address = dbus_address_escape_value(conf->default_dbus_server))) - goto oom; + address = pa_xstrdup(conf->default_dbus_server); } else { if (!(address = pa_get_dbus_address_from_server_type(sl->core->server_type))) { - if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "get_dbus_server_from_type() failed."))) + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) goto fail; if (!dbus_connection_send(conn, reply, NULL)) goto oom; @@ -144,10 +141,8 @@ static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *m if (!dbus_connection_send(conn, reply, NULL)) goto oom; - pa_log_debug("handle_get_dbus_address(): Sent reply with address '%s'.", address); - + pa_client_conf_free(conf); pa_xfree(address); - dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in index 5541bbe4..0ca32bd3 100755 --- a/src/daemon/system.pa.in +++ b/src/daemon/system.pa.in @@ -33,7 +33,8 @@ load-module module-detect load-module module-esound-protocol-unix .endif .ifexists module-dbus-protocol@PA_SOEXT@ -load-module module-dbus-protocol +### If you want to allow TCP connections, set access to "remote" or "local,remote". +load-module module-dbus-protocol access=local .endif load-module module-native-protocol-unix -- cgit From 6e2fec05ddd38fa460276202ca2f4ecf68761ed0 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Tue, 30 Jun 2009 15:21:20 +0300 Subject: server-lookup: Update the D-Bus identifiers to be versioned. --- src/daemon/main.c | 2 +- src/daemon/server-lookup.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/main.c b/src/daemon/main.c index 61b0c840..d320c9e4 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -943,7 +943,7 @@ int main(int argc, char *argv[]) { if (!conf->system_instance) { if (!(server_lookup = pa_dbusobj_server_lookup_new(c))) goto finish; - if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.pulseaudio.PulseAudio"))) + if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.pulseaudio.PulseAudio1"))) goto finish; } diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c index 33d6b24c..7c80d677 100644 --- a/src/daemon/server-lookup.c +++ b/src/daemon/server-lookup.c @@ -36,6 +36,9 @@ #include "server-lookup.h" +#define OBJECT_PATH "/org/pulseaudio1/server_lookup" +#define INTERFACE "org.pulseaudio.ServerLookup1" + struct pa_dbusobj_server_lookup { pa_core *core; pa_dbus_connection *conn; @@ -47,7 +50,7 @@ static const char introspection[] = "" " \n" - " " + " " " " " " " " @@ -182,7 +185,7 @@ static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) return handle_introspect(conn, msg, sl); - if (dbus_message_is_method_call(msg, "org.pulseaudio.ServerLookup", "GetAddress")) + if (dbus_message_is_method_call(msg, INTERFACE, "GetAddress")) return handle_get_address(conn, msg, sl); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -212,8 +215,8 @@ pa_dbusobj_server_lookup *pa_dbusobj_server_lookup_new(pa_core *c) { goto fail; } - if (!dbus_connection_register_object_path(pa_dbus_connection_get(sl->conn), "/org/pulseaudio/server_lookup", &vtable, sl)) { - pa_log("dbus_connection_register_object_path() failed for /org/pulseaudio/server_lookup."); + if (!dbus_connection_register_object_path(pa_dbus_connection_get(sl->conn), OBJECT_PATH, &vtable, sl)) { + pa_log("dbus_connection_register_object_path() failed for " OBJECT_PATH "."); goto fail; } @@ -234,8 +237,8 @@ void pa_dbusobj_server_lookup_free(pa_dbusobj_server_lookup *sl) { if (sl->path_registered) { pa_assert(sl->conn); - if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(sl->conn), "/org/pulseaudio/server_lookup")) - pa_log_debug("dbus_connection_unregister_object_path() failed for /org/pulseaudio/server_lookup."); + if (!dbus_connection_unregister_object_path(pa_dbus_connection_get(sl->conn), OBJECT_PATH)) + pa_log_debug("dbus_connection_unregister_object_path() failed for " OBJECT_PATH "."); } if (sl->conn) -- cgit From 5c7952e4fa5e560f64255ef173c3e6570bee433a Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Fri, 3 Jul 2009 02:49:07 +0300 Subject: dbus: Implement the Name property of the core object. --- src/daemon/main.c | 2 +- src/daemon/server-lookup.c | 414 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 345 insertions(+), 71 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/main.c b/src/daemon/main.c index d320c9e4..f4209859 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -943,7 +943,7 @@ int main(int argc, char *argv[]) { if (!conf->system_instance) { if (!(server_lookup = pa_dbusobj_server_lookup_new(c))) goto finish; - if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.pulseaudio.PulseAudio1"))) + if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1"))) goto finish; } diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c index 7c80d677..ebacc099 100644 --- a/src/daemon/server-lookup.c +++ b/src/daemon/server-lookup.c @@ -37,7 +37,7 @@ #include "server-lookup.h" #define OBJECT_PATH "/org/pulseaudio1/server_lookup" -#define INTERFACE "org.pulseaudio.ServerLookup1" +#define INTERFACE "org.PulseAudio.ServerLookup1" struct pa_dbusobj_server_lookup { pa_core *core; @@ -50,17 +50,31 @@ static const char introspection[] = "" " \n" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; static void unregister_cb(DBusConnection *conn, void *user_data) { pa_dbusobj_server_lookup *sl = user_data; @@ -72,105 +86,352 @@ static void unregister_cb(DBusConnection *conn, void *user_data) { } static DBusHandlerResult handle_introspect(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; const char *i = introspection; DBusMessage *reply = NULL; pa_assert(conn); pa_assert(msg); - if (!(reply = dbus_message_new_method_return(msg))) - goto fail; + if (!(reply = dbus_message_new_method_return(msg))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &i, DBUS_TYPE_INVALID)) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } - if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &i, DBUS_TYPE_INVALID)) - goto fail; +finish: + if (reply) + dbus_message_unref(reply); - if (!dbus_connection_send(conn, reply, NULL)) - goto oom; + return r; +} - dbus_message_unref(reply); +enum get_address_result_t { + SUCCESS, + FAILED_TO_LOAD_CLIENT_CONF, + SERVER_FROM_TYPE_FAILED +}; - return DBUS_HANDLER_RESULT_HANDLED; +/* Caller frees the returned address. */ +static enum get_address_result_t get_address(pa_server_type_t server_type, char **address) { + enum get_address_result_t r = SUCCESS; + pa_client_conf *conf = pa_client_conf_new(); -fail: - if (reply) - dbus_message_unref(reply); + *address = NULL; - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (pa_client_conf_load(conf, NULL) < 0) { + r = FAILED_TO_LOAD_CLIENT_CONF; + goto finish; + } -oom: - if (reply) - dbus_message_unref(reply); + if (conf->default_dbus_server) + *address = pa_xstrdup(conf->default_dbus_server); + else if (!(*address = pa_get_dbus_address_from_server_type(server_type))) { + r = SERVER_FROM_TYPE_FAILED; + goto finish; + } - return DBUS_HANDLER_RESULT_NEED_MEMORY; +finish: + pa_client_conf_free(conf); + return r; } static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; DBusMessage *reply = NULL; - pa_client_conf *conf = NULL; char *address = NULL; + DBusMessageIter msg_iter; + DBusMessageIter variant_iter; pa_assert(conn); pa_assert(msg); pa_assert(sl); - conf = pa_client_conf_new(); + switch (get_address(sl->core->server_type, &address)) { + case SUCCESS: + if (!(reply = dbus_message_new_method_return(msg))) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + dbus_message_iter_init_append(reply, &msg_iter); + if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&msg_iter, &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case FAILED_TO_LOAD_CLIENT_CONF: + if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case SERVER_FROM_TYPE_FAILED: + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + default: + pa_assert_not_reached(); + } - if (pa_client_conf_load(conf, NULL) < 0) { - if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) - goto fail; - if (!dbus_connection_send(conn, reply, NULL)) - goto oom; - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (conf->default_dbus_server) { - address = pa_xstrdup(conf->default_dbus_server); - } else { - if (!(address = pa_get_dbus_address_from_server_type(sl->core->server_type))) { - if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) - goto fail; - if (!dbus_connection_send(conn, reply, NULL)) - goto oom; - return DBUS_HANDLER_RESULT_HANDLED; +finish: + pa_xfree(address); + if (reply) + dbus_message_unref(reply); + + return r; +} + +static DBusHandlerResult handle_get(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + const char* interface; + const char* property; + DBusMessage *reply = NULL; + + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; } - if (!(reply = dbus_message_new_method_return(msg))) - goto oom; + if (*interface && !pa_streq(interface, INTERFACE)) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } - if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) - goto fail; + if (!pa_streq(property, "Address")) { + if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } - if (!dbus_connection_send(conn, reply, NULL)) - goto oom; + r = handle_get_address(conn, msg, sl); - pa_client_conf_free(conf); - pa_xfree(address); - dbus_message_unref(reply); +finish: + if (reply) + dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_HANDLED; + return r; +} -fail: - if (conf) - pa_client_conf_free(conf); +static DBusHandlerResult handle_set(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + const char* interface; + const char* property; + DBusMessage *reply = NULL; - pa_xfree(address); + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + if (*interface && !pa_streq(interface, INTERFACE)) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + + if (!pa_streq(property, "Address")) { + if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + if (!(reply = dbus_message_new_error_printf(msg, DBUS_ERROR_ACCESS_DENIED, "%s: Property not settable", property))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; +finish: if (reply) dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return r; +} -oom: - if (conf) - pa_client_conf_free(conf); +static DBusHandlerResult handle_get_all(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { + DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; + DBusMessage *reply = NULL; + const char *property = "Address"; + char *interface = NULL; + char *address = NULL; + DBusMessageIter msg_iter; + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + DBusMessageIter variant_iter; - pa_xfree(address); + pa_assert(conn); + pa_assert(msg); + pa_assert(sl); + if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) { + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + } + + switch (get_address(sl->core->server_type, &address)) { + case SUCCESS: + if (!(reply = dbus_message_new_method_return(msg))) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + dbus_message_iter_init_append(reply, &msg_iter); + if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &property)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&dict_entry_iter, &variant_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_message_iter_close_container(&msg_iter, &dict_iter)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case FAILED_TO_LOAD_CLIENT_CONF: + if (!(reply = dbus_message_new_error(msg, "org.pulseaudio.ClientConfLoadError", "Failed to load client.conf."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + case SERVER_FROM_TYPE_FAILED: + if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) { + r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + goto finish; + } + if (!dbus_connection_send(conn, reply, NULL)) { + r = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto finish; + } + r = DBUS_HANDLER_RESULT_HANDLED; + goto finish; + + default: + pa_assert_not_reached(); + } + +finish: + pa_xfree(address); if (reply) dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; + return r; } static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -182,11 +443,24 @@ static DBusHandlerResult message_cb(DBusConnection *conn, DBusMessage *msg, void /* pa_log("Got message! type = %s path = %s iface = %s member = %s dest = %s", dbus_message_type_to_string(dbus_message_get_type(msg)), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), dbus_message_get_destination(msg)); */ - if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) + if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, "Introspect") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Introspect"))) return handle_introspect(conn, msg, sl); - if (dbus_message_is_method_call(msg, INTERFACE, "GetAddress")) - return handle_get_address(conn, msg, sl); + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Get") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Get"))) + return handle_get(conn, msg, sl); + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "Set") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "Set"))) + return handle_set(conn, msg, sl); + + if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PROPERTIES, "GetAll") || + (!dbus_message_get_interface(msg) && dbus_message_has_member(msg, "GetAll"))) + return handle_get_all(conn, msg, sl); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -- cgit From 9347e90fed732dac619bb88f6518c344e7436447 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Tue, 21 Jul 2009 00:02:27 +0300 Subject: Finish the Core dbus interface. --- src/daemon/server-lookup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/server-lookup.c b/src/daemon/server-lookup.c index ebacc099..45796e72 100644 --- a/src/daemon/server-lookup.c +++ b/src/daemon/server-lookup.c @@ -30,13 +30,13 @@ #include #include -#include #include #include +#include #include "server-lookup.h" -#define OBJECT_PATH "/org/pulseaudio1/server_lookup" +#define OBJECT_PATH "/org/pulseaudio/server_lookup1" #define INTERFACE "org.PulseAudio.ServerLookup1" struct pa_dbusobj_server_lookup { -- cgit From eac566226ed9026347cdb415a93ad9b15fbd8b45 Mon Sep 17 00:00:00 2001 From: Nix Date: Sat, 26 Sep 2009 20:18:00 +0100 Subject: Don't refuse to start on systems using GNU stow, graft, STORE et al There are multiple package management systems out there which implement packages using symlinks. The recent (otherwise useful) check to ensure that a re-executed pulseaudio is actually reexecuting itself unfortunately breaks in the presence of all these packaging systems, because PA_BINARY refers to its installed location (e.g. /usr/local/bin/pulseaudio), which is a symlink to the binary (e.g. /usr/local/stow/pulseaudio-0.9.18/bin/pulseaudio), because /proc/self/exe always contains the canonical path of the executable, with all symlinks resolved. (At least one distribution uses a symlink-based packaging system, so will be forced to apply this locally in any case.) The fix is simple: canonicalize PA_BINARY before equality-testing. (This should be completely safe, because the OS does just that when PA_BINARY is executed.) The patch is against 0.9.18, but applies without fuzz to current master. --- src/daemon/main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/main.c b/src/daemon/main.c index af59adef..2e16c187 100644 --- a/src/daemon/main.c +++ b/src/daemon/main.c @@ -416,23 +416,28 @@ int main(int argc, char *argv[]) { if (!getenv("LD_BIND_NOW")) { char *rp; + char *canonical_rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ pa_set_env("LD_BIND_NOW", "1"); + canonical_rp = pa_realpath(PA_BINARY); + if ((rp = pa_readlink("/proc/self/exe"))) { - if (pa_streq(rp, PA_BINARY)) + if (pa_streq(rp, canonical_rp)) pa_assert_se(execv(rp, argv) == 0); else - pa_log_warn("/proc/self/exe does not point to " PA_BINARY ", cannot self execute. Are you playing games?"); + pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); pa_xfree(rp); } else pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); + + pa_xfree(canonical_rp); } #endif -- cgit From b8de3bd214775acd6d24291ad65a03a8204a9ec6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Sep 2009 23:47:49 +0200 Subject: polkit: drop left-over polkit policy file from git tree --- src/daemon/org.pulseaudio.policy.in | 50 ------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 src/daemon/org.pulseaudio.policy.in (limited to 'src/daemon') diff --git a/src/daemon/org.pulseaudio.policy.in b/src/daemon/org.pulseaudio.policy.in deleted file mode 100644 index 1d0b6a7d..00000000 --- a/src/daemon/org.pulseaudio.policy.in +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - The PulseAudio Project - http://pulseaudio.org/ - audio-card - - - <_description>Real-time scheduling for the PulseAudio daemon - <_message>System policy prevents PulseAudio from acquiring real-time scheduling. - - no - no - no - - - - - <_description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon - <_message>System policy prevents PulseAudio from acquiring high-priority scheduling. - - no - no - no - - - - -- cgit From 42e28ce31c583ae9d431d2f1dd033d82cc63eb36 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Thu, 1 Oct 2009 22:33:22 +0100 Subject: device-manager: Add some scripts that are only run under KDE to load/initialise module-device-manager with routing turned on. --- src/daemon/pulseaudio-kde.desktop.in | 11 +++++++++++ src/daemon/start-pulseaudio-kde.in | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 src/daemon/pulseaudio-kde.desktop.in create mode 100755 src/daemon/start-pulseaudio-kde.in (limited to 'src/daemon') diff --git a/src/daemon/pulseaudio-kde.desktop.in b/src/daemon/pulseaudio-kde.desktop.in new file mode 100644 index 00000000..06846421 --- /dev/null +++ b/src/daemon/pulseaudio-kde.desktop.in @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Encoding=UTF-8 +_Name=PulseAudio Sound System KDE Routing Policy +_Comment=Start the PulseAudio Sound System with KDE Routing Policy +Exec=start-pulseaudio-kde +Terminal=false +Type=Application +Categories= +GenericName= +OnlyShowIn=KDE; diff --git a/src/daemon/start-pulseaudio-kde.in b/src/daemon/start-pulseaudio-kde.in new file mode 100755 index 00000000..a79a50b5 --- /dev/null +++ b/src/daemon/start-pulseaudio-kde.in @@ -0,0 +1,30 @@ +#!/bin/sh + +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +set -e + +[ -z "$PULSE_SERVER" ] + +@PA_BINARY@ --start "$@" + +if [ x"$DISPLAY" != x ] ; then + + @PACTL_BINARY@ load-module module-module-device-manager "do_routing=1" > /dev/null + +fi -- cgit From 50db81c8603e1274b1bfe8836d134bf8ad6fb0a1 Mon Sep 17 00:00:00 2001 From: Colin Guthrie Date: Fri, 2 Oct 2009 00:49:50 +0100 Subject: device-manager: Fix typo in module loading script. --- src/daemon/start-pulseaudio-kde.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/daemon') diff --git a/src/daemon/start-pulseaudio-kde.in b/src/daemon/start-pulseaudio-kde.in index a79a50b5..c319e7dd 100755 --- a/src/daemon/start-pulseaudio-kde.in +++ b/src/daemon/start-pulseaudio-kde.in @@ -25,6 +25,6 @@ set -e if [ x"$DISPLAY" != x ] ; then - @PACTL_BINARY@ load-module module-module-device-manager "do_routing=1" > /dev/null + @PACTL_BINARY@ load-module module-device-manager "do_routing=1" > /dev/null fi -- cgit