2003-10-14 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 "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_deleted (const char     *service_name,
43                                  BusTransaction *transaction,
44                                  DBusError      *error)
45 {
46   DBusMessage *message;
47   dbus_bool_t retval;
48
49   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
50   
51   _dbus_verbose ("sending service deleted: %s\n", service_name);
52
53   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
54                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
55                                      "ServiceDeleted");
56   
57   if (message == NULL)
58     {
59       BUS_SET_OOM (error);
60       return FALSE;
61     }
62   
63   if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) ||
64       !dbus_message_append_args (message,
65                                  DBUS_TYPE_STRING, service_name,
66                                  DBUS_TYPE_INVALID))
67     {
68       dbus_message_unref (message);
69       BUS_SET_OOM (error);
70       return FALSE;
71     }
72
73   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
74   dbus_message_unref (message);
75
76   return retval;
77 }
78
79 dbus_bool_t
80 bus_driver_send_service_created (const char     *service_name,
81                                  BusTransaction *transaction,
82                                  DBusError      *error)
83 {
84   DBusMessage *message;
85   dbus_bool_t retval;
86
87   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
88   
89   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
90                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
91                                      "ServiceCreated");
92   
93   if (message == NULL)
94     {
95       BUS_SET_OOM (error);
96       return FALSE;
97     }
98   
99   if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
100     {
101       dbus_message_unref (message);
102       BUS_SET_OOM (error);
103       return FALSE;
104     }
105   
106   if (!dbus_message_append_args (message,
107                                  DBUS_TYPE_STRING, service_name,
108                                  DBUS_TYPE_INVALID))
109     {
110       dbus_message_unref (message);
111       BUS_SET_OOM (error);
112       return FALSE;
113     }
114   
115   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
116   dbus_message_unref (message);
117
118   return retval;
119 }
120
121 dbus_bool_t
122 bus_driver_send_service_lost (DBusConnection *connection,
123                               const char     *service_name,
124                               BusTransaction *transaction,
125                               DBusError      *error)
126 {
127   DBusMessage *message;
128
129   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
130   
131   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
132                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
133                                      "ServiceLost");
134   
135   if (message == NULL)
136     {
137       BUS_SET_OOM (error);
138       return FALSE;
139     }
140   
141   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
142       !dbus_message_append_args (message,
143                                  DBUS_TYPE_STRING, service_name,
144                                  DBUS_TYPE_INVALID))
145     {
146       dbus_message_unref (message);
147       BUS_SET_OOM (error);
148       return FALSE;
149     }
150
151   if (!bus_transaction_send_from_driver (transaction, connection, message))
152     {
153       dbus_message_unref (message);
154       BUS_SET_OOM (error);
155       return FALSE;
156     }
157   else
158     {
159       dbus_message_unref (message);
160       return TRUE;
161     }
162 }
163
164 dbus_bool_t
165 bus_driver_send_service_acquired (DBusConnection *connection,
166                                   const char     *service_name,
167                                   BusTransaction *transaction,
168                                   DBusError      *error)
169 {
170   DBusMessage *message;
171
172   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
173   
174   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
175                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
176                                      "ServiceAcquired");
177
178   if (message == NULL)
179     {
180       BUS_SET_OOM (error);
181       return FALSE;
182     }
183   
184   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
185       !dbus_message_append_args (message,
186                                  DBUS_TYPE_STRING, service_name,
187                                  DBUS_TYPE_INVALID))
188     {
189       dbus_message_unref (message);
190       BUS_SET_OOM (error);
191       return FALSE;
192     }
193
194   if (!bus_transaction_send_from_driver (transaction, connection, message))
195     {
196       dbus_message_unref (message);
197       BUS_SET_OOM (error);
198       return FALSE;
199     }
200   else
201     {
202       dbus_message_unref (message);
203       return TRUE;
204     }
205 }
206
207 static dbus_bool_t
208 create_unique_client_name (BusRegistry *registry,
209                            DBusString  *str)
210 {
211   /* We never want to use the same unique client name twice, because
212    * we want to guarantee that if you send a message to a given unique
213    * name, you always get the same application. So we use two numbers
214    * for INT_MAX * INT_MAX combinations, should be pretty safe against
215    * wraparound.
216    */
217   /* FIXME these should be in BusRegistry rather than static vars */
218   static int next_major_number = 0;
219   static int next_minor_number = 0;
220   int len;
221   
222   len = _dbus_string_get_length (str);
223   
224   while (TRUE)
225     {
226       /* start out with 1-0, go to 1-1, 1-2, 1-3,
227        * up to 1-MAXINT, then 2-0, 2-1, etc.
228        */
229       if (next_minor_number <= 0)
230         {
231           next_major_number += 1;
232           next_minor_number = 0;
233           if (next_major_number <= 0)
234             _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
235         }
236
237       _dbus_assert (next_major_number > 0);
238       _dbus_assert (next_minor_number >= 0);
239
240       /* appname:MAJOR-MINOR */
241       
242       if (!_dbus_string_append (str, ":"))
243         return FALSE;
244       
245       if (!_dbus_string_append_int (str, next_major_number))
246         return FALSE;
247
248       if (!_dbus_string_append (str, "-"))
249         return FALSE;
250       
251       if (!_dbus_string_append_int (str, next_minor_number))
252         return FALSE;
253
254       next_minor_number += 1;
255       
256       /* Check if a client with the name exists */
257       if (bus_registry_lookup (registry, str) == NULL)
258         break;
259
260       /* drop the number again, try the next one. */
261       _dbus_string_set_length (str, len);
262     }
263
264   return TRUE;
265 }
266
267 static dbus_bool_t
268 bus_driver_handle_hello (DBusConnection *connection,
269                          BusTransaction *transaction,
270                          DBusMessage    *message,
271                          DBusError      *error)
272 {
273   DBusString unique_name;
274   BusService *service;
275   dbus_bool_t retval;
276   BusRegistry *registry;
277   BusConnections *connections;
278
279   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
280
281   /* Note that when these limits are exceeded we don't disconnect the
282    * connection; we just sort of leave it hanging there until it times
283    * out or disconnects itself or is dropped due to the max number of
284    * incomplete connections. It's even OK if the connection wants to
285    * retry the hello message, we support that.
286    */
287   connections = bus_connection_get_connections (connection);
288   if (!bus_connections_check_limits (connections, connection,
289                                      error))
290     {
291       _DBUS_ASSERT_ERROR_IS_SET (error);
292       return FALSE;
293     }
294   
295   if (!_dbus_string_init (&unique_name))
296     {
297       BUS_SET_OOM (error);
298       return FALSE;
299     }
300
301   retval = FALSE;
302
303   registry = bus_connection_get_registry (connection);
304   
305   if (!create_unique_client_name (registry, &unique_name))
306     {
307       BUS_SET_OOM (error);
308       goto out_0;
309     }
310
311   if (!bus_connection_complete (connection, &unique_name, error))
312     {
313       _DBUS_ASSERT_ERROR_IS_SET (error);
314       goto out_0;
315     }
316   
317   if (!dbus_message_set_sender (message,
318                                 bus_connection_get_name (connection)))
319     {
320       BUS_SET_OOM (error);
321       goto out_0;
322     }
323   
324   if (!bus_driver_send_welcome_message (connection, message, transaction, error))
325     goto out_0;
326
327   /* Create the service */
328   service = bus_registry_ensure (registry,
329                                  &unique_name, connection, transaction, error);
330   if (service == NULL)
331     goto out_0;
332   
333   bus_service_set_prohibit_replacement (service, TRUE);
334
335   _dbus_assert (bus_connection_is_active (connection));
336   retval = TRUE;
337   
338  out_0:
339   _dbus_string_free (&unique_name);
340   return retval;
341 }
342
343 static dbus_bool_t
344 bus_driver_send_welcome_message (DBusConnection *connection,
345                                  DBusMessage    *hello_message,
346                                  BusTransaction *transaction,
347                                  DBusError      *error)
348 {
349   DBusMessage *welcome;
350   const char *name;
351
352   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
353   
354   name = bus_connection_get_name (connection);
355   _dbus_assert (name != NULL);
356   
357   welcome = dbus_message_new_method_return (hello_message);
358   if (welcome == NULL)
359     {
360       BUS_SET_OOM (error);
361       return FALSE;
362     }
363   
364   if (!dbus_message_append_args (welcome,
365                                  DBUS_TYPE_STRING, name,
366                                  DBUS_TYPE_INVALID))
367     {
368       dbus_message_unref (welcome);
369       BUS_SET_OOM (error);
370       return FALSE;
371     }
372
373   if (!bus_transaction_send_from_driver (transaction, connection, welcome))
374     {
375       dbus_message_unref (welcome);
376       BUS_SET_OOM (error);
377       return FALSE;
378     }
379   else
380     {
381       dbus_message_unref (welcome);
382       return TRUE;
383     }
384 }
385
386 static dbus_bool_t
387 bus_driver_handle_list_services (DBusConnection *connection,
388                                  BusTransaction *transaction,
389                                  DBusMessage    *message,
390                                  DBusError      *error)
391 {
392   DBusMessage *reply;
393   int len;
394   char **services;
395   BusRegistry *registry;
396
397   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
398   
399   registry = bus_connection_get_registry (connection);
400   
401   reply = dbus_message_new_method_return (message);
402   if (reply == NULL)
403     {
404       BUS_SET_OOM (error);
405       return FALSE;
406     }
407
408   if (!bus_registry_list_services (registry, &services, &len))
409     {
410       dbus_message_unref (reply);
411       BUS_SET_OOM (error);
412       return FALSE;
413     }
414   
415   if (!dbus_message_append_args (reply,
416                                  DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, services, len,
417                                  DBUS_TYPE_INVALID))
418     {
419       dbus_free_string_array (services);
420       dbus_message_unref (reply);
421       BUS_SET_OOM (error);
422       return FALSE;
423     }
424
425   dbus_free_string_array (services);
426   
427   if (!bus_transaction_send_from_driver (transaction, connection, reply))
428     {
429       dbus_message_unref (reply);
430       BUS_SET_OOM (error);
431       return FALSE;
432     }
433   else
434     {
435       dbus_message_unref (reply);
436       return TRUE;
437     }
438 }
439
440 static dbus_bool_t
441 bus_driver_handle_acquire_service (DBusConnection *connection,
442                                    BusTransaction *transaction,
443                                    DBusMessage    *message,
444                                    DBusError      *error)
445 {
446   DBusMessage *reply;
447   DBusString service_name;
448   char *name;
449   int service_reply;
450   int flags;
451   dbus_bool_t retval;
452   BusRegistry *registry;
453
454   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
455   
456   registry = bus_connection_get_registry (connection);
457   
458   if (!dbus_message_get_args (message, error,
459                               DBUS_TYPE_STRING, &name,
460                               DBUS_TYPE_UINT32, &flags,
461                               DBUS_TYPE_INVALID))
462     return FALSE;
463   
464   _dbus_verbose ("Trying to own service %s with flags 0x%x\n", name, flags);
465   
466   retval = FALSE;
467   reply = NULL;
468
469   _dbus_string_init_const (&service_name, name);
470
471   if (!bus_registry_acquire_service (registry, connection,
472                                      &service_name, flags,
473                                      &service_reply, transaction,
474                                      error))
475     goto out;
476   
477   reply = dbus_message_new_method_return (message);
478   if (reply == NULL)
479     {
480       BUS_SET_OOM (error);
481       goto out;
482     }
483
484   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, DBUS_TYPE_INVALID))
485     {
486       BUS_SET_OOM (error);
487       goto out;
488     }
489
490   if (!bus_transaction_send_from_driver (transaction, connection, reply))
491     {
492       BUS_SET_OOM (error);
493       goto out;
494     }
495
496   retval = TRUE;
497   
498  out:
499   dbus_free (name);
500   if (reply)
501     dbus_message_unref (reply);
502   return retval;
503
504
505 static dbus_bool_t
506 bus_driver_handle_service_exists (DBusConnection *connection,
507                                   BusTransaction *transaction,
508                                   DBusMessage    *message,
509                                   DBusError      *error)
510 {
511   DBusMessage *reply;
512   DBusString service_name;
513   BusService *service;
514   char *name;
515   dbus_bool_t retval;
516   BusRegistry *registry;
517
518   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
519   
520   registry = bus_connection_get_registry (connection);
521   
522   if (!dbus_message_get_args (message, error,
523                               DBUS_TYPE_STRING, &name,
524                               DBUS_TYPE_INVALID))
525     return FALSE;
526
527   retval = FALSE;
528   
529   _dbus_string_init_const (&service_name, name);
530   service = bus_registry_lookup (registry, &service_name);
531  
532   reply = dbus_message_new_method_return (message);
533   if (reply == NULL)
534     {
535       BUS_SET_OOM (error);
536       goto out;
537     }
538
539   if (!dbus_message_append_args (reply,
540                                  DBUS_TYPE_UINT32, service != NULL,
541                                  0))
542     {
543       BUS_SET_OOM (error);
544       goto out;
545     }
546
547   if (!bus_transaction_send_from_driver (transaction, connection, reply))
548     {
549       BUS_SET_OOM (error);
550       goto out;
551     }
552
553   retval = TRUE;
554   
555  out:
556   if (reply)
557     dbus_message_unref (reply);
558   dbus_free (name);
559
560   return retval;
561 }
562
563 static dbus_bool_t
564 bus_driver_handle_activate_service (DBusConnection *connection,
565                                     BusTransaction *transaction,
566                                     DBusMessage    *message,
567                                     DBusError      *error)
568 {
569   dbus_uint32_t flags;
570   char *name;
571   dbus_bool_t retval;
572   BusActivation *activation;
573
574   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
575   
576   activation = bus_connection_get_activation (connection);
577   
578   if (!dbus_message_get_args (message, error,
579                               DBUS_TYPE_STRING, &name,
580                               DBUS_TYPE_UINT32, &flags,
581                               DBUS_TYPE_INVALID))
582     {
583       _DBUS_ASSERT_ERROR_IS_SET (error);
584       _dbus_verbose ("No memory to get arguments to ActivateService\n");
585       return FALSE;
586     }
587
588   retval = FALSE;
589
590   if (!bus_activation_activate_service (activation, connection, transaction,
591                                         message, name, error))
592     {
593       _DBUS_ASSERT_ERROR_IS_SET (error);
594       _dbus_verbose ("bus_activation_activate_service() failed\n");
595       goto out;
596     }
597
598   retval = TRUE;
599   
600  out:
601   dbus_free (name);
602   return retval;
603 }
604
605 static dbus_bool_t
606 send_ack_reply (DBusConnection *connection,
607                 BusTransaction *transaction,
608                 DBusMessage    *message,
609                 DBusError      *error)
610 {
611   DBusMessage *reply;
612
613   reply = dbus_message_new_method_return (message);
614   if (reply == NULL)
615     {
616       BUS_SET_OOM (error);
617       return FALSE;
618     }
619
620   if (!bus_transaction_send_from_driver (transaction, connection, reply))
621     {
622       BUS_SET_OOM (error);
623       dbus_message_unref (reply);
624       return FALSE;
625     }
626
627   dbus_message_unref (reply);
628   
629   return TRUE;
630 }
631
632 static dbus_bool_t
633 bus_driver_handle_add_match (DBusConnection *connection,
634                              BusTransaction *transaction,
635                              DBusMessage    *message,
636                              DBusError      *error)
637 {
638   BusMatchRule *rule;
639   char *text;
640   DBusString str;
641   BusMatchmaker *matchmaker;
642   
643   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
644
645   text = NULL;
646   rule = NULL;
647
648   if (bus_connection_get_n_match_rules (connection) >=
649       bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
650     {
651       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
652                       "Connection \"%s\" is not allowed to add more match rules "
653                       "(increase limits in configuration file if required)",
654                       bus_connection_is_active (connection) ?
655                       bus_connection_get_name (connection) :
656                       "(inactive)");
657       goto failed;
658     }
659   
660   if (!dbus_message_get_args (message, error,
661                               DBUS_TYPE_STRING, &text,
662                               DBUS_TYPE_INVALID))
663     {
664       _dbus_verbose ("No memory to get arguments to AddMatch\n");
665       goto failed;
666     }
667
668   _dbus_string_init_const (&str, text);
669
670   rule = bus_match_rule_parse (connection, &str, error);
671   if (rule == NULL)
672     goto failed;
673
674   matchmaker = bus_connection_get_matchmaker (connection);
675
676   if (!bus_matchmaker_add_rule (matchmaker, rule))
677     {
678       BUS_SET_OOM (error);
679       goto failed;
680     }
681
682   if (!send_ack_reply (connection, transaction,
683                        message, error))
684     {
685       bus_matchmaker_remove_rule (matchmaker, rule);
686       goto failed;
687     }
688   
689   bus_match_rule_unref (rule);
690   dbus_free (text);
691   
692   return TRUE;
693
694  failed:
695   _DBUS_ASSERT_ERROR_IS_SET (error);
696   if (rule)
697     bus_match_rule_unref (rule);
698   if (text)
699     dbus_free (text);
700   return FALSE;
701 }
702
703 static dbus_bool_t
704 bus_driver_handle_remove_match (DBusConnection *connection,
705                                 BusTransaction *transaction,
706                                 DBusMessage    *message,
707                                 DBusError      *error)
708 {
709   BusMatchRule *rule;
710   char *text;
711   DBusString str;
712   BusMatchmaker *matchmaker;
713   
714   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
715
716   text = NULL;
717   rule = NULL;
718   
719   if (!dbus_message_get_args (message, error,
720                               DBUS_TYPE_STRING, &text,
721                               DBUS_TYPE_INVALID))
722     {
723       _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
724       goto failed;
725     }
726
727   _dbus_string_init_const (&str, text);
728
729   rule = bus_match_rule_parse (connection, &str, error);
730   if (rule == NULL)
731     goto failed;
732
733   /* Send the ack before we remove the rule, since the ack is undone
734    * on transaction cancel, but rule removal isn't.
735    */
736   if (!send_ack_reply (connection, transaction,
737                        message, error))
738     goto failed;
739   
740   matchmaker = bus_connection_get_matchmaker (connection);
741
742   if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
743     goto failed;
744
745   bus_match_rule_unref (rule);
746   dbus_free (text);
747   
748   return TRUE;
749
750  failed:
751   _DBUS_ASSERT_ERROR_IS_SET (error);
752   if (rule)
753     bus_match_rule_unref (rule);
754   if (text)
755     dbus_free (text);
756   return FALSE;
757 }
758
759 /* For speed it might be useful to sort this in order of
760  * frequency of use (but doesn't matter with only a few items
761  * anyhow)
762  */
763 struct
764 {
765   const char *name;
766   dbus_bool_t (* handler) (DBusConnection *connection,
767                            BusTransaction *transaction,
768                            DBusMessage    *message,
769                            DBusError      *error);
770 } message_handlers[] = {
771   { "AcquireService", bus_driver_handle_acquire_service },
772   { "ActivateService", bus_driver_handle_activate_service },
773   { "Hello", bus_driver_handle_hello },
774   { "ServiceExists", bus_driver_handle_service_exists },
775   { "ListServices", bus_driver_handle_list_services },
776   { "AddMatch", bus_driver_handle_add_match },
777   { "RemoveMatch", bus_driver_handle_remove_match }
778 };
779
780 dbus_bool_t
781 bus_driver_handle_message (DBusConnection *connection,
782                            BusTransaction *transaction,
783                            DBusMessage    *message,
784                            DBusError      *error)
785 {
786   const char *name, *sender;
787   int i;
788
789   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
790
791   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
792     {
793       _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
794       return TRUE; /* we just ignore this */
795     }
796
797   _dbus_assert (dbus_message_get_interface (message) != NULL);
798   _dbus_assert (dbus_message_get_member (message) != NULL);
799
800   name = dbus_message_get_member (message);
801   sender = dbus_message_get_sender (message);
802   
803   if (strcmp (dbus_message_get_interface (message),
804               DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0)
805     {
806       _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
807                      dbus_message_get_interface (message));
808       goto unknown;
809     }
810   
811   _dbus_verbose ("Driver got a method call: %s\n",
812                  dbus_message_get_member (message));
813   
814   /* security checks should have kept this from getting here */
815   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
816
817   if (dbus_message_get_reply_serial (message) != 0)
818     {
819       _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n");
820       return TRUE;
821     }
822   
823   i = 0;
824   while (i < _DBUS_N_ELEMENTS (message_handlers))
825     {
826       if (strcmp (message_handlers[i].name, name) == 0)
827         {
828           _dbus_verbose ("Running driver handler for %s\n", name);
829           if ((* message_handlers[i].handler) (connection, transaction, message, error))
830             {
831               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
832               _dbus_verbose ("Driver handler succeeded\n");
833               return TRUE;
834             }
835           else
836             {
837               _DBUS_ASSERT_ERROR_IS_SET (error);
838               _dbus_verbose ("Driver handler returned failure\n");
839               return FALSE;
840             }
841         }
842       
843       ++i;
844     }
845
846  unknown:
847   _dbus_verbose ("No driver handler for message \"%s\"\n",
848                  name);
849
850   dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
851                   "%s does not understand message %s",
852                   DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, name);
853   
854   return FALSE;
855 }
856
857 void
858 bus_driver_remove_connection (DBusConnection *connection)
859 {
860   /* FIXME Does nothing for now, should unregister the connection
861    * with the bus driver.
862    */
863 }