X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdbus%2Fobject.c;h=c333d5b702438de733ea81fb76f05569afebaaca;hb=5e42775e3dbed134c7e319b38b50eaf488b0f450;hp=3327cf4373a5999d323384a2be3203f91a07d1c5;hpb=c1445c100e2523fb4d8fcdf8a3cc0c1cd6769e4a;p=platform%2Fupstream%2Fconnman.git diff --git a/gdbus/object.c b/gdbus/object.c old mode 100644 new mode 100755 index 3327cf4..c333d5b --- a/gdbus/object.c +++ b/gdbus/object.c @@ -86,6 +86,7 @@ struct property_data { static int global_flags = 0; static struct generic_data *root; +static GSList *pending = NULL; static gboolean process_changes(gpointer user_data); static void process_properties_from_interface(struct generic_data *data, @@ -257,7 +258,8 @@ static DBusHandlerResult process_message(DBusConnection *connection, reply = method->function(connection, message, iface_user_data); - if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) { + if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY || + dbus_message_get_no_reply(message)) { if (reply != NULL) dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; @@ -271,8 +273,7 @@ static DBusHandlerResult process_message(DBusConnection *connection, if (reply == NULL) return DBUS_HANDLER_RESULT_NEED_MEMORY; - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); + g_dbus_send_message(connection, reply); return DBUS_HANDLER_RESULT_HANDLED; } @@ -312,19 +313,14 @@ void g_dbus_pending_error_valist(DBusConnection *connection, for (list = pending_security; list; list = list->next) { struct security_data *secdata = list->data; - DBusMessage *reply; if (secdata->pending != pending) continue; pending_security = g_slist_remove(pending_security, secdata); - reply = g_dbus_create_error_valist(secdata->message, + g_dbus_send_error_valist(connection, secdata->message, name, format, args); - if (reply != NULL) { - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } dbus_message_unref(secdata->message); g_free(secdata); @@ -469,18 +465,13 @@ void g_dbus_pending_property_error_valist(GDBusPendingReply id, va_list args) { struct property_data *propdata; - DBusMessage *reply; propdata = remove_pending_property_data(id); if (propdata == NULL) return; - reply = g_dbus_create_error_valist(propdata->message, name, format, - args); - if (reply != NULL) { - dbus_connection_send(propdata->conn, reply, NULL); - dbus_message_unref(reply); - } + g_dbus_send_error_valist(propdata->conn, propdata->message, name, + format, args); dbus_message_unref(propdata->message); g_free(propdata); @@ -599,7 +590,9 @@ static void emit_interfaces_added(struct generic_data *data) dbus_message_iter_close_container(&iter, &array); - g_dbus_send_message(data->conn, signal); + /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */ + dbus_connection_send(data->conn, signal, NULL); + dbus_message_unref(signal); } static struct interface_data *find_interface(GSList *interfaces, @@ -640,6 +633,16 @@ static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args, return TRUE; } +static void add_pending(struct generic_data *data) +{ + if (data->process_id > 0) + return; + + data->process_id = g_idle_add(process_changes, data); + + pending = g_slist_append(pending, data); +} + static gboolean remove_interface(struct generic_data *data, const char *name) { struct interface_data *iface; @@ -677,10 +680,7 @@ static gboolean remove_interface(struct generic_data *data, const char *name) data->removed = g_slist_prepend(data->removed, iface->name); g_free(iface); - if (data->process_id > 0) - return TRUE; - - data->process_id = g_idle_add(process_changes, data); + add_pending(data); return TRUE; } @@ -976,14 +976,26 @@ static void emit_interfaces_removed(struct generic_data *data) dbus_message_iter_close_container(&iter, &array); - g_dbus_send_message(data->conn, signal); + /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */ + dbus_connection_send(data->conn, signal, NULL); + dbus_message_unref(signal); +} + +static void remove_pending(struct generic_data *data) +{ + if (data->process_id > 0) { + g_source_remove(data->process_id); + data->process_id = 0; + } + + pending = g_slist_remove(pending, data); } static gboolean process_changes(gpointer user_data) { struct generic_data *data = user_data; - data->process_id = 0; + remove_pending(data); if (data->added != NULL) emit_interfaces_added(data); @@ -995,6 +1007,8 @@ static gboolean process_changes(gpointer user_data) if (data->removed != NULL) emit_interfaces_removed(data); + data->process_id = 0; + return FALSE; } @@ -1008,6 +1022,7 @@ static void generic_unregister(DBusConnection *connection, void *user_data) if (data->process_id > 0) { g_source_remove(data->process_id); + data->process_id = 0; process_changes(data); } @@ -1074,7 +1089,6 @@ static const GDBusMethodTable introspect_methods[] = { static void append_interfaces(struct generic_data *data, DBusMessageIter *iter) { DBusMessageIter array; - GSList *l; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING @@ -1086,12 +1100,7 @@ static void append_interfaces(struct generic_data *data, DBusMessageIter *iter) DBUS_DICT_ENTRY_END_CHAR_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array); - for (l = data->interfaces; l != NULL; l = l->next) { - if (g_slist_find(data->added, l->data)) - continue; - - append_interface(l->data, &array); - } + g_slist_foreach(data->interfaces, append_interface, &array); dbus_message_iter_close_container(iter, &array); } @@ -1211,10 +1220,8 @@ done: return TRUE; data->added = g_slist_append(data->added, iface); - if (data->process_id > 0) - return TRUE; - data->process_id = g_idle_add(process_changes, data); + add_pending(data); return TRUE; } @@ -1241,6 +1248,10 @@ static struct generic_data *object_path_ref(DBusConnection *connection, if (!dbus_connection_register_object_path(connection, path, &generic_table, data)) { +#if !defined TIZEN_EXT + dbus_connection_unref(data->conn); + g_free(data->path); +#endif g_free(data->introspect); g_free(data); return NULL; @@ -1319,45 +1330,6 @@ static gboolean check_signal(DBusConnection *conn, const char *path, return FALSE; } -static dbus_bool_t emit_signal_valist(DBusConnection *conn, - const char *path, - const char *interface, - const char *name, - int first, - va_list var_args) -{ - DBusMessage *signal; - dbus_bool_t ret; - const GDBusArgInfo *args; - - if (!check_signal(conn, path, interface, name, &args)) - return FALSE; - - signal = dbus_message_new_signal(path, interface, name); - if (signal == NULL) { - error("Unable to allocate new %s.%s signal", interface, name); - return FALSE; - } - - ret = dbus_message_append_args_valist(signal, first, var_args); - if (!ret) - goto fail; - - if (g_dbus_args_have_signature(args, signal) == FALSE) { - error("%s.%s: got unexpected signature '%s'", interface, name, - dbus_message_get_signature(signal)); - ret = FALSE; - goto fail; - } - - ret = dbus_connection_send(conn, signal, NULL); - -fail: - dbus_message_unref(signal); - - return ret; -} - gboolean g_dbus_register_interface(DBusConnection *connection, const char *path, const char *name, const GDBusMethodTable *methods, @@ -1443,7 +1415,10 @@ DBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name, { char str[1024]; - vsnprintf(str, sizeof(str), format, args); + if (format) + vsnprintf(str, sizeof(str), format, args); + else + str[0] = '\0'; return dbus_message_new_error(message, name, str); } @@ -1494,9 +1469,24 @@ DBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...) return reply; } +static void g_dbus_flush(DBusConnection *connection) +{ + GSList *l; + + for (l = pending; l;) { + struct generic_data *data = l->data; + + l = l->next; + if (data->conn != connection) + continue; + + process_changes(data); + } +} + gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message) { - dbus_bool_t result; + dbus_bool_t result = FALSE; if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL) dbus_message_set_no_reply(message, TRUE); @@ -1507,26 +1497,47 @@ gboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message) const GDBusArgInfo *args; if (!check_signal(connection, path, interface, name, &args)) - return FALSE; + goto out; } + /* Flush pending signal to guarantee message order */ + g_dbus_flush(connection); + result = dbus_connection_send(connection, message, NULL); +out: dbus_message_unref(message); return result; } +gboolean g_dbus_send_message_with_reply(DBusConnection *connection, + DBusMessage *message, + DBusPendingCall **call, int timeout) +{ + dbus_bool_t ret; + + /* Flush pending signal to guarantee message order */ + g_dbus_flush(connection); + + ret = dbus_connection_send_with_reply(connection, message, call, + timeout); + + if (ret == TRUE && call != NULL && *call == NULL) { + error("Unable to send message (passing fd blocked?)"); + return FALSE; + } + + return ret; +} + gboolean g_dbus_send_error_valist(DBusConnection *connection, DBusMessage *message, const char *name, const char *format, va_list args) { DBusMessage *error; - char str[1024]; - - vsnprintf(str, sizeof(str), format, args); - error = dbus_message_new_error(message, name, str); + error = g_dbus_create_error_valist(message, name, format, args); if (error == NULL) return FALSE; @@ -1590,7 +1601,7 @@ gboolean g_dbus_emit_signal(DBusConnection *connection, va_start(args, type); - result = emit_signal_valist(connection, path, interface, + result = g_dbus_emit_signal_valist(connection, path, interface, name, type, args); va_end(args); @@ -1602,8 +1613,36 @@ gboolean g_dbus_emit_signal_valist(DBusConnection *connection, const char *path, const char *interface, const char *name, int type, va_list args) { - return emit_signal_valist(connection, path, interface, - name, type, args); + DBusMessage *signal; + dbus_bool_t ret; + const GDBusArgInfo *args_info; + + if (!check_signal(connection, path, interface, name, &args_info)) + return FALSE; + + signal = dbus_message_new_signal(path, interface, name); + if (signal == NULL) { + error("Unable to allocate new %s.%s signal", interface, name); + return FALSE; + } + + ret = dbus_message_append_args_valist(signal, type, args); + if (!ret) + goto fail; + + if (g_dbus_args_have_signature(args_info, signal) == FALSE) { + error("%s.%s: got unexpected signature '%s'", interface, name, + dbus_message_get_signature(signal)); + ret = FALSE; + goto fail; + } + + return g_dbus_send_message(connection, signal); + +fail: + dbus_message_unref(signal); + + return ret; } static void process_properties_from_interface(struct generic_data *data, @@ -1614,6 +1653,8 @@ static void process_properties_from_interface(struct generic_data *data, DBusMessageIter iter, dict, array; GSList *invalidated; + data->pending_prop = FALSE; + if (iface->pending_prop == NULL) return; @@ -1663,10 +1704,12 @@ static void process_properties_from_interface(struct generic_data *data, g_slist_free(invalidated); dbus_message_iter_close_container(&iter, &array); - g_dbus_send_message(data->conn, signal); - g_slist_free(iface->pending_prop); iface->pending_prop = NULL; + + /* Use dbus_connection_send to avoid recursive calls to g_dbus_flush */ + dbus_connection_send(data->conn, signal, NULL); + dbus_message_unref(signal); } static void process_property_changes(struct generic_data *data) @@ -1678,13 +1721,12 @@ static void process_property_changes(struct generic_data *data) process_properties_from_interface(data, iface); } - - data->pending_prop = FALSE; } -void g_dbus_emit_property_changed(DBusConnection *connection, +void g_dbus_emit_property_changed_full(DBusConnection *connection, const char *path, const char *interface, - const char *name) + const char *name, + GDbusPropertyChangedFlags flags) { const GDBusPropertyTable *property; struct generic_data *data; @@ -1701,6 +1743,13 @@ void g_dbus_emit_property_changed(DBusConnection *connection, if (iface == NULL) return; + /* + * If ObjectManager is attached, don't emit property changed if + * interface is not yet published + */ + if (root && g_slist_find(data->added, iface)) + return; + property = find_property(iface->properties, name); if (property == NULL) { error("Could not find property %s in %p", name, @@ -1715,10 +1764,16 @@ void g_dbus_emit_property_changed(DBusConnection *connection, iface->pending_prop = g_slist_prepend(iface->pending_prop, (void *) property); - if (!data->process_id) { - data->process_id = g_idle_add(process_changes, data); - return; - } + if (flags & G_DBUS_PROPERTY_CHANGED_FLAG_FLUSH) + process_property_changes(data); + else + add_pending(data); +} + +void g_dbus_emit_property_changed(DBusConnection *connection, const char *path, + const char *interface, const char *name) +{ + g_dbus_emit_property_changed_full(connection, path, interface, name, 0); } gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, @@ -1774,3 +1829,8 @@ void g_dbus_set_flags(int flags) { global_flags = flags; } + +int g_dbus_get_flags(void) +{ + return global_flags; +}