2003-04-25 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / driver.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* driver.c  Bus client (driver)
3  *
4  * Copyright (C) 2003 CodeFactory AB
5  * Copyright (C) 2003 Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "activation.h"
26 #include "connection.h"
27 #include "driver.h"
28 #include "dispatch.h"
29 #include "services.h"
30 #include "utils.h"
31 #include <dbus/dbus-string.h>
32 #include <dbus/dbus-internals.h>
33 #include <string.h>
34
35 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
36                                                     DBusMessage    *hello_message,
37                                                     BusTransaction *transaction,
38                                                     DBusError      *error);
39
40 dbus_bool_t
41 bus_driver_send_service_deleted (const char     *service_name,
42                                  BusTransaction *transaction,
43                                  DBusError      *error)
44 {
45   DBusMessage *message;
46   dbus_bool_t retval;
47
48   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
49   
50   _dbus_verbose ("sending service deleted: %s\n", service_name);
51
52   message = dbus_message_new (DBUS_MESSAGE_SERVICE_DELETED,
53                               DBUS_SERVICE_BROADCAST);
54   if (message == NULL)
55     {
56       BUS_SET_OOM (error);
57       return FALSE;
58     }
59   
60   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
61       !dbus_message_append_args (message,
62                                  DBUS_TYPE_STRING, service_name,
63                                  0))
64     {
65       dbus_message_unref (message);
66       BUS_SET_OOM (error);
67       return FALSE;
68     }
69
70   retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
71   dbus_message_unref (message);
72
73   return retval;
74 }
75
76 dbus_bool_t
77 bus_driver_send_service_created (const char     *service_name,
78                                  BusTransaction *transaction,
79                                  DBusError      *error)
80 {
81   DBusMessage *message;
82   dbus_bool_t retval;
83
84   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
85   
86   message = dbus_message_new (DBUS_MESSAGE_SERVICE_CREATED,
87                               DBUS_SERVICE_BROADCAST);
88   if (message == NULL)
89     {
90       BUS_SET_OOM (error);
91       return FALSE;
92     }
93   
94   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
95     {
96       dbus_message_unref (message);
97       BUS_SET_OOM (error);
98       return FALSE;
99     }
100   
101   if (!dbus_message_append_args (message,
102                                  DBUS_TYPE_STRING, service_name,
103                                  0))
104     {
105       dbus_message_unref (message);
106       BUS_SET_OOM (error);
107       return FALSE;
108     }
109   
110   retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
111   dbus_message_unref (message);
112
113   return retval;
114 }
115
116 dbus_bool_t
117 bus_driver_send_service_lost (DBusConnection *connection,
118                               const char     *service_name,
119                               BusTransaction *transaction,
120                               DBusError      *error)
121 {
122   DBusMessage *message;
123
124   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
125   
126   message = dbus_message_new (DBUS_MESSAGE_SERVICE_LOST,
127                               bus_connection_get_name (connection));
128   if (message == NULL)
129     {
130       BUS_SET_OOM (error);
131       return FALSE;
132     }
133   
134   if (!dbus_message_append_args (message,
135                                  DBUS_TYPE_STRING, service_name,
136                                  0))
137     {
138       dbus_message_unref (message);
139       BUS_SET_OOM (error);
140       return FALSE;
141     }
142
143   if (!bus_transaction_send_from_driver (transaction, connection, message))
144     {
145       dbus_message_unref (message);
146       BUS_SET_OOM (error);
147       return FALSE;
148     }
149   else
150     {
151       dbus_message_unref (message);
152       return TRUE;
153     }
154 }
155
156 dbus_bool_t
157 bus_driver_send_service_acquired (DBusConnection *connection,
158                                   const char     *service_name,
159                                   BusTransaction *transaction,
160                                   DBusError      *error)
161 {
162   DBusMessage *message;
163
164   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
165   
166   message = dbus_message_new (DBUS_MESSAGE_SERVICE_ACQUIRED,
167                               bus_connection_get_name (connection));
168
169   if (message == NULL)
170     {
171       BUS_SET_OOM (error);
172       return FALSE;
173     }
174   
175   if (!dbus_message_append_args (message,
176                                  DBUS_TYPE_STRING, service_name,
177                                  0))
178     {
179       dbus_message_unref (message);
180       BUS_SET_OOM (error);
181       return FALSE;
182     }
183
184   if (!bus_transaction_send_from_driver (transaction, connection, message))
185     {
186       dbus_message_unref (message);
187       BUS_SET_OOM (error);
188       return FALSE;
189     }
190   else
191     {
192       dbus_message_unref (message);
193       return TRUE;
194     }
195 }
196
197 static dbus_bool_t
198 create_unique_client_name (BusRegistry *registry,
199                            DBusString  *str)
200 {
201   /* We never want to use the same unique client name twice, because
202    * we want to guarantee that if you send a message to a given unique
203    * name, you always get the same application. So we use two numbers
204    * for INT_MAX * INT_MAX combinations, should be pretty safe against
205    * wraparound.
206    */
207   static int next_major_number = 0;
208   static int next_minor_number = 0;
209   int len;
210
211   len = _dbus_string_get_length (str);
212   
213   while (TRUE)
214     {
215       /* start out with 1-0, go to 1-1, 1-2, 1-3,
216        * up to 1-MAXINT, then 2-0, 2-1, etc.
217        */
218       if (next_minor_number <= 0)
219         {
220           next_major_number += 1;
221           next_minor_number = 0;
222           if (next_major_number <= 0)
223             _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
224         }
225
226       _dbus_assert (next_major_number > 0);
227       _dbus_assert (next_minor_number >= 0);
228
229       /* appname:MAJOR-MINOR */
230       
231       if (!_dbus_string_append (str, ":"))
232         return FALSE;
233       
234       if (!_dbus_string_append_int (str, next_major_number))
235         return FALSE;
236
237       if (!_dbus_string_append (str, "-"))
238         return FALSE;
239       
240       if (!_dbus_string_append_int (str, next_minor_number))
241         return FALSE;
242
243       next_minor_number += 1;
244       
245       /* Check if a client with the name exists */
246       if (bus_registry_lookup (registry, str) == NULL)
247         break;
248
249       /* drop the number again, try the next one. */
250       _dbus_string_set_length (str, len);
251     }
252
253   return TRUE;
254 }
255
256 static dbus_bool_t
257 bus_driver_handle_hello (DBusConnection *connection,
258                          BusTransaction *transaction,
259                          DBusMessage    *message,
260                          DBusError      *error)
261 {
262   DBusString unique_name;
263   BusService *service;
264   dbus_bool_t retval;
265   BusRegistry *registry;
266   BusConnections *connections;
267
268   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
269
270   /* Note that when these limits are exceeded we don't disconnect the
271    * connection; we just sort of leave it hanging there until it times
272    * out or disconnects itself or is dropped due to the max number of
273    * incomplete connections. It's even OK if the connection wants to
274    * retry the hello message, we support that.
275    */
276   connections = bus_connection_get_connections (connection);
277   if (!bus_connections_check_limits (connections, connection,
278                                      error))
279     {
280       _DBUS_ASSERT_ERROR_IS_SET (error);
281       return FALSE;
282     }
283   
284   if (!_dbus_string_init (&unique_name))
285     {
286       BUS_SET_OOM (error);
287       return FALSE;
288     }
289
290   retval = FALSE;
291
292   registry = bus_connection_get_registry (connection);
293   
294   if (!create_unique_client_name (registry, &unique_name))
295     {
296       BUS_SET_OOM (error);
297       goto out_0;
298     }
299
300   if (!bus_connection_set_name (connection, &unique_name))
301     {
302       BUS_SET_OOM (error);
303       goto out_0;
304     }
305   
306   if (!dbus_message_set_sender (message,
307                                 bus_connection_get_name (connection)))
308     {
309       BUS_SET_OOM (error);
310       goto out_0;
311     }
312   
313   if (!bus_driver_send_welcome_message (connection, message, transaction, error))
314     goto out_0;
315
316   /* Create the service */
317   service = bus_registry_ensure (registry,
318                                  &unique_name, connection, transaction, error);
319   if (service == NULL)
320     goto out_0;
321   
322   bus_service_set_prohibit_replacement (service, TRUE);
323
324   retval = TRUE;
325   
326  out_0:
327   _dbus_string_free (&unique_name);
328   return retval;
329 }
330
331 static dbus_bool_t
332 bus_driver_send_welcome_message (DBusConnection *connection,
333                                  DBusMessage    *hello_message,
334                                  BusTransaction *transaction,
335                                  DBusError      *error)
336 {
337   DBusMessage *welcome;
338   const char *name;
339
340   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
341   
342   name = bus_connection_get_name (connection);
343   _dbus_assert (name != NULL);
344   
345   welcome = dbus_message_new_reply (hello_message);
346   if (welcome == NULL)
347     {
348       BUS_SET_OOM (error);
349       return FALSE;
350     }
351   
352   if (!dbus_message_append_args (welcome,
353                                  DBUS_TYPE_STRING, name,
354                                  NULL))
355     {
356       dbus_message_unref (welcome);
357       BUS_SET_OOM (error);
358       return FALSE;
359     }
360
361   if (!bus_transaction_send_from_driver (transaction, connection, welcome))
362     {
363       dbus_message_unref (welcome);
364       BUS_SET_OOM (error);
365       return FALSE;
366     }
367   else
368     {
369       dbus_message_unref (welcome);
370       return TRUE;
371     }
372 }
373
374 static dbus_bool_t
375 bus_driver_handle_list_services (DBusConnection *connection,
376                                  BusTransaction *transaction,
377                                  DBusMessage    *message,
378                                  DBusError      *error)
379 {
380   DBusMessage *reply;
381   int len;
382   char **services;
383   BusRegistry *registry;
384
385   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
386   
387   registry = bus_connection_get_registry (connection);
388   
389   reply = dbus_message_new_reply (message);
390   if (reply == NULL)
391     {
392       BUS_SET_OOM (error);
393       return FALSE;
394     }
395
396   if (!bus_registry_list_services (registry, &services, &len))
397     {
398       dbus_message_unref (reply);
399       BUS_SET_OOM (error);
400       return FALSE;
401     }
402   
403   if (!dbus_message_append_args (reply,
404                                  DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, services, len,
405                                  0))
406     {
407       dbus_free_string_array (services);
408       dbus_message_unref (reply);
409       BUS_SET_OOM (error);
410       return FALSE;
411     }
412
413   dbus_free_string_array (services);
414   
415   if (!bus_transaction_send_from_driver (transaction, connection, reply))
416     {
417       dbus_message_unref (reply);
418       BUS_SET_OOM (error);
419       return FALSE;
420     }
421   else
422     {
423       dbus_message_unref (reply);
424       return TRUE;
425     }
426 }
427
428 static dbus_bool_t
429 bus_driver_handle_acquire_service (DBusConnection *connection,
430                                    BusTransaction *transaction,
431                                    DBusMessage    *message,
432                                    DBusError      *error)
433 {
434   DBusMessage *reply;
435   DBusString service_name;
436   char *name;
437   int service_reply;
438   int flags;
439   dbus_bool_t retval;
440   BusRegistry *registry;
441
442   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
443   
444   registry = bus_connection_get_registry (connection);
445   
446   if (!dbus_message_get_args (message, error,
447                               DBUS_TYPE_STRING, &name,
448                               DBUS_TYPE_UINT32, &flags,
449                               0))
450     return FALSE;
451   
452   _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags);
453   
454   retval = FALSE;
455   reply = NULL;
456
457   _dbus_string_init_const (&service_name, name);
458
459   if (!bus_registry_acquire_service (registry, connection,
460                                      &service_name, flags,
461                                      &service_reply, transaction,
462                                      error))
463     goto out;
464   
465   reply = dbus_message_new_reply (message);
466   if (reply == NULL)
467     {
468       BUS_SET_OOM (error);
469       goto out;
470     }
471
472   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, DBUS_TYPE_INVALID))
473     {
474       BUS_SET_OOM (error);
475       goto out;
476     }
477
478   if (!bus_transaction_send_from_driver (transaction, connection, reply))
479     {
480       BUS_SET_OOM (error);
481       goto out;
482     }
483
484   retval = TRUE;
485   
486  out:
487   dbus_free (name);
488   if (reply)
489     dbus_message_unref (reply);
490   return retval;
491
492
493 static dbus_bool_t
494 bus_driver_handle_service_exists (DBusConnection *connection,
495                                   BusTransaction *transaction,
496                                   DBusMessage    *message,
497                                   DBusError      *error)
498 {
499   DBusMessage *reply;
500   DBusString service_name;
501   BusService *service;
502   char *name;
503   dbus_bool_t retval;
504   BusRegistry *registry;
505
506   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
507   
508   registry = bus_connection_get_registry (connection);
509   
510   if (!dbus_message_get_args (message, error,
511                               DBUS_TYPE_STRING, &name,
512                               0))
513     return FALSE;
514
515   retval = FALSE;
516   
517   _dbus_string_init_const (&service_name, name);
518   service = bus_registry_lookup (registry, &service_name);
519  
520   reply = dbus_message_new_reply (message);
521   if (reply == NULL)
522     {
523       BUS_SET_OOM (error);
524       goto out;
525     }
526
527   if (!dbus_message_append_args (reply,
528                                  DBUS_TYPE_UINT32, service != NULL,
529                                  0))
530     {
531       BUS_SET_OOM (error);
532       goto out;
533     }
534
535   if (!bus_transaction_send_from_driver (transaction, connection, reply))
536     {
537       BUS_SET_OOM (error);
538       goto out;
539     }
540
541   retval = TRUE;
542   
543  out:
544   if (reply)
545     dbus_message_unref (reply);
546   dbus_free (name);
547
548   return retval;
549 }
550
551 static dbus_bool_t
552 bus_driver_handle_activate_service (DBusConnection *connection,
553                                     BusTransaction *transaction,
554                                     DBusMessage    *message,
555                                     DBusError      *error)
556 {
557   dbus_uint32_t flags;
558   char *name;
559   dbus_bool_t retval;
560   BusActivation *activation;
561
562   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
563   
564   activation = bus_connection_get_activation (connection);
565   
566   if (!dbus_message_get_args (message, error,
567                               DBUS_TYPE_STRING, &name,
568                               DBUS_TYPE_UINT32, &flags,
569                               0))
570     {
571       _DBUS_ASSERT_ERROR_IS_SET (error);
572       _dbus_verbose ("No memory to get arguments to ActivateService\n");
573       return FALSE;
574     }
575
576   retval = FALSE;
577
578   if (!bus_activation_activate_service (activation, connection, transaction,
579                                         message, name, error))
580     {
581       _DBUS_ASSERT_ERROR_IS_SET (error);
582       _dbus_verbose ("bus_activation_activate_service() failed\n");
583       goto out;
584     }
585
586   retval = TRUE;
587   
588  out:
589   dbus_free (name);
590   return retval;
591 }
592
593 /* For speed it might be useful to sort this in order of
594  * frequency of use (but doesn't matter with only a few items
595  * anyhow)
596  */
597 struct
598 {
599   const char *name;
600   dbus_bool_t (* handler) (DBusConnection *connection,
601                            BusTransaction *transaction,
602                            DBusMessage    *message,
603                            DBusError      *error);
604 } message_handlers[] = {
605   { DBUS_MESSAGE_ACQUIRE_SERVICE, bus_driver_handle_acquire_service },
606   { DBUS_MESSAGE_ACTIVATE_SERVICE, bus_driver_handle_activate_service },
607   { DBUS_MESSAGE_HELLO, bus_driver_handle_hello },
608   { DBUS_MESSAGE_SERVICE_EXISTS, bus_driver_handle_service_exists },
609   { DBUS_MESSAGE_LIST_SERVICES, bus_driver_handle_list_services }
610 };
611
612 dbus_bool_t
613 bus_driver_handle_message (DBusConnection *connection,
614                            BusTransaction *transaction,
615                            DBusMessage    *message,
616                            DBusError      *error)
617 {
618   const char *name, *sender;
619   int i;
620
621   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
622   
623   _dbus_verbose ("Driver got a message: %s\n",
624                  dbus_message_get_name (message));
625   
626   name = dbus_message_get_name (message);
627   sender = dbus_message_get_sender (message);
628
629   if (sender == NULL && (strcmp (name, DBUS_MESSAGE_HELLO) != 0))
630     {
631       dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
632                       "Client tried to send a message other than %s without being registered",
633                       DBUS_MESSAGE_HELLO);
634
635       dbus_connection_disconnect (connection);
636       return FALSE;
637     }
638
639   if (dbus_message_get_reply_serial (message) == 0)
640     {
641       _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n");
642       return TRUE;
643     }
644   
645   i = 0;
646   while (i < _DBUS_N_ELEMENTS (message_handlers))
647     {
648       if (strcmp (message_handlers[i].name, name) == 0)
649         {
650           _dbus_verbose ("Running driver handler for %s\n", name);
651           if ((* message_handlers[i].handler) (connection, transaction, message, error))
652             {
653               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
654               _dbus_verbose ("Driver handler succeeded\n");
655               return TRUE;
656             }
657           else
658             {
659               _DBUS_ASSERT_ERROR_IS_SET (error);
660               _dbus_verbose ("Driver handler returned failure\n");
661               return FALSE;
662             }
663         }
664       
665       ++i;
666     }
667
668   _dbus_verbose ("No driver handler for %s\n", name);
669
670   dbus_set_error (error, DBUS_ERROR_UNKNOWN_MESSAGE,
671                   "%s does not understand message %s",
672                   DBUS_SERVICE_DBUS, name);
673   
674   return FALSE;
675 }
676
677 void
678 bus_driver_remove_connection (DBusConnection *connection)
679 {
680   /* FIXME Does nothing for now, should unregister the connection
681    * with the bus driver.
682    */
683 }