2003-04-10 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 <dbus/dbus-internals.h>
33 #include <string.h>
34
35 static int message_handler_slot = -1;
36 static int message_handler_slot_refcount;
37
38 typedef struct
39 {
40   DBusMessage    *message;
41   BusTransaction *transaction;
42   DBusError      *error;
43 } SendMessageData;
44
45 static dbus_bool_t
46 send_one_message (DBusConnection *connection, void *data)
47 {
48   SendMessageData *d = data;
49   
50   if (!bus_connection_is_active (connection))
51     return TRUE;
52
53   if (!bus_transaction_send_message (d->transaction,
54                                      connection,
55                                      d->message))
56     {
57       BUS_SET_OOM (d->error);
58       return FALSE;
59     }
60
61   return TRUE;
62 }
63
64 dbus_bool_t
65 bus_dispatch_broadcast_message (BusTransaction *transaction,
66                                 DBusMessage    *message,
67                                 DBusError      *error)
68 {
69   DBusError tmp_error;
70   SendMessageData d;
71   BusConnections *connections;
72
73   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
74   
75   _dbus_assert (dbus_message_get_sender (message) != NULL);
76
77   connections = bus_transaction_get_connections (transaction);
78   
79   dbus_error_init (&tmp_error);
80   d.message = message;
81   d.transaction = transaction;
82   d.error = &tmp_error;
83   
84   bus_connections_foreach (connections, send_one_message, &d);
85
86   if (dbus_error_is_set (&tmp_error))
87     {
88       dbus_move_error (&tmp_error, error);
89       return FALSE;
90     }
91   else
92     return TRUE;
93 }
94
95 static dbus_bool_t
96 send_service_nonexistent_error (BusTransaction *transaction,
97                                 DBusConnection *connection,
98                                 const char     *service_name,
99                                 DBusMessage    *in_reply_to,
100                                 DBusError      *error)
101 {
102   DBusMessage *error_reply;
103   DBusString error_message;
104   const char *error_str;
105
106   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
107   
108   /* Trying to send a message to a non-existant service,
109    * bounce back an error message.
110    */
111           
112   if (!_dbus_string_init (&error_message))
113     {
114       BUS_SET_OOM (error);
115       return FALSE;
116     }
117
118   if (!_dbus_string_append (&error_message, "Service \"") ||
119       !_dbus_string_append (&error_message, service_name) ||
120       !_dbus_string_append (&error_message, "\" does not exist"))
121     {
122       _dbus_string_free (&error_message);
123       BUS_SET_OOM (error);
124       return FALSE;
125     }
126               
127   error_str = _dbus_string_get_const_data (&error_message);
128   error_reply = dbus_message_new_error_reply (in_reply_to,
129                                               DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
130                                               error_str);
131
132   _dbus_string_free (&error_message);
133               
134   if (error_reply == NULL)
135     {
136       BUS_SET_OOM (error);
137       return FALSE;
138     }
139
140   if (!dbus_message_set_sender (error_reply, DBUS_SERVICE_DBUS))
141     {
142       dbus_message_unref (error_reply);
143       BUS_SET_OOM (error);
144       return FALSE;
145     }      
146   
147   if (!bus_transaction_send_message (transaction, connection, error_reply))
148     {
149       dbus_message_unref (error_reply);
150       BUS_SET_OOM (error);
151       return FALSE;
152     }
153               
154   dbus_message_unref (error_reply);
155
156   return TRUE;
157 }
158
159 static void
160 bus_dispatch (DBusConnection *connection,
161               DBusMessage    *message)
162 {
163   const char *sender, *service_name, *message_name;
164   DBusError error;
165   BusTransaction *transaction;
166   BusContext *context;
167   
168   transaction = NULL;
169   dbus_error_init (&error);
170   
171   context = bus_connection_get_context (connection);
172   _dbus_assert (context != NULL);
173   
174   /* If we can't even allocate an OOM error, we just go to sleep
175    * until we can.
176    */
177   while (!bus_connection_preallocate_oom_error (connection))
178     _dbus_wait_for_memory ();
179   
180   /* Ref connection in case we disconnect it at some point in here */
181   dbus_connection_ref (connection);
182
183   service_name = dbus_message_get_service (message);
184   message_name = dbus_message_get_name (message);
185
186   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
187
188   _dbus_verbose ("DISPATCH: %s to %s\n",
189                  message_name, service_name ? service_name : "peer");
190   
191   /* If service_name is NULL, this is a message to the bus daemon, not intended
192    * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these
193    * immediately, especially disconnection messages.
194    */
195   if (service_name == NULL)
196     {      
197       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
198         bus_connection_disconnected (connection);
199
200       /* DBusConnection also handles some of these automatically, we leave
201        * it to do so.
202        */
203       goto out;
204     }
205
206   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
207   
208   /* Create our transaction */
209   transaction = bus_transaction_new (context);
210   if (transaction == NULL)
211     {
212       BUS_SET_OOM (&error);
213       goto out;
214     }
215   
216   /* Assign a sender to the message */
217   if (bus_connection_is_active (connection))
218     {
219       sender = bus_connection_get_name (connection);
220       _dbus_assert (sender != NULL);
221
222       if (!dbus_message_set_sender (message, sender))
223         {
224           BUS_SET_OOM (&error);
225           goto out;
226         }
227
228       /* We need to refetch the service name here, because
229        * dbus_message_set_sender can cause the header to be
230        * reallocated, and thus the service_name pointer will become
231        * invalid.
232        */
233       service_name = dbus_message_get_service (message);
234     }
235
236   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
237     {
238       if (!bus_driver_handle_message (connection, transaction, message, &error))
239         goto out;
240     }
241   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
242     {
243       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
244       dbus_connection_disconnect (connection);
245     }
246   /* FIXME what if we un-special-case this service and just have a flag
247    * on services that all service owners will get messages to it, not just
248    * the primary owner.
249    */
250   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
251     {
252       if (!bus_dispatch_broadcast_message (transaction, message, &error))
253         goto out;
254     }
255   else  /* route to named service */
256     {
257       DBusString service_string;
258       BusService *service;
259       BusRegistry *registry;
260
261       registry = bus_connection_get_registry (connection);
262       
263       _dbus_string_init_const (&service_string, service_name);
264       service = bus_registry_lookup (registry, &service_string);
265
266       if (service == NULL)
267         {
268           if (!send_service_nonexistent_error (transaction, connection,
269                                                service_name,
270                                                message, &error))
271             goto out;
272         }
273       else
274         {
275           _dbus_assert (bus_service_get_primary_owner (service) != NULL);
276       
277           /* Dispatch the message */
278           if (!bus_transaction_send_message (transaction,
279                                              bus_service_get_primary_owner (service),
280                                              message))
281             {
282               BUS_SET_OOM (&error);
283               goto out;
284             }
285         }
286     }
287   
288  out:
289   if (dbus_error_is_set (&error))
290     {
291       if (!dbus_connection_get_is_connected (connection))
292         {
293           /* If we disconnected it, we won't bother to send it any error
294            * messages.
295            */
296         }
297       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
298         {
299           bus_connection_send_oom_error (connection, message);
300
301           /* cancel transaction due to OOM */
302           if (transaction != NULL)
303             {
304               bus_transaction_cancel_and_free (transaction);
305               transaction = NULL;
306             }
307         }
308       else
309         {
310           /* Try to send the real error, if no mem to do that, send
311            * the OOM error
312            */
313           _dbus_assert (transaction != NULL);
314           
315           if (!bus_transaction_send_error_reply (transaction, connection,
316                                                  &error, message))
317             {
318               bus_connection_send_oom_error (connection, message);
319
320               /* cancel transaction due to OOM */
321               if (transaction != NULL)
322                 {
323                   bus_transaction_cancel_and_free (transaction);
324                   transaction = NULL;
325                 }
326             }
327         }
328       
329       dbus_error_free (&error);
330     }
331
332   if (transaction != NULL)
333     {
334       bus_transaction_execute_and_free (transaction);
335     }
336
337   dbus_connection_unref (connection);
338 }
339
340 static DBusHandlerResult
341 bus_dispatch_message_handler (DBusMessageHandler *handler,
342                               DBusConnection     *connection,
343                               DBusMessage        *message,
344                               void               *user_data)
345 {
346   bus_dispatch (connection, message);
347   
348   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
349 }
350
351 static dbus_bool_t
352 message_handler_slot_ref (void)
353 {
354   if (message_handler_slot < 0)
355     {
356       message_handler_slot = dbus_connection_allocate_data_slot ();
357       
358       if (message_handler_slot < 0)
359         return FALSE;
360
361       _dbus_assert (message_handler_slot_refcount == 0);
362     }  
363
364   message_handler_slot_refcount += 1;
365
366   return TRUE;
367 }
368
369 static void
370 message_handler_slot_unref (void)
371 {
372   _dbus_assert (message_handler_slot_refcount > 0);
373
374   message_handler_slot_refcount -= 1;
375   
376   if (message_handler_slot_refcount == 0)
377     {
378       dbus_connection_free_data_slot (message_handler_slot);
379       message_handler_slot = -1;
380     }
381 }
382
383 static void
384 free_message_handler (void *data)
385 {
386   DBusMessageHandler *handler = data;
387   
388   _dbus_assert (message_handler_slot >= 0);
389   _dbus_assert (message_handler_slot_refcount > 0);
390   
391   dbus_message_handler_unref (handler);
392   message_handler_slot_unref ();
393 }
394
395 dbus_bool_t
396 bus_dispatch_add_connection (DBusConnection *connection)
397 {
398   DBusMessageHandler *handler;
399
400   if (!message_handler_slot_ref ())
401     return FALSE;
402   
403   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
404   if (handler == NULL)
405     {
406       message_handler_slot_unref ();
407       return FALSE;
408     }    
409   
410   if (!dbus_connection_add_filter (connection, handler))
411     {
412       dbus_message_handler_unref (handler);
413       message_handler_slot_unref ();
414       
415       return FALSE;
416     }
417
418   _dbus_assert (message_handler_slot >= 0);
419   _dbus_assert (message_handler_slot_refcount > 0);
420   
421   if (!dbus_connection_set_data (connection,
422                                  message_handler_slot,
423                                  handler,
424                                  free_message_handler))
425     {
426       dbus_message_handler_unref (handler);
427       message_handler_slot_unref ();
428
429       return FALSE;
430     }
431
432   return TRUE;
433 }
434
435 void
436 bus_dispatch_remove_connection (DBusConnection *connection)
437 {
438   /* Here we tell the bus driver that we want to get off. */
439   bus_driver_remove_connection (connection);
440
441   dbus_connection_set_data (connection,
442                             message_handler_slot,
443                             NULL, NULL);
444 }
445
446 #ifdef DBUS_BUILD_TESTS
447
448 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
449 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
450                                     DBusConnection *connection);
451
452 static dbus_bool_t check_no_leftovers (BusContext *context);
453
454 static void
455 block_connection_until_message_from_bus (BusContext     *context,
456                                          DBusConnection *connection)
457 {
458   while (dbus_connection_get_dispatch_status (connection) ==
459          DBUS_DISPATCH_COMPLETE &&
460          dbus_connection_get_is_connected (connection))
461     {
462       bus_test_run_bus_loop (context, TRUE);
463       bus_test_run_clients_loop (FALSE);
464     }
465 }
466
467 /* compensate for fact that pop_message() can return #NULL due to OOM */
468 static DBusMessage*
469 pop_message_waiting_for_memory (DBusConnection *connection)
470 {
471   while (dbus_connection_get_dispatch_status (connection) ==
472          DBUS_DISPATCH_NEED_MEMORY)
473     _dbus_wait_for_memory ();
474
475   return dbus_connection_pop_message (connection);
476 }
477
478 typedef struct
479 {
480   const char *expected_service_name;
481   dbus_bool_t failed;
482 } CheckServiceDeletedData;
483
484 static dbus_bool_t
485 check_service_deleted_foreach (DBusConnection *connection,
486                                void           *data)
487 {
488   CheckServiceDeletedData *d = data;
489   DBusMessage *message;
490   DBusError error;
491   char *service_name;
492
493   dbus_error_init (&error);
494   d->failed = TRUE;
495   service_name = NULL;
496   
497   message = pop_message_waiting_for_memory (connection);
498   if (message == NULL)
499     {
500       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
501                   connection, DBUS_MESSAGE_SERVICE_DELETED);
502       goto out;
503     }
504   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
505     {
506       _dbus_warn ("Received message %s on %p, expecting %s\n",
507                   dbus_message_get_name (message),
508                   connection, DBUS_MESSAGE_SERVICE_DELETED);
509       goto out;
510     }
511   else
512     {
513       if (!dbus_message_get_args (message, &error,
514                                   DBUS_TYPE_STRING, &service_name,
515                                   DBUS_TYPE_INVALID))
516         {
517           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
518             {
519               _dbus_verbose ("no memory to get service name arg\n");
520             }
521           else
522             {
523               _dbus_assert (dbus_error_is_set (&error));
524               _dbus_warn ("Did not get the expected single string argument\n");
525               goto out;
526             }
527         }
528       else if (strcmp (service_name, d->expected_service_name) != 0)
529         {
530           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
531                       d->expected_service_name,
532                       service_name);
533           goto out;
534         }
535     }
536
537   d->failed = FALSE;
538   
539  out:
540   dbus_free (service_name);
541   dbus_error_free (&error);
542   
543   if (message)
544     dbus_message_unref (message);
545
546   return !d->failed;
547 }
548
549 static void
550 kill_client_connection (BusContext     *context,
551                         DBusConnection *connection)
552 {
553   char *base_service;
554   const char *s;
555   CheckServiceDeletedData csdd;
556
557   _dbus_verbose ("killing connection %p\n", connection);
558   
559   s = dbus_bus_get_base_service (connection);
560   _dbus_assert (s != NULL);
561
562   while ((base_service = _dbus_strdup (s)) == NULL)
563     _dbus_wait_for_memory ();
564
565   dbus_connection_ref (connection);
566   
567   /* kick in the disconnect handler that unrefs the connection */
568   dbus_connection_disconnect (connection);
569
570   bus_test_run_everything (context);
571   
572   _dbus_assert (bus_test_client_listed (connection));
573   
574   /* Run disconnect handler in test.c */
575   if (bus_connection_dispatch_one_message (connection))
576     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
577   
578   _dbus_assert (!dbus_connection_get_is_connected (connection));
579   dbus_connection_unref (connection);
580   connection = NULL;
581   _dbus_assert (!bus_test_client_listed (connection));
582   
583   csdd.expected_service_name = base_service;
584   csdd.failed = FALSE;
585
586   bus_test_clients_foreach (check_service_deleted_foreach,
587                             &csdd);
588
589   dbus_free (base_service);
590   
591   if (csdd.failed)
592     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
593   
594   if (!check_no_leftovers (context))
595     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
596 }
597
598 static void
599 kill_client_connection_unchecked (DBusConnection *connection)
600 {
601   /* This kills the connection without expecting it to affect
602    * the rest of the bus.
603    */  
604   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
605
606   dbus_connection_ref (connection);
607   dbus_connection_disconnect (connection);
608   /* dispatching disconnect handler will unref once */
609   if (bus_connection_dispatch_one_message (connection))
610     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
611   dbus_connection_unref (connection);
612   _dbus_assert (!bus_test_client_listed (connection));
613 }
614
615 typedef struct
616 {
617   dbus_bool_t failed;
618 } CheckNoMessagesData;
619
620 static dbus_bool_t
621 check_no_messages_foreach (DBusConnection *connection,
622                            void           *data)
623 {
624   CheckNoMessagesData *d = data;
625   DBusMessage *message;
626
627   message = pop_message_waiting_for_memory (connection);
628   if (message != NULL)
629     {
630       _dbus_warn ("Received message %s on %p, expecting no messages\n",
631                   dbus_message_get_name (message), connection);
632       d->failed = TRUE;
633     }
634
635   if (message)
636     dbus_message_unref (message);
637   return !d->failed;
638 }
639
640 typedef struct
641 {
642   DBusConnection *skip_connection;
643   const char *expected_service_name;
644   dbus_bool_t failed;
645 } CheckServiceCreatedData;
646
647 static dbus_bool_t
648 check_service_created_foreach (DBusConnection *connection,
649                                void           *data)
650 {
651   CheckServiceCreatedData *d = data;
652   DBusMessage *message;
653   DBusError error;
654   char *service_name;
655
656   if (connection == d->skip_connection)
657     return TRUE;
658
659   dbus_error_init (&error);
660   d->failed = TRUE;
661   service_name = NULL;
662   
663   message = pop_message_waiting_for_memory (connection);
664   if (message == NULL)
665     {
666       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
667                   connection, DBUS_MESSAGE_SERVICE_CREATED);
668       goto out;
669     }
670   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
671     {
672       _dbus_warn ("Received message %s on %p, expecting %s\n",
673                   dbus_message_get_name (message),
674                   connection, DBUS_MESSAGE_SERVICE_CREATED);
675       goto out;
676     }
677   else
678     {
679       if (!dbus_message_get_args (message, &error,
680                                   DBUS_TYPE_STRING, &service_name,
681                                   DBUS_TYPE_INVALID))
682         {
683           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
684             {
685               _dbus_verbose ("no memory to get service name arg\n");
686             }
687           else
688             {
689               _dbus_assert (dbus_error_is_set (&error));
690               _dbus_warn ("Did not get the expected single string argument\n");
691               goto out;
692             }
693         }
694       else if (strcmp (service_name, d->expected_service_name) != 0)
695         {
696           _dbus_warn ("expected creation of service %s, got creation of %s\n",
697                       d->expected_service_name,
698                       service_name);
699           goto out;
700         }
701     }
702
703   d->failed = FALSE;
704   
705  out:
706   dbus_free (service_name);
707   dbus_error_free (&error);
708   
709   if (message)
710     dbus_message_unref (message);
711
712   return !d->failed;
713 }
714
715 static dbus_bool_t
716 check_no_leftovers (BusContext *context)
717 {
718   CheckNoMessagesData nmd;
719
720   nmd.failed = FALSE;
721   bus_test_clients_foreach (check_no_messages_foreach,
722                             &nmd);
723   
724   if (nmd.failed)
725     return FALSE;
726   else
727     return TRUE;
728 }
729
730 /* returns TRUE if the correct thing happens,
731  * but the correct thing may include OOM errors.
732  */
733 static dbus_bool_t
734 check_hello_message (BusContext     *context,
735                      DBusConnection *connection)
736 {
737   DBusMessage *message;
738   dbus_int32_t serial;
739   dbus_bool_t retval;
740   DBusError error;
741   char *name;
742   char *acquired;
743   
744   dbus_error_init (&error);
745   name = NULL;
746   acquired = NULL;
747   
748   message = dbus_message_new (DBUS_SERVICE_DBUS,
749                               DBUS_MESSAGE_HELLO);
750
751   if (message == NULL)
752     return TRUE;
753
754   if (!dbus_connection_send (connection, message, &serial))
755     {
756       dbus_message_unref (message);
757       return TRUE;
758     }
759
760   dbus_message_unref (message);
761   message = NULL;
762
763   bus_test_run_everything (context);
764
765   if (!dbus_connection_get_is_connected (connection))
766     {
767       _dbus_verbose ("connection was disconnected\n");
768       return TRUE;
769     }
770   
771   retval = FALSE;
772   
773   message = pop_message_waiting_for_memory (connection);
774   if (message == NULL)
775     {
776       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
777                   DBUS_MESSAGE_HELLO, serial, connection);
778       goto out;
779     }
780
781   _dbus_verbose ("Received %s on %p\n",
782                  dbus_message_get_name (message), connection);
783
784   if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
785     {
786       _dbus_warn ("Message has wrong sender %s\n",
787                   dbus_message_get_sender (message) ?
788                   dbus_message_get_sender (message) : "(none)");
789       goto out;
790     }
791   
792   if (dbus_message_get_is_error (message))
793     {
794       if (dbus_message_name_is (message,
795                                 DBUS_ERROR_NO_MEMORY))
796         {
797           ; /* good, this is a valid response */
798         }
799       else
800         {
801           _dbus_warn ("Did not expect error %s\n",
802                       dbus_message_get_name (message));
803           goto out;
804         }
805     }
806   else
807     {
808       CheckServiceCreatedData scd;
809       
810       if (dbus_message_name_is (message,
811                                 DBUS_MESSAGE_HELLO))
812         {
813           ; /* good, expected */
814         }
815       else
816         {
817           _dbus_warn ("Did not expect reply %s\n",
818                       dbus_message_get_name (message));
819           goto out;
820         }
821
822     retry_get_hello_name:
823       if (!dbus_message_get_args (message, &error,
824                                   DBUS_TYPE_STRING, &name,
825                                   DBUS_TYPE_INVALID))
826         {
827           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
828             {
829               _dbus_verbose ("no memory to get service name arg from hello\n");
830               dbus_error_free (&error);
831               _dbus_wait_for_memory ();
832               goto retry_get_hello_name;
833             }
834           else
835             {
836               _dbus_assert (dbus_error_is_set (&error));
837               _dbus_warn ("Did not get the expected single string argument to hello\n");
838               goto out;
839             }
840         }
841
842       _dbus_verbose ("Got hello name: %s\n", name);
843
844       while (!dbus_bus_set_base_service (connection, name))
845         _dbus_wait_for_memory ();
846       
847       scd.skip_connection = NULL;
848       scd.failed = FALSE;
849       scd.expected_service_name = name;
850       bus_test_clients_foreach (check_service_created_foreach,
851                                 &scd);
852       
853       if (scd.failed)
854         goto out;
855       
856       /* Client should also have gotten ServiceAcquired */
857       dbus_message_unref (message);
858       message = pop_message_waiting_for_memory (connection);
859       if (message == NULL)
860         {
861           _dbus_warn ("Expecting %s, got nothing\n",
862                       DBUS_MESSAGE_SERVICE_ACQUIRED);
863           goto out;
864         }
865       
866     retry_get_acquired_name:
867       if (!dbus_message_get_args (message, &error,
868                                   DBUS_TYPE_STRING, &acquired,
869                                   DBUS_TYPE_INVALID))
870         {
871           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
872             {
873               _dbus_verbose ("no memory to get service name arg from acquired\n");
874               dbus_error_free (&error);
875               _dbus_wait_for_memory ();
876               goto retry_get_acquired_name;
877             }
878           else
879             {
880               _dbus_assert (dbus_error_is_set (&error));
881               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
882               goto out;
883             }
884         }
885
886       _dbus_verbose ("Got acquired name: %s\n", acquired);
887
888       if (strcmp (acquired, name) != 0)
889         {
890           _dbus_warn ("Acquired name is %s but expected %s\n",
891                       acquired, name);
892           goto out;
893         }
894     }
895
896   if (!check_no_leftovers (context))
897     goto out;
898   
899   retval = TRUE;
900   
901  out:
902   dbus_error_free (&error);
903   
904   dbus_free (name);
905   dbus_free (acquired);
906   
907   if (message)
908     dbus_message_unref (message);
909   
910   return retval;
911 }
912
913 /* returns TRUE if the correct thing happens,
914  * but the correct thing may include OOM errors.
915  */
916 static dbus_bool_t
917 check_hello_connection (BusContext *context)
918 {
919   DBusConnection *connection;
920   DBusError error;
921
922   dbus_error_init (&error);
923
924   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
925   if (connection == NULL)
926     {
927       _DBUS_ASSERT_ERROR_IS_SET (&error);
928       dbus_error_free (&error);
929       return TRUE;
930     }
931
932   if (!bus_setup_debug_client (connection))
933     {
934       dbus_connection_disconnect (connection);
935       dbus_connection_unref (connection);
936       return TRUE;
937     }
938
939   if (!check_hello_message (context, connection))
940     return FALSE;
941
942   if (dbus_bus_get_base_service (connection) == NULL)
943     {
944       /* We didn't successfully register, so we can't
945        * do the usual kill_client_connection() checks
946        */
947       kill_client_connection_unchecked (connection);
948     }
949   else
950     {
951       kill_client_connection (context, connection);
952     }
953
954   return TRUE;
955 }
956
957 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
958
959 /* returns TRUE if the correct thing happens,
960  * but the correct thing may include OOM errors.
961  */
962 static dbus_bool_t
963 check_nonexistent_service_activation (BusContext     *context,
964                                       DBusConnection *connection)
965 {
966   DBusMessage *message;
967   dbus_int32_t serial;
968   dbus_bool_t retval;
969   DBusError error;
970   
971   dbus_error_init (&error);
972   
973   message = dbus_message_new (DBUS_SERVICE_DBUS,
974                               DBUS_MESSAGE_ACTIVATE_SERVICE);
975
976   if (message == NULL)
977     return TRUE;
978
979   if (!dbus_message_append_args (message,
980                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
981                                  DBUS_TYPE_UINT32, 0,
982                                  DBUS_TYPE_INVALID))
983     {
984       dbus_message_unref (message);
985       return TRUE;
986     }
987   
988   if (!dbus_connection_send (connection, message, &serial))
989     {
990       dbus_message_unref (message);
991       return TRUE;
992     }
993
994   dbus_message_unref (message);
995   message = NULL;
996
997   bus_test_run_everything (context);
998   block_connection_until_message_from_bus (context, connection);
999   bus_test_run_everything (context);
1000
1001   if (!dbus_connection_get_is_connected (connection))
1002     {
1003       _dbus_verbose ("connection was disconnected\n");
1004       return TRUE;
1005     }
1006   
1007   retval = FALSE;
1008   
1009   message = pop_message_waiting_for_memory (connection);
1010   if (message == NULL)
1011     {
1012       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1013                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1014       goto out;
1015     }
1016
1017   _dbus_verbose ("Received %s on %p\n",
1018                  dbus_message_get_name (message), connection);
1019
1020   if (dbus_message_get_is_error (message))
1021     {
1022       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1023         {
1024           _dbus_warn ("Message has wrong sender %s\n",
1025                       dbus_message_get_sender (message) ?
1026                       dbus_message_get_sender (message) : "(none)");
1027           goto out;
1028         }
1029       
1030       if (dbus_message_name_is (message,
1031                                 DBUS_ERROR_NO_MEMORY))
1032         {
1033           ; /* good, this is a valid response */
1034         }
1035       else if (dbus_message_name_is (message,
1036                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1037         {
1038           ; /* good, this is expected also */
1039         }
1040       else
1041         {
1042           _dbus_warn ("Did not expect error %s\n",
1043                       dbus_message_get_name (message));
1044           goto out;
1045         }
1046     }
1047   else
1048     {
1049       _dbus_warn ("Did not expect to successfully activate %s\n",
1050                   NONEXISTENT_SERVICE_NAME);
1051       goto out;
1052     }
1053
1054   retval = TRUE;
1055   
1056  out:
1057   if (message)
1058     dbus_message_unref (message);
1059   
1060   return retval;
1061 }
1062
1063 static dbus_bool_t
1064 check_base_service_activated (BusContext     *context,
1065                               DBusConnection *connection,
1066                               DBusMessage    *initial_message,
1067                               char          **base_service_p)
1068 {
1069   DBusMessage *message;
1070   dbus_bool_t retval;
1071   DBusError error;
1072   char *base_service;
1073   
1074   base_service = NULL;
1075   retval = FALSE;
1076   
1077   dbus_error_init (&error);
1078
1079   message = initial_message;
1080   dbus_message_ref (message);  
1081
1082   if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1083     {
1084       char *service_name;
1085       CheckServiceCreatedData scd;
1086
1087     reget_service_name_arg:
1088       if (!dbus_message_get_args (message, &error,
1089                                   DBUS_TYPE_STRING, &service_name,
1090                                   DBUS_TYPE_INVALID))
1091         {
1092           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1093             {
1094               dbus_error_free (&error);
1095               _dbus_wait_for_memory ();
1096               goto reget_service_name_arg;
1097             }
1098           else
1099             {
1100               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1101                           dbus_message_get_name (message),
1102                           error.message);
1103               dbus_error_free (&error);
1104               goto out;
1105             }
1106         }
1107
1108       if (*service_name != ':')
1109         {
1110           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1111                       service_name);
1112           goto out;
1113         }
1114               
1115       base_service = service_name;
1116       service_name = NULL;
1117       
1118       scd.skip_connection = connection;
1119       scd.failed = FALSE;
1120       scd.expected_service_name = base_service;
1121       bus_test_clients_foreach (check_service_created_foreach,
1122                                 &scd);
1123       
1124       if (scd.failed)
1125         goto out;
1126     }
1127   else
1128     {
1129       _dbus_warn ("Expected to get base service ServiceCreated, instead got %s\n",
1130                   dbus_message_get_name (message));
1131       goto out;
1132     }
1133
1134   retval = TRUE;
1135
1136   if (base_service_p)
1137     {
1138       *base_service_p = base_service;
1139       base_service = NULL;
1140     }
1141   
1142  out:
1143   if (message)
1144     dbus_message_unref (message);
1145
1146   if (base_service)
1147     dbus_free (base_service);
1148   
1149   return retval;
1150 }
1151
1152 static dbus_bool_t
1153 check_service_activated (BusContext     *context,
1154                          DBusConnection *connection,
1155                          const char     *activated_name,
1156                          const char     *base_service_name,
1157                          DBusMessage    *initial_message)
1158 {
1159   DBusMessage *message;
1160   dbus_bool_t retval;
1161   DBusError error;
1162   dbus_uint32_t activation_result;
1163   
1164   retval = FALSE;
1165   
1166   dbus_error_init (&error);
1167
1168   message = initial_message;
1169   dbus_message_ref (message);
1170
1171   if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1172     {
1173       char *service_name;
1174       CheckServiceCreatedData scd;
1175
1176     reget_service_name_arg:
1177       if (!dbus_message_get_args (message, &error,
1178                                   DBUS_TYPE_STRING, &service_name,
1179                                   DBUS_TYPE_INVALID))
1180         {
1181           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1182             {
1183               dbus_error_free (&error);
1184               _dbus_wait_for_memory ();
1185               goto reget_service_name_arg;
1186             }
1187           else
1188             {
1189               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1190                           dbus_message_get_name (message),
1191                           error.message);
1192               dbus_error_free (&error);
1193               goto out;
1194             }
1195         }
1196
1197       if (strcmp (service_name, activated_name) != 0)
1198         {
1199           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1200                       activated_name, service_name);
1201           dbus_free (service_name);
1202           goto out;
1203         }
1204       
1205       scd.skip_connection = connection;
1206       scd.failed = FALSE;
1207       scd.expected_service_name = service_name;
1208       bus_test_clients_foreach (check_service_created_foreach,
1209                                 &scd);
1210           
1211       dbus_free (service_name);
1212
1213       if (scd.failed)
1214         goto out;
1215           
1216       dbus_message_unref (message);
1217       message = pop_message_waiting_for_memory (connection);
1218       if (message == NULL)
1219         {
1220           _dbus_warn ("Expected a reply to %s, got nothing\n",
1221                       DBUS_MESSAGE_ACTIVATE_SERVICE);
1222           goto out;
1223         }
1224     }
1225   else
1226     {
1227       _dbus_warn ("Expected to get service %s ServiceCreated, instead got %s\n",
1228                   activated_name, dbus_message_get_name (message));
1229       goto out;
1230     }
1231   
1232   if (!dbus_message_name_is (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
1233     {
1234       _dbus_warn ("Expected reply to %s, got message %s instead\n",
1235                   DBUS_MESSAGE_ACTIVATE_SERVICE,
1236                   dbus_message_get_name (message));
1237       goto out;
1238     }
1239
1240   activation_result = 0;
1241   if (!dbus_message_get_args (message, &error,
1242                               DBUS_TYPE_UINT32, &activation_result,
1243                               DBUS_TYPE_INVALID))
1244     {
1245       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1246         {
1247           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1248                       DBUS_MESSAGE_ACTIVATE_SERVICE, error.message);
1249           dbus_error_free (&error);
1250           goto out;
1251         }
1252
1253       dbus_error_free (&error);
1254     }
1255   else
1256     {
1257       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
1258         ; /* Good */
1259       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
1260         ; /* Good also */
1261       else
1262         {
1263           _dbus_warn ("Activation result was 0x%x, no good.\n",
1264                       activation_result);
1265           goto out;
1266         }
1267     }
1268
1269   dbus_message_unref (message);
1270   message = NULL;
1271       
1272   if (!check_no_leftovers (context))
1273     {
1274       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1275       goto out;
1276     }
1277
1278   retval = TRUE;
1279   
1280  out:
1281   if (message)
1282     dbus_message_unref (message);
1283   
1284   return retval;
1285 }
1286
1287 static dbus_bool_t
1288 check_service_deactivated (BusContext     *context,
1289                            DBusConnection *connection,
1290                            const char     *activated_name,
1291                            const char     *base_service)
1292 {
1293   DBusMessage *message;
1294   dbus_bool_t retval;
1295   DBusError error;
1296   CheckServiceDeletedData csdd;
1297
1298   message = NULL;
1299   retval = FALSE;
1300   
1301   dbus_error_init (&error);
1302
1303   /* Now we are expecting ServiceDeleted messages for the base
1304    * service and the activated_name.  The base service
1305    * notification is required to come last.
1306    */
1307   csdd.expected_service_name = activated_name;
1308   csdd.failed = FALSE;
1309   bus_test_clients_foreach (check_service_deleted_foreach,
1310                             &csdd);      
1311
1312   if (csdd.failed)
1313     goto out;
1314       
1315   csdd.expected_service_name = base_service;
1316   csdd.failed = FALSE;
1317   bus_test_clients_foreach (check_service_deleted_foreach,
1318                             &csdd);
1319
1320   if (csdd.failed)
1321     goto out;
1322       
1323   if (!check_no_leftovers (context))
1324     {
1325       _dbus_warn ("Messages were left over after verifying results of service exiting\n");
1326       goto out;
1327     }
1328
1329   retval = TRUE;
1330   
1331  out:
1332   if (message)
1333     dbus_message_unref (message);
1334   
1335   return retval;
1336 }
1337
1338 static dbus_bool_t
1339 check_send_exit_to_service (BusContext     *context,
1340                             DBusConnection *connection,
1341                             const char     *service_name,
1342                             const char     *base_service)
1343 {
1344   dbus_bool_t got_error;
1345   DBusMessage *message;
1346   dbus_int32_t serial;
1347   dbus_bool_t retval;
1348   
1349   _dbus_verbose ("Sending exit message to the test service\n");
1350
1351   retval = FALSE;
1352   
1353   /* Kill off the test service by sending it a quit message */
1354   message = dbus_message_new (service_name,
1355                               "org.freedesktop.DBus.TestSuiteExit");
1356       
1357   if (message == NULL)
1358     {
1359       /* Do this again; we still need the service to exit... */
1360       if (!check_send_exit_to_service (context, connection,
1361                                        service_name, base_service))
1362         goto out;
1363       
1364       return TRUE;
1365     }
1366       
1367   if (!dbus_connection_send (connection, message, &serial))
1368     {
1369       dbus_message_unref (message);
1370
1371       /* Do this again; we still need the service to exit... */
1372       if (!check_send_exit_to_service (context, connection,
1373                                        service_name, base_service))
1374         goto out;
1375       
1376       return TRUE;
1377     }
1378
1379   dbus_message_unref (message);
1380   message = NULL;
1381
1382   /* send message */
1383   bus_test_run_clients_loop (TRUE);
1384
1385   /* read it in and write it out to test service */
1386   bus_test_run_bus_loop (context, FALSE);
1387
1388   /* see if we got an error during message bus dispatching */
1389   bus_test_run_clients_loop (FALSE);
1390   message = dbus_connection_borrow_message (connection);
1391   got_error = message != NULL && dbus_message_get_is_error (message);
1392   if (message)
1393     dbus_connection_return_message (connection, message);
1394           
1395   if (!got_error)
1396     {
1397       /* If no error, wait for the test service to exit */
1398       block_connection_until_message_from_bus (context, connection);
1399               
1400       bus_test_run_everything (context);
1401     }
1402
1403   if (got_error)
1404     {
1405       message = pop_message_waiting_for_memory (connection);
1406       _dbus_assert (message != NULL);
1407
1408       if (!dbus_message_get_is_error (message))
1409         {
1410           _dbus_warn ("expecting an error reply to asking test service to exit, got %s\n",
1411                       dbus_message_get_name (message));
1412           goto out;
1413         }
1414       else if (!dbus_message_name_is (message, DBUS_ERROR_NO_MEMORY))
1415         {
1416           _dbus_warn ("not expecting error %s when asking test service to exit\n",
1417                       dbus_message_get_name (message));
1418           goto out;
1419         }
1420
1421       _dbus_verbose ("Got error %s when asking test service to exit\n",
1422                      dbus_message_get_name (message));
1423
1424       /* Do this again; we still need the service to exit... */
1425       if (!check_send_exit_to_service (context, connection,
1426                                        service_name, base_service))
1427         goto out;
1428     }
1429   else
1430     {
1431       if (!check_service_deactivated (context, connection,
1432                                       service_name, base_service))
1433         goto out;
1434     }
1435
1436   retval = TRUE;
1437   
1438  out:
1439   if (message)
1440     dbus_message_unref (message);
1441   
1442   return retval;
1443 }
1444
1445 static dbus_bool_t
1446 check_got_error (BusContext     *context,
1447                  DBusConnection *connection,
1448                  const char     *error_name)
1449 {
1450   DBusMessage *message;
1451   dbus_bool_t retval;
1452
1453   retval = FALSE;
1454   
1455   message = pop_message_waiting_for_memory (connection);
1456   if (message == NULL)
1457     {
1458       _dbus_warn ("Did not get an expected error\n");
1459       goto out;
1460     }
1461
1462   if (!dbus_message_get_is_error (message))
1463     {
1464       _dbus_warn ("Expected an error, got %s\n",
1465                   dbus_message_get_name (message));
1466       goto out;
1467     }
1468
1469   if (!dbus_message_name_is (message, error_name))
1470     {
1471       _dbus_warn ("Expected error %s, got %s instead\n",
1472                   error_name,
1473                   dbus_message_get_name (message));
1474       goto out;
1475     }
1476
1477   retval = TRUE;
1478   
1479  out:
1480   if (message)
1481     dbus_message_unref (message);
1482   
1483   return retval;
1484 }
1485           
1486 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1487
1488 /* returns TRUE if the correct thing happens,
1489  * but the correct thing may include OOM errors.
1490  */
1491 static dbus_bool_t
1492 check_existent_service_activation (BusContext     *context,
1493                                    DBusConnection *connection)
1494 {
1495   DBusMessage *message;
1496   dbus_int32_t serial;
1497   dbus_bool_t retval;
1498   DBusError error;
1499   char *base_service;
1500
1501   base_service = NULL;
1502   
1503   dbus_error_init (&error);
1504   
1505   message = dbus_message_new (DBUS_SERVICE_DBUS,
1506                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1507
1508   if (message == NULL)
1509     return TRUE;
1510
1511   if (!dbus_message_append_args (message,
1512                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
1513                                  DBUS_TYPE_UINT32, 0,
1514                                  DBUS_TYPE_INVALID))
1515     {
1516       dbus_message_unref (message);
1517       return TRUE;
1518     }
1519   
1520   if (!dbus_connection_send (connection, message, &serial))
1521     {
1522       dbus_message_unref (message);
1523       return TRUE;
1524     }
1525
1526   dbus_message_unref (message);
1527   message = NULL;
1528
1529   bus_test_run_everything (context);
1530
1531   /* now wait for the message bus to hear back from the activated
1532    * service.
1533    */
1534   block_connection_until_message_from_bus (context, connection);
1535
1536   bus_test_run_everything (context);
1537
1538   if (!dbus_connection_get_is_connected (connection))
1539     {
1540       _dbus_verbose ("connection was disconnected\n");
1541       return TRUE;
1542     }
1543   
1544   retval = FALSE;
1545   
1546   message = pop_message_waiting_for_memory (connection);
1547   if (message == NULL)
1548     {
1549       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
1550                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1551       goto out;
1552     }
1553
1554   _dbus_verbose ("Received %s on %p after sending %s\n",
1555                  dbus_message_get_name (message), connection,
1556                  DBUS_MESSAGE_ACTIVATE_SERVICE);
1557
1558   if (dbus_message_get_is_error (message))
1559     {
1560       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1561         {
1562           _dbus_warn ("Message has wrong sender %s\n",
1563                       dbus_message_get_sender (message) ?
1564                       dbus_message_get_sender (message) : "(none)");
1565           goto out;
1566         }
1567       
1568       if (dbus_message_name_is (message,
1569                                 DBUS_ERROR_NO_MEMORY))
1570         {
1571           ; /* good, this is a valid response */
1572         }
1573       else if (dbus_message_name_is (message,
1574                                      DBUS_ERROR_SPAWN_CHILD_EXITED))
1575         {
1576           ; /* good, this is expected also */
1577         }
1578       else
1579         {
1580           _dbus_warn ("Did not expect error %s\n",
1581                       dbus_message_get_name (message));
1582           goto out;
1583         }
1584     }
1585   else
1586     {
1587       dbus_bool_t got_service_deleted;
1588       dbus_bool_t got_error;
1589       
1590       if (!check_base_service_activated (context, connection,
1591                                          message, &base_service))
1592         goto out;
1593
1594       dbus_message_unref (message);
1595       message = NULL;
1596
1597       /* We may need to block here for the test service to exit or finish up */
1598       block_connection_until_message_from_bus (context, connection);
1599       
1600       message = dbus_connection_borrow_message (connection);
1601       if (message == NULL)
1602         {
1603           _dbus_warn ("Did not receive any messages after base service creation notification\n");
1604           goto out;
1605         }
1606
1607       got_service_deleted = dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED);
1608       got_error = dbus_message_get_is_error (message);
1609       
1610       dbus_connection_return_message (connection, message);
1611       message = NULL;
1612
1613       if (got_error)
1614         {
1615           if (!check_got_error (context, connection,
1616                                 DBUS_ERROR_SPAWN_CHILD_EXITED))
1617             goto out;
1618
1619           /* A service deleted should be coming along now after this error.
1620            * We can also get the error *after* the service deleted.
1621            */
1622           got_service_deleted = TRUE;
1623         }
1624       
1625       if (got_service_deleted)
1626         {
1627           /* The service started up and got a base address, but then
1628            * failed to register under EXISTENT_SERVICE_NAME
1629            */
1630           CheckServiceDeletedData csdd;
1631           
1632           csdd.expected_service_name = base_service;
1633           csdd.failed = FALSE;
1634           bus_test_clients_foreach (check_service_deleted_foreach,
1635                                     &csdd);
1636
1637           if (csdd.failed)
1638             goto out;
1639
1640           /* Now we should get an error about the service exiting
1641            * if we didn't get it before.
1642            */
1643           if (!got_error)
1644             {
1645               block_connection_until_message_from_bus (context, connection);
1646               
1647               /* and process everything again */
1648               bus_test_run_everything (context);
1649               
1650               if (!check_got_error (context, connection,
1651                                     DBUS_ERROR_SPAWN_CHILD_EXITED))
1652                 goto out;
1653             }
1654         }
1655       else
1656         {
1657           message = pop_message_waiting_for_memory (connection);
1658           if (message == NULL)
1659             {
1660               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
1661               goto out;
1662             }
1663           
1664           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
1665                                         base_service, message))
1666             goto out;
1667           
1668           dbus_message_unref (message);
1669           message = NULL;
1670
1671
1672           if (!check_no_leftovers (context))
1673             {
1674               _dbus_warn ("Messages were left over after successful activation\n");
1675               goto out;
1676             }
1677
1678           if (!check_send_exit_to_service (context, connection,
1679                                            EXISTENT_SERVICE_NAME, base_service))
1680             goto out;
1681         }
1682     }
1683   
1684   retval = TRUE;
1685   
1686  out:
1687   if (message)
1688     dbus_message_unref (message);
1689
1690   if (base_service)
1691     dbus_free (base_service);
1692   
1693   return retval;
1694 }
1695
1696 /* returns TRUE if the correct thing happens,
1697  * but the correct thing may include OOM errors.
1698  */
1699 static dbus_bool_t
1700 check_segfault_service_activation (BusContext     *context,
1701                                    DBusConnection *connection)
1702 {
1703   DBusMessage *message;
1704   dbus_int32_t serial;
1705   dbus_bool_t retval;
1706   DBusError error;
1707   
1708   dbus_error_init (&error);
1709   
1710   message = dbus_message_new (DBUS_SERVICE_DBUS,
1711                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1712
1713   if (message == NULL)
1714     return TRUE;
1715
1716   if (!dbus_message_append_args (message,
1717                                  DBUS_TYPE_STRING,
1718                                  "org.freedesktop.DBus.TestSuiteSegfaultService",
1719                                  DBUS_TYPE_UINT32, 0,
1720                                  DBUS_TYPE_INVALID))
1721     {
1722       dbus_message_unref (message);
1723       return TRUE;
1724     }
1725   
1726   if (!dbus_connection_send (connection, message, &serial))
1727     {
1728       dbus_message_unref (message);
1729       return TRUE;
1730     }
1731
1732   dbus_message_unref (message);
1733   message = NULL;
1734
1735   bus_test_run_everything (context);
1736   block_connection_until_message_from_bus (context, connection);
1737   bus_test_run_everything (context);
1738
1739   if (!dbus_connection_get_is_connected (connection))
1740     {
1741       _dbus_verbose ("connection was disconnected\n");
1742       return TRUE;
1743     }
1744   
1745   retval = FALSE;
1746   
1747   message = pop_message_waiting_for_memory (connection);
1748   if (message == NULL)
1749     {
1750       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1751                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1752       goto out;
1753     }
1754
1755   _dbus_verbose ("Received %s on %p\n",
1756                  dbus_message_get_name (message), connection);
1757
1758   if (dbus_message_get_is_error (message))
1759     {
1760       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1761         {
1762           _dbus_warn ("Message has wrong sender %s\n",
1763                       dbus_message_get_sender (message) ?
1764                       dbus_message_get_sender (message) : "(none)");
1765           goto out;
1766         }
1767       
1768       if (dbus_message_name_is (message,
1769                                 DBUS_ERROR_NO_MEMORY))
1770         {
1771           ; /* good, this is a valid response */
1772         }
1773       else if (dbus_message_name_is (message,
1774                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED))
1775         {
1776           ; /* good, this is expected also */
1777         }
1778       else
1779         {
1780           _dbus_warn ("Did not expect error %s\n",
1781                       dbus_message_get_name (message));
1782           goto out;
1783         }
1784     }
1785   else
1786     {
1787       _dbus_warn ("Did not expect to successfully activate segfault service\n");
1788       goto out;
1789     }
1790
1791   retval = TRUE;
1792   
1793  out:
1794   if (message)
1795     dbus_message_unref (message);
1796   
1797   return retval;
1798 }
1799
1800 typedef struct
1801 {
1802   Check1Func func;
1803   BusContext *context;
1804 } Check1Data;
1805
1806 static dbus_bool_t
1807 check_oom_check1_func (void *data)
1808 {
1809   Check1Data *d = data;
1810
1811   if (! (* d->func) (d->context))
1812     return FALSE;
1813   
1814   if (!check_no_leftovers (d->context))
1815     {
1816       _dbus_warn ("Messages were left over, should be covered by test suite\n");
1817       return FALSE;
1818     }
1819
1820   return TRUE;
1821 }
1822
1823 static void
1824 check1_try_iterations (BusContext *context,
1825                        const char *description,
1826                        Check1Func  func)
1827 {
1828   Check1Data d;
1829
1830   d.func = func;
1831   d.context = context;
1832
1833   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
1834                                 &d))
1835     _dbus_assert_not_reached ("test failed");
1836 }
1837
1838 typedef struct
1839 {
1840   Check2Func func;
1841   BusContext *context;
1842   DBusConnection *connection;
1843 } Check2Data;
1844
1845 static dbus_bool_t
1846 check_oom_check2_func (void *data)
1847 {
1848   Check2Data *d = data;
1849
1850   if (! (* d->func) (d->context, d->connection))
1851     return FALSE;
1852   
1853   if (!check_no_leftovers (d->context))
1854     {
1855       _dbus_warn ("Messages were left over, should be covered by test suite");
1856       return FALSE;
1857     }
1858
1859   return TRUE;
1860 }
1861
1862 static void
1863 check2_try_iterations (BusContext     *context,
1864                        DBusConnection *connection,
1865                        const char     *description,
1866                        Check2Func      func)
1867 {
1868   Check2Data d;
1869
1870   d.func = func;
1871   d.context = context;
1872   d.connection = connection;
1873   
1874   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
1875                                 &d))
1876     _dbus_assert_not_reached ("test failed");
1877 }
1878
1879 dbus_bool_t
1880 bus_dispatch_test (const DBusString *test_data_dir)
1881 {
1882   BusContext *context;
1883   DBusConnection *foo;
1884   DBusConnection *bar;
1885   DBusConnection *baz;
1886   DBusError error;
1887   
1888   context = bus_context_new_test (test_data_dir,
1889                                   "valid-config-files/debug-allow-all.conf");
1890   if (context == NULL)
1891     return FALSE;
1892
1893   dbus_error_init (&error);
1894   
1895   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1896   if (foo == NULL)
1897     _dbus_assert_not_reached ("could not alloc connection");
1898
1899   if (!bus_setup_debug_client (foo))
1900     _dbus_assert_not_reached ("could not set up connection");
1901
1902   if (!check_hello_message (context, foo))
1903     _dbus_assert_not_reached ("hello message failed");
1904   
1905   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
1906   if (bar == NULL)
1907     _dbus_assert_not_reached ("could not alloc connection");
1908
1909   if (!bus_setup_debug_client (bar))
1910     _dbus_assert_not_reached ("could not set up connection");
1911
1912   if (!check_hello_message (context, bar))
1913     _dbus_assert_not_reached ("hello message failed");
1914   
1915   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
1916   if (baz == NULL)
1917     _dbus_assert_not_reached ("could not alloc connection");
1918
1919   if (!bus_setup_debug_client (baz))
1920     _dbus_assert_not_reached ("could not set up connection");
1921
1922   if (!check_hello_message (context, baz))
1923     _dbus_assert_not_reached ("hello message failed");
1924
1925   check1_try_iterations (context, "create_and_hello",
1926                          check_hello_connection);
1927   
1928   check2_try_iterations (context, foo, "nonexistent_service_activation",
1929                          check_nonexistent_service_activation);
1930
1931   check2_try_iterations (context, foo, "segfault_service_activation",
1932                          check_segfault_service_activation);
1933   
1934   check2_try_iterations (context, foo, "existent_service_activation",
1935                          check_existent_service_activation);
1936   
1937   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1938
1939   kill_client_connection_unchecked (foo);
1940   kill_client_connection_unchecked (bar);
1941   kill_client_connection_unchecked (baz);
1942
1943   bus_context_unref (context);
1944   
1945   return TRUE;
1946 }
1947 #endif /* DBUS_BUILD_TESTS */