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 if (gerror != NULL)
01455 g_error_free (gerror);
01456 g_value_array_free (value_array);
01457 return result;
01458 nomem:
01459 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
01460 goto done;
01461 }
01462
01463 static DBusHandlerResult
01464 gobject_message_function (DBusConnection *connection,
01465 DBusMessage *message,
01466 void *user_data)
01467 {
01468 GParamSpec *pspec;
01469 GObject *object;
01470 gboolean setter;
01471 gboolean getter;
01472 gboolean getall;
01473 char *s;
01474 const char *wincaps_propname;
01475
01476 DBusMessageIter iter;
01477 const DBusGMethodInfo *method;
01478 const DBusGObjectInfo *object_info;
01479 DBusMessage *ret;
01480
01481 object = G_OBJECT (user_data);
01482
01483 if (dbus_message_is_method_call (message,
01484 DBUS_INTERFACE_INTROSPECTABLE,
01485 "Introspect"))
01486 return handle_introspect (connection, message, object);
01487
01488
01489 object_info = NULL;
01490 if (lookup_object_and_method (object, message, &object_info, &method))
01491 return invoke_object_method (object, object_info, method, connection, message);
01492
01493
01494
01495
01496 getter = FALSE;
01497 setter = FALSE;
01498 getall = FALSE;
01499 if (dbus_message_is_method_call (message,
01500 DBUS_INTERFACE_PROPERTIES,
01501 "Get"))
01502 getter = TRUE;
01503 else if (dbus_message_is_method_call (message,
01504 DBUS_INTERFACE_PROPERTIES,
01505 "Set"))
01506 setter = TRUE;
01507 else if (dbus_message_is_method_call (message,
01508 DBUS_INTERFACE_PROPERTIES,
01509 "GetAll"))
01510 getall = TRUE;
01511
01512 if (!(setter || getter || getall))
01513 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01514
01515 ret = NULL;
01516
01517 dbus_message_iter_init (message, &iter);
01518
01519 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01520 {
01521 g_warning ("Property get or set does not have an interface string as first arg\n");
01522 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01523 }
01524
01525
01526
01527
01528 dbus_message_iter_next (&iter);
01529
01530 if (getall)
01531 {
01532 if (object_info != NULL)
01533 ret = get_all_object_properties (connection, message, object_info, object);
01534 else
01535 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01536 }
01537 else if (getter || setter)
01538 {
01539 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
01540 {
01541 g_warning ("Property get or set does not have a property name string as second arg\n");
01542 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01543 }
01544 dbus_message_iter_get_basic (&iter, &wincaps_propname);
01545 dbus_message_iter_next (&iter);
01546
01547 s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
01548
01549 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
01550 s);
01551
01552 g_free (s);
01553
01554 if (pspec != NULL)
01555 {
01556 if (setter)
01557 {
01558 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT)
01559 {
01560 g_warning ("Property set does not have a variant value as third arg\n");
01561 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01562 }
01563
01564 ret = set_object_property (connection, message, &iter,
01565 object, pspec);
01566 dbus_message_iter_next (&iter);
01567 }
01568 else if (getter)
01569 {
01570 ret = get_object_property (connection, message,
01571 object, pspec);
01572 }
01573 else
01574 {
01575 g_assert_not_reached ();
01576 ret = NULL;
01577 }
01578 }
01579 else
01580 {
01581 ret = dbus_message_new_error_printf (message,
01582 DBUS_ERROR_INVALID_ARGS,
01583 "No such property %s", wincaps_propname);
01584 }
01585 }
01586
01587 g_assert (ret != NULL);
01588
01589 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID)
01590 g_warning ("Property get, set or set all had too many arguments\n");
01591
01592 dbus_connection_send (connection, ret, NULL);
01593 dbus_message_unref (ret);
01594 return DBUS_HANDLER_RESULT_HANDLED;
01595 }
01596
01597 static const DBusObjectPathVTable gobject_dbus_vtable = {
01598 gobject_unregister_function,
01599 gobject_message_function,
01600 NULL
01601 };
01602
01603 typedef struct {
01604 GClosure closure;
01605 DBusGConnection *connection;
01606 GObject *object;
01607 const char *signame;
01608 const char *sigiface;
01609 } DBusGSignalClosure;
01610
01611 static GClosure *
01612 dbus_g_signal_closure_new (DBusGConnection *connection,
01613 GObject *object,
01614 const char *signame,
01615 const char *sigiface)
01616 {
01617 DBusGSignalClosure *closure;
01618
01619 closure = (DBusGSignalClosure*) g_closure_new_simple (sizeof (DBusGSignalClosure), NULL);
01620
01621 closure->connection = dbus_g_connection_ref (connection);
01622 closure->object = object;
01623 closure->signame = signame;
01624 closure->sigiface = sigiface;
01625 return (GClosure*) closure;
01626 }
01627
01628 static void
01629 dbus_g_signal_closure_finalize (gpointer data,
01630 GClosure *closure)
01631 {
01632 DBusGSignalClosure *sigclosure = (DBusGSignalClosure *) closure;
01633
01634 dbus_g_connection_unref (sigclosure->connection);
01635 }
01636
01637 static void
01638 signal_emitter_marshaller (GClosure *closure,
01639 GValue *retval,
01640 guint n_param_values,
01641 const GValue *param_values,
01642 gpointer invocation_hint,
01643 gpointer marshal_data)
01644 {
01645 DBusGSignalClosure *sigclosure;
01646 DBusMessage *signal;
01647 DBusMessageIter iter;
01648 guint i;
01649 const char *path;
01650
01651 sigclosure = (DBusGSignalClosure *) closure;
01652
01653 g_assert (retval == NULL);
01654
01655 path = _dbus_gobject_get_path (sigclosure->object);
01656
01657 g_assert (path != NULL);
01658
01659 signal = dbus_message_new_signal (path,
01660 sigclosure->sigiface,
01661 sigclosure->signame);
01662 if (!signal)
01663 {
01664 g_error ("out of memory");
01665 return;
01666 }
01667
01668 dbus_message_iter_init_append (signal, &iter);
01669
01670
01671 for (i = 1; i < n_param_values; i++)
01672 {
01673 if (!_dbus_gvalue_marshal (&iter,
01674 (GValue *) (&(param_values[i]))))
01675 {
01676 g_warning ("failed to marshal parameter %d for signal %s",
01677 i, sigclosure->signame);
01678 goto out;
01679 }
01680 }
01681 dbus_connection_send (DBUS_CONNECTION_FROM_G_CONNECTION (sigclosure->connection),
01682 signal, NULL);
01683 out:
01684 dbus_message_unref (signal);
01685 }
01686
01687 static void
01688 export_signals (DBusGConnection *connection, const GList *info_list, GObject *object)
01689 {
01690 GType gtype;
01691 const char *sigdata;
01692 const char *iface;
01693 const char *signame;
01694 const DBusGObjectInfo *info;
01695
01696 gtype = G_TYPE_FROM_INSTANCE (object);
01697
01698 for (; info_list != NULL; info_list = g_list_next (info_list))
01699 {
01700 info = (DBusGObjectInfo *) info_list->data;
01701
01702 sigdata = info->exported_signals;
01703
01704 while (*sigdata != '\0')
01705 {
01706 guint id;
01707 GSignalQuery query;
01708 GClosure *closure;
01709 char *s;
01710
01711 sigdata = propsig_iterate (sigdata, &iface, &signame);
01712
01713 s = _dbus_gutils_wincaps_to_uscore (signame);
01714
01715 id = g_signal_lookup (s, gtype);
01716 if (id == 0)
01717 {
01718 g_warning ("signal \"%s\" (from \"%s\") exported but not found in object class \"%s\"",
01719 s, signame, g_type_name (gtype));
01720 g_free (s);
01721 continue;
01722 }
01723
01724 g_signal_query (id, &query);
01725
01726 if (query.return_type != G_TYPE_NONE)
01727 {
01728 g_warning ("Not exporting signal \"%s\" for object class \"%s\" as it has a return type \"%s\"",
01729 s, g_type_name (gtype), g_type_name (query.return_type));
01730 g_free (s);
01731 continue;
01732 }
01733
01734 closure = dbus_g_signal_closure_new (connection, object, signame, (char*) iface);
01735 g_closure_set_marshal (closure, signal_emitter_marshaller);
01736
01737 g_signal_connect_closure_by_id (object,
01738 id,
01739 0,
01740 closure,
01741 FALSE);
01742
01743 g_closure_add_finalize_notifier (closure, NULL,
01744 dbus_g_signal_closure_finalize);
01745 g_free (s);
01746 }
01747 }
01748 }
01749
01750 static gint
01751 dbus_error_to_gerror_code (const char *derr)
01752 {
01753 if (0) ;
01754 else if (!strcmp (derr, DBUS_ERROR_FAILED ))
01755 return DBUS_GERROR_FAILED ;
01756 else if (!strcmp (derr, DBUS_ERROR_NO_MEMORY ))
01757 return DBUS_GERROR_NO_MEMORY ;
01758 else if (!strcmp (derr, DBUS_ERROR_SERVICE_UNKNOWN ))
01759 return DBUS_GERROR_SERVICE_UNKNOWN ;
01760 else if (!strcmp (derr, DBUS_ERROR_NAME_HAS_NO_OWNER ))
01761 return DBUS_GERROR_NAME_HAS_NO_OWNER ;
01762 else if (!strcmp (derr, DBUS_ERROR_NO_REPLY ))
01763 return DBUS_GERROR_NO_REPLY ;
01764 else if (!strcmp (derr, DBUS_ERROR_IO_ERROR ))
01765 return DBUS_GERROR_IO_ERROR ;
01766 else if (!strcmp (derr, DBUS_ERROR_BAD_ADDRESS ))
01767 return DBUS_GERROR_BAD_ADDRESS ;
01768 else if (!strcmp (derr, DBUS_ERROR_NOT_SUPPORTED ))
01769 return DBUS_GERROR_NOT_SUPPORTED ;
01770 else if (!strcmp (derr, DBUS_ERROR_LIMITS_EXCEEDED ))
01771 return DBUS_GERROR_LIMITS_EXCEEDED ;
01772 else if (!strcmp (derr, DBUS_ERROR_ACCESS_DENIED ))
01773 return DBUS_GERROR_ACCESS_DENIED ;
01774 else if (!strcmp (derr, DBUS_ERROR_AUTH_FAILED ))
01775 return DBUS_GERROR_AUTH_FAILED ;
01776 else if (!strcmp (derr, DBUS_ERROR_NO_SERVER ))
01777 return DBUS_GERROR_NO_SERVER ;
01778 else if (!strcmp (derr, DBUS_ERROR_TIMEOUT ))
01779 return DBUS_GERROR_TIMEOUT ;
01780 else if (!strcmp (derr, DBUS_ERROR_NO_NETWORK ))
01781 return DBUS_GERROR_NO_NETWORK ;
01782 else if (!strcmp (derr, DBUS_ERROR_ADDRESS_IN_USE ))
01783 return DBUS_GERROR_ADDRESS_IN_USE ;
01784 else if (!strcmp (derr, DBUS_ERROR_DISCONNECTED ))
01785 return DBUS_GERROR_DISCONNECTED ;
01786 else if (!strcmp (derr, DBUS_ERROR_INVALID_ARGS ))
01787 return DBUS_GERROR_INVALID_ARGS ;
01788 else if (!strcmp (derr, DBUS_ERROR_FILE_NOT_FOUND ))
01789 return DBUS_GERROR_FILE_NOT_FOUND ;
01790 else if (!strcmp (derr, DBUS_ERROR_FILE_EXISTS ))
01791 return DBUS_GERROR_FILE_EXISTS ;
01792 else if (!strcmp (derr, DBUS_ERROR_UNKNOWN_METHOD ))
01793 return DBUS_GERROR_UNKNOWN_METHOD ;
01794 else if (!strcmp (derr, DBUS_ERROR_TIMED_OUT ))
01795 return DBUS_GERROR_TIMED_OUT ;
01796 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_NOT_FOUND ))
01797 return DBUS_GERROR_MATCH_RULE_NOT_FOUND ;
01798 else if (!strcmp (derr, DBUS_ERROR_MATCH_RULE_INVALID ))
01799 return DBUS_GERROR_MATCH_RULE_INVALID ;
01800 else if (!strcmp (derr, DBUS_ERROR_SPAWN_EXEC_FAILED ))
01801 return DBUS_GERROR_SPAWN_EXEC_FAILED ;
01802 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FORK_FAILED ))
01803 return DBUS_GERROR_SPAWN_FORK_FAILED ;
01804 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_EXITED ))
01805 return DBUS_GERROR_SPAWN_CHILD_EXITED ;
01806 else if (!strcmp (derr, DBUS_ERROR_SPAWN_CHILD_SIGNALED ))
01807 return DBUS_GERROR_SPAWN_CHILD_SIGNALED ;
01808 else if (!strcmp (derr, DBUS_ERROR_SPAWN_FAILED ))
01809 return DBUS_GERROR_SPAWN_FAILED ;
01810 else if (!strcmp (derr, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN ))
01811 return DBUS_GERROR_UNIX_PROCESS_ID_UNKNOWN ;
01812 else if (!strcmp (derr, DBUS_ERROR_INVALID_SIGNATURE ))
01813 return DBUS_GERROR_INVALID_SIGNATURE ;
01814 else if (!strcmp (derr, DBUS_ERROR_INVALID_FILE_CONTENT ))
01815 return DBUS_GERROR_INVALID_FILE_CONTENT ;
01816 else if (!strcmp (derr, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ))
01817 return DBUS_GERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN ;
01818 else
01819 return DBUS_GERROR_REMOTE_EXCEPTION;
01820 }
01821
01844 void
01845 dbus_set_g_error (GError **gerror,
01846 DBusError *error)
01847 {
01848 int code;
01849
01850 code = dbus_error_to_gerror_code (error->name);
01851 if (code != DBUS_GERROR_REMOTE_EXCEPTION)
01852 g_set_error (gerror, DBUS_GERROR,
01853 code,
01854 "%s",
01855 error->message);
01856 else
01857 g_set_error (gerror, DBUS_GERROR,
01858 code,
01859 "%s%c%s",
01860 error->message ? error->message : "",
01861 '\0',
01862 error->name);
01863 }
01864
01865 static void
01866 dbus_g_error_info_free (gpointer p)
01867 {
01868 DBusGErrorInfo *info;
01869
01870 info = p;
01871
01872 g_free (info->default_iface);
01873 g_free (info);
01874 }
01875
01900 void
01901 dbus_g_object_type_install_info (GType object_type,
01902 const DBusGObjectInfo *info)
01903 {
01904 g_return_if_fail (G_TYPE_IS_CLASSED (object_type) || G_TYPE_IS_INTERFACE (object_type));
01905
01906 _dbus_g_value_types_init ();
01907
01908 g_type_set_qdata (object_type,
01909 dbus_g_object_type_dbus_metadata_quark (),
01910 (gpointer) info);
01911 }
01912
01923 void
01924 dbus_g_error_domain_register (GQuark domain,
01925 const char *default_iface,
01926 GType code_enum)
01927 {
01928 DBusGErrorInfo *info;
01929
01930 g_return_if_fail (g_quark_to_string (domain) != NULL);
01931 g_return_if_fail (code_enum != G_TYPE_INVALID);
01932 g_return_if_fail (G_TYPE_FUNDAMENTAL (code_enum) == G_TYPE_ENUM);
01933
01934 g_static_rw_lock_writer_lock (&globals_lock);
01935
01936 if (error_metadata == NULL)
01937 g_datalist_init (&error_metadata);
01938
01939 info = g_datalist_id_get_data (&error_metadata, domain);
01940
01941 if (info != NULL)
01942 {
01943 g_warning ("Metadata for error domain \"%s\" already registered\n",
01944 g_quark_to_string (domain));
01945 }
01946 else
01947 {
01948 info = g_new0 (DBusGErrorInfo, 1);
01949 info->default_iface = g_strdup (default_iface);
01950 info->code_enum = code_enum;
01951
01952 g_datalist_id_set_data_full (&error_metadata,
01953 domain,
01954 info,
01955 dbus_g_error_info_free);
01956 }
01957
01958 g_static_rw_lock_writer_unlock (&globals_lock);
01959 }
01960
01961 static void
01962 unregister_gobject (DBusGConnection *connection, GObject *dead)
01963 {
01964 char *path;
01965 path = g_object_steal_data (dead, "dbus_glib_object_path");
01966 dbus_connection_unregister_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection), path);
01967 g_free (path);
01968 }
01969
01984 void
01985 dbus_g_connection_register_g_object (DBusGConnection *connection,
01986 const char *at_path,
01987 GObject *object)
01988 {
01989 GList *info_list;
01990 g_return_if_fail (connection != NULL);
01991 g_return_if_fail (at_path != NULL);
01992 g_return_if_fail (G_IS_OBJECT (object));
01993
01994 info_list = lookup_object_info (object);
01995 if (info_list == NULL)
01996 {
01997 g_warning ("No introspection data registered for object class \"%s\"",
01998 g_type_name (G_TYPE_FROM_INSTANCE (object)));
01999 return;
02000 }
02001
02002 if (!dbus_connection_register_object_path (DBUS_CONNECTION_FROM_G_CONNECTION (connection),
02003 at_path,
02004 &gobject_dbus_vtable,
02005 object))
02006 {
02007 g_error ("Failed to register GObject with DBusConnection");
02008 return;
02009 }
02010
02011 export_signals (connection, info_list, object);
02012 g_list_free (info_list);
02013
02014 g_object_set_data (object, "dbus_glib_object_path", g_strdup (at_path));
02015 g_object_weak_ref (object, (GWeakNotify)unregister_gobject, connection);
02016 }
02017
02027 GObject *
02028 dbus_g_connection_lookup_g_object (DBusGConnection *connection,
02029 const char *at_path)
02030 {
02031 gpointer ret;
02032 if (!dbus_connection_get_object_path_data (DBUS_CONNECTION_FROM_G_CONNECTION (connection), at_path, &ret))
02033 return NULL;
02034 return ret;
02035 }
02036
02037 typedef struct {
02038 GType rettype;
02039 guint n_params;
02040 GType *params;
02041 } DBusGFuncSignature;
02042
02043 static guint
02044 funcsig_hash (gconstpointer key)
02045 {
02046 const DBusGFuncSignature *sig = key;
02047 GType *types;
02048 guint ret;
02049 guint i;
02050
02051 ret = sig->rettype;
02052 types = sig->params;
02053
02054 for (i = 0; i < sig->n_params; i++)
02055 {
02056 ret += (int) (*types);
02057 types++;
02058 }
02059
02060 return ret;
02061 }
02062
02063 static gboolean
02064 funcsig_equal (gconstpointer aval,
02065 gconstpointer bval)
02066 {
02067 const DBusGFuncSignature *a = aval;
02068 const DBusGFuncSignature *b = bval;
02069 const GType *atypes;
02070 const GType *btypes;
02071 guint i;
02072
02073 if (a->rettype != b->rettype
02074 || a->n_params != b->n_params)
02075 return FALSE;
02076
02077 atypes = a->params;
02078 btypes = b->params;
02079
02080 for (i = 0; i < a->n_params; i++)
02081 {
02082 if (*btypes != *atypes)
02083 return FALSE;
02084 atypes++;
02085 btypes++;
02086 }
02087
02088 return TRUE;
02089 }
02090
02091 static void
02092 funcsig_free (DBusGFuncSignature *sig)
02093 {
02094 g_free (sig->params);
02095 g_free (sig);
02096 }
02097
02098 GClosureMarshal
02099 _dbus_gobject_lookup_marshaller (GType rettype,
02100 guint n_params,
02101 const GType *param_types)
02102 {
02103 GClosureMarshal ret;
02104 DBusGFuncSignature sig;
02105 GType *params;
02106 guint i;
02107
02108
02109 rettype = G_TYPE_FUNDAMENTAL (rettype);
02110 params = g_new (GType, n_params);
02111 for (i = 0; i < n_params; i++)
02112 params[i] = G_TYPE_FUNDAMENTAL (param_types[i]);
02113
02114 sig.rettype = rettype;
02115 sig.n_params = n_params;
02116 sig.params = params;
02117
02118 g_static_rw_lock_reader_lock (&globals_lock);
02119
02120 if (marshal_table)
02121 ret = g_hash_table_lookup (marshal_table, &sig);
02122 else
02123 ret = NULL;
02124
02125 g_static_rw_lock_reader_unlock (&globals_lock);
02126
02127 if (ret == NULL)
02128 {
02129 if (rettype == G_TYPE_NONE)
02130 {
02131 if (n_params == 0)
02132 ret = g_cclosure_marshal_VOID__VOID;
02133 else if (n_params == 1)
02134 {
02135 switch (params[0])
02136 {
02137 case G_TYPE_BOOLEAN:
02138 ret = g_cclosure_marshal_VOID__BOOLEAN;
02139 break;
02140 case G_TYPE_UCHAR:
02141 ret = g_cclosure_marshal_VOID__UCHAR;
02142 break;
02143 case G_TYPE_INT:
02144 ret = g_cclosure_marshal_VOID__INT;
02145 break;
02146 case G_TYPE_UINT:
02147 ret = g_cclosure_marshal_VOID__UINT;
02148 break;
02149 case G_TYPE_DOUBLE:
02150 ret = g_cclosure_marshal_VOID__DOUBLE;
02151 break;
02152 case G_TYPE_STRING:
02153 ret = g_cclosure_marshal_VOID__STRING;
02154 break;
02155 case G_TYPE_BOXED:
02156 ret = g_cclosure_marshal_VOID__BOXED;
02157 break;
02158 }
02159 }
02160 else if (n_params == 3
02161 && params[0] == G_TYPE_STRING
02162 && params[1] == G_TYPE_STRING
02163 && params[2] == G_TYPE_STRING)
02164 {
02165 ret = _dbus_g_marshal_NONE__STRING_STRING_STRING;
02166 }
02167 }
02168 }
02169
02170 g_free (params);
02171 return ret;
02172 }
02173
02186 void
02187 dbus_g_object_register_marshaller (GClosureMarshal marshaller,
02188 GType rettype,
02189 ...)
02190 {
02191 va_list args;
02192 GArray *types;
02193 GType gtype;
02194
02195 va_start (args, rettype);
02196
02197 types = g_array_new (TRUE, TRUE, sizeof (GType));
02198
02199 while ((gtype = va_arg (args, GType)) != G_TYPE_INVALID)
02200 g_array_append_val (types, gtype);
02201
02202 dbus_g_object_register_marshaller_array (marshaller, rettype,
02203 types->len, (GType*) types->data);
02204
02205 g_array_free (types, TRUE);
02206 va_end (args);
02207 }
02208
02219 void
02220 dbus_g_object_register_marshaller_array (GClosureMarshal marshaller,
02221 GType rettype,
02222 guint n_types,
02223 const GType* types)
02224 {
02225 DBusGFuncSignature *sig;
02226 guint i;
02227
02228 g_static_rw_lock_writer_lock (&globals_lock);
02229
02230 if (marshal_table == NULL)
02231 marshal_table = g_hash_table_new_full (funcsig_hash,
02232 funcsig_equal,
02233 (GDestroyNotify) funcsig_free,
02234 NULL);
02235 sig = g_new0 (DBusGFuncSignature, 1);
02236 sig->rettype = G_TYPE_FUNDAMENTAL (rettype);
02237 sig->n_params = n_types;
02238 sig->params = g_new (GType, n_types);
02239 for (i = 0; i < n_types; i++)
02240 sig->params[i] = G_TYPE_FUNDAMENTAL (types[i]);
02241
02242 g_hash_table_insert (marshal_table, sig, marshaller);
02243
02244 g_static_rw_lock_writer_unlock (&globals_lock);
02245 }
02246
02259 gchar *
02260 dbus_g_method_get_sender (DBusGMethodInvocation *context)
02261 {
02262 const gchar *sender;
02263
02264 sender = dbus_message_get_sender (dbus_g_message_get_message (context->message));
02265
02266 if (sender == NULL)
02267 return NULL;
02268
02269 return strdup (sender);
02270 }
02271
02282 DBusMessage *
02283 dbus_g_method_get_reply (DBusGMethodInvocation *context)
02284 {
02285 return dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02286 }
02287
02297 void
02298 dbus_g_method_send_reply (DBusGMethodInvocation *context, DBusMessage *reply)
02299 {
02300 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02301 dbus_message_unref (reply);
02302
02303 dbus_g_connection_unref (context->connection);
02304 dbus_g_message_unref (context->message);
02305 g_free (context);
02306 }
02307
02308
02316 void
02317 dbus_g_method_return (DBusGMethodInvocation *context, ...)
02318 {
02319 DBusMessage *reply;
02320 DBusMessageIter iter;
02321 va_list args;
02322 char *out_sig;
02323 GArray *argsig;
02324 guint i;
02325
02326 reply = dbus_message_new_method_return (dbus_g_message_get_message (context->message));
02327 out_sig = method_output_signature_from_object_info (context->object, context->method);
02328 argsig = _dbus_gtypes_from_arg_signature (out_sig, FALSE);
02329
02330 dbus_message_iter_init_append (reply, &iter);
02331
02332 va_start (args, context);
02333 for (i = 0; i < argsig->len; i++)
02334 {
02335 GValue value = {0,};
02336 char *error;
02337 g_value_init (&value, g_array_index (argsig, GType, i));
02338 error = NULL;
02339 G_VALUE_COLLECT (&value, args, G_VALUE_NOCOPY_CONTENTS, &error);
02340 if (error)
02341 {
02342 g_warning(error);
02343 g_free (error);
02344 }
02345 _dbus_gvalue_marshal (&iter, &value);
02346 }
02347 va_end (args);
02348
02349 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02350 dbus_message_unref (reply);
02351
02352 dbus_g_connection_unref (context->connection);
02353 dbus_g_message_unref (context->message);
02354 g_free (context);
02355 g_free (out_sig);
02356 g_array_free (argsig, TRUE);
02357 }
02358
02367 void
02368 dbus_g_method_return_error (DBusGMethodInvocation *context, GError *error)
02369 {
02370 DBusMessage *reply;
02371 reply = gerror_to_dbus_error_message (context->object, dbus_g_message_get_message (context->message), error);
02372 dbus_connection_send (dbus_g_connection_get_connection (context->connection), reply, NULL);
02373 dbus_message_unref (reply);
02374
02375 dbus_g_connection_unref (context->connection);
02376 dbus_g_message_unref (context->message);
02377 g_free (context);
02378 }
02379
02380 const char * _dbus_gobject_get_path (GObject *obj)
02381 {
02382 return g_object_get_data (obj, "dbus_glib_object_path");
02383 }
02384
02385 #ifdef DBUS_BUILD_TESTS
02386 #include <stdlib.h>
02387
02388 static void
02389 _dummy_function (void)
02390 {
02391 }
02392
02393
02394
02395
02396 static const DBusGMethodInfo dbus_glib_internal_test_methods[] = {
02397 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 0 },
02398 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 49 },
02399 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 117 },
02400 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 191 },
02401 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 270 },
02402 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 320 },
02403 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 391 },
02404 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 495 },
02405 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 623 },
02406 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 693 },
02407 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 765 },
02408 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 838 },
02409 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 911 },
02410 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 988 },
02411 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1064 },
02412 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1140 },
02413 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1204 },
02414 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1278 },
02415 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1347 },
02416 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1408 },
02417 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1460 },
02418 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1533 },
02419 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1588 },
02420 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1647 },
02421 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1730 },
02422 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1784 },
02423 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1833 },
02424 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1895 },
02425 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1947 },
02426 { (GCallback) _dummy_function, g_cclosure_marshal_VOID__VOID, 1999 },
02427 };
02428
02429 const DBusGObjectInfo dbus_glib_internal_test_object_info = {
02430 0,
02431 dbus_glib_internal_test_methods,
02432 30,
02433 "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",
02434 "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",
02435 "\0"
02436 };
02437
02438
02444 gboolean
02445 _dbus_gobject_test (const char *test_data_dir)
02446 {
02447 int i;
02448 const char *arg;
02449 const char *arg_name;
02450 gboolean arg_in;
02451 gboolean constval;
02452 RetvalType retval;
02453 const char *arg_signature;
02454 const char *sigdata;
02455 const char *iface;
02456 const char *signame;
02457
02458 static struct { const char *wincaps; const char *uscore; } name_pairs[] = {
02459 { "SetFoo", "set_foo" },
02460 { "Foo", "foo" },
02461 { "GetFooBar", "get_foo_bar" },
02462 { "Hello", "hello" }
02463
02464
02465
02466 };
02467
02468
02469
02470
02471
02472
02473 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02474 &(dbus_glib_internal_test_methods[0]));
02475 g_assert (*arg == '\0');
02476
02477
02478 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02479 &(dbus_glib_internal_test_methods[1]));
02480 g_assert (*arg != '\0');
02481 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02482 g_assert (!strcmp (arg_name, "x"));
02483 g_assert (arg_in == TRUE);
02484 g_assert (!strcmp (arg_signature, "u"));
02485 g_assert (*arg != '\0');
02486 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02487 g_assert (arg_in == FALSE);
02488 g_assert (retval == RETVAL_NONE);
02489 g_assert (!strcmp (arg_signature, "u"));
02490 g_assert (*arg == '\0');
02491
02492
02493 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02494 &(dbus_glib_internal_test_methods[2]));
02495 g_assert (*arg != '\0');
02496 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02497 g_assert (!strcmp (arg_name, "x"));
02498 g_assert (arg_in == TRUE);
02499 g_assert (!strcmp (arg_signature, "u"));
02500 g_assert (*arg != '\0');
02501 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02502 g_assert (retval == RETVAL_NOERROR);
02503 g_assert (arg_in == FALSE);
02504 g_assert (!strcmp (arg_signature, "u"));
02505 g_assert (*arg == '\0');
02506
02507
02508 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02509 &(dbus_glib_internal_test_methods[3]));
02510 g_assert (*arg != '\0');
02511 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02512 g_assert (!strcmp (arg_name, "x"));
02513 g_assert (arg_in == TRUE);
02514 g_assert (!strcmp (arg_signature, "u"));
02515 g_assert (*arg != '\0');
02516 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02517 g_assert (retval == RETVAL_ERROR);
02518 g_assert (arg_in == FALSE);
02519 g_assert (!strcmp (arg_signature, "u"));
02520 g_assert (*arg == '\0');
02521
02522
02523 arg = method_arg_info_from_object_info (&dbus_glib_internal_test_object_info,
02524 &(dbus_glib_internal_test_methods[8]));
02525 g_assert (*arg != '\0');
02526 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02527 g_assert (!strcmp (arg_name, "val"));
02528 g_assert (arg_in == TRUE);
02529 g_assert (!strcmp (arg_signature, "v"));
02530 g_assert (*arg != '\0');
02531 arg = arg_iterate (arg, &arg_name, &arg_in, &constval, &retval, &arg_signature);
02532 g_assert (retval == RETVAL_NONE);
02533 g_assert (arg_in == FALSE);
02534 g_assert (!strcmp (arg_signature, "s"));
02535 g_assert (*arg == '\0');
02536
02537 sigdata = dbus_glib_internal_test_object_info.exported_signals;
02538 g_assert (*sigdata != '\0');
02539 sigdata = propsig_iterate (sigdata, &iface, &signame);
02540 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
02541 g_assert (!strcmp (signame, "Frobnicate"));
02542 g_assert (*sigdata != '\0');
02543 sigdata = propsig_iterate (sigdata, &iface, &signame);
02544 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02545 g_assert (!strcmp (signame, "Sig0"));
02546 g_assert (*sigdata != '\0');
02547 sigdata = propsig_iterate (sigdata, &iface, &signame);
02548 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02549 g_assert (!strcmp (signame, "Sig1"));
02550 g_assert (*sigdata != '\0');
02551 sigdata = propsig_iterate (sigdata, &iface, &signame);
02552 g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
02553 g_assert (!strcmp (signame, "Sig2"));
02554 g_assert (*sigdata == '\0');
02555
02556
02557 i = 0;
02558 while (i < (int) G_N_ELEMENTS (name_pairs))
02559 {
02560 char *uscore;
02561 char *wincaps;
02562
02563 uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
02564 wincaps = uscore_to_wincaps (name_pairs[i].uscore);
02565
02566 if (strcmp (uscore, name_pairs[i].uscore) != 0)
02567 {
02568 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02569 name_pairs[i].wincaps, name_pairs[i].uscore,
02570 uscore);
02571 exit (1);
02572 }
02573
02574 if (strcmp (wincaps, name_pairs[i].wincaps) != 0)
02575 {
02576 g_printerr ("\"%s\" should have been converted to \"%s\" not \"%s\"\n",
02577 name_pairs[i].uscore, name_pairs[i].wincaps,
02578 wincaps);
02579 exit (1);
02580 }
02581
02582 g_free (uscore);
02583 g_free (wincaps);
02584
02585 ++i;
02586 }
02587
02588 return TRUE;
02589 }
02590
02591 #endif