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