d24cb77f8b5e32c04a53ac2c360d0347602adada
[platform/upstream/dbus.git] / bus / driver.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* bus.c  Bus client (driver)
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
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.
12  *
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.
17  * 
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
21  *
22  */
23
24 #include "connection.h"
25 #include "driver.h"
26 #include "services.h"
27 #include <dbus/dbus-internals.h>
28 #include <dbus/dbus-string.h>
29 #include <string.h>
30
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"
34
35 static dbus_bool_t  bus_driver_send_welcome_message (DBusConnection *connection,
36                                                      DBusMessage    *hello_message);
37
38 static dbus_bool_t
39 create_unique_client_name (const char *name, DBusString *str)
40 {
41   int i, len;
42
43   if (!_dbus_string_init (str, _DBUS_INT_MAX))
44     return FALSE;
45
46   if (!_dbus_string_append (str, name))
47     return FALSE;
48   
49   len = _dbus_string_get_length (str);
50   
51   i = 0;  
52   while (1)
53     {
54       if (!_dbus_string_append_int (str, i))
55         {
56           _dbus_string_free (str);
57           return FALSE;
58         }
59       
60       /* Check if a client with the name exists */
61       if (bus_service_lookup (str, FALSE) == NULL)
62         break;
63
64       _dbus_string_set_length (str, len);
65       
66       i++;
67     }
68
69   return TRUE;
70 }
71
72 static dbus_bool_t
73 bus_driver_handle_hello_message (DBusConnection *connection,
74                                  DBusMessage    *message)
75 {
76   DBusResultCode result;
77   char *name;
78   DBusString unique_name;
79   BusService *service;
80   dbus_bool_t retval;
81   
82   result = dbus_message_get_fields (message,
83                                     DBUS_TYPE_STRING, &name,
84                                     0);
85
86   /* FIXME: Handle this in a better way */
87   if (result != DBUS_RESULT_SUCCESS)
88     return FALSE;
89
90   if (!create_unique_client_name (name, &unique_name))
91     return FALSE;
92
93   /* Create the service */
94   service = bus_service_lookup (&unique_name, TRUE);
95   if (!service)
96     {
97       _dbus_string_free (&unique_name);
98       return FALSE;
99     }
100
101   /* FIXME: Error checks from this point */
102   
103   /* Add the connection as the owner */
104   bus_service_add_owner (service, connection);
105   bus_connection_set_name (connection, &unique_name);
106
107   /* We need to assign the sender to the message here */
108   _dbus_message_set_sender (message,
109                             bus_connection_get_name (connection));
110   
111   _dbus_string_free (&unique_name);
112
113   retval = bus_driver_send_welcome_message (connection, message);
114
115   return retval;
116 }
117
118 static dbus_bool_t
119 bus_driver_send_welcome_message (DBusConnection *connection,
120                                  DBusMessage    *hello_message)
121 {
122   DBusMessage *welcome;
123   const char *name;
124   dbus_bool_t retval;
125   
126   
127   name = bus_connection_get_name (connection);
128   _dbus_assert (name != NULL);
129   
130   welcome = dbus_message_new_reply (BUS_DRIVER_WELCOME_NAME,
131                                     hello_message);
132   if (welcome == NULL)
133     return FALSE;
134
135   /* FIXME: Return value */
136   _dbus_message_set_sender (welcome, BUS_DRIVER_SERVICE_NAME);
137   
138   if (!dbus_message_append_fields (welcome,
139                                    DBUS_TYPE_STRING, name,
140                                    NULL))
141     {
142       dbus_message_unref (welcome);
143       return FALSE;
144     }
145
146   retval = dbus_connection_send_message (connection, welcome, NULL, NULL);
147   dbus_message_unref (welcome);
148
149   return retval;
150 }
151
152 /* This is where all the magic occurs */
153 static DBusHandlerResult
154 bus_driver_message_handler (DBusMessageHandler *handler,
155                             DBusConnection     *connection,
156                             DBusMessage        *message,
157                             void               *user_data)
158 {
159   const char *service, *name;
160
161   service = dbus_message_get_service (message);
162   name = dbus_message_get_name (message);
163
164   _dbus_message_set_sender (message,
165                             bus_connection_get_name (connection));
166   
167   if (strcmp (service, BUS_DRIVER_SERVICE_NAME) == 0)
168     {
169       if (strcmp (name, BUS_DRIVER_HELLO_NAME) == 0)
170         bus_driver_handle_hello_message (connection, message);
171     }
172   else
173     {
174       /* FIXME: Dispatch the message :-) */
175     }
176
177   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
178 }
179
180 dbus_bool_t
181 bus_driver_add_connection (DBusConnection *connection)
182 {
183   DBusMessageHandler *handler;
184
185   handler = dbus_message_handler_new (bus_driver_message_handler, NULL, NULL);
186
187   if (!dbus_connection_add_filter (connection, handler))
188     {
189       dbus_message_handler_unref (handler);
190
191       return FALSE;
192     }
193
194   _dbus_verbose ("D-Bus driver on board...\n");
195   
196   return TRUE;
197 }
198
199 void
200 bus_driver_remove_connection (DBusConnection *connection)
201 {
202   BusService *service;
203   DBusString service_name;
204   const char *name;
205
206   name = bus_connection_get_name (connection);
207
208   if (name == NULL)
209     return;
210   
211   _dbus_string_init_const (&service_name, name);
212   
213   service = bus_service_lookup (&service_name, FALSE);
214
215   if (service)
216     bus_service_free (service);
217 }