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