From ee1133de4dc5e181be5d09f084d8823388d5f693 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 27 Jan 2003 11:20:55 +0000 Subject: 2003-01-27 Anders Carlsson * bus/dispatch.c: (bus_dispatch_message_handler): Dispatch messages sent to services. * bus/driver.c: (bus_driver_send_service_deleted), (bus_driver_send_service_created), (bus_driver_send_service_lost), (bus_driver_send_service_acquired): Add helper functions for sending service related messages. (bus_driver_send_welcome_message): Send HELLO_REPLY instead of WELCOME. (bus_driver_handle_list_services): Send LIST_SERVICES_REPLY instead of SERVICES. (bus_driver_handle_own_service), (bus_driver_handle_service_exists): New message handlers. (bus_driver_handle_message): Invoke new message handlers. (bus_driver_remove_connection): Don't remove any services here since that's done automatically by bus_service_remove_owner now. * bus/driver.h: New function signatures. * bus/services.c: (bus_service_add_owner): Send ServiceAcquired message if we're the only primary owner. (bus_service_remove_owner): Send ServiceAcquired/ServiceLost messages. (bus_service_set_prohibit_replacement), (bus_service_get_prohibit_replacement): Functions for setting prohibit replacement. (bus_service_has_owner): New function that checks if a connection is in the owner queue of a certain service. * bus/services.h: Add new function signatures. * dbus/dbus-list.c: (_dbus_list_test): Add tests for _dbus_list_remove_last and traversing the list backwards. * dbus/dbus-list.h: Fix a typo in _dbus_list_get_prev_link, if we're at the first element we can't go any further, so return NULL then. * dbus/dbus-protocol.h: Add new messages, service flags and service replies. --- bus/dispatch.c | 20 ++++-- bus/driver.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++------- bus/driver.h | 13 +++- bus/services.c | 74 ++++++++++++++++++---- bus/services.h | 27 ++++---- 5 files changed, 273 insertions(+), 52 deletions(-) (limited to 'bus') diff --git a/bus/dispatch.c b/bus/dispatch.c index a74b3719..a02916be 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -50,16 +50,16 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, DBusMessage *message, void *user_data) { - const char *sender, *service; + const char *sender, *service_name; /* Assign a sender to the message */ sender = bus_connection_get_name (connection); _DBUS_HANDLE_OOM (dbus_message_set_sender (message, sender)); - service = dbus_message_get_service (message); + service_name = dbus_message_get_service (message); /* See if the message is to the driver */ - if (strcmp (service, DBUS_SERVICE_DBUS) == 0) + if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) { bus_driver_handle_message (connection, message); } @@ -68,13 +68,23 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, _dbus_verbose ("Received message from non-registered client. Disconnecting.\n"); dbus_connection_disconnect (connection); } - else if (strcmp (service, DBUS_SERVICE_BROADCAST) == 0) + else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) { bus_dispatch_broadcast_message (message); } else { + DBusString service_string; + BusService *service; + + _dbus_string_init_const (&service_string, service_name); + service = bus_service_lookup (&service_string, FALSE); + + _dbus_assert (bus_service_get_primary_owner (service) != NULL); + /* Dispatch the message */ + _DBUS_HANDLE_OOM (dbus_connection_send_message (bus_service_get_primary_owner (service), + message, NULL, NULL)); } return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; @@ -118,7 +128,7 @@ bus_dispatch_remove_connection (DBusConnection *connection) { /* Here we tell the bus driver that we want to get off. */ bus_driver_remove_connection (connection); - + dbus_connection_set_data (connection, message_handler_slot, NULL, NULL); diff --git a/bus/driver.c b/bus/driver.c index 9f159a22..c8631ffb 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -32,12 +32,12 @@ static void bus_driver_send_welcome_message (DBusConnection *connection, DBusMessage *hello_message); -static void -bus_driver_send_service_deleted (DBusConnection *connection, const char *name) +void +bus_driver_send_service_deleted (const char *service_name) { DBusMessage *message; - _dbus_verbose ("sending service deleted: %s\n", name); + _dbus_verbose ("sending service deleted: %s\n", service_name); _DBUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST, DBUS_MESSAGE_SERVICE_DELETED)); @@ -45,14 +45,14 @@ bus_driver_send_service_deleted (DBusConnection *connection, const char *name) _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS)); _DBUS_HANDLE_OOM (dbus_message_append_fields (message, - DBUS_TYPE_STRING, name, + DBUS_TYPE_STRING, service_name, 0)); bus_dispatch_broadcast_message (message); dbus_message_unref (message); } static void -bus_driver_send_service_created (DBusConnection *connection, const char *name) +bus_driver_send_service_created (const char *service_name) { DBusMessage *message; @@ -62,12 +62,48 @@ bus_driver_send_service_created (DBusConnection *connection, const char *name) _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS)); _DBUS_HANDLE_OOM (dbus_message_append_fields (message, - DBUS_TYPE_STRING, name, + DBUS_TYPE_STRING, service_name, 0)); bus_dispatch_broadcast_message (message); dbus_message_unref (message); } +void +bus_driver_send_service_lost (DBusConnection *connection, + const char *service_name) +{ + DBusMessage *message; + + _DBUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST, + DBUS_MESSAGE_SERVICE_LOST)); + + _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS)); + _DBUS_HANDLE_OOM (dbus_message_append_fields (message, + DBUS_TYPE_STRING, service_name, + 0)); + _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, message, NULL, NULL)); + + dbus_message_unref (message); +} + +void +bus_driver_send_service_acquired (DBusConnection *connection, + const char *service_name) +{ + DBusMessage *message; + + _DBUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST, + DBUS_MESSAGE_SERVICE_ACQUIRED)); + + _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS)); + _DBUS_HANDLE_OOM (dbus_message_append_fields (message, + DBUS_TYPE_STRING, service_name, + 0)); + _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, message, NULL, NULL)); + + dbus_message_unref (message); +} + static dbus_bool_t create_unique_client_name (const char *name, DBusString *str) @@ -158,7 +194,8 @@ bus_driver_handle_hello (DBusConnection *connection, /* Create the service */ _DBUS_HANDLE_OOM (service = bus_service_lookup (&unique_name, TRUE)); - + bus_service_set_prohibit_replacement (service, TRUE); + /* Add the connection as the owner */ _DBUS_HANDLE_OOM (bus_service_add_owner (service, connection)); _DBUS_HANDLE_OOM (bus_connection_set_name (connection, &unique_name)); @@ -171,7 +208,7 @@ bus_driver_handle_hello (DBusConnection *connection, _DBUS_HANDLE_OOM (bus_driver_send_welcome_message (connection, message)); /* Broadcast a service created message */ - bus_driver_send_service_created (connection, bus_service_get_name (service)); + bus_driver_send_service_created (bus_service_get_name (service)); } static void @@ -184,7 +221,7 @@ bus_driver_send_welcome_message (DBusConnection *connection, name = bus_connection_get_name (connection); _dbus_assert (name != NULL); - _DBUS_HANDLE_OOM (welcome = dbus_message_new_reply (DBUS_MESSAGE_WELCOME, + _DBUS_HANDLE_OOM (welcome = dbus_message_new_reply (DBUS_MESSAGE_HELLO_REPLY, hello_message)); _DBUS_HANDLE_OOM (dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS)); @@ -206,7 +243,7 @@ bus_driver_handle_list_services (DBusConnection *connection, int len, i; char **services; - _DBUS_HANDLE_OOM (reply = dbus_message_new_reply (DBUS_MESSAGE_SERVICES, message)); + _DBUS_HANDLE_OOM (reply = dbus_message_new_reply (DBUS_MESSAGE_LIST_SERVICES_REPLY, message)); _DBUS_HANDLE_OOM (services = bus_services_list (&len)); @@ -226,26 +263,125 @@ bus_driver_handle_list_services (DBusConnection *connection, } } -void -bus_driver_remove_connection (DBusConnection *connection) +static void +bus_driver_handle_own_service (DBusConnection *connection, + DBusMessage *message) { - BusService *service; + DBusMessage *reply; + DBusResultCode result; DBusString service_name; - const char *name; + BusService *service; + char *name; + int service_reply; + int flags; + + _DBUS_HANDLE_OOM ((result = dbus_message_get_fields (message, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_UINT32, &flags, + 0)) != DBUS_RESULT_NO_MEMORY); + + if (result != DBUS_RESULT_SUCCESS) + { + dbus_free (name); + dbus_connection_disconnect (connection); + return; + } - name = bus_connection_get_name (connection); + _dbus_verbose ("Trying to own service %s with flags %d\n", name, flags); - if (name == NULL) - return; - _dbus_string_init_const (&service_name, name); + service = bus_service_lookup (&service_name, TRUE); + + _DBUS_HANDLE_OOM ((reply = dbus_message_new_reply (DBUS_MESSAGE_ACQUIRE_SERVICE_REPLY, message))); - service = bus_service_lookup (&service_name, FALSE); + /* + * Check if the service already has an owner + */ + if (bus_service_get_primary_owner (service) != NULL) + { + if (bus_service_has_owner (service, connection)) + service_reply = DBUS_SERVICE_REPLY_ALREADY_OWNER; + else if (!(flags & DBUS_SERVICE_FLAG_REPLACE_EXISTING)) + service_reply = DBUS_SERVICE_REPLY_SERVICE_EXISTS; + else + { + if (bus_service_get_prohibit_replacement (service)) + { + + /* Queue the connection */ + _DBUS_HANDLE_OOM (bus_service_add_owner (service, connection)); + + service_reply = DBUS_SERVICE_REPLY_IN_QUEUE; + } + else + { + DBusConnection *owner; + + /* We can replace the primary owner */ + owner = bus_service_get_primary_owner (service); + + /* We enqueue the new owner and remove the first one because + * that will cause ServiceAcquired and ServiceLost messages to + * be sent. + */ + _DBUS_HANDLE_OOM (bus_service_add_owner (service, connection)); + bus_service_remove_owner (service, owner); + _dbus_assert (connection == bus_service_get_primary_owner (service)); + } + } + } + else + { + bus_service_set_prohibit_replacement (service, + (flags & DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT)); + + /* Broadcast service created message */ + bus_driver_send_service_created (bus_service_get_name (service)); + + _DBUS_HANDLE_OOM (bus_service_add_owner (service, connection)); + + service_reply = DBUS_SERVICE_REPLY_PRIMARY_OWNER; + } + + /* Send service reply */ + _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, reply, NULL, NULL)); + dbus_free (name); + dbus_message_unref (reply); +} - bus_driver_send_service_deleted (connection, name); +static void +bus_driver_handle_service_exists (DBusConnection *connection, + DBusMessage *message) +{ + DBusMessage *reply; + DBusResultCode result; + DBusString service_name; + BusService *service; + char *name; - if (service) - bus_service_free (service); + _DBUS_HANDLE_OOM ((result = dbus_message_get_fields (message, + DBUS_TYPE_STRING, &name, + 0)) != DBUS_RESULT_NO_MEMORY); + if (result != DBUS_RESULT_SUCCESS) + { + dbus_free (name); + dbus_connection_disconnect (connection); + return; + } + + _dbus_string_init_const (&service_name, name); + service = bus_service_lookup (&service_name, FALSE); + + _DBUS_HANDLE_OOM ((reply = dbus_message_new_reply (DBUS_MESSAGE_ACQUIRE_SERVICE_REPLY, message))); + _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS)); + + _DBUS_HANDLE_OOM (dbus_message_append_fields (message, + DBUS_TYPE_UINT32, (service != NULL ? 1 : 0), + 0)); + _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, message, NULL, NULL)); + + dbus_message_unref (message); + dbus_free (name); } void @@ -272,4 +408,15 @@ bus_driver_handle_message (DBusConnection *connection, bus_driver_handle_hello (connection, message); else if (strcmp (name, DBUS_MESSAGE_LIST_SERVICES) == 0) bus_driver_handle_list_services (connection, message); + else if (strcmp (name, DBUS_MESSAGE_ACQUIRE_SERVICE) == 0) + bus_driver_handle_own_service (connection, message); + else if (strcmp (name, DBUS_MESSAGE_SERVICE_EXISTS) == 0) + bus_driver_handle_service_exists (connection, message); + +} + +void +bus_driver_remove_connection (DBusConnection *connection) +{ + /* Does nothing for now */ } diff --git a/bus/driver.h b/bus/driver.h index 897a2db2..fc4d2590 100644 --- a/bus/driver.h +++ b/bus/driver.h @@ -26,8 +26,15 @@ #include -void bus_driver_handle_message (DBusConnection *connection, - DBusMessage *message); -void bus_driver_remove_connection (DBusConnection *connection); +void bus_driver_remove_connection (DBusConnection *connection); +void bus_driver_handle_message (DBusConnection *connection, + DBusMessage *message); +void bus_driver_send_service_deleted (const char *service_name); +void bus_driver_send_service_lost (DBusConnection *connection, + const char *service_name); +void bus_driver_send_service_acquired (DBusConnection *connection, + const char *service_name); + + #endif /* BUS_DRIVER_H */ diff --git a/bus/services.c b/bus/services.c index 0be56e75..1c949559 100644 --- a/bus/services.c +++ b/bus/services.c @@ -2,6 +2,7 @@ /* services.c Service management * * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2003 CodeFactory AB * * Licensed under the Academic Free License version 1.2 * @@ -20,6 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#include "driver.h" #include "services.h" #include "connection.h" #include @@ -30,6 +32,8 @@ struct BusService { char *name; DBusList *owners; + + unsigned int prohibit_replacement:1; }; static DBusHashTable *service_hash = NULL; @@ -98,17 +102,6 @@ bus_service_lookup (const DBusString *service_name, return service; } -void -bus_service_free (BusService *service) -{ - _dbus_assert (service->owners == NULL); - - _dbus_hash_table_remove_string (service_hash, service->name); - - dbus_free (service->name); - _dbus_mem_pool_dealloc (service_pool, service); -} - dbus_bool_t bus_service_add_owner (BusService *service, DBusConnection *owner) @@ -123,6 +116,10 @@ bus_service_add_owner (BusService *service, return FALSE; } + /* Send service acquired message */ + if (bus_service_get_primary_owner (service) == owner) + bus_driver_send_service_acquired (owner, service->name); + return TRUE; } @@ -130,8 +127,29 @@ void bus_service_remove_owner (BusService *service, DBusConnection *owner) { + /* Send service lost message */ + if (bus_service_get_primary_owner (service) == owner) + bus_driver_send_service_lost (owner, service->name); + _dbus_list_remove_last (&service->owners, owner); bus_connection_remove_owned_service (owner, service); + + if (service->owners == NULL) + { + /* Delete service */ + bus_driver_send_service_deleted (service->name); + + _dbus_hash_table_remove_string (service_hash, service->name); + + dbus_free (service->name); + _dbus_mem_pool_dealloc (service_pool, service); + } + else + { + /* Send service acquired to the new owner */ + bus_driver_send_service_acquired (bus_service_get_primary_owner (service), + service->name); + } } DBusConnection* @@ -202,3 +220,37 @@ bus_services_list (int *array_len) return NULL; } + +void +bus_service_set_prohibit_replacement (BusService *service, + dbus_bool_t prohibit_replacement) +{ + _dbus_assert (service->owners == NULL); + + service->prohibit_replacement = prohibit_replacement != FALSE; +} + +dbus_bool_t +bus_service_get_prohibit_replacement (BusService *service) +{ + return service->prohibit_replacement; +} + +dbus_bool_t +bus_service_has_owner (BusService *service, + DBusConnection *owner) +{ + DBusList *link; + + link = _dbus_list_get_first_link (&service->owners); + + while (link != NULL) + { + if (link->data == owner) + return TRUE; + + link = _dbus_list_get_next_link (&service->owners, link); + } + + return FALSE; +} diff --git a/bus/services.h b/bus/services.h index 3dd2b0f5..3f6b31a9 100644 --- a/bus/services.h +++ b/bus/services.h @@ -38,17 +38,22 @@ typedef struct BusService BusService; typedef void (* BusServiceForeachFunction) (BusService *service, void *data); -BusService* bus_service_lookup (const DBusString *service_name, - dbus_bool_t create_if_not_found); -void bus_service_free (BusService *service); -dbus_bool_t bus_service_add_owner (BusService *service, - DBusConnection *owner); -void bus_service_remove_owner (BusService *service, - DBusConnection *owner); -DBusConnection* bus_service_get_primary_owner (BusService *service); -const char* bus_service_get_name (BusService *service); -void bus_service_foreach (BusServiceForeachFunction function, - void *data); +BusService* bus_service_lookup (const DBusString *service_name, + dbus_bool_t create_if_not_found); +dbus_bool_t bus_service_add_owner (BusService *service, + DBusConnection *owner); +void bus_service_remove_owner (BusService *service, + DBusConnection *owner); +dbus_bool_t bus_service_has_owner (BusService *service, + DBusConnection *owner); +DBusConnection* bus_service_get_primary_owner (BusService *service); +void bus_service_set_prohibit_replacement (BusService *service, + dbus_bool_t prohibit_replacement); +dbus_bool_t bus_service_get_prohibit_replacement (BusService *service); +const char* bus_service_get_name (BusService *service); +void bus_service_foreach (BusServiceForeachFunction function, + void *data); + char **bus_services_list (int *array_len); -- cgit