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