diff options
Diffstat (limited to 'hcid')
-rw-r--r-- | hcid/dbus-common.c | 2 | ||||
-rw-r--r-- | hcid/dbus-database.c | 39 | ||||
-rw-r--r-- | hcid/dbus-error.c | 6 | ||||
-rw-r--r-- | hcid/dbus-error.h | 1 | ||||
-rw-r--r-- | hcid/dbus-service.c | 705 | ||||
-rw-r--r-- | hcid/dbus-service.h | 35 | ||||
-rw-r--r-- | hcid/main.c | 2 | ||||
-rw-r--r-- | hcid/manager.c | 29 |
8 files changed, 129 insertions, 690 deletions
diff --git a/hcid/dbus-common.c b/hcid/dbus-common.c index 0094c11e..20453c82 100644 --- a/hcid/dbus-common.c +++ b/hcid/dbus-common.c @@ -244,8 +244,6 @@ static gboolean system_bus_reconnect(void *data) if (hcid_dbus_init() < 0) return TRUE; - init_services(CONFIGDIR); - /* Create and bind HCI socket */ sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sk < 0) { diff --git a/hcid/dbus-database.c b/hcid/dbus-database.c index d37b4d97..9519975e 100644 --- a/hcid/dbus-database.c +++ b/hcid/dbus-database.c @@ -353,57 +353,34 @@ static DBusHandlerResult remove_service_record(DBusConnection *conn, return send_message_and_unref(conn, reply); } -static DBusHandlerResult register_service(DBusConnection *conn, +static DBusHandlerResult register_service_old(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessage *reply; - const char *sender, *ident, *name, *desc; + const char *ident, *name, *desc; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ident, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &desc, DBUS_TYPE_INVALID) == FALSE) return error_invalid_arguments(conn, msg, NULL); - sender = dbus_message_get_sender(msg); - - if (service_register(conn, sender, ident, name, desc) < 0) - return error_failed_errno(conn, msg, EIO); - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - return send_message_and_unref(conn, reply); + return error_failed_errno(conn, msg, EIO); } -static DBusHandlerResult unregister_service(DBusConnection *conn, +static DBusHandlerResult unregister_service_old(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessage *reply; - const char *sender, *ident; struct service *service; + const char *ident; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ident, DBUS_TYPE_INVALID) == FALSE) return error_invalid_arguments(conn, msg, NULL); - sender = dbus_message_get_sender(msg); - service = search_service(ident); if (!service) return error_service_does_not_exist(conn, msg); - if (!service->external || strcmp(sender, service->bus_name)) - return error_not_authorized(conn, msg); - - if (service_unregister(conn, service) < 0) - return error_failed_errno(conn, msg, EIO); - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - return send_message_and_unref(conn, reply); + return error_failed_errno(conn, msg, EIO); } static DBusHandlerResult request_authorization_old(DBusConnection *conn, @@ -486,8 +463,8 @@ static DBusMethodVTable database_methods[] = { { "UpdateServiceRecord", update_service_record, "uay", "" }, { "UpdateServiceRecordFromXML", update_service_record_from_xml, "us", "" }, { "RemoveServiceRecord", remove_service_record, "u", "" }, - { "RegisterService", register_service, "sss", "" }, - { "UnregisterService", unregister_service, "s", "" }, + { "RegisterService", register_service_old, "sss", "" }, + { "UnregisterService", unregister_service_old, "s", "" }, { "RequestAuthorization", request_authorization_old, "ss", "" }, { "CancelAuthorizationRequest", cancel_authorization_request, "ss", "" }, { NULL, NULL, NULL, NULL } diff --git a/hcid/dbus-error.c b/hcid/dbus-error.c index 66fb2490..20a55c5c 100644 --- a/hcid/dbus-error.c +++ b/hcid/dbus-error.c @@ -170,12 +170,6 @@ DBusHandlerResult error_disconnect_in_progress(DBusConnection *conn, DBusMessage return error_in_progress(conn, msg, "Disconnection in progress"); } -DBusHandlerResult error_service_start_in_progress(DBusConnection *conn, - DBusMessage *msg) -{ - return error_in_progress(conn, msg, "Service start in progress"); -} - static const char *strsdperror(int err) { switch (err) { diff --git a/hcid/dbus-error.h b/hcid/dbus-error.h index b50c4772..2cdabdde 100644 --- a/hcid/dbus-error.h +++ b/hcid/dbus-error.h @@ -51,4 +51,3 @@ DBusHandlerResult error_service_search_in_progress(DBusConnection *conn, DBusMes DBusHandlerResult error_sdp_failed(DBusConnection *conn, DBusMessage *msg, int err); DBusHandlerResult error_audit_already_exists(DBusConnection *conn, DBusMessage *msg); DBusHandlerResult error_disconnect_in_progress(DBusConnection *conn, DBusMessage *msg); -DBusHandlerResult error_service_start_in_progress(DBusConnection *conn, DBusMessage *msg); diff --git a/hcid/dbus-service.c b/hcid/dbus-service.c index 01f07b2f..5282ffd1 100644 --- a/hcid/dbus-service.c +++ b/hcid/dbus-service.c @@ -61,14 +61,6 @@ #define SERVICE_INTERFACE "org.bluez.Service" -#define STARTUP_TIMEOUT (10 * 1000) /* 10 seconds */ -#define SHUTDOWN_TIMEOUT (2 * 1000) /* 2 seconds */ - -#define SERVICE_SUFFIX ".service" -#define SERVICE_GROUP "Bluetooth Service" - -#define NAME_MATCH "interface=" DBUS_INTERFACE_DBUS ",member=NameOwnerChanged" - struct service_uuids { char *name; char **uuids; @@ -81,69 +73,19 @@ struct service_auth { static GSList *services = NULL; static GSList *services_uuids = NULL; -static GSList *removed = NULL; static void service_free(struct service *service) { if (!service) return; - if (service->action) - dbus_message_unref(service->action); - - g_free(service->bus_name); - g_free(service->filename); g_free(service->object_path); - g_free(service->name); - g_free(service->descr); g_free(service->ident); + g_free(service->name); g_free(service); } -static void service_exit(const char *name, struct service *service) -{ - DBusConnection *conn = get_dbus_connection(); - - debug("Service owner exited: %s", name); - - dbus_connection_emit_signal(conn, service->object_path, - SERVICE_INTERFACE, "Stopped", - DBUS_TYPE_INVALID); - - if (service->action) { - DBusMessage *reply; - reply = dbus_message_new_method_return(service->action); - send_message_and_unref(conn, reply); - dbus_message_unref(service->action); - service->action = NULL; - } - - g_free(service->bus_name); - service->bus_name = NULL; -} - -static void external_service_exit(const char *name, struct service *service) -{ - DBusConnection *conn = get_dbus_connection(); - - if (!conn) - return; - - service_exit(name, service); - - dbus_connection_emit_signal(conn, BASE_PATH, MANAGER_INTERFACE, - "ServiceRemoved", - DBUS_TYPE_STRING, &service->object_path, - DBUS_TYPE_INVALID); - - if (!dbus_connection_destroy_object_path(conn, service->object_path)) - return; - - services = g_slist_remove(services, service); - service_free(service); -} - static DBusHandlerResult get_info(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -151,7 +93,6 @@ static DBusHandlerResult get_info(DBusConnection *conn, DBusMessage *reply; DBusMessageIter iter; DBusMessageIter dict; - dbus_bool_t running; reply = dbus_message_new_method_return(msg); if (!reply) @@ -170,14 +111,6 @@ static DBusHandlerResult get_info(DBusConnection *conn, dbus_message_iter_append_dict_entry(&dict, "name", DBUS_TYPE_STRING, &service->name); - dbus_message_iter_append_dict_entry(&dict, "description", - DBUS_TYPE_STRING, &service->descr); - - running = (service->external || service->bus_name) ? TRUE : FALSE; - - dbus_message_iter_append_dict_entry(&dict, "running", - DBUS_TYPE_BOOLEAN, &running); - dbus_message_iter_close_container(&iter, &dict); return send_message_and_unref(conn, reply); @@ -198,9 +131,8 @@ static DBusHandlerResult get_identifier(DBusConnection *conn, if (service->ident) identifier = service->ident; - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &identifier, - DBUS_TYPE_INVALID); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &identifier, + DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply); } @@ -220,9 +152,8 @@ static DBusHandlerResult get_name(DBusConnection *conn, if (service->name) name = service->name; - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply); } @@ -230,7 +161,6 @@ static DBusHandlerResult get_name(DBusConnection *conn, static DBusHandlerResult get_description(DBusConnection *conn, DBusMessage *msg, void *data) { - struct service *service = data; DBusMessage *reply; const char *description = ""; @@ -238,12 +168,8 @@ static DBusHandlerResult get_description(DBusConnection *conn, if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (service->descr) - description = service->descr; - - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &description, - DBUS_TYPE_INVALID); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &description, + DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply); } @@ -251,291 +177,41 @@ static DBusHandlerResult get_description(DBusConnection *conn, static DBusHandlerResult get_bus_name(DBusConnection *conn, DBusMessage *msg, void *data) { - struct service *service = data; DBusMessage *reply; - - if (!service->bus_name) - return error_not_available(conn, msg); + const char *busname = "org.bluez"; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &service->bus_name, - DBUS_TYPE_INVALID); - - return send_message_and_unref(conn, reply); -} - -static void service_setup(gpointer data) -{ - /* struct service *service = data; */ -} - -static DBusHandlerResult service_filter(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - DBusError err; - struct service *service = data; - const char *name, *old, *new; - unsigned long pid; - - if (!dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, - DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) { - error("Invalid arguments for NameOwnerChanged signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (*new == '\0' || *old != '\0' || *new != ':') - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (!dbus_bus_get_unix_process_id(conn, new, &pid)) { - error("Could not get PID of %s", new); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if ((GPid) pid != service->pid) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - debug("Child PID %d got the unique bus name %s", service->pid, new); - - service->bus_name = g_strdup(new); - - dbus_error_init(&err); - dbus_bus_remove_match(conn, NAME_MATCH, &err); - if (dbus_error_is_set(&err)) { - error("Remove match \"%s\" failed: %s" NAME_MATCH, err.message); - dbus_error_free(&err); - } - dbus_connection_remove_filter(conn, service_filter, service); - - if (service->action) { - msg = dbus_message_new_method_return(service->action); - if (msg) { - if (dbus_message_is_method_call(service->action, MANAGER_INTERFACE, - "ActivateService")) - dbus_message_append_args(msg, DBUS_TYPE_STRING, &new, + dbus_message_append_args(reply, DBUS_TYPE_STRING, &busname, DBUS_TYPE_INVALID); - send_message_and_unref(conn, msg); - } - dbus_message_unref(service->action); - service->action = NULL; - } - - if (service->startup_timer) { - g_source_remove(service->startup_timer); - service->startup_timer = 0; - } else - debug("service_filter: timeout was already removed!"); - - name_listener_add(conn, new, (name_cb_t) service_exit, service); - - dbus_connection_emit_signal(conn, service->object_path, - SERVICE_INTERFACE, "Started", - DBUS_TYPE_INVALID); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static void abort_startup(struct service *service, DBusConnection *conn, int ecode) -{ - DBusError err; - - if (conn) { - dbus_error_init(&err); - dbus_bus_remove_match(conn, NAME_MATCH, &err); - if (dbus_error_is_set(&err)) { - error("Remove match \"%s\" failed: %s" NAME_MATCH, err.message); - dbus_error_free(&err); - } - - dbus_connection_remove_filter(conn, service_filter, service); - } - - g_source_remove(service->startup_timer); - service->startup_timer = 0; - - if (service->action) { - if (conn) - error_failed_errno(conn, service->action, ecode); - dbus_message_unref(service->action); - service->action = NULL; - } - - if (service->pid > 0 && kill(service->pid, SIGKILL) < 0) - error("kill(%d, SIGKILL): %s (%d)", service->pid, - strerror(errno), errno); -} - -static void service_died(GPid pid, gint status, gpointer data) -{ - struct service *service = data; - - if (WIFEXITED(status)) - debug("%s (%s) exited with status %d", service->name, - service->ident, WEXITSTATUS(status)); - else - debug("%s (%s) was killed by signal %d", service->name, - service->ident, WTERMSIG(status)); - - g_spawn_close_pid(pid); - service->pid = 0; - - if (service->startup_timer) - abort_startup(service, get_dbus_connection(), ECANCELED); - - if (service->shutdown_timer) { - g_source_remove(service->shutdown_timer); - service->shutdown_timer = 0; - } - - if (g_slist_find(removed, service)) { - removed = g_slist_remove(removed, service); - service_free(service); - } -} - -static gboolean service_shutdown_timeout(gpointer data) -{ - struct service *service = data; - - if (service->pid > 0) { - debug("SIGKILL for \"%s\" (PID %d) since it didn't exit yet", - service->name, service->pid); - - if (kill(service->pid, SIGKILL) < 0) - error("kill(%d, SIGKILL): %s (%d)", service->pid, - strerror(errno), errno); - } - - service->shutdown_timer = 0; - - return FALSE; -} - -static void stop_service(struct service *service, gboolean remove) -{ - if (service->pid > 0 && kill(service->pid, SIGTERM) < 0) - error("kill(%d, SIGTERM): %s (%d)", service->pid, - strerror(errno), errno); - - service->shutdown_timer = g_timeout_add(SHUTDOWN_TIMEOUT, - service_shutdown_timeout, - service); - - if (remove) { - services = g_slist_remove(services, service); - removed = g_slist_append(removed, service); - } -} - -static gboolean service_startup_timeout(gpointer data) -{ - struct service *service = data; - - debug("Killing \"%s\" (PID %d) because it did not connect to D-Bus in time", - service->name, service->pid); - - abort_startup(service, get_dbus_connection(), ETIME); - - return FALSE; -} - -int service_start(struct service *service, DBusConnection *conn) -{ - DBusError derr; - char *argv[2], *envp[1], command[PATH_MAX]; - - if (!dbus_connection_add_filter(conn, service_filter, service, NULL)) { - error("Unable to add signal filter"); - return -1; - } - - dbus_error_init(&derr); - dbus_bus_add_match(conn, NAME_MATCH, &derr); - if (dbus_error_is_set(&derr)) { - error("Add match \"%s\" failed: %s", NAME_MATCH, derr.message); - dbus_error_free(&derr); - dbus_connection_remove_filter(conn, service_filter, service); - return -1; - } - - snprintf(command, sizeof(command) - 1, "%s/bluetoothd-service-%s", - SERVICEDIR, service->ident); - argv[0] = command; - argv[1] = NULL; - - envp[0] = NULL; - - if (!g_spawn_async(SERVICEDIR, argv, envp, G_SPAWN_DO_NOT_REAP_CHILD, - service_setup, service, &service->pid, NULL)) { - error("Unable to execute %s", argv[0]); - dbus_connection_remove_filter(conn, service_filter, service); - dbus_bus_remove_match(conn, NAME_MATCH, NULL); - return -1; - } - - g_child_watch_add(service->pid, service_died, service); - - debug("%s executed with PID %d", argv[0], service->pid); - - service->startup_timer = g_timeout_add(STARTUP_TIMEOUT, - service_startup_timeout, - service); - - return 0; + return send_message_and_unref(conn, reply); } static DBusHandlerResult start(DBusConnection *conn, DBusMessage *msg, void *data) { - struct service *service = data; - - if (service->external || service->pid) - return error_failed_errno(conn, msg, EALREADY); - - if (service_start(service, conn) < 0) - return error_failed_errno(conn, msg, ENOEXEC); - - service->action = dbus_message_ref(msg); - - return DBUS_HANDLER_RESULT_HANDLED; + return error_failed_errno(conn, msg, EALREADY); } static DBusHandlerResult stop(DBusConnection *conn, DBusMessage *msg, void *data) { - struct service *service = data; - - if (service->external || !service->bus_name) - return error_failed_errno(conn, msg, EPERM); - - stop_service(service, FALSE); - - service->action = dbus_message_ref(msg); - - return DBUS_HANDLER_RESULT_HANDLED; + return error_failed_errno(conn, msg, EPERM); } static DBusHandlerResult is_running(DBusConnection *conn, DBusMessage *msg, void *data) { - struct service *service = data; DBusMessage *reply; - dbus_bool_t running; + dbus_bool_t running = TRUE; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; - running = (service->external || service->bus_name) ? TRUE : FALSE; - dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &running, DBUS_TYPE_INVALID); @@ -546,15 +222,15 @@ static DBusHandlerResult is_running(DBusConnection *conn, static DBusHandlerResult is_external(DBusConnection *conn, DBusMessage *msg, void *data) { - struct service *service = data; DBusMessage *reply; + dbus_bool_t external = TRUE; reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_append_args(reply, - DBUS_TYPE_BOOLEAN, &service->external, + DBUS_TYPE_BOOLEAN, &external, DBUS_TYPE_INVALID); return send_message_and_unref(conn, reply); @@ -590,34 +266,34 @@ static DBusHandlerResult set_trusted(DBusConnection *conn, } static DBusHandlerResult list_trusted(DBusConnection *conn, - DBusMessage *msg, void *data) + DBusMessage *msg, void *data) { - struct service *service = data; - DBusMessage *reply; - GSList *trusts, *l; - char **addrs; - int len; + struct service *service = data; + DBusMessage *reply; + GSList *trusts, *l; + char **addrs; + int len; - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - trusts = list_trusts(BDADDR_ANY, service->ident); + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; - addrs = g_new(char *, g_slist_length(trusts)); + trusts = list_trusts(BDADDR_ANY, service->ident); - for (l = trusts, len = 0; l; l = l->next, len++) - addrs[len] = l->data; + addrs = g_new(char *, g_slist_length(trusts)); - dbus_message_append_args(reply, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &addrs, len, - DBUS_TYPE_INVALID); + for (l = trusts, len = 0; l; l = l->next, len++) + addrs[len] = l->data; + + dbus_message_append_args(reply, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &addrs, len, DBUS_TYPE_INVALID); - g_free(addrs); - g_slist_foreach(trusts, (GFunc) g_free, NULL); - g_slist_free(trusts); + g_free(addrs); + g_slist_foreach(trusts, (GFunc) g_free, NULL); + g_slist_free(trusts); - return send_message_and_unref(conn, reply); + return send_message_and_unref(conn, reply); } static DBusHandlerResult is_trusted(DBusConnection *conn, @@ -720,66 +396,6 @@ static int service_cmp_ident(struct service *service, const char *ident) return strcmp(service->ident, ident); } -static int register_service(struct service *service) -{ - char obj_path[PATH_MAX], *suffix; - DBusConnection *conn = get_dbus_connection(); - int i; - - if (g_slist_find_custom(services, service->ident, - (GCompareFunc) service_cmp_ident) - || !strcmp(service->ident, GLOBAL_TRUST)) - return -EADDRINUSE; - - if (service->external) { - snprintf(obj_path, sizeof(obj_path) - 1, - "/org/bluez/external_%s", service->ident); - } else { - snprintf(obj_path, sizeof(obj_path) - 1, - "/org/bluez/service_%s", service->filename); - - /* Don't include the .service part in the path */ - suffix = strstr(obj_path, SERVICE_SUFFIX); - *suffix = '\0'; - } - - /* Make the path valid for D-Bus */ - for (i = strlen("/org/bluez/"); obj_path[i]; i++) { - if (!isalnum(obj_path[i])) - obj_path[i] = '_'; - } - - if (g_slist_find_custom(services, obj_path, - (GCompareFunc) service_cmp_path)) - return -EADDRINUSE; - - debug("Registering service object: ident=%s, name=%s (%s)", - service->ident, service->name, obj_path); - - - if (!dbus_connection_create_object_path(conn, obj_path, - service, NULL)) { - error("D-Bus failed to register %s object", obj_path); - return -1; - } - - if (!service_init(conn, obj_path)) { - error("Service init failed"); - return -1; - } - - service->object_path = g_strdup(obj_path); - - services = g_slist_append(services, service); - - dbus_connection_emit_signal(conn, BASE_PATH, MANAGER_INTERFACE, - "ServiceAdded", - DBUS_TYPE_STRING, &service->object_path, - DBUS_TYPE_INVALID); - - return 0; -} - static int unregister_service_for_connection(DBusConnection *connection, struct service *service) { @@ -790,13 +406,6 @@ static int unregister_service_for_connection(DBusConnection *connection, if (!conn) goto cleanup; - if (service->bus_name) { - name_cb_t cb = (name_cb_t) (service->external ? - external_service_exit : service_exit); - name_listener_remove(connection, service->bus_name, - cb, service); - } - dbus_connection_emit_signal(conn, service->object_path, SERVICE_INTERFACE, "Stopped", DBUS_TYPE_INVALID); @@ -807,36 +416,30 @@ static int unregister_service_for_connection(DBusConnection *connection, DBUS_TYPE_INVALID); if (!dbus_connection_destroy_object_path(conn, service->object_path)) { - error("D-Bus failed to unregister %s object", service->object_path); + error("D-Bus failed to unregister %s object", + service->object_path); return -1; } cleanup: - if (service->pid) { - if (service->startup_timer) { - abort_startup(service, conn, ECANCELED); - services = g_slist_remove(services, service); - removed = g_slist_append(removed, service); - } else if (!service->shutdown_timer) - stop_service(service, TRUE); - } else { - services = g_slist_remove(services, service); - service_free(service); - } + services = g_slist_remove(services, service); + service_free(service); return 0; } -static int unregister_service(struct service *service) +static int do_unregister(struct service *service) { - return unregister_service_for_connection(get_dbus_connection(), service); + DBusConnection *conn = get_dbus_connection(); + + return unregister_service_for_connection(conn, service); } void release_services(DBusConnection *conn) { debug("release_services"); - g_slist_foreach(services, (GFunc) unregister_service, NULL); + g_slist_foreach(services, (GFunc) do_unregister, NULL); g_slist_free(services); services = NULL; } @@ -856,9 +459,6 @@ struct service *search_service(const char *pattern) if (service->ident && !strcmp(service->ident, pattern)) return service; - - if (service->bus_name && !strcmp(service->bus_name, pattern)) - return service; } return NULL; @@ -876,188 +476,97 @@ void append_available_services(DBusMessageIter *array_iter) } } -static struct service *create_service(const char *file) +int service_unregister(DBusConnection *conn, struct service *service) +{ + return unregister_service_for_connection(conn, service); +} + +static struct service *create_external_service(const char *ident) { - GKeyFile *keyfile; - GError *err = NULL; struct service *service; - gboolean autostart; - const char *slash; + const char *name; service = g_try_new0(struct service, 1); if (!service) { - error("OOM while allocating new service"); + error("OOM while allocating new external service"); return NULL; } - service->external = FALSE; - - keyfile = g_key_file_new(); - - if (!g_key_file_load_from_file(keyfile, file, 0, &err)) { - error("Parsing %s failed: %s", file, err->message); - g_error_free(err); - goto failed; - } - - service->ident = g_key_file_get_string(keyfile, SERVICE_GROUP, - "Identifier", &err); - if (err) { - debug("%s: %s", file, err->message); - g_error_free(err); - goto failed; - } - - service->name = g_key_file_get_string(keyfile, SERVICE_GROUP, - "Name", &err); - if (!service->name) { - error("%s: %s", file, err->message); - g_error_free(err); - goto failed; - } - - slash = strrchr(file, '/'); - if (!slash) { - error("No slash in service file path!?"); - goto failed; - } - - service->filename = g_strdup(slash + 1); - - service->descr = g_key_file_get_string(keyfile, SERVICE_GROUP, - "Description", &err); - if (err) { - debug("%s: %s", file, err->message); - g_error_free(err); - err = NULL; - } - - autostart = g_key_file_get_boolean(keyfile, SERVICE_GROUP, - "Autostart", &err); - if (err) { - debug("%s: %s", file, err->message); - g_error_free(err); - err = NULL; - } else - service->autostart = autostart; + if (!strcmp(ident, "input")) + name = "Input service"; + else if (!strcmp(ident, "audio")) + name = "Audio service"; + else if (!strcmp(ident, "network")) + name = "Network service"; + else if (!strcmp(ident, "serial")) + name = "Serial service"; + else + name = ""; - g_key_file_free(keyfile); + service->ident = g_strdup(ident); + service->name = g_strdup(name); return service; - -failed: - g_key_file_free(keyfile); - service_free(service); - return NULL; -} - -static gint service_filename_cmp(struct service *service, const char *filename) -{ - return strcmp(service->filename, filename); } -int init_services(const char *path) +int register_service(const char *ident) { - DIR *d; - struct dirent *e; - - d = opendir(path); - if (!d) { - error("Unable to open service dir %s: %s", path, strerror(errno)); - return -1; - } - - while ((e = readdir(d)) != NULL) { - char full_path[PATH_MAX]; - struct service *service; - size_t len = strlen(e->d_name); - - if (len < (strlen(SERVICE_SUFFIX) + 1)) - continue; - - /* Skip if the file doesn't end in .service */ - if (strcmp(&e->d_name[len - strlen(SERVICE_SUFFIX)], SERVICE_SUFFIX)) - continue; - - snprintf(full_path, sizeof(full_path) - 1, "%s/%s", path, e->d_name); + DBusConnection *conn = get_dbus_connection(); + struct service *service; + char obj_path[PATH_MAX]; + int i; - service = create_service(full_path); - if (!service) { - error("Unable to read %s", full_path); - continue; - } + if (g_slist_find_custom(services, ident, + (GCompareFunc) service_cmp_ident)) + return -EADDRINUSE; - if (register_service(service) < 0) { - error("Unable to register service"); - service_free(service); - continue; - } + snprintf(obj_path, sizeof(obj_path) - 1, + "/org/bluez/service_%s", ident); - if (service->autostart) - service_start(service, get_dbus_connection()); + /* Make the path valid for D-Bus */ + for (i = strlen("/org/bluez/"); obj_path[i]; i++) { + if (!isalnum(obj_path[i])) + obj_path[i] = '_'; } - closedir(d); + if (g_slist_find_custom(services, obj_path, + (GCompareFunc) service_cmp_path)) + return -EADDRINUSE; - return 0; -} + service = create_external_service(ident); -static struct service *create_external_service(const char *ident, - const char *name, const char *description) -{ - struct service *service; + debug("Registering service object: %s (%s)", + service->ident, obj_path); - service = g_try_new0(struct service, 1); - if (!service) { - error("OOM while allocating new external service"); - return NULL; + if (!dbus_connection_create_object_path(conn, obj_path, + service, NULL)) { + error("D-Bus failed to register %s object", obj_path); + return -1; } - service->filename = NULL; - service->name = g_strdup(name); - service->descr = g_strdup(description); - service->ident = g_strdup(ident); - - service->external = TRUE; - - return service; -} - -int service_register(DBusConnection *conn, const char *bus_name, const char *ident, - const char *name, const char *description) -{ - struct service *service; - const char *sender; - - service = create_external_service(ident, name, description); - if (!service) + if (!service_init(conn, obj_path)) { + error("Service init failed"); return -1; + } - if (!bus_name) { - sender = dbus_bus_get_unique_name(get_dbus_connection()); - service->bus_name = g_strdup(sender); - } else - service->bus_name = g_strdup(bus_name); + service->object_path = g_strdup(obj_path); - if (register_service(service) < 0) { - service_free(service); - return -1; - } + services = g_slist_append(services, service); - if (conn && bus_name) - name_listener_add(conn, bus_name, (name_cb_t) external_service_exit, - service); + dbus_connection_emit_signal(conn, BASE_PATH, MANAGER_INTERFACE, + "ServiceAdded", + DBUS_TYPE_STRING, &service->object_path, + DBUS_TYPE_INVALID); - dbus_connection_emit_signal(get_dbus_connection(), service->object_path, - SERVICE_INTERFACE, "Started", - DBUS_TYPE_INVALID); + dbus_connection_emit_signal(conn, service->object_path, + SERVICE_INTERFACE, + "Started", DBUS_TYPE_INVALID); return 0; } -int service_unregister(DBusConnection *conn, struct service *service) +void unregister_service(const char *ident) { - return unregister_service_for_connection(conn, service); } static gint name_cmp(struct service_uuids *su, const char *name) @@ -1098,16 +607,16 @@ struct service *search_service_by_uuid(const char *uuid) return service; } -void register_uuids(const char *name, const char **uuids) +void register_uuids(const char *ident, const char **uuids) { struct service_uuids *su; int i; - if (!name) + if (!ident) return; su = g_new0(struct service_uuids, 1); - su->name = g_strdup(name); + su->name = g_strdup(ident); for (i = 0; uuids[i]; i++); @@ -1134,7 +643,7 @@ static void service_uuids_free(struct service_uuids *su) g_free(su); } -void unregister_uuids(const char *name) +void unregister_uuids(const char *ident) { struct service_uuids *su; GSList *l; @@ -1142,7 +651,7 @@ void unregister_uuids(const char *name) if (!services_uuids) return; - l = g_slist_find_custom(services_uuids, name, (GCompareFunc) name_cmp); + l = g_slist_find_custom(services_uuids, ident, (GCompareFunc) name_cmp); if (!l) return; diff --git a/hcid/dbus-service.h b/hcid/dbus-service.h index 72a23f25..c96179ea 100644 --- a/hcid/dbus-service.h +++ b/hcid/dbus-service.h @@ -22,29 +22,10 @@ * */ -#define START_REPLY_TIMEOUT 5000 - struct service { - char *filename; char *object_path; - - DBusMessage *action; /* Either Start or Stop method call */ - - guint startup_timer; - guint shutdown_timer; - - /* These are set when the service is running */ - GPid pid; /* Process id */ - char *bus_name; /* D-Bus unique name */ - - /* Information parsed from the service file */ - char *name; - char *descr; char *ident; - gboolean autostart; - - /* Services without a *.service file */ - gboolean external; + char *name; }; void release_services(DBusConnection *conn); @@ -55,17 +36,13 @@ struct service *search_service(const char *pattern); struct service *search_service_by_uuid(const char *uuid); -int service_start(struct service *service, DBusConnection *conn); - -int init_services(const char *path); - -int service_register(DBusConnection *conn, const char *bus_name, const char *ident, - const char *name, const char *description); - int service_unregister(DBusConnection *conn, struct service *service); -void register_uuids(const char *name, const char **uuids); -void unregister_uuids(const char *name); +int register_service(const char *ident); +void unregister_service(const char *ident); + +void register_uuids(const char *ident, const char **uuids); +void unregister_uuids(const char *ident); typedef void (*service_auth_cb) (DBusError *derr, void *user_data); int service_req_auth(bdaddr_t *src, bdaddr_t *dst, diff --git a/hcid/main.c b/hcid/main.c index 9980cc4e..980afec2 100644 --- a/hcid/main.c +++ b/hcid/main.c @@ -922,8 +922,6 @@ int main(int argc, char *argv[]) * daemon needs to be re-worked. */ plugin_init(); - init_services(CONFIGDIR); - /* Start event processor */ g_main_loop_run(event_loop); diff --git a/hcid/manager.c b/hcid/manager.c index d470e53b..c4288278 100644 --- a/hcid/manager.c +++ b/hcid/manager.c @@ -312,8 +312,10 @@ static DBusHandlerResult list_services(DBusConnection *conn, static DBusHandlerResult activate_service(DBusConnection *conn, DBusMessage *msg, void *data) { + DBusMessage *reply; const char *pattern; struct service *service; + const char *busname = "org.bluez"; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern, @@ -324,29 +326,14 @@ static DBusHandlerResult activate_service(DBusConnection *conn, if (!service) return error_no_such_service(conn, msg); - if (service->bus_name) { - DBusMessage *reply; - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &service->bus_name, - DBUS_TYPE_INVALID); - - return send_message_and_unref(conn, reply); - } - - if (service->pid) - return error_service_start_in_progress(conn, msg); - - if (service_start(service, conn) < 0) - return error_failed_errno(conn, msg, ENOEXEC); + reply = dbus_message_new_method_return(msg); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; - service->action = dbus_message_ref(msg); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &busname, + DBUS_TYPE_INVALID); - return DBUS_HANDLER_RESULT_HANDLED; + return send_message_and_unref(conn, reply); } static DBusMethodVTable old_manager_methods[] = { |