1ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann/* 2ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 3be0ba88ce4a4c37821f1ffa46ff6411d278297c1Marcel Holtmann * D-Bus helper library 4ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 5d21f53083c83614a4dbae21b06e7aabfa1a12454Marcel Holtmann * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 6ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 7ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 8ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * This program is free software; you can redistribute it and/or modify 9ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * it under the terms of the GNU General Public License as published by 10ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * the Free Software Foundation; either version 2 of the License, or 11ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * (at your option) any later version. 12ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 13ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * This program is distributed in the hope that it will be useful, 14ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * GNU General Public License for more details. 17ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 18ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * You should have received a copy of the GNU General Public License 19ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * along with this program; if not, write to the Free Software 20ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann * 22ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann */ 23ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 24ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann#ifdef HAVE_CONFIG_H 25ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann#include <config.h> 26ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann#endif 27ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 2815ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#include <stdio.h> 29ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann#include <string.h> 30ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 318cc5595d9091b484b9a4abe314c0f3ec055e0581Marcel Holtmann#include <glib.h> 32ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann#include <dbus/dbus.h> 33ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 3415ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#include "gdbus.h" 35ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 3615ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#define info(fmt...) 3715ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#define error(fmt...) 3815ea15b3a752f0487bc50d0ea04925f1b9d33dcbMarcel Holtmann#define debug(fmt...) 39ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 40ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmannstruct generic_data { 41dd368f19884b9751a0f99ffebcd2c5520069f5dbMarcel Holtmann unsigned int refcount; 42f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmann GSList *interfaces; 43f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmann char *introspect; 44f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmann}; 45f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmann 46f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmannstruct interface_data { 4730957bc2890f3db99907178304046610e77c7efaJohan Hedberg char *name; 48d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusMethodTable *methods; 49d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusSignalTable *signals; 50d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusPropertyTable *properties; 5197e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann void *user_data; 5297e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann GDBusDestroyFunction destroy; 53ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann}; 54ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 5530877999b61e655ff7f4e804240098c4cd31831eMarcel Holtmannstatic void print_arguments(GString *gstr, const char *sig, 5630877999b61e655ff7f4e804240098c4cd31831eMarcel Holtmann const char *direction) 57d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg{ 58d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg int i; 59d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 60d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg for (i = 0; sig[i]; i++) { 61223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg char type[32]; 62b75f83543ab6385e56adc5efe0110b94a9a9555eMarcel Holtmann int struct_level, dict_level; 63b75f83543ab6385e56adc5efe0110b94a9a9555eMarcel Holtmann unsigned int len; 64223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg gboolean complete; 65223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg 66223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg complete = FALSE; 67223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg struct_level = dict_level = 0; 68223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg memset(type, 0, sizeof(type)); 69223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg 70223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg /* Gather enough data to have a single complete type */ 71223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) { 72223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg switch (sig[i]){ 73223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg case '(': 74223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg struct_level++; 75223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 76223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg case ')': 77223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg struct_level--; 78223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg if (struct_level <= 0 && dict_level <= 0) 79223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg complete = TRUE; 80223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 81223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg case '{': 82223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg dict_level++; 83223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 84223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg case '}': 85223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg dict_level--; 86223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg if (struct_level <= 0 && dict_level <= 0) 87223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg complete = TRUE; 88223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 89223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg case 'a': 90223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 91223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg default: 92223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg if (struct_level <= 0 && dict_level <= 0) 93223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg complete = TRUE; 94223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 95223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg } 96223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg 97223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg type[len] = sig[i]; 98223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg 99223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg if (complete) 100223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg break; 101223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg } 102223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg 103223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg 104d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg if (direction) 105d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg g_string_append_printf(gstr, 106223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg "\t\t\t<arg type=\"%s\" direction=\"%s\"/>\n", 107223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg type, direction); 108d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg else 109d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg g_string_append_printf(gstr, 110223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg "\t\t\t<arg type=\"%s\"/>\n", 111223aa9581953c03f371a10b3f0555f7fa132f690Johan Hedberg type); 112d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg } 113d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg} 114d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 115e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmannstatic void generate_interface_xml(GString *gstr, struct interface_data *iface) 116e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann{ 117d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusMethodTable *method; 118d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusSignalTable *signal; 119e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann 120e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann for (method = iface->methods; method && method->name; method++) { 121e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann if (!strlen(method->signature) && !strlen(method->reply)) 122e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n", 123e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann method->name); 124e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann else { 125e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n", 126e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann method->name); 127e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann print_arguments(gstr, method->signature, "in"); 128e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann print_arguments(gstr, method->reply, "out"); 129e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t\t</method>\n"); 130e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann } 131e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann } 132e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann 133e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann for (signal = iface->signals; signal && signal->name; signal++) { 134e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann if (!strlen(signal->signature)) 135e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n", 136e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann signal->name); 137e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann else { 138e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n", 139e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann signal->name); 140e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann print_arguments(gstr, signal->signature, NULL); 141e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t\t</signal>\n"); 142e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann } 143e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann } 144e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann} 145e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann 146251f743f1501e99176c4071487b93567e94fefaaJohan Hedbergstatic void generate_introspection_xml(DBusConnection *conn, 147e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann struct generic_data *data, const char *path) 148d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg{ 149d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg GSList *list; 150d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg GString *gstr; 1515cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg char **children; 1525cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg int i; 153d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 154d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg g_free(data->introspect); 155d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 156d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE); 157d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 158b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely g_string_append_printf(gstr, "<node name=\"%s\">\n", path); 159d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 160d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg for (list = data->interfaces; list; list = list->next) { 161d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg struct interface_data *iface = list->data; 162d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 163e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t<interface name=\"%s\">\n", 164e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann iface->name); 165d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 166e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann generate_interface_xml(gstr, iface); 167d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 168d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg g_string_append_printf(gstr, "\t</interface>\n"); 169d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg } 170d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 1715cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg if (!dbus_connection_list_registered(conn, path, &children)) 1725cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg goto done; 1735cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 1745cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg for (i = 0; children[i]; i++) 175e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann g_string_append_printf(gstr, "\t<node name=\"%s\"/>\n", 176e7bf43c753dda82371be083bdb063a96767576ebMarcel Holtmann children[i]); 1775cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 1785cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg dbus_free_string_array(children); 1795cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 1805cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedbergdone: 181d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg g_string_append_printf(gstr, "</node>\n"); 182d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg 183d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg data->introspect = g_string_free(gstr, FALSE); 184d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg} 185f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmann 186b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergelystatic DBusMessage *introspect(DBusConnection *connection, 187b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely DBusMessage *message, void *user_data) 188251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg{ 189b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely struct generic_data *data = user_data; 190251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg DBusMessage *reply; 191251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 192d1c4d1d53a5f153d6c778debe1470fc1f32857e8Johan Hedberg if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) { 193251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg error("Unexpected signature to introspect call"); 194b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely return NULL; 195251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg } 196251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 197251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg if (!data->introspect) 198251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg generate_introspection_xml(connection, data, 199251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg dbus_message_get_path(message)); 200251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 201251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg reply = dbus_message_new_method_return(message); 202251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg if (!reply) 203b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely return NULL; 204251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 205251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect, 206251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg DBUS_TYPE_INVALID); 207251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 208b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely return reply; 209251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg} 210251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 211251f743f1501e99176c4071487b93567e94fefaaJohan Hedbergstatic void generic_unregister(DBusConnection *connection, void *user_data) 212251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg{ 213251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg struct generic_data *data = user_data; 214251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 215251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg g_free(data->introspect); 216251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg g_free(data); 217251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg} 218251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 219251f743f1501e99176c4071487b93567e94fefaaJohan Hedbergstatic struct interface_data *find_interface(GSList *interfaces, 220251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg const char *name) 221251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg{ 222251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg GSList *list; 223251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 224b8481a1eb474bd60c9fc0cffbcbf0f8da76c1c9dMarcel Holtmann if (!name) 225b8481a1eb474bd60c9fc0cffbcbf0f8da76c1c9dMarcel Holtmann return NULL; 226b8481a1eb474bd60c9fc0cffbcbf0f8da76c1c9dMarcel Holtmann 227251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg for (list = interfaces; list; list = list->next) { 228251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg struct interface_data *iface = list->data; 229251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg if (!strcmp(name, iface->name)) 230251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg return iface; 231251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg } 232251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 233251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg return NULL; 234251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg} 235251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 236251f743f1501e99176c4071487b93567e94fefaaJohan Hedbergstatic DBusHandlerResult generic_message(DBusConnection *connection, 237251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg DBusMessage *message, void *user_data) 238251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg{ 239251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg struct generic_data *data = user_data; 240251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg struct interface_data *iface; 241d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusMethodTable *method; 242251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg const char *interface; 243251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 244251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg interface = dbus_message_get_interface(message); 245251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 246251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg iface = find_interface(data->interfaces, interface); 247251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg if (!iface) 248251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 249251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 250cc2d696524d90b3c624c8857338f8572c7edff99Marcel Holtmann for (method = iface->methods; method && 251aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann method->name && method->function; method++) { 252aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann DBusMessage *reply; 253aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 254aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (dbus_message_is_method_call(message, iface->name, 255aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann method->name) == FALSE) 256aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann continue; 257aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 258aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (dbus_message_has_signature(message, 259aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann method->signature) == FALSE) 260aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann continue; 261aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 262aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann reply = method->function(connection, message, iface->user_data); 263aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 264aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (method->flags & G_DBUS_METHOD_FLAG_NOREPLY) { 265aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (reply != NULL) 266aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann dbus_message_unref(reply); 267aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann return DBUS_HANDLER_RESULT_HANDLED; 268aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann } 269aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 270aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (method->flags & G_DBUS_METHOD_FLAG_ASYNC) { 271aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (reply == NULL) 272aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann return DBUS_HANDLER_RESULT_HANDLED; 273aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann } 274aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 275aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann if (reply == NULL) 276aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann return DBUS_HANDLER_RESULT_NEED_MEMORY; 277aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 278aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann dbus_connection_send(connection, reply, NULL); 279aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann dbus_message_unref(reply); 280aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 281aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann return DBUS_HANDLER_RESULT_HANDLED; 282aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann } 283aff0ec6707716c2ea129695f85715d59e3d9474bMarcel Holtmann 284251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 285251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg} 286251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 287251f743f1501e99176c4071487b93567e94fefaaJohan Hedbergstatic DBusObjectPathVTable generic_table = { 288251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg .unregister_function = generic_unregister, 289251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg .message_function = generic_message, 290251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg}; 291251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg 292fb2c49cfc95ee82f77df6b8242199599f5e9f9eeJohan Hedbergstatic void invalidate_parent_data(DBusConnection *conn, const char *child_path) 2935cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg{ 2945fcad6abebf97c6a06d9eb5c206d5c10bcf14eb7Claudio Takahasi struct generic_data *data = NULL; 2955cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg char *parent_path, *slash; 2965cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 2975cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg parent_path = g_strdup(child_path); 2985cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg slash = strrchr(parent_path, '/'); 2995cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg if (!slash) 3005cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg goto done; 3015cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 3021f6936fe7c9d16a2e184add8730ce714e8b8eaddDenis Kenzior if (slash == parent_path && parent_path[1] != '\0') 3031f6936fe7c9d16a2e184add8730ce714e8b8eaddDenis Kenzior parent_path[1] = '\0'; 3041f6936fe7c9d16a2e184add8730ce714e8b8eaddDenis Kenzior else 3051f6936fe7c9d16a2e184add8730ce714e8b8eaddDenis Kenzior *slash = '\0'; 3061f6936fe7c9d16a2e184add8730ce714e8b8eaddDenis Kenzior 3075cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg if (!strlen(parent_path)) 3085cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg goto done; 3095cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 3105cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg if (!dbus_connection_get_object_path_data(conn, parent_path, 311800e8fa2575c80d236312451f43ca5f4780524a6Johan Hedberg (void *) &data)) { 312800e8fa2575c80d236312451f43ca5f4780524a6Johan Hedberg invalidate_parent_data(conn, parent_path); 3135cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg goto done; 314800e8fa2575c80d236312451f43ca5f4780524a6Johan Hedberg } 3155cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 3165cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg if (!data) 3175cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg goto done; 3185cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 319251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg g_free(data->introspect); 320251f743f1501e99176c4071487b93567e94fefaaJohan Hedberg data->introspect = NULL; 3215cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 3225cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedbergdone: 3235cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg g_free(parent_path); 3245cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg} 3255cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 326b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergelystatic GDBusMethodTable introspect_methods[] = { 327b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely { "Introspect", "", "s", introspect }, 328b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely { } 329b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely}; 330b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 331b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergelystatic void add_interface(struct generic_data *data, const char *name, 332d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusMethodTable *methods, 333d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusSignalTable *signals, 334d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusPropertyTable *properties, 335b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely void *user_data, 336b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely GDBusDestroyFunction destroy) 337b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely{ 338b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely struct interface_data *iface; 339b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 340b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface = g_new0(struct interface_data, 1); 341b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->name = g_strdup(name); 342b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->methods = methods; 343b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->signals = signals; 344b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->properties = properties; 345b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->user_data = user_data; 346b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->destroy = destroy; 347b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 348b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely data->interfaces = g_slist_append(data->interfaces, iface); 349b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely} 350b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 351ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmannstatic struct generic_data *object_path_ref(DBusConnection *connection, 352ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann const char *path) 353ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann{ 354af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann struct generic_data *data; 355ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 356ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann if (dbus_connection_get_object_path_data(connection, path, 357af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann (void *) &data) == TRUE) { 358af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann if (data != NULL) { 359af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann data->refcount++; 360af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann return data; 361af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann } 362ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann } 363ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 364ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann data = g_new0(struct generic_data, 1); 365ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 366d370964fbe6a9e32837037dcf193a216a0a75077Johan Hedberg data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<node></node>"); 367f7c027662d2066b3862f41dbae3b68e5c1bafce7Marcel Holtmann 368ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann data->refcount = 1; 369ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 370d1c4d1d53a5f153d6c778debe1470fc1f32857e8Johan Hedberg if (!dbus_connection_register_object_path(connection, path, 371d1c4d1d53a5f153d6c778debe1470fc1f32857e8Johan Hedberg &generic_table, data)) { 37279e5dd0c9e917822d0a97a1f803fc7571b253643Marcel Holtmann g_free(data->introspect); 3733d16152fd30f2570ad8e9bb2427045e6fd317ce3Johan Hedberg g_free(data); 374ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann return NULL; 375ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann } 376ee6b2930a0519021232f92f615f6a8fd9cd61805Marcel Holtmann 377fb2c49cfc95ee82f77df6b8242199599f5e9f9eeJohan Hedberg invalidate_parent_data(connection, path); 3785cf1ae29510f5ec975080c793c692fedc10d86d8Johan Hedberg 379b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, 380b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely introspect_methods, NULL, NULL, data, NULL); 381b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 382ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann return data; 383ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann} 384ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 385b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergelystatic gboolean remove_interface(struct generic_data *data, const char *name) 386b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely{ 387b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely struct interface_data *iface; 388b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 389b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface = find_interface(data->interfaces, name); 390b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely if (!iface) 391b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely return FALSE; 392b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 393b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely data->interfaces = g_slist_remove(data->interfaces, iface); 394b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 395b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely if (iface->destroy) 396b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely iface->destroy(iface->user_data); 397b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 398b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely g_free(iface->name); 399b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely g_free(iface); 400b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 401b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely return TRUE; 402b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely} 403b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 404ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmannstatic void object_path_unref(DBusConnection *connection, const char *path) 405ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann{ 406ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann struct generic_data *data = NULL; 407ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 408af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann if (dbus_connection_get_object_path_data(connection, path, 409af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann (void *) &data) == FALSE) 410af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann return; 411af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann 412af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann if (data == NULL) 413ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann return; 414ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 415ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann data->refcount--; 416ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 417ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann if (data->refcount > 0) 418ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann return; 419ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 420b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE); 421b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely 422ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann invalidate_parent_data(connection, path); 423ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 424ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann dbus_connection_unregister_object_path(connection, path); 425ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann} 426ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 4273ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentzstatic gboolean check_signal(DBusConnection *conn, const char *path, 4283ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz const char *interface, const char *name, 4293ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz const char **args) 43055466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg{ 4315fcad6abebf97c6a06d9eb5c206d5c10bcf14eb7Claudio Takahasi struct generic_data *data = NULL; 43255466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg struct interface_data *iface; 433d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusSignalTable *signal; 43455466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 4353ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz *args = NULL; 4365fcad6abebf97c6a06d9eb5c206d5c10bcf14eb7Claudio Takahasi if (!dbus_connection_get_object_path_data(conn, path, 4375fcad6abebf97c6a06d9eb5c206d5c10bcf14eb7Claudio Takahasi (void *) &data) || !data) { 438d1c4d1d53a5f153d6c778debe1470fc1f32857e8Johan Hedberg error("dbus_connection_emit_signal: path %s isn't registered", 439d1c4d1d53a5f153d6c778debe1470fc1f32857e8Johan Hedberg path); 44055466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg return FALSE; 44155466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg } 44255466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 44355466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg iface = find_interface(data->interfaces, interface); 44455466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg if (!iface) { 44555466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg error("dbus_connection_emit_signal: %s does not implement %s", 44655466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg path, interface); 44755466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg return FALSE; 44855466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg } 44955466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 4501ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann for (signal = iface->signals; signal && signal->name; signal++) { 4511ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann if (!strcmp(signal->name, name)) { 4521ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann *args = signal->signature; 4531ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann break; 4541ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann } 4551ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann } 4561ed48482e52554d7bfa1a8edf8239399ae3e1155Marcel Holtmann 4573ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz if (!*args) { 45855466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg error("No signal named %s on interface %s", name, interface); 45955466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg return FALSE; 46055466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg } 46155466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 4623ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz return TRUE; 4633ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz} 4643ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz 465f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmannstatic dbus_bool_t emit_signal_valist(DBusConnection *conn, 4663ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz const char *path, 4673ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz const char *interface, 4683ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz const char *name, 4693ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz int first, 4703ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz va_list var_args) 4713ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz{ 4723ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz DBusMessage *signal; 4733ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz dbus_bool_t ret; 4743ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz const char *signature, *args; 4753ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz 4763ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz if (!check_signal(conn, path, interface, name, &args)) 4773ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz return FALSE; 4783ca0c59a0f86f9d4aaf6b6db167a3fd390dc0e4fLuiz Augusto von Dentz 47955466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg signal = dbus_message_new_signal(path, interface, name); 48055466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg if (!signal) { 48155466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg error("Unable to allocate new %s.%s signal", interface, name); 48255466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg return FALSE; 48355466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg } 48455466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 4859dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi ret = dbus_message_append_args_valist(signal, first, var_args); 4869dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi if (!ret) 4879dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi goto fail; 48855466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 4899dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi signature = dbus_message_get_signature(signal); 4909dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi if (strcmp(args, signature) != 0) { 4919dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi error("%s.%s: expected signature'%s' but got '%s'", 4929dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi interface, name, args, signature); 4939dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi ret = FALSE; 4949dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi goto fail; 49555466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg } 49655466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 4979dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi ret = dbus_connection_send(conn, signal, NULL); 498dd368f19884b9751a0f99ffebcd2c5520069f5dbMarcel Holtmann 4999dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasifail: 50055466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg dbus_message_unref(signal); 50155466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 5029dca4cf2d579b58c62d0ce98102250a6e0759daeClaudio Takahasi return ret; 50355466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg} 50455466e2f43cf52b563954a9c2d1a722f6c646f7cJohan Hedberg 5055567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmanngboolean g_dbus_register_interface(DBusConnection *connection, 5065567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann const char *path, const char *name, 507d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusMethodTable *methods, 508d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusSignalTable *signals, 509d44989c514beb2f66874babe6b0e75eb444c11e8Marcel Holtmann const GDBusPropertyTable *properties, 5105567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann void *user_data, 5115567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann GDBusDestroyFunction destroy) 5125567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann{ 513ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann struct generic_data *data; 51497e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 515ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann data = object_path_ref(connection, path); 516ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann if (data == NULL) 51797e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann return FALSE; 51897e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 5199bbcbff03911ed1094ce4f2d4aa57df1282621d2Johan Hedberg if (find_interface(data->interfaces, name)) { 5209bbcbff03911ed1094ce4f2d4aa57df1282621d2Johan Hedberg object_path_unref(connection, path); 52197e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann return FALSE; 5229bbcbff03911ed1094ce4f2d4aa57df1282621d2Johan Hedberg } 52397e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 524b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely add_interface(data, name, methods, signals, 525b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely properties, user_data, destroy); 52697e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 52797e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann g_free(data->introspect); 52897e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann data->introspect = NULL; 52997e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 53097e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann return TRUE; 5315567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann} 5325567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann 5335567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmanngboolean g_dbus_unregister_interface(DBusConnection *connection, 5345567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann const char *path, const char *name) 5355567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann{ 53697e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann struct generic_data *data = NULL; 53797e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 53821f3750cf534b1326f9d1357b8713d881437907aRaymond Liu if (!path) 53921f3750cf534b1326f9d1357b8713d881437907aRaymond Liu return FALSE; 54021f3750cf534b1326f9d1357b8713d881437907aRaymond Liu 541af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann if (dbus_connection_get_object_path_data(connection, path, 542af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann (void *) &data) == FALSE) 543af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann return FALSE; 544af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann 545af6885a49f231d2e5fe421187679b27252658b6cMarcel Holtmann if (data == NULL) 54697e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann return FALSE; 54797e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 548b7ec8242e53006e83c63cb8cd8b27a007e91aa48RISKÓ Gergely if (remove_interface(data, name) == FALSE) 54997e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann return FALSE; 55097e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 55197e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann g_free(data->introspect); 55297e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann data->introspect = NULL; 55397e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann 554ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann object_path_unref(connection, path); 555ac79141ef561c9d87494350c2b28b0d37975650aMarcel Holtmann 55697e97deb25d098c2e094ebfa8be2ed3994cc56baMarcel Holtmann return TRUE; 5575567809ce0381ebfc22d77e5df31624d23c591dcMarcel Holtmann} 558d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann 559d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel HoltmannDBusMessage *g_dbus_create_error_valist(DBusMessage *message, const char *name, 560d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann const char *format, va_list args) 561d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann{ 5620b3d10c5ef6262410e6799ee3e2037c4441b563dJohan Hedberg char str[1024]; 5630b3d10c5ef6262410e6799ee3e2037c4441b563dJohan Hedberg 5640b3d10c5ef6262410e6799ee3e2037c4441b563dJohan Hedberg vsnprintf(str, sizeof(str), format, args); 5650b3d10c5ef6262410e6799ee3e2037c4441b563dJohan Hedberg 5660b3d10c5ef6262410e6799ee3e2037c4441b563dJohan Hedberg return dbus_message_new_error(message, name, str); 567d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann} 568d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann 569d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel HoltmannDBusMessage *g_dbus_create_error(DBusMessage *message, const char *name, 570d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann const char *format, ...) 571d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann{ 572d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann va_list args; 573d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann DBusMessage *reply; 574d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann 575d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann va_start(args, format); 576d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann 577d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann reply = g_dbus_create_error_valist(message, name, format, args); 578d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann 579d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann va_end(args); 580d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann 581d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann return reply; 582d0b06ea8fd1a8642c99d6b2c7661d562acf3c43eMarcel Holtmann} 583671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 584671e8bc7340909da8b0fe750176423113e9ea8c1Marcel HoltmannDBusMessage *g_dbus_create_reply_valist(DBusMessage *message, 585671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann int type, va_list args) 586671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann{ 587671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann DBusMessage *reply; 588671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 589671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann reply = dbus_message_new_method_return(message); 590671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann if (reply == NULL) 591671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann return NULL; 592671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 593671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann if (dbus_message_append_args_valist(reply, type, args) == FALSE) { 594671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann dbus_message_unref(reply); 595671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann return NULL; 596671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann } 597671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 598671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann return reply; 599671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann} 600671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 601671e8bc7340909da8b0fe750176423113e9ea8c1Marcel HoltmannDBusMessage *g_dbus_create_reply(DBusMessage *message, int type, ...) 602671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann{ 603671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann va_list args; 604671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann DBusMessage *reply; 605671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 606671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann va_start(args, type); 607671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 608671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann reply = g_dbus_create_reply_valist(message, type, args); 609671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 610671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann va_end(args); 611671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann 612671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann return reply; 613671e8bc7340909da8b0fe750176423113e9ea8c1Marcel Holtmann} 61480d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 61580d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmanngboolean g_dbus_send_message(DBusConnection *connection, DBusMessage *message) 61680d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann{ 61780d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann dbus_bool_t result; 61880d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 619b892677f0ba83e28daf6c05561295c1145d1c59fMarcel Holtmann if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 620b892677f0ba83e28daf6c05561295c1145d1c59fMarcel Holtmann dbus_message_set_no_reply(message, TRUE); 621b892677f0ba83e28daf6c05561295c1145d1c59fMarcel Holtmann 62280d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann result = dbus_connection_send(connection, message, NULL); 62380d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 62480d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann dbus_message_unref(message); 62580d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 62680d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann return result; 62780d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann} 62880d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 62980d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmanngboolean g_dbus_send_reply_valist(DBusConnection *connection, 63080d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann DBusMessage *message, int type, va_list args) 63180d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann{ 63280d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann DBusMessage *reply; 63380d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 63480d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann reply = dbus_message_new_method_return(message); 63580d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann if (reply == NULL) 63680d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann return FALSE; 63780d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 63880d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann if (dbus_message_append_args_valist(reply, type, args) == FALSE) { 63980d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann dbus_message_unref(reply); 64080d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann return FALSE; 64180d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann } 64280d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 64380d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann return g_dbus_send_message(connection, reply); 64480d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann} 64580d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 64680d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmanngboolean g_dbus_send_reply(DBusConnection *connection, 64780d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann DBusMessage *message, int type, ...) 64880d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann{ 64980d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann va_list args; 65080d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann gboolean result; 65180d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 65280d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann va_start(args, type); 65380d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 65480d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann result = g_dbus_send_reply_valist(connection, message, type, args); 65580d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 65680d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann va_end(args); 65780d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann 65880d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann return result; 65980d6914d167a731d97aff4e25497f84e96e09fe3Marcel Holtmann} 660f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann 661f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmanngboolean g_dbus_emit_signal(DBusConnection *connection, 662f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann const char *path, const char *interface, 663f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann const char *name, int type, ...) 664f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann{ 66514673292786fe0c37ed2953cadedd2e200759887Marcel Holtmann va_list args; 666f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann gboolean result; 667f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann 66814673292786fe0c37ed2953cadedd2e200759887Marcel Holtmann va_start(args, type); 669f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann 670f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann result = emit_signal_valist(connection, path, interface, 671f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann name, type, args); 672f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann 67314673292786fe0c37ed2953cadedd2e200759887Marcel Holtmann va_end(args); 674f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann 67514673292786fe0c37ed2953cadedd2e200759887Marcel Holtmann return result; 676f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann} 677f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann 678f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmanngboolean g_dbus_emit_signal_valist(DBusConnection *connection, 679f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann const char *path, const char *interface, 680f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann const char *name, int type, va_list args) 681f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann{ 682f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann return emit_signal_valist(connection, path, interface, 683f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann name, type, args); 684f06919f22999bd132ae6d84191245387eae9d733Marcel Holtmann} 685