From 6ecc14ffabcffb69aa938a67940db48272e05046 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 13 Mar 2003 03:52:58 +0000 Subject: 2003-03-12 Havoc Pennington Throughout: purge global variables, introduce BusActivation, BusConnections, BusRegistry, etc. objects instead. * bus/bus.h, bus/bus.c: introduce BusContext as a global message bus object * test/Makefile.am (TEST_BINARIES): disable bus-test for now, going to redo this a bit differently I think --- bus/Makefile.am | 2 + bus/activation.c | 101 ++++++++++++++++-------- bus/activation.h | 15 ++-- bus/bus.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++ bus/bus.h | 48 +++++++++++ bus/connection.c | 199 ++++++++++++++++++++++++++++++++++++---------- bus/connection.h | 24 ++++-- bus/dispatch.c | 21 ++++- bus/driver.c | 39 ++++++--- bus/main.c | 105 +++++------------------- bus/services.c | 237 +++++++++++++++++++++++++++++++------------------------ bus/services.h | 40 +++++----- 12 files changed, 719 insertions(+), 314 deletions(-) create mode 100644 bus/bus.c create mode 100644 bus/bus.h (limited to 'bus') diff --git a/bus/Makefile.am b/bus/Makefile.am index d84e99d7..f9f4dbfc 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -11,6 +11,8 @@ noinst_LTLIBRARIES=libdbus-daemon.la libdbus_daemon_la_SOURCES= \ activation.c \ activation.h \ + bus.c \ + bus.h \ connection.c \ connection.h \ desktop-file.c \ diff --git a/bus/activation.c b/bus/activation.c index 4e428bde..ba130edd 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -33,8 +33,12 @@ #define DBUS_SERVICE_NAME "Name" #define DBUS_SERVICE_EXEC "Exec" -static DBusHashTable *activation_entries = NULL; -static char *server_address = NULL; +struct BusActivation +{ + int refcount; + DBusHashTable *entries; + char *server_address; +}; typedef struct { @@ -42,12 +46,6 @@ typedef struct char *exec; } BusActivationEntry; -static DBusHashTable *pending_activations = NULL; -typedef struct -{ - char *service; -} BusPendingActivation; - static void bus_activation_entry_free (BusActivationEntry *entry) { @@ -59,7 +57,8 @@ bus_activation_entry_free (BusActivationEntry *entry) } static dbus_bool_t -add_desktop_file_entry (BusDesktopFile *desktop_file, +add_desktop_file_entry (BusActivation *activation, + BusDesktopFile *desktop_file, DBusError *error) { char *name, *exec; @@ -92,7 +91,7 @@ add_desktop_file_entry (BusDesktopFile *desktop_file, /* FIXME we need a better-defined algorithm for which service file to * pick than "whichever one is first in the directory listing" */ - if (_dbus_hash_table_lookup_string (activation_entries, name)) + if (_dbus_hash_table_lookup_string (activation->entries, name)) { dbus_set_error (error, DBUS_ERROR_FAILED, "Service %s already exists in activation entry list\n", name); @@ -109,7 +108,7 @@ add_desktop_file_entry (BusDesktopFile *desktop_file, entry->name = name; entry->exec = exec; - if (!_dbus_hash_table_insert_string (activation_entries, entry->name, entry)) + if (!_dbus_hash_table_insert_string (activation->entries, entry->name, entry)) { BUS_SET_OOM (error); goto failed; @@ -131,8 +130,9 @@ add_desktop_file_entry (BusDesktopFile *desktop_file, * hash entries it already added. */ static dbus_bool_t -load_directory (const char *directory, - DBusError *error) +load_directory (BusActivation *activation, + const char *directory, + DBusError *error) { DBusDirIter *iter; DBusString dir, filename; @@ -213,7 +213,7 @@ load_directory (const char *directory, continue; } - if (!add_desktop_file_entry (desktop_file, &tmp_error)) + if (!add_desktop_file_entry (activation, desktop_file, &tmp_error)) { const char *full_path_c; @@ -263,27 +263,34 @@ load_directory (const char *directory, return FALSE; } -dbus_bool_t -bus_activation_init (const char *address, - const char **directories, - DBusError *error) +BusActivation* +bus_activation_new (const char *address, + const char **directories, + DBusError *error) { int i; + BusActivation *activation; - _dbus_assert (server_address == NULL); - _dbus_assert (activation_entries == NULL); + activation = dbus_new0 (BusActivation, 1); + if (activation == NULL) + { + BUS_SET_OOM (error); + return NULL; + } + + activation->refcount = 1; /* FIXME: We should split up the server addresses. */ - server_address = _dbus_strdup (address); - if (server_address == NULL) + activation->server_address = _dbus_strdup (address); + if (activation->server_address == NULL) { BUS_SET_OOM (error); goto failed; } - activation_entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, + activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, (DBusFreeFunction)bus_activation_entry_free); - if (activation_entries == NULL) + if (activation->entries == NULL) { BUS_SET_OOM (error); goto failed; @@ -293,39 +300,63 @@ bus_activation_init (const char *address, i = 0; while (directories[i] != NULL) { - if (!load_directory (directories[i], error)) + if (!load_directory (activation, directories[i], error)) goto failed; ++i; } - return TRUE; + return activation; failed: - dbus_free (server_address); - if (activation_entries) - _dbus_hash_table_unref (activation_entries); + bus_activation_unref (activation); + return NULL; +} + +void +bus_activation_ref (BusActivation *activation) +{ + _dbus_assert (activation->refcount > 0); - return FALSE; + activation->refcount += 1; +} + +void +bus_activation_unref (BusActivation *activation) +{ + _dbus_assert (activation->refcount > 0); + + activation->refcount -= 1; + + if (activation->refcount == 0) + { + dbus_free (activation->server_address); + if (activation->entries) + _dbus_hash_table_unref (activation->entries); + dbus_free (activation); + } } static void child_setup (void *data) { + BusActivation *activation = data; + /* If no memory, we simply have the child exit, so it won't try * to connect to the wrong thing. */ - if (!_dbus_setenv ("DBUS_ADDRESS", server_address)) + if (!_dbus_setenv ("DBUS_ADDRESS", activation->server_address)) _dbus_exit (1); } dbus_bool_t -bus_activation_activate_service (const char *service_name, - DBusError *error) +bus_activation_activate_service (BusActivation *activation, + const char *service_name, + DBusError *error) { BusActivationEntry *entry; char *argv[2]; - entry = _dbus_hash_table_lookup_string (activation_entries, service_name); + entry = _dbus_hash_table_lookup_string (activation->entries, service_name); if (!entry) { @@ -344,7 +375,7 @@ bus_activation_activate_service (const char *service_name, argv[1] = NULL; if (!_dbus_spawn_async (argv, - child_setup, NULL, + child_setup, activation, error)) return FALSE; diff --git a/bus/activation.h b/bus/activation.h index e7a9cdfc..4e363c92 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -25,12 +25,17 @@ #define BUS_ACTIVATION_H #include +#include "bus.h" + +BusActivation* bus_activation_new (const char *address, + const char **paths, + DBusError *error); +void bus_activation_ref (BusActivation *activation); +void bus_activation_unref (BusActivation *activation); +dbus_bool_t bus_activation_activate_service (BusActivation *activation, + const char *service_name, + DBusError *error); -dbus_bool_t bus_activation_init (const char *address, - const char **paths, - DBusError *error); -dbus_bool_t bus_activation_activate_service (const char *service_name, - DBusError *error); #endif /* BUS_ACTIVATION_H */ diff --git a/bus/bus.c b/bus/bus.c new file mode 100644 index 00000000..7ac0beee --- /dev/null +++ b/bus/bus.c @@ -0,0 +1,202 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* bus.c message bus context object + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "bus.h" +#include "loop.h" +#include "activation.h" +#include "connection.h" +#include "services.h" +#include "utils.h" +#include + +struct BusContext +{ + int refcount; + char *address; + DBusServer *server; + BusConnections *connections; + BusActivation *activation; + BusRegistry *registry; +}; + +static void +server_watch_callback (DBusWatch *watch, + unsigned int condition, + void *data) +{ + BusContext *context = data; + + dbus_server_handle_watch (context->server, watch, condition); +} + +static void +add_server_watch (DBusWatch *watch, + BusContext *context) +{ + bus_loop_add_watch (watch, server_watch_callback, context, + NULL); +} + +static void +remove_server_watch (DBusWatch *watch, + BusContext *context) +{ + bus_loop_remove_watch (watch, server_watch_callback, context); +} + +static void +new_connection_callback (DBusServer *server, + DBusConnection *new_connection, + void *data) +{ + BusContext *context = data; + + if (!bus_connections_setup_connection (context->connections, new_connection)) + _dbus_verbose ("No memory to setup new connection\n"); + + /* on OOM, we won't have ref'd the connection so it will die */ +} + +BusContext* +bus_context_new (const char *address, + const char **service_dirs, + DBusError *error) +{ + BusContext *context; + DBusResultCode result; + + context = dbus_new0 (BusContext, 1); + if (context == NULL) + { + BUS_SET_OOM (error); + return NULL; + } + + context->refcount = 1; + + context->address = _dbus_strdup (address); + if (context->address == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + + context->server = dbus_server_listen (address, &result); + if (context->server == NULL) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to start server on %s: %s\n", + address, dbus_result_to_string (result)); + goto failed; + } + + context->activation = bus_activation_new (address, service_dirs, + error); + if (context->activation == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + + context->connections = bus_connections_new (context); + if (context->connections == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + + context->registry = bus_registry_new (); + if (context->registry == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + + dbus_server_set_new_connection_function (context->server, + new_connection_callback, + context, NULL); + + dbus_server_set_watch_functions (context->server, + (DBusAddWatchFunction) add_server_watch, + (DBusRemoveWatchFunction) remove_server_watch, + context, + NULL); + + return context; + + failed: + bus_context_unref (context); + return NULL; +} + +void +bus_context_shutdown (BusContext *context) +{ + dbus_server_disconnect (context->server); +} + +void +bus_context_ref (BusContext *context) +{ + _dbus_assert (context->refcount > 0); + context->refcount += 1; +} + +void +bus_context_unref (BusContext *context) +{ + _dbus_assert (context->refcount > 0); + context->refcount -= 1; + + if (context->refcount == 0) + { + if (context->registry) + bus_registry_unref (context->registry); + if (context->connections) + bus_connections_unref (context->connections); + if (context->activation) + bus_activation_unref (context->activation); + if (context->server) + dbus_server_unref (context->server); + dbus_free (context->address); + dbus_free (context); + } +} + +BusRegistry* +bus_context_get_registry (BusContext *context) +{ + return context->registry; +} + +BusConnections* +bus_context_get_connections (BusContext *context) +{ + return context->connections; +} + +BusActivation* +bus_context_get_activation (BusContext *context) +{ + return context->activation; +} diff --git a/bus/bus.h b/bus/bus.h new file mode 100644 index 00000000..4d922f0c --- /dev/null +++ b/bus/bus.h @@ -0,0 +1,48 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* bus.h message bus context object + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef BUS_BUS_H +#define BUS_BUS_H + +#include +#include + +typedef struct BusActivation BusActivation; +typedef struct BusConnections BusConnections; +typedef struct BusContext BusContext; +typedef struct BusRegistry BusRegistry; +typedef struct BusService BusService; +typedef struct BusTransaction BusTransaction; + +BusContext* bus_context_new (const char *address, + const char **service_dirs, + DBusError *error); +void bus_context_shutdown (BusContext *context); +void bus_context_ref (BusContext *context); +void bus_context_unref (BusContext *context); +BusRegistry* bus_context_get_registry (BusContext *context); +BusConnections* bus_context_get_connections (BusContext *context); +BusActivation* bus_context_get_activation (BusContext *context); + + +#endif /* BUS_BUS_H */ diff --git a/bus/connection.c b/bus/connection.c index ff671c58..cdc8be79 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -29,11 +29,18 @@ static void bus_connection_remove_transactions (DBusConnection *connection); -static int connection_data_slot; -static DBusList *connections = NULL; +struct BusConnections +{ + int refcount; + DBusList *list; /**< List of all the connections */ + BusContext *context; +}; + +static int connection_data_slot = -1; typedef struct { + BusConnections *connections; DBusConnection *connection; DBusList *services_owned; char *name; @@ -74,7 +81,7 @@ bus_connection_disconnected (DBusConnection *connection) transaction = NULL; while (transaction == NULL) { - transaction = bus_transaction_new (); + transaction = bus_transaction_new (d->connections->context); bus_wait_for_memory (); } @@ -107,12 +114,14 @@ bus_connection_disconnected (DBusConnection *connection) NULL); bus_connection_remove_transactions (connection); - + + _dbus_list_remove (&d->connections->list, connection); + + /* frees "d" as side effect */ dbus_connection_set_data (connection, connection_data_slot, NULL, NULL); - - _dbus_list_remove (&connections, connection); + dbus_connection_unref (connection); } @@ -166,19 +175,55 @@ free_connection_data (void *data) dbus_free (d); } -dbus_bool_t -bus_connection_init (void) +BusConnections* +bus_connections_new (BusContext *context) { - connection_data_slot = dbus_connection_allocate_data_slot (); + BusConnections *connections; if (connection_data_slot < 0) - return FALSE; + { + connection_data_slot = dbus_connection_allocate_data_slot (); + + if (connection_data_slot < 0) + return NULL; + } - return TRUE; + connections = dbus_new0 (BusConnections, 1); + if (connections == NULL) + return NULL; + + connections->refcount = 1; + connections->context = context; + + return connections; +} + +void +bus_connections_ref (BusConnections *connections) +{ + _dbus_assert (connections->refcount > 0); + connections->refcount += 1; +} + +void +bus_connections_unref (BusConnections *connections) +{ + _dbus_assert (connections->refcount > 0); + connections->refcount -= 1; + if (connections->refcount == 0) + { + /* FIXME free each connection... */ + _dbus_assert_not_reached ("shutting down connections not implemented"); + + _dbus_list_clear (&connections->list); + + dbus_free (connections); + } } dbus_bool_t -bus_connection_setup (DBusConnection *connection) +bus_connections_setup_connection (BusConnections *connections, + DBusConnection *connection) { BusConnectionData *d; @@ -187,6 +232,7 @@ bus_connection_setup (DBusConnection *connection) if (d == NULL) return FALSE; + d->connections = connections; d->connection = connection; if (!dbus_connection_set_data (connection, @@ -197,7 +243,7 @@ bus_connection_setup (DBusConnection *connection) return FALSE; } - if (!_dbus_list_append (&connections, connection)) + if (!_dbus_list_append (&connections->list, connection)) { /* this will free our data when connection gets finalized */ dbus_connection_disconnect (connection); @@ -219,6 +265,89 @@ bus_connection_setup (DBusConnection *connection) return TRUE; } + +/** + * Calls function on each connection; if the function returns + * #FALSE, stops iterating. + * + * @param connections the connections object + * @param function the function + * @param data data to pass to it as a second arg + */ +void +bus_connections_foreach (BusConnections *connections, + BusConnectionForeachFunction function, + void *data) +{ + DBusList *link; + + link = _dbus_list_get_first_link (&connections->list); + while (link != NULL) + { + DBusConnection *connection = link->data; + DBusList *next = _dbus_list_get_next_link (&connections->list, link); + + if (!(* function) (connection, data)) + break; + + link = next; + } +} + +BusContext* +bus_connections_get_context (BusConnections *connections) +{ + return connections->context; +} + +BusContext* +bus_connection_get_context (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + + _dbus_assert (d != NULL); + + return d->connections->context; +} + +BusConnections* +bus_connection_get_connections (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + + _dbus_assert (d != NULL); + + return d->connections; +} + +BusRegistry* +bus_connection_get_registry (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + + _dbus_assert (d != NULL); + + return bus_context_get_registry (d->connections->context); +} + +BusActivation* +bus_connection_get_activation (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + + _dbus_assert (d != NULL); + + return bus_context_get_activation (d->connections->context); +} + /** * Checks whether the connection is registered with the message bus. * @@ -361,32 +490,6 @@ bus_connection_get_name (DBusConnection *connection) return d->name; } -/** - * Calls function on each connection; if the function returns - * #FALSE, stops iterating. - * - * @param function the function - * @param data data to pass to it as a second arg - */ -void -bus_connection_foreach (BusConnectionForeachFunction function, - void *data) -{ - DBusList *link; - - link = _dbus_list_get_first_link (&connections); - while (link != NULL) - { - DBusConnection *connection = link->data; - DBusList *next = _dbus_list_get_next_link (&connections, link); - - if (!(* function) (connection, data)) - break; - - link = next; - } -} - typedef struct { BusTransaction *transaction; @@ -397,7 +500,7 @@ typedef struct struct BusTransaction { DBusList *connections; - + BusContext *context; }; static void @@ -414,7 +517,7 @@ message_to_send_free (DBusConnection *connection, } BusTransaction* -bus_transaction_new (void) +bus_transaction_new (BusContext *context) { BusTransaction *transaction; @@ -422,9 +525,23 @@ bus_transaction_new (void) if (transaction == NULL) return NULL; + transaction->context = context; + return transaction; } +BusContext* +bus_transaction_get_context (BusTransaction *transaction) +{ + return transaction->context; +} + +BusConnections* +bus_transaction_get_connections (BusTransaction *transaction) +{ + return bus_context_get_connections (transaction->context); +} + dbus_bool_t bus_transaction_send_message (BusTransaction *transaction, DBusConnection *connection, diff --git a/bus/connection.h b/bus/connection.h index a7a448a1..f78c3ac1 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -25,14 +25,26 @@ #define BUS_CONNECTION_H #include -#include "services.h" +#include "bus.h" typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection, void *data); -dbus_bool_t bus_connection_init (void); -dbus_bool_t bus_connection_setup (DBusConnection *connection); +BusConnections* bus_connections_new (BusContext *context); +void bus_connections_ref (BusConnections *connections); +void bus_connections_unref (BusConnections *connections); +dbus_bool_t bus_connections_setup_connection (BusConnections *connections, + DBusConnection *connection); +void bus_connections_foreach (BusConnections *connections, + BusConnectionForeachFunction function, + void *data); +BusContext* bus_connections_get_context (BusConnections *connections); + +BusContext* bus_connection_get_context (DBusConnection *connection); +BusConnections* bus_connection_get_connections (DBusConnection *connection); +BusRegistry* bus_connection_get_registry (DBusConnection *connection); +BusActivation* bus_connection_get_activation (DBusConnection *connection); dbus_bool_t bus_connection_is_active (DBusConnection *connection); @@ -50,14 +62,14 @@ void bus_connection_remove_owned_service (DBusConnection *connection, dbus_bool_t bus_connection_set_name (DBusConnection *connection, const DBusString *name); const char *bus_connection_get_name (DBusConnection *connection); -void bus_connection_foreach (BusConnectionForeachFunction function, - void *data); /* called by dispatch.c when the connection is dropped */ void bus_connection_disconnected (DBusConnection *connection); /* transaction API so we can send or not send a block of messages as a whole */ -BusTransaction* bus_transaction_new (void); +BusTransaction* bus_transaction_new (BusContext *context); +BusContext* bus_transaction_get_context (BusTransaction *transaction); +BusConnections* bus_transaction_get_connections (BusTransaction *transaction); dbus_bool_t bus_transaction_send_message (BusTransaction *transaction, DBusConnection *connection, DBusMessage *message); diff --git a/bus/dispatch.c b/bus/dispatch.c index d9fe81ac..1d2ea1c2 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -24,7 +24,9 @@ #include "dispatch.h" #include "connection.h" #include "driver.h" +#include "services.h" #include "utils.h" +#include "bus.h" #include #include @@ -63,14 +65,18 @@ bus_dispatch_broadcast_message (BusTransaction *transaction, { DBusError tmp_error; SendMessageData d; + BusConnections *connections; _dbus_assert (dbus_message_get_sender (message) != NULL); + connections = bus_transaction_get_connections (transaction); + dbus_error_init (&tmp_error); d.message = message; d.transaction = transaction; d.error = &tmp_error; - bus_connection_foreach (send_one_message, &d); + + bus_connections_foreach (connections, send_one_message, &d); if (dbus_error_is_set (&tmp_error)) { @@ -145,9 +151,13 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, const char *sender, *service_name, *message_name; DBusError error; BusTransaction *transaction; - + BusContext *context; + transaction = NULL; dbus_error_init (&error); + + context = bus_connection_get_context (connection); + _dbus_assert (context != NULL); /* If we can't even allocate an OOM error, we just go to sleep * until we can. @@ -181,7 +191,7 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, _dbus_assert (service_name != NULL); /* this message is intended for bus routing */ /* Create our transaction */ - transaction = bus_transaction_new (); + transaction = bus_transaction_new (context); if (transaction == NULL) { BUS_SET_OOM (&error); @@ -224,9 +234,12 @@ bus_dispatch_message_handler (DBusMessageHandler *handler, { DBusString service_string; BusService *service; + BusRegistry *registry; + registry = bus_connection_get_registry (connection); + _dbus_string_init_const (&service_string, service_name); - service = bus_service_lookup (&service_string); + service = bus_registry_lookup (registry, &service_string); if (service == NULL) { diff --git a/bus/driver.c b/bus/driver.c index 46985594..09ec18af 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -199,7 +199,8 @@ bus_driver_send_service_acquired (DBusConnection *connection, } static dbus_bool_t -create_unique_client_name (DBusString *str) +create_unique_client_name (BusRegistry *registry, + DBusString *str) { /* We never want to use the same unique client name twice, because * we want to guarantee that if you send a message to a given unique @@ -246,7 +247,7 @@ create_unique_client_name (DBusString *str) next_minor_number += 1; /* Check if a client with the name exists */ - if (bus_service_lookup (str) == NULL) + if (bus_registry_lookup (registry, str) == NULL) break; /* drop the number again, try the next one. */ @@ -265,6 +266,7 @@ bus_driver_handle_hello (DBusConnection *connection, DBusString unique_name; BusService *service; dbus_bool_t retval; + BusRegistry *registry; if (!_dbus_string_init (&unique_name, _DBUS_INT_MAX)) { @@ -273,8 +275,10 @@ bus_driver_handle_hello (DBusConnection *connection, } retval = FALSE; + + registry = bus_connection_get_registry (connection); - if (!create_unique_client_name (&unique_name)) + if (!create_unique_client_name (registry, &unique_name)) { BUS_SET_OOM (error); goto out_0; @@ -297,7 +301,8 @@ bus_driver_handle_hello (DBusConnection *connection, goto out_0; /* Create the service */ - service = bus_service_ensure (&unique_name, connection, transaction, error); + service = bus_registry_ensure (registry, + &unique_name, connection, transaction, error); if (service == NULL) goto out_0; @@ -367,7 +372,10 @@ bus_driver_handle_list_services (DBusConnection *connection, DBusMessage *reply; int len; char **services; - + BusRegistry *registry; + + registry = bus_connection_get_registry (connection); + reply = dbus_message_new_reply (message); if (reply == NULL) { @@ -375,8 +383,7 @@ bus_driver_handle_list_services (DBusConnection *connection, return FALSE; } - services = bus_services_list (&len); - if (services == NULL) + if (!bus_registry_list_services (registry, &services, &len)) { dbus_message_unref (reply); BUS_SET_OOM (error); @@ -423,6 +430,9 @@ bus_driver_handle_acquire_service (DBusConnection *connection, dbus_bool_t retval; DBusConnection *old_owner; DBusConnection *current_owner; + BusRegistry *registry; + + registry = bus_connection_get_registry (connection); if (!dbus_message_get_args (message, error, @@ -438,7 +448,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, _dbus_string_init_const (&service_name, name); - service = bus_service_lookup (&service_name); + service = bus_registry_lookup (registry, &service_name); if (service != NULL) old_owner = bus_service_get_primary_owner (service); @@ -454,7 +464,8 @@ bus_driver_handle_acquire_service (DBusConnection *connection, if (service == NULL) { - service = bus_service_ensure (&service_name, connection, transaction, error); + service = bus_registry_ensure (registry, + &service_name, connection, transaction, error); if (service == NULL) goto out; } @@ -542,6 +553,9 @@ bus_driver_handle_service_exists (DBusConnection *connection, BusService *service; char *name; dbus_bool_t retval; + BusRegistry *registry; + + registry = bus_connection_get_registry (connection); if (!dbus_message_get_args (message, error, DBUS_TYPE_STRING, &name, @@ -551,7 +565,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, retval = FALSE; _dbus_string_init_const (&service_name, name); - service = bus_service_lookup (&service_name); + service = bus_registry_lookup (registry, &service_name); reply = dbus_message_new_reply (message); if (reply == NULL) @@ -599,6 +613,9 @@ bus_driver_handle_activate_service (DBusConnection *connection, dbus_uint32_t flags; char *name; dbus_bool_t retval; + BusActivation *activation; + + activation = bus_connection_get_activation (connection); if (!dbus_message_get_args (message, error, DBUS_TYPE_STRING, &name, @@ -608,7 +625,7 @@ bus_driver_handle_activate_service (DBusConnection *connection, retval = FALSE; - if (!bus_activation_activate_service (name, error)) + if (!bus_activation_activate_service (activation, name, error)) goto out; retval = TRUE; diff --git a/bus/main.c b/bus/main.c index 56345c76..ce03a6a7 100644 --- a/bus/main.c +++ b/bus/main.c @@ -20,110 +20,41 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ +#include "bus.h" #include "loop.h" -#include "activation.h" -#include "connection.h" -#include "driver.h" -#include - -static void -server_watch_callback (DBusWatch *watch, - unsigned int condition, - void *data) -{ - DBusServer *server = data; - - dbus_server_handle_watch (server, watch, condition); -} - -static void -add_server_watch (DBusWatch *watch, - DBusServer *server) -{ - bus_loop_add_watch (watch, server_watch_callback, server, - NULL); -} - -static void -remove_server_watch (DBusWatch *watch, - DBusServer *server) -{ - bus_loop_remove_watch (watch, server_watch_callback, server); -} - -static void -setup_server (DBusServer *server) -{ - dbus_server_set_watch_functions (server, - (DBusAddWatchFunction) add_server_watch, - (DBusRemoveWatchFunction) remove_server_watch, - server, - NULL); -} - -static void -new_connection_callback (DBusServer *server, - DBusConnection *new_connection, - void *data) -{ - if (!bus_connection_setup (new_connection)) - ; /* we won't have ref'd the connection so it will die */ -} +#include int main (int argc, char **argv) { - DBusServer *server; - DBusResultCode result; - - if (argc < 2) + BusContext *context; + DBusError error; + const char *paths[] = { NULL, NULL }; + + if (argc < 3) { - _dbus_warn ("Give the server address as an argument\n"); + /* FIXME obviously just for testing */ + _dbus_warn ("Give the server address as an argument and activation directory as args\n"); return 1; } + paths[0] = argv[2]; - server = dbus_server_listen (argv[1], &result); - if (server == NULL) + dbus_error_init (&error); + context = bus_context_new (argv[1], paths, &error); + if (context == NULL) { - _dbus_warn ("Failed to start server on %s: %s\n", - argv[1], dbus_result_to_string (result)); + _dbus_warn ("Failed to start message bus: %s\n", + error.message); + dbus_error_free (&error); return 1; } - if (argc < 3) - { - _dbus_warn ("No service location given, not activating activation\n"); - } - else - { - const char *paths[] = { argv[2], NULL }; - DBusError error; - - dbus_error_init (&error); - if (!bus_activation_init (argv[1], paths, - &error)) - { - _dbus_warn ("Could not initialize service activation: %s\n", - error.message); - dbus_error_free (&error); - return 1; - } - } - - setup_server (server); - - bus_connection_init (); - - dbus_server_set_new_connection_function (server, - new_connection_callback, - NULL, NULL); - _dbus_verbose ("We are on D-Bus...\n"); bus_loop_run (); - dbus_server_disconnect (server); - dbus_server_unref (server); + bus_context_shutdown (context); + bus_context_unref (context); return 0; } diff --git a/bus/services.c b/bus/services.c index 22302af4..9508b2f7 100644 --- a/bus/services.c +++ b/bus/services.c @@ -32,65 +32,94 @@ struct BusService { + BusRegistry *registry; char *name; DBusList *owners; unsigned int prohibit_replacement : 1; }; -static DBusHashTable *service_hash = NULL; -static DBusMemPool *service_pool = NULL; +struct BusRegistry +{ + int refcount; + + DBusHashTable *service_hash; + DBusMemPool *service_pool; +}; + +BusRegistry* +bus_registry_new (void) +{ + BusRegistry *registry; + + registry = dbus_new0 (BusRegistry, 1); + if (registry == NULL) + return NULL; + + registry->refcount = 1; + + registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING, + NULL, NULL); + if (registry->service_hash == NULL) + goto failed; + + registry->service_pool = _dbus_mem_pool_new (sizeof (BusService), + TRUE); + if (registry->service_pool == NULL) + goto failed; + + return registry; + + failed: + bus_registry_unref (registry); + return NULL; +} + +void +bus_registry_ref (BusRegistry *registry) +{ + _dbus_assert (registry->refcount > 0); + registry->refcount += 1; +} -static dbus_bool_t -init_hash (void) +void +bus_registry_unref (BusRegistry *registry) { - if (service_hash == NULL) + _dbus_assert (registry->refcount > 0); + registry->refcount -= 1; + + if (registry->refcount == 0) { - service_hash = _dbus_hash_table_new (DBUS_HASH_STRING, - NULL, NULL); - service_pool = _dbus_mem_pool_new (sizeof (BusService), - TRUE); + if (registry->service_hash) + _dbus_hash_table_unref (registry->service_hash); + if (registry->service_pool) + _dbus_mem_pool_free (registry->service_pool); - if (service_hash == NULL || service_pool == NULL) - { - if (service_hash) - { - _dbus_hash_table_unref (service_hash); - service_hash = NULL; - } - if (service_pool) - { - _dbus_mem_pool_free (service_pool); - service_pool = NULL; - } - return FALSE; - } + dbus_free (registry); } - return TRUE; } BusService* -bus_service_lookup (const DBusString *service_name) +bus_registry_lookup (BusRegistry *registry, + const DBusString *service_name) { const char *c_name; BusService *service; - if (!init_hash ()) - return NULL; - _dbus_string_get_const_data (service_name, &c_name); - service = _dbus_hash_table_lookup_string (service_hash, + service = _dbus_hash_table_lookup_string (registry->service_hash, c_name); return service; } BusService* -bus_service_ensure (const DBusString *service_name, - DBusConnection *owner_if_created, - BusTransaction *transaction, - DBusError *error) +bus_registry_ensure (BusRegistry *registry, + const DBusString *service_name, + DBusConnection *owner_if_created, + BusTransaction *transaction, + DBusError *error) { const char *c_name; BusService *service; @@ -98,27 +127,26 @@ bus_service_ensure (const DBusString *service_name, _dbus_assert (owner_if_created != NULL); _dbus_assert (transaction != NULL); - if (!init_hash ()) - return NULL; - _dbus_string_get_const_data (service_name, &c_name); - service = _dbus_hash_table_lookup_string (service_hash, + service = _dbus_hash_table_lookup_string (registry->service_hash, c_name); if (service != NULL) return service; - service = _dbus_mem_pool_alloc (service_pool); + service = _dbus_mem_pool_alloc (registry->service_pool); if (service == NULL) { BUS_SET_OOM (error); return NULL; } + service->registry = registry; + service->name = _dbus_strdup (c_name); if (service->name == NULL) { - _dbus_mem_pool_dealloc (service_pool, service); + _dbus_mem_pool_dealloc (registry->service_pool, service); BUS_SET_OOM (error); return NULL; } @@ -126,7 +154,7 @@ bus_service_ensure (const DBusString *service_name, if (!bus_driver_send_service_created (service->name, transaction, error)) { dbus_free (service->name); - _dbus_mem_pool_dealloc (service_pool, service); + _dbus_mem_pool_dealloc (registry->service_pool, service); return NULL; } @@ -134,17 +162,17 @@ bus_service_ensure (const DBusString *service_name, transaction, error)) { dbus_free (service->name); - _dbus_mem_pool_dealloc (service_pool, service); + _dbus_mem_pool_dealloc (registry->service_pool, service); return NULL; } - if (!_dbus_hash_table_insert_string (service_hash, + if (!_dbus_hash_table_insert_string (registry->service_hash, service->name, service)) { _dbus_list_clear (&service->owners); dbus_free (service->name); - _dbus_mem_pool_dealloc (service_pool, service); + _dbus_mem_pool_dealloc (registry->service_pool, service); BUS_SET_OOM (error); return NULL; } @@ -152,6 +180,66 @@ bus_service_ensure (const DBusString *service_name, return service; } +void +bus_registry_foreach (BusRegistry *registry, + BusServiceForeachFunction function, + void *data) +{ + DBusHashIter iter; + + _dbus_hash_iter_init (registry->service_hash, &iter); + while (_dbus_hash_iter_next (&iter)) + { + BusService *service = _dbus_hash_iter_get_value (&iter); + + (* function) (service, data); + } +} + +dbus_bool_t +bus_registry_list_services (BusRegistry *registry, + char ***listp, + int *array_len) +{ + int i, j, len; + char **retval; + DBusHashIter iter; + + len = _dbus_hash_table_get_n_entries (registry->service_hash); + retval = dbus_new (char *, len + 1); + + if (retval == NULL) + return FALSE; + + _dbus_hash_iter_init (registry->service_hash, &iter); + i = 0; + while (_dbus_hash_iter_next (&iter)) + { + BusService *service = _dbus_hash_iter_get_value (&iter); + + retval[i] = _dbus_strdup (service->name); + if (retval[i] == NULL) + goto error; + + i++; + } + + retval[i] = NULL; + + if (array_len) + *array_len = len; + + *listp = retval; + return TRUE; + + error: + for (j = 0; j < i; j++) + dbus_free (retval[i]); + dbus_free (retval); + + return FALSE; +} + dbus_bool_t bus_service_add_owner (BusService *service, DBusConnection *owner, @@ -232,10 +320,10 @@ bus_service_remove_owner (BusService *service, if (service->owners == NULL) { /* Delete service (already sent message that it was deleted above) */ - _dbus_hash_table_remove_string (service_hash, service->name); + _dbus_hash_table_remove_string (service->registry->service_hash, service->name); dbus_free (service->name); - _dbus_mem_pool_dealloc (service_pool, service); + _dbus_mem_pool_dealloc (service->registry->service_pool, service); } return TRUE; @@ -253,65 +341,6 @@ bus_service_get_name (BusService *service) return service->name; } -void -bus_service_foreach (BusServiceForeachFunction function, - void *data) -{ - DBusHashIter iter; - - if (service_hash == NULL) - return; - - _dbus_hash_iter_init (service_hash, &iter); - while (_dbus_hash_iter_next (&iter)) - { - BusService *service = _dbus_hash_iter_get_value (&iter); - - (* function) (service, data); - } -} - -char ** -bus_services_list (int *array_len) -{ - int i, j, len; - char **retval; - DBusHashIter iter; - - len = _dbus_hash_table_get_n_entries (service_hash); - retval = dbus_new (char *, len + 1); - - if (retval == NULL) - return NULL; - - _dbus_hash_iter_init (service_hash, &iter); - i = 0; - while (_dbus_hash_iter_next (&iter)) - { - BusService *service = _dbus_hash_iter_get_value (&iter); - - retval[i] = _dbus_strdup (service->name); - if (retval[i] == NULL) - goto error; - - i++; - } - - retval[i] = NULL; - - if (array_len) - *array_len = len; - - return retval; - - error: - for (j = 0; j < i; j++) - dbus_free (retval[i]); - dbus_free (retval); - - return NULL; -} - void bus_service_set_prohibit_replacement (BusService *service, dbus_bool_t prohibit_replacement) diff --git a/bus/services.h b/bus/services.h index 97583582..5e9ece18 100644 --- a/bus/services.h +++ b/bus/services.h @@ -27,26 +27,29 @@ #include #include #include "connection.h" - -/* forward decl that probably shouldn't be in this file */ -typedef struct BusTransaction BusTransaction; - -/* Each service can have multiple owners; one owner is the "real - * owner" and the others are queued up. For example, if I have - * multiple text editors open, one might own the TextEditor service; - * if I close that one, the next in line will become the owner of it. - */ - -typedef struct BusService BusService; +#include "bus.h" typedef void (* BusServiceForeachFunction) (BusService *service, void *data); -BusService* bus_service_lookup (const DBusString *service_name); -BusService* bus_service_ensure (const DBusString *service_name, - DBusConnection *owner_if_created, - BusTransaction *transaction, - DBusError *error); +BusRegistry* bus_registry_new (void); +void bus_registry_ref (BusRegistry *registry); +void bus_registry_unref (BusRegistry *registry); +BusService* bus_registry_lookup (BusRegistry *registry, + const DBusString *service_name); +BusService* bus_registry_ensure (BusRegistry *registry, + const DBusString *service_name, + DBusConnection *owner_if_created, + BusTransaction *transaction, + DBusError *error); +void bus_registry_foreach (BusRegistry *registry, + BusServiceForeachFunction function, + void *data); +dbus_bool_t bus_registry_list_services (BusRegistry *registry, + char ***listp, + int *array_len); + + dbus_bool_t bus_service_add_owner (BusService *service, DBusConnection *owner, BusTransaction *transaction, @@ -62,10 +65,5 @@ void bus_service_set_prohibit_replacement (BusService 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); #endif /* BUS_SERVICES_H */ -- cgit