diff options
Diffstat (limited to 'src/service-dbus/util/serviceutil.c')
-rw-r--r-- | src/service-dbus/util/serviceutil.c | 193 |
1 files changed, 192 insertions, 1 deletions
diff --git a/src/service-dbus/util/serviceutil.c b/src/service-dbus/util/serviceutil.c index 50b18b9..eed0ad8 100644 --- a/src/service-dbus/util/serviceutil.c +++ b/src/service-dbus/util/serviceutil.c @@ -26,7 +26,6 @@ #include <unistd.h> #include <sys/types.h> #include <dirent.h> -#include <gio/gio.h> #include "serviceutil.h" @@ -346,3 +345,195 @@ unsigned int service_operation( g_object_unref(manager_proxy); return 0; } + +/* Indications */ + +pthread_mutex_t m; +pthread_cond_t c; + +void *loop_thread( + void *arg) +{ + ServiceIndication *si = (ServiceIndication *) arg; + + lmi_debug("loop_thread enter"); + + g_main_loop_run(si->loop); + + lmi_debug("loop_thread exit"); + + return NULL; +} + +static void on_signal( + GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + lmi_debug("on_signal enter, object_path: %s", g_dbus_proxy_get_object_path(proxy)); + + pthread_mutex_lock(&m); + pthread_cond_signal(&c); + pthread_mutex_unlock(&m); + + lmi_debug("on_signal exit"); +} + +int ind_init(ServiceIndication *si, char *output, int output_len) +{ + GVariant *result = NULL; + GError *error = NULL; + gchar *tmps = NULL; + int i = 0; + + lmi_debug("ind_init enter"); + + si->context = g_main_context_new(); + g_main_context_push_thread_default(si->context); + + si->loop = NULL; + + si->slist = service_find_all(output, output_len); + if (si->slist == NULL) { + g_main_context_unref(si->context); + return -1; + } + + si->manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + NULL, MANAGER_NAME, MANAGER_OP, MANAGER_INTERFACE, NULL, &error); + if (!si->manager_proxy) { + strncpy(output, error->message, output_len); + g_error_free(error); + g_main_context_unref(si->context); + service_free_slist(si->slist); + return -1; + } + + si->signal_proxy = malloc(si->slist->cnt * sizeof(GDBusProxy *)); + if (!si->signal_proxy) { + strncpy(output, "Insufficient memory", output_len); + g_main_context_unref(si->context); + service_free_slist(si->slist); + return -1; + } + + for (i = 0; i < si->slist->cnt; i++) { + result = g_dbus_proxy_call_sync(si->manager_proxy, "LoadUnit", g_variant_new("(s)", si->slist->name[i]), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + strncpy(output, error->message, output_len); + g_error_free(error); + ind_destroy(si); + return -1; + } + g_variant_get(result, "(&o)", &tmps); + + error = NULL; + si->signal_proxy[i] = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + NULL, MANAGER_NAME, tmps, PROPERTY_INTERFACE, NULL, &error); + g_variant_unref(result); + if (si->signal_proxy[i] == NULL) + { + strncpy(output, error->message, output_len); + g_error_free(error); + ind_destroy(si); + return -1; + } + g_signal_connect(si->signal_proxy[i], "g-signal", G_CALLBACK(on_signal), NULL); + } + + error = NULL; + g_dbus_proxy_call_sync(si->manager_proxy, "Subscribe", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + strncpy(output, error->message, output_len); + g_error_free(error); + ind_destroy(si); + return -1; + } + + g_main_context_pop_thread_default(si->context); + + si->loop = g_main_loop_new(si->context, FALSE); + + if (pthread_create(&si->p, NULL, loop_thread, si) != 0) { + ind_destroy(si); + return -1; + } + + if (pthread_mutex_init(&m, NULL) != 0) { + strncpy(output, "pthread_mutex_init error", output_len); + return -1; + } + if (pthread_cond_init(&c, NULL) != 0) { + strncpy(output, "pthread_cond_init error", output_len); + return -1; + } + + lmi_debug("ind_init exit"); + + return 0; +} + +bool ind_watcher( + void **data) +{ + lmi_debug("ind_watcher enter"); + + pthread_mutex_lock(&m); + pthread_cond_wait(&c, &m); + pthread_mutex_unlock(&m); + + lmi_debug("ind_watcher exit"); + + return true; +} + +void ind_destroy(ServiceIndication *si) +{ + int i; + GError *error = NULL; + + lmi_debug("ind_destroy enter"); + + if (si->loop) { + g_main_loop_quit(si->loop); + if (pthread_join(si->p, NULL) != 0) { + lmi_debug("pthread_join error"); + } + g_main_loop_unref(si->loop); + } + + if (pthread_cond_destroy(&c) != 0) { + lmi_debug("pthread_cond_destroy error"); + } + if (pthread_mutex_destroy(&m) != 0) { + lmi_debug("pthread_mutex_destroy error"); + } + + g_main_context_unref(si->context); + + for (i = 0; i < si->slist->cnt; i++) { + if (si->signal_proxy[i]) { + g_object_unref(si->signal_proxy[i]); + } + } + free(si->signal_proxy); + + g_dbus_proxy_call_sync(si->manager_proxy, "Unsubscribe", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (error) { + lmi_debug("Unsubscribe error: %s", error->message); + g_error_free(error); + } + + g_object_unref(si->manager_proxy); + + service_free_slist(si->slist); + + lmi_debug("ind_destroy exit"); + + return; +} |