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"
28 #include <dbus/dbus-string.h>
29 #include <dbus/dbus-internals.h>
32 static void bus_driver_send_welcome_message (DBusConnection *connection,
33 DBusMessage *hello_message);
36 bus_driver_send_service_deleted (DBusConnection *connection, const char *name)
40 _dbus_verbose ("sending service deleted: %s\n", name);
42 _DBUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST,
43 DBUS_MESSAGE_SERVICE_DELETED));
45 _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS));
47 _DBUS_HANDLE_OOM (dbus_message_append_fields (message,
48 DBUS_TYPE_STRING, name,
50 bus_dispatch_broadcast_message (message);
51 dbus_message_unref (message);
55 bus_driver_send_service_created (DBusConnection *connection, const char *name)
59 _DBUS_HANDLE_OOM (message = dbus_message_new (DBUS_SERVICE_BROADCAST,
60 DBUS_MESSAGE_SERVICE_CREATED));
62 _DBUS_HANDLE_OOM (dbus_message_set_sender (message, DBUS_SERVICE_DBUS));
64 _DBUS_HANDLE_OOM (dbus_message_append_fields (message,
65 DBUS_TYPE_STRING, name,
67 bus_dispatch_broadcast_message (message);
68 dbus_message_unref (message);
72 create_unique_client_name (const char *name,
75 /* We never want to use the same unique client name twice, because
76 * we want to guarantee that if you send a message to a given unique
77 * name, you always get the same application. So we use two numbers
78 * for INT_MAX * INT_MAX combinations, should be pretty safe against
81 static int next_major_number = 0;
82 static int next_minor_number = 0;
85 if (!_dbus_string_append (str, name))
88 len = _dbus_string_get_length (str);
92 /* start out with 1-0, go to 1-1, 1-2, 1-3,
93 * up to 1-MAXINT, then 2-0, 2-1, etc.
95 if (next_minor_number <= 0)
97 next_major_number += 1;
98 next_minor_number = 0;
99 if (next_major_number <= 0)
100 _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
103 _dbus_assert (next_major_number > 0);
104 _dbus_assert (next_minor_number >= 0);
106 /* appname:MAJOR-MINOR */
108 if (!_dbus_string_append (str, ":"))
111 if (!_dbus_string_append_int (str, next_major_number))
114 if (!_dbus_string_append (str, "-"))
117 if (!_dbus_string_append_int (str, next_minor_number))
120 next_minor_number += 1;
122 /* Check if a client with the name exists */
123 if (bus_service_lookup (str, FALSE) == NULL)
126 /* drop the number again, try the next one. */
127 _dbus_string_set_length (str, len);
134 bus_driver_handle_hello (DBusConnection *connection,
135 DBusMessage *message)
137 DBusResultCode result;
139 DBusString unique_name;
142 _DBUS_HANDLE_OOM ((result = dbus_message_get_fields (message,
143 DBUS_TYPE_STRING, &name,
144 0)) != DBUS_RESULT_NO_MEMORY);
146 if (result != DBUS_RESULT_SUCCESS)
149 dbus_connection_disconnect (connection);
152 _DBUS_HANDLE_OOM (_dbus_string_init (&unique_name, _DBUS_INT_MAX));
154 _DBUS_HANDLE_OOM (create_unique_client_name (name, &unique_name));
158 /* Create the service */
159 _DBUS_HANDLE_OOM (service = bus_service_lookup (&unique_name, TRUE));
161 /* Add the connection as the owner */
162 _DBUS_HANDLE_OOM (bus_service_add_owner (service, connection));
163 _DBUS_HANDLE_OOM (bus_connection_set_name (connection, &unique_name));
165 _DBUS_HANDLE_OOM (dbus_message_set_sender (message,
166 bus_connection_get_name (connection)));
168 _dbus_string_free (&unique_name);
170 _DBUS_HANDLE_OOM (bus_driver_send_welcome_message (connection, message));
172 /* Broadcast a service created message */
173 bus_driver_send_service_created (connection, bus_service_get_name (service));
177 bus_driver_send_welcome_message (DBusConnection *connection,
178 DBusMessage *hello_message)
180 DBusMessage *welcome;
183 name = bus_connection_get_name (connection);
184 _dbus_assert (name != NULL);
186 _DBUS_HANDLE_OOM (welcome = dbus_message_new_reply (DBUS_MESSAGE_WELCOME,
189 _DBUS_HANDLE_OOM (dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS));
191 _DBUS_HANDLE_OOM (dbus_message_append_fields (welcome,
192 DBUS_TYPE_STRING, name,
195 _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, welcome, NULL, NULL));
197 dbus_message_unref (welcome);
201 bus_driver_handle_list_services (DBusConnection *connection,
202 DBusMessage *message)
208 _DBUS_HANDLE_OOM (reply = dbus_message_new_reply (DBUS_MESSAGE_SERVICES, message));
210 _DBUS_HANDLE_OOM (services = bus_services_list (&len));
212 _DBUS_HANDLE_OOM (dbus_message_append_fields (reply,
213 DBUS_TYPE_STRING_ARRAY, services, len,
216 _DBUS_HANDLE_OOM (dbus_connection_send_message (connection, reply, NULL, NULL));
218 dbus_message_unref (reply);
220 if (services != NULL)
222 for (i = 0; i < len; i++)
223 dbus_free (services[i]);
224 dbus_free (services);
229 bus_driver_remove_connection (DBusConnection *connection)
232 DBusString service_name;
235 name = bus_connection_get_name (connection);
240 _dbus_string_init_const (&service_name, name);
242 service = bus_service_lookup (&service_name, FALSE);
244 bus_driver_send_service_deleted (connection, name);
247 bus_service_free (service);
251 bus_driver_handle_message (DBusConnection *connection,
252 DBusMessage *message)
254 const char *name, *sender;
256 _dbus_verbose ("Driver got a message: %s\n",
257 dbus_message_get_name (message));
259 name = dbus_message_get_name (message);
260 sender = dbus_message_get_sender (message);
262 if (sender == NULL && (strcmp (name, DBUS_MESSAGE_HELLO) != 0))
264 _dbus_verbose ("Trying to send a message without being registered. Disconnecting.\n");
265 dbus_connection_disconnect (connection);
269 /* Now check names. */
270 if (strcmp (name, DBUS_MESSAGE_HELLO) == 0)
271 bus_driver_handle_hello (connection, message);
272 else if (strcmp (name, DBUS_MESSAGE_LIST_SERVICES) == 0)
273 bus_driver_handle_list_services (connection, message);