From 98ad8a8ec6626f7f5c78915b6bdf2be688b4839f Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 30 Jan 2005 07:44:08 +0000 Subject: 2005-01-30 Havoc Pennington * glib/dbus-gobject.c (introspect_properties): fix the XML generated * dbus/dbus-message.c (dbus_message_unref): add an in_cache flag which effectively detects the use of freed messages * glib/dbus-gobject.c (handle_introspect): modify and return the reply message instead of the incoming message * dbus/dbus-object-tree.c (handle_default_introspect_unlocked): gee, maybe it should SEND THE XML instead of just making a string and freeing it again ;-) * tools/dbus-print-message.c (print_message): improve printing of messages * configure.in: add debug-glib.service to the output --- ChangeLog | 20 +++++++ bus/driver.c | 2 +- configure.in | 3 +- dbus/dbus-connection-internal.h | 4 +- dbus/dbus-connection.c | 13 ++++- dbus/dbus-marshal-validate.c | 4 ++ dbus/dbus-message-private.h | 4 ++ dbus/dbus-message.c | 14 ++++- dbus/dbus-object-tree.c | 30 ++++++++++ glib/dbus-gobject.c | 10 ++-- glib/dbus-gparser.c | 2 + test/glib/run-test.sh | 5 +- test/glib/test-service-glib.c | 118 +++++++++++++++++++++++++++++++++++++++- tools/dbus-print-message.c | 52 ++++++++++-------- tools/dbus-viewer.c | 79 ++++++++++++++++++++++----- 15 files changed, 307 insertions(+), 53 deletions(-) diff --git a/ChangeLog b/ChangeLog index dcb3a6de..029dafe9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2005-01-30 Havoc Pennington + + * glib/dbus-gobject.c (introspect_properties): fix the XML + generated + + * dbus/dbus-message.c (dbus_message_unref): add an in_cache flag + which effectively detects the use of freed messages + + * glib/dbus-gobject.c (handle_introspect): modify and return the + reply message instead of the incoming message + + * dbus/dbus-object-tree.c (handle_default_introspect_unlocked): + gee, maybe it should SEND THE XML instead of just making a string + and freeing it again ;-) + + * tools/dbus-print-message.c (print_message): improve printing of + messages + + * configure.in: add debug-glib.service to the output + 2005-01-30 Havoc Pennington dbus-viewer introspected and displayed the bus driver diff --git a/bus/driver.c b/bus/driver.c index 58b8fcbf..580301a9 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -470,7 +470,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, DBUS_TYPE_INVALID)) return FALSE; - _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags); + _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags); retval = FALSE; reply = NULL; diff --git a/configure.in b/configure.in index b09430d5..1df76996 100644 --- a/configure.in +++ b/configure.in @@ -1111,7 +1111,7 @@ AC_SUBST(TEST_$1) TEST_PATH(SERVICE_DIR, data/valid-service-files) TEST_PATH(SERVICE_BINARY, test-service) -TEST_PATH(GLIB_SERVICE_BINARY, test-service-glib) +TEST_PATH(GLIB_SERVICE_BINARY, glib/test-service-glib) TEST_PATH(EXIT_BINARY, test-exit) TEST_PATH(SEGFAULT_BINARY, test-segfault) TEST_PATH(SLEEP_FOREVER_BINARY, test-sleep-forever) @@ -1216,6 +1216,7 @@ test/data/valid-config-files/debug-allow-all.conf test/data/valid-config-files/debug-allow-all-sha1.conf test/data/valid-service-files/debug-echo.service test/data/valid-service-files/debug-segfault.service +test/data/valid-service-files/debug-glib.service ]) ### FIXME it's bizarre that have_qt and have_glib are used diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index b5781d9c..14184ad2 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -89,7 +89,9 @@ DBusMessage* _dbus_connection_block_for_reply (DBusConnection int timeout_milliseconds); void _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending, DBusMessage *message); - +dbus_bool_t _dbus_connection_send_unlocked (DBusConnection *connection, + DBusMessage *message, + dbus_uint32_t *client_serial); /** * @addtogroup DBusPendingCallInternals DBusPendingCall implementation details diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 90d7c38b..f01133c5 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -357,7 +357,7 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, _dbus_connection_wakeup_mainloop (connection); - _dbus_verbose ("Message %p (%d %s %s '%s') added to incoming queue %p, %d incoming\n", + _dbus_verbose ("Message %p (%d %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? @@ -367,6 +367,7 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, dbus_message_get_member (message) : "no member", dbus_message_get_signature (message), + dbus_message_get_reply_serial (message), connection, connection->n_incoming); } @@ -1562,7 +1563,7 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, sig = dbus_message_get_signature (message); - _dbus_verbose ("Message %p (%d %s %s '%s') added to outgoing queue %p, %d pending to send\n", + _dbus_verbose ("Message %p (%d %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? @@ -1572,6 +1573,9 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, dbus_message_get_member (message) : "no member", sig, + dbus_message_get_destination (message) ? + dbus_message_get_destination (message) : + "null", connection, connection->n_outgoing); @@ -1587,6 +1591,9 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, if (client_serial) *client_serial = dbus_message_get_serial (message); } + + _dbus_verbose ("Message %p serial is %u\n", + message, dbus_message_get_serial (message)); _dbus_message_lock (message); @@ -1638,7 +1645,7 @@ dbus_connection_send_preallocated (DBusConnection *connection, CONNECTION_UNLOCK (connection); } -static dbus_bool_t +dbus_bool_t _dbus_connection_send_unlocked (DBusConnection *connection, DBusMessage *message, dbus_uint32_t *client_serial) diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c index d9b85cb7..b144b62a 100644 --- a/dbus/dbus-marshal-validate.c +++ b/dbus/dbus-marshal-validate.c @@ -178,9 +178,11 @@ validate_body_helper (DBusTypeReader *reader, const unsigned char *a; int alignment; +#if 0 _dbus_verbose (" validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n", _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, (int) (end - p)); +#endif /* Guarantee that p has one byte to look at */ if (p == end) @@ -436,9 +438,11 @@ validate_body_helper (DBusTypeReader *reader, break; } +#if 0 _dbus_verbose (" validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n", _dbus_type_to_string (current_type), reader, reader->type_pos, p, end, (int) (end - p)); +#endif if (p > end) { diff --git a/dbus/dbus-message-private.h b/dbus/dbus-message-private.h index 5f727ae1..9ba5c2f4 100644 --- a/dbus/dbus-message-private.h +++ b/dbus/dbus-message-private.h @@ -97,6 +97,10 @@ struct DBusMessage unsigned int locked : 1; /**< Message being sent, no modifications allowed. */ +#ifndef DBUS_DISABLE_CHECKS + unsigned int in_cache : 1; /**< Has been "freed" since it's in the cache (this is a debug feature) */ +#endif + DBusList *size_counters; /**< 0-N DBusCounter used to track message size. */ long size_counter_delta; /**< Size we incremented the size counters by. */ diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 85252005..0d816595 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -456,6 +456,8 @@ dbus_message_finalize (DBusMessage *message) _dbus_header_free (&message->header); _dbus_string_free (&message->body); + _dbus_assert (message->refcount.value == 0); + dbus_free (message); } @@ -657,10 +659,15 @@ dbus_message_cache_or_finalize (DBusMessage *message) message_cache[i] = message; message_cache_count += 1; was_cached = TRUE; +#ifndef DBUS_DISABLE_CHECKS + message->in_cache = TRUE; +#endif out: _DBUS_UNLOCK (message_cache); + _dbus_assert (message->refcount.value == 0); + if (!was_cached) dbus_message_finalize (message); } @@ -691,6 +698,9 @@ dbus_message_new_empty_header (void) message->refcount.value = 1; message->byte_order = DBUS_COMPILER_BYTE_ORDER; message->locked = FALSE; +#ifndef DBUS_DISABLE_CHECKS + message->in_cache = FALSE; +#endif message->size_counters = NULL; message->size_counter_delta = 0; message->changed_stamp = 0; @@ -1067,7 +1077,8 @@ dbus_message_ref (DBusMessage *message) _dbus_return_val_if_fail (message != NULL, NULL); _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL); - + _dbus_return_val_if_fail (!message->in_cache, NULL); + old_refcount = _dbus_atomic_inc (&message->refcount); _dbus_assert (old_refcount >= 1); @@ -1087,6 +1098,7 @@ dbus_message_unref (DBusMessage *message) _dbus_return_if_fail (message != NULL); _dbus_return_if_fail (message->generation == _dbus_current_generation); + _dbus_return_if_fail (!message->in_cache); old_refcount = _dbus_atomic_dec (&message->refcount); diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c index f8797595..da8d8c26 100644 --- a/dbus/dbus-object-tree.c +++ b/dbus/dbus-object-tree.c @@ -615,11 +615,22 @@ handle_default_introspect_unlocked (DBusObjectTree *tree, DBusHandlerResult result; char **children; int i; + DBusMessage *reply; + DBusMessageIter iter; + const char *v_STRING; + /* We have the connection lock here */ + + _dbus_verbose (" considering default Introspect() handler...\n"); + + reply = NULL; + if (!dbus_message_is_method_call (message, DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, "Introspect")) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + _dbus_verbose (" using default Introspect() handler!\n"); if (!_dbus_string_init (&xml)) return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -648,12 +659,31 @@ handle_default_introspect_unlocked (DBusObjectTree *tree, if (!_dbus_string_append (&xml, "\n")) goto out; + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto out; + + dbus_message_iter_init_append (reply, &iter); + v_STRING = _dbus_string_get_const_data (&xml); + if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &v_STRING)) + goto out; + +#ifdef DBUS_BUILD_TESTS + if (tree->connection) +#endif + { + if (!_dbus_connection_send_unlocked (tree->connection, reply, NULL)) + goto out; + } result = DBUS_HANDLER_RESULT_HANDLED; out: _dbus_string_free (&xml); dbus_free_string_array (children); + if (reply) + dbus_message_unref (reply); return result; } diff --git a/glib/dbus-gobject.c b/glib/dbus-gobject.c index 245ebf1e..abaf2e0e 100644 --- a/glib/dbus-gobject.c +++ b/glib/dbus-gobject.c @@ -204,7 +204,7 @@ introspect_properties (GObject *object, GString *xml) g_string_append (xml, s); g_string_append (xml, "\" type=\""); g_string_append (xml, _dbus_gutils_type_to_string (dbus_type)); - g_string_append (xml, "\" access=\"\n"); + g_string_append (xml, "\" access=\""); if (can_set && can_get) g_string_append (xml, "readwrite"); @@ -216,7 +216,7 @@ introspect_properties (GObject *object, GString *xml) g_string_append (xml, "write"); } - g_string_append (xml, "\">\n"); + g_string_append (xml, "\"/>\n"); } g_free (s); @@ -329,12 +329,12 @@ handle_introspect (DBusConnection *connection, if (ret == NULL) g_error ("Out of memory"); - dbus_message_append_args (message, + dbus_message_append_args (ret, DBUS_TYPE_STRING, &xml->str, DBUS_TYPE_INVALID); - dbus_connection_send (connection, message, NULL); - dbus_message_unref (message); + dbus_connection_send (connection, ret, NULL); + dbus_message_unref (ret); g_string_free (xml, TRUE); diff --git a/glib/dbus-gparser.c b/glib/dbus-gparser.c index 83922af4..963a5730 100644 --- a/glib/dbus-gparser.c +++ b/glib/dbus-gparser.c @@ -483,6 +483,8 @@ basic_type_from_string (const char *str) return DBUS_TYPE_BYTE; else if (strcmp (str, "object") == 0) return DBUS_TYPE_OBJECT_PATH; + else if (strcmp (str, "variant") == 0) + return DBUS_TYPE_VARIANT; else return DBUS_TYPE_INVALID; } diff --git a/test/glib/run-test.sh b/test/glib/run-test.sh index 0a5e3f65..cf0a85fc 100755 --- a/test/glib/run-test.sh +++ b/test/glib/run-test.sh @@ -67,9 +67,12 @@ elif test x$MODE = xviewer ; then echo "Launching dbus-viewer" ARGS= if test x$DEBUG = x ; then - ARGS="--services org.freedesktop.DBus" + ARGS="--services org.freedesktop.DBus org.freedesktop.DBus.TestSuiteGLibService" fi libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/tools/dbus-viewer $ARGS || die "could not run dbus-viewer" +elif test x$MODE = xwait ; then + echo "Waiting DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" + sleep 86400 else echo "running test-dbus-glib" libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/glib/test-dbus-glib || die "test-dbus-glib failed" diff --git a/test/glib/test-service-glib.c b/test/glib/test-service-glib.c index 9b1be0ad..413bcc20 100644 --- a/test/glib/test-service-glib.c +++ b/test/glib/test-service-glib.c @@ -3,6 +3,7 @@ #include #include #include +#include typedef struct MyObject MyObject; typedef struct MyObjectClass MyObjectClass; @@ -12,6 +13,7 @@ GType my_object_get_type (void); struct MyObject { GObject parent; + char *this_is_a_string; }; struct MyObjectClass @@ -20,7 +22,7 @@ struct MyObjectClass }; #define MY_TYPE_OBJECT (my_object_get_type ()) -#define MY_OBJECT_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject)) +#define MY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MY_TYPE_OBJECT, MyObject)) #define MY_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass)) #define MY_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MY_TYPE_OBJECT)) #define MY_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT)) @@ -28,6 +30,67 @@ struct MyObjectClass G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT) +/* Properties */ +enum +{ + PROP_0, + PROP_THIS_IS_A_STRING +}; + +static void +my_object_finalize (GObject *object) +{ + MyObject *mobject = MY_OBJECT (object); + + g_free (mobject->this_is_a_string); + + (G_OBJECT_CLASS (my_object_parent_class)->finalize) (object); +} + +static void +my_object_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MyObject *mobject; + + mobject = MY_OBJECT (object); + + switch (prop_id) + { + case PROP_THIS_IS_A_STRING: + g_free (mobject->this_is_a_string); + mobject->this_is_a_string = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +my_object_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MyObject *mobject; + + mobject = MY_OBJECT (object); + + switch (prop_id) + { + case PROP_THIS_IS_A_STRING: + g_value_set_string (value, mobject->this_is_a_string); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} static void my_object_init (MyObject *obj) @@ -36,9 +99,21 @@ my_object_init (MyObject *obj) } static void -my_object_class_init (MyObjectClass *obj_class) +my_object_class_init (MyObjectClass *mobject_class) { + GObjectClass *gobject_class = G_OBJECT_CLASS (mobject_class); + + gobject_class->finalize = my_object_finalize; + gobject_class->set_property = my_object_set_property; + gobject_class->get_property = my_object_get_property; + g_object_class_install_property (gobject_class, + PROP_THIS_IS_A_STRING, + g_param_spec_string ("this_is_a_string", + _("Sample string"), + _("Example of a string property"), + "default value", + G_PARAM_READWRITE)); } static GMainLoop *loop; @@ -49,6 +124,10 @@ main (int argc, char **argv) DBusGConnection *connection; GError *error; GObject *obj; + DBusGProxy *driver_proxy; + DBusGPendingCall *call; + const char *v_STRING; + guint32 v_UINT32; g_type_init (); @@ -70,7 +149,40 @@ main (int argc, char **argv) dbus_g_connection_register_g_object (connection, "/org/freedesktop/my_test_object", obj); - + + driver_proxy = dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS); + + v_STRING = "org.freedesktop.DBus.TestSuiteGLibService"; + v_UINT32 = 0; + call = dbus_g_proxy_begin_call (driver_proxy, "RequestName", + DBUS_TYPE_STRING, + &v_STRING, + DBUS_TYPE_UINT32, + &v_UINT32, + DBUS_TYPE_INVALID); + if (!dbus_g_proxy_end_call (driver_proxy, call, + &error, DBUS_TYPE_UINT32, &v_UINT32, + DBUS_TYPE_INVALID)) + { + g_assert (error != NULL); + g_printerr ("Failed to get name: %s\n", + error->message); + g_error_free (error); + exit (1); + } + g_assert (error == NULL); + dbus_g_pending_call_unref (call); + + if (!(v_UINT32 == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)) + { + g_printerr ("Got result code %u from requesting name\n", v_UINT32); + exit (1); + } + + g_print ("GLib test service has name '%s'\n", v_STRING); g_print ("GLib test service entering main loop\n"); g_main_loop_run (loop); diff --git a/tools/dbus-print-message.c b/tools/dbus-print-message.c index 572a1d14..b3559256 100644 --- a/tools/dbus-print-message.c +++ b/tools/dbus-print-message.c @@ -44,43 +44,45 @@ print_message (DBusMessage *message) { DBusMessageIter iter; const char *sender; + const char *destination; int message_type; + int count; message_type = dbus_message_get_type (message); - sender = dbus_message_get_sender (message); - + sender = dbus_message_get_sender (message); + destination = dbus_message_get_destination (message); + + printf ("%s sender=%s -> dest=%s", + type_to_name (message_type), + sender ? sender : "(null sender)", + destination ? destination : "(null destination)"); + switch (message_type) { case DBUS_MESSAGE_TYPE_METHOD_CALL: case DBUS_MESSAGE_TYPE_SIGNAL: - printf ("%s interface=%s; member=%s; sender=%s\n", - type_to_name (message_type), + printf (" interface=%s; member=%s\n", dbus_message_get_interface (message), - dbus_message_get_member (message), - sender ? sender : "(no sender)"); + dbus_message_get_member (message)); break; case DBUS_MESSAGE_TYPE_METHOD_RETURN: - printf ("%s; sender=%s\n", - type_to_name (message_type), - sender ? sender : "(no sender)"); + printf ("\n"); break; case DBUS_MESSAGE_TYPE_ERROR: - printf ("%s name=%s; sender=%s\n", - type_to_name (message_type), - dbus_message_get_error_name (message), - sender ? sender : "(no sender)"); + printf (" error_name=%s\n", + dbus_message_get_error_name (message)); break; default: - printf ("Message of unknown type %d received\n", - message_type); + printf ("\n"); break; } - - dbus_message_iter_init (message, &iter); + dbus_message_iter_init (message, &iter); + count = 0; + do { int type = dbus_message_iter_get_arg_type (&iter); @@ -98,38 +100,40 @@ print_message (DBusMessage *message) { case DBUS_TYPE_STRING: dbus_message_iter_get_basic (&iter, &str); - printf ("string:%s\n", str); + printf (" %d string \"%s\"\n", count, str); break; case DBUS_TYPE_INT32: dbus_message_iter_get_basic (&iter, &int32); - printf ("int32:%d\n", int32); + printf (" %d int32 %d\n", count, int32); break; case DBUS_TYPE_UINT32: dbus_message_iter_get_basic (&iter, &uint32); - printf ("int32:%u\n", uint32); + printf (" %d uint32 %u\n", count, uint32); break; case DBUS_TYPE_DOUBLE: dbus_message_iter_get_basic (&iter, &d); - printf ("double:%f\n", d); + printf (" %d double %g\n", count, d); break; case DBUS_TYPE_BYTE: dbus_message_iter_get_basic (&iter, &byte); - printf ("byte:%d\n", byte); + printf (" %d byte %d\n", count, byte); break; case DBUS_TYPE_BOOLEAN: dbus_message_iter_get_basic (&iter, &boolean); - printf ("boolean:%s\n", boolean ? "true" : "false"); + printf (" %d boolean %s\n", count, boolean ? "true" : "false"); break; default: - printf ("(unknown arg type %d)\n", type); + printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type); break; } + + count += 1; } while (dbus_message_iter_next (&iter)); } diff --git a/tools/dbus-viewer.c b/tools/dbus-viewer.c index c32e6fd9..abd299f6 100644 --- a/tools/dbus-viewer.c +++ b/tools/dbus-viewer.c @@ -192,6 +192,7 @@ show_error_dialog (GtkWindow *transient_parent, static gboolean load_child_nodes (const char *service_name, NodeInfo *parent, + GString *path, GError **error) { DBusGConnection *connection; @@ -200,7 +201,7 @@ load_child_nodes (const char *service_name, connection = dbus_g_bus_get (DBUS_BUS_SESSION, error); if (connection == NULL) return FALSE; - + tmp = node_info_get_nodes (parent); while (tmp != NULL) { @@ -209,17 +210,37 @@ load_child_nodes (const char *service_name, const char *data; NodeInfo *child; NodeInfo *complete_child; + int save_len; complete_child = NULL; + call = NULL; child = tmp->data; - g_assert (*service_name == ':'); /* so we don't need new_for_name_owner */ - proxy = dbus_g_proxy_new_for_name (connection, - service_name, - "/", - DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE); - g_assert (proxy != NULL); + save_len = path->len; + + if (save_len > 1) + g_string_append (path, "/"); + g_string_append (path, base_info_get_name ((BaseInfo*)child)); + + if (*service_name == ':') + { + proxy = dbus_g_proxy_new_for_name (connection, + service_name, + path->str, + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE); + g_assert (proxy != NULL); + } + else + { + proxy = dbus_g_proxy_new_for_name_owner (connection, + service_name, + path->str, + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, + error); + if (proxy == NULL) + goto done; + } call = dbus_g_proxy_begin_call (proxy, "Introspect", DBUS_TYPE_INVALID); @@ -231,10 +252,14 @@ load_child_nodes (const char *service_name, complete_child = description_load_from_string (data, -1, error); if (complete_child == NULL) - goto done; + { + g_printerr ("%s\n", data); + goto done; + } done: - dbus_g_pending_call_unref (call); + if (call) + dbus_g_pending_call_unref (call); g_object_unref (proxy); if (complete_child == NULL) @@ -249,8 +274,11 @@ load_child_nodes (const char *service_name, node_info_unref (complete_child); /* ref still held by parent */ /* Now recurse */ - if (!load_child_nodes (service_name, complete_child, error)) + if (!load_child_nodes (service_name, complete_child, path, error)) return FALSE; + + /* restore path */ + g_string_set_size (path, save_len); tmp = tmp->next; } @@ -267,21 +295,36 @@ load_from_service (const char *service_name, DBusGPendingCall *call; const char *data; NodeInfo *node; + GString *path; node = NULL; call = NULL; + path = NULL; connection = dbus_g_bus_get (DBUS_BUS_SESSION, error); if (connection == NULL) return NULL; +#if 1 + /* this will end up autolaunching the service when we introspect it */ + root_proxy = dbus_g_proxy_new_for_name (connection, + service_name, + "/", + DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE); + g_assert (root_proxy != NULL); +#else + /* this will be an error if the service doesn't exist */ root_proxy = dbus_g_proxy_new_for_name_owner (connection, service_name, "/", DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE, error); if (root_proxy == NULL) - return NULL; + { + g_printerr ("Failed to get owner of '%s'\n", service_name); + return NULL; + } +#endif call = dbus_g_proxy_begin_call (root_proxy, "Introspect", DBUS_TYPE_INVALID); @@ -289,7 +332,11 @@ load_from_service (const char *service_name, data = NULL; if (!dbus_g_proxy_end_call (root_proxy, call, error, DBUS_TYPE_STRING, &data, DBUS_TYPE_INVALID)) - goto out; + { + g_printerr ("Failed to Introspect() %s\n", + dbus_g_proxy_get_bus_name (root_proxy)); + goto out; + } node = description_load_from_string (data, -1, error); @@ -299,9 +346,11 @@ load_from_service (const char *service_name, goto out; base_info_set_name ((BaseInfo*)node, "/"); + + path = g_string_new ("/"); if (!load_child_nodes (dbus_g_proxy_get_bus_name (root_proxy), - node, error)) + node, path, error)) { node_info_unref (node); node = NULL; @@ -313,6 +362,10 @@ load_from_service (const char *service_name, dbus_g_pending_call_unref (call); g_object_unref (root_proxy); + + if (path) + g_string_free (path, TRUE); + return node; } -- cgit