summaryrefslogtreecommitdiffstats
path: root/bus
diff options
context:
space:
mode:
Diffstat (limited to 'bus')
-rw-r--r--bus/Makefile.am2
-rw-r--r--bus/connection.c44
-rw-r--r--bus/connection.h7
-rw-r--r--bus/driver.c217
-rw-r--r--bus/driver.h32
-rw-r--r--bus/main.c1
-rw-r--r--bus/services.c11
-rw-r--r--bus/services.h10
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 */
diff --git a/bus/main.c b/bus/main.c
index 27720fbc..fb5e0397 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -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 */