2003-04-14 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 int message_handler_slot = -1;
36 static int message_handler_slot_refcount;
37
38 typedef struct
39 {
40   BusContext     *context;
41   DBusConnection *sender;
42   DBusMessage    *message;
43   BusTransaction *transaction;
44   DBusError      *error;
45 } SendMessageData;
46
47 static dbus_bool_t
48 send_one_message (DBusConnection *connection, void *data)
49 {
50   SendMessageData *d = data;
51   
52   if (!bus_connection_is_active (connection))
53     return TRUE;
54
55   if (!bus_context_check_security_policy (d->context,
56                                           d->sender,
57                                           connection,
58                                           d->message,
59                                           NULL))
60     return TRUE; /* silently don't send it */
61   
62   if (!bus_transaction_send (d->transaction,
63                              connection,
64                              d->message))
65     {
66       BUS_SET_OOM (d->error);
67       return FALSE;
68     }
69
70   return TRUE;
71 }
72
73 dbus_bool_t
74 bus_dispatch_broadcast_message (BusTransaction *transaction,
75                                 DBusConnection *sender,
76                                 DBusMessage    *message,
77                                 DBusError      *error)
78 {
79   DBusError tmp_error;
80   SendMessageData d;
81   BusConnections *connections;
82
83   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
84   
85   _dbus_assert (dbus_message_get_sender (message) != NULL);
86
87   connections = bus_transaction_get_connections (transaction);
88   
89   dbus_error_init (&tmp_error);
90   d.sender = sender;
91   d.context = bus_transaction_get_context (transaction);
92   d.message = message;
93   d.transaction = transaction;
94   d.error = &tmp_error;
95   
96   bus_connections_foreach (connections, send_one_message, &d);
97
98   if (dbus_error_is_set (&tmp_error))
99     {
100       dbus_move_error (&tmp_error, error);
101       return FALSE;
102     }
103   else
104     return TRUE;
105 }
106
107 static void
108 bus_dispatch (DBusConnection *connection,
109               DBusMessage    *message)
110 {
111   const char *sender, *service_name, *message_name;
112   DBusError error;
113   BusTransaction *transaction;
114   BusContext *context;
115   
116   transaction = NULL;
117   dbus_error_init (&error);
118   
119   context = bus_connection_get_context (connection);
120   _dbus_assert (context != NULL);
121   
122   /* If we can't even allocate an OOM error, we just go to sleep
123    * until we can.
124    */
125   while (!bus_connection_preallocate_oom_error (connection))
126     _dbus_wait_for_memory ();
127   
128   /* Ref connection in case we disconnect it at some point in here */
129   dbus_connection_ref (connection);
130
131   service_name = dbus_message_get_service (message);
132   message_name = dbus_message_get_name (message);
133
134   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
135
136   _dbus_verbose ("DISPATCH: %s to %s\n",
137                  message_name, service_name ? service_name : "peer");
138   
139   /* If service_name is NULL, this is a message to the bus daemon, not
140    * intended to actually go "on the bus"; e.g. a peer-to-peer
141    * ping. Handle these immediately, especially disconnection
142    * messages. There are no security policy checks on these.
143    */
144   if (service_name == NULL)
145     {      
146       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
147         bus_connection_disconnected (connection);
148
149       /* DBusConnection also handles some of these automatically, we leave
150        * it to do so.
151        */
152       goto out;
153     }
154
155   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
156   
157   /* Create our transaction */
158   transaction = bus_transaction_new (context);
159   if (transaction == NULL)
160     {
161       BUS_SET_OOM (&error);
162       goto out;
163     }
164   
165   /* Assign a sender to the message */
166   if (bus_connection_is_active (connection))
167     {
168       sender = bus_connection_get_name (connection);
169       _dbus_assert (sender != NULL);
170
171       if (!dbus_message_set_sender (message, sender))
172         {
173           BUS_SET_OOM (&error);
174           goto out;
175         }
176
177       /* We need to refetch the service name here, because
178        * dbus_message_set_sender can cause the header to be
179        * reallocated, and thus the service_name pointer will become
180        * invalid.
181        */
182       service_name = dbus_message_get_service (message);
183     }
184
185   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
186     {
187       if (!bus_context_check_security_policy (context,
188                                               connection, NULL, message, &error))
189         goto out;
190       
191       if (!bus_driver_handle_message (connection, transaction, message, &error))
192         goto out;
193     }
194   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
195     {
196       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
197       dbus_connection_disconnect (connection);
198     }
199   /* FIXME what if we un-special-case this service and just have a flag
200    * on services that all service owners will get messages to it, not just
201    * the primary owner.
202    */
203   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
204     {
205       if (!bus_dispatch_broadcast_message (transaction, connection, message, &error))
206         goto out;
207     }
208   else  /* route to named service */
209     {
210       DBusString service_string;
211       BusService *service;
212       BusRegistry *registry;
213
214       registry = bus_connection_get_registry (connection);
215       
216       _dbus_string_init_const (&service_string, service_name);
217       service = bus_registry_lookup (registry, &service_string);
218
219       if (service == NULL)
220         {
221           dbus_set_error (&error,
222                           DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
223                           "Service \"%s\" does not exist",
224                           service_name);
225           goto out;
226         }
227       else
228         {
229           DBusConnection *recipient;
230           
231           recipient = bus_service_get_primary_owner (service);
232           _dbus_assert (recipient != NULL);
233           
234           if (!bus_context_check_security_policy (context,
235                                                   connection, recipient, message, &error))
236             goto out;
237           
238           /* Dispatch the message */
239           if (!bus_transaction_send (transaction, recipient, message))
240             {
241               BUS_SET_OOM (&error);
242               goto out;
243             }
244         }
245     }
246   
247  out:
248   if (dbus_error_is_set (&error))
249     {
250       if (!dbus_connection_get_is_connected (connection))
251         {
252           /* If we disconnected it, we won't bother to send it any error
253            * messages.
254            */
255         }
256       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
257         {
258           bus_connection_send_oom_error (connection, message);
259
260           /* cancel transaction due to OOM */
261           if (transaction != NULL)
262             {
263               bus_transaction_cancel_and_free (transaction);
264               transaction = NULL;
265             }
266         }
267       else
268         {
269           /* Try to send the real error, if no mem to do that, send
270            * the OOM error
271            */
272           _dbus_assert (transaction != NULL);
273           
274           if (!bus_transaction_send_error_reply (transaction, connection,
275                                                  &error, message))
276             {
277               bus_connection_send_oom_error (connection, message);
278               
279               /* cancel transaction due to OOM */
280               if (transaction != NULL)
281                 {
282                   bus_transaction_cancel_and_free (transaction);
283                   transaction = NULL;
284                 }
285             }
286         }
287       
288       dbus_error_free (&error);
289     }
290
291   if (transaction != NULL)
292     {
293       bus_transaction_execute_and_free (transaction);
294     }
295
296   dbus_connection_unref (connection);
297 }
298
299 static DBusHandlerResult
300 bus_dispatch_message_handler (DBusMessageHandler *handler,
301                               DBusConnection     *connection,
302                               DBusMessage        *message,
303                               void               *user_data)
304 {
305   bus_dispatch (connection, message);
306   
307   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
308 }
309
310 static dbus_bool_t
311 message_handler_slot_ref (void)
312 {
313   if (message_handler_slot < 0)
314     {
315       message_handler_slot = dbus_connection_allocate_data_slot ();
316       
317       if (message_handler_slot < 0)
318         return FALSE;
319
320       _dbus_assert (message_handler_slot_refcount == 0);
321     }  
322
323   message_handler_slot_refcount += 1;
324
325   return TRUE;
326 }
327
328 static void
329 message_handler_slot_unref (void)
330 {
331   _dbus_assert (message_handler_slot_refcount > 0);
332
333   message_handler_slot_refcount -= 1;
334   
335   if (message_handler_slot_refcount == 0)
336     {
337       dbus_connection_free_data_slot (message_handler_slot);
338       message_handler_slot = -1;
339     }
340 }
341
342 static void
343 free_message_handler (void *data)
344 {
345   DBusMessageHandler *handler = data;
346   
347   _dbus_assert (message_handler_slot >= 0);
348   _dbus_assert (message_handler_slot_refcount > 0);
349   
350   dbus_message_handler_unref (handler);
351   message_handler_slot_unref ();
352 }
353
354 dbus_bool_t
355 bus_dispatch_add_connection (DBusConnection *connection)
356 {
357   DBusMessageHandler *handler;
358
359   if (!message_handler_slot_ref ())
360     return FALSE;
361   
362   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
363   if (handler == NULL)
364     {
365       message_handler_slot_unref ();
366       return FALSE;
367     }    
368   
369   if (!dbus_connection_add_filter (connection, handler))
370     {
371       dbus_message_handler_unref (handler);
372       message_handler_slot_unref ();
373       
374       return FALSE;
375     }
376
377   _dbus_assert (message_handler_slot >= 0);
378   _dbus_assert (message_handler_slot_refcount > 0);
379   
380   if (!dbus_connection_set_data (connection,
381                                  message_handler_slot,
382                                  handler,
383                                  free_message_handler))
384     {
385       dbus_message_handler_unref (handler);
386       message_handler_slot_unref ();
387
388       return FALSE;
389     }
390
391   return TRUE;
392 }
393
394 void
395 bus_dispatch_remove_connection (DBusConnection *connection)
396 {
397   /* Here we tell the bus driver that we want to get off. */
398   bus_driver_remove_connection (connection);
399
400   dbus_connection_set_data (connection,
401                             message_handler_slot,
402                             NULL, NULL);
403 }
404
405 #ifdef DBUS_BUILD_TESTS
406
407 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
408 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
409                                     DBusConnection *connection);
410
411 static dbus_bool_t check_no_leftovers (BusContext *context);
412
413 static void
414 block_connection_until_message_from_bus (BusContext     *context,
415                                          DBusConnection *connection)
416 {
417   while (dbus_connection_get_dispatch_status (connection) ==
418          DBUS_DISPATCH_COMPLETE &&
419          dbus_connection_get_is_connected (connection))
420     {
421       bus_test_run_bus_loop (context, TRUE);
422       bus_test_run_clients_loop (FALSE);
423     }
424 }
425
426 /* compensate for fact that pop_message() can return #NULL due to OOM */
427 static DBusMessage*
428 pop_message_waiting_for_memory (DBusConnection *connection)
429 {
430   while (dbus_connection_get_dispatch_status (connection) ==
431          DBUS_DISPATCH_NEED_MEMORY)
432     _dbus_wait_for_memory ();
433
434   return dbus_connection_pop_message (connection);
435 }
436
437 typedef struct
438 {
439   const char *expected_service_name;
440   dbus_bool_t failed;
441 } CheckServiceDeletedData;
442
443 static dbus_bool_t
444 check_service_deleted_foreach (DBusConnection *connection,
445                                void           *data)
446 {
447   CheckServiceDeletedData *d = data;
448   DBusMessage *message;
449   DBusError error;
450   char *service_name;
451
452   dbus_error_init (&error);
453   d->failed = TRUE;
454   service_name = NULL;
455   
456   message = pop_message_waiting_for_memory (connection);
457   if (message == NULL)
458     {
459       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
460                   connection, DBUS_MESSAGE_SERVICE_DELETED);
461       goto out;
462     }
463   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
464     {
465       _dbus_warn ("Received message %s on %p, expecting %s\n",
466                   dbus_message_get_name (message),
467                   connection, DBUS_MESSAGE_SERVICE_DELETED);
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       _dbus_warn ("Received message %s on %p, expecting no messages\n",
591                   dbus_message_get_name (message), connection);
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, DBUS_MESSAGE_SERVICE_CREATED);
628       goto out;
629     }
630   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
631     {
632       _dbus_warn ("Received message %s on %p, expecting %s\n",
633                   dbus_message_get_name (message),
634                   connection, DBUS_MESSAGE_SERVICE_CREATED);
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 (DBUS_SERVICE_DBUS,
711                               DBUS_MESSAGE_HELLO);
712
713   if (message == NULL)
714     return TRUE;
715
716   if (!dbus_connection_send (connection, message, &serial))
717     {
718       dbus_message_unref (message);
719       return TRUE;
720     }
721
722   dbus_message_unref (message);
723   message = NULL;
724
725   /* send our message */
726   bus_test_run_clients_loop (TRUE);
727
728   dbus_connection_ref (connection); /* because we may get disconnected */
729   block_connection_until_message_from_bus (context, connection);
730
731   if (!dbus_connection_get_is_connected (connection))
732     {
733       _dbus_verbose ("connection was disconnected\n");
734
735       dbus_connection_unref (connection);
736       
737       return TRUE;
738     }
739
740   dbus_connection_unref (connection);
741   
742   message = pop_message_waiting_for_memory (connection);
743   if (message == NULL)
744     {
745       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
746                   DBUS_MESSAGE_HELLO, serial, connection);
747       goto out;
748     }
749
750   _dbus_verbose ("Received %s on %p\n",
751                  dbus_message_get_name (message), connection);
752
753   if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
754     {
755       _dbus_warn ("Message has wrong sender %s\n",
756                   dbus_message_get_sender (message) ?
757                   dbus_message_get_sender (message) : "(none)");
758       goto out;
759     }
760   
761   if (dbus_message_get_is_error (message))
762     {
763       if (dbus_message_name_is (message,
764                                 DBUS_ERROR_NO_MEMORY))
765         {
766           ; /* good, this is a valid response */
767         }
768       else
769         {
770           _dbus_warn ("Did not expect error %s\n",
771                       dbus_message_get_name (message));
772           goto out;
773         }
774     }
775   else
776     {
777       CheckServiceCreatedData scd;
778       
779       if (dbus_message_name_is (message,
780                                 DBUS_MESSAGE_HELLO))
781         {
782           ; /* good, expected */
783         }
784       else
785         {
786           _dbus_warn ("Did not expect reply %s\n",
787                       dbus_message_get_name (message));
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                       DBUS_MESSAGE_SERVICE_ACQUIRED);
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 (DBUS_SERVICE_DBUS,
943                               DBUS_MESSAGE_ACTIVATE_SERVICE);
944
945   if (message == NULL)
946     return TRUE;
947
948   if (!dbus_message_append_args (message,
949                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
950                                  DBUS_TYPE_UINT32, 0,
951                                  DBUS_TYPE_INVALID))
952     {
953       dbus_message_unref (message);
954       return TRUE;
955     }
956   
957   if (!dbus_connection_send (connection, message, &serial))
958     {
959       dbus_message_unref (message);
960       return TRUE;
961     }
962
963   dbus_message_unref (message);
964   message = NULL;
965
966   bus_test_run_everything (context);
967   block_connection_until_message_from_bus (context, connection);
968   bus_test_run_everything (context);
969
970   if (!dbus_connection_get_is_connected (connection))
971     {
972       _dbus_verbose ("connection was disconnected\n");
973       return TRUE;
974     }
975   
976   retval = FALSE;
977   
978   message = pop_message_waiting_for_memory (connection);
979   if (message == NULL)
980     {
981       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
982                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
983       goto out;
984     }
985
986   _dbus_verbose ("Received %s on %p\n",
987                  dbus_message_get_name (message), connection);
988
989   if (dbus_message_get_is_error (message))
990     {
991       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
992         {
993           _dbus_warn ("Message has wrong sender %s\n",
994                       dbus_message_get_sender (message) ?
995                       dbus_message_get_sender (message) : "(none)");
996           goto out;
997         }
998       
999       if (dbus_message_name_is (message,
1000                                 DBUS_ERROR_NO_MEMORY))
1001         {
1002           ; /* good, this is a valid response */
1003         }
1004       else if (dbus_message_name_is (message,
1005                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1006         {
1007           ; /* good, this is expected also */
1008         }
1009       else
1010         {
1011           _dbus_warn ("Did not expect error %s\n",
1012                       dbus_message_get_name (message));
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_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1052     {
1053       char *service_name;
1054       CheckServiceCreatedData scd;
1055
1056     reget_service_name_arg:
1057       if (!dbus_message_get_args (message, &error,
1058                                   DBUS_TYPE_STRING, &service_name,
1059                                   DBUS_TYPE_INVALID))
1060         {
1061           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1062             {
1063               dbus_error_free (&error);
1064               _dbus_wait_for_memory ();
1065               goto reget_service_name_arg;
1066             }
1067           else
1068             {
1069               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1070                           dbus_message_get_name (message),
1071                           error.message);
1072               dbus_error_free (&error);
1073               goto out;
1074             }
1075         }
1076
1077       if (*service_name != ':')
1078         {
1079           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1080                       service_name);
1081           goto out;
1082         }
1083               
1084       base_service = service_name;
1085       service_name = NULL;
1086       
1087       scd.skip_connection = connection;
1088       scd.failed = FALSE;
1089       scd.expected_service_name = base_service;
1090       bus_test_clients_foreach (check_service_created_foreach,
1091                                 &scd);
1092       
1093       if (scd.failed)
1094         goto out;
1095     }
1096   else
1097     {
1098       _dbus_warn ("Expected to get base service ServiceCreated, instead got %s\n",
1099                   dbus_message_get_name (message));
1100       goto out;
1101     }
1102
1103   retval = TRUE;
1104
1105   if (base_service_p)
1106     {
1107       *base_service_p = base_service;
1108       base_service = NULL;
1109     }
1110   
1111  out:
1112   if (message)
1113     dbus_message_unref (message);
1114
1115   if (base_service)
1116     dbus_free (base_service);
1117   
1118   return retval;
1119 }
1120
1121 static dbus_bool_t
1122 check_service_activated (BusContext     *context,
1123                          DBusConnection *connection,
1124                          const char     *activated_name,
1125                          const char     *base_service_name,
1126                          DBusMessage    *initial_message)
1127 {
1128   DBusMessage *message;
1129   dbus_bool_t retval;
1130   DBusError error;
1131   dbus_uint32_t activation_result;
1132   
1133   retval = FALSE;
1134   
1135   dbus_error_init (&error);
1136
1137   message = initial_message;
1138   dbus_message_ref (message);
1139
1140   if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1141     {
1142       char *service_name;
1143       CheckServiceCreatedData scd;
1144
1145     reget_service_name_arg:
1146       if (!dbus_message_get_args (message, &error,
1147                                   DBUS_TYPE_STRING, &service_name,
1148                                   DBUS_TYPE_INVALID))
1149         {
1150           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1151             {
1152               dbus_error_free (&error);
1153               _dbus_wait_for_memory ();
1154               goto reget_service_name_arg;
1155             }
1156           else
1157             {
1158               _dbus_warn ("Message %s doesn't have a service name: %s\n",
1159                           dbus_message_get_name (message),
1160                           error.message);
1161               dbus_error_free (&error);
1162               goto out;
1163             }
1164         }
1165
1166       if (strcmp (service_name, activated_name) != 0)
1167         {
1168           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1169                       activated_name, service_name);
1170           dbus_free (service_name);
1171           goto out;
1172         }
1173       
1174       scd.skip_connection = connection;
1175       scd.failed = FALSE;
1176       scd.expected_service_name = service_name;
1177       bus_test_clients_foreach (check_service_created_foreach,
1178                                 &scd);
1179           
1180       dbus_free (service_name);
1181
1182       if (scd.failed)
1183         goto out;
1184           
1185       dbus_message_unref (message);
1186       message = pop_message_waiting_for_memory (connection);
1187       if (message == NULL)
1188         {
1189           _dbus_warn ("Expected a reply to %s, got nothing\n",
1190                       DBUS_MESSAGE_ACTIVATE_SERVICE);
1191           goto out;
1192         }
1193     }
1194   else
1195     {
1196       _dbus_warn ("Expected to get service %s ServiceCreated, instead got %s\n",
1197                   activated_name, dbus_message_get_name (message));
1198       goto out;
1199     }
1200   
1201   if (!dbus_message_name_is (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
1202     {
1203       _dbus_warn ("Expected reply to %s, got message %s instead\n",
1204                   DBUS_MESSAGE_ACTIVATE_SERVICE,
1205                   dbus_message_get_name (message));
1206       goto out;
1207     }
1208
1209   activation_result = 0;
1210   if (!dbus_message_get_args (message, &error,
1211                               DBUS_TYPE_UINT32, &activation_result,
1212                               DBUS_TYPE_INVALID))
1213     {
1214       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1215         {
1216           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1217                       DBUS_MESSAGE_ACTIVATE_SERVICE, error.message);
1218           dbus_error_free (&error);
1219           goto out;
1220         }
1221
1222       dbus_error_free (&error);
1223     }
1224   else
1225     {
1226       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
1227         ; /* Good */
1228       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
1229         ; /* Good also */
1230       else
1231         {
1232           _dbus_warn ("Activation result was 0x%x, no good.\n",
1233                       activation_result);
1234           goto out;
1235         }
1236     }
1237
1238   dbus_message_unref (message);
1239   message = NULL;
1240       
1241   if (!check_no_leftovers (context))
1242     {
1243       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1244       goto out;
1245     }
1246
1247   retval = TRUE;
1248   
1249  out:
1250   if (message)
1251     dbus_message_unref (message);
1252   
1253   return retval;
1254 }
1255
1256 static dbus_bool_t
1257 check_service_deactivated (BusContext     *context,
1258                            DBusConnection *connection,
1259                            const char     *activated_name,
1260                            const char     *base_service)
1261 {
1262   DBusMessage *message;
1263   dbus_bool_t retval;
1264   DBusError error;
1265   CheckServiceDeletedData csdd;
1266
1267   message = NULL;
1268   retval = FALSE;
1269   
1270   dbus_error_init (&error);
1271
1272   /* Now we are expecting ServiceDeleted messages for the base
1273    * service and the activated_name.  The base service
1274    * notification is required to come last.
1275    */
1276   csdd.expected_service_name = activated_name;
1277   csdd.failed = FALSE;
1278   bus_test_clients_foreach (check_service_deleted_foreach,
1279                             &csdd);      
1280
1281   if (csdd.failed)
1282     goto out;
1283       
1284   csdd.expected_service_name = base_service;
1285   csdd.failed = FALSE;
1286   bus_test_clients_foreach (check_service_deleted_foreach,
1287                             &csdd);
1288
1289   if (csdd.failed)
1290     goto out;
1291       
1292   if (!check_no_leftovers (context))
1293     {
1294       _dbus_warn ("Messages were left over after verifying results of service exiting\n");
1295       goto out;
1296     }
1297
1298   retval = TRUE;
1299   
1300  out:
1301   if (message)
1302     dbus_message_unref (message);
1303   
1304   return retval;
1305 }
1306
1307 static dbus_bool_t
1308 check_send_exit_to_service (BusContext     *context,
1309                             DBusConnection *connection,
1310                             const char     *service_name,
1311                             const char     *base_service)
1312 {
1313   dbus_bool_t got_error;
1314   DBusMessage *message;
1315   dbus_int32_t serial;
1316   dbus_bool_t retval;
1317   
1318   _dbus_verbose ("Sending exit message to the test service\n");
1319
1320   retval = FALSE;
1321   
1322   /* Kill off the test service by sending it a quit message */
1323   message = dbus_message_new (service_name,
1324                               "org.freedesktop.DBus.TestSuiteExit");
1325       
1326   if (message == NULL)
1327     {
1328       /* Do this again; we still need the service to exit... */
1329       if (!check_send_exit_to_service (context, connection,
1330                                        service_name, base_service))
1331         goto out;
1332       
1333       return TRUE;
1334     }
1335       
1336   if (!dbus_connection_send (connection, message, &serial))
1337     {
1338       dbus_message_unref (message);
1339
1340       /* Do this again; we still need the service to exit... */
1341       if (!check_send_exit_to_service (context, connection,
1342                                        service_name, base_service))
1343         goto out;
1344       
1345       return TRUE;
1346     }
1347
1348   dbus_message_unref (message);
1349   message = NULL;
1350
1351   /* send message */
1352   bus_test_run_clients_loop (TRUE);
1353
1354   /* read it in and write it out to test service */
1355   bus_test_run_bus_loop (context, FALSE);
1356
1357   /* see if we got an error during message bus dispatching */
1358   bus_test_run_clients_loop (FALSE);
1359   message = dbus_connection_borrow_message (connection);
1360   got_error = message != NULL && dbus_message_get_is_error (message);
1361   if (message)
1362     {
1363       dbus_connection_return_message (connection, message);
1364       message = NULL;
1365     }
1366           
1367   if (!got_error)
1368     {
1369       /* If no error, wait for the test service to exit */
1370       block_connection_until_message_from_bus (context, connection);
1371               
1372       bus_test_run_everything (context);
1373     }
1374
1375   if (got_error)
1376     {
1377       message = pop_message_waiting_for_memory (connection);
1378       _dbus_assert (message != NULL);
1379
1380       if (!dbus_message_get_is_error (message))
1381         {
1382           _dbus_warn ("expecting an error reply to asking test service to exit, got %s\n",
1383                       dbus_message_get_name (message));
1384           goto out;
1385         }
1386       else if (!dbus_message_name_is (message, DBUS_ERROR_NO_MEMORY))
1387         {
1388           _dbus_warn ("not expecting error %s when asking test service to exit\n",
1389                       dbus_message_get_name (message));
1390           goto out;
1391         }
1392
1393       _dbus_verbose ("Got error %s when asking test service to exit\n",
1394                      dbus_message_get_name (message));
1395
1396       /* Do this again; we still need the service to exit... */
1397       if (!check_send_exit_to_service (context, connection,
1398                                        service_name, base_service))
1399         goto out;
1400     }
1401   else
1402     {
1403       if (!check_service_deactivated (context, connection,
1404                                       service_name, base_service))
1405         goto out;
1406     }
1407
1408   retval = TRUE;
1409   
1410  out:
1411   if (message)
1412     dbus_message_unref (message);
1413   
1414   return retval;
1415 }
1416
1417 static dbus_bool_t
1418 check_got_error (BusContext     *context,
1419                  DBusConnection *connection,
1420                  const char     *first_error_name,
1421                  ...)
1422 {
1423   DBusMessage *message;
1424   dbus_bool_t retval;
1425   va_list ap;
1426   dbus_bool_t error_found;
1427   const char *error_name;
1428   
1429   retval = FALSE;
1430   
1431   message = pop_message_waiting_for_memory (connection);
1432   if (message == NULL)
1433     {
1434       _dbus_warn ("Did not get an expected error\n");
1435       goto out;
1436     }
1437
1438   if (!dbus_message_get_is_error (message))
1439     {
1440       _dbus_warn ("Expected an error, got %s\n",
1441                   dbus_message_get_name (message));
1442       goto out;
1443     }
1444
1445   error_found = FALSE;
1446
1447   va_start (ap, first_error_name);
1448   error_name = first_error_name;
1449   while (error_name != NULL)
1450     {
1451       if (dbus_message_name_is (message, error_name))
1452         {
1453           error_found = TRUE;
1454           break;
1455         }
1456       error_name = va_arg (ap, char*);
1457     }
1458   va_end (ap);
1459
1460   if (!error_found)
1461     {
1462       _dbus_warn ("Expected error %s or other, got %s instead\n",
1463                   first_error_name,
1464                   dbus_message_get_name (message));
1465       goto out;
1466     }
1467
1468   retval = TRUE;
1469   
1470  out:
1471   if (message)
1472     dbus_message_unref (message);
1473   
1474   return retval;
1475 }
1476           
1477 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1478
1479 /* returns TRUE if the correct thing happens,
1480  * but the correct thing may include OOM errors.
1481  */
1482 static dbus_bool_t
1483 check_existent_service_activation (BusContext     *context,
1484                                    DBusConnection *connection)
1485 {
1486   DBusMessage *message;
1487   dbus_int32_t serial;
1488   dbus_bool_t retval;
1489   DBusError error;
1490   char *base_service;
1491
1492   base_service = NULL;
1493   
1494   dbus_error_init (&error);
1495   
1496   message = dbus_message_new (DBUS_SERVICE_DBUS,
1497                               DBUS_MESSAGE_ACTIVATE_SERVICE);
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                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1542       goto out;
1543     }
1544
1545   _dbus_verbose ("Received %s on %p after sending %s\n",
1546                  dbus_message_get_name (message), connection,
1547                  DBUS_MESSAGE_ACTIVATE_SERVICE);
1548
1549   if (dbus_message_get_is_error (message))
1550     {
1551       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1552         {
1553           _dbus_warn ("Message has wrong sender %s\n",
1554                       dbus_message_get_sender (message) ?
1555                       dbus_message_get_sender (message) : "(none)");
1556           goto out;
1557         }
1558       
1559       if (dbus_message_name_is (message,
1560                                 DBUS_ERROR_NO_MEMORY))
1561         {
1562           ; /* good, this is a valid response */
1563         }
1564       else if (dbus_message_name_is (message,
1565                                      DBUS_ERROR_SPAWN_CHILD_EXITED))
1566         {
1567           ; /* good, this is expected also */
1568         }
1569       else
1570         {
1571           _dbus_warn ("Did not expect error %s\n",
1572                       dbus_message_get_name (message));
1573           goto out;
1574         }
1575     }
1576   else
1577     {
1578       dbus_bool_t got_service_deleted;
1579       dbus_bool_t got_error;
1580       
1581       if (!check_base_service_activated (context, connection,
1582                                          message, &base_service))
1583         goto out;
1584
1585       dbus_message_unref (message);
1586       message = NULL;
1587
1588       /* We may need to block here for the test service to exit or finish up */
1589       block_connection_until_message_from_bus (context, connection);
1590       
1591       message = dbus_connection_borrow_message (connection);
1592       if (message == NULL)
1593         {
1594           _dbus_warn ("Did not receive any messages after base service creation notification\n");
1595           goto out;
1596         }
1597
1598       got_service_deleted = dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED);
1599       got_error = dbus_message_get_is_error (message);
1600       
1601       dbus_connection_return_message (connection, message);
1602       message = NULL;
1603
1604       if (got_error)
1605         {
1606           if (!check_got_error (context, connection,
1607                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
1608                                 DBUS_ERROR_NO_MEMORY,
1609                                 NULL))
1610             goto out;
1611
1612           /* A service deleted should be coming along now after this error.
1613            * We can also get the error *after* the service deleted.
1614            */
1615           got_service_deleted = TRUE;
1616         }
1617       
1618       if (got_service_deleted)
1619         {
1620           /* The service started up and got a base address, but then
1621            * failed to register under EXISTENT_SERVICE_NAME
1622            */
1623           CheckServiceDeletedData csdd;
1624           
1625           csdd.expected_service_name = base_service;
1626           csdd.failed = FALSE;
1627           bus_test_clients_foreach (check_service_deleted_foreach,
1628                                     &csdd);
1629
1630           if (csdd.failed)
1631             goto out;
1632
1633           /* Now we should get an error about the service exiting
1634            * if we didn't get it before.
1635            */
1636           if (!got_error)
1637             {
1638               block_connection_until_message_from_bus (context, connection);
1639               
1640               /* and process everything again */
1641               bus_test_run_everything (context);
1642               
1643               if (!check_got_error (context, connection,
1644                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
1645                                     NULL))
1646                 goto out;
1647             }
1648         }
1649       else
1650         {
1651           message = pop_message_waiting_for_memory (connection);
1652           if (message == NULL)
1653             {
1654               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
1655               goto out;
1656             }
1657           
1658           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
1659                                         base_service, message))
1660             goto out;
1661           
1662           dbus_message_unref (message);
1663           message = NULL;
1664
1665
1666           if (!check_no_leftovers (context))
1667             {
1668               _dbus_warn ("Messages were left over after successful activation\n");
1669               goto out;
1670             }
1671
1672           if (!check_send_exit_to_service (context, connection,
1673                                            EXISTENT_SERVICE_NAME, base_service))
1674             goto out;
1675         }
1676     }
1677   
1678   retval = TRUE;
1679   
1680  out:
1681   if (message)
1682     dbus_message_unref (message);
1683
1684   if (base_service)
1685     dbus_free (base_service);
1686   
1687   return retval;
1688 }
1689
1690 /* returns TRUE if the correct thing happens,
1691  * but the correct thing may include OOM errors.
1692  */
1693 static dbus_bool_t
1694 check_segfault_service_activation (BusContext     *context,
1695                                    DBusConnection *connection)
1696 {
1697   DBusMessage *message;
1698   dbus_int32_t serial;
1699   dbus_bool_t retval;
1700   DBusError error;
1701   
1702   dbus_error_init (&error);
1703   
1704   message = dbus_message_new (DBUS_SERVICE_DBUS,
1705                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1706
1707   if (message == NULL)
1708     return TRUE;
1709
1710   if (!dbus_message_append_args (message,
1711                                  DBUS_TYPE_STRING,
1712                                  "org.freedesktop.DBus.TestSuiteSegfaultService",
1713                                  DBUS_TYPE_UINT32, 0,
1714                                  DBUS_TYPE_INVALID))
1715     {
1716       dbus_message_unref (message);
1717       return TRUE;
1718     }
1719   
1720   if (!dbus_connection_send (connection, message, &serial))
1721     {
1722       dbus_message_unref (message);
1723       return TRUE;
1724     }
1725
1726   dbus_message_unref (message);
1727   message = NULL;
1728
1729   bus_test_run_everything (context);
1730   block_connection_until_message_from_bus (context, connection);
1731   bus_test_run_everything (context);
1732
1733   if (!dbus_connection_get_is_connected (connection))
1734     {
1735       _dbus_verbose ("connection was disconnected\n");
1736       return TRUE;
1737     }
1738   
1739   retval = FALSE;
1740   
1741   message = pop_message_waiting_for_memory (connection);
1742   if (message == NULL)
1743     {
1744       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1745                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1746       goto out;
1747     }
1748
1749   _dbus_verbose ("Received %s on %p\n",
1750                  dbus_message_get_name (message), connection);
1751
1752   if (dbus_message_get_is_error (message))
1753     {
1754       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1755         {
1756           _dbus_warn ("Message has wrong sender %s\n",
1757                       dbus_message_get_sender (message) ?
1758                       dbus_message_get_sender (message) : "(none)");
1759           goto out;
1760         }
1761       
1762       if (dbus_message_name_is (message,
1763                                 DBUS_ERROR_NO_MEMORY))
1764         {
1765           ; /* good, this is a valid response */
1766         }
1767       else if (dbus_message_name_is (message,
1768                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED))
1769         {
1770           ; /* good, this is expected also */
1771         }
1772       else
1773         {
1774           _dbus_warn ("Did not expect error %s\n",
1775                       dbus_message_get_name (message));
1776           goto out;
1777         }
1778     }
1779   else
1780     {
1781       _dbus_warn ("Did not expect to successfully activate segfault service\n");
1782       goto out;
1783     }
1784
1785   retval = TRUE;
1786   
1787  out:
1788   if (message)
1789     dbus_message_unref (message);
1790   
1791   return retval;
1792 }
1793
1794 typedef struct
1795 {
1796   Check1Func func;
1797   BusContext *context;
1798 } Check1Data;
1799
1800 static dbus_bool_t
1801 check_oom_check1_func (void *data)
1802 {
1803   Check1Data *d = data;
1804
1805   if (! (* d->func) (d->context))
1806     return FALSE;
1807   
1808   if (!check_no_leftovers (d->context))
1809     {
1810       _dbus_warn ("Messages were left over, should be covered by test suite\n");
1811       return FALSE;
1812     }
1813
1814   return TRUE;
1815 }
1816
1817 static void
1818 check1_try_iterations (BusContext *context,
1819                        const char *description,
1820                        Check1Func  func)
1821 {
1822   Check1Data d;
1823
1824   d.func = func;
1825   d.context = context;
1826
1827   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
1828                                 &d))
1829     _dbus_assert_not_reached ("test failed");
1830 }
1831
1832 typedef struct
1833 {
1834   Check2Func func;
1835   BusContext *context;
1836   DBusConnection *connection;
1837 } Check2Data;
1838
1839 static dbus_bool_t
1840 check_oom_check2_func (void *data)
1841 {
1842   Check2Data *d = data;
1843
1844   if (! (* d->func) (d->context, d->connection))
1845     return FALSE;
1846   
1847   if (!check_no_leftovers (d->context))
1848     {
1849       _dbus_warn ("Messages were left over, should be covered by test suite");
1850       return FALSE;
1851     }
1852
1853   return TRUE;
1854 }
1855
1856 static void
1857 check2_try_iterations (BusContext     *context,
1858                        DBusConnection *connection,
1859                        const char     *description,
1860                        Check2Func      func)
1861 {
1862   Check2Data d;
1863
1864   d.func = func;
1865   d.context = context;
1866   d.connection = connection;
1867   
1868   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
1869                                 &d))
1870     _dbus_assert_not_reached ("test failed");
1871 }
1872
1873 dbus_bool_t
1874 bus_dispatch_test (const DBusString *test_data_dir)
1875 {
1876   BusContext *context;
1877   DBusConnection *foo;
1878   DBusConnection *bar;
1879   DBusConnection *baz;
1880   DBusError error;
1881
1882   dbus_error_init (&error);
1883   
1884   context = bus_context_new_test (test_data_dir,
1885                                   "valid-config-files/debug-allow-all.conf");
1886   if (context == NULL)
1887     return FALSE;
1888   
1889   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1890   if (foo == NULL)
1891     _dbus_assert_not_reached ("could not alloc connection");
1892
1893   if (!bus_setup_debug_client (foo))
1894     _dbus_assert_not_reached ("could not set up connection");
1895
1896   if (!check_hello_message (context, foo))
1897     _dbus_assert_not_reached ("hello message failed");
1898   
1899   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
1900   if (bar == NULL)
1901     _dbus_assert_not_reached ("could not alloc connection");
1902
1903   if (!bus_setup_debug_client (bar))
1904     _dbus_assert_not_reached ("could not set up connection");
1905
1906   if (!check_hello_message (context, bar))
1907     _dbus_assert_not_reached ("hello message failed");
1908   
1909   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
1910   if (baz == NULL)
1911     _dbus_assert_not_reached ("could not alloc connection");
1912
1913   if (!bus_setup_debug_client (baz))
1914     _dbus_assert_not_reached ("could not set up connection");
1915
1916   if (!check_hello_message (context, baz))
1917     _dbus_assert_not_reached ("hello message failed");
1918
1919   if (!check_no_leftovers (context))
1920     {
1921       _dbus_warn ("Messages were left over after setting up initial connections");
1922       _dbus_assert_not_reached ("initial connection setup failed");
1923     }
1924   
1925   check1_try_iterations (context, "create_and_hello_sha1",
1926                          check_hello_connection);
1927   
1928   check2_try_iterations (context, foo, "nonexistent_service_activation",
1929                          check_nonexistent_service_activation);
1930
1931   check2_try_iterations (context, foo, "segfault_service_activation",
1932                          check_segfault_service_activation);
1933   
1934   check2_try_iterations (context, foo, "existent_service_activation",
1935                          check_existent_service_activation);
1936   
1937   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1938
1939   kill_client_connection_unchecked (foo);
1940   kill_client_connection_unchecked (bar);
1941   kill_client_connection_unchecked (baz);
1942
1943   bus_context_unref (context);
1944   
1945   return TRUE;
1946 }
1947
1948 dbus_bool_t
1949 bus_dispatch_sha1_test (const DBusString *test_data_dir)
1950 {
1951   BusContext *context;
1952   DBusConnection *foo;
1953   DBusError error;
1954
1955   dbus_error_init (&error);
1956   
1957   /* Test SHA1 authentication */
1958   _dbus_verbose ("Testing SHA1 context\n");
1959   
1960   context = bus_context_new_test (test_data_dir,
1961                                   "valid-config-files/debug-allow-all.conf");
1962   if (context == NULL)
1963     return FALSE;
1964
1965   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1966   if (foo == NULL)
1967     _dbus_assert_not_reached ("could not alloc connection");
1968
1969   if (!bus_setup_debug_client (foo))
1970     _dbus_assert_not_reached ("could not set up connection");
1971
1972   if (!check_hello_message (context, foo))
1973     _dbus_assert_not_reached ("hello message failed");
1974
1975   if (!check_no_leftovers (context))
1976     {
1977       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection");
1978       _dbus_assert_not_reached ("initial connection setup failed");
1979     }
1980   
1981   check1_try_iterations (context, "create_and_hello",
1982                          check_hello_connection);
1983
1984   kill_client_connection_unchecked (foo);
1985
1986   bus_context_unref (context);
1987
1988   return TRUE;
1989 }
1990
1991 #endif /* DBUS_BUILD_TESTS */