diff options
Diffstat (limited to 'bus')
-rw-r--r-- | bus/Makefile.am | 2 | ||||
-rw-r--r-- | bus/connection.c | 44 | ||||
-rw-r--r-- | bus/connection.h | 7 | ||||
-rw-r--r-- | bus/driver.c | 217 | ||||
-rw-r--r-- | bus/driver.h | 32 | ||||
-rw-r--r-- | bus/main.c | 1 | ||||
-rw-r--r-- | bus/services.c | 11 | ||||
-rw-r--r-- | bus/services.h | 10 |
8 files changed, 318 insertions, 6 deletions
diff --git a/bus/Makefile.am b/bus/Makefile.am index b7f4504a..af25867b 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -9,6 +9,8 @@ bin_PROGRAMS=dbus-daemon-1 dbus_daemon_1_SOURCES= \ connection.c \ connection.h \ + driver.c \ + driver.h \ loop.c \ loop.h \ main.c \ diff --git a/bus/connection.c b/bus/connection.c index a80e46d4..4a805731 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -21,6 +21,7 @@ * */ #include "connection.h" +#include "driver.h" #include "loop.h" #include "services.h" #include <dbus/dbus-list.h> @@ -32,6 +33,7 @@ typedef struct { DBusList *services_owned; + char *name; } BusConnectionData; #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot)) @@ -52,6 +54,9 @@ connection_disconnect_handler (DBusConnection *connection, while ((service = _dbus_list_get_last (&d->services_owned))) bus_service_remove_owner (service, connection); + /* Tell bus driver that we want to get off */ + bus_driver_remove_connection (connection); + /* no more watching */ dbus_connection_set_watch_functions (connection, NULL, NULL, @@ -74,6 +79,8 @@ connection_watch_callback (DBusWatch *watch, DBusConnection *connection = data; dbus_connection_handle_watch (connection, watch, condition); + + while (dbus_connection_dispatch_message (connection)); } static void @@ -98,6 +105,8 @@ free_connection_data (void *data) /* services_owned should be NULL since we should be disconnected */ _dbus_assert (d->services_owned == NULL); + + dbus_free (d->name); dbus_free (d); } @@ -150,6 +159,9 @@ bus_connection_setup (DBusConnection *connection) connection_disconnect_handler, NULL, NULL); + if (!bus_driver_add_connection (connection)) + return FALSE; + return TRUE; } @@ -180,3 +192,35 @@ bus_connection_remove_owned_service (DBusConnection *connection, _dbus_list_remove_last (&d->services_owned, service); } + +dbus_bool_t +bus_connection_set_name (DBusConnection *connection, + const DBusString *name) +{ + const char *c_name; + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); + _dbus_assert (d->name == NULL); + + _dbus_string_get_const_data (name, &c_name); + + d->name = _dbus_strdup (c_name); + + if (d->name == NULL) + return FALSE; + + return TRUE; +} + +const char * +bus_connection_get_name (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); + + return d->name; +} diff --git a/bus/connection.h b/bus/connection.h index e6f9d10d..1a23867b 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -31,11 +31,16 @@ dbus_bool_t bus_connection_init (void); dbus_bool_t bus_connection_setup (DBusConnection *connection); - /* called by services.c */ dbus_bool_t bus_connection_add_owned_service (DBusConnection *connection, BusService *service); void bus_connection_remove_owned_service (DBusConnection *connection, BusService *service); +/* called by driver.c */ +dbus_bool_t bus_connection_set_name (DBusConnection *connection, + const DBusString *name); +const char *bus_connection_get_name (DBusConnection *connection); + + #endif /* BUS_CONNECTION_H */ diff --git a/bus/driver.c b/bus/driver.c new file mode 100644 index 00000000..d24cb77f --- /dev/null +++ b/bus/driver.c @@ -0,0 +1,217 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* bus.c Bus client (driver) + * + * Copyright (C) 2003 CodeFactory AB + * + * 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 "connection.h" +#include "driver.h" +#include "services.h" +#include <dbus/dbus-internals.h> +#include <dbus/dbus-string.h> +#include <string.h> + +#define BUS_DRIVER_SERVICE_NAME "org.freedesktop.DBus" +#define BUS_DRIVER_HELLO_NAME "org.freedesktop.DBus.Hello" +#define BUS_DRIVER_WELCOME_NAME "org.freedesktop.DBus.Welcome" + +static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection, + DBusMessage *hello_message); + +static dbus_bool_t +create_unique_client_name (const char *name, DBusString *str) +{ + int i, len; + + if (!_dbus_string_init (str, _DBUS_INT_MAX)) + return FALSE; + + if (!_dbus_string_append (str, name)) + return FALSE; + + len = _dbus_string_get_length (str); + + i = 0; + while (1) + { + if (!_dbus_string_append_int (str, i)) + { + _dbus_string_free (str); + return FALSE; + } + + /* Check if a client with the name exists */ + if (bus_service_lookup (str, FALSE) == NULL) + break; + + _dbus_string_set_length (str, len); + + i++; + } + + return TRUE; +} + +static dbus_bool_t +bus_driver_handle_hello_message (DBusConnection *connection, + DBusMessage *message) +{ + DBusResultCode result; + char *name; + DBusString unique_name; + BusService *service; + dbus_bool_t retval; + + result = dbus_message_get_fields (message, + DBUS_TYPE_STRING, &name, + 0); + + /* FIXME: Handle this in a better way */ + if (result != DBUS_RESULT_SUCCESS) + return FALSE; + + if (!create_unique_client_name (name, &unique_name)) + return FALSE; + + /* Create the service */ + service = bus_service_lookup (&unique_name, TRUE); + if (!service) + { + _dbus_string_free (&unique_name); + return FALSE; + } + + /* FIXME: Error checks from this point */ + + /* Add the connection as the owner */ + bus_service_add_owner (service, connection); + bus_connection_set_name (connection, &unique_name); + + /* We need to assign the sender to the message here */ + _dbus_message_set_sender (message, + bus_connection_get_name (connection)); + + _dbus_string_free (&unique_name); + + retval = bus_driver_send_welcome_message (connection, message); + + return retval; +} + +static dbus_bool_t +bus_driver_send_welcome_message (DBusConnection *connection, + DBusMessage *hello_message) +{ + DBusMessage *welcome; + const char *name; + dbus_bool_t retval; + + + name = bus_connection_get_name (connection); + _dbus_assert (name != NULL); + + welcome = dbus_message_new_reply (BUS_DRIVER_WELCOME_NAME, + hello_message); + if (welcome == NULL) + return FALSE; + + /* FIXME: Return value */ + _dbus_message_set_sender (welcome, BUS_DRIVER_SERVICE_NAME); + + if (!dbus_message_append_fields (welcome, + DBUS_TYPE_STRING, name, + NULL)) + { + dbus_message_unref (welcome); + return FALSE; + } + + retval = dbus_connection_send_message (connection, welcome, NULL, NULL); + dbus_message_unref (welcome); + + return retval; +} + +/* This is where all the magic occurs */ +static DBusHandlerResult +bus_driver_message_handler (DBusMessageHandler *handler, + DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + const char *service, *name; + + service = dbus_message_get_service (message); + name = dbus_message_get_name (message); + + _dbus_message_set_sender (message, + bus_connection_get_name (connection)); + + if (strcmp (service, BUS_DRIVER_SERVICE_NAME) == 0) + { + if (strcmp (name, BUS_DRIVER_HELLO_NAME) == 0) + bus_driver_handle_hello_message (connection, message); + } + else + { + /* FIXME: Dispatch the message :-) */ + } + + return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; +} + +dbus_bool_t +bus_driver_add_connection (DBusConnection *connection) +{ + DBusMessageHandler *handler; + + handler = dbus_message_handler_new (bus_driver_message_handler, NULL, NULL); + + if (!dbus_connection_add_filter (connection, handler)) + { + dbus_message_handler_unref (handler); + + return FALSE; + } + + _dbus_verbose ("D-Bus driver on board...\n"); + + return TRUE; +} + +void +bus_driver_remove_connection (DBusConnection *connection) +{ + BusService *service; + DBusString service_name; + const char *name; + + name = bus_connection_get_name (connection); + + if (name == NULL) + return; + + _dbus_string_init_const (&service_name, name); + + service = bus_service_lookup (&service_name, FALSE); + + if (service) + bus_service_free (service); +} diff --git a/bus/driver.h b/bus/driver.h new file mode 100644 index 00000000..3667aac8 --- /dev/null +++ b/bus/driver.h @@ -0,0 +1,32 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* bus.h Bus client (driver) + * + * Copyright (C) 2003 CodeFactory AB + * + * 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_DRIVER_H +#define BUS_DRIVER_H + +#include <dbus/dbus.h> + +dbus_bool_t bus_driver_add_connection (DBusConnection *connection); +void bus_driver_remove_connection (DBusConnection *connection); + +#endif /* BUS_DRIVER_H */ @@ -22,6 +22,7 @@ */ #include "loop.h" #include "connection.h" +#include "driver.h" #include <dbus/dbus-list.h> static void diff --git a/bus/services.c b/bus/services.c index f8124b05..c07b20fd 100644 --- a/bus/services.c +++ b/bus/services.c @@ -98,6 +98,17 @@ 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) diff --git a/bus/services.h b/bus/services.h index 56ed3d1b..8c2344a4 100644 --- a/bus/services.h +++ b/bus/services.h @@ -39,15 +39,15 @@ typedef void (* BusServiceForeachFunction) (BusService *service, void *data); BusService* bus_service_lookup (const DBusString *service_name, - dbus_bool_t create_if_not_found); + dbus_bool_t create_if_not_found); +void bus_service_free (BusService *service); dbus_bool_t bus_service_add_owner (BusService *service, - DBusConnection *owner); + DBusConnection *owner); void bus_service_remove_owner (BusService *service, - DBusConnection *owner); + 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); + void *data); #endif /* BUS_SERVICES_H */ |