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