2005-01-16 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, 2004 Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 2.1
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 "signals.h"
31 #include "utils.h"
32 #include <dbus/dbus-string.h>
33 #include <dbus/dbus-internals.h>
34 #include <string.h>
35
36 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
37                                                     DBusMessage    *hello_message,
38                                                     BusTransaction *transaction,
39                                                     DBusError      *error);
40
41 dbus_bool_t
42 bus_driver_send_service_owner_changed (const char     *service_name,
43                                        const char     *old_owner,
44                                        const char     *new_owner,
45                                        BusTransaction *transaction,
46                                        DBusError      *error)
47 {
48   DBusMessage *message;
49   dbus_bool_t retval;
50   const char *null_service;
51
52   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
53
54   null_service = "";
55   _dbus_verbose ("sending service owner changed: %s [%s -> %s]\n",
56                  service_name, 
57                  old_owner ? old_owner : null_service, 
58                  new_owner ? new_owner : null_service);
59
60   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
61                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
62                                      "ServiceOwnerChanged");
63   
64   if (message == NULL)
65     {
66       BUS_SET_OOM (error);
67       return FALSE;
68     }
69   
70   if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
71     goto oom;
72
73   if (!dbus_message_append_args (message,
74                                  DBUS_TYPE_STRING, &service_name,
75                                  DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
76                                  DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
77                                  DBUS_TYPE_INVALID))
78     goto oom;
79
80   _dbus_assert (dbus_message_has_signature (message, "sss"));
81   
82   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
83   dbus_message_unref (message);
84
85   return retval;
86
87  oom:
88   dbus_message_unref (message);
89   BUS_SET_OOM (error);
90   return FALSE;
91 }
92
93 dbus_bool_t
94 bus_driver_send_service_lost (DBusConnection *connection,
95                               const char     *service_name,
96                               BusTransaction *transaction,
97                               DBusError      *error)
98 {
99   DBusMessage *message;
100
101   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
102   
103   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
104                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
105                                      "ServiceLost");
106   
107   if (message == NULL)
108     {
109       BUS_SET_OOM (error);
110       return FALSE;
111     }
112   
113   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
114       !dbus_message_append_args (message,
115                                  DBUS_TYPE_STRING, &service_name,
116                                  DBUS_TYPE_INVALID))
117     {
118       dbus_message_unref (message);
119       BUS_SET_OOM (error);
120       return FALSE;
121     }
122
123   if (!bus_transaction_send_from_driver (transaction, connection, message))
124     {
125       dbus_message_unref (message);
126       BUS_SET_OOM (error);
127       return FALSE;
128     }
129   else
130     {
131       dbus_message_unref (message);
132       return TRUE;
133     }
134 }
135
136 dbus_bool_t
137 bus_driver_send_service_acquired (DBusConnection *connection,
138                                   const char     *service_name,
139                                   BusTransaction *transaction,
140                                   DBusError      *error)
141 {
142   DBusMessage *message;
143
144   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
145   
146   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
147                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
148                                      "ServiceAcquired");
149
150   if (message == NULL)
151     {
152       BUS_SET_OOM (error);
153       return FALSE;
154     }
155   
156   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
157       !dbus_message_append_args (message,
158                                  DBUS_TYPE_STRING, &service_name,
159                                  DBUS_TYPE_INVALID))
160     {
161       dbus_message_unref (message);
162       BUS_SET_OOM (error);
163       return FALSE;
164     }
165
166   if (!bus_transaction_send_from_driver (transaction, connection, message))
167     {
168       dbus_message_unref (message);
169       BUS_SET_OOM (error);
170       return FALSE;
171     }
172   else
173     {
174       dbus_message_unref (message);
175       return TRUE;
176     }
177 }
178
179 static dbus_bool_t
180 create_unique_client_name (BusRegistry *registry,
181                            DBusString  *str)
182 {
183   /* We never want to use the same unique client name twice, because
184    * we want to guarantee that if you send a message to a given unique
185    * name, you always get the same application. So we use two numbers
186    * for INT_MAX * INT_MAX combinations, should be pretty safe against
187    * wraparound.
188    */
189   /* FIXME these should be in BusRegistry rather than static vars */
190   static int next_major_number = 0;
191   static int next_minor_number = 0;
192   int len;
193   
194   len = _dbus_string_get_length (str);
195   
196   while (TRUE)
197     {
198       /* start out with 1-0, go to 1-1, 1-2, 1-3,
199        * up to 1-MAXINT, then 2-0, 2-1, etc.
200        */
201       if (next_minor_number <= 0)
202         {
203           next_major_number += 1;
204           next_minor_number = 0;
205           if (next_major_number <= 0)
206             _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
207         }
208
209       _dbus_assert (next_major_number > 0);
210       _dbus_assert (next_minor_number >= 0);
211
212       /* appname:MAJOR-MINOR */
213       
214       if (!_dbus_string_append (str, ":"))
215         return FALSE;
216       
217       if (!_dbus_string_append_int (str, next_major_number))
218         return FALSE;
219
220       if (!_dbus_string_append (str, "."))
221         return FALSE;
222       
223       if (!_dbus_string_append_int (str, next_minor_number))
224         return FALSE;
225
226       next_minor_number += 1;
227       
228       /* Check if a client with the name exists */
229       if (bus_registry_lookup (registry, str) == NULL)
230         break;
231
232       /* drop the number again, try the next one. */
233       _dbus_string_set_length (str, len);
234     }
235
236   return TRUE;
237 }
238
239 static dbus_bool_t
240 bus_driver_handle_hello (DBusConnection *connection,
241                          BusTransaction *transaction,
242                          DBusMessage    *message,
243                          DBusError      *error)
244 {
245   DBusString unique_name;
246   BusService *service;
247   dbus_bool_t retval;
248   BusRegistry *registry;
249   BusConnections *connections;
250
251   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
252
253   if (bus_connection_is_active (connection))
254     {
255       /* We already handled an Hello message for this connection. */
256       dbus_set_error (error, DBUS_ERROR_FAILED,
257                       "Already handled an Hello message");
258       return FALSE;
259     }
260
261   /* Note that when these limits are exceeded we don't disconnect the
262    * connection; we just sort of leave it hanging there until it times
263    * out or disconnects itself or is dropped due to the max number of
264    * incomplete connections. It's even OK if the connection wants to
265    * retry the hello message, we support that.
266    */
267   connections = bus_connection_get_connections (connection);
268   if (!bus_connections_check_limits (connections, connection,
269                                      error))
270     {
271       _DBUS_ASSERT_ERROR_IS_SET (error);
272       return FALSE;
273     }
274   
275   if (!_dbus_string_init (&unique_name))
276     {
277       BUS_SET_OOM (error);
278       return FALSE;
279     }
280
281   retval = FALSE;
282
283   registry = bus_connection_get_registry (connection);
284   
285   if (!create_unique_client_name (registry, &unique_name))
286     {
287       BUS_SET_OOM (error);
288       goto out_0;
289     }
290
291   if (!bus_connection_complete (connection, &unique_name, error))
292     {
293       _DBUS_ASSERT_ERROR_IS_SET (error);
294       goto out_0;
295     }
296   
297   if (!dbus_message_set_sender (message,
298                                 bus_connection_get_name (connection)))
299     {
300       BUS_SET_OOM (error);
301       goto out_0;
302     }
303   
304   if (!bus_driver_send_welcome_message (connection, message, transaction, error))
305     goto out_0;
306
307   /* Create the service */
308   service = bus_registry_ensure (registry,
309                                  &unique_name, connection, transaction, error);
310   if (service == NULL)
311     goto out_0;
312   
313   bus_service_set_prohibit_replacement (service, TRUE);
314
315   _dbus_assert (bus_connection_is_active (connection));
316   retval = TRUE;
317   
318  out_0:
319   _dbus_string_free (&unique_name);
320   return retval;
321 }
322
323 static dbus_bool_t
324 bus_driver_send_welcome_message (DBusConnection *connection,
325                                  DBusMessage    *hello_message,
326                                  BusTransaction *transaction,
327                                  DBusError      *error)
328 {
329   DBusMessage *welcome;
330   const char *name;
331
332   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
333   
334   name = bus_connection_get_name (connection);
335   _dbus_assert (name != NULL);
336   
337   welcome = dbus_message_new_method_return (hello_message);
338   if (welcome == NULL)
339     {
340       BUS_SET_OOM (error);
341       return FALSE;
342     }
343   
344   if (!dbus_message_append_args (welcome,
345                                  DBUS_TYPE_STRING, &name,
346                                  DBUS_TYPE_INVALID))
347     {
348       dbus_message_unref (welcome);
349       BUS_SET_OOM (error);
350       return FALSE;
351     }
352
353   _dbus_assert (dbus_message_has_signature (welcome, "s"));
354   
355   if (!bus_transaction_send_from_driver (transaction, connection, welcome))
356     {
357       dbus_message_unref (welcome);
358       BUS_SET_OOM (error);
359       return FALSE;
360     }
361   else
362     {
363       dbus_message_unref (welcome);
364       return TRUE;
365     }
366 }
367
368 static dbus_bool_t
369 bus_driver_handle_list_services (DBusConnection *connection,
370                                  BusTransaction *transaction,
371                                  DBusMessage    *message,
372                                  DBusError      *error)
373 {
374   DBusMessage *reply;
375   int len;
376   char **services;
377   BusRegistry *registry;
378   int i;
379   DBusMessageIter iter;
380   DBusMessageIter sub;
381
382   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
383   
384   registry = bus_connection_get_registry (connection);
385   
386   reply = dbus_message_new_method_return (message);
387   if (reply == NULL)
388     {
389       BUS_SET_OOM (error);
390       return FALSE;
391     }
392
393   if (!bus_registry_list_services (registry, &services, &len))
394     {
395       dbus_message_unref (reply);
396       BUS_SET_OOM (error);
397       return FALSE;
398     }
399
400   dbus_message_iter_init_append (reply, &iter);
401   
402   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
403                                          DBUS_TYPE_STRING_AS_STRING,
404                                          &sub))
405     {
406       dbus_free_string_array (services);
407       dbus_message_unref (reply);
408       BUS_SET_OOM (error);
409       return FALSE;
410     }
411
412   i = 0;
413   while (i < len)
414     {
415       if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
416                                            &services[i]))
417         {
418           dbus_free_string_array (services);
419           dbus_message_unref (reply);
420           BUS_SET_OOM (error);
421           return FALSE;
422         }
423       ++i;
424     }
425
426   if (!dbus_message_iter_close_container (&iter, &sub))
427     {
428       dbus_free_string_array (services);
429       dbus_message_unref (reply);
430       BUS_SET_OOM (error);
431       return FALSE;
432     }
433   
434   dbus_free_string_array (services);
435   
436   if (!bus_transaction_send_from_driver (transaction, connection, reply))
437     {
438       dbus_message_unref (reply);
439       BUS_SET_OOM (error);
440       return FALSE;
441     }
442   else
443     {
444       dbus_message_unref (reply);
445       return TRUE;
446     }
447 }
448
449 static dbus_bool_t
450 bus_driver_handle_acquire_service (DBusConnection *connection,
451                                    BusTransaction *transaction,
452                                    DBusMessage    *message,
453                                    DBusError      *error)
454 {
455   DBusMessage *reply;
456   DBusString service_name;
457   const char *name;
458   int service_reply;
459   dbus_uint32_t flags;
460   dbus_bool_t retval;
461   BusRegistry *registry;
462
463   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
464   
465   registry = bus_connection_get_registry (connection);
466   
467   if (!dbus_message_get_args (message, error,
468                               DBUS_TYPE_STRING, &name,
469                               DBUS_TYPE_UINT32, &flags,
470                               DBUS_TYPE_INVALID))
471     return FALSE;
472   
473   _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags);
474   
475   retval = FALSE;
476   reply = NULL;
477
478   _dbus_string_init_const (&service_name, name);
479
480   if (!bus_registry_acquire_service (registry, connection,
481                                      &service_name, flags,
482                                      &service_reply, transaction,
483                                      error))
484     goto out;
485   
486   reply = dbus_message_new_method_return (message);
487   if (reply == NULL)
488     {
489       BUS_SET_OOM (error);
490       goto out;
491     }
492
493   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
494     {
495       BUS_SET_OOM (error);
496       goto out;
497     }
498
499   if (!bus_transaction_send_from_driver (transaction, connection, reply))
500     {
501       BUS_SET_OOM (error);
502       goto out;
503     }
504
505   retval = TRUE;
506   
507  out:
508   if (reply)
509     dbus_message_unref (reply);
510   return retval;
511
512
513 static dbus_bool_t
514 bus_driver_handle_service_exists (DBusConnection *connection,
515                                   BusTransaction *transaction,
516                                   DBusMessage    *message,
517                                   DBusError      *error)
518 {
519   DBusMessage *reply;
520   DBusString service_name;
521   BusService *service;
522   unsigned char service_exists;
523   const char *name;
524   dbus_bool_t retval;
525   BusRegistry *registry;
526
527   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
528   
529   registry = bus_connection_get_registry (connection);
530   
531   if (!dbus_message_get_args (message, error,
532                               DBUS_TYPE_STRING, &name,
533                               DBUS_TYPE_INVALID))
534     return FALSE;
535
536   retval = FALSE;
537
538   if (strcmp (name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0)
539     {
540       service_exists = TRUE;
541     }
542   else
543     {
544       _dbus_string_init_const (&service_name, name);
545       service = bus_registry_lookup (registry, &service_name);
546       service_exists = service != NULL;
547     }
548   
549   reply = dbus_message_new_method_return (message);
550   if (reply == NULL)
551     {
552       BUS_SET_OOM (error);
553       goto out;
554     }
555
556   if (!dbus_message_append_args (reply,
557                                  DBUS_TYPE_BOOLEAN, &service_exists,
558                                  0))
559     {
560       BUS_SET_OOM (error);
561       goto out;
562     }
563
564   if (!bus_transaction_send_from_driver (transaction, connection, reply))
565     {
566       BUS_SET_OOM (error);
567       goto out;
568     }
569
570   retval = TRUE;
571   
572  out:
573   if (reply)
574     dbus_message_unref (reply);
575
576   return retval;
577 }
578
579 static dbus_bool_t
580 bus_driver_handle_activate_service (DBusConnection *connection,
581                                     BusTransaction *transaction,
582                                     DBusMessage    *message,
583                                     DBusError      *error)
584 {
585   dbus_uint32_t flags;
586   const char *name;
587   dbus_bool_t retval;
588   BusActivation *activation;
589
590   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
591   
592   activation = bus_connection_get_activation (connection);
593   
594   if (!dbus_message_get_args (message, error,
595                               DBUS_TYPE_STRING, &name,
596                               DBUS_TYPE_UINT32, &flags,
597                               DBUS_TYPE_INVALID))
598     {
599       _DBUS_ASSERT_ERROR_IS_SET (error);
600       _dbus_verbose ("No memory to get arguments to ActivateService\n");
601       return FALSE;
602     }
603
604   retval = FALSE;
605
606   if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
607                                         message, name, error))
608     {
609       _DBUS_ASSERT_ERROR_IS_SET (error);
610       _dbus_verbose ("bus_activation_activate_service() failed\n");
611       goto out;
612     }
613
614   retval = TRUE;
615   
616  out:
617   return retval;
618 }
619
620 static dbus_bool_t
621 send_ack_reply (DBusConnection *connection,
622                 BusTransaction *transaction,
623                 DBusMessage    *message,
624                 DBusError      *error)
625 {
626   DBusMessage *reply;
627
628   reply = dbus_message_new_method_return (message);
629   if (reply == NULL)
630     {
631       BUS_SET_OOM (error);
632       return FALSE;
633     }
634
635   if (!bus_transaction_send_from_driver (transaction, connection, reply))
636     {
637       BUS_SET_OOM (error);
638       dbus_message_unref (reply);
639       return FALSE;
640     }
641
642   dbus_message_unref (reply);
643   
644   return TRUE;
645 }
646
647 static dbus_bool_t
648 bus_driver_handle_add_match (DBusConnection *connection,
649                              BusTransaction *transaction,
650                              DBusMessage    *message,
651                              DBusError      *error)
652 {
653   BusMatchRule *rule;
654   const char *text;
655   DBusString str;
656   BusMatchmaker *matchmaker;
657   
658   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
659
660   text = NULL;
661   rule = NULL;
662
663   if (bus_connection_get_n_match_rules (connection) >=
664       bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
665     {
666       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
667                       "Connection \"%s\" is not allowed to add more match rules "
668                       "(increase limits in configuration file if required)",
669                       bus_connection_is_active (connection) ?
670                       bus_connection_get_name (connection) :
671                       "(inactive)");
672       goto failed;
673     }
674   
675   if (!dbus_message_get_args (message, error,
676                               DBUS_TYPE_STRING, &text,
677                               DBUS_TYPE_INVALID))
678     {
679       _dbus_verbose ("No memory to get arguments to AddMatch\n");
680       goto failed;
681     }
682
683   _dbus_string_init_const (&str, text);
684
685   rule = bus_match_rule_parse (connection, &str, error);
686   if (rule == NULL)
687     goto failed;
688
689   matchmaker = bus_connection_get_matchmaker (connection);
690
691   if (!bus_matchmaker_add_rule (matchmaker, rule))
692     {
693       BUS_SET_OOM (error);
694       goto failed;
695     }
696
697   if (!send_ack_reply (connection, transaction,
698                        message, error))
699     {
700       bus_matchmaker_remove_rule (matchmaker, rule);
701       goto failed;
702     }
703   
704   bus_match_rule_unref (rule);
705   
706   return TRUE;
707
708  failed:
709   _DBUS_ASSERT_ERROR_IS_SET (error);
710   if (rule)
711     bus_match_rule_unref (rule);
712   return FALSE;
713 }
714
715 static dbus_bool_t
716 bus_driver_handle_remove_match (DBusConnection *connection,
717                                 BusTransaction *transaction,
718                                 DBusMessage    *message,
719                                 DBusError      *error)
720 {
721   BusMatchRule *rule;
722   const char *text;
723   DBusString str;
724   BusMatchmaker *matchmaker;
725   
726   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
727
728   text = NULL;
729   rule = NULL;
730   
731   if (!dbus_message_get_args (message, error,
732                               DBUS_TYPE_STRING, &text,
733                               DBUS_TYPE_INVALID))
734     {
735       _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
736       goto failed;
737     }
738
739   _dbus_string_init_const (&str, text);
740
741   rule = bus_match_rule_parse (connection, &str, error);
742   if (rule == NULL)
743     goto failed;
744
745   /* Send the ack before we remove the rule, since the ack is undone
746    * on transaction cancel, but rule removal isn't.
747    */
748   if (!send_ack_reply (connection, transaction,
749                        message, error))
750     goto failed;
751   
752   matchmaker = bus_connection_get_matchmaker (connection);
753
754   if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
755     goto failed;
756
757   bus_match_rule_unref (rule);
758   
759   return TRUE;
760
761  failed:
762   _DBUS_ASSERT_ERROR_IS_SET (error);
763   if (rule)
764     bus_match_rule_unref (rule);
765   return FALSE;
766 }
767
768 static dbus_bool_t
769 bus_driver_handle_get_service_owner (DBusConnection *connection,
770                                      BusTransaction *transaction,
771                                      DBusMessage    *message,
772                                      DBusError      *error)
773 {
774   const char *text;
775   const char *base_name;
776   DBusString str;
777   BusRegistry *registry;
778   BusService *service;
779   DBusMessage *reply;
780   
781   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
782
783   registry = bus_connection_get_registry (connection);
784
785   text = NULL;
786   reply = NULL;
787
788   if (! dbus_message_get_args (message, error,
789                                DBUS_TYPE_STRING, &text,
790                                DBUS_TYPE_INVALID))
791       goto failed;
792
793   _dbus_string_init_const (&str, text);
794   service = bus_registry_lookup (registry, &str);
795   if (service == NULL)
796     {
797       dbus_set_error (error, 
798                       DBUS_ERROR_SERVICE_HAS_NO_OWNER,
799                       "Could not get owner of service '%s': no such service", text);
800       goto failed;
801     }
802
803   base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
804   if (base_name == NULL)
805     {
806       dbus_set_error (error,
807                       DBUS_ERROR_FAILED,
808                       "Could not determine base service for '%s'", text);
809       goto failed;
810     }
811   _dbus_assert (*base_name == ':');
812
813   reply = dbus_message_new_method_return (message);
814   if (reply == NULL)
815     goto oom;
816
817   if (! dbus_message_append_args (reply, 
818                                   DBUS_TYPE_STRING, &base_name,
819                                   DBUS_TYPE_INVALID))
820     goto oom;
821   
822   if (! bus_transaction_send_from_driver (transaction, connection, reply))
823     goto oom;
824
825   dbus_message_unref (reply);
826
827   return TRUE;
828
829  oom:
830   BUS_SET_OOM (error);
831
832  failed:
833   _DBUS_ASSERT_ERROR_IS_SET (error);
834   if (reply)
835     dbus_message_unref (reply);
836   return FALSE;
837 }
838
839 static dbus_bool_t
840 bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
841                                             BusTransaction *transaction,
842                                             DBusMessage    *message,
843                                             DBusError      *error)
844 {
845   const char *service;
846   DBusString str;
847   BusRegistry *registry;
848   BusService *serv;
849   DBusConnection *conn;
850   DBusMessage *reply;
851   unsigned long uid;
852   dbus_uint32_t uid32;
853
854   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
855
856   registry = bus_connection_get_registry (connection);
857
858   service = NULL;
859   reply = NULL;
860
861   if (! dbus_message_get_args (message, error,
862                                DBUS_TYPE_STRING, &service,
863                                DBUS_TYPE_INVALID))
864       goto failed;
865
866   _dbus_verbose ("asked for UID of connection %s\n", service);
867
868   _dbus_string_init_const (&str, service);
869   serv = bus_registry_lookup (registry, &str);
870   if (serv == NULL)
871     {
872       dbus_set_error (error, 
873                       DBUS_ERROR_SERVICE_HAS_NO_OWNER,
874                       "Could not get owner of service '%s': no such service", service);
875       goto failed;
876     }
877
878   conn = bus_service_get_primary_owner (serv);
879
880   reply = dbus_message_new_method_return (message);
881   if (reply == NULL)
882     goto oom;
883
884   if (!dbus_connection_get_unix_user (conn, &uid))
885     {
886       dbus_set_error (error,
887                       DBUS_ERROR_FAILED,
888                       "Could not determine UID for '%s'", service);
889       goto failed;
890     }
891
892   uid32 = uid;
893   if (! dbus_message_append_args (reply,
894                                   DBUS_TYPE_UINT32, &uid32,
895                                   DBUS_TYPE_INVALID))
896     goto oom;
897
898   if (! bus_transaction_send_from_driver (transaction, connection, reply))
899     goto oom;
900
901   dbus_message_unref (reply);
902
903   return TRUE;
904
905  oom:
906   BUS_SET_OOM (error);
907
908  failed:
909   _DBUS_ASSERT_ERROR_IS_SET (error);
910   if (reply)
911     dbus_message_unref (reply);
912   return FALSE;
913 }
914
915 static dbus_bool_t
916 bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
917                                                   BusTransaction *transaction,
918                                                   DBusMessage    *message,
919                                                   DBusError      *error)
920 {
921   const char *service;
922   DBusString str;
923   BusRegistry *registry;
924   BusService *serv;
925   DBusConnection *conn;
926   DBusMessage *reply;
927   unsigned long pid;
928   dbus_uint32_t pid32;
929
930   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
931
932   registry = bus_connection_get_registry (connection);
933
934   service = NULL;
935   reply = NULL;
936
937   if (! dbus_message_get_args (message, error,
938                                DBUS_TYPE_STRING, &service,
939                                DBUS_TYPE_INVALID))
940       goto failed;
941
942   _dbus_verbose ("asked for PID of connection %s\n", service);
943
944   _dbus_string_init_const (&str, service);
945   serv = bus_registry_lookup (registry, &str);
946   if (serv == NULL)
947     {
948       dbus_set_error (error, 
949                       DBUS_ERROR_SERVICE_HAS_NO_OWNER,
950                       "Could not get owner of service '%s': no such service", service);
951       goto failed;
952     }
953
954   conn = bus_service_get_primary_owner (serv);
955
956   reply = dbus_message_new_method_return (message);
957   if (reply == NULL)
958     goto oom;
959
960   if (!dbus_connection_get_unix_process_id (conn, &pid))
961     {
962       dbus_set_error (error,
963                       DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
964                       "Could not determine PID for '%s'", service);
965       goto failed;
966     }
967
968   pid32 = pid;
969   if (! dbus_message_append_args (reply,
970                                   DBUS_TYPE_UINT32, &pid32,
971                                   DBUS_TYPE_INVALID))
972     goto oom;
973
974   if (! bus_transaction_send_from_driver (transaction, connection, reply))
975     goto oom;
976
977   dbus_message_unref (reply);
978
979   return TRUE;
980
981  oom:
982   BUS_SET_OOM (error);
983
984  failed:
985   _DBUS_ASSERT_ERROR_IS_SET (error);
986   if (reply)
987     dbus_message_unref (reply);
988   return FALSE;
989 }
990
991 static dbus_bool_t
992 bus_driver_handle_reload_config (DBusConnection *connection,
993                                  BusTransaction *transaction,
994                                  DBusMessage    *message,
995                                  DBusError      *error)
996 {
997   BusContext *context;
998   dbus_bool_t retval;
999
1000   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1001
1002   retval = FALSE;
1003
1004   context = bus_connection_get_context (connection);
1005   if (!bus_context_reload_config (context, error))
1006     {
1007       _DBUS_ASSERT_ERROR_IS_SET (error);
1008       goto out;
1009     }
1010
1011   retval = TRUE;
1012   
1013  out:
1014   return retval;
1015 }
1016
1017 /* For speed it might be useful to sort this in order of
1018  * frequency of use (but doesn't matter with only a few items
1019  * anyhow)
1020  */
1021 struct
1022 {
1023   const char *name;
1024   dbus_bool_t (* handler) (DBusConnection *connection,
1025                            BusTransaction *transaction,
1026                            DBusMessage    *message,
1027                            DBusError      *error);
1028 } message_handlers[] = {
1029   { "AcquireService", bus_driver_handle_acquire_service },
1030   { "ActivateService", bus_driver_handle_activate_service },
1031   { "Hello", bus_driver_handle_hello },
1032   { "ServiceExists", bus_driver_handle_service_exists },
1033   { "ListServices", bus_driver_handle_list_services },
1034   { "AddMatch", bus_driver_handle_add_match },
1035   { "RemoveMatch", bus_driver_handle_remove_match },
1036   { "GetServiceOwner", bus_driver_handle_get_service_owner },
1037   { "GetConnectionUnixUser", bus_driver_handle_get_connection_unix_user },
1038   { "GetConnectionUnixProcessID", bus_driver_handle_get_connection_unix_process_id },
1039   { "ReloadConfig", bus_driver_handle_reload_config }
1040 };
1041
1042 dbus_bool_t
1043 bus_driver_handle_message (DBusConnection *connection,
1044                            BusTransaction *transaction,
1045                            DBusMessage    *message,
1046                            DBusError      *error)
1047 {
1048   const char *name, *sender;
1049   int i;
1050
1051   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1052
1053   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1054     {
1055       _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1056       return TRUE; /* we just ignore this */
1057     }
1058
1059   _dbus_assert (dbus_message_get_interface (message) != NULL);
1060   _dbus_assert (dbus_message_get_member (message) != NULL);
1061
1062   name = dbus_message_get_member (message);
1063   sender = dbus_message_get_sender (message);
1064   
1065   if (strcmp (dbus_message_get_interface (message),
1066               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0)
1067     {
1068       _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
1069                      dbus_message_get_interface (message));
1070       goto unknown;
1071     }
1072   
1073   _dbus_verbose ("Driver got a method call: %s\n",
1074                  dbus_message_get_member (message));
1075   
1076   /* security checks should have kept this from getting here */
1077   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
1078
1079   if (dbus_message_get_reply_serial (message) != 0)
1080     {
1081       _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n");
1082       return TRUE;
1083     }
1084   
1085   i = 0;
1086   while (i < _DBUS_N_ELEMENTS (message_handlers))
1087     {
1088       if (strcmp (message_handlers[i].name, name) == 0)
1089         {
1090           _dbus_verbose ("Running driver handler for %s\n", name);
1091           if ((* message_handlers[i].handler) (connection, transaction, message, error))
1092             {
1093               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1094               _dbus_verbose ("Driver handler succeeded\n");
1095               return TRUE;
1096             }
1097           else
1098             {
1099               _DBUS_ASSERT_ERROR_IS_SET (error);
1100               _dbus_verbose ("Driver handler returned failure\n");
1101               return FALSE;
1102             }
1103         }
1104       
1105       ++i;
1106     }
1107
1108  unknown:
1109   _dbus_verbose ("No driver handler for message \"%s\"\n",
1110                  name);
1111
1112   dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
1113                   "%s does not understand message %s",
1114                   DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, name);
1115   
1116   return FALSE;
1117 }
1118
1119 void
1120 bus_driver_remove_connection (DBusConnection *connection)
1121 {
1122   /* FIXME Does nothing for now, should unregister the connection
1123    * with the bus driver.
1124    */
1125 }