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