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