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