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