From d8abf955f5bff3e83cabd267883039f7a42c98c3 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 8 Jul 2003 05:07:32 +0000 Subject: 2003-07-08 Havoc Pennington * dbus/dbus-object.h: sketch out an API for registering objects with a connection, that allows us to use as little as 24 bytes per object and lets application code represent an object in any conceivable way. * dbus/dbus-object-registry.c: implement the hard bits of the DBusConnection aspect of object API. Not yet wired up. --- dbus/dbus-connection.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 01b2a7bf..237c195b 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -920,6 +920,22 @@ _dbus_connection_handle_watch (DBusWatch *watch, return retval; } +/** + * Get the ID to be used in the high bits of an object ID for an object + * registered with this connection. + * + * @todo implement this function + * + * @param connection the connection. + * @returns the connection portion of the object ID + */ +dbus_uint32_t +_dbus_connection_get_id (DBusConnection *connection) +{ + /* FIXME */ + return 1492; +} + /** @} */ /** -- cgit From 824d4a5edfe1fa7222ab5cb49928bf78a675b563 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 9 Jul 2003 03:41:00 +0000 Subject: 2003-07-08 Havoc Pennington * dbus/dbus-object.c: implement some of this * dbus/dbus-object-registry.c (_dbus_object_registry_add_and_unlock): fill in the object_id out param (_dbus_object_registry_new): handle OOM --- dbus/dbus-connection.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 237c195b..ed29edc9 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2942,6 +2942,51 @@ dbus_connection_unregister_handler (DBusConnection *connection, CONNECTION_UNLOCK (connection); } +/** + * Registers an object with the connection. This object is assigned an + * object ID, and will be visible under this ID and with the provided + * interfaces to the peer application on the other end of the + * connection. The object instance should be passed in as object_impl; + * the instance can be any datatype, as long as it fits in a void*. + * + * As a side effect of calling this function, the "registered" + * callback in the #DBusObjectVTable will be invoked. + * + * @param connection the connection to register the instance with + * @param interfaces #NULL-terminated array of interface names the instance supports + * @param vtable virtual table of functions for manipulating the instance + * @param object_impl object instance + * @param object_id if non-#NULL, object ID to initialize with the new object's ID + * @returns #FALSE if not enough memory to register the object instance + */ +dbus_bool_t +dbus_connection_register_object (DBusConnection *connection, + const char **interfaces, + const DBusObjectVTable *vtable, + void *object_impl, + DBusObjectID *object_id) +{ + + return FALSE; +} + +/** + * Reverses the effects of dbus_connection_register_object(), + * and invokes the "unregistered" callback in the #DBusObjectVTable + * for the given object. The passed-in object ID must be a valid, + * registered object ID or the results are undefined. + * + * @param connection the connection to unregister the object ID from + * @param object_id the object ID to unregister + */ +void +dbus_connection_unregister_object (DBusConnection *connection, + const DBusObjectID *object_id) +{ + + +} + static DBusDataSlotAllocator slot_allocator; _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); -- cgit From f1ee877d76000920e6dbec1b59be1ffab39d2c81 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 12 Jul 2003 19:32:35 +0000 Subject: 2003-07-12 Havoc Pennington * dbus/dbus-object-registry.c: implement unit test, fix bugs discovered in process * dbus/dbus-connection.c: remove handler_table and register_handler(), add DBusObjectRegistry usage * dbus/dbus-objectid.c (dbus_object_id_is_null) (dbus_object_id_set_null): new functions --- dbus/dbus-connection.c | 262 +++++++++---------------------------------------- 1 file changed, 49 insertions(+), 213 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index ed29edc9..104fd41f 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -35,6 +35,7 @@ #include "dbus-threads.h" #include "dbus-protocol.h" #include "dbus-dataslot.h" +#include "dbus-object-registry.h" #if 0 #define CONNECTION_LOCK(connection) do { \ @@ -77,7 +78,7 @@ * you to set a function to be used to monitor the dispatch status. * * If you're using GLib or Qt add-on libraries for D-BUS, there are - * special convenience functions in those libraries that hide + * special convenience APIs in those libraries that hide * all the details of dispatch and watch/timeout monitoring. * For example, dbus_connection_setup_with_g_main(). * @@ -157,7 +158,6 @@ struct DBusConnection DBusWatchList *watches; /**< Stores active watches. */ DBusTimeoutList *timeouts; /**< Stores active timeouts. */ - DBusHashTable *handler_table; /**< Table of registered DBusMessageHandler */ DBusList *filter_list; /**< List of filters. */ DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */ @@ -180,6 +180,7 @@ struct DBusConnection DBusList *link_cache; /**< A cache of linked list links to prevent contention * for the global linked list mempool lock */ + DBusObjectRegistry *objects; /**< Objects registered with this connection */ }; typedef struct @@ -664,7 +665,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) DBusConnection *connection; DBusWatchList *watch_list; DBusTimeoutList *timeout_list; - DBusHashTable *handler_table, *pending_replies; + DBusHashTable *pending_replies; DBusMutex *mutex; DBusCondVar *message_returned_cond; DBusCondVar *dispatch_cond; @@ -672,10 +673,10 @@ _dbus_connection_new_for_transport (DBusTransport *transport) DBusList *disconnect_link; DBusMessage *disconnect_message; DBusCounter *outgoing_counter; + DBusObjectRegistry *objects; watch_list = NULL; connection = NULL; - handler_table = NULL; pending_replies = NULL; timeout_list = NULL; mutex = NULL; @@ -685,6 +686,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) disconnect_link = NULL; disconnect_message = NULL; outgoing_counter = NULL; + objects = NULL; watch_list = _dbus_watch_list_new (); if (watch_list == NULL) @@ -692,13 +694,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) timeout_list = _dbus_timeout_list_new (); if (timeout_list == NULL) - goto error; - - handler_table = - _dbus_hash_table_new (DBUS_HASH_STRING, - dbus_free, NULL); - if (handler_table == NULL) - goto error; + goto error; pending_replies = _dbus_hash_table_new (DBUS_HASH_INT, @@ -737,6 +733,10 @@ _dbus_connection_new_for_transport (DBusTransport *transport) outgoing_counter = _dbus_counter_new (); if (outgoing_counter == NULL) goto error; + + objects = _dbus_object_registry_new (connection); + if (objects == NULL) + goto error; if (_dbus_modify_sigpipe) _dbus_disable_sigpipe (); @@ -749,7 +749,6 @@ _dbus_connection_new_for_transport (DBusTransport *transport) connection->transport = transport; connection->watches = watch_list; connection->timeouts = timeout_list; - connection->handler_table = handler_table; connection->pending_replies = pending_replies; connection->outgoing_counter = outgoing_counter; connection->filter_list = NULL; @@ -790,9 +789,6 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (connection != NULL) dbus_free (connection); - if (handler_table) - _dbus_hash_table_unref (handler_table); - if (pending_replies) _dbus_hash_table_unref (pending_replies); @@ -804,6 +800,9 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (outgoing_counter) _dbus_counter_unref (outgoing_counter); + + if (objects) + _dbus_object_registry_unref (objects); return NULL; } @@ -853,19 +852,9 @@ void _dbus_connection_handler_destroyed_locked (DBusConnection *connection, DBusMessageHandler *handler) { - DBusHashIter iter; DBusList *link; CONNECTION_LOCK (connection); - - _dbus_hash_iter_init (connection->handler_table, &iter); - while (_dbus_hash_iter_next (&iter)) - { - DBusMessageHandler *h = _dbus_hash_iter_get_value (&iter); - - if (h == handler) - _dbus_hash_iter_remove_entry (&iter); - } link = _dbus_list_get_first_link (&connection->filter_list); while (link != NULL) @@ -1035,7 +1024,6 @@ free_outgoing_message (void *element, static void _dbus_connection_last_unref (DBusConnection *connection) { - DBusHashIter iter; DBusList *link; _dbus_verbose ("Finalizing connection %p\n", connection); @@ -1048,6 +1036,8 @@ _dbus_connection_last_unref (DBusConnection *connection) _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ + _dbus_object_registry_free_all_unlocked (connection->objects); + dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); @@ -1061,14 +1051,6 @@ _dbus_connection_last_unref (DBusConnection *connection) _dbus_data_slot_list_free (&connection->slot_list); /* ---- Done with stuff that invokes application callbacks */ - _dbus_hash_iter_init (connection->handler_table, &iter); - while (_dbus_hash_iter_next (&iter)) - { - DBusMessageHandler *h = _dbus_hash_iter_get_value (&iter); - - _dbus_message_handler_remove_connection (h, connection); - } - link = _dbus_list_get_first_link (&connection->filter_list); while (link != NULL) { @@ -1080,8 +1062,7 @@ _dbus_connection_last_unref (DBusConnection *connection) link = next; } - _dbus_hash_table_unref (connection->handler_table); - connection->handler_table = NULL; + _dbus_object_registry_unref (connection->objects); _dbus_hash_table_unref (connection->pending_replies); connection->pending_replies = NULL; @@ -2237,12 +2218,10 @@ dbus_connection_get_dispatch_status (DBusConnection *connection) DBusDispatchStatus dbus_connection_dispatch (DBusConnection *connection) { - DBusMessageHandler *handler; DBusMessage *message; DBusList *link, *filter_list_copy, *message_link; DBusHandlerResult result; ReplyHandlerData *reply_handler_data; - const char *name; dbus_int32_t reply_serial; DBusDispatchStatus status; @@ -2373,30 +2352,19 @@ dbus_connection_dispatch (DBusConnection *connection) CONNECTION_LOCK (connection); goto out; } - - name = dbus_message_get_name (message); - if (name != NULL) - { - handler = _dbus_hash_table_lookup_string (connection->handler_table, - name); - if (handler != NULL) - { - /* We're still protected from dispatch() reentrancy here - * since we acquired the dispatcher - */ - CONNECTION_UNLOCK (connection); - - _dbus_verbose (" running app handler on message %p (%s)\n", - message, dbus_message_get_name (message)); - - result = _dbus_message_handler_handle_message (handler, connection, - message); - CONNECTION_LOCK (connection); - if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) - goto out; - } - } + /* We're still protected from dispatch() reentrancy here + * since we acquired the dispatcher + */ + _dbus_verbose (" running object handler on message %p (%s)\n", + message, dbus_message_get_name (message)); + + result = _dbus_object_registry_handle_and_unlock (connection->objects, + message); + CONNECTION_LOCK (connection); + if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) + goto out; + _dbus_verbose (" done dispatching %p (%s) on connection %p\n", message, dbus_message_get_name (message), connection); @@ -2721,8 +2689,8 @@ dbus_connection_set_unix_user_function (DBusConnection *connection, /** * Adds a message filter. Filters are handlers that are run on - * all incoming messages, prior to the normal handlers - * registered with dbus_connection_register_handler(). + * all incoming messages, prior to the objects + * registered with dbus_connection_register_object(). * Filters are run in the order that they were added. * The same handler can be added as a filter more than once, in * which case it will be run more than once. @@ -2795,153 +2763,6 @@ dbus_connection_remove_filter (DBusConnection *connection, CONNECTION_UNLOCK (connection); } -/** - * Registers a handler for a list of message names. A single handler - * can be registered for any number of message names, but each message - * name can only have one handler at a time. It's not allowed to call - * this function with the name of a message that already has a - * handler. If the function returns #FALSE, the handlers were not - * registered due to lack of memory. - * - * The connection does NOT add a reference to the message handler; - * instead, if the message handler is finalized, the connection simply - * forgets about it. Thus the caller of this function must keep a - * reference to the message handler. - * - * @todo the messages_to_handle arg may be more convenient if it's a - * single string instead of an array. Though right now MessageHandler - * is sort of designed to say be associated with an entire object with - * multiple methods, that's why for example the connection only - * weakrefs it. So maybe the "manual" API should be different. - * - * @param connection the connection - * @param handler the handler - * @param messages_to_handle the messages to handle - * @param n_messages the number of message names in messages_to_handle - * @returns #TRUE on success, #FALSE if no memory or another handler already exists - * - **/ -dbus_bool_t -dbus_connection_register_handler (DBusConnection *connection, - DBusMessageHandler *handler, - const char **messages_to_handle, - int n_messages) -{ - int i; - - _dbus_return_val_if_fail (connection != NULL, FALSE); - _dbus_return_val_if_fail (handler != NULL, FALSE); - _dbus_return_val_if_fail (n_messages >= 0, FALSE); - _dbus_return_val_if_fail (n_messages == 0 || messages_to_handle != NULL, FALSE); - - CONNECTION_LOCK (connection); - i = 0; - while (i < n_messages) - { - DBusHashIter iter; - char *key; - - key = _dbus_strdup (messages_to_handle[i]); - if (key == NULL) - goto failed; - - if (!_dbus_hash_iter_lookup (connection->handler_table, - key, TRUE, - &iter)) - { - dbus_free (key); - goto failed; - } - - if (_dbus_hash_iter_get_value (&iter) != NULL) - { - _dbus_warn ("Bug in application: attempted to register a second handler for %s\n", - messages_to_handle[i]); - dbus_free (key); /* won't have replaced the old key with the new one */ - goto failed; - } - - if (!_dbus_message_handler_add_connection (handler, connection)) - { - _dbus_hash_iter_remove_entry (&iter); - /* key has freed on nuking the entry */ - goto failed; - } - - _dbus_hash_iter_set_value (&iter, handler); - - ++i; - } - - CONNECTION_UNLOCK (connection); - return TRUE; - - failed: - /* unregister everything registered so far, - * so we don't fail partially - */ - dbus_connection_unregister_handler (connection, - handler, - messages_to_handle, - i); - - CONNECTION_UNLOCK (connection); - return FALSE; -} - -/** - * Unregisters a handler for a list of message names. The handlers - * must have been previously registered. - * - * @param connection the connection - * @param handler the handler - * @param messages_to_handle the messages to handle - * @param n_messages the number of message names in messages_to_handle - * - **/ -void -dbus_connection_unregister_handler (DBusConnection *connection, - DBusMessageHandler *handler, - const char **messages_to_handle, - int n_messages) -{ - int i; - - _dbus_return_if_fail (connection != NULL); - _dbus_return_if_fail (handler != NULL); - _dbus_return_if_fail (n_messages >= 0); - _dbus_return_if_fail (n_messages == 0 || messages_to_handle != NULL); - - CONNECTION_LOCK (connection); - i = 0; - while (i < n_messages) - { - DBusHashIter iter; - - if (!_dbus_hash_iter_lookup (connection->handler_table, - (char*) messages_to_handle[i], FALSE, - &iter)) - { - _dbus_warn ("Bug in application: attempted to unregister handler for %s which was not registered\n", - messages_to_handle[i]); - } - else if (_dbus_hash_iter_get_value (&iter) != handler) - { - _dbus_warn ("Bug in application: attempted to unregister handler for %s which was registered by a different handler\n", - messages_to_handle[i]); - } - else - { - _dbus_hash_iter_remove_entry (&iter); - _dbus_message_handler_remove_connection (handler, connection); - } - - ++i; - } - - CONNECTION_UNLOCK (connection); -} - /** * Registers an object with the connection. This object is assigned an * object ID, and will be visible under this ID and with the provided @@ -2951,7 +2772,11 @@ dbus_connection_unregister_handler (DBusConnection *connection, * * As a side effect of calling this function, the "registered" * callback in the #DBusObjectVTable will be invoked. - * + * + * If the object is deleted, be sure to unregister it with + * dbus_connection_unregister_object() or it will continue to get + * messages. + * * @param connection the connection to register the instance with * @param interfaces #NULL-terminated array of interface names the instance supports * @param vtable virtual table of functions for manipulating the instance @@ -2966,8 +2791,15 @@ dbus_connection_register_object (DBusConnection *connection, void *object_impl, DBusObjectID *object_id) { + _dbus_return_val_if_fail (connection != NULL, FALSE); + + CONNECTION_LOCK (connection); - return FALSE; + return _dbus_object_registry_add_and_unlock (connection->objects, + interfaces, + vtable, + object_impl, + object_id); } /** @@ -2983,8 +2815,12 @@ void dbus_connection_unregister_object (DBusConnection *connection, const DBusObjectID *object_id) { - + _dbus_return_if_fail (connection != NULL); + + CONNECTION_LOCK (connection); + return _dbus_object_registry_remove_and_unlock (connection->objects, + object_id); } static DBusDataSlotAllocator slot_allocator; -- cgit From 8b7fe6f99dd35f32443a4e23466c8a1e4cfaa32b Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 17 Jul 2003 01:10:57 +0000 Subject: 2003-07-13 Havoc Pennington * dbus/dbus-object.h (struct DBusObjectVTable): add padding fields to DBusObjectVTable and DBusObjectInfo --- dbus/dbus-connection.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 104fd41f..d604bfcb 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2791,8 +2791,12 @@ dbus_connection_register_object (DBusConnection *connection, void *object_impl, DBusObjectID *object_id) { - _dbus_return_val_if_fail (connection != NULL, FALSE); - + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (vtable != NULL, FALSE); + _dbus_return_val_if_fail (vtable->dbus_internal_pad1 == NULL); + _dbus_return_val_if_fail (vtable->dbus_internal_pad2 == NULL); + _dbus_return_val_if_fail (vtable->dbus_internal_pad3 == NULL); + CONNECTION_LOCK (connection); return _dbus_object_registry_add_and_unlock (connection->objects, -- cgit From fe195a911d86d0a71349988360de65cfac1b3f86 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 2 Aug 2003 01:59:14 +0000 Subject: 2003-08-01 Havoc Pennington * dbus/dbus-protocol.h (DBUS_MESSAGE_TYPE_*): introduce a message type enum to distinguish kinds of message (DBUS_HEADER_FLAG_NO_REPLY_EXPECTED): flag for a message that need not be replied to 2003-08-01 Havoc Pennington * dbus/dbus-marshal.c: adapt to DBusObjectID changes (unpack_8_octets): fix no-64-bit-int bug * dbus/dbus-object-registry.c (validate_id): validate the connection ID bits, not just the instance ID. * dbus/dbus-connection.c (_dbus_connection_init_id): initialize the connection-global 33 bits of the object ID * dbus/dbus-object-registry.c (info_from_entry): fill in object ID in the new way * dbus/dbus-objectid.h: rather than high/low bits, specifically define server/client/instance bits. --- dbus/dbus-connection.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d604bfcb..4b72d600 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -910,19 +910,22 @@ _dbus_connection_handle_watch (DBusWatch *watch, } /** - * Get the ID to be used in the high bits of an object ID for an object + * Get the server ID to be used in the object ID for an object * registered with this connection. * * @todo implement this function * * @param connection the connection. - * @returns the connection portion of the object ID + * @returns the portion of the object ID */ -dbus_uint32_t -_dbus_connection_get_id (DBusConnection *connection) +void +_dbus_connection_init_id (DBusConnection *connection, + DBusObjectID *object_id) { /* FIXME */ - return 1492; + dbus_object_id_set_server_bits (object_id, 15); + dbus_object_id_set_client_bits (object_id, 31); + dbus_object_id_set_is_server_bit (object_id, FALSE); } /** @} */ @@ -2793,9 +2796,9 @@ dbus_connection_register_object (DBusConnection *connection, { _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); - _dbus_return_val_if_fail (vtable->dbus_internal_pad1 == NULL); - _dbus_return_val_if_fail (vtable->dbus_internal_pad2 == NULL); - _dbus_return_val_if_fail (vtable->dbus_internal_pad3 == NULL); + _dbus_return_val_if_fail (vtable->dbus_internal_pad1 == NULL, FALSE); + _dbus_return_val_if_fail (vtable->dbus_internal_pad2 == NULL, FALSE); + _dbus_return_val_if_fail (vtable->dbus_internal_pad3 == NULL, FALSE); CONNECTION_LOCK (connection); -- cgit From 9c5d01f0fe1ba855c0f7518c4f27d75a609b8faa Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 2 Aug 2003 03:39:35 +0000 Subject: 2003-08-01 Havoc Pennington * dbus/dbus-object-registry.c (_dbus_object_registry_handle_and_unlock): implement * dbus/dbus-message.c (dbus_message_get_type): new function * doc/dbus-specification.sgml: add "type" byte to messages --- dbus/dbus-connection.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 4b72d600..ced50bd1 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -722,7 +722,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (io_path_cond == NULL) goto error; - disconnect_message = dbus_message_new (DBUS_MESSAGE_LOCAL_DISCONNECT, NULL); + disconnect_message = dbus_message_new_signal (DBUS_MESSAGE_LOCAL_DISCONNECT); if (disconnect_message == NULL) goto error; @@ -1615,8 +1615,8 @@ dbus_connection_send_with_reply (DBusConnection *connection, dbus_message_handler_ref (reply_handler); - reply = dbus_message_new_error_reply (message, DBUS_ERROR_NO_REPLY, - "No reply within specified time"); + reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY, + "No reply within specified time"); if (!reply) { CONNECTION_UNLOCK (connection); -- cgit From cefb84edc5f84011c5a171e5d052e37c56c55d27 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 7 Aug 2003 02:18:54 +0000 Subject: 2003-08-06 Havoc Pennington * dbus/dbus-object-registry.c: implement signal connection and dispatch * dbus/dbus-connection.c (_dbus_connection_unref_unlocked): new * dbus/dbus-internals.c (_dbus_memdup): new function --- dbus/dbus-connection.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index ced50bd1..407b4d24 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -203,7 +203,7 @@ static void _dbus_connection_remove_timeout_locked (DB static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, DBusDispatchStatus new_status); - +static void _dbus_connection_last_unref (DBusConnection *connection); /** @@ -824,6 +824,39 @@ _dbus_connection_ref_unlocked (DBusConnection *connection) #endif } +/** + * Decrements the reference count of a DBusConnection. + * Requires that the caller already holds the connection lock. + * + * @param connection the connection. + */ +void +_dbus_connection_unref_unlocked (DBusConnection *connection) +{ + dbus_bool_t last_unref; + + _dbus_return_if_fail (connection != NULL); + + /* The connection lock is better than the global + * lock in the atomic increment fallback + */ + +#ifdef DBUS_HAVE_ATOMIC_INT + last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); +#else + _dbus_assert (connection->refcount.value > 0); + + connection->refcount.value -= 1; + last_unref = (connection->refcount.value == 0); +#if 0 + printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value); +#endif +#endif + + if (last_unref) + _dbus_connection_last_unref (connection); +} + static dbus_uint32_t _dbus_connection_get_next_client_serial (DBusConnection *connection) { @@ -2215,6 +2248,8 @@ dbus_connection_get_dispatch_status (DBusConnection *connection) * does not necessarily dispatch a message, as the data may * be part of authentication or the like. * + * @todo some FIXME in here about handling DBUS_HANDLER_RESULT_NEED_MEMORY + * * @param connection the connection * @returns dispatch status */ @@ -2310,7 +2345,7 @@ dbus_connection_dispatch (DBusConnection *connection) result = _dbus_message_handler_handle_message (handler, connection, message); - if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) + if (result != DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS) break; link = next; @@ -2323,6 +2358,9 @@ dbus_connection_dispatch (DBusConnection *connection) CONNECTION_LOCK (connection); + if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) + /* FIXME */ ; + /* Did a reply we were waiting on get filtered? */ if (reply_handler_data && result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) { @@ -2342,7 +2380,7 @@ dbus_connection_dispatch (DBusConnection *connection) if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) goto out; - + if (reply_handler_data) { CONNECTION_UNLOCK (connection); @@ -2364,9 +2402,13 @@ dbus_connection_dispatch (DBusConnection *connection) result = _dbus_object_registry_handle_and_unlock (connection->objects, message); + CONNECTION_LOCK (connection); if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) goto out; + + if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) + /* FIXME */ ; _dbus_verbose (" done dispatching %p (%s) on connection %p\n", message, dbus_message_get_name (message), connection); -- cgit From b29ea9115ea3277354b7ccbe442026279220f4ac Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 11 Aug 2003 02:11:58 +0000 Subject: 2003-08-10 Havoc Pennington * tools/dbus-send.c (main): add --type argument, for now supporting only method_call and signal types. * tools/dbus-print-message.c: print message type * dbus/dbus-connection.c (_dbus_connection_new_for_transport): init connection->objects * doc/dbus-specification.sgml: fix sgml * bus/*.c: port over to object-instance API changes * test/test-service.c: ditto * dbus/dbus-message.c (dbus_message_create_header): allow #NULL name, we will have to fix up the rest of the code to also handle this (dbus_message_new): generic message-creation call (set_string_field): allow appending name field --- dbus/dbus-connection.c | 1 + 1 file changed, 1 insertion(+) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 407b4d24..d30ccb0a 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -753,6 +753,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) connection->outgoing_counter = outgoing_counter; connection->filter_list = NULL; connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ + connection->objects = objects; _dbus_data_slot_list_init (&connection->slot_list); -- cgit From 5c1a8e44903bd1dedc8cbefad78b0c8b61daada5 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 12 Aug 2003 02:43:50 +0000 Subject: 2003-08-11 Havoc Pennington * bus/test.c (client_disconnect_handler): change to return HANDLED (would have been REMOVE_MESSAGE) * dbus/dbus-object.h (enum DBusHandlerResult): rename to HANDLED/NOT_YET_HANDLED instead of REMOVE_MESSAGE/ALLOW_MORE_HANDLERS to make it clearer how it should be used. --- dbus/dbus-connection.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d30ccb0a..17563f35 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2306,7 +2306,7 @@ dbus_connection_dispatch (DBusConnection *connection) message = message_link->data; - result = DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; reply_serial = dbus_message_get_reply_serial (message); reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies, @@ -2346,7 +2346,7 @@ dbus_connection_dispatch (DBusConnection *connection) result = _dbus_message_handler_handle_message (handler, connection, message); - if (result != DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS) + if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) break; link = next; @@ -2363,7 +2363,7 @@ dbus_connection_dispatch (DBusConnection *connection) /* FIXME */ ; /* Did a reply we were waiting on get filtered? */ - if (reply_handler_data && result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) + if (reply_handler_data && result == DBUS_HANDLER_RESULT_HANDLED) { /* Queue the timeout immediately! */ if (reply_handler_data->timeout_link) @@ -2379,7 +2379,7 @@ dbus_connection_dispatch (DBusConnection *connection) } } - if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) + if (result == DBUS_HANDLER_RESULT_HANDLED) goto out; if (reply_handler_data) @@ -2405,7 +2405,7 @@ dbus_connection_dispatch (DBusConnection *connection) message); CONNECTION_LOCK (connection); - if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) + if (result == DBUS_HANDLER_RESULT_HANDLED) goto out; if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) -- cgit From 1d1b0f20a467cf1cbdcaf81fbad3a111bcff6c48 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 12 Aug 2003 04:15:49 +0000 Subject: 2003-08-12 Havoc Pennington * bus/dispatch.c (bus_dispatch): make this return proper DBusHandlerResult to avoid DBUS_ERROR_UNKNOWN_METHOD * dbus/dbus-errors.c (dbus_set_error): use _dbus_string_append_printf_valist * dbus/dbus-string.c (_dbus_string_append_printf_valist) (_dbus_string_append_printf): new * dbus/dbus-errors.h (DBUS_ERROR_UNKNOWN_MESSAGE): change to UNKNOWN_METHOD * dbus/dbus-connection.c (dbus_connection_dispatch): handle DBUS_HANDLER_RESULT_NEED_MEMORY; send default error reply if a message is unhandled. --- dbus/dbus-connection.c | 103 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 9 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 17563f35..ba5601e3 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -36,6 +36,7 @@ #include "dbus-protocol.h" #include "dbus-dataslot.h" #include "dbus-object-registry.h" +#include "dbus-string.h" #if 0 #define CONNECTION_LOCK(connection) do { \ @@ -1942,6 +1943,8 @@ dbus_connection_borrow_message (DBusConnection *connection) DBusDispatchStatus status; _dbus_return_val_if_fail (connection != NULL, NULL); + /* can't borrow during dispatch */ + _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL); /* this is called for the side effect that it queues * up any messages from the transport @@ -1977,6 +1980,8 @@ dbus_connection_return_message (DBusConnection *connection, { _dbus_return_if_fail (connection != NULL); _dbus_return_if_fail (message != NULL); + /* can't borrow during dispatch */ + _dbus_return_if_fail (!connection->dispatch_acquired); CONNECTION_LOCK (connection); @@ -2005,6 +2010,8 @@ dbus_connection_steal_borrowed_message (DBusConnection *connection, _dbus_return_if_fail (connection != NULL); _dbus_return_if_fail (message != NULL); + /* can't borrow during dispatch */ + _dbus_return_if_fail (!connection->dispatch_acquired); CONNECTION_LOCK (connection); @@ -2074,6 +2081,22 @@ _dbus_connection_pop_message_unlocked (DBusConnection *connection) return NULL; } +static void +_dbus_connection_putback_message_link_unlocked (DBusConnection *connection, + DBusList *message_link) +{ + _dbus_assert (message_link != NULL); + /* You can't borrow a message while a link is outstanding */ + _dbus_assert (connection->message_borrowed == NULL); + + _dbus_list_prepend_link (&connection->incoming_messages, + message_link); + connection->n_incoming += 1; + + _dbus_verbose ("Message %p (%s) put back into queue %p, %d incoming\n", + message_link->data, dbus_message_get_name (message_link->data), + connection, connection->n_incoming); +} /** * Returns the first-received message from the incoming message queue, @@ -2360,7 +2383,7 @@ dbus_connection_dispatch (DBusConnection *connection) CONNECTION_LOCK (connection); if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) - /* FIXME */ ; + goto out; /* Did a reply we were waiting on get filtered? */ if (reply_handler_data && result == DBUS_HANDLER_RESULT_HANDLED) @@ -2405,22 +2428,84 @@ dbus_connection_dispatch (DBusConnection *connection) message); CONNECTION_LOCK (connection); - if (result == DBUS_HANDLER_RESULT_HANDLED) + + if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) goto out; - if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) - /* FIXME */ ; + if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) + { + DBusMessage *reply; + DBusString str; + DBusPreallocatedSend *preallocated; + + _dbus_verbose (" sending error %s\n", + DBUS_ERROR_UNKNOWN_METHOD); + + if (!_dbus_string_init (&str)) + { + result = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto out; + } + + if (!_dbus_string_append_printf (&str, + "Method \"%s\" doesn't exist\n", + dbus_message_get_name (message))) + { + _dbus_string_free (&str); + result = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto out; + } + + reply = dbus_message_new_error (message, + DBUS_ERROR_UNKNOWN_METHOD, + _dbus_string_get_const_data (&str)); + _dbus_string_free (&str); + + if (reply == NULL) + { + result = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto out; + } + + preallocated = _dbus_connection_preallocate_send_unlocked (connection); + + if (preallocated == NULL) + { + dbus_message_unref (reply); + result = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto out; + } + + _dbus_connection_send_preallocated_unlocked (connection, preallocated, + reply, NULL); + + dbus_message_unref (reply); + + result = DBUS_HANDLER_RESULT_HANDLED; + } _dbus_verbose (" done dispatching %p (%s) on connection %p\n", message, dbus_message_get_name (message), connection); out: + if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) + { + /* Put message back, and we'll start over. + * Yes this means handlers must be idempotent if they + * don't return HANDLED; c'est la vie. + */ + _dbus_connection_putback_message_link_unlocked (connection, + message_link); + } + else + { + _dbus_list_free_link (message_link); + dbus_message_unref (message); /* don't want the message to count in max message limits + * in computing dispatch status below + */ + } + _dbus_connection_release_dispatch (connection); - - _dbus_list_free_link (message_link); - dbus_message_unref (message); /* don't want the message to count in max message limits - * in computing dispatch status - */ status = _dbus_connection_get_dispatch_status_unlocked (connection); -- cgit From ef614207fc4f03e5cc02faeb109f739eb1ccdf31 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 15 Aug 2003 04:17:58 +0000 Subject: 2003-08-15 Havoc Pennington * dbus/dbus-connection.c, dbus/dbus-pending-call.c: Finish the pending call stuff --- dbus/dbus-connection.c | 364 +++++++++++++++++++++++++++---------------------- 1 file changed, 200 insertions(+), 164 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index ba5601e3..3af00ed0 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -37,6 +37,7 @@ #include "dbus-dataslot.h" #include "dbus-object-registry.h" #include "dbus-string.h" +#include "dbus-pending-call.h" #if 0 #define CONNECTION_LOCK(connection) do { \ @@ -124,9 +125,6 @@ * @{ */ -/** default timeout value when waiting for a message reply */ -#define DEFAULT_TIMEOUT_VALUE (15 * 1000) - static dbus_bool_t _dbus_modify_sigpipe = TRUE; /** @@ -163,7 +161,7 @@ struct DBusConnection DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */ - DBusHashTable *pending_replies; /**< Hash of message serials and their message handlers. */ + DBusHashTable *pending_replies; /**< Hash of message serials to #DBusPendingCall. */ dbus_uint32_t client_serial; /**< Client serial. Increments each time a message is sent */ DBusList *disconnect_message_link; /**< Preallocated list node for queueing the disconnection message */ @@ -184,21 +182,6 @@ struct DBusConnection DBusObjectRegistry *objects; /**< Objects registered with this connection */ }; -typedef struct -{ - DBusConnection *connection; - DBusMessageHandler *handler; - DBusTimeout *timeout; - int serial; - - DBusList *timeout_link; /* Preallocated timeout response */ - - dbus_bool_t timeout_added; - dbus_bool_t connection_added; -} ReplyHandlerData; - -static void reply_handler_data_free (ReplyHandlerData *data); - static void _dbus_connection_remove_timeout_locked (DBusConnection *connection, DBusTimeout *timeout); static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); @@ -283,7 +266,7 @@ void _dbus_connection_queue_received_message_link (DBusConnection *connection, DBusList *link) { - ReplyHandlerData *reply_handler_data; + DBusPendingCall *pending; dbus_int32_t reply_serial; DBusMessage *message; @@ -297,14 +280,15 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, reply_serial = dbus_message_get_reply_serial (message); if (reply_serial != -1) { - reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies, - reply_serial); - if (reply_handler_data != NULL) + pending = _dbus_hash_table_lookup_int (connection->pending_replies, + reply_serial); + if (pending != NULL) { - if (reply_handler_data->timeout_added) + if (pending->timeout_added) _dbus_connection_remove_timeout_locked (connection, - reply_handler_data->timeout); - reply_handler_data->timeout_added = FALSE; + pending->timeout); + + pending->timeout_added = FALSE; } } @@ -555,6 +539,86 @@ _dbus_connection_notify_disconnected (DBusConnection *connection) } } +static dbus_bool_t +_dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, + DBusPendingCall *pending) +{ + _dbus_assert (pending->reply_serial != 0); + + if (!_dbus_connection_add_timeout (connection, pending->timeout)) + return FALSE; + + if (!_dbus_hash_table_insert_int (connection->pending_replies, + pending->reply_serial, + pending)) + { + _dbus_connection_remove_timeout (connection, pending->timeout); + return FALSE; + } + + pending->timeout_added = TRUE; + pending->connection = connection; + + dbus_pending_call_ref (pending); + + return TRUE; +} + +static void +free_pending_call_on_hash_removal (void *data) +{ + DBusPendingCall *pending; + + if (data == NULL) + return; + + pending = data; + + if (pending->connection) + { + if (pending->timeout_added) + { + _dbus_connection_remove_timeout (pending->connection, + pending->timeout); + pending->timeout_added = FALSE; + } + + pending->connection = NULL; + + dbus_pending_call_unref (pending); + } +} + +static void +_dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, + DBusPendingCall *pending) +{ + /* The idea here is to avoid finalizing the pending call + * with the lock held, since there's a destroy notifier + * in pending call that goes out to application code. + */ + dbus_pending_call_ref (pending); + _dbus_hash_table_remove_int (connection->pending_replies, + pending->reply_serial); + CONNECTION_UNLOCK (connection); + dbus_pending_call_unref (pending); +} + +/** + * Removes a pending call from the connection, such that + * the pending reply will be ignored. May drop the last + * reference to the pending call. + * + * @param connection the connection + * @param pending the pending call + */ +void +_dbus_connection_remove_pending_call (DBusConnection *connection, + DBusPendingCall *pending) +{ + CONNECTION_LOCK (connection); + _dbus_connection_detach_pending_call_and_unlock (connection, pending); +} /** * Acquire the transporter I/O path. This must be done before @@ -699,7 +763,8 @@ _dbus_connection_new_for_transport (DBusTransport *transport) pending_replies = _dbus_hash_table_new (DBUS_HASH_INT, - NULL, (DBusFreeFunction)reply_handler_data_free); + NULL, + (DBusFreeFunction)free_pending_call_on_hash_removal); if (pending_replies == NULL) goto error; @@ -1442,6 +1507,28 @@ dbus_connection_send_preallocated (DBusConnection *connection, CONNECTION_UNLOCK (connection); } +static dbus_bool_t +_dbus_connection_send_unlocked (DBusConnection *connection, + DBusMessage *message, + dbus_uint32_t *client_serial) +{ + DBusPreallocatedSend *preallocated; + + _dbus_assert (connection != NULL); + _dbus_assert (message != NULL); + + preallocated = _dbus_connection_preallocate_send_unlocked (connection); + if (preallocated == NULL) + return FALSE; + + + _dbus_connection_send_preallocated_unlocked (connection, + preallocated, + message, + client_serial); + return TRUE; +} + /** * Adds a message to the outgoing message queue. Does not block to * write the message to the network; that happens asynchronously. To @@ -1465,50 +1552,41 @@ dbus_connection_send (DBusConnection *connection, DBusMessage *message, dbus_uint32_t *client_serial) { - DBusPreallocatedSend *preallocated; - _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (message != NULL, FALSE); CONNECTION_LOCK (connection); - - preallocated = _dbus_connection_preallocate_send_unlocked (connection); - if (preallocated == NULL) + + if (!_dbus_connection_send_unlocked (connection, message, client_serial)) { CONNECTION_UNLOCK (connection); return FALSE; } - else - { - _dbus_connection_send_preallocated_unlocked (connection, - preallocated, - message, - client_serial); - CONNECTION_UNLOCK (connection); - return TRUE; - } + + CONNECTION_UNLOCK (connection); + return TRUE; } static dbus_bool_t reply_handler_timeout (void *data) { DBusConnection *connection; - ReplyHandlerData *reply_handler_data = data; DBusDispatchStatus status; + DBusPendingCall *pending = data; - connection = reply_handler_data->connection; + connection = pending->connection; CONNECTION_LOCK (connection); - if (reply_handler_data->timeout_link) + if (pending->timeout_link) { _dbus_connection_queue_synthesized_message_link (connection, - reply_handler_data->timeout_link); - reply_handler_data->timeout_link = NULL; + pending->timeout_link); + pending->timeout_link = NULL; } _dbus_connection_remove_timeout (connection, - reply_handler_data->timeout); - reply_handler_data->timeout_added = FALSE; + pending->timeout); + pending->timeout_added = FALSE; status = _dbus_connection_get_dispatch_status_unlocked (connection); @@ -1518,52 +1596,29 @@ reply_handler_timeout (void *data) return TRUE; } -static void -reply_handler_data_free (ReplyHandlerData *data) -{ - if (!data) - return; - - if (data->timeout_added) - _dbus_connection_remove_timeout_locked (data->connection, - data->timeout); - - if (data->connection_added) - _dbus_message_handler_remove_connection (data->handler, - data->connection); - - if (data->timeout_link) - { - dbus_message_unref ((DBusMessage *)data->timeout_link->data); - _dbus_list_free_link (data->timeout_link); - } - - dbus_message_handler_unref (data->handler); - - dbus_free (data); -} - /** * Queues a message to send, as with dbus_connection_send_message(), - * but also sets up a DBusMessageHandler to receive a reply to the + * but also returns a #DBusPendingCall used to receive a reply to the * message. If no reply is received in the given timeout_milliseconds, - * expires the pending reply and sends the DBusMessageHandler a - * synthetic error reply (generated in-process, not by the remote - * application) indicating that a timeout occurred. - * - * Reply handlers see their replies after message filters see them, - * but before message handlers added with - * dbus_connection_register_handler() see them, regardless of the - * reply message's name. Reply handlers are only handed a single - * message as a reply, after one reply has been seen the handler is - * removed. If a filter filters out the reply before the handler sees - * it, the reply is immediately timed out and a timeout error reply is + * this function expires the pending reply and generates a synthetic + * error reply (generated in-process, not by the remote application) + * indicating that a timeout occurred. + * + * A #DBusPendingCall will see a reply message after any filters, but + * before any object instances or other handlers. A #DBusPendingCall + * will always see exactly one reply message, unless it's cancelled + * with dbus_pending_call_cancel(). + * + * If a filter filters out the reply before the handler sees it, the + * reply is immediately timed out and a timeout error reply is * generated. If a filter removes the timeout error reply then the - * reply handler will never be called. Filters should not do this. + * #DBusPendingCall will get confused. Filtering the timeout error + * is thus considered a bug and will print a warning. * - * If #NULL is passed for the reply_handler, the timeout reply will - * still be generated and placed into the message queue, but no - * specific message handler will receive the reply. + * If #NULL is passed for the pending_return, the #DBusPendingCall + * will still be generated internally, and used to track + * the message reply timeout. This means a timeout error will + * occur if no reply arrives, unlike with dbus_connection_send(). * * If -1 is passed for the timeout, a sane default timeout is used. -1 * is typically the best value for the timeout for this reason, unless @@ -1573,7 +1628,7 @@ reply_handler_data_free (ReplyHandlerData *data) * * @param connection the connection * @param message the message to send - * @param reply_handler message handler expecting the reply, or #NULL + * @param pending_return return location for a #DBusPendingCall object, or #NULL * @param timeout_milliseconds timeout in milliseconds or -1 for default * @returns #TRUE if the message is successfully queued, #FALSE if no memory. * @@ -1581,63 +1636,30 @@ reply_handler_data_free (ReplyHandlerData *data) dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection, DBusMessage *message, - DBusMessageHandler *reply_handler, + DBusPendingCall **pending_return, int timeout_milliseconds) { - DBusTimeout *timeout; - ReplyHandlerData *data; + DBusPendingCall *pending; DBusMessage *reply; DBusList *reply_link; dbus_int32_t serial = -1; _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (message != NULL, FALSE); - _dbus_return_val_if_fail (reply_handler != NULL, FALSE); _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); - - if (timeout_milliseconds == -1) - timeout_milliseconds = DEFAULT_TIMEOUT_VALUE; - data = dbus_new0 (ReplyHandlerData, 1); - - if (!data) - return FALSE; + if (pending_return) + *pending_return = NULL; - timeout = _dbus_timeout_new (timeout_milliseconds, reply_handler_timeout, - data, NULL); + pending = _dbus_pending_call_new (connection, + timeout_milliseconds, + reply_handler_timeout); - if (!timeout) - { - reply_handler_data_free (data); - return FALSE; - } + if (pending == NULL) + return FALSE; CONNECTION_LOCK (connection); - /* Add timeout */ - if (!_dbus_connection_add_timeout (connection, timeout)) - { - reply_handler_data_free (data); - _dbus_timeout_unref (timeout); - CONNECTION_UNLOCK (connection); - return FALSE; - } - - /* The connection now owns the reference to the timeout. */ - _dbus_timeout_unref (timeout); - - data->timeout_added = TRUE; - data->timeout = timeout; - data->connection = connection; - - if (!_dbus_message_handler_add_connection (reply_handler, connection)) - { - CONNECTION_UNLOCK (connection); - reply_handler_data_free (data); - return FALSE; - } - data->connection_added = TRUE; - /* Assign a serial to the message */ if (dbus_message_get_serial (message) == 0) { @@ -1645,17 +1667,14 @@ dbus_connection_send_with_reply (DBusConnection *connection, _dbus_message_set_serial (message, serial); } - data->handler = reply_handler; - data->serial = serial; - - dbus_message_handler_ref (reply_handler); + pending->reply_serial = serial; reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY, "No reply within specified time"); if (!reply) { CONNECTION_UNLOCK (connection); - reply_handler_data_free (data); + dbus_pending_call_unref (pending); return FALSE; } @@ -1664,33 +1683,42 @@ dbus_connection_send_with_reply (DBusConnection *connection, { CONNECTION_UNLOCK (connection); dbus_message_unref (reply); - reply_handler_data_free (data); + dbus_pending_call_unref (pending); return FALSE; } - data->timeout_link = reply_link; - - /* Insert the serial in the pending replies hash. */ - if (!_dbus_hash_table_insert_int (connection->pending_replies, serial, data)) + pending->timeout_link = reply_link; + + /* Insert the serial in the pending replies hash; + * hash takes a refcount on DBusPendingCall. + * Also, add the timeout. + */ + if (!_dbus_connection_attach_pending_call_unlocked (connection, + pending)) { CONNECTION_UNLOCK (connection); - reply_handler_data_free (data); + dbus_pending_call_unref (pending); return FALSE; } - - CONNECTION_UNLOCK (connection); - if (!dbus_connection_send (connection, message, NULL)) + if (!_dbus_connection_send_unlocked (connection, message, NULL)) { - /* This will free the handler data too */ - _dbus_hash_table_remove_int (connection->pending_replies, serial); + _dbus_connection_detach_pending_call_and_unlock (connection, + pending); return FALSE; } + if (pending_return) + { + dbus_pending_call_ref (pending); + *pending_return = pending; + } + + CONNECTION_UNLOCK (connection); + return TRUE; } - static DBusMessage* check_for_reply_unlocked (DBusConnection *connection, dbus_uint32_t client_serial) @@ -1755,7 +1783,7 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection, _dbus_return_val_if_error_is_set (error, NULL); if (timeout_milliseconds == -1) - timeout_milliseconds = DEFAULT_TIMEOUT_VALUE; + timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; /* it would probably seem logical to pass in _DBUS_INT_MAX * for infinite timeout, but then math below would get @@ -2283,7 +2311,7 @@ dbus_connection_dispatch (DBusConnection *connection) DBusMessage *message; DBusList *link, *filter_list_copy, *message_link; DBusHandlerResult result; - ReplyHandlerData *reply_handler_data; + DBusPendingCall *pending; dbus_int32_t reply_serial; DBusDispatchStatus status; @@ -2332,8 +2360,8 @@ dbus_connection_dispatch (DBusConnection *connection) result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; reply_serial = dbus_message_get_reply_serial (message); - reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies, - reply_serial); + pending = _dbus_hash_table_lookup_int (connection->pending_replies, + reply_serial); if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) { @@ -2386,34 +2414,42 @@ dbus_connection_dispatch (DBusConnection *connection) goto out; /* Did a reply we were waiting on get filtered? */ - if (reply_handler_data && result == DBUS_HANDLER_RESULT_HANDLED) + if (pending && result == DBUS_HANDLER_RESULT_HANDLED) { /* Queue the timeout immediately! */ - if (reply_handler_data->timeout_link) + if (pending->timeout_link) { _dbus_connection_queue_synthesized_message_link (connection, - reply_handler_data->timeout_link); - reply_handler_data->timeout_link = NULL; + pending->timeout_link); + pending->timeout_link = NULL; } else { /* We already queued the timeout? Then it was filtered! */ - _dbus_warn ("The timeout error with reply serial %d was filtered, so the reply handler will never be called.\n", reply_serial); + _dbus_warn ("The timeout error with reply serial %d was filtered, so the DBusPendingCall will never stop pending.\n", reply_serial); } } if (result == DBUS_HANDLER_RESULT_HANDLED) goto out; - if (reply_handler_data) + if (pending) { - CONNECTION_UNLOCK (connection); + _dbus_verbose (" handing message %p to pending call\n", message); + + _dbus_assert (pending->reply == NULL); + pending->reply = message; + dbus_message_ref (pending->reply); + + dbus_pending_call_ref (pending); /* in case there's no app with a ref held */ + _dbus_connection_detach_pending_call_and_unlock (connection, pending); + + /* Must be called unlocked since it invokes app callback */ + _dbus_pending_call_notify (pending); + dbus_pending_call_unref (pending); - _dbus_verbose (" running reply handler on message %p\n", message); + pending = NULL; - result = _dbus_message_handler_handle_message (reply_handler_data->handler, - connection, message); - reply_handler_data_free (reply_handler_data); CONNECTION_LOCK (connection); goto out; } -- cgit From a1b0bd33408f03894987ac32b4e6b46c6a15a594 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 15 Aug 2003 23:10:12 +0000 Subject: 2003-08-15 Havoc Pennington * dbus/dbus-pending-call.c (dbus_pending_call_block): implement * dbus/dbus-connection.c (dbus_connection_send_with_reply_and_block): factor out internals; change to convert any error replies to DBusError instead of returning them as a message --- dbus/dbus-connection.c | 161 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 115 insertions(+), 46 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 3af00ed0..bc26a3ec 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -620,6 +620,38 @@ _dbus_connection_remove_pending_call (DBusConnection *connection, _dbus_connection_detach_pending_call_and_unlock (connection, pending); } +/** + * Completes a pending call with the given message, + * or if the message is #NULL, by timing out the pending call. + * + * @param pending the pending call + * @param message the message to complete the call with, or #NULL + * to time out the call + */ +void +_dbus_pending_call_complete_and_unlock (DBusPendingCall *pending, + DBusMessage *message) +{ + if (message == NULL) + { + message = pending->timeout_link->data; + _dbus_list_clear (&pending->timeout_link); + } + + _dbus_verbose (" handing message %p to pending call\n", message); + + _dbus_assert (pending->reply == NULL); + pending->reply = message; + dbus_message_ref (pending->reply); + + dbus_pending_call_ref (pending); /* in case there's no app with a ref held */ + _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending); + + /* Must be called unlocked since it invokes app callback */ + _dbus_pending_call_notify (pending); + dbus_pending_call_unref (pending); +} + /** * Acquire the transporter I/O path. This must be done before * doing any I/O in the transporter. May sleep and drop the @@ -1745,42 +1777,31 @@ check_for_reply_unlocked (DBusConnection *connection, } /** - * Sends a message and blocks a certain time period while waiting for a reply. - * This function does not dispatch any message handlers until the main loop - * has been reached. This function is used to do non-reentrant "method calls." - * If a reply is received, it is returned, and removed from the incoming - * message queue. If it is not received, #NULL is returned and the - * error is set to #DBUS_ERROR_NO_REPLY. If something else goes - * wrong, result is set to whatever is appropriate, such as - * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED. + * Blocks a certain time period while waiting for a reply. + * If no reply arrives, returns #NULL. * * @todo could use performance improvements (it keeps scanning * the whole message queue for example) and has thread issues, * see comments in source * * @param connection the connection - * @param message the message to send + * @param client_serial the reply serial to wait for * @param timeout_milliseconds timeout in milliseconds or -1 for default - * @param error return location for error message - * @returns the message that is the reply or #NULL with an error code if the - * function fails. + * @returns the message that is the reply or #NULL if no reply */ -DBusMessage * -dbus_connection_send_with_reply_and_block (DBusConnection *connection, - DBusMessage *message, - int timeout_milliseconds, - DBusError *error) +DBusMessage* +_dbus_connection_block_for_reply (DBusConnection *connection, + dbus_uint32_t client_serial, + int timeout_milliseconds) { - dbus_uint32_t client_serial; long start_tv_sec, start_tv_usec; long end_tv_sec, end_tv_usec; long tv_sec, tv_usec; DBusDispatchStatus status; _dbus_return_val_if_fail (connection != NULL, NULL); - _dbus_return_val_if_fail (message != NULL, NULL); - _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); - _dbus_return_val_if_error_is_set (error, NULL); + _dbus_return_val_if_fail (client_serial != 0, NULL); + _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); if (timeout_milliseconds == -1) timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; @@ -1792,14 +1813,6 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection, if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6) timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6; - if (!dbus_connection_send (connection, message, &client_serial)) - { - _DBUS_SET_OOM (error); - return NULL; - } - - message = NULL; - /* Flush message queue */ dbus_connection_flush (connection); @@ -1894,11 +1907,6 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection, _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n", (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000); - - if (dbus_connection_get_is_connected (connection)) - dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply"); - else - dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply"); /* unlocks and calls out to user code */ _dbus_connection_update_dispatch_status_and_unlock (connection, status); @@ -1906,6 +1914,70 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection, return NULL; } +/** + * Sends a message and blocks a certain time period while waiting for + * a reply. This function does not reenter the main loop, + * i.e. messages other than the reply are queued up but not + * processed. This function is used to do non-reentrant "method + * calls." + * + * If a normal reply is received, it is returned, and removed from the + * incoming message queue. If it is not received, #NULL is returned + * and the error is set to #DBUS_ERROR_NO_REPLY. If an error reply is + * received, it is converted to a #DBusError and returned as an error, + * then the reply message is deleted. If something else goes wrong, + * result is set to whatever is appropriate, such as + * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED. + * + * @param connection the connection + * @param message the message to send + * @param timeout_milliseconds timeout in milliseconds or -1 for default + * @param error return location for error message + * @returns the message that is the reply or #NULL with an error code if the + * function fails. + */ +DBusMessage * +dbus_connection_send_with_reply_and_block (DBusConnection *connection, + DBusMessage *message, + int timeout_milliseconds, + DBusError *error) +{ + dbus_uint32_t client_serial; + DBusMessage *reply; + + _dbus_return_val_if_fail (connection != NULL, NULL); + _dbus_return_val_if_fail (message != NULL, NULL); + _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); + _dbus_return_val_if_error_is_set (error, NULL); + + if (!dbus_connection_send (connection, message, &client_serial)) + { + _DBUS_SET_OOM (error); + return NULL; + } + + reply = _dbus_connection_block_for_reply (connection, + client_serial, + timeout_milliseconds); + + if (reply == NULL) + { + if (dbus_connection_get_is_connected (connection)) + dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply"); + else + dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply"); + + return NULL; + } + else if (dbus_set_error_from_message (error, reply)) + { + dbus_message_unref (reply); + return NULL; + } + else + return reply; +} + /** * Blocks until the outgoing message queue is empty. * @@ -2301,6 +2373,10 @@ dbus_connection_get_dispatch_status (DBusConnection *connection) * be part of authentication or the like. * * @todo some FIXME in here about handling DBUS_HANDLER_RESULT_NEED_MEMORY + * + * @todo right now a message filter gets run on replies to a pending + * call in here, but not in the case where we block without + * entering the main loop. * * @param connection the connection * @returns dispatch status @@ -2435,18 +2511,7 @@ dbus_connection_dispatch (DBusConnection *connection) if (pending) { - _dbus_verbose (" handing message %p to pending call\n", message); - - _dbus_assert (pending->reply == NULL); - pending->reply = message; - dbus_message_ref (pending->reply); - - dbus_pending_call_ref (pending); /* in case there's no app with a ref held */ - _dbus_connection_detach_pending_call_and_unlock (connection, pending); - - /* Must be called unlocked since it invokes app callback */ - _dbus_pending_call_notify (pending); - dbus_pending_call_unref (pending); + _dbus_pending_call_complete_and_unlock (pending, message); pending = NULL; @@ -2869,6 +2934,10 @@ dbus_connection_set_unix_user_function (DBusConnection *connection, * forgets about it. Thus the caller of this function must keep a * reference to the message handler. * + * @todo we don't run filters on messages while blocking without + * entering the main loop, since filters are run as part of + * dbus_connection_dispatch(). + * * @param connection the connection * @param handler the handler * @returns #TRUE on success, #FALSE if not enough memory. -- cgit From 95717a938b237d12211935f6a7467ef610288fe5 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 18 Aug 2003 15:27:33 +0000 Subject: 2003-08-17 Havoc Pennington This doesn't compile yet, but syncing up so I can hack on it from work. What are branches for if not broken code? ;-) * dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER, DBUS_HEADER_FIELD_ERROR_NAME * dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use for the interface+member pairs (string_hash): change to use g_str_hash algorithm (find_direct_function, find_string_function): refactor these to share most code. * dbus/dbus-message.c: port all of this over to support interface/member fields instead of name field * dbus/dbus-object-registry.c: port over * dbus/dbus-string.c (_dbus_string_validate_interface): rename from _dbus_string_validate_name * bus/dbus-daemon-1.1: change file format for the / stuff to match new message naming scheme * bus/policy.c: port over * bus/config-parser.c: parse new format --- dbus/dbus-connection.c | 54 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index bc26a3ec..7be35b4c 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -296,9 +296,11 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, _dbus_connection_wakeup_mainloop (connection); - _dbus_assert (dbus_message_get_name (message) != NULL); _dbus_verbose ("Message %p (%s) added to incoming queue %p, %d incoming\n", - message, dbus_message_get_name (message), + message, + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : + "no interface", connection, connection->n_incoming); } @@ -381,7 +383,10 @@ _dbus_connection_message_sent (DBusConnection *connection, connection->n_outgoing -= 1; _dbus_verbose ("Message %p (%s) removed from outgoing queue %p, %d left to send\n", - message, dbus_message_get_name (message), + message, + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : + "no interface", connection, connection->n_outgoing); /* Save this link in the link cache also */ @@ -820,7 +825,9 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (io_path_cond == NULL) goto error; - disconnect_message = dbus_message_new_signal (DBUS_MESSAGE_LOCAL_DISCONNECT); + disconnect_message = dbus_message_new_signal (DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + "Disconnect"); + if (disconnect_message == NULL) goto error; @@ -1482,7 +1489,9 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, _dbus_verbose ("Message %p (%s) added to outgoing queue %p, %d pending to send\n", message, - dbus_message_get_name (message), + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : + "no interface", connection, connection->n_outgoing); @@ -1530,7 +1539,12 @@ dbus_connection_send_preallocated (DBusConnection *connection, _dbus_return_if_fail (preallocated != NULL); _dbus_return_if_fail (message != NULL); _dbus_return_if_fail (preallocated->connection == connection); - _dbus_return_if_fail (dbus_message_get_name (message) != NULL); + _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || + (dbus_message_get_interface (message) != NULL && + dbus_message_get_member (message) != NULL)); + _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || + (dbus_message_get_interface (message) != NULL && + dbus_message_get_member (message) != NULL)); CONNECTION_LOCK (connection); _dbus_connection_send_preallocated_unlocked (connection, @@ -1854,8 +1868,7 @@ _dbus_connection_block_for_reply (DBusConnection *connection, { status = _dbus_connection_get_dispatch_status_unlocked (connection); - _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n", - dbus_message_get_name (reply)); + _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); /* Unlocks, and calls out to user code */ _dbus_connection_update_dispatch_status_and_unlock (connection, status); @@ -2148,7 +2161,10 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) connection->n_incoming -= 1; _dbus_verbose ("Message %p (%s) removed from incoming queue %p, %d incoming\n", - link->data, dbus_message_get_name (link->data), + link->data, + dbus_message_get_interface (link->data) ? + dbus_message_get_interface (link->data) : + "no interface", connection, connection->n_incoming); return link; @@ -2194,7 +2210,10 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, connection->n_incoming += 1; _dbus_verbose ("Message %p (%s) put back into queue %p, %d incoming\n", - message_link->data, dbus_message_get_name (message_link->data), + message_link->data, + dbus_message_get_interface (message_link->data) ? + dbus_message_get_interface (message_link->data) : + "no interface", connection, connection->n_incoming); } @@ -2523,7 +2542,10 @@ dbus_connection_dispatch (DBusConnection *connection) * since we acquired the dispatcher */ _dbus_verbose (" running object handler on message %p (%s)\n", - message, dbus_message_get_name (message)); + message, + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : + "no interface"); result = _dbus_object_registry_handle_and_unlock (connection->objects, message); @@ -2549,8 +2571,9 @@ dbus_connection_dispatch (DBusConnection *connection) } if (!_dbus_string_append_printf (&str, - "Method \"%s\" doesn't exist\n", - dbus_message_get_name (message))) + "Method \"%s\" on interface \"%s\" doesn't exist\n", + dbus_message_get_member (message), + dbus_message_get_interface (message))) { _dbus_string_free (&str); result = DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -2586,7 +2609,10 @@ dbus_connection_dispatch (DBusConnection *connection) } _dbus_verbose (" done dispatching %p (%s) on connection %p\n", message, - dbus_message_get_name (message), connection); + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : + "no interface", + connection); out: if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) -- cgit From 68a3c593b9e77b33614726363c7b6fd85d113021 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 18 Aug 2003 22:43:30 +0000 Subject: 2003-08-18 Havoc Pennington * dbus/dbus-hash.c (_dbus_hash_table_insert_two_strings): fix * dbus/dbus-message.c (_dbus_message_loader_queue_messages): fix dumb bug created earlier (wrong order of args to decode_header_data()) * tools/dbus-send.c: port * tools/dbus-print-message.c (print_message): port * test/data/*messages: port all messages over * dbus/dbus-message-builder.c: support including message type * bus/driver.c: port over * bus/dispatch.c: port over to new stuff * dbus/dbus-connection.c (_dbus_connection_new_for_transport): rename disconnect signal to "Disconnected" --- dbus/dbus-connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 7be35b4c..45bbb42d 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -826,7 +826,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) goto error; disconnect_message = dbus_message_new_signal (DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, - "Disconnect"); + "Disconnected"); if (disconnect_message == NULL) goto error; -- cgit From 8d38a2e2c5dc95de992c4d856ec1b0c0948bca3e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 29 Aug 2003 01:05:00 +0000 Subject: 2003-08-28 Havoc Pennington purge DBusObjectID * dbus/dbus-connection.c: port to no ObjectID, create a DBusObjectTree, rename ObjectTree to ObjectPath in public API * dbus/dbus-connection.h (struct DBusObjectTreeVTable): delete everything except UnregisterFunction and MessageFunction * dbus/dbus-marshal.c: port away from DBusObjectID, add DBUS_TYPE_OBJECT_PATH * dbus/dbus-object-registry.[hc], dbus/dbus-object.[hc], dbus/dbus-objectid.[hc]: remove these, we are moving to path-based object IDs --- dbus/dbus-connection.c | 112 +++++++++++++++++++------------------------------ 1 file changed, 42 insertions(+), 70 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 45bbb42d..0c384594 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -35,9 +35,9 @@ #include "dbus-threads.h" #include "dbus-protocol.h" #include "dbus-dataslot.h" -#include "dbus-object-registry.h" #include "dbus-string.h" #include "dbus-pending-call.h" +#include "dbus-object-tree.h" #if 0 #define CONNECTION_LOCK(connection) do { \ @@ -179,7 +179,7 @@ struct DBusConnection DBusList *link_cache; /**< A cache of linked list links to prevent contention * for the global linked list mempool lock */ - DBusObjectRegistry *objects; /**< Objects registered with this connection */ + DBusObjectTree *objects; /**< Object path handlers registered with this connection */ }; static void _dbus_connection_remove_timeout_locked (DBusConnection *connection, @@ -775,7 +775,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) DBusList *disconnect_link; DBusMessage *disconnect_message; DBusCounter *outgoing_counter; - DBusObjectRegistry *objects; + DBusObjectTree *objects; watch_list = NULL; connection = NULL; @@ -839,7 +839,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (outgoing_counter == NULL) goto error; - objects = _dbus_object_registry_new (connection); + objects = _dbus_object_tree_new (connection); if (objects == NULL) goto error; @@ -908,7 +908,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) _dbus_counter_unref (outgoing_counter); if (objects) - _dbus_object_registry_unref (objects); + _dbus_object_tree_unref (objects); return NULL; } @@ -1048,25 +1048,6 @@ _dbus_connection_handle_watch (DBusWatch *watch, return retval; } -/** - * Get the server ID to be used in the object ID for an object - * registered with this connection. - * - * @todo implement this function - * - * @param connection the connection. - * @returns the portion of the object ID - */ -void -_dbus_connection_init_id (DBusConnection *connection, - DBusObjectID *object_id) -{ - /* FIXME */ - dbus_object_id_set_server_bits (object_id, 15); - dbus_object_id_set_client_bits (object_id, 31); - dbus_object_id_set_is_server_bit (object_id, FALSE); -} - /** @} */ /** @@ -1178,7 +1159,7 @@ _dbus_connection_last_unref (DBusConnection *connection) _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ - _dbus_object_registry_free_all_unlocked (connection->objects); + _dbus_object_tree_free_all_unlocked (connection->objects); dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); @@ -1204,7 +1185,7 @@ _dbus_connection_last_unref (DBusConnection *connection) link = next; } - _dbus_object_registry_unref (connection->objects); + _dbus_object_tree_unref (connection->objects); _dbus_hash_table_unref (connection->pending_replies); connection->pending_replies = NULL; @@ -2547,8 +2528,8 @@ dbus_connection_dispatch (DBusConnection *connection) dbus_message_get_interface (message) : "no interface"); - result = _dbus_object_registry_handle_and_unlock (connection->objects, - message); + result = _dbus_object_tree_dispatch_and_unlock (connection->objects, + message); CONNECTION_LOCK (connection); @@ -3026,67 +3007,58 @@ dbus_connection_remove_filter (DBusConnection *connection, } /** - * Registers an object with the connection. This object is assigned an - * object ID, and will be visible under this ID and with the provided - * interfaces to the peer application on the other end of the - * connection. The object instance should be passed in as object_impl; - * the instance can be any datatype, as long as it fits in a void*. + * Registers a handler for a given subsection of the object hierarchy. + * The given vtable handles messages at or below the given path. * - * As a side effect of calling this function, the "registered" - * callback in the #DBusObjectVTable will be invoked. - * - * If the object is deleted, be sure to unregister it with - * dbus_connection_unregister_object() or it will continue to get - * messages. * - * @param connection the connection to register the instance with - * @param interfaces #NULL-terminated array of interface names the instance supports - * @param vtable virtual table of functions for manipulating the instance - * @param object_impl object instance - * @param object_id if non-#NULL, object ID to initialize with the new object's ID - * @returns #FALSE if not enough memory to register the object instance + * @param connection the connection + * @param path #NULL-terminated array of path elements + * @param vtable the virtual table + * @param user_data data to pass to functions in the vtable + * @returns #FALSE if not enough memory */ dbus_bool_t -dbus_connection_register_object (DBusConnection *connection, - const char **interfaces, - const DBusObjectVTable *vtable, - void *object_impl, - DBusObjectID *object_id) +dbus_connection_register_object_path (DBusConnection *connection, + const char **path, + const DBusObjectPathVTable *vtable, + void *user_data) { + dbus_bool_t retval; + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (path != NULL, FALSE); + _dbus_return_val_if_fail (path[0] != NULL, FALSE); _dbus_return_val_if_fail (vtable != NULL, FALSE); - _dbus_return_val_if_fail (vtable->dbus_internal_pad1 == NULL, FALSE); - _dbus_return_val_if_fail (vtable->dbus_internal_pad2 == NULL, FALSE); - _dbus_return_val_if_fail (vtable->dbus_internal_pad3 == NULL, FALSE); - + CONNECTION_LOCK (connection); - return _dbus_object_registry_add_and_unlock (connection->objects, - interfaces, - vtable, - object_impl, - object_id); + retval = _dbus_object_tree_register (connection->objects, path, vtable, + user_data); + + CONNECTION_UNLOCK (connection); + + return retval; } /** - * Reverses the effects of dbus_connection_register_object(), - * and invokes the "unregistered" callback in the #DBusObjectVTable - * for the given object. The passed-in object ID must be a valid, - * registered object ID or the results are undefined. + * Unregisters the handler registered with exactly the given path. + * It's a bug to call this function for a path that isn't registered. * - * @param connection the connection to unregister the object ID from - * @param object_id the object ID to unregister + * @param connection the connection + * @param path the #NULL-terminated array of path elements */ void -dbus_connection_unregister_object (DBusConnection *connection, - const DBusObjectID *object_id) +dbus_connection_unregister_object_path (DBusConnection *connection, + const char **path) { - _dbus_return_if_fail (connection != NULL); + _dbus_return_if_fail (connection != NULL); + _dbus_return_if_fail (path != NULL); + _dbus_return_if_fail (path[0] != NULL); CONNECTION_LOCK (connection); - return _dbus_object_registry_remove_and_unlock (connection->objects, - object_id); + return _dbus_object_tree_unregister_and_unlock (connection->objects, + path); } static DBusDataSlotAllocator slot_allocator; -- cgit From 5fd1e389e1c1c12ad4a55c2af6abdc8e7a2f6d41 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 31 Aug 2003 01:51:44 +0000 Subject: 2003-08-30 Havoc Pennington * test/data/valid-config-files/system.d/test.conf: change to root for the user so warnings don't get printed * dbus/dbus-message.c: add dbus_message_get_path, dbus_message_set_path * dbus/dbus-object-tree.c (do_test_dispatch): add test of dispatching to a path * dbus/dbus-string.c (_dbus_string_validate_path): add * dbus/dbus-marshal.c (_dbus_demarshal_object_path): implement (_dbus_marshal_object_path): implement * dbus/dbus-protocol.h (DBUS_HEADER_FIELD_PATH): new header field to contain the path to the target object (DBUS_HEADER_FIELD_SENDER_SERVICE): rename DBUS_HEADER_FIELD_SENDER to explicitly say it's the sender service --- dbus/dbus-connection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 0c384594..86678673 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -825,7 +825,8 @@ _dbus_connection_new_for_transport (DBusTransport *transport) if (io_path_cond == NULL) goto error; - disconnect_message = dbus_message_new_signal (DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL, + DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, "Disconnected"); if (disconnect_message == NULL) @@ -2522,7 +2523,7 @@ dbus_connection_dispatch (DBusConnection *connection) /* We're still protected from dispatch() reentrancy here * since we acquired the dispatcher */ - _dbus_verbose (" running object handler on message %p (%s)\n", + _dbus_verbose (" running object path dispatch on message %p (%s)\n", message, dbus_message_get_interface (message) ? dbus_message_get_interface (message) : -- cgit From 1dd3f1788f1b4c9af2f4fa744abdb7892d0a14b9 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 31 Aug 2003 03:25:24 +0000 Subject: 2003-08-30 Havoc Pennington * dbus/dbus-connection.c: purge DBusMessageHandler * dbus/dbus-message-handler.c: remove DBusMessageHandler, just use callbacks everywhere --- dbus/dbus-connection.c | 203 +++++++++++++++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 81 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 86678673..608634d2 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -31,7 +31,6 @@ #include "dbus-list.h" #include "dbus-hash.h" #include "dbus-message-internal.h" -#include "dbus-message-handler.h" #include "dbus-threads.h" #include "dbus-protocol.h" #include "dbus-dataslot.h" @@ -125,6 +124,16 @@ * @{ */ +typedef struct DBusMessageFilter DBusMessageFilter; + +struct DBusMessageFilter +{ + DBusAtomic refcount; + DBusHandleMessageFunction function; + void *user_data; + DBusFreeFunction free_user_data_function; +}; + static dbus_bool_t _dbus_modify_sigpipe = TRUE; /** @@ -189,6 +198,26 @@ static void _dbus_connection_update_dispatch_status_and_unlock (DB DBusDispatchStatus new_status); static void _dbus_connection_last_unref (DBusConnection *connection); +static void +_dbus_message_filter_ref (DBusMessageFilter *filter) +{ + _dbus_assert (filter->refcount.value > 0); + _dbus_atomic_inc (&filter->refcount); +} + +static void +_dbus_message_filter_unref (DBusMessageFilter *filter) +{ + _dbus_assert (filter->refcount.value > 0); + + if (_dbus_atomic_dec (&filter->refcount) == 1) + { + if (filter->free_user_data_function) + (* filter->free_user_data_function) (filter->user_data); + + dbus_free (filter); + } +} /** * Acquires the connection lock. @@ -977,40 +1006,6 @@ _dbus_connection_get_next_client_serial (DBusConnection *connection) return serial; } -/** - * Used to notify a connection when a DBusMessageHandler is - * destroyed, so the connection can drop any reference - * to the handler. This is a private function, but still - * takes the connection lock. Don't call it with the lock held. - * - * @todo needs to check in pending_replies too. - * - * @param connection the connection - * @param handler the handler - */ -void -_dbus_connection_handler_destroyed_locked (DBusConnection *connection, - DBusMessageHandler *handler) -{ - DBusList *link; - - CONNECTION_LOCK (connection); - - link = _dbus_list_get_first_link (&connection->filter_list); - while (link != NULL) - { - DBusMessageHandler *h = link->data; - DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); - - if (h == handler) - _dbus_list_remove_link (&connection->filter_list, - link); - - link = next; - } - CONNECTION_UNLOCK (connection); -} - /** * A callback for use with dbus_watch_new() to create a DBusWatch. * @@ -1173,18 +1168,22 @@ _dbus_connection_last_unref (DBusConnection *connection) connection->timeouts = NULL; _dbus_data_slot_list_free (&connection->slot_list); - /* ---- Done with stuff that invokes application callbacks */ link = _dbus_list_get_first_link (&connection->filter_list); while (link != NULL) { - DBusMessageHandler *h = link->data; + DBusMessageFilter *filter = link->data; DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); - - _dbus_message_handler_remove_connection (h, connection); + + filter->function = NULL; + _dbus_message_filter_unref (filter); /* calls app callback */ + link->data = NULL; link = next; } + _dbus_list_clear (&connection->filter_list); + + /* ---- Done with stuff that invokes application callbacks */ _dbus_object_tree_unref (connection->objects); @@ -2456,7 +2455,7 @@ dbus_connection_dispatch (DBusConnection *connection) } _dbus_list_foreach (&filter_list_copy, - (DBusForeachFunction)dbus_message_handler_ref, + (DBusForeachFunction)_dbus_message_filter_ref, NULL); /* We're still protected from dispatch() reentrancy here @@ -2467,12 +2466,11 @@ dbus_connection_dispatch (DBusConnection *connection) link = _dbus_list_get_first_link (&filter_list_copy); while (link != NULL) { - DBusMessageHandler *handler = link->data; + DBusMessageFilter *filter = link->data; DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); _dbus_verbose (" running filter on message %p\n", message); - result = _dbus_message_handler_handle_message (handler, connection, - message); + result = (* filter->function) (connection, message, filter->user_data); if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) break; @@ -2481,7 +2479,7 @@ dbus_connection_dispatch (DBusConnection *connection) } _dbus_list_foreach (&filter_list_copy, - (DBusForeachFunction)dbus_message_handler_unref, + (DBusForeachFunction)_dbus_message_filter_unref, NULL); _dbus_list_clear (&filter_list_copy); @@ -2928,83 +2926,126 @@ dbus_connection_set_unix_user_function (DBusConnection *connection, } /** - * Adds a message filter. Filters are handlers that are run on - * all incoming messages, prior to the objects - * registered with dbus_connection_register_object(). - * Filters are run in the order that they were added. - * The same handler can be added as a filter more than once, in - * which case it will be run more than once. - * Filters added during a filter callback won't be run on the - * message being processed. - * - * The connection does NOT add a reference to the message handler; - * instead, if the message handler is finalized, the connection simply - * forgets about it. Thus the caller of this function must keep a - * reference to the message handler. + * Adds a message filter. Filters are handlers that are run on all + * incoming messages, prior to the objects registered with + * dbus_connection_register_object_path(). Filters are run in the + * order that they were added. The same handler can be added as a + * filter more than once, in which case it will be run more than once. + * Filters added during a filter callback won't be run on the message + * being processed. * * @todo we don't run filters on messages while blocking without * entering the main loop, since filters are run as part of * dbus_connection_dispatch(). * * @param connection the connection - * @param handler the handler + * @param function function to handle messages + * @param user_data user data to pass to the function + * @param free_data_function function to use for freeing user data * @returns #TRUE on success, #FALSE if not enough memory. */ dbus_bool_t -dbus_connection_add_filter (DBusConnection *connection, - DBusMessageHandler *handler) +dbus_connection_add_filter (DBusConnection *connection, + DBusHandleMessageFunction function, + void *user_data, + DBusFreeFunction free_data_function) { + DBusMessageFilter *filter; + _dbus_return_val_if_fail (connection != NULL, FALSE); - _dbus_return_val_if_fail (handler != NULL, FALSE); + _dbus_return_val_if_fail (function != NULL, FALSE); + + filter = dbus_new0 (DBusMessageFilter, 1); + if (filter == NULL) + return FALSE; + filter->refcount.value = 1; + CONNECTION_LOCK (connection); - if (!_dbus_message_handler_add_connection (handler, connection)) - { - CONNECTION_UNLOCK (connection); - return FALSE; - } if (!_dbus_list_append (&connection->filter_list, - handler)) + filter)) { - _dbus_message_handler_remove_connection (handler, connection); + _dbus_message_filter_unref (filter); CONNECTION_UNLOCK (connection); return FALSE; } + /* Fill in filter after all memory allocated, + * so we don't run the free_user_data_function + * if the add_filter() fails + */ + + filter->function = function; + filter->user_data = user_data; + filter->free_user_data_function = free_data_function; + CONNECTION_UNLOCK (connection); return TRUE; } /** * Removes a previously-added message filter. It is a programming - * error to call this function for a handler that has not - * been added as a filter. If the given handler was added - * more than once, only one instance of it will be removed - * (the most recently-added instance). + * error to call this function for a handler that has not been added + * as a filter. If the given handler was added more than once, only + * one instance of it will be removed (the most recently-added + * instance). * * @param connection the connection * @param handler the handler to remove * */ void -dbus_connection_remove_filter (DBusConnection *connection, - DBusMessageHandler *handler) +dbus_connection_remove_filter (DBusConnection *connection, + DBusHandleMessageFunction function, + void *user_data) { + DBusList *link; + DBusMessageFilter *filter; + _dbus_return_if_fail (connection != NULL); - _dbus_return_if_fail (handler != NULL); + _dbus_return_if_fail (function != NULL); CONNECTION_LOCK (connection); - if (!_dbus_list_remove_last (&connection->filter_list, handler)) + + filter = NULL; + + link = _dbus_list_get_last_link (&connection->filter_list); + while (link != NULL) { - _dbus_warn ("Tried to remove a DBusConnection filter that had not been added\n"); - CONNECTION_UNLOCK (connection); - return; + filter = link->data; + + if (filter->function == function && + filter->user_data == user_data) + { + _dbus_list_remove_link (&connection->filter_list, link); + filter->function = NULL; + + break; + } + + link = _dbus_list_get_prev_link (&connection->filter_list, link); } + + CONNECTION_UNLOCK (connection); - _dbus_message_handler_remove_connection (handler, connection); +#ifndef DBUS_DISABLE_CHECKS + if (filter == NULL) + { + _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", + function, user_data); + return; + } +#endif + + /* Call application code */ + if (filter->free_user_data_function) + (* filter->free_user_data_function) (filter->user_data); - CONNECTION_UNLOCK (connection); + filter->free_user_data_function = NULL; + filter->user_data = NULL; + + _dbus_message_filter_unref (filter); } /** -- cgit From 666fe95480c14d7cbf5143b1a4e1bf0558403d4d Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 6 Sep 2003 18:21:00 +0000 Subject: 2003-09-06 Havoc Pennington * dbus/dbus-connection.c (dbus_connection_register_fallback): add this (dbus_connection_register_object_path): make this not handle messages to paths below the given path --- dbus/dbus-connection.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 608634d2..b8e67c14 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -3049,8 +3049,8 @@ dbus_connection_remove_filter (DBusConnection *connection, } /** - * Registers a handler for a given subsection of the object hierarchy. - * The given vtable handles messages at or below the given path. + * Registers a handler for a given path in the object hierarchy. + * The given vtable handles messages sent to exactly the given path. * * * @param connection the connection @@ -3074,7 +3074,47 @@ dbus_connection_register_object_path (DBusConnection *connection, CONNECTION_LOCK (connection); - retval = _dbus_object_tree_register (connection->objects, path, vtable, + retval = _dbus_object_tree_register (connection->objects, + FALSE, + path, vtable, + user_data); + + CONNECTION_UNLOCK (connection); + + return retval; +} + +/** + * Registers a fallback handler for a given subsection of the object + * hierarchy. The given vtable handles messages at or below the given + * path. You can use this to establish a default message handling + * policy for a whole "subdirectory." + * + * + * @param connection the connection + * @param path #NULL-terminated array of path elements + * @param vtable the virtual table + * @param user_data data to pass to functions in the vtable + * @returns #FALSE if not enough memory + */ +dbus_bool_t +dbus_connection_register_fallback (DBusConnection *connection, + const char **path, + const DBusObjectPathVTable *vtable, + void *user_data) +{ + dbus_bool_t retval; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (path != NULL, FALSE); + _dbus_return_val_if_fail (path[0] != NULL, FALSE); + _dbus_return_val_if_fail (vtable != NULL, FALSE); + + CONNECTION_LOCK (connection); + + retval = _dbus_object_tree_register (connection->objects, + TRUE, + path, vtable, user_data); CONNECTION_UNLOCK (connection); -- cgit From 85ab0327d82e4945ad16630e583d8cc68df25a90 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 7 Sep 2003 23:04:54 +0000 Subject: 2003-09-07 Havoc Pennington * Make Doxygen contented. --- dbus/dbus-connection.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index b8e67c14..bab6ffd8 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -124,14 +124,31 @@ * @{ */ +/** + * Internal struct representing a message filter function + */ typedef struct DBusMessageFilter DBusMessageFilter; +/** + * Internal struct representing a message filter function + */ struct DBusMessageFilter { - DBusAtomic refcount; - DBusHandleMessageFunction function; - void *user_data; - DBusFreeFunction free_user_data_function; + DBusAtomic refcount; /**< Reference count */ + DBusHandleMessageFunction function; /**< Function to call to filter */ + void *user_data; /**< User data for the function */ + DBusFreeFunction free_user_data_function; /**< Function to free the user data */ +}; + + +/** + * Internals of DBusPreallocatedSend + */ +struct DBusPreallocatedSend +{ + DBusConnection *connection; /**< Connection we'd send the message to */ + DBusList *queue_link; /**< Preallocated link in the queue */ + DBusList *counter_link; /**< Preallocated link in the resource counter */ }; static dbus_bool_t _dbus_modify_sigpipe = TRUE; @@ -1339,13 +1356,6 @@ dbus_connection_get_is_authenticated (DBusConnection *connection) return res; } -struct DBusPreallocatedSend -{ - DBusConnection *connection; - DBusList *queue_link; - DBusList *counter_link; -}; - static DBusPreallocatedSend* _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) { @@ -2992,7 +3002,8 @@ dbus_connection_add_filter (DBusConnection *connection, * instance). * * @param connection the connection - * @param handler the handler to remove + * @param function the handler to remove + * @param user_data user data for the handler to remove * */ void -- cgit From 583994cb3b7f5562fb7b8c37b4cb0d5af78e4ce2 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 17 Sep 2003 03:52:07 +0000 Subject: 2003-09-15 Havoc Pennington * dbus/dbus-pending-call.c: add the get/set object data boilerplate as for DBusConnection, etc. Use generic object data for the notify callback. * glib/dbus-gparser.c (parse_node): parse child nodes * tools/dbus-viewer.c: more hacking on the dbus-viewer * glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to contain functions shared between the convenience lib and the installed lib * glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add -export-symbols-regex to the GLib library * dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock): fix the locking in here, and add a default handler for Introspect() that just returns sub-nodes. 2003-09-14 Havoc Pennington * glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo rather than gfoo consistent * glib/dbus-gproxy.h: delete for now, move contents to dbus-glib.h, because the include files don't work right since we aren't in the dbus/ subdir. * glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing (dbus_gproxy_end_call): finish (dbus_gproxy_begin_call): finish * glib/dbus-gmain.c (dbus_set_g_error): new * glib/dbus-gobject.c (handle_introspect): include information about child nodes in the introspection * dbus/dbus-connection.c (dbus_connection_list_registered): new function to help in implementation of introspection * dbus/dbus-object-tree.c (_dbus_object_tree_list_registered_and_unlock): new function 2003-09-12 Havoc Pennington * glib/dbus-gidl.h: add common base class for all the foo_info types * tools/dbus-viewer.c: add GTK-based introspection UI thingy similar to kdcop * test/Makefile.am: try test srcdir -ef . in addition to test srcdir = ., one of them should work (yeah lame) * glib/Makefile.am: build the "idl" parser stuff as a convenience library * glib/dbus-gparser.h: make description_load routines return NodeInfo* not Parser* * Makefile.am (SUBDIRS): build test dir after all library dirs * configure.in: add GTK+ detection --- dbus/dbus-connection.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index bab6ffd8..b55f270c 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -3101,7 +3101,6 @@ dbus_connection_register_object_path (DBusConnection *connection, * path. You can use this to establish a default message handling * policy for a whole "subdirectory." * - * * @param connection the connection * @param path #NULL-terminated array of path elements * @param vtable the virtual table @@ -3136,6 +3135,7 @@ dbus_connection_register_fallback (DBusConnection *connection, /** * Unregisters the handler registered with exactly the given path. * It's a bug to call this function for a path that isn't registered. + * Can unregister both fallback paths and object paths. * * @param connection the connection * @param path the #NULL-terminated array of path elements @@ -3154,6 +3154,32 @@ dbus_connection_unregister_object_path (DBusConnection *connection, path); } +/** + * Lists the registered fallback handlers and object path handlers at + * the given parent_path. The returned array should be freed with + * dbus_free_string_array(). + * + * @param connection the connection + * @param parent_path the path to list the child handlers of + * @param child_entries returns #NULL-terminated array of children + * @returns #FALSE if no memory to allocate the child entries + */ +dbus_bool_t +dbus_connection_list_registered (DBusConnection *connection, + const char **parent_path, + char ***child_entries) +{ + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (parent_path != NULL, FALSE); + _dbus_return_val_if_fail (child_entries != NULL, FALSE); + + CONNECTION_LOCK (connection); + + return _dbus_object_tree_list_registered_and_unlock (connection->objects, + parent_path, + child_entries); +} + static DBusDataSlotAllocator slot_allocator; _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); -- cgit From 25cb861980003f81eade8707bfa1a61c9ece1779 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 22 Sep 2003 01:29:14 +0000 Subject: 2003-09-21 Havoc Pennington * dbus/dbus-bus.c (dbus_bus_get): set exit_on_disconnect to TRUE by default for message bus connections. * dbus/dbus-connection.c (dbus_connection_dispatch): exit if exit_on_disconnect flag is set and we process the disconnected signal. (dbus_connection_set_exit_on_disconnect): new function --- dbus/dbus-connection.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'dbus/dbus-connection.c') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index b55f270c..ed7d57d0 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -206,6 +206,8 @@ struct DBusConnection * for the global linked list mempool lock */ DBusObjectTree *objects; /**< Object path handlers registered with this connection */ + + unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */ }; static void _dbus_connection_remove_timeout_locked (DBusConnection *connection, @@ -906,6 +908,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport) connection->filter_list = NULL; connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ connection->objects = objects; + connection->exit_on_disconnect = FALSE; _dbus_data_slot_list_init (&connection->slot_list); @@ -1356,6 +1359,30 @@ dbus_connection_get_is_authenticated (DBusConnection *connection) return res; } +/** + * Set whether _exit() should be called when the connection receives a + * disconnect signal. The call to _exit() comes after any handlers for + * the disconnect signal run; handlers can cancel the exit by calling + * this function. + * + * By default, exit_on_disconnect is #FALSE; but for message bus + * connections returned from dbus_bus_get() it will be toggled on + * by default. + * + * @param connection the connection + * @param exit_on_disconnect #TRUE if _exit() should be called after a disconnect signal + */ +void +dbus_connection_set_exit_on_disconnect (DBusConnection *connection, + dbus_bool_t exit_on_disconnect) +{ + _dbus_return_if_fail (connection != NULL); + + CONNECTION_LOCK (connection); + connection->exit_on_disconnect = exit_on_disconnect != FALSE; + CONNECTION_UNLOCK (connection); +} + static DBusPreallocatedSend* _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) { @@ -2616,6 +2643,17 @@ dbus_connection_dispatch (DBusConnection *connection) } else { + if (connection->exit_on_disconnect && + dbus_message_is_signal (message, + DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, + "Disconnected")) + { + _dbus_verbose ("Exiting on Disconnected signal\n"); + CONNECTION_UNLOCK (connection); + _dbus_exit (1); + _dbus_assert_not_reached ("Call to exit() returned"); + } + _dbus_list_free_link (message_link); dbus_message_unref (message); /* don't want the message to count in max message limits * in computing dispatch status below -- cgit