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 reply = dbus_message_new_error (message,
01023 dbus_g_error_get_name (error),
01024 error->message);
01025 else
01026 {
01027 char *error_name;
01028 error_name = gerror_domaincode_to_dbus_error_name (object_info,
01029 dbus_message_get_interface (message),
01030 error->domain, error->code);
01031 reply = dbus_message_new_error (message, error_name, error->message);
01032 g_free (error_name);
01033 }
01034 }
01035 return reply;
01036 }
01037
01051 struct _DBusGMethodInvocation {
01052 DBusGConnection *connection;
01053 DBusGMessage *message;
01054 const DBusGObjectInfo *object;
01055 const DBusGMethodInfo *method;
01056 };
01057
01058 static DBusHandlerResult
01059 invoke_object_method (GObject *object,
01060 const DBusGObjectInfo *object_info,
01061 const DBusGMethodInfo *method,
01062 DBusConnection *connection,
01063 DBusMessage *message)
01064 {
01065 gboolean had_error, call_only;
01066 GError *gerror;
01067 GValueArray *value_array;
01068 GValue return_value = {0,};
01069 GClosure closure;
01070 char *in_signature;
01071 GArray *out_param_values = NULL;
01072 GValueArray *out_param_gvalues = NULL;
01073 int out_param_count;
01074 int out_param_pos, out_param_gvalue_pos;
01075 DBusHandlerResult result;
01076 DBusMessage *reply;
01077 gboolean have_retval;
01078 gboolean retval_signals_error;
01079 gboolean retval_is_synthetic;
01080 gboolean retval_is_constant;
01081 const char *arg_metadata;
01082
01083 gerror = NULL;
01084
01085
01086
01087
01088 if (strcmp (string_table_lookup (get_method_data (object_info, method), 2), "A") == 0)
01089 call_only = TRUE;
01090 else
01091 call_only = FALSE;
01092
01093 have_retval = FALSE;
01094 retval_signals_error = FALSE;
01095 retval_is_synthetic = FALSE;
01096 retval_is_constant = FALSE;
01097
01098
01099
01100
01101
01102
01103 memset (&closure, 0, sizeof (closure));
01104
01105 in_signature = method_input_signature_from_object_info (object_info, method);
01106
01107
01108 {
01109 GArray *types_array;
01110 guint n_params;
01111 const GType *types;
01112 DBusGValueMarshalCtx context;
01113 GError *error = NULL;
01114
01115 context.recursion_depth = 0;
01116 context.gconnection = DBUS_G_CONNECTION_FROM_CONNECTION (connection);
01117 context.proxy = NULL;
01118
01119 types_array = _dbus_gtypes_from_arg_signature (in_signature, FALSE);
01120 n_params = types_array->len;
01121 types = (const GType*) types_array->data;
01122
01123 value_array = _dbus_gvalue_demarshal_message (&context, message, n_params, types, &error);
01124 if (value_array == NULL)
01125 {
01126 g_free (in_signature);
01127 g_array_free (types_array, TRUE);
01128 reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error->message);
01129 dbus_connection_send (connection, reply, NULL);
01130 dbus_message_unref (reply);
01131 g_error_free (error);
01132 return DBUS_HANDLER_RESULT_HANDLED;
01133 }
01134 g_array_free (types_array, TRUE);
01135 }
01136
01137
01138 g_value_array_prepend (value_array, NULL);
01139 g_value_init (g_value_array_get_nth (value_array, 0), G_TYPE_OBJECT);
01140 g_value_set_object (g_value_array_get_nth (value_array, 0), object);
01141
01142 if (call_only)
01143 {
01144 GValue context_value = {0,};
01145 DBusGMethodInvocation *context;
01146 context = g_new (DBusGMethodInvocation, 1);
01147 context->connection = dbus_g_connection_ref (DBUS_G_CONNECTION_FROM_CONNECTION (connection));
01148 context->message = dbus_g_message_ref (DBUS_G_MESSAGE_FROM_MESSAGE (message));
01149 context->object = object_info;
01150 context->method = method;
01151 g_value_init (&context_value, G_TYPE_POINTER);
01152 g_value_set_pointer (&context_value, context);
01153 g_value_array_append (value_array, &context_value);
01154 }
01155 else
01156 {
01157 RetvalType retval;
01158 gboolean arg_in;
01159 gboolean arg_const;
01160 const char *argsig;
01161
01162 arg_metadata = method_arg_info_from_object_info (object_info, method);
01163
01164
01165 out_param_count = 0;
01166 while (*arg_metadata)
01167 {
01168 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, &arg_const, &retval, &argsig);
01169 if (arg_in)
01170 continue;
01171 if (retval != RETVAL_NONE)
01172 {
01173 DBusSignatureIter tmp_sigiter;
01174
01175 g_assert (!have_retval);
01176 have_retval = TRUE;
01177 retval_is_synthetic = FALSE;
01178
01179 switch (retval)
01180 {
01181 case RETVAL_NONE:
01182 g_assert_not_reached ();
01183 break;
01184 case RETVAL_NOERROR:
01185 retval_signals_error = FALSE;
01186 break;
01187 case RETVAL_ERROR:
01188 retval_signals_error = TRUE;
01189 break;
01190 }
01191
01192 retval_is_constant = arg_const;
01193
01194
01195 dbus_signature_iter_init (&tmp_sigiter, argsig);
01196 g_value_init (&return_value, _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE));
01197 }
01198 else
01199 {
01200
01201 out_param_count++;
01202 }
01203 }
01204
01205
01206
01207
01208
01209
01210
01211 if (!have_retval)
01212 {
01213 have_retval = TRUE;
01214 retval_is_synthetic = TRUE;
01215 retval_signals_error = TRUE;
01216 g_value_init (&return_value, G_TYPE_BOOLEAN);
01217 }
01218
01219
01220
01221
01222
01223
01224 out_param_values = g_array_sized_new (FALSE, TRUE, sizeof (GTypeCValue), out_param_count);
01225
01226
01227
01228
01229 out_param_gvalues = g_value_array_new (out_param_count);
01230 out_param_pos = 0;
01231 out_param_gvalue_pos = 0;
01232
01233
01234 arg_metadata = method_arg_info_from_object_info (object_info, method);
01235
01236
01237
01238
01239 while (*arg_metadata)
01240 {
01241 GValue value = {0, };
01242 GTypeCValue storage;
01243 DBusSignatureIter tmp_sigiter;
01244 GType current_gtype;
01245
01246 arg_metadata = arg_iterate (arg_metadata, NULL, &arg_in, NULL, &retval, &argsig);
01247
01248 if (arg_in || retval != RETVAL_NONE)
01249 continue;
01250
01251 dbus_signature_iter_init (&tmp_sigiter, argsig);
01252 current_gtype = _dbus_gtype_from_signature_iter (&tmp_sigiter, FALSE);
01253
01254 g_value_init (&value, G_TYPE_POINTER);
01255
01256
01257 if (current_gtype != G_TYPE_VALUE)
01258 {
01259 memset (&storage, 0, sizeof (storage));
01260 g_array_append_val (out_param_values, storage);
01261 g_value_set_pointer (&value, &(g_array_index (out_param_values, GTypeCValue, out_param_pos)));
01262 out_param_pos++;
01263 }
01264 else
01265 {
01266 g_value_array_append (out_param_gvalues, NULL);
01267 g_value_set_pointer (&value, out_param_gvalues->values + out_param_gvalue_pos);
01268 out_param_gvalue_pos++;
01269 }
01270 g_value_array_append (value_array, &value);
01271 }
01272 }
01273
01274
01275 if (retval_signals_error)
01276 {
01277 g_assert (have_retval);
01278 g_value_array_append (value_array, NULL);
01279 g_value_init (g_value_array_get_nth (value_array, value_array->n_values - 1), G_TYPE_POINTER);
01280 g_value_set_pointer (g_value_array_get_nth (value_array, value_array->n_values - 1), &gerror);
01281 }
01282
01283
01284 method->marshaller (&closure, have_retval ? &return_value : NULL,
01285 value_array->n_values,
01286 value_array->values,
01287 NULL, method->function);
01288 if (call_only)
01289 {
01290 result = DBUS_HANDLER_RESULT_HANDLED;
01291 goto done;
01292 }
01293 if (retval_signals_error)
01294 had_error = _dbus_gvalue_signals_error (&return_value);
01295 else
01296 had_error = FALSE;
01297
01298 if (!had_error)
01299 {
01300 DBusMessageIter iter;
01301
01302 reply = dbus_message_new_method_return (message);
01303 if (reply == NULL)
01304 goto nomem;
01305
01306
01307 dbus_message_iter_init_append (reply, &iter);
01308
01309
01310 if (have_retval && !retval_is_synthetic)
01311 {
01312 if (!_dbus_gvalue_marshal (&iter, &return_value))
01313 goto nomem;
01314 if (!retval_is_constant)
01315 g_value_unset (&return_value);
01316 }
01317
01318
01319 arg_metadata = method_arg_info_from_object_info (object_info, method);
01320
01321
01322 out_param_pos = 0;
01323 out_param_gvalue_pos = 0;
01324 while (*arg_metadata)
01325 {
01326 GValue gvalue = {0, };
01327 const char *arg_name;
01328 gboolean arg_in;
01329 gboolean constval;
01330 RetvalType retval;
01331 const char *arg_signature;
01332 DBusSignatureIter argsigiter;
01333
01334 do
01335 {
01336
01337
01338 arg_metadata = arg_iterate (arg_metadata, &arg_name, &arg_in, &constval, &retval, &arg_signature);
01339 }
01340 while ((arg_in || retval != RETVAL_NONE) && *arg_metadata);
01341
01342
01343
01344
01345 if (arg_in || retval != RETVAL_NONE)
01346 break;
01347
01348 dbus_signature_iter_init (&argsigiter, arg_signature);
01349
01350 g_value_init (&gvalue, _dbus_gtype_from_signature_iter (&argsigiter, FALSE));
01351 if (G_VALUE_TYPE (&gvalue) != G_TYPE_VALUE)
01352 {
01353 if (!_dbus_gvalue_take (&gvalue,
01354 &(g_array_index (out_param_values, GTypeCValue, out_param_pos))))
01355 g_assert_not_reached ();
01356 out_param_pos++;
01357 }
01358 else
01359 {
01360 g_value_set_static_boxed (&gvalue, out_param_gvalues->values + out_param_gvalue_pos);
01361 out_param_gvalue_pos++;
01362 }
01363
01364 if (!_dbus_gvalue_marshal (&iter, &gvalue))
01365 goto nomem;
01366
01367
01368
01369
01370 if (!constval)
01371 g_value_unset (&gvalue);
01372 }
01373 }
01374 else
01375 reply = gerror_to_dbus_error_message (object_info, message, gerror);
01376
01377 if (reply)
01378 {
01379 dbus_connection_send (connection, reply, NULL);
01380 dbus_message_unref (reply);
01381 }
01382
01383 result = DBUS_HANDLER_RESULT_HANDLED;
01384 done:
01385 g_free (in_signature);
01386 if (!call_only)
01387 {
01388 g_array_free (out_param_values, TRUE);
01389 g_value_array_free (out_param_gvalues);
01390 }
01391 g_value_array_free (value_array);
01392 return result;
01393 nomem:
01394 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
01395 goto done;
01396 }
01397
01398 static DBusHandlerResult
01399 gobject_message_function (DBusConnection *connection,
01400 DBusMessage *message,
01401 void *user_data)
01402 {
01403 GParamSpec *pspec;
01404 GObject *object;
01405 gboolean setter;
01406 gboolean getter;
01407 gboolean getall;
01408 char *s;
01409 const char *wincaps_propname;
01410
01411 DBusMessageIter iter;
01412 const DBusGMethodInfo *method;
01413 const DBusGObjectInfo *object_info;
01414 DBusMessage *ret;
01415
01416 object = G_OBJECT (user_data);
01417
01418 if (dbus_message_is_method_call (message,
01419 DBUS_INTERFACE_INTROSPECTABLE,
01420 "Introspect"))
01421 return handle_introspect (connection, message, object);
01422
01423
01424 object_info = NULL;
01425 if (lookup_object_and_method (object, message, &object_info, &method))
01426 return invoke_object_method (object, object_info, method, connection, message);
01427
01428
01429
01430
01431 getter = FALSE;
01432 setter = FALSE;
01433 getall = FALSE;
01434 if (dbus_message_is_method_call (message,
01435 DBUS_INTERFACE_PROPERTIES,
01436 "Get"))
01437 getter = TRUE;
01438 else if (dbus_message_is_method_call (message,
01439 DBUS_INTERFACE_PROPERTIES,
01440 "Set"))
01441 setter = TRUE;
01442 else if (dbus_message_is_method_call (message,
01443 DBUS_INTERFACE_PROPERTIES,
01444 "GetAll"))
01445 getall = TRUE;
01446
01447 if (!(setter || getter || getall))
01448 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01449
01450 ret = NULL;
01451
01452 dbus_message_iter_init (message, &iter);
01453
01454 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01455 {
01456 g_warning ("Property get or set does not have an interface string as first arg\n");
01457 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01458 }
01459
01460
01461
01462
01463 dbus_message_iter_next (&iter);
01464
01465 if (getall)
01466 {
01467 if (object_info != NULL)
01468 ret = get_all_object_properties (connection, message, object_info, object);
01469 else
01470 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01471 }
01472 else if (getter || setter)
01473 {
01474 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01475 {
01476 g_warning ("Property get or set does not have a property name string as second arg\n");
01477 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01478 }
01479 dbus_message_iter_get_basic (&iter, &wincaps_propname);
01480 dbus_message_iter_next (&iter);
01481
01482 s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
01483
01484 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
01485 s);
01486
01487 g_free (s);
01488
01489 if (pspec != NULL)
01490 {
01491 if (setter)
01492 {
01493 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
01494 {
01495 g_warning ("Property set does not have a variant value as third arg\n");
01496 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01497 }
01498
01499 ret = set_object_property (connection, message, &iter,
01500 object, pspec);
01501 dbus_message_iter_next (&iter);
01502 }
01503 else if (getter)
01504 {
01505 ret = get_object_property (connection, message,
01506 object, pspec);
01507 }
01508 else
01509 {
01510 g_assert_not_reached ();
01511 ret = NULL;
01512 }
01513 }
01514 else
01515 {
01516 ret = dbus_message_new_error_printf (message,
01517 DBUS_ERROR_INVALID_ARGS,
01518 "No such property %s", wincaps_propname);
01519 }
01520 }
01521
01522 g_assert (ret != NULL);
01523
01524 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
01525 g_warning ("Property get, set or set all had too many arguments\n");
01526
01527 dbus_connection_send (connection, ret, NULL);
01528 dbus_message_unref (ret);
01529 return DBUS_HANDLER_RESULT_HANDLED;
01530 }
01531
01532 static const DBusObjectPathVTable gobject_dbus_vtable = {
01533 gobject_unregister_function,
01534 gobject_message_function,
01535 NULL
01536 };
01537
01538 typedef struct {
01539 GClosure closure;
01540 DBusGConnection *connection;
01541 GObject *object;
01542 const char *signame;
01543 const char *sigiface;
01544 } DBusGSignalClosure;
01545
01546 static GClosure *
01547 dbus_g_signal_closure_new (DBusGConnection *connection,
01548 GObject *object,
01549 const char *signame,
01550 const char *sigiface)
01551 {
01552 DBusGSignalClosure *closure;
01553
01554 closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
01555
01556 closure->connection = dbus_g_connection_ref (connection);
01557 closure->object = object;
01558 closure->signame = signame;
01559 closure->sigiface = sigiface;
01560 return (GClosure*) closure;
01561 }
01562
01563 static void
01564 dbus_g_signal_closure_finalize (gpointer data,
01565 GClosure *closure)
01566 {
01567 DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
01568
01569 dbus_g_connection_unref (sigclosure->connection);
01570 }
01571
01572 static void
01573 signal_emitter_marshaller (GClosure *closure,
01574 GValue *retval,
01575 guint n_param_values,
01576 const GValue *param_values,
01577 gpointer invocation_hint,
01578 gpointer marshal_data)
01579 {
01580 DBusGSignalClosure *sigclosure;
01581 DBusMessage *signal;
01582 DBusMessageIter iter;
01583 guint i;
01584 const char *path;
01585
01586 sigclosure = (DBusGSignalClosure *) closure;
01587
01588 g_assert (retval == NULL);
01589
01590 path = _dbus_gobject_get_path (sigclosure->object);
01591
01592 g_assert (path != NULL);
01593
01594 signal = dbus_message_new_signal (path,
01595 sigclosure->sigiface,
01596 sigclosure->signame);
01597 if (!signal)
01598 {
01599 g_error ("out of memory");
01600 return;
01601 }
01602
01603 dbus_message_iter_init_append (signal, &iter);
01604
01605
01606 for (i = 1; i < n_param_values; i++)
01607 {
01608 if (!_dbus_gvalue_marshal (&iter,
01609 (GValue *) (&(param_values[i]))))
01610 {
01611 g_warning ("failed to marshal parameter %d for signal %s",
01612 i, sigclosure->signame);
01613 goto out;
01614 }
01615 }
01616 dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
01617 signal, NULL);
01618 out:
01619 dbus_message_unref (signal);
01620 }
01621
01622 static void
01623 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
01624 {
01625 GType gtype;
01626 const char *sigdata;
01627 const char *iface;
01628 const char *signame;
01629 const DBusGObjectInfo *info;
01630
01631 gtype = G_TYPE_FROM_INSTANCE (object);
01632
01633 for (; info_list != NULL; info_list = g_list_next (info_list))
01634 {
01635 info = (DBusGObjectInfo *) info_list->data;
01636
01637 sigdata = info->exported_signals;
01638
01639 while (*sigdata != '\0')
01640 {
01641 guint id;
01642 GSignalQuery query;
01643 GClosure *closure;
01644 char *s;
01645
01646 sigdata = propsig_iterate (sigdata, &iface, &signame);
01647
01648 s = _dbus_gutils_wincaps_to_uscore (signame);
01649
01650 id = g_signal_lookup (s, gtype);
01651 if (id == 0)
01652 {
01653 g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
01654 s, signame, g_type_name (gtype));
01655 g_free (s);
01656 continue;
01657 }
01658
01659 g_signal_query (id, &query);
01660
01661 if (query.return_type != G_TYPE_NONE)
01662 {
01663 g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
01664 s, g_type_name (gtype), g_type_name (query.return_type));
01665 g_free (s);
01666 continue;
01667 }
01668
01669 closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
01670 g_closure_set_marshal (closure, signal_emitter_marshaller);
01671
01672 g_signal_connect_closure_by_id (object,
01673 id,
01674 0,
01675 closure,
01676 FALSE);
01677
01678 g_closure_add_finalize_notifier (closure, NULL,
01679 dbus_g_signal_closure_finalize);
01680 g_free (s);
01681 }
01682 }
01683 }
01684
01685 static gint
01686 dbus_error_to_gerror_code (const char *derr)
01687 {
01688 if (0) ;
01689 else if (!strcmp (derr, DBUS_ERROR_FAILED ))
01690 return DBUS_GERROR_FAILED ;
01691 else if (!strcmp (derr, DBUS_ERROR_NO_MEMORY ))
01692 return DBUS_GERROR_NO_MEMORY ;
01693 else if (!strcmp (derr, DBUS_ERROR_SERVICE_UNKNOWN ))
01694 return DBUS_GERROR_SERVICE_UNKNOWN ;
01695 else if (!strcmp (derr, DBUS_ERROR_NAME_HAS_NO_OWNER ))
01696 return DBUS_GERROR_NAME_HAS_NO_OWNER ;
01697 else if (!strcmp (derr, DBUS_ERROR_NO_REPLY ))
01698 return DBUS_GERROR_NO_REPLY ;
01699 else if (!strcmp (derr, DBUS_ERROR_IO_ERROR ))
01700 return DBUS_GERROR_IO_ERROR ;
01701 else if (!strcmp (derr, DBUS_ERROR_BAD_ADDRESS ))
01702 return DBUS_GERROR_BAD_ADDRESS ;
01703 else if (!strcmp (derr, DBUS_ERROR_NOT_SUPPORTED ))
01704 return DBUS_GERROR_NOT_SUPPORTED ;
01705 else if (!strcmp (derr, DBUS_ERROR_LIMITS_EXCEEDED ))
01706 return DBUS_GERROR_LIMITS_EXCEEDED ;
01707 else if (!strcmp (derr, DBUS_ERROR_ACCESS_DENIED ))
01708 return DBUS_GERROR_ACCESS_DENIED ;
01709 else if (!strcmp (derr, DBUS_ERROR_AUTH_FAILED ))
01710 return DBUS_GERROR_AUTH_FAILED ;
01711 else if (!strcmp (derr, DBUS_ERROR_NO_SERVER ))
01712 return DBUS_GERROR_NO_SERVER ;
01713 else if (!strcmp (derr, DBUS_ERROR_TIMEOUT ))
01714 return DBUS_GERROR_TIMEOUT ;
01715 else if (!strcmp (derr, DBUS_ERROR_NO_NETWORK ))
01716 return DBUS_GERROR_NO_NETWORK ;
01717 else if (!strcmp (derr, DBUS_ERROR_ADDRESS_IN_USE ))
01718 return DBUS_GERROR_ADDRESS_IN_USE ;
01719 else if (!strcmp (derr, DBUS_ERROR_DISCONNECTED ))
01720 return DBUS_GERROR_DISCONNECTED ;
01721 else if (!strcmp (derr, DBUS_ERROR_INVALID_ARGS ))
01722 return DBUS_GERROR_INVALID_ARGS ;
01723 else if (!strcmp (derr, DBUS_ERROR_FILE_NOT_FOUND ))
01724 return DBUS_GERROR_FILE_NOT_FOUND ;
01725 else if (!strcmp (derr, DBUS_ERROR_FILE_EXISTS ))
01726 return DBUS_GERROR_FILE_EXISTS ;
01727 else if (!strcmp (derr, DBUS_ERROR_UNKNOWN_METHOD ))
01728 return DBUS_GERROR_UNKNOWN_METHOD ;
01729 else if (!strcmp (derr, DBUS_ERROR_TIMED_OUT ))
01730 return DBUS_GERROR_TIMED_OUT ;
01731 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_NOT_FOUND ))
01732 return DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
01733 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_INVALID ))
01734 return DBUS_GERROR_MATCH_RULE_INVALID ;
01735 else if (!strcmp (derr, DBUS_ERROR_SPAWN_EXEC_FAILED ))
01736 return DBUS_GERROR_SPAWN_EXEC_FAILED ;
01737 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FORK_FAILED ))
01738 return DBUS_GERROR_SPAWN_FORK_FAILED ;
01739 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_EXITED ))
01740 return DBUS_GERROR_SPAWN_CHILD_EXITED ;
01741 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_SIGNALED ))
01742 return DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
01743 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FAILED ))
01744 return DBUS_GERROR_SPAWN_FAILED ;
01745 else if (!strcmp (derr, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN ))
01746 return DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
01747 else if (!strcmp (derr, DBUS_ERROR_INVALID_SIGNATURE ))
01748 return DBUS_GERROR_INVALID_SIGNATURE ;
01749 else if (!strcmp (derr, DBUS_ERROR_INVALID_FILE_CONTENT ))
01750 return DBUS_GERROR_INVALID_FILE_CONTENT ;
01751 else if (!strcmp (derr, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ))
01752 return DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
01753 else
01754 return DBUS_GERROR_REMOTE_EXCEPTION;
01755 }
01756
01779 void
01780 dbus_set_g_error (GError **gerror,
01781 DBusError *error)
01782 {
01783 int code;
01784
01785 code = dbus_error_to_gerror_code (error->name);
01786 if (code != DBUS_GERROR_REMOTE_EXCEPTION)
01787 g_set_error (gerror, DBUS_GERROR,
01788 code,
01789 "%s",
01790 error->message);
01791 else
01792 g_set_error (gerror, DBUS_GERROR,
01793 code,
01794 "%s%c%s",
01795 error->message ? error->message : "",
01796 '\0',
01797 error->name);
01798 }
01799
01800 static void
01801 dbus_g_error_info_free (gpointer p)
01802 {
01803 DBusGErrorInfo *info;
01804
01805 info = p;
01806
01807 g_free (info->default_iface);
01808 g_free (info);
01809 }
01810
01835 void
01836 dbus_g_object_type_install_info (GType object_type,
01837 const DBusGObjectInfo *info)
01838 {
01839 g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
01840
01841 _dbus_g_value_types_init ();
01842
01843 g_type_set_qdata (object_type,
01844 dbus_g_object_type_dbus_metadata_quark (),
01845 (gpointer) info);
01846 }
01847
01858 void
01859 dbus_g_error_domain_register (GQuark domain,
01860 const char *default_iface,
01861 GType code_enum)
01862 {
01863 DBusGErrorInfo *info;
01864
01865 g_return_if_fail (g_quark_to_string (domain) != NULL);
01866 g_return_if_fail (code_enum != G_TYPE_INVALID);
01867 g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
01868
01869 g_static_rw_lock_writer_lock (&globals_lock);
01870
01871 if (error_metadata == NULL)
01872 g_datalist_init (&error_metadata);
01873
01874 info = g_datalist_id_get_data (&error_metadata, domain);
01875
01876 if (info != NULL)
01877 {
01878 g_warning ("Metadata for error domain \"%s\" already registered\n",
01879 g_quark_to_string (domain));
01880 }
01881 else
01882 {
01883 info = g_new0 (DBusGErrorInfo, 1);
01884 info->default_iface = g_strdup (default_iface);
01885 info->code_enum = code_enum;
01886
01887 g_datalist_id_set_data_full (&error_metadata,
01888 domain,
01889 info,
01890 dbus_g_error_info_free);
01891 }
01892
01893 g_static_rw_lock_writer_unlock (&globals_lock);
01894 }
01895
01896 static void
01897 unregister_gobject (DBusGConnection *connection, GObject *dead)
01898 {
01899 char *path;
01900 path = g_object_steal_data (dead, "dbus_glib_object_path");
01901 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection), path);
01902 g_free (path);
01903 }
01904
01919 void
01920 dbus_g_connection_register_g_object (DBusGConnection *connection,
01921 const char *at_path,
01922 GObject *object)
01923 {
01924 GList *info_list;
01925 g_return_if_fail (connection != NULL);
01926 g_return_if_fail (at_path != NULL);
01927 g_return_if_fail (G_IS_OBJECT (object));
01928
01929 info_list = lookup_object_info (object);
01930 if (info_list == NULL)
01931 {
01932 g_warning ("No introspection data registered for object class \"%s\"",
01933 g_type_name (G_TYPE_FROM_INSTANCE (object)));
01934 return;
01935 }
01936
01937 if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
01938 at_path,
01939 &gobject_dbus_vtable,
01940 object))
01941 {
01942 g_error ("Failed to register GObject with DBusConnection");
01943 return;
01944 }
01945
01946 export_signals (connection, info_list, object);
01947 g_list_free (info_list);
01948
01949 g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
01950 g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
01951 }
01952
01962 GObject *
01963 dbus_g_connection_lookup_g_object (DBusGConnection *connection,
01964 const char *at_path)
01965 {
01966 gpointer ret;
01967 if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &ret))
01968 return NULL;
01969 return ret;
01970 }
01971
01972 typedef struct {
01973 GType rettype;
01974 guint n_params;
01975 GType *params;
01976 } DBusGFuncSignature;
01977
01978 static guint
01979 funcsig_hash (gconstpointer key)
01980 {
01981 const DBusGFuncSignature *sig = key;
01982 GType *types;
01983 guint ret;
01984 guint i;
01985
01986 ret = sig->rettype;
01987 types = sig->params;
01988
01989 for (i = 0; i < sig->n_params; i++)
01990 {
01991 ret += (int) (*types);
01992 types++;
01993 }
01994
01995 return ret;
01996 }
01997
01998 static gboolean
01999 funcsig_equal (gconstpointer aval,
02000 gconstpointer bval)
02001 {
02002 const DBusGFuncSignature *a = aval;
02003 const DBusGFuncSignature *b = bval;
02004 const GType *atypes;
02005 const GType *btypes;
02006 guint i;
02007
02008 if (a->rettype != b->rettype
02009 || a->n_params != b->n_params)
02010 return FALSE;
02011
02012 atypes = a->params;
02013 btypes = b->params;
02014
02015 for (i = 0; i < a->n_params; i++)
02016 {
02017 if (*btypes != *atypes)
02018 return FALSE;
02019 atypes++;
02020 btypes++;
02021 }
02022
02023 return TRUE;
02024 }
02025
02026 static void
02027 funcsig_free (DBusGFuncSignature *sig)
02028 {
02029 g_free (sig->params);
02030 g_free (sig);
02031 }
02032
02033 GClosureMarshal
02034 _dbus_gobject_lookup_marshaller (GType rettype,
02035 guint n_params,
02036 const GType *param_types)
02037 {
02038 GClosureMarshal ret;
02039 DBusGFuncSignature sig;
02040 GType *params;
02041 guint i;
02042
02043
02044 rettype = G_TYPE_FUNDAMENTAL (rettype);
02045 params = g_new (GType, n_params);
02046 for (i = 0; i < n_params; i++)
02047 params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
02048
02049 sig.rettype = rettype;
02050 sig.n_params = n_params;
02051 sig.params = params;
02052
02053 g_static_rw_lock_reader_lock (&globals_lock);
02054
02055 if (marshal_table)
02056 ret = g_hash_table_lookup (marshal_table, &sig);
02057 else
02058 ret = NULL;
02059
02060 g_static_rw_lock_reader_unlock (&globals_lock);
02061
02062 if (ret == NULL)
02063 {
02064 if (rettype == G_TYPE_NONE)
02065 {
02066 if (n_params == 0)
02067 ret = g_cclosure_marshal_VOID__VOID;
02068 else if (n_params == 1)
02069 {
02070 switch (params[0])
02071 {
02072 case G_TYPE_BOOLEAN:
02073 ret = g_cclosure_marshal_VOID__BOOLEAN;
02074 break;
02075 case G_TYPE_UCHAR:
02076 ret = g_cclosure_marshal_VOID__UCHAR;
02077 break;
02078 case G_TYPE_INT:
02079 ret = g_cclosure_marshal_VOID__INT;
02080 break;
02081 case G_TYPE_UINT:
02082 ret = g_cclosure_marshal_VOID__UINT;
02083 break;
02084 case G_TYPE_DOUBLE:
02085 ret = g_cclosure_marshal_VOID__DOUBLE;
02086 break;
02087 case G_TYPE_STRING:
02088 ret = g_cclosure_marshal_VOID__STRING;
02089 break;
02090 case G_TYPE_BOXED:
02091 ret = g_cclosure_marshal_VOID__BOXED;
02092 break;
02093 }
02094 }
02095 else if (n_params == 3
02096 && params[0] == G_TYPE_STRING
02097 && params[1] == G_TYPE_STRING
02098 && params[2] == G_TYPE_STRING)
02099 {
02100 ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
02101 }
02102 }
02103 }
02104
02105 g_free (params);
02106 return ret;
02107 }
02108
02121 void
02122 dbus_g_object_register_marshaller (GClosureMarshal marshaller,
02123 GType rettype,
02124 ...)
02125 {
02126 va_list args;
02127 GArray *types;
02128 GType gtype;
02129
02130 va_start (args, rettype);
02131
02132 types = g_array_new (TRUE, TRUE, sizeof (GType));
02133
02134 while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
02135 g_array_append_val (types, gtype);
02136
02137 dbus_g_object_register_marshaller_array (marshaller, rettype,
02138 types->len, (GType*) types->data);
02139
02140 g_array_free (types, TRUE);
02141 va_end (args);
02142 }
02143
02154 void
02155 dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
02156 GType rettype,
02157 guint n_types,
02158 const GType* types)
02159 {
02160 DBusGFuncSignature *sig;
02161 guint i;
02162
02163 g_static_rw_lock_writer_lock (&globals_lock);
02164
02165 if (marshal_table == NULL)
02166 marshal_table = g_hash_table_new_full (funcsig_hash,
02167 funcsig_equal,
02168 (GDestroyNotify) funcsig_free,
02169 NULL);
02170 sig = g_new0 (DBusGFuncSignature, 1);
02171 sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
02172 sig->n_params = n_types;
02173 sig->params = g_new (GType, n_types);
02174 for (i = 0; i < n_types; i++)
02175 sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
02176
02177 g_hash_table_insert (marshal_table, sig, marshaller);
02178
02179 g_static_rw_lock_writer_unlock (&globals_lock);
02180 }
02181
02194 gchar *
02195 dbus_g_method_get_sender (DBusGMethodInvocation *context)
02196 {
02197 const gchar *sender;
02198
02199 sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
02200
02201 if (sender == NULL)
02202 return NULL;
02203
02204 return strdup (sender);
02205 }
02206
02217 DBusMessage *
02218 dbus_g_method_get_reply (DBusGMethodInvocation *context)
02219 {
02220 return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02221 }
02222
02232 void
02233 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
02234 {
02235 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02236 dbus_message_unref (reply);
02237
02238 dbus_g_connection_unref (context->connection);
02239 dbus_g_message_unref (context->message);
02240 g_free (context);
02241 }
02242
02243
02251 void
02252 dbus_g_method_return (DBusGMethodInvocation *context, ...)
02253 {
02254 DBusMessage *reply;
02255 DBusMessageIter iter;
02256 va_list args;
02257 char *out_sig;
02258 GArray *argsig;
02259 guint i;
02260
02261 reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02262 out_sig = method_output_signature_from_object_info (context->object, context->method);
02263 argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
02264
02265 dbus_message_iter_init_append (reply, &iter);
02266
02267 va_start (args, context);
02268 for (i = 0; i < argsig->len; i++)
02269 {
02270 GValue value = {0,};
02271 char *error;
02272 g_value_init (&value, g_array_index (argsig, GType, i));
02273 error = NULL;
02274 G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
02275 if (error)
02276 {
02277 g_warning(error);
02278 g_free (error);
02279 }
02280 _dbus_gvalue_marshal (&iter, &value);
02281 }
02282 va_end (args);
02283
02284 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02285 dbus_message_unref (reply);
02286
02287 dbus_g_connection_unref (context->connection);
02288 dbus_g_message_unref (context->message);
02289 g_free (context);
02290 g_free (out_sig);
02291 g_array_free (argsig, TRUE);
02292 }
02293
02302 void
02303 dbus_g_method_return_error (DBusGMethodInvocation *context, GError *error)
02304 {
02305 DBusMessage *reply;
02306 reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
02307 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02308 dbus_message_unref (reply);
02309
02310 dbus_g_connection_unref (context->connection);
02311 dbus_g_message_unref (context->message);
02312 g_free (context);
02313 }
02314
02315 const char * _dbus_gobject_get_path (GObject *obj)
02316 {
02317 return g_object_get_data (obj, "dbus_glib_object_path");
02318 }
02319
02320 #ifdef DBUS_BUILD_TESTS
02321 #include <stdlib.h>
02322
02323 static void
02324 _dummy_function (void)
02325 {
02326 }
02327
02328
02329
02330
02331 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
02332 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
02333 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
02334 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
02335 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
02336 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
02337 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
02338 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
02339 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
02340 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
02341 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
02342 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
02343 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
02344 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
02345 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
02346 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
02347 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
02348 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
02349 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
02350 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
02351 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
02352 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
02353 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
02354 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
02355 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
02356 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
02357 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
02358 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
02359 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
02360 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
02361 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
02362 };
02363
02364 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
02365 0,
02366 dbus_glib_internal_test_methods,
02367 30,
02368 "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",
02369 "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",
02370 "\0"
02371 };
02372
02373
02379 gboolean
02380 _dbus_gobject_test (const char *test_data_dir)
02381 {
02382 int i;
02383 const char *arg;
02384 const char *arg_name;
02385 gboolean arg_in;
02386 gboolean constval;
02387 RetvalType retval;
02388 const char *arg_signature;
02389 const char *sigdata;
02390 const char *iface;
02391 const char *signame;
02392
02393 static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
02394 { "SetFoo", "set_foo" },
02395 { "Foo", "foo" },
02396 { "GetFooBar", "get_foo_bar" },
02397 { "Hello", "hello" }
02398
02399
02400
02401 };
02402
02403
02404
02405
02406
02407
02408 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02409 &(dbus_glib_internal_test_methods[0]));
02410 g_assert (*arg == '\0');
02411
02412
02413 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02414 &(dbus_glib_internal_test_methods[1]));
02415 g_assert (*arg != '\0');
02416 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02417 g_assert (!strcmp (arg_name, "x"));
02418 g_assert (arg_in == TRUE);
02419 g_assert (!strcmp (arg_signature, "u"));
02420 g_assert (*arg != '\0');
02421 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02422 g_assert (arg_in == FALSE);
02423 g_assert (retval == RETVAL_NONE);
02424 g_assert (!strcmp (arg_signature, "u"));
02425 g_assert (*arg == '\0');
02426
02427
02428 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02429 &(dbus_glib_internal_test_methods[2]));
02430 g_assert (*arg != '\0');
02431 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02432 g_assert (!strcmp (arg_name, "x"));
02433 g_assert (arg_in == TRUE);
02434 g_assert (!strcmp (arg_signature, "u"));
02435 g_assert (*arg != '\0');
02436 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02437 g_assert (retval == RETVAL_NOERROR);
02438 g_assert (arg_in == FALSE);
02439 g_assert (!strcmp (arg_signature, "u"));
02440 g_assert (*arg == '\0');
02441
02442
02443 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02444 &(dbus_glib_internal_test_methods[3]));
02445 g_assert (*arg != '\0');
02446 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02447 g_assert (!strcmp (arg_name, "x"));
02448 g_assert (arg_in == TRUE);
02449 g_assert (!strcmp (arg_signature, "u"));
02450 g_assert (*arg != '\0');
02451 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02452 g_assert (retval == RETVAL_ERROR);
02453 g_assert (arg_in == FALSE);
02454 g_assert (!strcmp (arg_signature, "u"));
02455 g_assert (*arg == '\0');
02456
02457
02458 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02459 &(dbus_glib_internal_test_methods[8]));
02460 g_assert (*arg != '\0');
02461 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02462 g_assert (!strcmp (arg_name, "val"));
02463 g_assert (arg_in == TRUE);
02464 g_assert (!strcmp (arg_signature, "v"));
02465 g_assert (*arg != '\0');
02466 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02467 g_assert (retval == RETVAL_NONE);
02468 g_assert (arg_in == FALSE);
02469 g_assert (!strcmp (arg_signature, "s"));
02470 g_assert (*arg == '\0');
02471
02472 sigdata = dbus_glib_internal_test_object_info.exported_signals;
02473 g_assert (*sigdata != '\0');
02474 sigdata = propsig_iterate (sigdata, &iface, &signame);
02475 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
02476 g_assert (!strcmp (signame, "Frobnicate"));
02477 g_assert (*sigdata != '\0');
02478 sigdata = propsig_iterate (sigdata, &iface, &signame);
02479 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02480 g_assert (!strcmp (signame, "Sig0"));
02481 g_assert (*sigdata != '\0');
02482 sigdata = propsig_iterate (sigdata, &iface, &signame);
02483 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02484 g_assert (!strcmp (signame, "Sig1"));
02485 g_assert (*sigdata != '\0');
02486 sigdata = propsig_iterate (sigdata, &iface, &signame);
02487 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02488 g_assert (!strcmp (signame, "Sig2"));
02489 g_assert (*sigdata == '\0');
02490
02491
02492 i = 0;
02493 while (i < (int) G_N_ELEMENTS (name_pairs))
02494 {
02495 char *uscore;
02496 char *wincaps;
02497
02498 uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
02499 wincaps = uscore_to_wincaps (name_pairs[i].uscore);
02500
02501 if (strcmp (uscore, name_pairs[i].uscore) != 0)
02502 {
02503 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02504 name_pairs[i].wincaps, name_pairs[i].uscore,
02505 uscore);
02506 exit (1);
02507 }
02508
02509 if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
02510 {
02511 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02512 name_pairs[i].uscore, name_pairs[i].wincaps,
02513 wincaps);
02514 exit (1);
02515 }
02516
02517 g_free (uscore);
02518 g_free (wincaps);
02519
02520 ++i;
02521 }
02522
02523 return TRUE;
02524 }
02525
02526 #endif