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