2003-03-31 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / dispatch.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dispatch.c  Message dispatcher
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 "dispatch.h"
26 #include "connection.h"
27 #include "driver.h"
28 #include "services.h"
29 #include "utils.h"
30 #include "bus.h"
31 #include "test.h"
32 #include "loop.h"
33 #include <dbus/dbus-internals.h>
34 #include <string.h>
35
36 static int message_handler_slot = -1;
37 static int message_handler_slot_refcount;
38
39 typedef struct
40 {
41   DBusMessage    *message;
42   BusTransaction *transaction;
43   DBusError      *error;
44 } SendMessageData;
45
46 static dbus_bool_t
47 send_one_message (DBusConnection *connection, void *data)
48 {
49   SendMessageData *d = data;
50   
51   if (!bus_connection_is_active (connection))
52     return TRUE;
53
54   if (!bus_transaction_send_message (d->transaction,
55                                      connection,
56                                      d->message))
57     {
58       BUS_SET_OOM (d->error);
59       return FALSE;
60     }
61
62   return TRUE;
63 }
64
65 dbus_bool_t
66 bus_dispatch_broadcast_message (BusTransaction *transaction,
67                                 DBusMessage    *message,
68                                 DBusError      *error)
69 {
70   DBusError tmp_error;
71   SendMessageData d;
72   BusConnections *connections;
73
74   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
75   
76   _dbus_assert (dbus_message_get_sender (message) != NULL);
77
78   connections = bus_transaction_get_connections (transaction);
79   
80   dbus_error_init (&tmp_error);
81   d.message = message;
82   d.transaction = transaction;
83   d.error = &tmp_error;
84   
85   bus_connections_foreach (connections, send_one_message, &d);
86
87   if (dbus_error_is_set (&tmp_error))
88     {
89       dbus_move_error (&tmp_error, error);
90       return FALSE;
91     }
92   else
93     return TRUE;
94 }
95
96 static dbus_bool_t
97 send_service_nonexistent_error (BusTransaction *transaction,
98                                 DBusConnection *connection,
99                                 const char     *service_name,
100                                 DBusMessage    *in_reply_to,
101                                 DBusError      *error)
102 {
103   DBusMessage *error_reply;
104   DBusString error_message;
105   const char *error_str;
106
107   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
108   
109   /* Trying to send a message to a non-existant service,
110    * bounce back an error message.
111    */
112           
113   if (!_dbus_string_init (&error_message))
114     {
115       BUS_SET_OOM (error);
116       return FALSE;
117     }
118
119   if (!_dbus_string_append (&error_message, "Service \"") ||
120       !_dbus_string_append (&error_message, service_name) ||
121       !_dbus_string_append (&error_message, "\" does not exist"))
122     {
123       _dbus_string_free (&error_message);
124       BUS_SET_OOM (error);
125       return FALSE;
126     }
127               
128   error_str = _dbus_string_get_const_data (&error_message);
129   error_reply = dbus_message_new_error_reply (in_reply_to,
130                                               DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
131                                               error_str);
132
133   _dbus_string_free (&error_message);
134               
135   if (error_reply == NULL)
136     {
137       BUS_SET_OOM (error);
138       return FALSE;
139     }
140               
141   if (!bus_transaction_send_message (transaction, connection, error_reply))
142     {
143       dbus_message_unref (error_reply);
144       BUS_SET_OOM (error);
145       return FALSE;
146     }
147               
148   dbus_message_unref (error_reply);
149
150   return TRUE;
151 }
152
153 static void
154 bus_dispatch (DBusConnection *connection,
155               DBusMessage    *message)
156 {
157   const char *sender, *service_name, *message_name;
158   DBusError error;
159   BusTransaction *transaction;
160   BusContext *context;
161   
162   transaction = NULL;
163   dbus_error_init (&error);
164   
165   context = bus_connection_get_context (connection);
166   _dbus_assert (context != NULL);
167   
168   /* If we can't even allocate an OOM error, we just go to sleep
169    * until we can.
170    */
171   while (!bus_connection_preallocate_oom_error (connection))
172     bus_wait_for_memory ();
173   
174   /* Ref connection in case we disconnect it at some point in here */
175   dbus_connection_ref (connection);
176
177   service_name = dbus_message_get_service (message);
178   message_name = dbus_message_get_name (message);
179
180   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
181
182   _dbus_verbose ("DISPATCH: %s to %s\n",
183                  message_name, service_name ? service_name : "peer");
184   
185   /* If service_name is NULL, this is a message to the bus daemon, not intended
186    * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these
187    * immediately, especially disconnection messages.
188    */
189   if (service_name == NULL)
190     {      
191       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
192         bus_connection_disconnected (connection);
193
194       /* DBusConnection also handles some of these automatically, we leave
195        * it to do so.
196        */
197       goto out;
198     }
199
200   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
201   
202   /* Create our transaction */
203   transaction = bus_transaction_new (context);
204   if (transaction == NULL)
205     {
206       BUS_SET_OOM (&error);
207       goto out;
208     }
209   
210   /* Assign a sender to the message */
211   if (bus_connection_is_active (connection))
212     {
213       sender = bus_connection_get_name (connection);
214       _dbus_assert (sender != NULL);
215
216       if (!dbus_message_set_sender (message, sender))
217         {
218           BUS_SET_OOM (&error);
219           goto out;
220         }
221
222       /* We need to refetch the service name here, because
223        * dbus_message_set_sender can cause the header to be
224        * reallocated, and thus the service_name pointer will become
225        * invalid.
226        */
227       service_name = dbus_message_get_service (message);
228     }
229
230   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
231     {
232       if (!bus_driver_handle_message (connection, transaction, message, &error))
233         goto out;
234     }
235   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
236     {
237       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
238       dbus_connection_disconnect (connection);
239     }
240   /* FIXME what if we un-special-case this service and just have a flag
241    * on services that all service owners will get messages to it, not just
242    * the primary owner.
243    */
244   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
245     {
246       if (!bus_dispatch_broadcast_message (transaction, message, &error))
247         goto out;
248     }
249   else  /* route to named service */
250     {
251       DBusString service_string;
252       BusService *service;
253       BusRegistry *registry;
254
255       registry = bus_connection_get_registry (connection);
256       
257       _dbus_string_init_const (&service_string, service_name);
258       service = bus_registry_lookup (registry, &service_string);
259
260       if (service == NULL)
261         {
262           if (!send_service_nonexistent_error (transaction, connection,
263                                                service_name,
264                                                message, &error))
265             goto out;
266         }
267       else
268         {
269           _dbus_assert (bus_service_get_primary_owner (service) != NULL);
270       
271           /* Dispatch the message */
272           if (!bus_transaction_send_message (transaction,
273                                              bus_service_get_primary_owner (service),
274                                              message))
275             {
276               BUS_SET_OOM (&error);
277               goto out;
278             }
279         }
280     }
281   
282  out:
283   if (dbus_error_is_set (&error))
284     {
285       if (!dbus_connection_get_is_connected (connection))
286         {
287           /* If we disconnected it, we won't bother to send it any error
288            * messages.
289            */
290         }
291       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
292         {
293           bus_connection_send_oom_error (connection, message);
294
295           /* cancel transaction due to OOM */
296           if (transaction != NULL)
297             {
298               bus_transaction_cancel_and_free (transaction);
299               transaction = NULL;
300             }
301         }
302       else
303         {
304           /* Try to send the real error, if no mem to do that, send
305            * the OOM error
306            */
307           _dbus_assert (transaction != NULL);
308           
309           if (!bus_transaction_send_error_reply (transaction, connection,
310                                                  &error, message))
311             {
312               bus_connection_send_oom_error (connection, message);
313
314               /* cancel transaction due to OOM */
315               if (transaction != NULL)
316                 {
317                   bus_transaction_cancel_and_free (transaction);
318                   transaction = NULL;
319                 }
320             }
321         }
322       
323       dbus_error_free (&error);
324     }
325
326   if (transaction != NULL)
327     {
328       bus_transaction_execute_and_free (transaction);
329     }
330
331   dbus_connection_unref (connection);
332 }
333
334 static DBusHandlerResult
335 bus_dispatch_message_handler (DBusMessageHandler *handler,
336                               DBusConnection     *connection,
337                               DBusMessage        *message,
338                               void               *user_data)
339 {
340   bus_dispatch (connection, message);
341   
342   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
343 }
344
345 static dbus_bool_t
346 message_handler_slot_ref (void)
347 {
348   if (message_handler_slot < 0)
349     {
350       message_handler_slot = dbus_connection_allocate_data_slot ();
351       
352       if (message_handler_slot < 0)
353         return FALSE;
354
355       _dbus_assert (message_handler_slot_refcount == 0);
356     }  
357
358   message_handler_slot_refcount += 1;
359
360   return TRUE;
361 }
362
363 static void
364 message_handler_slot_unref (void)
365 {
366   _dbus_assert (message_handler_slot_refcount > 0);
367
368   message_handler_slot_refcount -= 1;
369   
370   if (message_handler_slot_refcount == 0)
371     {
372       dbus_connection_free_data_slot (message_handler_slot);
373       message_handler_slot = -1;
374     }
375 }
376
377 static void
378 free_message_handler (void *data)
379 {
380   DBusMessageHandler *handler = data;
381   
382   _dbus_assert (message_handler_slot >= 0);
383   _dbus_assert (message_handler_slot_refcount > 0);
384   
385   dbus_message_handler_unref (handler);
386   message_handler_slot_unref ();
387 }
388
389 dbus_bool_t
390 bus_dispatch_add_connection (DBusConnection *connection)
391 {
392   DBusMessageHandler *handler;
393
394   if (!message_handler_slot_ref ())
395     return FALSE;
396   
397   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
398   if (handler == NULL)
399     {
400       message_handler_slot_unref ();
401       return FALSE;
402     }    
403   
404   if (!dbus_connection_add_filter (connection, handler))
405     {
406       dbus_message_handler_unref (handler);
407       message_handler_slot_unref ();
408       
409       return FALSE;
410     }
411
412   _dbus_assert (message_handler_slot >= 0);
413   _dbus_assert (message_handler_slot_refcount > 0);
414   
415   if (!dbus_connection_set_data (connection,
416                                  message_handler_slot,
417                                  handler,
418                                  free_message_handler))
419     {
420       dbus_message_handler_unref (handler);
421       message_handler_slot_unref ();
422
423       return FALSE;
424     }
425
426   return TRUE;
427 }
428
429 void
430 bus_dispatch_remove_connection (DBusConnection *connection)
431 {
432   /* Here we tell the bus driver that we want to get off. */
433   bus_driver_remove_connection (connection);
434
435   dbus_connection_set_data (connection,
436                             message_handler_slot,
437                             NULL, NULL);
438 }
439
440 #ifdef DBUS_BUILD_TESTS
441
442 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
443 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
444                                     DBusConnection *connection);
445
446 static dbus_bool_t check_no_leftovers (BusContext *context);
447
448 typedef struct
449 {
450   const char *expected_service_name;
451   dbus_bool_t failed;
452 } CheckServiceDeletedData;
453
454 static dbus_bool_t
455 check_service_deleted_foreach (DBusConnection *connection,
456                                void           *data)
457 {
458   CheckServiceDeletedData *d = data;
459   DBusMessage *message;
460   DBusError error;
461   char *service_name;
462
463   dbus_error_init (&error);
464   d->failed = TRUE;
465   service_name = NULL;
466   
467   message = dbus_connection_pop_message (connection);
468   if (message == NULL)
469     {
470       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
471                   connection, DBUS_MESSAGE_SERVICE_DELETED);
472       goto out;
473     }
474   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
475     {
476       _dbus_warn ("Received message %s on %p, expecting %s\n",
477                   dbus_message_get_name (message),
478                   connection, DBUS_MESSAGE_SERVICE_DELETED);
479       goto out;
480     }
481   else
482     {
483       if (!dbus_message_get_args (message, &error,
484                                   DBUS_TYPE_STRING, &service_name,
485                                   DBUS_TYPE_INVALID))
486         {
487           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
488             {
489               _dbus_verbose ("no memory to get service name arg\n");
490             }
491           else
492             {
493               _dbus_assert (dbus_error_is_set (&error));
494               _dbus_warn ("Did not get the expected single string argument\n");
495               goto out;
496             }
497         }
498       else if (strcmp (service_name, d->expected_service_name) != 0)
499         {
500           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
501                       d->expected_service_name,
502                       service_name);
503           goto out;
504         }
505     }
506
507   d->failed = FALSE;
508   
509  out:
510   dbus_free (service_name);
511   dbus_error_free (&error);
512   
513   if (message)
514     dbus_message_unref (message);
515
516   return !d->failed;
517 }
518
519 static void
520 kill_client_connection (BusContext     *context,
521                         DBusConnection *connection)
522 {
523   char *base_service;
524   const char *s;
525   CheckServiceDeletedData csdd;
526
527   _dbus_verbose ("killing connection %p\n", connection);
528   
529   s = dbus_bus_get_base_service (connection);
530   _dbus_assert (s != NULL);
531
532   while ((base_service = _dbus_strdup (s)) == NULL)
533     bus_wait_for_memory ();
534
535   dbus_connection_ref (connection);
536   
537   /* kick in the disconnect handler that unrefs the connection */
538   dbus_connection_disconnect (connection);
539
540   bus_test_flush_bus (context);
541
542   _dbus_assert (bus_test_client_listed (connection));
543   
544   /* Run disconnect handler in test.c */
545   if (bus_connection_dispatch_one_message (connection))
546     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
547   
548   _dbus_assert (!dbus_connection_get_is_connected (connection));
549   dbus_connection_unref (connection);
550   connection = NULL;
551   _dbus_assert (!bus_test_client_listed (connection));
552   
553   csdd.expected_service_name = base_service;
554   csdd.failed = FALSE;
555
556   bus_test_clients_foreach (check_service_deleted_foreach,
557                             &csdd);
558
559   dbus_free (base_service);
560   
561   if (csdd.failed)
562     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
563   
564   if (!check_no_leftovers (context))
565     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
566 }
567
568 static void
569 kill_client_connection_unchecked (DBusConnection *connection)
570 {
571   /* This kills the connection without expecting it to affect
572    * the rest of the bus.
573    */  
574   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
575
576   dbus_connection_ref (connection);
577   dbus_connection_disconnect (connection);
578   /* dispatching disconnect handler will unref once */
579   if (bus_connection_dispatch_one_message (connection))
580     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
581   dbus_connection_unref (connection);
582   _dbus_assert (!bus_test_client_listed (connection));
583 }
584
585 typedef struct
586 {
587   dbus_bool_t failed;
588 } CheckNoMessagesData;
589
590 static dbus_bool_t
591 check_no_messages_foreach (DBusConnection *connection,
592                            void           *data)
593 {
594   CheckNoMessagesData *d = data;
595   DBusMessage *message;
596
597   message = dbus_connection_pop_message (connection);
598   if (message != NULL)
599     {
600       _dbus_warn ("Received message %s on %p, expecting no messages\n",
601                   dbus_message_get_name (message), connection);
602       d->failed = TRUE;
603     }
604
605   if (message)
606     dbus_message_unref (message);
607   return !d->failed;
608 }
609
610 typedef struct
611 {
612   DBusConnection *skip_connection;
613   const char *expected_service_name;
614   dbus_bool_t failed;
615 } CheckServiceCreatedData;
616
617 static dbus_bool_t
618 check_service_created_foreach (DBusConnection *connection,
619                                void           *data)
620 {
621   CheckServiceCreatedData *d = data;
622   DBusMessage *message;
623   DBusError error;
624   char *service_name;
625
626   if (connection == d->skip_connection)
627     return TRUE;
628
629   dbus_error_init (&error);
630   d->failed = TRUE;
631   service_name = NULL;
632   
633   message = dbus_connection_pop_message (connection);
634   if (message == NULL)
635     {
636       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
637                   connection, DBUS_MESSAGE_SERVICE_CREATED);
638       goto out;
639     }
640   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
641     {
642       _dbus_warn ("Received message %s on %p, expecting %s\n",
643                   dbus_message_get_name (message),
644                   connection, DBUS_MESSAGE_SERVICE_CREATED);
645       goto out;
646     }
647   else
648     {
649       if (!dbus_message_get_args (message, &error,
650                                   DBUS_TYPE_STRING, &service_name,
651                                   DBUS_TYPE_INVALID))
652         {
653           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
654             {
655               _dbus_verbose ("no memory to get service name arg\n");
656             }
657           else
658             {
659               _dbus_assert (dbus_error_is_set (&error));
660               _dbus_warn ("Did not get the expected single string argument\n");
661               goto out;
662             }
663         }
664       else if (strcmp (service_name, d->expected_service_name) != 0)
665         {
666           _dbus_warn ("expected creation of service %s, got creation of %s\n",
667                       d->expected_service_name,
668                       service_name);
669           goto out;
670         }
671     }
672
673   d->failed = FALSE;
674   
675  out:
676   dbus_free (service_name);
677   dbus_error_free (&error);
678   
679   if (message)
680     dbus_message_unref (message);
681
682   return !d->failed;
683 }
684
685 static dbus_bool_t
686 check_no_leftovers (BusContext *context)
687 {
688   CheckNoMessagesData nmd;
689
690   nmd.failed = FALSE;
691   bus_test_clients_foreach (check_no_messages_foreach,
692                             &nmd);
693   
694   if (nmd.failed)
695     return FALSE;
696   else
697     return TRUE;
698 }
699
700 /* returns TRUE if the correct thing happens,
701  * but the correct thing may include OOM errors.
702  */
703 static dbus_bool_t
704 check_hello_message (BusContext     *context,
705                      DBusConnection *connection)
706 {
707   DBusMessage *message;
708   dbus_int32_t serial;
709   dbus_bool_t retval;
710   DBusError error;
711   char *name;
712   char *acquired;
713   
714   dbus_error_init (&error);
715   name = NULL;
716   acquired = NULL;
717   
718   message = dbus_message_new (DBUS_SERVICE_DBUS,
719                               DBUS_MESSAGE_HELLO);
720
721   if (message == NULL)
722     return TRUE;
723
724   if (!dbus_connection_send (connection, message, &serial))
725     {
726       dbus_message_unref (message);
727       return TRUE;
728     }
729
730   dbus_message_unref (message);
731   message = NULL;
732   
733   bus_test_flush_bus (context);
734
735   if (!dbus_connection_get_is_connected (connection))
736     {
737       _dbus_verbose ("connection was disconnected\n");
738       return TRUE;
739     }
740   
741   retval = FALSE;
742   
743   message = dbus_connection_pop_message (connection);
744   if (message == NULL)
745     {
746       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
747                   DBUS_MESSAGE_HELLO, serial, connection);
748       goto out;
749     }
750
751   _dbus_verbose ("Received %s on %p\n",
752                  dbus_message_get_name (message), connection);
753
754   if (dbus_message_get_is_error (message))
755     {
756       if (dbus_message_name_is (message,
757                                 DBUS_ERROR_NO_MEMORY))
758         {
759           ; /* good, this is a valid response */
760         }
761       else
762         {
763           _dbus_warn ("Did not expect error %s\n",
764                       dbus_message_get_name (message));
765           goto out;
766         }
767     }
768   else
769     {
770       CheckServiceCreatedData scd;
771       
772       if (dbus_message_name_is (message,
773                                 DBUS_MESSAGE_HELLO))
774         {
775           ; /* good, expected */
776         }
777       else
778         {
779           _dbus_warn ("Did not expect reply %s\n",
780                       dbus_message_get_name (message));
781           goto out;
782         }
783
784     retry_get_hello_name:
785       if (!dbus_message_get_args (message, &error,
786                                   DBUS_TYPE_STRING, &name,
787                                   DBUS_TYPE_INVALID))
788         {
789           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
790             {
791               _dbus_verbose ("no memory to get service name arg from hello\n");
792               dbus_error_free (&error);
793               bus_wait_for_memory ();
794               goto retry_get_hello_name;
795             }
796           else
797             {
798               _dbus_assert (dbus_error_is_set (&error));
799               _dbus_warn ("Did not get the expected single string argument to hello\n");
800               goto out;
801             }
802         }
803
804       _dbus_verbose ("Got hello name: %s\n", name);
805
806       while (!dbus_bus_set_base_service (connection, name))
807         bus_wait_for_memory ();
808       
809       scd.skip_connection = NULL;
810       scd.failed = FALSE;
811       scd.expected_service_name = name;
812       bus_test_clients_foreach (check_service_created_foreach,
813                                 &scd);
814       
815       if (scd.failed)
816         goto out;
817       
818       /* Client should also have gotten ServiceAcquired */
819       dbus_message_unref (message);
820       message = dbus_connection_pop_message (connection);
821       if (message == NULL)
822         {
823           _dbus_warn ("Expecting %s, got nothing\n",
824                       DBUS_MESSAGE_SERVICE_ACQUIRED);
825           goto out;
826         }
827       
828     retry_get_acquired_name:
829       if (!dbus_message_get_args (message, &error,
830                                   DBUS_TYPE_STRING, &acquired,
831                                   DBUS_TYPE_INVALID))
832         {
833           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
834             {
835               _dbus_verbose ("no memory to get service name arg from acquired\n");
836               dbus_error_free (&error);
837               bus_wait_for_memory ();
838               goto retry_get_acquired_name;
839             }
840           else
841             {
842               _dbus_assert (dbus_error_is_set (&error));
843               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
844               goto out;
845             }
846         }
847
848       _dbus_verbose ("Got acquired name: %s\n", acquired);
849
850       if (strcmp (acquired, name) != 0)
851         {
852           _dbus_warn ("Acquired name is %s but expected %s\n",
853                       acquired, name);
854           goto out;
855         }
856     }
857
858   if (!check_no_leftovers (context))
859     goto out;
860   
861   retval = TRUE;
862   
863  out:
864   dbus_error_free (&error);
865   
866   dbus_free (name);
867   dbus_free (acquired);
868   
869   if (message)
870     dbus_message_unref (message);
871   
872   return retval;
873 }
874
875 /* returns TRUE if the correct thing happens,
876  * but the correct thing may include OOM errors.
877  */
878 static dbus_bool_t
879 check_hello_connection (BusContext *context)
880 {
881   DBusConnection *connection;
882   DBusError error;
883
884   dbus_error_init (&error);
885
886   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
887   if (connection == NULL)
888     {
889       _DBUS_ASSERT_ERROR_IS_SET (&error);
890       dbus_error_free (&error);
891       return TRUE;
892     }
893
894   if (!bus_setup_debug_client (connection))
895     {
896       dbus_connection_disconnect (connection);
897       dbus_connection_unref (connection);
898       return TRUE;
899     }
900
901   if (!check_hello_message (context, connection))
902     return FALSE;
903
904   if (dbus_bus_get_base_service (connection) == NULL)
905     {
906       /* We didn't successfully register, so we can't
907        * do the usual kill_client_connection() checks
908        */
909       kill_client_connection_unchecked (connection);
910     }
911   else
912     {
913       kill_client_connection (context, connection);
914     }
915
916   return TRUE;
917 }
918
919 typedef struct
920 {
921   Check1Func func;
922   BusContext *context;
923 } Check1Data;
924
925 static dbus_bool_t
926 check_oom_check1_func (void *data)
927 {
928   Check1Data *d = data;
929
930   if (! (* d->func) (d->context))
931     return FALSE;
932   
933   if (!check_no_leftovers (d->context))
934     {
935       _dbus_warn ("Messages were left over, should be covered by test suite");
936       return FALSE;
937     }
938
939   return TRUE;
940 }
941
942 static void
943 check1_try_iterations (BusContext *context,
944                        const char *description,
945                        Check1Func  func)
946 {
947   Check1Data d;
948
949   d.func = func;
950   d.context = context;
951
952   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
953                                 &d))
954     _dbus_assert_not_reached ("test failed");
955 }
956
957 dbus_bool_t
958 bus_dispatch_test (const DBusString *test_data_dir)
959 {
960   BusContext *context;
961   DBusConnection *foo;
962   DBusConnection *bar;
963   DBusConnection *baz;
964   DBusError error;
965   
966   context = bus_context_new_test (test_data_dir,
967                                   "valid-config-files/debug-allow-all.conf");
968   if (context == NULL)
969     return FALSE;
970
971   dbus_error_init (&error);
972   
973   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
974   if (foo == NULL)
975     _dbus_assert_not_reached ("could not alloc connection");
976
977   if (!bus_setup_debug_client (foo))
978     _dbus_assert_not_reached ("could not set up connection");
979
980   if (!check_hello_message (context, foo))
981     _dbus_assert_not_reached ("hello message failed");
982   
983   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
984   if (bar == NULL)
985     _dbus_assert_not_reached ("could not alloc connection");
986
987   if (!bus_setup_debug_client (bar))
988     _dbus_assert_not_reached ("could not set up connection");
989
990   if (!check_hello_message (context, bar))
991     _dbus_assert_not_reached ("hello message failed");
992   
993   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
994   if (baz == NULL)
995     _dbus_assert_not_reached ("could not alloc connection");
996
997   if (!bus_setup_debug_client (baz))
998     _dbus_assert_not_reached ("could not set up connection");
999
1000   if (!check_hello_message (context, baz))
1001     _dbus_assert_not_reached ("hello message failed");
1002
1003   check1_try_iterations (context, "create_and_hello",
1004                          check_hello_connection);
1005   
1006   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1007
1008   kill_client_connection_unchecked (foo);
1009   kill_client_connection_unchecked (bar);
1010   kill_client_connection_unchecked (baz);
1011
1012   bus_context_unref (context);
1013   
1014   return TRUE;
1015 }
1016 #endif /* DBUS_BUILD_TESTS */