diff options
-rw-r--r-- | common/dbus-helper.c | 188 |
1 files changed, 97 insertions, 91 deletions
diff --git a/common/dbus-helper.c b/common/dbus-helper.c index 639b6d3f..40cd3eac 100644 --- a/common/dbus-helper.c +++ b/common/dbus-helper.c @@ -61,93 +61,6 @@ DBusHandlerResult dbus_connection_send_and_unref(DBusConnection *connection, return DBUS_HANDLER_RESULT_HANDLED; } -static DBusHandlerResult introspect(DBusConnection *connection, - DBusMessage *message, struct generic_data *data) -{ - DBusMessage *reply; - - if (dbus_message_has_signature(message, - DBUS_TYPE_INVALID_AS_STRING) == FALSE) { - error("Unexpected signature to introspect call"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (!data->introspect) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - reply = dbus_message_new_method_return(message); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, - DBUS_TYPE_INVALID); - - return dbus_connection_send_and_unref(connection, reply); -} - -static void generic_unregister(DBusConnection *connection, void *user_data) -{ - struct generic_data *data = user_data; - - if (data->unregister_function) - data->unregister_function(connection, data->user_data); - - g_free(data->introspect); - g_free(data); -} - -static struct interface_data *find_interface(GSList *interfaces, - const char *name) -{ - GSList *list; - - for (list = interfaces; list; list = list->next) { - struct interface_data *iface = list->data; - if (!strcmp(name, iface->name)) - return iface; - } - - return NULL; -} - -static DBusHandlerResult generic_message(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct generic_data *data = user_data; - struct interface_data *iface; - DBusMethodVTable *current; - const char *interface; - - if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, - "Introspect") == TRUE) - return introspect(connection, message, data); - - interface = dbus_message_get_interface(message); - - iface = find_interface(data->interfaces, interface); - if (!iface) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - for (current = iface->methods; - current->name && current->message_function; current++) { - if (dbus_message_is_method_call(message, - iface->name, current->name) == FALSE) - continue; - - if (dbus_message_has_signature(message, - current->signature) == TRUE) - return current->message_function(connection, - message, data->user_data); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusObjectPathVTable generic_table = { - .unregister_function = generic_unregister, - .message_function = generic_message, -}; - static void print_arguments(GString *gstr, const char *sig, const char *direction) { int i; @@ -206,7 +119,9 @@ static void print_arguments(GString *gstr, const char *sig, const char *directio } } -static void update_introspection_data(DBusConnection *conn, struct generic_data *data, const char *path) +static void generate_introspection_xml(DBusConnection *conn, + struct generic_data *data, + const char *path) { GSList *list; GString *gstr; @@ -278,6 +193,94 @@ done: data->introspect = g_string_free(gstr, FALSE); } +static DBusHandlerResult introspect(DBusConnection *connection, + DBusMessage *message, struct generic_data *data) +{ + DBusMessage *reply; + + if (dbus_message_has_signature(message, + DBUS_TYPE_INVALID_AS_STRING) == FALSE) { + error("Unexpected signature to introspect call"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!data->introspect) + generate_introspection_xml(connection, data, + dbus_message_get_path(message)); + + reply = dbus_message_new_method_return(message); + if (!reply) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + + dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, + DBUS_TYPE_INVALID); + + return dbus_connection_send_and_unref(connection, reply); +} + +static void generic_unregister(DBusConnection *connection, void *user_data) +{ + struct generic_data *data = user_data; + + if (data->unregister_function) + data->unregister_function(connection, data->user_data); + + g_free(data->introspect); + g_free(data); +} + +static struct interface_data *find_interface(GSList *interfaces, + const char *name) +{ + GSList *list; + + for (list = interfaces; list; list = list->next) { + struct interface_data *iface = list->data; + if (!strcmp(name, iface->name)) + return iface; + } + + return NULL; +} + +static DBusHandlerResult generic_message(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + struct interface_data *iface; + DBusMethodVTable *current; + const char *interface; + + if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, + "Introspect") == TRUE) + return introspect(connection, message, data); + + interface = dbus_message_get_interface(message); + + iface = find_interface(data->interfaces, interface); + if (!iface) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + for (current = iface->methods; + current->name && current->message_function; current++) { + if (dbus_message_is_method_call(message, + iface->name, current->name) == FALSE) + continue; + + if (dbus_message_has_signature(message, + current->signature) == TRUE) + return current->message_function(connection, + message, data->user_data); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusObjectPathVTable generic_table = { + .unregister_function = generic_unregister, + .message_function = generic_message, +}; + static void update_parent_data(DBusConnection *conn, const char *child_path) { struct generic_data *data; @@ -299,7 +302,8 @@ static void update_parent_data(DBusConnection *conn, const char *child_path) if (!data) goto done; - update_introspection_data(conn, data, parent_path); + g_free(data->introspect); + data->introspect = NULL; done: g_free(parent_path); @@ -380,7 +384,8 @@ dbus_bool_t dbus_connection_register_interface(DBusConnection *connection, data->interfaces = g_slist_append(data->interfaces, iface); - update_introspection_data(connection, data, path); + g_free(data->introspect); + data->introspect = NULL; return TRUE; } @@ -404,7 +409,8 @@ dbus_bool_t dbus_connection_unregister_interface(DBusConnection *connection, g_free(iface->name); g_free(iface); - update_introspection_data(connection, data, path); + g_free(data->introspect); + data->introspect = NULL; return TRUE; } |