2003-04-06 Havoc Pennington <hp@pobox.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 (!dbus_message_set_sender (error_reply, DBUS_SERVICE_DBUS))
142     {
143       dbus_message_unref (error_reply);
144       BUS_SET_OOM (error);
145       return FALSE;
146     }      
147   
148   if (!bus_transaction_send_message (transaction, connection, error_reply))
149     {
150       dbus_message_unref (error_reply);
151       BUS_SET_OOM (error);
152       return FALSE;
153     }
154               
155   dbus_message_unref (error_reply);
156
157   return TRUE;
158 }
159
160 static void
161 bus_dispatch (DBusConnection *connection,
162               DBusMessage    *message)
163 {
164   const char *sender, *service_name, *message_name;
165   DBusError error;
166   BusTransaction *transaction;
167   BusContext *context;
168   
169   transaction = NULL;
170   dbus_error_init (&error);
171   
172   context = bus_connection_get_context (connection);
173   _dbus_assert (context != NULL);
174   
175   /* If we can't even allocate an OOM error, we just go to sleep
176    * until we can.
177    */
178   while (!bus_connection_preallocate_oom_error (connection))
179     bus_wait_for_memory ();
180   
181   /* Ref connection in case we disconnect it at some point in here */
182   dbus_connection_ref (connection);
183
184   service_name = dbus_message_get_service (message);
185   message_name = dbus_message_get_name (message);
186
187   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
188
189   _dbus_verbose ("DISPATCH: %s to %s\n",
190                  message_name, service_name ? service_name : "peer");
191   
192   /* If service_name is NULL, this is a message to the bus daemon, not intended
193    * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these
194    * immediately, especially disconnection messages.
195    */
196   if (service_name == NULL)
197     {      
198       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
199         bus_connection_disconnected (connection);
200
201       /* DBusConnection also handles some of these automatically, we leave
202        * it to do so.
203        */
204       goto out;
205     }
206
207   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
208   
209   /* Create our transaction */
210   transaction = bus_transaction_new (context);
211   if (transaction == NULL)
212     {
213       BUS_SET_OOM (&error);
214       goto out;
215     }
216   
217   /* Assign a sender to the message */
218   if (bus_connection_is_active (connection))
219     {
220       sender = bus_connection_get_name (connection);
221       _dbus_assert (sender != NULL);
222
223       if (!dbus_message_set_sender (message, sender))
224         {
225           BUS_SET_OOM (&error);
226           goto out;
227         }
228
229       /* We need to refetch the service name here, because
230        * dbus_message_set_sender can cause the header to be
231        * reallocated, and thus the service_name pointer will become
232        * invalid.
233        */
234       service_name = dbus_message_get_service (message);
235     }
236
237   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
238     {
239       if (!bus_driver_handle_message (connection, transaction, message, &error))
240         goto out;
241     }
242   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
243     {
244       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
245       dbus_connection_disconnect (connection);
246     }
247   /* FIXME what if we un-special-case this service and just have a flag
248    * on services that all service owners will get messages to it, not just
249    * the primary owner.
250    */
251   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
252     {
253       if (!bus_dispatch_broadcast_message (transaction, message, &error))
254         goto out;
255     }
256   else  /* route to named service */
257     {
258       DBusString service_string;
259       BusService *service;
260       BusRegistry *registry;
261
262       registry = bus_connection_get_registry (connection);
263       
264       _dbus_string_init_const (&service_string, service_name);
265       service = bus_registry_lookup (registry, &service_string);
266
267       if (service == NULL)
268         {
269           if (!send_service_nonexistent_error (transaction, connection,
270                                                service_name,
271                                                message, &error))
272             goto out;
273         }
274       else
275         {
276           _dbus_assert (bus_service_get_primary_owner (service) != NULL);
277       
278           /* Dispatch the message */
279           if (!bus_transaction_send_message (transaction,
280                                              bus_service_get_primary_owner (service),
281                                              message))
282             {
283               BUS_SET_OOM (&error);
284               goto out;
285             }
286         }
287     }
288   
289  out:
290   if (dbus_error_is_set (&error))
291     {
292       if (!dbus_connection_get_is_connected (connection))
293         {
294           /* If we disconnected it, we won't bother to send it any error
295            * messages.
296            */
297         }
298       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
299         {
300           bus_connection_send_oom_error (connection, message);
301
302           /* cancel transaction due to OOM */
303           if (transaction != NULL)
304             {
305               bus_transaction_cancel_and_free (transaction);
306               transaction = NULL;
307             }
308         }
309       else
310         {
311           /* Try to send the real error, if no mem to do that, send
312            * the OOM error
313            */
314           _dbus_assert (transaction != NULL);
315           
316           if (!bus_transaction_send_error_reply (transaction, connection,
317                                                  &error, message))
318             {
319               bus_connection_send_oom_error (connection, message);
320
321               /* cancel transaction due to OOM */
322               if (transaction != NULL)
323                 {
324                   bus_transaction_cancel_and_free (transaction);
325                   transaction = NULL;
326                 }
327             }
328         }
329       
330       dbus_error_free (&error);
331     }
332
333   if (transaction != NULL)
334     {
335       bus_transaction_execute_and_free (transaction);
336     }
337
338   dbus_connection_unref (connection);
339 }
340
341 static DBusHandlerResult
342 bus_dispatch_message_handler (DBusMessageHandler *handler,
343                               DBusConnection     *connection,
344                               DBusMessage        *message,
345                               void               *user_data)
346 {
347   bus_dispatch (connection, message);
348   
349   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
350 }
351
352 static dbus_bool_t
353 message_handler_slot_ref (void)
354 {
355   if (message_handler_slot < 0)
356     {
357       message_handler_slot = dbus_connection_allocate_data_slot ();
358       
359       if (message_handler_slot < 0)
360         return FALSE;
361
362       _dbus_assert (message_handler_slot_refcount == 0);
363     }  
364
365   message_handler_slot_refcount += 1;
366
367   return TRUE;
368 }
369
370 static void
371 message_handler_slot_unref (void)
372 {
373   _dbus_assert (message_handler_slot_refcount > 0);
374
375   message_handler_slot_refcount -= 1;
376   
377   if (message_handler_slot_refcount == 0)
378     {
379       dbus_connection_free_data_slot (message_handler_slot);
380       message_handler_slot = -1;
381     }
382 }
383
384 static void
385 free_message_handler (void *data)
386 {
387   DBusMessageHandler *handler = data;
388   
389   _dbus_assert (message_handler_slot >= 0);
390   _dbus_assert (message_handler_slot_refcount > 0);
391   
392   dbus_message_handler_unref (handler);
393   message_handler_slot_unref ();
394 }
395
396 dbus_bool_t
397 bus_dispatch_add_connection (DBusConnection *connection)
398 {
399   DBusMessageHandler *handler;
400
401   if (!message_handler_slot_ref ())
402     return FALSE;
403   
404   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
405   if (handler == NULL)
406     {
407       message_handler_slot_unref ();
408       return FALSE;
409     }    
410   
411   if (!dbus_connection_add_filter (connection, handler))
412     {
413       dbus_message_handler_unref (handler);
414       message_handler_slot_unref ();
415       
416       return FALSE;
417     }
418
419   _dbus_assert (message_handler_slot >= 0);
420   _dbus_assert (message_handler_slot_refcount > 0);
421   
422   if (!dbus_connection_set_data (connection,
423                                  message_handler_slot,
424                                  handler,
425                                  free_message_handler))
426     {
427       dbus_message_handler_unref (handler);
428       message_handler_slot_unref ();
429
430       return FALSE;
431     }
432
433   return TRUE;
434 }
435
436 void
437 bus_dispatch_remove_connection (DBusConnection *connection)
438 {
439   /* Here we tell the bus driver that we want to get off. */
440   bus_driver_remove_connection (connection);
441
442   dbus_connection_set_data (connection,
443                             message_handler_slot,
444                             NULL, NULL);
445 }
446
447 #ifdef DBUS_BUILD_TESTS
448
449 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
450 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
451                                     DBusConnection *connection);
452
453 static dbus_bool_t check_no_leftovers (BusContext *context);
454
455 typedef struct
456 {
457   const char *expected_service_name;
458   dbus_bool_t failed;
459 } CheckServiceDeletedData;
460
461 static dbus_bool_t
462 check_service_deleted_foreach (DBusConnection *connection,
463                                void           *data)
464 {
465   CheckServiceDeletedData *d = data;
466   DBusMessage *message;
467   DBusError error;
468   char *service_name;
469
470   dbus_error_init (&error);
471   d->failed = TRUE;
472   service_name = NULL;
473   
474   message = dbus_connection_pop_message (connection);
475   if (message == NULL)
476     {
477       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
478                   connection, DBUS_MESSAGE_SERVICE_DELETED);
479       goto out;
480     }
481   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
482     {
483       _dbus_warn ("Received message %s on %p, expecting %s\n",
484                   dbus_message_get_name (message),
485                   connection, DBUS_MESSAGE_SERVICE_DELETED);
486       goto out;
487     }
488   else
489     {
490       if (!dbus_message_get_args (message, &error,
491                                   DBUS_TYPE_STRING, &service_name,
492                                   DBUS_TYPE_INVALID))
493         {
494           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
495             {
496               _dbus_verbose ("no memory to get service name arg\n");
497             }
498           else
499             {
500               _dbus_assert (dbus_error_is_set (&error));
501               _dbus_warn ("Did not get the expected single string argument\n");
502               goto out;
503             }
504         }
505       else if (strcmp (service_name, d->expected_service_name) != 0)
506         {
507           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
508                       d->expected_service_name,
509                       service_name);
510           goto out;
511         }
512     }
513
514   d->failed = FALSE;
515   
516  out:
517   dbus_free (service_name);
518   dbus_error_free (&error);
519   
520   if (message)
521     dbus_message_unref (message);
522
523   return !d->failed;
524 }
525
526 static void
527 kill_client_connection (BusContext     *context,
528                         DBusConnection *connection)
529 {
530   char *base_service;
531   const char *s;
532   CheckServiceDeletedData csdd;
533
534   _dbus_verbose ("killing connection %p\n", connection);
535   
536   s = dbus_bus_get_base_service (connection);
537   _dbus_assert (s != NULL);
538
539   while ((base_service = _dbus_strdup (s)) == NULL)
540     bus_wait_for_memory ();
541
542   dbus_connection_ref (connection);
543   
544   /* kick in the disconnect handler that unrefs the connection */
545   dbus_connection_disconnect (connection);
546
547   bus_test_run_everything (context);
548   
549   _dbus_assert (bus_test_client_listed (connection));
550   
551   /* Run disconnect handler in test.c */
552   if (bus_connection_dispatch_one_message (connection))
553     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
554   
555   _dbus_assert (!dbus_connection_get_is_connected (connection));
556   dbus_connection_unref (connection);
557   connection = NULL;
558   _dbus_assert (!bus_test_client_listed (connection));
559   
560   csdd.expected_service_name = base_service;
561   csdd.failed = FALSE;
562
563   bus_test_clients_foreach (check_service_deleted_foreach,
564                             &csdd);
565
566   dbus_free (base_service);
567   
568   if (csdd.failed)
569     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
570   
571   if (!check_no_leftovers (context))
572     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
573 }
574
575 static void
576 kill_client_connection_unchecked (DBusConnection *connection)
577 {
578   /* This kills the connection without expecting it to affect
579    * the rest of the bus.
580    */  
581   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
582
583   dbus_connection_ref (connection);
584   dbus_connection_disconnect (connection);
585   /* dispatching disconnect handler will unref once */
586   if (bus_connection_dispatch_one_message (connection))
587     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
588   dbus_connection_unref (connection);
589   _dbus_assert (!bus_test_client_listed (connection));
590 }
591
592 typedef struct
593 {
594   dbus_bool_t failed;
595 } CheckNoMessagesData;
596
597 static dbus_bool_t
598 check_no_messages_foreach (DBusConnection *connection,
599                            void           *data)
600 {
601   CheckNoMessagesData *d = data;
602   DBusMessage *message;
603
604   message = dbus_connection_pop_message (connection);
605   if (message != NULL)
606     {
607       _dbus_warn ("Received message %s on %p, expecting no messages\n",
608                   dbus_message_get_name (message), connection);
609       d->failed = TRUE;
610     }
611
612   if (message)
613     dbus_message_unref (message);
614   return !d->failed;
615 }
616
617 typedef struct
618 {
619   DBusConnection *skip_connection;
620   const char *expected_service_name;
621   dbus_bool_t failed;
622 } CheckServiceCreatedData;
623
624 static dbus_bool_t
625 check_service_created_foreach (DBusConnection *connection,
626                                void           *data)
627 {
628   CheckServiceCreatedData *d = data;
629   DBusMessage *message;
630   DBusError error;
631   char *service_name;
632
633   if (connection == d->skip_connection)
634     return TRUE;
635
636   dbus_error_init (&error);
637   d->failed = TRUE;
638   service_name = NULL;
639   
640   message = dbus_connection_pop_message (connection);
641   if (message == NULL)
642     {
643       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
644                   connection, DBUS_MESSAGE_SERVICE_CREATED);
645       goto out;
646     }
647   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
648     {
649       _dbus_warn ("Received message %s on %p, expecting %s\n",
650                   dbus_message_get_name (message),
651                   connection, DBUS_MESSAGE_SERVICE_CREATED);
652       goto out;
653     }
654   else
655     {
656       if (!dbus_message_get_args (message, &error,
657                                   DBUS_TYPE_STRING, &service_name,
658                                   DBUS_TYPE_INVALID))
659         {
660           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
661             {
662               _dbus_verbose ("no memory to get service name arg\n");
663             }
664           else
665             {
666               _dbus_assert (dbus_error_is_set (&error));
667               _dbus_warn ("Did not get the expected single string argument\n");
668               goto out;
669             }
670         }
671       else if (strcmp (service_name, d->expected_service_name) != 0)
672         {
673           _dbus_warn ("expected creation of service %s, got creation of %s\n",
674                       d->expected_service_name,
675                       service_name);
676           goto out;
677         }
678     }
679
680   d->failed = FALSE;
681   
682  out:
683   dbus_free (service_name);
684   dbus_error_free (&error);
685   
686   if (message)
687     dbus_message_unref (message);
688
689   return !d->failed;
690 }
691
692 static dbus_bool_t
693 check_no_leftovers (BusContext *context)
694 {
695   CheckNoMessagesData nmd;
696
697   nmd.failed = FALSE;
698   bus_test_clients_foreach (check_no_messages_foreach,
699                             &nmd);
700   
701   if (nmd.failed)
702     return FALSE;
703   else
704     return TRUE;
705 }
706
707 /* returns TRUE if the correct thing happens,
708  * but the correct thing may include OOM errors.
709  */
710 static dbus_bool_t
711 check_hello_message (BusContext     *context,
712                      DBusConnection *connection)
713 {
714   DBusMessage *message;
715   dbus_int32_t serial;
716   dbus_bool_t retval;
717   DBusError error;
718   char *name;
719   char *acquired;
720   
721   dbus_error_init (&error);
722   name = NULL;
723   acquired = NULL;
724   
725   message = dbus_message_new (DBUS_SERVICE_DBUS,
726                               DBUS_MESSAGE_HELLO);
727
728   if (message == NULL)
729     return TRUE;
730
731   if (!dbus_connection_send (connection, message, &serial))
732     {
733       dbus_message_unref (message);
734       return TRUE;
735     }
736
737   dbus_message_unref (message);
738   message = NULL;
739
740   bus_test_run_everything (context);
741
742   if (!dbus_connection_get_is_connected (connection))
743     {
744       _dbus_verbose ("connection was disconnected\n");
745       return TRUE;
746     }
747   
748   retval = FALSE;
749   
750   message = dbus_connection_pop_message (connection);
751   if (message == NULL)
752     {
753       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
754                   DBUS_MESSAGE_HELLO, serial, connection);
755       goto out;
756     }
757
758   _dbus_verbose ("Received %s on %p\n",
759                  dbus_message_get_name (message), connection);
760
761   if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
762     {
763       _dbus_warn ("Message has wrong sender %s\n",
764                   dbus_message_get_sender (message) ?
765                   dbus_message_get_sender (message) : "(none)");
766       goto out;
767     }
768   
769   if (dbus_message_get_is_error (message))
770     {
771       if (dbus_message_name_is (message,
772                                 DBUS_ERROR_NO_MEMORY))
773         {
774           ; /* good, this is a valid response */
775         }
776       else
777         {
778           _dbus_warn ("Did not expect error %s\n",
779                       dbus_message_get_name (message));
780           goto out;
781         }
782     }
783   else
784     {
785       CheckServiceCreatedData scd;
786       
787       if (dbus_message_name_is (message,
788                                 DBUS_MESSAGE_HELLO))
789         {
790           ; /* good, expected */
791         }
792       else
793         {
794           _dbus_warn ("Did not expect reply %s\n",
795                       dbus_message_get_name (message));
796           goto out;
797         }
798
799     retry_get_hello_name:
800       if (!dbus_message_get_args (message, &error,
801                                   DBUS_TYPE_STRING, &name,
802                                   DBUS_TYPE_INVALID))
803         {
804           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
805             {
806               _dbus_verbose ("no memory to get service name arg from hello\n");
807               dbus_error_free (&error);
808               bus_wait_for_memory ();
809               goto retry_get_hello_name;
810             }
811           else
812             {
813               _dbus_assert (dbus_error_is_set (&error));
814               _dbus_warn ("Did not get the expected single string argument to hello\n");
815               goto out;
816             }
817         }
818
819       _dbus_verbose ("Got hello name: %s\n", name);
820
821       while (!dbus_bus_set_base_service (connection, name))
822         bus_wait_for_memory ();
823       
824       scd.skip_connection = NULL;
825       scd.failed = FALSE;
826       scd.expected_service_name = name;
827       bus_test_clients_foreach (check_service_created_foreach,
828                                 &scd);
829       
830       if (scd.failed)
831         goto out;
832       
833       /* Client should also have gotten ServiceAcquired */
834       dbus_message_unref (message);
835       message = dbus_connection_pop_message (connection);
836       if (message == NULL)
837         {
838           _dbus_warn ("Expecting %s, got nothing\n",
839                       DBUS_MESSAGE_SERVICE_ACQUIRED);
840           goto out;
841         }
842       
843     retry_get_acquired_name:
844       if (!dbus_message_get_args (message, &error,
845                                   DBUS_TYPE_STRING, &acquired,
846                                   DBUS_TYPE_INVALID))
847         {
848           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
849             {
850               _dbus_verbose ("no memory to get service name arg from acquired\n");
851               dbus_error_free (&error);
852               bus_wait_for_memory ();
853               goto retry_get_acquired_name;
854             }
855           else
856             {
857               _dbus_assert (dbus_error_is_set (&error));
858               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
859               goto out;
860             }
861         }
862
863       _dbus_verbose ("Got acquired name: %s\n", acquired);
864
865       if (strcmp (acquired, name) != 0)
866         {
867           _dbus_warn ("Acquired name is %s but expected %s\n",
868                       acquired, name);
869           goto out;
870         }
871     }
872
873   if (!check_no_leftovers (context))
874     goto out;
875   
876   retval = TRUE;
877   
878  out:
879   dbus_error_free (&error);
880   
881   dbus_free (name);
882   dbus_free (acquired);
883   
884   if (message)
885     dbus_message_unref (message);
886   
887   return retval;
888 }
889
890 /* returns TRUE if the correct thing happens,
891  * but the correct thing may include OOM errors.
892  */
893 static dbus_bool_t
894 check_hello_connection (BusContext *context)
895 {
896   DBusConnection *connection;
897   DBusError error;
898
899   dbus_error_init (&error);
900
901   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
902   if (connection == NULL)
903     {
904       _DBUS_ASSERT_ERROR_IS_SET (&error);
905       dbus_error_free (&error);
906       return TRUE;
907     }
908
909   if (!bus_setup_debug_client (connection))
910     {
911       dbus_connection_disconnect (connection);
912       dbus_connection_unref (connection);
913       return TRUE;
914     }
915
916   if (!check_hello_message (context, connection))
917     return FALSE;
918
919   if (dbus_bus_get_base_service (connection) == NULL)
920     {
921       /* We didn't successfully register, so we can't
922        * do the usual kill_client_connection() checks
923        */
924       kill_client_connection_unchecked (connection);
925     }
926   else
927     {
928       kill_client_connection (context, connection);
929     }
930
931   return TRUE;
932 }
933
934 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
935
936 /* returns TRUE if the correct thing happens,
937  * but the correct thing may include OOM errors.
938  */
939 static dbus_bool_t
940 check_nonexistent_service_activation (BusContext     *context,
941                                       DBusConnection *connection)
942 {
943   DBusMessage *message;
944   dbus_int32_t serial;
945   dbus_bool_t retval;
946   DBusError error;
947   
948   dbus_error_init (&error);
949   
950   message = dbus_message_new (DBUS_SERVICE_DBUS,
951                               DBUS_MESSAGE_ACTIVATE_SERVICE);
952
953   if (message == NULL)
954     return TRUE;
955
956   if (!dbus_message_append_args (message,
957                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
958                                  DBUS_TYPE_UINT32, 0,
959                                  DBUS_TYPE_INVALID))
960     {
961       dbus_message_unref (message);
962       return TRUE;
963     }
964   
965   if (!dbus_connection_send (connection, message, &serial))
966     {
967       dbus_message_unref (message);
968       return TRUE;
969     }
970
971   dbus_message_unref (message);
972   message = NULL;
973
974   bus_test_run_everything (context);
975
976   if (!dbus_connection_get_is_connected (connection))
977     {
978       _dbus_verbose ("connection was disconnected\n");
979       return TRUE;
980     }
981   
982   retval = FALSE;
983   
984   message = dbus_connection_pop_message (connection);
985   if (message == NULL)
986     {
987       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
988                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
989       goto out;
990     }
991
992   _dbus_verbose ("Received %s on %p\n",
993                  dbus_message_get_name (message), connection);
994
995   if (dbus_message_get_is_error (message))
996     {
997       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
998         {
999           _dbus_warn ("Message has wrong sender %s\n",
1000                       dbus_message_get_sender (message) ?
1001                       dbus_message_get_sender (message) : "(none)");
1002           goto out;
1003         }
1004       
1005       if (dbus_message_name_is (message,
1006                                 DBUS_ERROR_NO_MEMORY))
1007         {
1008           ; /* good, this is a valid response */
1009         }
1010       else if (dbus_message_name_is (message,
1011                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1012         {
1013           ; /* good, this is expected also */
1014         }
1015       else
1016         {
1017           _dbus_warn ("Did not expect error %s\n",
1018                       dbus_message_get_name (message));
1019           goto out;
1020         }
1021     }
1022   else
1023     {
1024       _dbus_warn ("Did not expect to successfully activate %s\n",
1025                   NONEXISTENT_SERVICE_NAME);
1026       goto out;
1027     }
1028
1029   retval = TRUE;
1030   
1031  out:
1032   if (message)
1033     dbus_message_unref (message);
1034   
1035   return retval;
1036 }
1037
1038 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1039
1040 /* returns TRUE if the correct thing happens,
1041  * but the correct thing may include OOM errors.
1042  */
1043 static dbus_bool_t
1044 check_existent_service_activation (BusContext     *context,
1045                                    DBusConnection *connection)
1046 {
1047   DBusMessage *message;
1048   dbus_int32_t serial;
1049   dbus_bool_t retval;
1050   DBusError error;
1051   
1052   dbus_error_init (&error);
1053   
1054   message = dbus_message_new (DBUS_SERVICE_DBUS,
1055                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1056
1057   if (message == NULL)
1058     return TRUE;
1059
1060   if (!dbus_message_append_args (message,
1061                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
1062                                  DBUS_TYPE_UINT32, 0,
1063                                  DBUS_TYPE_INVALID))
1064     {
1065       dbus_message_unref (message);
1066       return TRUE;
1067     }
1068   
1069   if (!dbus_connection_send (connection, message, &serial))
1070     {
1071       dbus_message_unref (message);
1072       return TRUE;
1073     }
1074
1075   dbus_message_unref (message);
1076   message = NULL;
1077
1078   bus_test_run_everything (context);
1079
1080   if (dbus_connection_get_dispatch_status (connection) ==
1081       DBUS_DISPATCH_COMPLETE)
1082     /* now wait for the message bus to hear back from the activated service */
1083     bus_test_run_bus_loop (context);
1084   
1085   /* and process everything again */
1086   bus_test_run_everything (context);
1087
1088   if (!dbus_connection_get_is_connected (connection))
1089     {
1090       _dbus_verbose ("connection was disconnected\n");
1091       return TRUE;
1092     }
1093   
1094   retval = FALSE;
1095   
1096   message = dbus_connection_pop_message (connection);
1097   if (message == NULL)
1098     {
1099       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1100                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1101       goto out;
1102     }
1103
1104   _dbus_verbose ("Received %s on %p\n",
1105                  dbus_message_get_name (message), connection);
1106
1107   if (dbus_message_get_is_error (message))
1108     {
1109       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1110         {
1111           _dbus_warn ("Message has wrong sender %s\n",
1112                       dbus_message_get_sender (message) ?
1113                       dbus_message_get_sender (message) : "(none)");
1114           goto out;
1115         }
1116       
1117       if (dbus_message_name_is (message,
1118                                 DBUS_ERROR_NO_MEMORY))
1119         {
1120           ; /* good, this is a valid response */
1121         }
1122       else if (dbus_message_name_is (message,
1123                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1124         {
1125           ; /* good, this is expected also */
1126         }
1127       else
1128         {
1129           _dbus_warn ("Did not expect error %s\n",
1130                       dbus_message_get_name (message));
1131           goto out;
1132         }
1133     }
1134   else
1135     {
1136       _dbus_warn ("Did not expect to successfully activate %s\n",
1137                   EXISTENT_SERVICE_NAME);
1138       goto out;
1139     }
1140
1141   retval = TRUE;
1142   
1143  out:
1144   if (message)
1145     dbus_message_unref (message);
1146   
1147   return retval;
1148 }
1149
1150 typedef struct
1151 {
1152   Check1Func func;
1153   BusContext *context;
1154 } Check1Data;
1155
1156 static dbus_bool_t
1157 check_oom_check1_func (void *data)
1158 {
1159   Check1Data *d = data;
1160
1161   if (! (* d->func) (d->context))
1162     return FALSE;
1163   
1164   if (!check_no_leftovers (d->context))
1165     {
1166       _dbus_warn ("Messages were left over, should be covered by test suite");
1167       return FALSE;
1168     }
1169
1170   return TRUE;
1171 }
1172
1173 static void
1174 check1_try_iterations (BusContext *context,
1175                        const char *description,
1176                        Check1Func  func)
1177 {
1178   Check1Data d;
1179
1180   d.func = func;
1181   d.context = context;
1182
1183   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
1184                                 &d))
1185     _dbus_assert_not_reached ("test failed");
1186 }
1187
1188 typedef struct
1189 {
1190   Check2Func func;
1191   BusContext *context;
1192   DBusConnection *connection;
1193 } Check2Data;
1194
1195 static dbus_bool_t
1196 check_oom_check2_func (void *data)
1197 {
1198   Check2Data *d = data;
1199
1200   if (! (* d->func) (d->context, d->connection))
1201     return FALSE;
1202   
1203   if (!check_no_leftovers (d->context))
1204     {
1205       _dbus_warn ("Messages were left over, should be covered by test suite");
1206       return FALSE;
1207     }
1208
1209   return TRUE;
1210 }
1211
1212 static void
1213 check2_try_iterations (BusContext     *context,
1214                        DBusConnection *connection,
1215                        const char     *description,
1216                        Check2Func      func)
1217 {
1218   Check2Data d;
1219
1220   d.func = func;
1221   d.context = context;
1222   d.connection = connection;
1223   
1224   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
1225                                 &d))
1226     _dbus_assert_not_reached ("test failed");
1227 }
1228
1229 dbus_bool_t
1230 bus_dispatch_test (const DBusString *test_data_dir)
1231 {
1232   BusContext *context;
1233   DBusConnection *foo;
1234   DBusConnection *bar;
1235   DBusConnection *baz;
1236   DBusError error;
1237   
1238   context = bus_context_new_test (test_data_dir,
1239                                   "valid-config-files/debug-allow-all.conf");
1240   if (context == NULL)
1241     return FALSE;
1242
1243   dbus_error_init (&error);
1244   
1245   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1246   if (foo == NULL)
1247     _dbus_assert_not_reached ("could not alloc connection");
1248
1249   if (!bus_setup_debug_client (foo))
1250     _dbus_assert_not_reached ("could not set up connection");
1251
1252   if (!check_hello_message (context, foo))
1253     _dbus_assert_not_reached ("hello message failed");
1254   
1255   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
1256   if (bar == NULL)
1257     _dbus_assert_not_reached ("could not alloc connection");
1258
1259   if (!bus_setup_debug_client (bar))
1260     _dbus_assert_not_reached ("could not set up connection");
1261
1262   if (!check_hello_message (context, bar))
1263     _dbus_assert_not_reached ("hello message failed");
1264   
1265   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
1266   if (baz == NULL)
1267     _dbus_assert_not_reached ("could not alloc connection");
1268
1269   if (!bus_setup_debug_client (baz))
1270     _dbus_assert_not_reached ("could not set up connection");
1271
1272   if (!check_hello_message (context, baz))
1273     _dbus_assert_not_reached ("hello message failed");
1274
1275 #if 0
1276   check2_try_iterations (context, foo, "existent_service_activation",
1277                          check_existent_service_activation);
1278 #endif
1279   
1280   check2_try_iterations (context, foo, "nonexistent_service_activation",
1281                          check_nonexistent_service_activation);
1282
1283   check1_try_iterations (context, "create_and_hello",
1284                          check_hello_connection);
1285   
1286   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1287
1288   kill_client_connection_unchecked (foo);
1289   kill_client_connection_unchecked (bar);
1290   kill_client_connection_unchecked (baz);
1291
1292   bus_context_unref (context);
1293   
1294   return TRUE;
1295 }
1296 #endif /* DBUS_BUILD_TESTS */