X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=gdbus%2Fwatch.c;h=1ca3c4bda3cb0f7a614ed0e4367ec64fa0cd4807;hb=3a8dc46a144e3902729553ced331a2dc0d8140fa;hp=a402ca972f2a61af7e87098109901f7d692d6990;hpb=b1a3b1a457010d2495b20e836331106c6758fb96;p=platform%2Fupstream%2Fconnman.git diff --git a/gdbus/watch.c b/gdbus/watch.c old mode 100644 new mode 100755 index a402ca9..1ca3c4b --- a/gdbus/watch.c +++ b/gdbus/watch.c @@ -136,6 +136,51 @@ static struct filter_data *filter_data_find(DBusConnection *connection) return NULL; } +#if defined TIZEN_EXT +#define SENDER_PREFIX ",sender='%s'" +#define PATH_PREFIX ",path='%s'" +#define IFACE_PREFIX ",interface='%s'" +#define MEMBER_PREFIX ",member='%s'" +#define ARG0_PREFIX ",arg0='%s'" + +static gboolean check_rule_length(int remains, const char *prefix, const char *data) +{ + if (!prefix || !data) + return FALSE; + + return strlen(prefix) - 2 + strlen(data) < remains; +} + +static void format_rule(struct filter_data *data, char *rule, size_t size) +{ + const char *sender; + int offset; + + offset = snprintf(rule, size, "type='signal'"); + sender = data->name ? : data->owner; + + if (sender && + check_rule_length(size - offset, SENDER_PREFIX, sender)) + offset += snprintf(rule + offset, size - offset, + SENDER_PREFIX, sender); + if (data->path && + check_rule_length(size - offset, PATH_PREFIX, data->path)) + offset += snprintf(rule + offset, size - offset, + PATH_PREFIX, data->path); + if (data->interface && + check_rule_length(size - offset, IFACE_PREFIX, data->interface)) + offset += snprintf(rule + offset, size - offset, + IFACE_PREFIX, data->interface); + if (data->member && + check_rule_length(size - offset, MEMBER_PREFIX, data->member)) + offset += snprintf(rule + offset, size - offset, + MEMBER_PREFIX, data->member); + if (data->argument && + check_rule_length(size - offset, ARG0_PREFIX, data->argument)) + snprintf(rule + offset, size - offset, + ARG0_PREFIX, data->argument); +} +#else static void format_rule(struct filter_data *data, char *rule, size_t size) { const char *sender; @@ -160,6 +205,7 @@ static void format_rule(struct filter_data *data, char *rule, size_t size) snprintf(rule + offset, size - offset, ",arg0='%s'", data->argument); } +#endif static gboolean add_match(struct filter_data *data, DBusHandleMessageFunction filter) @@ -204,6 +250,30 @@ static gboolean remove_match(struct filter_data *data) return TRUE; } +static void filter_data_free(struct filter_data *data) +{ + GSList *l; + + /* Remove filter if there are no listeners left for the connection */ + if (filter_data_find(data->connection) == NULL) + dbus_connection_remove_filter(data->connection, message_filter, + NULL); + + for (l = data->callbacks; l != NULL; l = l->next) + g_free(l->data); + + g_slist_free(data->callbacks); + g_dbus_remove_watch(data->connection, data->name_watch); + g_free(data->name); + g_free(data->owner); + g_free(data->path); + g_free(data->interface); + g_free(data->member); + g_free(data->argument); + dbus_connection_unref(data->connection); + g_free(data); +} + static struct filter_data *filter_data_get(DBusConnection *connection, DBusHandleMessageFunction filter, const char *sender, @@ -240,15 +310,15 @@ proceed: data = g_new0(struct filter_data, 1); data->connection = dbus_connection_ref(connection); - data->name = name ? g_strdup(name) : NULL; - data->owner = owner ? g_strdup(owner) : NULL; + data->name = g_strdup(name); + data->owner = g_strdup(owner); data->path = g_strdup(path); data->interface = g_strdup(interface); data->member = g_strdup(member); data->argument = g_strdup(argument); if (!add_match(data, filter)) { - g_free(data); + filter_data_free(data); return NULL; } @@ -277,25 +347,6 @@ static struct filter_callback *filter_data_find_callback( return NULL; } -static void filter_data_free(struct filter_data *data) -{ - GSList *l; - - for (l = data->callbacks; l != NULL; l = l->next) - g_free(l->data); - - g_slist_free(data->callbacks); - g_dbus_remove_watch(data->connection, data->name_watch); - g_free(data->name); - g_free(data->owner); - g_free(data->path); - g_free(data->interface); - g_free(data->member); - g_free(data->argument); - dbus_connection_unref(data->connection); - g_free(data); -} - static void filter_data_call_and_free(struct filter_data *data) { GSList *l; @@ -357,11 +408,10 @@ static void service_data_free(struct service_data *data) callback->data = NULL; } +/* Returns TRUE if data is freed */ static gboolean filter_data_remove_callback(struct filter_data *data, struct filter_callback *cb) { - DBusConnection *connection; - data->callbacks = g_slist_remove(data->callbacks, cb); data->processed = g_slist_remove(data->processed, cb); @@ -380,21 +430,13 @@ static gboolean filter_data_remove_callback(struct filter_data *data, /* Don't remove the filter if other callbacks exist or data is lock * processing callbacks */ if (data->callbacks || data->lock) - return TRUE; + return FALSE; if (data->registered && !remove_match(data)) return FALSE; - connection = dbus_connection_ref(data->connection); listeners = g_slist_remove(listeners, data); - - /* Remove filter if there are no listeners left for the connection */ - if (filter_data_find(connection) == NULL) - dbus_connection_remove_filter(connection, message_filter, - NULL); - filter_data_free(data); - dbus_connection_unref(connection); return TRUE; } @@ -410,7 +452,9 @@ static DBusHandlerResult signal_filter(DBusConnection *connection, if (cb->signal_func && !cb->signal_func(connection, message, cb->user_data)) { - filter_data_remove_callback(data, cb); + if (filter_data_remove_callback(data, cb)) + break; + continue; } @@ -494,7 +538,9 @@ static DBusHandlerResult service_filter(DBusConnection *connection, /* Only auto remove if it is a bus name watch */ if (data->argument[0] == ':' && (cb->conn_func == NULL || cb->disc_func == NULL)) { - filter_data_remove_callback(data, cb); + if (filter_data_remove_callback(data, cb)) + break; + continue; } @@ -523,7 +569,7 @@ static DBusHandlerResult message_filter(DBusConnection *connection, member = dbus_message_get_member(message); dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID); - /* Sender is always the owner */ + /* If sender != NULL it is always the owner */ for (current = listeners; current != NULL; current = current->next) { data = current->data; @@ -531,6 +577,9 @@ static DBusHandlerResult message_filter(DBusConnection *connection, if (connection != data->connection) continue; + if (!sender && data->owner) + continue; + if (data->owner && g_str_equal(sender, data->owner) == FALSE) continue; @@ -563,6 +612,9 @@ static DBusHandlerResult message_filter(DBusConnection *connection, current); } + if (delete_listener == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + for (current = delete_listener; current != NULL; current = delete_listener->next) { GSList *l = current->data; @@ -574,18 +626,13 @@ static DBusHandlerResult message_filter(DBusConnection *connection, continue; remove_match(data); - listeners = g_slist_remove_link(listeners, l); + listeners = g_slist_delete_link(listeners, l); filter_data_free(data); } g_slist_free(delete_listener); - /* Remove filter if there are no listeners left for the connection */ - if (filter_data_find(connection) == NULL) - dbus_connection_remove_filter(connection, message_filter, - NULL); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -593,12 +640,15 @@ static gboolean update_service(void *user_data) { struct service_data *data = user_data; struct filter_callback *cb = data->callback; + DBusConnection *conn; + + conn = dbus_connection_ref(data->conn); + service_data_free(data); - update_name_cache(data->name, data->owner); if (cb->conn_func) - cb->conn_func(data->conn, cb->user_data); + cb->conn_func(conn, cb->user_data); - service_data_free(data); + dbus_connection_unref(conn); return FALSE; } @@ -700,7 +750,8 @@ guint g_dbus_add_service_watch(DBusConnection *connection, const char *name, if (name == NULL) return 0; - data = filter_data_get(connection, service_filter, NULL, NULL, + data = filter_data_get(connection, service_filter, + DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameOwnerChanged", name); if (data == NULL) @@ -752,6 +803,34 @@ guint g_dbus_add_signal_watch(DBusConnection *connection, return cb->id; } +guint g_dbus_add_properties_watch(DBusConnection *connection, + const char *sender, const char *path, + const char *interface, + GDBusSignalFunction function, void *user_data, + GDBusDestroyFunction destroy) +{ + struct filter_data *data; + struct filter_callback *cb; + + data = filter_data_get(connection, signal_filter, sender, path, + DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", + interface); + if (data == NULL) + return 0; + + cb = filter_data_add_callback(data, NULL, NULL, function, destroy, + user_data); + if (cb == NULL) + return 0; + + if (data->name != NULL && data->name_watch == 0) + data->name_watch = g_dbus_add_service_watch(connection, + data->name, NULL, + NULL, NULL, NULL); + + return cb->id; +} + gboolean g_dbus_remove_watch(DBusConnection *connection, guint id) { struct filter_data *data; @@ -782,6 +861,4 @@ void g_dbus_remove_all_watches(DBusConnection *connection) listeners = g_slist_remove(listeners, data); filter_data_call_and_free(data); } - - dbus_connection_remove_filter(connection, message_filter, NULL); }