2003-03-12 Havoc Pennington <hp@pobox.com>

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
This commit is contained in:
Havoc Pennington 2003-03-13 03:52:58 +00:00
parent 29560adcc7
commit 6ecc14ffab
14 changed files with 742 additions and 327 deletions

View file

@ -1,3 +1,14 @@
2003-03-12 Havoc Pennington <hp@pobox.com>
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
2003-03-12 Havoc Pennington <hp@redhat.com>
Mega-patch that gets the message bus daemon initially handling

View file

@ -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 \

View file

@ -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;

View file

@ -25,12 +25,17 @@
#define BUS_ACTIVATION_H
#include <dbus/dbus.h>
#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 */

202
bus/bus.c Normal file
View file

@ -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 <dbus/dbus-internals.h>
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;
}

48
bus/bus.h Normal file
View file

@ -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 <dbus/dbus.h>
#include <dbus/dbus-string.h>
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 */

View file

@ -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,

View file

@ -25,14 +25,26 @@
#define BUS_CONNECTION_H
#include <dbus/dbus.h>
#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);

View file

@ -24,7 +24,9 @@
#include "dispatch.h"
#include "connection.h"
#include "driver.h"
#include "services.h"
#include "utils.h"
#include "bus.h"
#include <dbus/dbus-internals.h>
#include <string.h>
@ -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)
{

View file

@ -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;

View file

@ -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 <dbus/dbus-list.h>
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 <dbus/dbus-internals.h>
int
main (int argc, char **argv)
{
DBusServer *server;
DBusResultCode result;
if (argc < 2)
{
_dbus_warn ("Give the server address as an argument\n");
return 1;
}
BusContext *context;
DBusError error;
const char *paths[] = { NULL, NULL };
server = dbus_server_listen (argv[1], &result);
if (server == NULL)
{
_dbus_warn ("Failed to start server on %s: %s\n",
argv[1], dbus_result_to_string (result));
return 1;
}
if (argc < 3)
{
_dbus_warn ("No service location given, not activating activation\n");
/* FIXME obviously just for testing */
_dbus_warn ("Give the server address as an argument and activation directory as args\n");
return 1;
}
else
paths[0] = argv[2];
dbus_error_init (&error);
context = bus_context_new (argv[1], paths, &error);
if (context == NULL)
{
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;
}
_dbus_warn ("Failed to start message bus: %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;
}

View file

@ -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;
static dbus_bool_t
init_hash (void)
struct BusRegistry
{
if (service_hash == NULL)
{
service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
NULL, NULL);
service_pool = _dbus_mem_pool_new (sizeof (BusService),
TRUE);
int refcount;
DBusHashTable *service_hash;
DBusMemPool *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;
}
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;
}
void
bus_registry_unref (BusRegistry *registry)
{
_dbus_assert (registry->refcount > 0);
registry->refcount -= 1;
if (registry->refcount == 0)
{
if (registry->service_hash)
_dbus_hash_table_unref (registry->service_hash);
if (registry->service_pool)
_dbus_mem_pool_free (registry->service_pool);
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)

View file

@ -27,26 +27,29 @@
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
#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 */

View file

@ -2,7 +2,7 @@
INCLUDES=-I$(top_srcdir) $(DBUS_TEST_CFLAGS)
if DBUS_BUILD_TESTS
TEST_BINARIES=echo-client echo-server unbase64 bus-test break-loader spawn-test
TEST_BINARIES=echo-client echo-server unbase64 break-loader spawn-test
else
TEST_BINARIES=
endif
@ -22,13 +22,12 @@ echo_server_SOURCES= \
unbase64_SOURCES= \
unbase64.c
bus_test_SOURCES = \
debug-thread.c \
debug-thread.h \
bus-test.c \
bus-test-loop.c \
bus-test-loop.h
# bus_test_SOURCES = \
# debug-thread.c \
# debug-thread.h \
# bus-test.c \
# bus-test-loop.c \
# bus-test-loop.h
break_loader_SOURCES= \
break-loader.c
@ -42,7 +41,7 @@ echo_client_LDADD=$(TEST_LIBS)
echo_server_LDADD=$(TEST_LIBS)
unbase64_LDADD=$(TEST_LIBS)
break_loader_LDADD= $(TEST_LIBS)
bus_test_LDADD=$(TEST_LIBS) $(top_builddir)/bus/libdbus-daemon.la
#bus_test_LDADD=$(TEST_LIBS) $(top_builddir)/bus/libdbus-daemon.la
spawn_test_LDADD=$(TEST_LIBS)
dist-hook: