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