1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* driver.c Bus client (driver)
4 * Copyright (C) 2003 CodeFactory AB
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "connection.h"
27 #include <dbus/dbus-internals.h>
28 #include <dbus/dbus-string.h>
31 #define BUS_DRIVER_SERVICE_NAME "org.freedesktop.DBus"
32 #define BUS_DRIVER_HELLO_NAME "org.freedesktop.DBus.Hello"
33 #define BUS_DRIVER_WELCOME_NAME "org.freedesktop.DBus.Welcome"
35 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
36 DBusMessage *hello_message);
39 create_unique_client_name (const char *name,
42 /* We never want to use the same unique client name twice, because
43 * we want to guarantee that if you send a message to a given unique
44 * name, you always get the same application. So we use two numbers
45 * for INT_MAX * INT_MAX combinations, should be pretty safe against
48 static int next_major_number = 0;
49 static int next_minor_number = 0;
52 if (!_dbus_string_append (str, name))
55 len = _dbus_string_get_length (str);
59 /* start out with 1-0, go to 1-1, 1-2, 1-3,
60 * up to 1-MAXINT, then 2-0, 2-1, etc.
62 if (next_minor_number <= 0)
64 next_major_number += 1;
65 next_minor_number = 0;
66 if (next_major_number <= 0)
67 _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
70 _dbus_assert (next_major_number > 0);
71 _dbus_assert (next_minor_number >= 0);
73 /* appname:MAJOR-MINOR */
75 if (!_dbus_string_append (str, ":"))
78 if (!_dbus_string_append_int (str, next_major_number))
81 if (!_dbus_string_append (str, "-"))
84 if (!_dbus_string_append_int (str, next_minor_number))
87 next_minor_number += 1;
89 /* Check if a client with the name exists */
90 if (bus_service_lookup (str, FALSE) == NULL)
93 /* drop the number again, try the next one. */
94 _dbus_string_set_length (str, len);
101 bus_driver_handle_hello_message (DBusConnection *connection,
102 DBusMessage *message)
104 DBusResultCode result;
106 DBusString unique_name;
110 result = dbus_message_get_fields (message,
111 DBUS_TYPE_STRING, &name,
114 /* FIXME: Handle this in a better way */
115 if (result != DBUS_RESULT_SUCCESS)
118 if (!_dbus_string_init (&unique_name, _DBUS_INT_MAX))
121 if (!create_unique_client_name (name, &unique_name))
123 _dbus_string_free (&unique_name);
127 /* Create the service */
128 service = bus_service_lookup (&unique_name, TRUE);
131 _dbus_string_free (&unique_name);
135 /* FIXME: Error checks from this point */
137 /* Add the connection as the owner */
138 bus_service_add_owner (service, connection);
139 bus_connection_set_name (connection, &unique_name);
141 /* We need to assign the sender to the message here */
142 _dbus_message_set_sender (message,
143 bus_connection_get_name (connection));
145 _dbus_string_free (&unique_name);
147 retval = bus_driver_send_welcome_message (connection, message);
153 bus_driver_send_welcome_message (DBusConnection *connection,
154 DBusMessage *hello_message)
156 DBusMessage *welcome;
161 name = bus_connection_get_name (connection);
162 _dbus_assert (name != NULL);
164 welcome = dbus_message_new_reply (BUS_DRIVER_WELCOME_NAME,
169 /* FIXME: Return value */
170 _dbus_message_set_sender (welcome, BUS_DRIVER_SERVICE_NAME);
172 if (!dbus_message_append_fields (welcome,
173 DBUS_TYPE_STRING, name,
176 dbus_message_unref (welcome);
180 retval = dbus_connection_send_message (connection, welcome, NULL, NULL);
181 dbus_message_unref (welcome);
186 /* This is where all the magic occurs */
187 static DBusHandlerResult
188 bus_driver_message_handler (DBusMessageHandler *handler,
189 DBusConnection *connection,
190 DBusMessage *message,
193 const char *service, *name;
195 service = dbus_message_get_service (message);
196 name = dbus_message_get_name (message);
198 _dbus_message_set_sender (message,
199 bus_connection_get_name (connection));
201 if (strcmp (service, BUS_DRIVER_SERVICE_NAME) == 0)
203 if (strcmp (name, BUS_DRIVER_HELLO_NAME) == 0)
204 bus_driver_handle_hello_message (connection, message);
208 /* FIXME: Dispatch the message :-) */
211 return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
215 bus_driver_add_connection (DBusConnection *connection)
217 DBusMessageHandler *handler;
219 handler = dbus_message_handler_new (bus_driver_message_handler, NULL, NULL);
221 if (!dbus_connection_add_filter (connection, handler))
223 dbus_message_handler_unref (handler);
228 /* FIXME we are leaking the DBusMessageHandler */
230 _dbus_verbose ("D-Bus driver on board...\n");
236 bus_driver_remove_connection (DBusConnection *connection)
239 DBusString service_name;
242 name = bus_connection_get_name (connection);
247 _dbus_string_init_const (&service_name, name);
249 service = bus_service_lookup (&service_name, FALSE);
252 bus_service_free (service);