X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdbus%2Fmainloop.c;h=cff326f6153881b3aab4e0829b72803e38d7cce8;hb=091f5fa9229897a52424cd442b325f97d361dbc3;hp=eaba42ea4a5ec4f5127067b977afee8f043affbc;hpb=991fe1e5f6458aa30ee82ad73b2f0411b74b1d3e;p=framework%2Fconnectivity%2Fconnman.git diff --git a/gdbus/mainloop.c b/gdbus/mainloop.c index eaba42e..cff326f 100644 --- a/gdbus/mainloop.c +++ b/gdbus/mainloop.c @@ -2,7 +2,7 @@ * * D-Bus helper library * - * Copyright (C) 2004-2009 Marcel Holtmann + * Copyright (C) 2004-2011 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -25,15 +25,9 @@ #include #endif -#include - #include #include -#ifdef NEED_DBUS_WATCH_GET_UNIX_FD -#define dbus_watch_get_unix_fd dbus_watch_get_fd -#endif - #include "gdbus.h" #define DISPATCH_TIMEOUT 0 @@ -42,116 +36,135 @@ #define error(fmt...) #define debug(fmt...) -typedef struct { - uint32_t id; +struct timeout_handler { + guint id; DBusTimeout *timeout; -} timeout_handler_t; +}; struct watch_info { - guint watch_id; - GIOChannel *io; + guint id; + DBusWatch *watch; DBusConnection *conn; }; -struct server_info { - guint watch_id; - GIOChannel *io; - DBusServer *server; -}; - struct disconnect_data { - GDBusWatchFunction disconnect_cb; + GDBusWatchFunction function; void *user_data; }; -static DBusHandlerResult disconnect_filter(DBusConnection *conn, +static gboolean disconnected_signal(DBusConnection *conn, DBusMessage *msg, void *data) { struct disconnect_data *dc_data = data; - if (dbus_message_is_signal(msg, - DBUS_INTERFACE_LOCAL, "Disconnected") == TRUE) { - error("Got disconnected from the system message bus"); - dc_data->disconnect_cb(conn, dc_data->user_data); - dbus_connection_unref(conn); - } + error("Got disconnected from the system message bus"); + + dc_data->function(conn, dc_data->user_data); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + dbus_connection_unref(conn); + + return TRUE; } -static gboolean message_dispatch_cb(void *data) +static gboolean message_dispatch(void *data) { - DBusConnection *connection = data; + DBusConnection *conn = data; - dbus_connection_ref(connection); + dbus_connection_ref(conn); /* Dispatch messages */ - while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS); + while (dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS); - dbus_connection_unref(connection); + dbus_connection_unref(conn); return FALSE; } +static inline void queue_dispatch(DBusConnection *conn, + DBusDispatchStatus status) +{ + if (status == DBUS_DISPATCH_DATA_REMAINS) + g_timeout_add(DISPATCH_TIMEOUT, message_dispatch, conn); +} + static gboolean watch_func(GIOChannel *chan, GIOCondition cond, gpointer data) { - DBusWatch *watch = data; - struct watch_info *info = dbus_watch_get_data(watch); - int flags = 0; + struct watch_info *info = data; + unsigned int flags = 0; + DBusDispatchStatus status; + + dbus_connection_ref(info->conn); if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; if (cond & G_IO_HUP) flags |= DBUS_WATCH_HANGUP; if (cond & G_IO_ERR) flags |= DBUS_WATCH_ERROR; - dbus_watch_handle(watch, flags); + dbus_watch_handle(info->watch, flags); + + status = dbus_connection_get_dispatch_status(info->conn); + queue_dispatch(info->conn, status); - if (dbus_connection_get_dispatch_status(info->conn) == DBUS_DISPATCH_DATA_REMAINS) - g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, info->conn); + dbus_connection_unref(info->conn); return TRUE; } +static void watch_info_free(void *data) +{ + struct watch_info *info = data; + + if (info->id > 0) { + g_source_remove(info->id); + info->id = 0; + } + + dbus_connection_unref(info->conn); + + g_free(info); +} + static dbus_bool_t add_watch(DBusWatch *watch, void *data) { - GIOCondition cond = G_IO_HUP | G_IO_ERR; DBusConnection *conn = data; + GIOCondition cond = G_IO_HUP | G_IO_ERR; + GIOChannel *chan; struct watch_info *info; - int fd, flags; + unsigned int flags; + int fd; if (!dbus_watch_get_enabled(watch)) return TRUE; - info = g_new(struct watch_info, 1); + info = g_new0(struct watch_info, 1); fd = dbus_watch_get_unix_fd(watch); - info->io = g_io_channel_unix_new(fd); + chan = g_io_channel_unix_new(fd); + + info->watch = watch; info->conn = dbus_connection_ref(conn); - dbus_watch_set_data(watch, info, NULL); + dbus_watch_set_data(watch, info, watch_info_free); flags = dbus_watch_get_flags(watch); if (flags & DBUS_WATCH_READABLE) cond |= G_IO_IN; if (flags & DBUS_WATCH_WRITABLE) cond |= G_IO_OUT; - info->watch_id = g_io_add_watch(info->io, cond, watch_func, watch); + info->id = g_io_add_watch(chan, cond, watch_func, info); + + g_io_channel_unref(chan); return TRUE; } static void remove_watch(DBusWatch *watch, void *data) { - struct watch_info *info = dbus_watch_get_data(watch); + if (dbus_watch_get_enabled(watch)) + return; + /* will trigger watch_info_free() */ dbus_watch_set_data(watch, NULL, NULL); - - if (info) { - g_source_remove(info->watch_id); - g_io_channel_unref(info->io); - dbus_connection_unref(info->conn); - g_free(info); - } } static void watch_toggled(DBusWatch *watch, void *data) @@ -166,10 +179,12 @@ static void watch_toggled(DBusWatch *watch, void *data) static gboolean timeout_handler_dispatch(gpointer data) { - timeout_handler_t *handler = data; + struct timeout_handler *handler = data; + + handler->id = 0; /* if not enabled should not be polled by the main loop */ - if (dbus_timeout_get_enabled(handler->timeout) != TRUE) + if (!dbus_timeout_get_enabled(handler->timeout)) return FALSE; dbus_timeout_handle(handler->timeout); @@ -179,34 +194,40 @@ static gboolean timeout_handler_dispatch(gpointer data) static void timeout_handler_free(void *data) { - timeout_handler_t *handler = data; - if (!handler) - return; + struct timeout_handler *handler = data; + + if (handler->id > 0) { + g_source_remove(handler->id); + handler->id = 0; + } - g_source_remove(handler->id); g_free(handler); } static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) { - timeout_handler_t *handler; + int interval = dbus_timeout_get_interval(timeout); + struct timeout_handler *handler; if (!dbus_timeout_get_enabled(timeout)) return TRUE; - handler = g_new0(timeout_handler_t, 1); + handler = g_new0(struct timeout_handler, 1); handler->timeout = timeout; - handler->id = g_timeout_add(dbus_timeout_get_interval(timeout), - timeout_handler_dispatch, handler); dbus_timeout_set_data(timeout, handler, timeout_handler_free); + handler->id = g_timeout_add(interval, timeout_handler_dispatch, + handler); + return TRUE; } static void remove_timeout(DBusTimeout *timeout, void *data) { + /* will trigger timeout_handler_free() */ + dbus_timeout_set_data(timeout, NULL, NULL); } static void timeout_toggled(DBusTimeout *timeout, void *data) @@ -217,26 +238,51 @@ static void timeout_toggled(DBusTimeout *timeout, void *data) remove_timeout(timeout, data); } -static void dispatch_status_cb(DBusConnection *conn, - DBusDispatchStatus new_status, void *data) +static void dispatch_status(DBusConnection *conn, + DBusDispatchStatus status, void *data) { if (!dbus_connection_get_is_connected(conn)) return; - if (new_status == DBUS_DISPATCH_DATA_REMAINS) - g_timeout_add(DISPATCH_TIMEOUT, message_dispatch_cb, data); + queue_dispatch(conn, status); } -static void setup_dbus_with_main_loop(DBusConnection *conn) +static inline void setup_dbus_with_main_loop(DBusConnection *conn) { dbus_connection_set_watch_functions(conn, add_watch, remove_watch, watch_toggled, conn, NULL); dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, - timeout_toggled, conn, NULL); + timeout_toggled, NULL, NULL); + + dbus_connection_set_dispatch_status_function(conn, dispatch_status, + NULL, NULL); +} + +static gboolean setup_bus(DBusConnection *conn, const char *name, + DBusError *error) +{ + gboolean result; + DBusDispatchStatus status; + + if (name != NULL) { + result = g_dbus_request_name(conn, name, error); + + if (error != NULL) { + if (dbus_error_is_set(error) == TRUE) + return FALSE; + } - dbus_connection_set_dispatch_status_function(conn, dispatch_status_cb, - conn, NULL); + if (result == FALSE) + return FALSE; + } + + setup_dbus_with_main_loop(conn); + + status = dbus_connection_get_dispatch_status(conn); + queue_dispatch(conn, status); + + return TRUE; } DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name, @@ -254,74 +300,58 @@ DBusConnection *g_dbus_setup_bus(DBusBusType type, const char *name, if (conn == NULL) return NULL; - if (name != NULL) { - if (dbus_bus_request_name(conn, name, - DBUS_NAME_FLAG_DO_NOT_QUEUE, error) != - DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ) { - dbus_connection_unref(conn); - return NULL; - } - - if (error != NULL) { - if (dbus_error_is_set(error) == TRUE) { - dbus_connection_unref(conn); - return NULL; - } - } + if (setup_bus(conn, name, error) == FALSE) { + dbus_connection_unref(conn); + return NULL; } - setup_dbus_with_main_loop(conn); - return conn; } -gboolean g_dbus_request_name(DBusConnection *connection, const char *name, +DBusConnection *g_dbus_setup_private(DBusBusType type, const char *name, DBusError *error) { - return TRUE; -} + DBusConnection *conn; -gboolean g_dbus_check_service(DBusConnection *connection, const char *name) -{ - DBusMessage *message, *reply; - const char **names; - int i, count; - gboolean result = FALSE; - - message = dbus_message_new_method_call(DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "ListNames"); - if (message == NULL) { - error("Can't allocate new message"); - return FALSE; - } + conn = dbus_bus_get_private(type, error); - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, NULL); + if (error != NULL) { + if (dbus_error_is_set(error) == TRUE) + return NULL; + } - dbus_message_unref(message); + if (conn == NULL) + return NULL; - if (reply == NULL) { - error("Failed to execute method call"); - return FALSE; + if (setup_bus(conn, name, error) == FALSE) { + dbus_connection_unref(conn); + return NULL; } - if (dbus_message_get_args(reply, NULL, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &names, &count, DBUS_TYPE_INVALID) == FALSE) { - error("Failed to read name list"); - goto done; + return conn; +} + +gboolean g_dbus_request_name(DBusConnection *connection, const char *name, + DBusError *error) +{ + int result; + + result = dbus_bus_request_name(connection, name, + DBUS_NAME_FLAG_DO_NOT_QUEUE, error); + + if (error != NULL) { + if (dbus_error_is_set(error) == TRUE) + return FALSE; } - for (i = 0; i < count; i++) - if (g_str_equal(names[i], name) == TRUE) { - result = TRUE; - break; - } + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + if (error != NULL) + dbus_set_error(error, name, "Name already in use"); -done: - dbus_message_unref(reply); + return FALSE; + } - return result; + return TRUE; } gboolean g_dbus_set_disconnect_function(DBusConnection *connection, @@ -330,16 +360,17 @@ gboolean g_dbus_set_disconnect_function(DBusConnection *connection, { struct disconnect_data *dc_data; - dc_data = g_new(struct disconnect_data, 1); + dc_data = g_new0(struct disconnect_data, 1); - dc_data->disconnect_cb = function; + dc_data->function = function; dc_data->user_data = user_data; dbus_connection_set_exit_on_disconnect(connection, FALSE); - if (dbus_connection_add_filter(connection, disconnect_filter, - dc_data, g_free) == FALSE) { - error("Can't add D-Bus disconnect filter"); + if (g_dbus_add_signal_watch(connection, NULL, NULL, + DBUS_INTERFACE_LOCAL, "Disconnected", + disconnected_signal, dc_data, g_free) == 0) { + error("Failed to add watch for D-Bus Disconnected signal"); g_free(dc_data); return FALSE; }