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