00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026 #include <gobject/gvaluecollector.h>
00027 #include <dbus/dbus-glib.h>
00028 #include <dbus/dbus-glib-lowlevel.h>
00029 #include "dbus-gtest.h"
00030 #include "dbus-gutils.h"
00031 #include "dbus-gobject.h"
00032 #include "dbus-gsignature.h"
00033 #include "dbus-gvalue.h"
00034 #include "dbus-gmarshal.h"
00035 #include "dbus-gvalue-utils.h"
00036 #include <string.h>
00037
00038 typedef struct
00039 {
00040 char *default_iface;
00041 GType code_enum;
00042 } DBusGErrorInfo;
00043
00044 static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
00045 static GHashTable *marshal_table = NULL;
00046 static GData *error_metadata = NULL;
00047
00048 static char*
00049 uscore_to_wincaps (const char *uscore)
00050 {
00051 const char *p;
00052 GString *str;
00053 gboolean last_was_uscore;
00054
00055 last_was_uscore = TRUE;
00056
00057 str = g_string_new (NULL);
00058 p = uscore;
00059 while (p && *p)
00060 {
00061 if (*p == '-' || *p == '_')
00062 {
00063 last_was_uscore = TRUE;
00064 }
00065 else
00066 {
00067 if (last_was_uscore)
00068 {
00069 g_string_append_c (str, g_ascii_toupper (*p));
00070 last_was_uscore = FALSE;
00071 }
00072 else
00073 g_string_append_c (str, *p);
00074 }
00075 ++p;
00076 }
00077
00078 return g_string_free (str, FALSE);
00079 }
00080
00081 static const char *
00082 string_table_next (const char *table)
00083 {
00084 return (table + (strlen (table) + 1));
00085 }
00086
00087 static const char *
00088 string_table_lookup (const char *table, int index)
00089 {
00090 const char *ret;
00091
00092 ret = table;
00093
00094 while (index--)
00095 ret = string_table_next (ret);
00096
00097 return ret;
00098 }
00099
00100 static const char *
00101 get_method_data (const DBusGObjectInfo *object,
00102 const DBusGMethodInfo *method)
00103 {
00104 return object->data + method->data_offset;
00105 }
00106
00107 static char *
00108 object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
00109 {
00110
00111 return NULL;
00112 }
00113
00114 static char *
00115 object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
00116 {
00117
00118 return NULL;
00119 }
00120
00121 static const char *
00122 method_interface_from_object_info (const DBusGObjectInfo *object,
00123 const DBusGMethodInfo *method)
00124 {
00125 return string_table_lookup (get_method_data (object, method), 0);
00126 }
00127
00128 static const char *
00129 method_name_from_object_info (const DBusGObjectInfo *object,
00130 const DBusGMethodInfo *method)
00131 {
00132 return string_table_lookup (get_method_data (object, method), 1);
00133 }
00134
00135 static const char *
00136 method_arg_info_from_object_info (const DBusGObjectInfo *object,
00137 const DBusGMethodInfo *method)
00138 {
00139 return string_table_lookup (get_method_data (object, method), 3);
00140 }
00141
00142 typedef enum
00143 {
00144 RETVAL_NONE,
00145 RETVAL_NOERROR,
00146 RETVAL_ERROR
00147 } RetvalType;
00148
00149 static const char *
00150 arg_iterate (const char *data,
00151 const char **name,
00152 gboolean *in,
00153 gboolean *constval,
00154 RetvalType *retval,
00155 const char **type)
00156 {
00157 gboolean inarg;
00158
00159 if (name)
00160 *name = data;
00161
00162 data = string_table_next (data);
00163 switch (*data)
00164 {
00165 case 'I':
00166 inarg = TRUE;
00167 break;
00168 case 'O':
00169 inarg = FALSE;
00170 break;
00171 default:
00172 g_warning ("invalid arg direction '%c'", *data);
00173 inarg = FALSE;
00174 break;
00175 }
00176 if (in)
00177 *in = inarg;
00178
00179 if (!inarg)
00180 {
00181 data = string_table_next (data);
00182 switch (*data)
00183 {
00184 case 'F':
00185 if (constval)
00186 *constval = FALSE;
00187 break;
00188 case 'C':
00189 if (constval)
00190 *constval = TRUE;
00191 break;
00192 default:
00193 g_warning ("invalid arg const value '%c'", *data);
00194 break;
00195 }
00196 data = string_table_next (data);
00197 switch (*data)
00198 {
00199 case 'N':
00200 if (retval)
00201 *retval = RETVAL_NONE;
00202 break;
00203 case 'E':
00204 if (retval)
00205 *retval = RETVAL_ERROR;
00206 break;
00207 case 'R':
00208 if (retval)
00209 *retval = RETVAL_NOERROR;
00210 break;
00211 default:
00212 g_warning ("invalid arg ret value '%c'", *data);
00213 break;
00214 }
00215 }
00216 else
00217 {
00218 if (constval)
00219 *constval = FALSE;
00220 if (retval)
00221 *retval = FALSE;
00222 }
00223
00224 data = string_table_next (data);
00225 if (type)
00226 *type = data;
00227
00228 return string_table_next (data);
00229 }
00230
00231 static char *
00232 method_dir_signature_from_object_info (const DBusGObjectInfo *object,
00233 const DBusGMethodInfo *method,
00234 gboolean in)
00235 {
00236 const char *arg;
00237 GString *ret;
00238
00239 arg = method_arg_info_from_object_info (object, method);
00240
00241 ret = g_string_new (NULL);
00242
00243 while (*arg)
00244 {
00245 const char *name;
00246 gboolean arg_in;
00247 const char *type;
00248
00249 arg = arg_iterate (arg, &name, &arg_in, NULL, NULL, &type);
00250
00251 if (arg_in == in)
00252 g_string_append (ret, type);
00253 }
00254
00255 return g_string_free (ret, FALSE);
00256 }
00257
00258 static char *
00259 method_input_signature_from_object_info (const DBusGObjectInfo *object,
00260 const DBusGMethodInfo *method)
00261 {
00262 return method_dir_signature_from_object_info (object, method, TRUE);
00263 }
00264
00265 static char *
00266 method_output_signature_from_object_info (const DBusGObjectInfo *object,
00267 const DBusGMethodInfo *method)
00268 {
00269 return method_dir_signature_from_object_info (object, method, FALSE);
00270 }
00271
00272 static const char *
00273 propsig_iterate (const char *data, const char **iface, const char **name)
00274 {
00275 *iface = data;
00276
00277 data = string_table_next (data);
00278 *name = data;
00279
00280 return string_table_next (data);
00281 }
00282
00283 static GQuark
00284 dbus_g_object_type_dbus_metadata_quark (void)
00285 {
00286 static GQuark quark;
00287
00288 if (!quark)
00289 quark = g_quark_from_static_string ("DBusGObjectTypeDBusMetadataQuark");
00290 return quark;
00291 }
00292
00293 static GList *
00294 lookup_object_info (GObject *object)
00295 {
00296 GType *interfaces, *p;
00297 GList *info_list = NULL;
00298 const DBusGObjectInfo *info;
00299 GType classtype;
00300
00301 interfaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), NULL);
00302
00303 for (p = interfaces; *p != 0; p++)
00304 {
00305 info = g_type_get_qdata (*p, dbus_g_object_type_dbus_metadata_quark ());
00306 if (info != NULL && info->format_version >= 0)
00307 info_list = g_list_prepend (info_list, (gpointer) info);
00308 }
00309
00310 g_free (interfaces);
00311
00312 for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
00313 {
00314 info = g_type_get_qdata (classtype, dbus_g_object_type_dbus_metadata_quark ());
00315 if (info != NULL && info->format_version >= 0)
00316 info_list = g_list_prepend (info_list, (gpointer) info);
00317 }
00318
00319
00320
00321
00322
00323 return info_list;
00324 }
00325
00326 static void
00327 gobject_unregister_function (DBusConnection *connection,
00328 void *user_data)
00329 {
00330 GObject *object;
00331
00332 object = G_OBJECT (user_data);
00333
00334
00335
00336 }
00337
00338 typedef struct
00339 {
00340 GString *xml;
00341 GType gtype;
00342 const DBusGObjectInfo *object_info;
00343 } DBusGLibWriteIterfaceData;
00344
00345 typedef struct
00346 {
00347 GSList *methods;
00348 GSList *signals;
00349 GSList *properties;
00350 } DBusGLibWriteInterfaceValues;
00351
00352 static void
00353 write_interface (gpointer key, gpointer val, gpointer user_data)
00354 {
00355 const char *name;
00356 GSList *methods;
00357 GSList *signals;
00358 GSList *properties;
00359 GString *xml;
00360 const DBusGObjectInfo *object_info;
00361 DBusGLibWriteIterfaceData *data;
00362 DBusGLibWriteInterfaceValues *values;
00363
00364 name = key;
00365
00366 values = val;
00367 methods = values->methods;
00368 signals = values->signals;
00369 properties = values->properties;
00370
00371 data = user_data;
00372 xml = data->xml;
00373 object_info = data->object_info;
00374
00375 g_string_append_printf (xml, " <interface name=\"%s\">\n", name);
00376
00377
00378 for (; methods; methods = methods->next)
00379 {
00380 DBusGMethodInfo *method;
00381 const char *args;
00382 method = methods->data;
00383
00384 g_string_append_printf (xml, " <method name=\"%s\">\n",
00385 method_name_from_object_info (object_info, method));
00386
00387 args = method_arg_info_from_object_info (object_info, method);
00388
00389 while (*args)
00390 {
00391 const char *name;
00392 gboolean arg_in;
00393 const char *type;
00394
00395 args = arg_iterate (args, &name, &arg_in, NULL, NULL, &type);
00396
00397
00398 g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
00399 name, type, arg_in ? "in" : "out");
00400
00401 }
00402 g_string_append (xml, " </method>\n");
00403
00404 }
00405 g_slist_free (values->methods);
00406
00407 for (; signals; signals = signals->next)
00408 {
00409 guint id;
00410 guint arg;
00411 const char *signame;
00412 GSignalQuery query;
00413 char *s;
00414
00415 signame = signals->data;
00416
00417 s = _dbus_gutils_wincaps_to_uscore (signame);
00418
00419 id = g_signal_lookup (s, data->gtype);
00420 g_assert (id != 0);
00421
00422 g_signal_query (id, &query);
00423 g_assert (query.return_type == G_TYPE_NONE);
00424
00425 g_string_append_printf (xml, " <signal name=\"%s\">\n", signame);
00426
00427 for (arg = 0; arg < query.n_params; arg++)
00428 {
00429 char *dbus_type = _dbus_gtype_to_signature (query.param_types[arg]);
00430
00431 g_assert (dbus_type != NULL);
00432
00433 g_string_append (xml, " <arg type=\"");
00434 g_string_append (xml, dbus_type);
00435 g_string_append (xml, "\"/>\n");
00436 g_free (dbus_type);
00437 }
00438
00439 g_string_append (xml, " </signal>\n");
00440 g_free (s);
00441 }
00442 g_slist_free (values->signals);
00443
00444 for (; properties; properties = properties->next)
00445 {
00446 const char *propname;
00447 GParamSpec *spec;
00448 char *dbus_type;
00449 gboolean can_set;
00450 gboolean can_get;
00451 char *s;
00452
00453 propname = properties->data;
00454 spec = NULL;
00455
00456 s = _dbus_gutils_wincaps_to_uscore (propname);
00457
00458 spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
00459 g_assert (spec != NULL);
00460 g_free (s);
00461
00462 dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
00463 g_assert (dbus_type != NULL);
00464
00465 can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
00466 (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
00467
00468 can_get = (spec->flags & G_PARAM_READABLE) != 0;
00469
00470 if (can_set || can_get)
00471 {
00472 g_string_append_printf (xml, " <property name=\"%s\" ", propname);
00473 g_string_append (xml, "type=\"");
00474 g_string_append (xml, dbus_type);
00475 g_string_append (xml, "\" access=\"");
00476
00477 if (can_set && can_get)
00478 g_string_append (xml, "readwrite");
00479 else if (can_get)
00480 g_string_append (xml, "read");
00481 else
00482 {
00483 g_assert (can_set);
00484 g_string_append (xml, "write");
00485 }
00486
00487 g_string_append (xml, "\"/>\n");
00488 }
00489
00490 g_free (dbus_type);
00491 }
00492 g_slist_free (values->properties);
00493
00494 g_free (values);
00495 g_string_append (xml, " </interface>\n");
00496 }
00497
00498 static DBusGLibWriteInterfaceValues *
00499 lookup_values (GHashTable *interfaces, const char *method_interface)
00500 {
00501 DBusGLibWriteInterfaceValues *values;
00502 if ((values = g_hash_table_lookup (interfaces, (gpointer) method_interface)) == NULL)
00503 {
00504 values = g_new0 (DBusGLibWriteInterfaceValues, 1);
00505 g_hash_table_insert (interfaces, (gpointer) method_interface, values);
00506 }
00507 return values;
00508 }
00509
00510 static void
00511 introspect_interfaces (GObject *object, GString *xml)
00512 {
00513 GList *info_list;
00514 const GList *info_list_walk;
00515 const DBusGObjectInfo *info;
00516 DBusGLibWriteIterfaceData data;
00517 int i;
00518 GHashTable *interfaces;
00519 DBusGLibWriteInterfaceValues *values;
00520 const char *propsig;
00521
00522 info_list = lookup_object_info (object);
00523
00524 g_assert (info_list != NULL);
00525
00526
00527 for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
00528 {
00529 info = (DBusGObjectInfo *) info_list_walk->data;
00530 interfaces = g_hash_table_new (g_str_hash, g_str_equal);
00531
00532 g_assert (info != NULL);
00533
00534 for (i = 0; i < info->n_method_infos; i++)
00535 {
00536 const char *method_name;
00537 const char *method_interface;
00538 const char *method_args;
00539 const DBusGMethodInfo *method;
00540
00541 method = &(info->method_infos[i]);
00542
00543 method_interface = method_interface_from_object_info (info, method);
00544 method_name = method_name_from_object_info (info, method);
00545 method_args = method_arg_info_from_object_info (info, method);
00546
00547 values = lookup_values (interfaces, method_interface);
00548 values->methods = g_slist_prepend (values->methods, (gpointer) method);
00549 }
00550
00551 propsig = info->exported_signals;
00552 while (*propsig)
00553 {
00554 const char *iface;
00555 const char *signame;
00556
00557 propsig = propsig_iterate (propsig, &iface, &signame);
00558
00559 values = lookup_values (interfaces, iface);
00560 values->signals = g_slist_prepend (values->signals, (gpointer) signame);
00561 }
00562
00563 propsig = info->exported_properties;
00564 while (*propsig)
00565 {
00566 const char *iface;
00567 const char *propname;
00568
00569 propsig = propsig_iterate (propsig, &iface, &propname);
00570
00571 values = lookup_values (interfaces, iface);
00572 values->properties = g_slist_prepend (values->properties, (gpointer) propname);
00573 }
00574
00575 memset (&data, 0, sizeof (data));
00576 data.xml = xml;
00577 data.gtype = G_TYPE_FROM_INSTANCE (object);
00578 data.object_info = info;
00579
00580 g_hash_table_foreach (interfaces, write_interface, &data);
00581 g_hash_table_destroy (interfaces);
00582 }
00583
00584 g_list_free (info_list);
00585 }
00586
00587 static DBusHandlerResult
00588 handle_introspect (DBusConnection *connection,
00589 DBusMessage *message,
00590 GObject *object)
00591 {
00592 GString *xml;
00593 unsigned int i;
00594 DBusMessage *ret;
00595 char **children;
00596
00597 if (!dbus_connection_list_registered (connection,
00598 dbus_message_get_path (message),
00599 &children))
00600 g_error ("Out of memory");
00601
00602 xml = g_string_new (NULL);
00603
00604 g_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
00605
00606 g_string_append (xml, "<node>\n");
00607
00608
00609 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE);
00610 g_string_append (xml, " <method name=\"Introspect\">\n");
00611 g_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00612 g_string_append (xml, " </method>\n");
00613 g_string_append (xml, " </interface>\n");
00614
00615
00616 g_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_PROPERTIES);
00617 g_string_append (xml, " <method name=\"Get\">\n");
00618 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00619 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00620 g_string_append_printf (xml, " <arg name=\"value\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
00621 g_string_append (xml, " </method>\n");
00622 g_string_append (xml, " <method name=\"Set\">\n");
00623 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00624 g_string_append_printf (xml, " <arg name=\"propname\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00625 g_string_append_printf (xml, " <arg name=\"value\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_VARIANT_AS_STRING);
00626 g_string_append (xml, " </method>\n");
00627 g_string_append (xml, " <method name=\"GetAll\">\n");
00628 g_string_append_printf (xml, " <arg name=\"interface\" direction=\"in\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING);
00629 g_string_append_printf (xml, " <arg name=\"props\" direction=\"out\" type=\"%s\"/>\n",
00630 DBUS_TYPE_ARRAY_AS_STRING
00631 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00632 DBUS_TYPE_STRING_AS_STRING
00633 DBUS_TYPE_VARIANT_AS_STRING
00634 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
00635 );
00636
00637 g_string_append (xml, " </method>\n");
00638 g_string_append (xml, " </interface>\n");
00639
00640 introspect_interfaces (object, xml);
00641
00642
00643 for (i = 0; children[i]; i++)
00644 g_string_append_printf (xml, " <node name=\"%s\"/>\n",
00645 children[i]);
00646
00647
00648 g_string_append (xml, "</node>\n");
00649
00650 ret = dbus_message_new_method_return (message);
00651 if (ret == NULL)
00652 g_error ("Out of memory");
00653
00654 dbus_message_append_args (ret,
00655 DBUS_TYPE_STRING, &xml->str,
00656 DBUS_TYPE_INVALID);
00657
00658 dbus_connection_send (connection, ret, NULL);
00659 dbus_message_unref (ret);
00660
00661 g_string_free (xml, TRUE);
00662
00663 dbus_free_string_array (children);
00664
00665 return DBUS_HANDLER_RESULT_HANDLED;
00666 }
00667
00668 static DBusMessage*
00669 set_object_property (DBusConnection *connection,
00670 DBusMessage *message,
00671 DBusMessageIter *iter,
00672 GObject *object,
00673 GParamSpec *pspec)
00674 {
00675 GValue value = { 0, };
00676 DBusMessage *ret;
00677 DBusMessageIter sub;
00678 DBusGValueMarshalCtx context;
00679
00680 dbus_message_iter_recurse (iter, &sub);
00681
00682 context.recursion_depth = 0;
00683 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
00684 context.proxy = NULL;
00685
00686 g_value_init (&value, pspec->value_type);
00687 if (_dbus_gvalue_demarshal (&context, &sub, &value, NULL))
00688 {
00689 g_object_set_property (object,
00690 pspec->name,
00691 &value);
00692
00693 g_value_unset (&value);
00694
00695 ret = dbus_message_new_method_return (message);
00696 if (ret == NULL)
00697 g_error ("out of memory");
00698 }
00699 else
00700 {
00701 ret = dbus_message_new_error (message,
00702 DBUS_ERROR_INVALID_ARGS,
00703 "Argument's D-BUS type can't be converted to a GType");
00704 if (ret == NULL)
00705 g_error ("out of memory");
00706 }
00707
00708 return ret;
00709 }
00710
00711 static DBusMessage*
00712 get_object_property (DBusConnection *connection,
00713 DBusMessage *message,
00714 GObject *object,
00715 GParamSpec *pspec)
00716 {
00717 GType value_gtype;
00718 GValue value = {0, };
00719 gchar *variant_sig;
00720 DBusMessage *ret;
00721 DBusMessageIter iter, subiter;
00722
00723 ret = dbus_message_new_method_return (message);
00724 if (ret == NULL)
00725 g_error ("out of memory");
00726
00727
00728 g_value_init (&value, pspec->value_type);
00729 g_object_get_property (object, pspec->name, &value);
00730
00731 variant_sig = _dbus_gvalue_to_signature (&value);
00732 if (variant_sig == NULL)
00733 {
00734 value_gtype = G_VALUE_TYPE (&value);
00735 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
00736 g_value_unset (&value);
00737 return ret;
00738 }
00739
00740 dbus_message_iter_init_append (ret, &iter);
00741 if (!dbus_message_iter_open_container (&iter,
00742 DBUS_TYPE_VARIANT,
00743 variant_sig,
00744 &subiter))
00745 {
00746 g_free (variant_sig);
00747 g_value_unset (&value);
00748 return ret;
00749 }
00750
00751 if (!_dbus_gvalue_marshal (&subiter, &value))
00752 {
00753 dbus_message_unref (ret);
00754 ret = dbus_message_new_error (message,
00755 DBUS_ERROR_UNKNOWN_METHOD,
00756 "Can't convert GType of object property to a D-BUS type");
00757 }
00758
00759 dbus_message_iter_close_container (&iter, &subiter);
00760
00761 g_value_unset (&value);
00762 g_free (variant_sig);
00763
00764 return ret;
00765 }
00766
00767 static DBusMessage*
00768 get_all_object_properties (DBusConnection *connection,
00769 DBusMessage *message,
00770 const DBusGObjectInfo *object_info,
00771 GObject *object)
00772 {
00773 DBusMessage *ret;
00774 DBusMessageIter iter_ret;
00775 DBusMessageIter iter_dict;
00776 DBusMessageIter iter_dict_entry;
00777 DBusMessageIter iter_dict_value;
00778 const char *p;
00779 char *uscore_propname;
00780
00781 ret = dbus_message_new_method_return (message);
00782 if (ret == NULL)
00783 goto oom;
00784
00785 dbus_message_iter_init_append (ret, &iter_ret);
00786
00787 if (!dbus_message_iter_open_container (&iter_ret,
00788 DBUS_TYPE_ARRAY,
00789 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
00790 DBUS_TYPE_STRING_AS_STRING
00791 DBUS_TYPE_VARIANT_AS_STRING
00792 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
00793 &iter_dict))
00794 goto oom;
00795
00796 p = object_info->exported_properties;
00797 while (p != NULL && *p != '\0')
00798 {
00799 const char *prop_ifname;
00800 const char *prop_name;
00801 GParamSpec *pspec;
00802 GType value_gtype;
00803 GValue value = {0, };
00804 gchar *variant_sig;
00805
00806 prop_ifname = p;
00807
00808 while (*p != '\0')
00809 p++;
00810 p++;
00811 if (*p == '\0') {
00812 g_warning ("malformed exported_properties in object_info");
00813 break;
00814 }
00815 prop_name = p;
00816 while (*p != '\0')
00817 p++;
00818 p++;
00819
00820 uscore_propname = _dbus_gutils_wincaps_to_uscore (prop_name);
00821
00822 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), uscore_propname);
00823 if (pspec == NULL)
00824 {
00825 g_warning ("introspection data references non-existing property %s", uscore_propname);
00826 g_free (uscore_propname);
00827 continue;
00828 }
00829
00830 g_free (uscore_propname);
00831
00832 g_value_init (&value, pspec->value_type);
00833 g_object_get_property (object, pspec->name, &value);
00834
00835 variant_sig = _dbus_gvalue_to_signature (&value);
00836 if (variant_sig == NULL)
00837 {
00838 value_gtype = G_VALUE_TYPE (&value);
00839 g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
00840 g_value_unset (&value);
00841 continue;
00842 }
00843
00844 if (!dbus_message_iter_open_container (&iter_dict,
00845 DBUS_TYPE_DICT_ENTRY,
00846 NULL,
00847 &iter_dict_entry))
00848 goto oom;
00849 if (!dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &prop_name))
00850 goto oom;
00851
00852 if (!dbus_message_iter_open_container (&iter_dict_entry,
00853 DBUS_TYPE_VARIANT,
00854 variant_sig,
00855 &iter_dict_value))
00856 goto oom;
00857
00858 if (!_dbus_gvalue_marshal (&iter_dict_value, &value))
00859 goto oom;
00860
00861 if (!dbus_message_iter_close_container (&iter_dict_entry,
00862 &iter_dict_value))
00863 goto oom;
00864 if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
00865 goto oom;
00866
00867 g_value_unset (&value);
00868 g_free (variant_sig);
00869 }
00870
00871 if (!dbus_message_iter_close_container (&iter_ret, &iter_dict))
00872 goto oom;
00873
00874 return ret;
00875
00876 oom:
00877 g_error ("out of memory");
00878 }
00879
00880 static gboolean
00881 lookup_object_and_method (GObject *object,
00882 DBusMessage *message,
00883 const DBusGObjectInfo **object_ret,
00884 const DBusGMethodInfo **method_ret)
00885 {
00886 const char *interface;
00887 const char *member;
00888 const char *signature;
00889 GList *info_list;
00890 const GList *info_list_walk;
00891 const DBusGObjectInfo *info;
00892 int i;
00893
00894 interface = dbus_message_get_interface (message);
00895 member = dbus_message_get_member (message);
00896 signature = dbus_message_get_signature (message);
00897
00898 info_list = lookup_object_info (object);
00899
00900 for (info_list_walk = info_list; info_list_walk != NULL; info_list_walk = g_list_next (info_list_walk))
00901 {
00902 info = (DBusGObjectInfo *) info_list_walk->data;
00903 *object_ret = info;
00904
00905 for (i = 0; i < info->n_method_infos; i++)
00906 {
00907 const char *expected_member;
00908 const char *expected_interface;
00909 char *expected_signature;
00910 const DBusGMethodInfo *method;
00911
00912 method = &(info->method_infos[i]);
00913
00914
00915 expected_interface = method_interface_from_object_info (*object_ret, method);
00916 expected_member = method_name_from_object_info (*object_ret, method);
00917 expected_signature = method_input_signature_from_object_info (*object_ret, method);
00918
00919 if ((interface == NULL
00920 || strcmp (expected_interface, interface) == 0)
00921 && strcmp (expected_member, member) == 0
00922 && strcmp (expected_signature, signature) == 0)
00923 {
00924 g_free (expected_signature);
00925 *method_ret = method;
00926 g_list_free (info_list);
00927 return TRUE;
00928 }
00929 g_free (expected_signature);
00930 }
00931 }
00932
00933 if (info_list)
00934 g_list_free (info_list);
00935
00936 return FALSE;
00937 }
00938
00939 static char *
00940 gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
00941 const char *msg_interface,
00942 GQuark domain, gint code)
00943 {
00944 const char *domain_str;
00945 const char *code_str;
00946 GString *dbus_error_name;
00947
00948 domain_str = object_error_domain_prefix_from_object_info (object_info);
00949 code_str = object_error_code_from_object_info (object_info, domain, code);
00950
00951 if (!domain_str || !code_str)
00952 {
00953 DBusGErrorInfo *info;
00954
00955 g_static_rw_lock_reader_lock (&globals_lock);
00956
00957 if (error_metadata != NULL)
00958 info = g_datalist_id_get_data (&error_metadata, domain);
00959 else
00960 info = NULL;
00961
00962 g_static_rw_lock_reader_unlock (&globals_lock);
00963
00964 if (info)
00965 {
00966 GEnumValue *value;
00967 GEnumClass *klass;
00968
00969 klass = g_type_class_ref (info->code_enum);
00970 value = g_enum_get_value (klass, code);
00971 g_type_class_unref (klass);
00972
00973 domain_str = info->default_iface;
00974 code_str = value->value_nick;
00975 }
00976 }
00977
00978 if (!domain_str)
00979 domain_str = msg_interface;
00980
00981 if (!domain_str || !code_str)
00982 {
00983
00984 char *domain_from_quark;
00985
00986 dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
00987
00988 domain_from_quark = uscore_to_wincaps (g_quark_to_string (domain));
00989 g_string_append (dbus_error_name, domain_from_quark);
00990 g_free (domain_from_quark);
00991
00992 g_string_append_printf (dbus_error_name, ".Code%d", code);
00993 }
00994 else
00995 {
00996 dbus_error_name = g_string_new (domain_str);
00997 g_string_append_c (dbus_error_name, '.');
00998 g_string_append (dbus_error_name, code_str);
00999 }
01000
01001 return g_string_free (dbus_error_name, FALSE);
01002 }
01003
01004 static DBusMessage *
01005 gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
01006 DBusMessage *message,
01007 GError *error)
01008 {
01009 DBusMessage *reply;
01010
01011 if (!error)
01012 {
01013 char *error_msg;
01014
01015 error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
01016 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
01017 g_free (error_msg);
01018 }
01019 else
01020 {
01021 if (error->domain == DBUS_GERROR)
01022 {
01023 const gchar *name = DBUS_ERROR_FAILED;
01024
01025 switch (error->code)
01026 {
01027 case DBUS_GERROR_FAILED:
01028 name = DBUS_ERROR_FAILED;
01029 break;
01030 case DBUS_GERROR_NO_MEMORY:
01031 name = DBUS_ERROR_NO_MEMORY;
01032 break;
01033 case DBUS_GERROR_SERVICE_UNKNOWN:
01034 name = DBUS_ERROR_SERVICE_UNKNOWN;
01035 break;
01036 case DBUS_GERROR_NAME_HAS_NO_OWNER:
01037 name = DBUS_ERROR_NAME_HAS_NO_OWNER;
01038 break;
01039 case DBUS_GERROR_NO_REPLY:
01040 name = DBUS_ERROR_NO_REPLY;
01041 break;
01042 case DBUS_GERROR_IO_ERROR:
01043 name = DBUS_ERROR_IO_ERROR;
01044 break;
01045 case DBUS_GERROR_BAD_ADDRESS:
01046 name = DBUS_ERROR_BAD_ADDRESS;
01047 break;
01048 case DBUS_GERROR_NOT_SUPPORTED:
01049 name = DBUS_ERROR_NOT_SUPPORTED;
01050 break;
01051 case DBUS_GERROR_LIMITS_EXCEEDED:
01052 name = DBUS_ERROR_LIMITS_EXCEEDED;
01053 break;
01054 case DBUS_GERROR_ACCESS_DENIED:
01055 name = DBUS_ERROR_ACCESS_DENIED;
01056 break;
01057 case DBUS_GERROR_AUTH_FAILED:
01058 name = DBUS_ERROR_AUTH_FAILED;
01059 break;
01060 case DBUS_GERROR_NO_SERVER:
01061 name = DBUS_ERROR_NO_SERVER;
01062 break;
01063 case DBUS_GERROR_TIMEOUT:
01064 name = DBUS_ERROR_TIMEOUT;
01065 break;
01066 case DBUS_GERROR_NO_NETWORK:
01067 name = DBUS_ERROR_NO_NETWORK;
01068 break;
01069 case DBUS_GERROR_ADDRESS_IN_USE:
01070 name = DBUS_ERROR_ADDRESS_IN_USE;
01071 break;
01072 case DBUS_GERROR_DISCONNECTED:
01073 name = DBUS_ERROR_DISCONNECTED;
01074 break;
01075 case DBUS_GERROR_INVALID_ARGS:
01076 name = DBUS_ERROR_INVALID_ARGS;
01077 break;
01078 case DBUS_GERROR_FILE_NOT_FOUND:
01079 name = DBUS_ERROR_FILE_NOT_FOUND;
01080 break;
01081 case DBUS_GERROR_REMOTE_EXCEPTION:
01082 name = dbus_g_error_get_name (error);
01083 break;
01084 }
01085
01086 reply = dbus_message_new_error (message, name, error->message);
01087 }
01088 else
01089 {
01090 char *error_name;
01091 error_name = gerror_domaincode_to_dbus_error_name (object_info,
01092 dbus_message_get_interface (message),
01093 error->domain, error->code);
01094 reply = dbus_message_new_error (message, error_name, error->message);
01095 g_free (error_name);
01096 }
01097 }
01098 return reply;
01099 }
01100
01114 struct _DBusGMethodInvocation {
01115 DBusGConnection *connection;
01116 DBusGMessage *message;
01117 const DBusGObjectInfo *object;
01118 const DBusGMethodInfo *method;
01119 };
01120
01121 static DBusHandlerResult
01122 invoke_object_method (GObject *object,
01123 const DBusGObjectInfo *object_info,
01124 const DBusGMethodInfo *method,
01125 DBusConnection *connection,
01126 DBusMessage *message)
01127 {
01128 gboolean had_error, call_only;
01129 GError *gerror;
01130 GValueArray *value_array;
01131 GValue return_value = {0,};
01132 GClosure closure;
01133 char *in_signature;
01134 GArray *out_param_values = NULL;
01135 GValueArray *out_param_gvalues = NULL;
01136 int out_param_count;
01137 int out_param_pos, out_param_gvalue_pos;
01138 DBusHandlerResult result;
01139 DBusMessage *reply;
01140 gboolean have_retval;
01141 gboolean retval_signals_error;
01142 gboolean retval_is_synthetic;
01143 gboolean retval_is_constant;
01144 const char *arg_metadata;
01145
01146 gerror = NULL;
01147
01148
01149
01150
01151 if (strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0)
01152 call_only = TRUE;
01153 else
01154 call_only = FALSE;
01155
01156 have_retval = FALSE;
01157 retval_signals_error = FALSE;
01158 retval_is_synthetic = FALSE;
01159 retval_is_constant = FALSE;
01160
01161
01162
01163
01164
01165
01166 memset (&closure, 0, sizeof (closure));
01167
01168 in_signature = method_input_signature_from_object_info (object_info, method);
01169
01170
01171 {
01172 GArray *types_array;
01173 guint n_params;
01174 const GType *types;
01175 DBusGValueMarshalCtx context;
01176 GError *error = NULL;
01177
01178 context.recursion_depth = 0;
01179 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
01180 context.proxy = NULL;
01181
01182 types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
01183 n_params = types_array->len;
01184 types = (const GType*) types_array->data;
01185
01186 value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
01187 if (value_array == NULL)
01188 {
01189 g_free (in_signature);
01190 g_array_free (types_array, TRUE);
01191 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
01192 dbus_connection_send (connection, reply, NULL);
01193 dbus_message_unref (reply);
01194 g_error_free (error);
01195 return DBUS_HANDLER_RESULT_HANDLED;
01196 }
01197 g_array_free (types_array, TRUE);
01198 }
01199
01200
01201 g_value_array_prepend (value_array, NULL);
01202 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
01203 g_value_set_object (g_value_array_get_nth (value_array, 0), object);
01204
01205 if (call_only)
01206 {
01207 GValue context_value = {0,};
01208 DBusGMethodInvocation *context;
01209 context = g_new (DBusGMethodInvocation, 1);
01210 context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
01211 context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
01212 context->object = object_info;
01213 context->method = method;
01214 g_value_init (&context_value, G_TYPE_POINTER);
01215 g_value_set_pointer (&context_value, context);
01216 g_value_array_append (value_array, &context_value);
01217 }
01218 else
01219 {
01220 RetvalType retval;
01221 gboolean arg_in;
01222 gboolean arg_const;
01223 const char *argsig;
01224
01225 arg_metadata = method_arg_info_from_object_info (object_info, method);
01226
01227
01228 out_param_count = 0;
01229 while (*arg_metadata)
01230 {
01231 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
01232 if (arg_in)
01233 continue;
01234 if (retval != RETVAL_NONE)
01235 {
01236 DBusSignatureIter tmp_sigiter;
01237
01238 g_assert (!have_retval);
01239 have_retval = TRUE;
01240 retval_is_synthetic = FALSE;
01241
01242 switch (retval)
01243 {
01244 case RETVAL_NONE:
01245 g_assert_not_reached ();
01246 break;
01247 case RETVAL_NOERROR:
01248 retval_signals_error = FALSE;
01249 break;
01250 case RETVAL_ERROR:
01251 retval_signals_error = TRUE;
01252 break;
01253 }
01254
01255 retval_is_constant = arg_const;
01256
01257
01258 dbus_signature_iter_init (&tmp_sigiter, argsig);
01259 g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
01260 }
01261 else
01262 {
01263
01264 out_param_count++;
01265 }
01266 }
01267
01268
01269
01270
01271
01272
01273
01274 if (!have_retval)
01275 {
01276 have_retval = TRUE;
01277 retval_is_synthetic = TRUE;
01278 retval_signals_error = TRUE;
01279 g_value_init (&return_value, G_TYPE_BOOLEAN);
01280 }
01281
01282
01283
01284
01285
01286
01287 out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
01288
01289
01290
01291
01292 out_param_gvalues = g_value_array_new (out_param_count);
01293 out_param_pos = 0;
01294 out_param_gvalue_pos = 0;
01295
01296
01297 arg_metadata = method_arg_info_from_object_info (object_info, method);
01298
01299
01300
01301
01302 while (*arg_metadata)
01303 {
01304 GValue value = {0, };
01305 GTypeCValue storage;
01306 DBusSignatureIter tmp_sigiter;
01307 GType current_gtype;
01308
01309 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
01310
01311 if (arg_in || retval != RETVAL_NONE)
01312 continue;
01313
01314 dbus_signature_iter_init (&tmp_sigiter, argsig);
01315 current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
01316
01317 g_value_init (&value, G_TYPE_POINTER);
01318
01319
01320 if (current_gtype != G_TYPE_VALUE)
01321 {
01322 memset (&storage, 0, sizeof (storage));
01323 g_array_append_val (out_param_values, storage);
01324 g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
01325 out_param_pos++;
01326 }
01327 else
01328 {
01329 g_value_array_append (out_param_gvalues, NULL);
01330 g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
01331 out_param_gvalue_pos++;
01332 }
01333 g_value_array_append (value_array, &value);
01334 }
01335 }
01336
01337
01338 if (retval_signals_error)
01339 {
01340 g_assert (have_retval);
01341 g_value_array_append (value_array, NULL);
01342 g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
01343 g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
01344 }
01345
01346
01347 method->marshaller (&closure, have_retval ? &return_value : NULL,
01348 value_array->n_values,
01349 value_array->values,
01350 NULL, method->function);
01351 if (call_only)
01352 {
01353 result = DBUS_HANDLER_RESULT_HANDLED;
01354 goto done;
01355 }
01356 if (retval_signals_error)
01357 had_error = _dbus_gvalue_signals_error (&return_value);
01358 else
01359 had_error = FALSE;
01360
01361 if (!had_error)
01362 {
01363 DBusMessageIter iter;
01364
01365 reply = dbus_message_new_method_return (message);
01366 if (reply == NULL)
01367 goto nomem;
01368
01369
01370 dbus_message_iter_init_append (reply, &iter);
01371
01372
01373 if (have_retval && !retval_is_synthetic)
01374 {
01375 if (!_dbus_gvalue_marshal (&iter, &return_value))
01376 goto nomem;
01377 if (!retval_is_constant)
01378 g_value_unset (&return_value);
01379 }
01380
01381
01382 arg_metadata = method_arg_info_from_object_info (object_info, method);
01383
01384
01385 out_param_pos = 0;
01386 out_param_gvalue_pos = 0;
01387 while (*arg_metadata)
01388 {
01389 GValue gvalue = {0, };
01390 const char *arg_name;
01391 gboolean arg_in;
01392 gboolean constval;
01393 RetvalType retval;
01394 const char *arg_signature;
01395 DBusSignatureIter argsigiter;
01396
01397 do
01398 {
01399
01400
01401 arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
01402 }
01403 while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
01404
01405
01406
01407
01408 if (arg_in || retval != RETVAL_NONE)
01409 break;
01410
01411 dbus_signature_iter_init (&argsigiter, arg_signature);
01412
01413 g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
01414 if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
01415 {
01416 if (!_dbus_gvalue_take (&gvalue,
01417 &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
01418 g_assert_not_reached ();
01419 out_param_pos++;
01420 }
01421 else
01422 {
01423 g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
01424 out_param_gvalue_pos++;
01425 }
01426
01427 if (!_dbus_gvalue_marshal (&iter, &gvalue))
01428 goto nomem;
01429
01430
01431
01432
01433 if (!constval)
01434 g_value_unset (&gvalue);
01435 }
01436 }
01437 else
01438 reply = gerror_to_dbus_error_message (object_info, message, gerror);
01439
01440 if (reply)
01441 {
01442 dbus_connection_send (connection, reply, NULL);
01443 dbus_message_unref (reply);
01444 }
01445
01446 result = DBUS_HANDLER_RESULT_HANDLED;
01447 done:
01448 g_free (in_signature);
01449 if (!call_only)
01450 {
01451 g_array_free (out_param_values, TRUE);
01452 g_value_array_free (out_param_gvalues);
01453 }
01454 g_value_array_free (value_array);
01455 return result;
01456 nomem:
01457 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
01458 goto done;
01459 }
01460
01461 static DBusHandlerResult
01462 gobject_message_function (DBusConnection *connection,
01463 DBusMessage *message,
01464 void *user_data)
01465 {
01466 GParamSpec *pspec;
01467 GObject *object;
01468 gboolean setter;
01469 gboolean getter;
01470 gboolean getall;
01471 char *s;
01472 const char *wincaps_propname;
01473
01474 DBusMessageIter iter;
01475 const DBusGMethodInfo *method;
01476 const DBusGObjectInfo *object_info;
01477 DBusMessage *ret;
01478
01479 object = G_OBJECT (user_data);
01480
01481 if (dbus_message_is_method_call (message,
01482 DBUS_INTERFACE_INTROSPECTABLE,
01483 "Introspect"))
01484 return handle_introspect (connection, message, object);
01485
01486
01487 object_info = NULL;
01488 if (lookup_object_and_method (object, message, &object_info, &method))
01489 return invoke_object_method (object, object_info, method, connection, message);
01490
01491
01492
01493
01494 getter = FALSE;
01495 setter = FALSE;
01496 getall = FALSE;
01497 if (dbus_message_is_method_call (message,
01498 DBUS_INTERFACE_PROPERTIES,
01499 "Get"))
01500 getter = TRUE;
01501 else if (dbus_message_is_method_call (message,
01502 DBUS_INTERFACE_PROPERTIES,
01503 "Set"))
01504 setter = TRUE;
01505 else if (dbus_message_is_method_call (message,
01506 DBUS_INTERFACE_PROPERTIES,
01507 "GetAll"))
01508 getall = TRUE;
01509
01510 if (!(setter || getter || getall))
01511 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01512
01513 ret = NULL;
01514
01515 dbus_message_iter_init (message, &iter);
01516
01517 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01518 {
01519 g_warning ("Property get or set does not have an interface string as first arg\n");
01520 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01521 }
01522
01523
01524
01525
01526 dbus_message_iter_next (&iter);
01527
01528 if (getall)
01529 {
01530 if (object_info != NULL)
01531 ret = get_all_object_properties (connection, message, object_info, object);
01532 else
01533 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01534 }
01535 else if (getter || setter)
01536 {
01537 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01538 {
01539 g_warning ("Property get or set does not have a property name string as second arg\n");
01540 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01541 }
01542 dbus_message_iter_get_basic (&iter, &wincaps_propname);
01543 dbus_message_iter_next (&iter);
01544
01545 s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
01546
01547 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
01548 s);
01549
01550 g_free (s);
01551
01552 if (pspec != NULL)
01553 {
01554 if (setter)
01555 {
01556 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
01557 {
01558 g_warning ("Property set does not have a variant value as third arg\n");
01559 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01560 }
01561
01562 ret = set_object_property (connection, message, &iter,
01563 object, pspec);
01564 dbus_message_iter_next (&iter);
01565 }
01566 else if (getter)
01567 {
01568 ret = get_object_property (connection, message,
01569 object, pspec);
01570 }
01571 else
01572 {
01573 g_assert_not_reached ();
01574 ret = NULL;
01575 }
01576 }
01577 else
01578 {
01579 ret = dbus_message_new_error_printf (message,
01580 DBUS_ERROR_INVALID_ARGS,
01581 "No such property %s", wincaps_propname);
01582 }
01583 }
01584
01585 g_assert (ret != NULL);
01586
01587 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
01588 g_warning ("Property get, set or set all had too many arguments\n");
01589
01590 dbus_connection_send (connection, ret, NULL);
01591 dbus_message_unref (ret);
01592 return DBUS_HANDLER_RESULT_HANDLED;
01593 }
01594
01595 static const DBusObjectPathVTable gobject_dbus_vtable = {
01596 gobject_unregister_function,
01597 gobject_message_function,
01598 NULL
01599 };
01600
01601 typedef struct {
01602 GClosure closure;
01603 DBusGConnection *connection;
01604 GObject *object;
01605 const char *signame;
01606 const char *sigiface;
01607 } DBusGSignalClosure;
01608
01609 static GClosure *
01610 dbus_g_signal_closure_new (DBusGConnection *connection,
01611 GObject *object,
01612 const char *signame,
01613 const char *sigiface)
01614 {
01615 DBusGSignalClosure *closure;
01616
01617 closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
01618
01619 closure->connection = dbus_g_connection_ref (connection);
01620 closure->object = object;
01621 closure->signame = signame;
01622 closure->sigiface = sigiface;
01623 return (GClosure*) closure;
01624 }
01625
01626 static void
01627 dbus_g_signal_closure_finalize (gpointer data,
01628 GClosure *closure)
01629 {
01630 DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
01631
01632 dbus_g_connection_unref (sigclosure->connection);
01633 }
01634
01635 static void
01636 signal_emitter_marshaller (GClosure *closure,
01637 GValue *retval,
01638 guint n_param_values,
01639 const GValue *param_values,
01640 gpointer invocation_hint,
01641 gpointer marshal_data)
01642 {
01643 DBusGSignalClosure *sigclosure;
01644 DBusMessage *signal;
01645 DBusMessageIter iter;
01646 guint i;
01647 const char *path;
01648
01649 sigclosure = (DBusGSignalClosure *) closure;
01650
01651 g_assert (retval == NULL);
01652
01653 path = _dbus_gobject_get_path (sigclosure->object);
01654
01655 g_assert (path != NULL);
01656
01657 signal = dbus_message_new_signal (path,
01658 sigclosure->sigiface,
01659 sigclosure->signame);
01660 if (!signal)
01661 {
01662 g_error ("out of memory");
01663 return;
01664 }
01665
01666 dbus_message_iter_init_append (signal, &iter);
01667
01668
01669 for (i = 1; i < n_param_values; i++)
01670 {
01671 if (!_dbus_gvalue_marshal (&iter,
01672 (GValue *) (&(param_values[i]))))
01673 {
01674 g_warning ("failed to marshal parameter %d for signal %s",
01675 i, sigclosure->signame);
01676 goto out;
01677 }
01678 }
01679 dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
01680 signal, NULL);
01681 out:
01682 dbus_message_unref (signal);
01683 }
01684
01685 static void
01686 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
01687 {
01688 GType gtype;
01689 const char *sigdata;
01690 const char *iface;
01691 const char *signame;
01692 const DBusGObjectInfo *info;
01693
01694 gtype = G_TYPE_FROM_INSTANCE (object);
01695
01696 for (; info_list != NULL; info_list = g_list_next (info_list))
01697 {
01698 info = (DBusGObjectInfo *) info_list->data;
01699
01700 sigdata = info->exported_signals;
01701
01702 while (*sigdata != '\0')
01703 {
01704 guint id;
01705 GSignalQuery query;
01706 GClosure *closure;
01707 char *s;
01708
01709 sigdata = propsig_iterate (sigdata, &iface, &signame);
01710
01711 s = _dbus_gutils_wincaps_to_uscore (signame);
01712
01713 id = g_signal_lookup (s, gtype);
01714 if (id == 0)
01715 {
01716 g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
01717 s, signame, g_type_name (gtype));
01718 g_free (s);
01719 continue;
01720 }
01721
01722 g_signal_query (id, &query);
01723
01724 if (query.return_type != G_TYPE_NONE)
01725 {
01726 g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
01727 s, g_type_name (gtype), g_type_name (query.return_type));
01728 g_free (s);
01729 continue;
01730 }
01731
01732 closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
01733 g_closure_set_marshal (closure, signal_emitter_marshaller);
01734
01735 g_signal_connect_closure_by_id (object,
01736 id,
01737 0,
01738 closure,
01739 FALSE);
01740
01741 g_closure_add_finalize_notifier (closure, NULL,
01742 dbus_g_signal_closure_finalize);
01743 g_free (s);
01744 }
01745 }
01746 }
01747
01748 static gint
01749 dbus_error_to_gerror_code (const char *derr)
01750 {
01751 if (0) ;
01752 else if (!strcmp (derr, DBUS_ERROR_FAILED ))
01753 return DBUS_GERROR_FAILED ;
01754 else if (!strcmp (derr, DBUS_ERROR_NO_MEMORY ))
01755 return DBUS_GERROR_NO_MEMORY ;
01756 else if (!strcmp (derr, DBUS_ERROR_SERVICE_UNKNOWN ))
01757 return DBUS_GERROR_SERVICE_UNKNOWN ;
01758 else if (!strcmp (derr, DBUS_ERROR_NAME_HAS_NO_OWNER ))
01759 return DBUS_GERROR_NAME_HAS_NO_OWNER ;
01760 else if (!strcmp (derr, DBUS_ERROR_NO_REPLY ))
01761 return DBUS_GERROR_NO_REPLY ;
01762 else if (!strcmp (derr, DBUS_ERROR_IO_ERROR ))
01763 return DBUS_GERROR_IO_ERROR ;
01764 else if (!strcmp (derr, DBUS_ERROR_BAD_ADDRESS ))
01765 return DBUS_GERROR_BAD_ADDRESS ;
01766 else if (!strcmp (derr, DBUS_ERROR_NOT_SUPPORTED ))
01767 return DBUS_GERROR_NOT_SUPPORTED ;
01768 else if (!strcmp (derr, DBUS_ERROR_LIMITS_EXCEEDED ))
01769 return DBUS_GERROR_LIMITS_EXCEEDED ;
01770 else if (!strcmp (derr, DBUS_ERROR_ACCESS_DENIED ))
01771 return DBUS_GERROR_ACCESS_DENIED ;
01772 else if (!strcmp (derr, DBUS_ERROR_AUTH_FAILED ))
01773 return DBUS_GERROR_AUTH_FAILED ;
01774 else if (!strcmp (derr, DBUS_ERROR_NO_SERVER ))
01775 return DBUS_GERROR_NO_SERVER ;
01776 else if (!strcmp (derr, DBUS_ERROR_TIMEOUT ))
01777 return DBUS_GERROR_TIMEOUT ;
01778 else if (!strcmp (derr, DBUS_ERROR_NO_NETWORK ))
01779 return DBUS_GERROR_NO_NETWORK ;
01780 else if (!strcmp (derr, DBUS_ERROR_ADDRESS_IN_USE ))
01781 return DBUS_GERROR_ADDRESS_IN_USE ;
01782 else if (!strcmp (derr, DBUS_ERROR_DISCONNECTED ))
01783 return DBUS_GERROR_DISCONNECTED ;
01784 else if (!strcmp (derr, DBUS_ERROR_INVALID_ARGS ))
01785 return DBUS_GERROR_INVALID_ARGS ;
01786 else if (!strcmp (derr, DBUS_ERROR_FILE_NOT_FOUND ))
01787 return DBUS_GERROR_FILE_NOT_FOUND ;
01788 else if (!strcmp (derr, DBUS_ERROR_FILE_EXISTS ))
01789 return DBUS_GERROR_FILE_EXISTS ;
01790 else if (!strcmp (derr, DBUS_ERROR_UNKNOWN_METHOD ))
01791 return DBUS_GERROR_UNKNOWN_METHOD ;
01792 else if (!strcmp (derr, DBUS_ERROR_TIMED_OUT ))
01793 return DBUS_GERROR_TIMED_OUT ;
01794 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_NOT_FOUND ))
01795 return DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
01796 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_INVALID ))
01797 return DBUS_GERROR_MATCH_RULE_INVALID ;
01798 else if (!strcmp (derr, DBUS_ERROR_SPAWN_EXEC_FAILED ))
01799 return DBUS_GERROR_SPAWN_EXEC_FAILED ;
01800 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FORK_FAILED ))
01801 return DBUS_GERROR_SPAWN_FORK_FAILED ;
01802 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_EXITED ))
01803 return DBUS_GERROR_SPAWN_CHILD_EXITED ;
01804 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_SIGNALED ))
01805 return DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
01806 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FAILED ))
01807 return DBUS_GERROR_SPAWN_FAILED ;
01808 else if (!strcmp (derr, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN ))
01809 return DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
01810 else if (!strcmp (derr, DBUS_ERROR_INVALID_SIGNATURE ))
01811 return DBUS_GERROR_INVALID_SIGNATURE ;
01812 else if (!strcmp (derr, DBUS_ERROR_INVALID_FILE_CONTENT ))
01813 return DBUS_GERROR_INVALID_FILE_CONTENT ;
01814 else if (!strcmp (derr, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ))
01815 return DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
01816 else
01817 return DBUS_GERROR_REMOTE_EXCEPTION;
01818 }
01819
01842 void
01843 dbus_set_g_error (GError **gerror,
01844 DBusError *error)
01845 {
01846 int code;
01847
01848 code = dbus_error_to_gerror_code (error->name);
01849 if (code != DBUS_GERROR_REMOTE_EXCEPTION)
01850 g_set_error (gerror, DBUS_GERROR,
01851 code,
01852 "%s",
01853 error->message);
01854 else
01855 g_set_error (gerror, DBUS_GERROR,
01856 code,
01857 "%s%c%s",
01858 error->message ? error->message : "",
01859 '\0',
01860 error->name);
01861 }
01862
01863 static void
01864 dbus_g_error_info_free (gpointer p)
01865 {
01866 DBusGErrorInfo *info;
01867
01868 info = p;
01869
01870 g_free (info->default_iface);
01871 g_free (info);
01872 }
01873
01898 void
01899 dbus_g_object_type_install_info (GType object_type,
01900 const DBusGObjectInfo *info)
01901 {
01902 g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
01903
01904 _dbus_g_value_types_init ();
01905
01906 g_type_set_qdata (object_type,
01907 dbus_g_object_type_dbus_metadata_quark (),
01908 (gpointer) info);
01909 }
01910
01921 void
01922 dbus_g_error_domain_register (GQuark domain,
01923 const char *default_iface,
01924 GType code_enum)
01925 {
01926 DBusGErrorInfo *info;
01927
01928 g_return_if_fail (g_quark_to_string (domain) != NULL);
01929 g_return_if_fail (code_enum != G_TYPE_INVALID);
01930 g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
01931
01932 g_static_rw_lock_writer_lock (&globals_lock);
01933
01934 if (error_metadata == NULL)
01935 g_datalist_init (&error_metadata);
01936
01937 info = g_datalist_id_get_data (&error_metadata, domain);
01938
01939 if (info != NULL)
01940 {
01941 g_warning ("Metadata for error domain \"%s\" already registered\n",
01942 g_quark_to_string (domain));
01943 }
01944 else
01945 {
01946 info = g_new0 (DBusGErrorInfo, 1);
01947 info->default_iface = g_strdup (default_iface);
01948 info->code_enum = code_enum;
01949
01950 g_datalist_id_set_data_full (&error_metadata,
01951 domain,
01952 info,
01953 dbus_g_error_info_free);
01954 }
01955
01956 g_static_rw_lock_writer_unlock (&globals_lock);
01957 }
01958
01959 static void
01960 unregister_gobject (DBusGConnection *connection, GObject *dead)
01961 {
01962 char *path;
01963 path = g_object_steal_data (dead, "dbus_glib_object_path");
01964 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection), path);
01965 g_free (path);
01966 }
01967
01982 void
01983 dbus_g_connection_register_g_object (DBusGConnection *connection,
01984 const char *at_path,
01985 GObject *object)
01986 {
01987 GList *info_list;
01988 g_return_if_fail (connection != NULL);
01989 g_return_if_fail (at_path != NULL);
01990 g_return_if_fail (G_IS_OBJECT (object));
01991
01992 info_list = lookup_object_info (object);
01993 if (info_list == NULL)
01994 {
01995 g_warning ("No introspection data registered for object class \"%s\"",
01996 g_type_name (G_TYPE_FROM_INSTANCE (object)));
01997 return;
01998 }
01999
02000 if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
02001 at_path,
02002 &gobject_dbus_vtable,
02003 object))
02004 {
02005 g_error ("Failed to register GObject with DBusConnection");
02006 return;
02007 }
02008
02009 export_signals (connection, info_list, object);
02010 g_list_free (info_list);
02011
02012 g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
02013 g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
02014 }
02015
02025 GObject *
02026 dbus_g_connection_lookup_g_object (DBusGConnection *connection,
02027 const char *at_path)
02028 {
02029 gpointer ret;
02030 if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &ret))
02031 return NULL;
02032 return ret;
02033 }
02034
02035 typedef struct {
02036 GType rettype;
02037 guint n_params;
02038 GType *params;
02039 } DBusGFuncSignature;
02040
02041 static guint
02042 funcsig_hash (gconstpointer key)
02043 {
02044 const DBusGFuncSignature *sig = key;
02045 GType *types;
02046 guint ret;
02047 guint i;
02048
02049 ret = sig->rettype;
02050 types = sig->params;
02051
02052 for (i = 0; i < sig->n_params; i++)
02053 {
02054 ret += (int) (*types);
02055 types++;
02056 }
02057
02058 return ret;
02059 }
02060
02061 static gboolean
02062 funcsig_equal (gconstpointer aval,
02063 gconstpointer bval)
02064 {
02065 const DBusGFuncSignature *a = aval;
02066 const DBusGFuncSignature *b = bval;
02067 const GType *atypes;
02068 const GType *btypes;
02069 guint i;
02070
02071 if (a->rettype != b->rettype
02072 || a->n_params != b->n_params)
02073 return FALSE;
02074
02075 atypes = a->params;
02076 btypes = b->params;
02077
02078 for (i = 0; i < a->n_params; i++)
02079 {
02080 if (*btypes != *atypes)
02081 return FALSE;
02082 atypes++;
02083 btypes++;
02084 }
02085
02086 return TRUE;
02087 }
02088
02089 static void
02090 funcsig_free (DBusGFuncSignature *sig)
02091 {
02092 g_free (sig->params);
02093 g_free (sig);
02094 }
02095
02096 GClosureMarshal
02097 _dbus_gobject_lookup_marshaller (GType rettype,
02098 guint n_params,
02099 const GType *param_types)
02100 {
02101 GClosureMarshal ret;
02102 DBusGFuncSignature sig;
02103 GType *params;
02104 guint i;
02105
02106
02107 rettype = G_TYPE_FUNDAMENTAL (rettype);
02108 params = g_new (GType, n_params);
02109 for (i = 0; i < n_params; i++)
02110 params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
02111
02112 sig.rettype = rettype;
02113 sig.n_params = n_params;
02114 sig.params = params;
02115
02116 g_static_rw_lock_reader_lock (&globals_lock);
02117
02118 if (marshal_table)
02119 ret = g_hash_table_lookup (marshal_table, &sig);
02120 else
02121 ret = NULL;
02122
02123 g_static_rw_lock_reader_unlock (&globals_lock);
02124
02125 if (ret == NULL)
02126 {
02127 if (rettype == G_TYPE_NONE)
02128 {
02129 if (n_params == 0)
02130 ret = g_cclosure_marshal_VOID__VOID;
02131 else if (n_params == 1)
02132 {
02133 switch (params[0])
02134 {
02135 case G_TYPE_BOOLEAN:
02136 ret = g_cclosure_marshal_VOID__BOOLEAN;
02137 break;
02138 case G_TYPE_UCHAR:
02139 ret = g_cclosure_marshal_VOID__UCHAR;
02140 break;
02141 case G_TYPE_INT:
02142 ret = g_cclosure_marshal_VOID__INT;
02143 break;
02144 case G_TYPE_UINT:
02145 ret = g_cclosure_marshal_VOID__UINT;
02146 break;
02147 case G_TYPE_DOUBLE:
02148 ret = g_cclosure_marshal_VOID__DOUBLE;
02149 break;
02150 case G_TYPE_STRING:
02151 ret = g_cclosure_marshal_VOID__STRING;
02152 break;
02153 case G_TYPE_BOXED:
02154 ret = g_cclosure_marshal_VOID__BOXED;
02155 break;
02156 }
02157 }
02158 else if (n_params == 3
02159 && params[0] == G_TYPE_STRING
02160 && params[1] == G_TYPE_STRING
02161 && params[2] == G_TYPE_STRING)
02162 {
02163 ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
02164 }
02165 }
02166 }
02167
02168 g_free (params);
02169 return ret;
02170 }
02171
02184 void
02185 dbus_g_object_register_marshaller (GClosureMarshal marshaller,
02186 GType rettype,
02187 ...)
02188 {
02189 va_list args;
02190 GArray *types;
02191 GType gtype;
02192
02193 va_start (args, rettype);
02194
02195 types = g_array_new (TRUE, TRUE, sizeof (GType));
02196
02197 while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
02198 g_array_append_val (types, gtype);
02199
02200 dbus_g_object_register_marshaller_array (marshaller, rettype,
02201 types->len, (GType*) types->data);
02202
02203 g_array_free (types, TRUE);
02204 va_end (args);
02205 }
02206
02217 void
02218 dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
02219 GType rettype,
02220 guint n_types,
02221 const GType* types)
02222 {
02223 DBusGFuncSignature *sig;
02224 guint i;
02225
02226 g_static_rw_lock_writer_lock (&globals_lock);
02227
02228 if (marshal_table == NULL)
02229 marshal_table = g_hash_table_new_full (funcsig_hash,
02230 funcsig_equal,
02231 (GDestroyNotify) funcsig_free,
02232 NULL);
02233 sig = g_new0 (DBusGFuncSignature, 1);
02234 sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
02235 sig->n_params = n_types;
02236 sig->params = g_new (GType, n_types);
02237 for (i = 0; i < n_types; i++)
02238 sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
02239
02240 g_hash_table_insert (marshal_table, sig, marshaller);
02241
02242 g_static_rw_lock_writer_unlock (&globals_lock);
02243 }
02244
02257 gchar *
02258 dbus_g_method_get_sender (DBusGMethodInvocation *context)
02259 {
02260 const gchar *sender;
02261
02262 sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
02263
02264 if (sender == NULL)
02265 return NULL;
02266
02267 return strdup (sender);
02268 }
02269
02280 DBusMessage *
02281 dbus_g_method_get_reply (DBusGMethodInvocation *context)
02282 {
02283 return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02284 }
02285
02295 void
02296 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
02297 {
02298 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02299 dbus_message_unref (reply);
02300
02301 dbus_g_connection_unref (context->connection);
02302 dbus_g_message_unref (context->message);
02303 g_free (context);
02304 }
02305
02306
02314 void
02315 dbus_g_method_return (DBusGMethodInvocation *context, ...)
02316 {
02317 DBusMessage *reply;
02318 DBusMessageIter iter;
02319 va_list args;
02320 char *out_sig;
02321 GArray *argsig;
02322 guint i;
02323
02324 reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02325 out_sig = method_output_signature_from_object_info (context->object, context->method);
02326 argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
02327
02328 dbus_message_iter_init_append (reply, &iter);
02329
02330 va_start (args, context);
02331 for (i = 0; i < argsig->len; i++)
02332 {
02333 GValue value = {0,};
02334 char *error;
02335 g_value_init (&value, g_array_index (argsig, GType, i));
02336 error = NULL;
02337 G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
02338 if (error)
02339 {
02340 g_warning(error);
02341 g_free (error);
02342 }
02343 _dbus_gvalue_marshal (&iter, &value);
02344 }
02345 va_end (args);
02346
02347 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02348 dbus_message_unref (reply);
02349
02350 dbus_g_connection_unref (context->connection);
02351 dbus_g_message_unref (context->message);
02352 g_free (context);
02353 g_free (out_sig);
02354 g_array_free (argsig, TRUE);
02355 }
02356
02365 void
02366 dbus_g_method_return_error (DBusGMethodInvocation *context, GError *error)
02367 {
02368 DBusMessage *reply;
02369 reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
02370 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02371 dbus_message_unref (reply);
02372
02373 dbus_g_connection_unref (context->connection);
02374 dbus_g_message_unref (context->message);
02375 g_free (context);
02376 }
02377
02378 const char * _dbus_gobject_get_path (GObject *obj)
02379 {
02380 return g_object_get_data (obj, "dbus_glib_object_path");
02381 }
02382
02383 #ifdef DBUS_BUILD_TESTS
02384 #include <stdlib.h>
02385
02386 static void
02387 _dummy_function (void)
02388 {
02389 }
02390
02391
02392
02393
02394 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
02395 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
02396 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
02397 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
02398 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
02399 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
02400 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
02401 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
02402 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
02403 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
02404 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
02405 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
02406 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
02407 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
02408 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
02409 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
02410 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
02411 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
02412 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
02413 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
02414 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
02415 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
02416 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
02417 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
02418 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
02419 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
02420 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
02421 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
02422 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
02423 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
02424 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
02425 };
02426
02427 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
02428 0,
02429 dbus_glib_internal_test_methods,
02430 30,
02431 "org.freedesktop.DBus.Tests.MyObject\0DoNothing\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Increment\0S\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetval\0S\0x\0I\0u\0arg1\0O\0F\0R\0u\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementRetvalError\0S\0x\0I\0u\0arg1\0O\0F\0E\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ThrowError\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Uppercase\0S\0arg0\0I\0s\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyArgs\0S\0x\0I\0u\0str\0I\0s\0trouble\0I\0d\0d_ret\0O\0F\0N\0d\0str_ret\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0ManyReturn\0S\0arg0\0O\0F\0N\0u\0arg1\0O\0F\0N\0s\0arg2\0O\0F\0N\0i\0arg3\0O\0F\0N\0u\0arg4\0O\0F\0N\0u\0arg5\0O\0C\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Stringify\0S\0val\0I\0v\0arg1\0O\0F\0N\0s\0\0org.freedesktop.DBus.Tests.MyObject\0Unstringify\0S\0val\0I\0s\0arg1\0O\0F\0N\0v\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive1\0S\0arg0\0I\0au\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0Recursive2\0S\0arg0\0I\0u\0arg1\0O\0F\0N\0au\0\0org.freedesktop.DBus.Tests.MyObject\0ManyUppercase\0S\0arg0\0I\0as\0arg1\0O\0F\0N\0as\0\0org.freedesktop.DBus.Tests.MyObject\0StrHashLen\0S\0arg0\0I\0a{ss}\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0SendCar\0S\0arg0\0I\0(suv)\0arg1\0O\0F\0N\0(uo)\0\0org.freedesktop.DBus.Tests.MyObject\0GetHash\0S\0arg0\0O\0F\0N\0a{ss}\0\0org.freedesktop.DBus.Tests.MyObject\0RecArrays\0S\0val\0I\0aas\0arg1\0O\0F\0N\0aau\0\0org.freedesktop.DBus.Tests.MyObject\0Objpath\0S\0arg0\0I\0o\0arg1\0O\0C\0N\0o\0\0org.freedesktop.DBus.Tests.MyObject\0GetObjs\0S\0arg0\0O\0F\0N\0ao\0\0org.freedesktop.DBus.Tests.MyObject\0IncrementVal\0S\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncIncrement\0A\0x\0I\0u\0arg1\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0AsyncThrowError\0A\0\0org.freedesktop.DBus.Tests.MyObject\0GetVal\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.MyObject\0ManyStringify\0S\0arg0\0I\0a{sv}\0arg1\0O\0F\0N\0a{sv}\0\0org.freedesktop.DBus.Tests.MyObject\0EmitFrobnicate\0S\0\0org.freedesktop.DBus.Tests.MyObject\0Terminate\0S\0\0org.freedesktop.DBus.Tests.FooObject\0GetValue\0S\0arg0\0O\0F\0N\0u\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignals\0S\0\0org.freedesktop.DBus.Tests.FooObject\0EmitSignal2\0S\0\0org.freedesktop.DBus.Tests.FooObject\0Terminate\0S\0\0\0",
02432 "org.freedesktop.DBus.Tests.MyObject\0Frobnicate\0org.freedesktop.DBus.Tests.FooObject\0Sig0\0org.freedesktop.DBus.Tests.FooObject\0Sig1\0org.freedesktop.DBus.Tests.FooObject\0Sig2\0\0",
02433 "\0"
02434 };
02435
02436
02442 gboolean
02443 _dbus_gobject_test (const char *test_data_dir)
02444 {
02445 int i;
02446 const char *arg;
02447 const char *arg_name;
02448 gboolean arg_in;
02449 gboolean constval;
02450 RetvalType retval;
02451 const char *arg_signature;
02452 const char *sigdata;
02453 const char *iface;
02454 const char *signame;
02455
02456 static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
02457 { "SetFoo", "set_foo" },
02458 { "Foo", "foo" },
02459 { "GetFooBar", "get_foo_bar" },
02460 { "Hello", "hello" }
02461
02462
02463
02464 };
02465
02466
02467
02468
02469
02470
02471 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02472 &(dbus_glib_internal_test_methods[0]));
02473 g_assert (*arg == '\0');
02474
02475
02476 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02477 &(dbus_glib_internal_test_methods[1]));
02478 g_assert (*arg != '\0');
02479 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02480 g_assert (!strcmp (arg_name, "x"));
02481 g_assert (arg_in == TRUE);
02482 g_assert (!strcmp (arg_signature, "u"));
02483 g_assert (*arg != '\0');
02484 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02485 g_assert (arg_in == FALSE);
02486 g_assert (retval == RETVAL_NONE);
02487 g_assert (!strcmp (arg_signature, "u"));
02488 g_assert (*arg == '\0');
02489
02490
02491 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02492 &(dbus_glib_internal_test_methods[2]));
02493 g_assert (*arg != '\0');
02494 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02495 g_assert (!strcmp (arg_name, "x"));
02496 g_assert (arg_in == TRUE);
02497 g_assert (!strcmp (arg_signature, "u"));
02498 g_assert (*arg != '\0');
02499 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02500 g_assert (retval == RETVAL_NOERROR);
02501 g_assert (arg_in == FALSE);
02502 g_assert (!strcmp (arg_signature, "u"));
02503 g_assert (*arg == '\0');
02504
02505
02506 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02507 &(dbus_glib_internal_test_methods[3]));
02508 g_assert (*arg != '\0');
02509 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02510 g_assert (!strcmp (arg_name, "x"));
02511 g_assert (arg_in == TRUE);
02512 g_assert (!strcmp (arg_signature, "u"));
02513 g_assert (*arg != '\0');
02514 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02515 g_assert (retval == RETVAL_ERROR);
02516 g_assert (arg_in == FALSE);
02517 g_assert (!strcmp (arg_signature, "u"));
02518 g_assert (*arg == '\0');
02519
02520
02521 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02522 &(dbus_glib_internal_test_methods[8]));
02523 g_assert (*arg != '\0');
02524 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02525 g_assert (!strcmp (arg_name, "val"));
02526 g_assert (arg_in == TRUE);
02527 g_assert (!strcmp (arg_signature, "v"));
02528 g_assert (*arg != '\0');
02529 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02530 g_assert (retval == RETVAL_NONE);
02531 g_assert (arg_in == FALSE);
02532 g_assert (!strcmp (arg_signature, "s"));
02533 g_assert (*arg == '\0');
02534
02535 sigdata = dbus_glib_internal_test_object_info.exported_signals;
02536 g_assert (*sigdata != '\0');
02537 sigdata = propsig_iterate (sigdata, &iface, &signame);
02538 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
02539 g_assert (!strcmp (signame, "Frobnicate"));
02540 g_assert (*sigdata != '\0');
02541 sigdata = propsig_iterate (sigdata, &iface, &signame);
02542 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02543 g_assert (!strcmp (signame, "Sig0"));
02544 g_assert (*sigdata != '\0');
02545 sigdata = propsig_iterate (sigdata, &iface, &signame);
02546 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02547 g_assert (!strcmp (signame, "Sig1"));
02548 g_assert (*sigdata != '\0');
02549 sigdata = propsig_iterate (sigdata, &iface, &signame);
02550 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02551 g_assert (!strcmp (signame, "Sig2"));
02552 g_assert (*sigdata == '\0');
02553
02554
02555 i = 0;
02556 while (i < (int) G_N_ELEMENTS (name_pairs))
02557 {
02558 char *uscore;
02559 char *wincaps;
02560
02561 uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
02562 wincaps = uscore_to_wincaps (name_pairs[i].uscore);
02563
02564 if (strcmp (uscore, name_pairs[i].uscore) != 0)
02565 {
02566 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02567 name_pairs[i].wincaps, name_pairs[i].uscore,
02568 uscore);
02569 exit (1);
02570 }
02571
02572 if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
02573 {
02574 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02575 name_pairs[i].uscore, name_pairs[i].wincaps,
02576 wincaps);
02577 exit (1);
02578 }
02579
02580 g_free (uscore);
02581 g_free (wincaps);
02582
02583 ++i;
02584 }
02585
02586 return TRUE;
02587 }
02588
02589 #endif