ce0d71c69f6c4dfaf50f7e95ab334c70836cf048
[platform/upstream/dbus.git] / bus / dispatch.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dispatch.c  Message dispatcher
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003  Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dispatch.h"
26 #include "connection.h"
27 #include "driver.h"
28 #include "services.h"
29 #include "utils.h"
30 #include "bus.h"
31 #include "test.h"
32 #include <dbus/dbus-internals.h>
33 #include <string.h>
34
35 static int message_handler_slot = -1;
36 static int message_handler_slot_refcount;
37
38 typedef struct
39 {
40   DBusMessage    *message;
41   BusTransaction *transaction;
42   DBusError      *error;
43 } SendMessageData;
44
45 static dbus_bool_t
46 send_one_message (DBusConnection *connection, void *data)
47 {
48   SendMessageData *d = data;
49   
50   if (!bus_connection_is_active (connection))
51     return TRUE;
52
53   if (!bus_transaction_send_message (d->transaction,
54                                      connection,
55                                      d->message))
56     {
57       BUS_SET_OOM (d->error);
58       return FALSE;
59     }
60
61   return TRUE;
62 }
63
64 dbus_bool_t
65 bus_dispatch_broadcast_message (BusTransaction *transaction,
66                                 DBusMessage    *message,
67                                 DBusError      *error)
68 {
69   DBusError tmp_error;
70   SendMessageData d;
71   BusConnections *connections;
72
73   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
74   
75   _dbus_assert (dbus_message_get_sender (message) != NULL);
76
77   connections = bus_transaction_get_connections (transaction);
78   
79   dbus_error_init (&tmp_error);
80   d.message = message;
81   d.transaction = transaction;
82   d.error = &tmp_error;
83   
84   bus_connections_foreach (connections, send_one_message, &d);
85
86   if (dbus_error_is_set (&tmp_error))
87     {
88       dbus_move_error (&tmp_error, error);
89       return FALSE;
90     }
91   else
92     return TRUE;
93 }
94
95 static dbus_bool_t
96 send_service_nonexistent_error (BusTransaction *transaction,
97                                 DBusConnection *connection,
98                                 const char     *service_name,
99                                 DBusMessage    *in_reply_to,
100                                 DBusError      *error)
101 {
102   DBusMessage *error_reply;
103   DBusString error_message;
104   const char *error_str;
105
106   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
107   
108   /* Trying to send a message to a non-existant service,
109    * bounce back an error message.
110    */
111           
112   if (!_dbus_string_init (&error_message))
113     {
114       BUS_SET_OOM (error);
115       return FALSE;
116     }
117
118   if (!_dbus_string_append (&error_message, "Service \"") ||
119       !_dbus_string_append (&error_message, service_name) ||
120       !_dbus_string_append (&error_message, "\" does not exist"))
121     {
122       _dbus_string_free (&error_message);
123       BUS_SET_OOM (error);
124       return FALSE;
125     }
126               
127   error_str = _dbus_string_get_const_data (&error_message);
128   error_reply = dbus_message_new_error_reply (in_reply_to,
129                                               DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
130                                               error_str);
131
132   _dbus_string_free (&error_message);
133               
134   if (error_reply == NULL)
135     {
136       BUS_SET_OOM (error);
137       return FALSE;
138     }
139
140   if (!dbus_message_set_sender (error_reply, DBUS_SERVICE_DBUS))
141     {
142       dbus_message_unref (error_reply);
143       BUS_SET_OOM (error);
144       return FALSE;
145     }      
146   
147   if (!bus_transaction_send_message (transaction, connection, error_reply))
148     {
149       dbus_message_unref (error_reply);
150       BUS_SET_OOM (error);
151       return FALSE;
152     }
153               
154   dbus_message_unref (error_reply);
155
156   return TRUE;
157 }
158
159 static void
160 bus_dispatch (DBusConnection *connection,
161               DBusMessage    *message)
162 {
163   const char *sender, *service_name, *message_name;
164   DBusError error;
165   BusTransaction *transaction;
166   BusContext *context;
167   
168   transaction = NULL;
169   dbus_error_init (&error);
170   
171   context = bus_connection_get_context (connection);
172   _dbus_assert (context != NULL);
173   
174   /* If we can't even allocate an OOM error, we just go to sleep
175    * until we can.
176    */
177   while (!bus_connection_preallocate_oom_error (connection))
178     _dbus_wait_for_memory ();
179   
180   /* Ref connection in case we disconnect it at some point in here */
181   dbus_connection_ref (connection);
182
183   service_name = dbus_message_get_service (message);
184   message_name = dbus_message_get_name (message);
185
186   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
187
188   _dbus_verbose ("DISPATCH: %s to %s\n",
189                  message_name, service_name ? service_name : "peer");
190   
191   /* If service_name is NULL, this is a message to the bus daemon, not intended
192    * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these
193    * immediately, especially disconnection messages.
194    */
195   if (service_name == NULL)
196     {      
197       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
198         bus_connection_disconnected (connection);
199
200       /* DBusConnection also handles some of these automatically, we leave
201        * it to do so.
202        */
203       goto out;
204     }
205
206   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
207   
208   /* Create our transaction */
209   transaction = bus_transaction_new (context);
210   if (transaction == NULL)
211     {
212       BUS_SET_OOM (&error);
213       goto out;
214     }
215   
216   /* Assign a sender to the message */
217   if (bus_connection_is_active (connection))
218     {
219       sender = bus_connection_get_name (connection);
220       _dbus_assert (sender != NULL);
221
222       if (!dbus_message_set_sender (message, sender))
223         {
224           BUS_SET_OOM (&error);
225           goto out;
226         }
227
228       /* We need to refetch the service name here, because
229        * dbus_message_set_sender can cause the header to be
230        * reallocated, and thus the service_name pointer will become
231        * invalid.
232        */
233       service_name = dbus_message_get_service (message);
234     }
235
236   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
237     {
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     }
246   /* FIXME what if we un-special-case this service and just have a flag
247    * on services that all service owners will get messages to it, not just
248    * the primary owner.
249    */
250   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
251     {
252       if (!bus_dispatch_broadcast_message (transaction, message, &error))
253         goto out;
254     }
255   else  /* route to named service */
256     {
257       DBusString service_string;
258       BusService *service;
259       BusRegistry *registry;
260
261       registry = bus_connection_get_registry (connection);
262       
263       _dbus_string_init_const (&service_string, service_name);
264       service = bus_registry_lookup (registry, &service_string);
265
266       if (service == NULL)
267         {
268           if (!send_service_nonexistent_error (transaction, connection,
269                                                service_name,
270                                                message, &error))
271             goto out;
272         }
273       else
274         {
275           _dbus_assert (bus_service_get_primary_owner (service) != NULL);
276       
277           /* Dispatch the message */
278           if (!bus_transaction_send_message (transaction,
279                                              bus_service_get_primary_owner (service),
280                                              message))
281             {
282               BUS_SET_OOM (&error);
283               goto out;
284             }
285         }
286     }
287   
288  out:
289   if (dbus_error_is_set (&error))
290     {
291       if (!dbus_connection_get_is_connected (connection))
292         {
293           /* If we disconnected it, we won't bother to send it any error
294            * messages.
295            */
296         }
297       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
298         {
299           bus_connection_send_oom_error (connection, message);
300
301           /* cancel transaction due to OOM */
302           if (transaction != NULL)
303             {
304               bus_transaction_cancel_and_free (transaction);
305               transaction = NULL;
306             }
307         }
308       else
309         {
310           /* Try to send the real error, if no mem to do that, send
311            * the OOM error
312            */
313           _dbus_assert (transaction != NULL);
314           
315           if (!bus_transaction_send_error_reply (transaction, connection,
316                                                  &error, message))
317             {
318               bus_connection_send_oom_error (connection, message);
319
320               /* cancel transaction due to OOM */
321               if (transaction != NULL)
322                 {
323                   bus_transaction_cancel_and_free (transaction);
324                   transaction = NULL;
325                 }
326             }
327         }
328       
329       dbus_error_free (&error);
330     }
331
332   if (transaction != NULL)
333     {
334       bus_transaction_execute_and_free (transaction);
335     }
336
337   dbus_connection_unref (connection);
338 }
339
340 static DBusHandlerResult
341 bus_dispatch_message_handler (DBusMessageHandler *handler,
342                               DBusConnection     *connection,
343                               DBusMessage        *message,
344                               void               *user_data)
345 {
346   bus_dispatch (connection, message);
347   
348   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
349 }
350
351 static dbus_bool_t
352 message_handler_slot_ref (void)
353 {
354   if (message_handler_slot < 0)
355     {
356       message_handler_slot = dbus_connection_allocate_data_slot ();
357       
358       if (message_handler_slot < 0)
359         return FALSE;
360
361       _dbus_assert (message_handler_slot_refcount == 0);
362     }  
363
364   message_handler_slot_refcount += 1;
365
366   return TRUE;
367 }
368
369 static void
370 message_handler_slot_unref (void)
371 {
372   _dbus_assert (message_handler_slot_refcount > 0);
373
374   message_handler_slot_refcount -= 1;
375   
376   if (message_handler_slot_refcount == 0)
377     {
378       dbus_connection_free_data_slot (message_handler_slot);
379       message_handler_slot = -1;
380     }
381 }
382
383 static void
384 free_message_handler (void *data)
385 {
386   DBusMessageHandler *handler = data;
387   
388   _dbus_assert (message_handler_slot >= 0);
389   _dbus_assert (message_handler_slot_refcount > 0);
390   
391   dbus_message_handler_unref (handler);
392   message_handler_slot_unref ();
393 }
394
395 dbus_bool_t
396 bus_dispatch_add_connection (DBusConnection *connection)
397 {
398   DBusMessageHandler *handler;
399
400   if (!message_handler_slot_ref ())
401     return FALSE;
402   
403   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
404   if (handler == NULL)
405     {
406       message_handler_slot_unref ();
407       return FALSE;
408     }    
409   
410   if (!dbus_connection_add_filter (connection, handler))
411     {
412       dbus_message_handler_unref (handler);
413       message_handler_slot_unref ();
414       
415       return FALSE;
416     }
417
418   _dbus_assert (message_handler_slot >= 0);
419   _dbus_assert (message_handler_slot_refcount > 0);
420   
421   if (!dbus_connection_set_data (connection,
422                                  message_handler_slot,
423                                  handler,
424                                  free_message_handler))
425     {
426       dbus_message_handler_unref (handler);
427       message_handler_slot_unref ();
428
429       return FALSE;
430     }
431
432   return TRUE;
433 }
434
435 void
436 bus_dispatch_remove_connection (DBusConnection *connection)
437 {
438   /* Here we tell the bus driver that we want to get off. */
439   bus_driver_remove_connection (connection);
440
441   dbus_connection_set_data (connection,
442                             message_handler_slot,
443                             NULL, NULL);
444 }
445
446 #ifdef DBUS_BUILD_TESTS
447
448 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
449 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
450                                     DBusConnection *connection);
451
452 static dbus_bool_t check_no_leftovers (BusContext *context);
453
454 typedef struct
455 {
456   const char *expected_service_name;
457   dbus_bool_t failed;
458 } CheckServiceDeletedData;
459
460 static dbus_bool_t
461 check_service_deleted_foreach (DBusConnection *connection,
462                                void           *data)
463 {
464   CheckServiceDeletedData *d = data;
465   DBusMessage *message;
466   DBusError error;
467   char *service_name;
468
469   dbus_error_init (&error);
470   d->failed = TRUE;
471   service_name = NULL;
472   
473   message = dbus_connection_pop_message (connection);
474   if (message == NULL)
475     {
476       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
477                   connection, DBUS_MESSAGE_SERVICE_DELETED);
478       goto out;
479     }
480   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
481     {
482       _dbus_warn ("Received message %s on %p, expecting %s\n",
483                   dbus_message_get_name (message),
484                   connection, DBUS_MESSAGE_SERVICE_DELETED);
485       goto out;
486     }
487   else
488     {
489       if (!dbus_message_get_args (message, &error,
490                                   DBUS_TYPE_STRING, &service_name,
491                                   DBUS_TYPE_INVALID))
492         {
493           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
494             {
495               _dbus_verbose ("no memory to get service name arg\n");
496             }
497           else
498             {
499               _dbus_assert (dbus_error_is_set (&error));
500               _dbus_warn ("Did not get the expected single string argument\n");
501               goto out;
502             }
503         }
504       else if (strcmp (service_name, d->expected_service_name) != 0)
505         {
506           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
507                       d->expected_service_name,
508                       service_name);
509           goto out;
510         }
511     }
512
513   d->failed = FALSE;
514   
515  out:
516   dbus_free (service_name);
517   dbus_error_free (&error);
518   
519   if (message)
520     dbus_message_unref (message);
521
522   return !d->failed;
523 }
524
525 static void
526 kill_client_connection (BusContext     *context,
527                         DBusConnection *connection)
528 {
529   char *base_service;
530   const char *s;
531   CheckServiceDeletedData csdd;
532
533   _dbus_verbose ("killing connection %p\n", connection);
534   
535   s = dbus_bus_get_base_service (connection);
536   _dbus_assert (s != NULL);
537
538   while ((base_service = _dbus_strdup (s)) == NULL)
539     _dbus_wait_for_memory ();
540
541   dbus_connection_ref (connection);
542   
543   /* kick in the disconnect handler that unrefs the connection */
544   dbus_connection_disconnect (connection);
545
546   bus_test_run_everything (context);
547   
548   _dbus_assert (bus_test_client_listed (connection));
549   
550   /* Run disconnect handler in test.c */
551   if (bus_connection_dispatch_one_message (connection))
552     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
553   
554   _dbus_assert (!dbus_connection_get_is_connected (connection));
555   dbus_connection_unref (connection);
556   connection = NULL;
557   _dbus_assert (!bus_test_client_listed (connection));
558   
559   csdd.expected_service_name = base_service;
560   csdd.failed = FALSE;
561
562   bus_test_clients_foreach (check_service_deleted_foreach,
563                             &csdd);
564
565   dbus_free (base_service);
566   
567   if (csdd.failed)
568     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
569   
570   if (!check_no_leftovers (context))
571     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
572 }
573
574 static void
575 kill_client_connection_unchecked (DBusConnection *connection)
576 {
577   /* This kills the connection without expecting it to affect
578    * the rest of the bus.
579    */  
580   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
581
582   dbus_connection_ref (connection);
583   dbus_connection_disconnect (connection);
584   /* dispatching disconnect handler will unref once */
585   if (bus_connection_dispatch_one_message (connection))
586     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
587   dbus_connection_unref (connection);
588   _dbus_assert (!bus_test_client_listed (connection));
589 }
590
591 typedef struct
592 {
593   dbus_bool_t failed;
594 } CheckNoMessagesData;
595
596 static dbus_bool_t
597 check_no_messages_foreach (DBusConnection *connection,
598                            void           *data)
599 {
600   CheckNoMessagesData *d = data;
601   DBusMessage *message;
602
603   message = dbus_connection_pop_message (connection);
604   if (message != NULL)
605     {
606       _dbus_warn ("Received message %s on %p, expecting no messages\n",
607                   dbus_message_get_name (message), connection);
608       d->failed = TRUE;
609     }
610
611   if (message)
612     dbus_message_unref (message);
613   return !d->failed;
614 }
615
616 typedef struct
617 {
618   DBusConnection *skip_connection;
619   const char *expected_service_name;
620   dbus_bool_t failed;
621 } CheckServiceCreatedData;
622
623 static dbus_bool_t
624 check_service_created_foreach (DBusConnection *connection,
625                                void           *data)
626 {
627   CheckServiceCreatedData *d = data;
628   DBusMessage *message;
629   DBusError error;
630   char *service_name;
631
632   if (connection == d->skip_connection)
633     return TRUE;
634
635   dbus_error_init (&error);
636   d->failed = TRUE;
637   service_name = NULL;
638   
639   message = dbus_connection_pop_message (connection);
640   if (message == NULL)
641     {
642       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
643                   connection, DBUS_MESSAGE_SERVICE_CREATED);
644       goto out;
645     }
646   else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
647     {
648       _dbus_warn ("Received message %s on %p, expecting %s\n",
649                   dbus_message_get_name (message),
650                   connection, DBUS_MESSAGE_SERVICE_CREATED);
651       goto out;
652     }
653   else
654     {
655       if (!dbus_message_get_args (message, &error,
656                                   DBUS_TYPE_STRING, &service_name,
657                                   DBUS_TYPE_INVALID))
658         {
659           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
660             {
661               _dbus_verbose ("no memory to get service name arg\n");
662             }
663           else
664             {
665               _dbus_assert (dbus_error_is_set (&error));
666               _dbus_warn ("Did not get the expected single string argument\n");
667               goto out;
668             }
669         }
670       else if (strcmp (service_name, d->expected_service_name) != 0)
671         {
672           _dbus_warn ("expected creation of service %s, got creation of %s\n",
673                       d->expected_service_name,
674                       service_name);
675           goto out;
676         }
677     }
678
679   d->failed = FALSE;
680   
681  out:
682   dbus_free (service_name);
683   dbus_error_free (&error);
684   
685   if (message)
686     dbus_message_unref (message);
687
688   return !d->failed;
689 }
690
691 static dbus_bool_t
692 check_no_leftovers (BusContext *context)
693 {
694   CheckNoMessagesData nmd;
695
696   nmd.failed = FALSE;
697   bus_test_clients_foreach (check_no_messages_foreach,
698                             &nmd);
699   
700   if (nmd.failed)
701     return FALSE;
702   else
703     return TRUE;
704 }
705
706 /* returns TRUE if the correct thing happens,
707  * but the correct thing may include OOM errors.
708  */
709 static dbus_bool_t
710 check_hello_message (BusContext     *context,
711                      DBusConnection *connection)
712 {
713   DBusMessage *message;
714   dbus_int32_t serial;
715   dbus_bool_t retval;
716   DBusError error;
717   char *name;
718   char *acquired;
719   
720   dbus_error_init (&error);
721   name = NULL;
722   acquired = NULL;
723   
724   message = dbus_message_new (DBUS_SERVICE_DBUS,
725                               DBUS_MESSAGE_HELLO);
726
727   if (message == NULL)
728     return TRUE;
729
730   if (!dbus_connection_send (connection, message, &serial))
731     {
732       dbus_message_unref (message);
733       return TRUE;
734     }
735
736   dbus_message_unref (message);
737   message = NULL;
738
739   bus_test_run_everything (context);
740
741   if (!dbus_connection_get_is_connected (connection))
742     {
743       _dbus_verbose ("connection was disconnected\n");
744       return TRUE;
745     }
746   
747   retval = FALSE;
748   
749   message = dbus_connection_pop_message (connection);
750   if (message == NULL)
751     {
752       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
753                   DBUS_MESSAGE_HELLO, serial, connection);
754       goto out;
755     }
756
757   _dbus_verbose ("Received %s on %p\n",
758                  dbus_message_get_name (message), connection);
759
760   if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
761     {
762       _dbus_warn ("Message has wrong sender %s\n",
763                   dbus_message_get_sender (message) ?
764                   dbus_message_get_sender (message) : "(none)");
765       goto out;
766     }
767   
768   if (dbus_message_get_is_error (message))
769     {
770       if (dbus_message_name_is (message,
771                                 DBUS_ERROR_NO_MEMORY))
772         {
773           ; /* good, this is a valid response */
774         }
775       else
776         {
777           _dbus_warn ("Did not expect error %s\n",
778                       dbus_message_get_name (message));
779           goto out;
780         }
781     }
782   else
783     {
784       CheckServiceCreatedData scd;
785       
786       if (dbus_message_name_is (message,
787                                 DBUS_MESSAGE_HELLO))
788         {
789           ; /* good, expected */
790         }
791       else
792         {
793           _dbus_warn ("Did not expect reply %s\n",
794                       dbus_message_get_name (message));
795           goto out;
796         }
797
798     retry_get_hello_name:
799       if (!dbus_message_get_args (message, &error,
800                                   DBUS_TYPE_STRING, &name,
801                                   DBUS_TYPE_INVALID))
802         {
803           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
804             {
805               _dbus_verbose ("no memory to get service name arg from hello\n");
806               dbus_error_free (&error);
807               _dbus_wait_for_memory ();
808               goto retry_get_hello_name;
809             }
810           else
811             {
812               _dbus_assert (dbus_error_is_set (&error));
813               _dbus_warn ("Did not get the expected single string argument to hello\n");
814               goto out;
815             }
816         }
817
818       _dbus_verbose ("Got hello name: %s\n", name);
819
820       while (!dbus_bus_set_base_service (connection, name))
821         _dbus_wait_for_memory ();
822       
823       scd.skip_connection = NULL;
824       scd.failed = FALSE;
825       scd.expected_service_name = name;
826       bus_test_clients_foreach (check_service_created_foreach,
827                                 &scd);
828       
829       if (scd.failed)
830         goto out;
831       
832       /* Client should also have gotten ServiceAcquired */
833       dbus_message_unref (message);
834       message = dbus_connection_pop_message (connection);
835       if (message == NULL)
836         {
837           _dbus_warn ("Expecting %s, got nothing\n",
838                       DBUS_MESSAGE_SERVICE_ACQUIRED);
839           goto out;
840         }
841       
842     retry_get_acquired_name:
843       if (!dbus_message_get_args (message, &error,
844                                   DBUS_TYPE_STRING, &acquired,
845                                   DBUS_TYPE_INVALID))
846         {
847           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
848             {
849               _dbus_verbose ("no memory to get service name arg from acquired\n");
850               dbus_error_free (&error);
851               _dbus_wait_for_memory ();
852               goto retry_get_acquired_name;
853             }
854           else
855             {
856               _dbus_assert (dbus_error_is_set (&error));
857               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
858               goto out;
859             }
860         }
861
862       _dbus_verbose ("Got acquired name: %s\n", acquired);
863
864       if (strcmp (acquired, name) != 0)
865         {
866           _dbus_warn ("Acquired name is %s but expected %s\n",
867                       acquired, name);
868           goto out;
869         }
870     }
871
872   if (!check_no_leftovers (context))
873     goto out;
874   
875   retval = TRUE;
876   
877  out:
878   dbus_error_free (&error);
879   
880   dbus_free (name);
881   dbus_free (acquired);
882   
883   if (message)
884     dbus_message_unref (message);
885   
886   return retval;
887 }
888
889 /* returns TRUE if the correct thing happens,
890  * but the correct thing may include OOM errors.
891  */
892 static dbus_bool_t
893 check_hello_connection (BusContext *context)
894 {
895   DBusConnection *connection;
896   DBusError error;
897
898   dbus_error_init (&error);
899
900   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
901   if (connection == NULL)
902     {
903       _DBUS_ASSERT_ERROR_IS_SET (&error);
904       dbus_error_free (&error);
905       return TRUE;
906     }
907
908   if (!bus_setup_debug_client (connection))
909     {
910       dbus_connection_disconnect (connection);
911       dbus_connection_unref (connection);
912       return TRUE;
913     }
914
915   if (!check_hello_message (context, connection))
916     return FALSE;
917
918   if (dbus_bus_get_base_service (connection) == NULL)
919     {
920       /* We didn't successfully register, so we can't
921        * do the usual kill_client_connection() checks
922        */
923       kill_client_connection_unchecked (connection);
924     }
925   else
926     {
927       kill_client_connection (context, connection);
928     }
929
930   return TRUE;
931 }
932
933 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
934
935 /* returns TRUE if the correct thing happens,
936  * but the correct thing may include OOM errors.
937  */
938 static dbus_bool_t
939 check_nonexistent_service_activation (BusContext     *context,
940                                       DBusConnection *connection)
941 {
942   DBusMessage *message;
943   dbus_int32_t serial;
944   dbus_bool_t retval;
945   DBusError error;
946   
947   dbus_error_init (&error);
948   
949   message = dbus_message_new (DBUS_SERVICE_DBUS,
950                               DBUS_MESSAGE_ACTIVATE_SERVICE);
951
952   if (message == NULL)
953     return TRUE;
954
955   if (!dbus_message_append_args (message,
956                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
957                                  DBUS_TYPE_UINT32, 0,
958                                  DBUS_TYPE_INVALID))
959     {
960       dbus_message_unref (message);
961       return TRUE;
962     }
963   
964   if (!dbus_connection_send (connection, message, &serial))
965     {
966       dbus_message_unref (message);
967       return TRUE;
968     }
969
970   dbus_message_unref (message);
971   message = NULL;
972
973   bus_test_run_everything (context);
974
975   if (!dbus_connection_get_is_connected (connection))
976     {
977       _dbus_verbose ("connection was disconnected\n");
978       return TRUE;
979     }
980   
981   retval = FALSE;
982   
983   message = dbus_connection_pop_message (connection);
984   if (message == NULL)
985     {
986       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
987                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
988       goto out;
989     }
990
991   _dbus_verbose ("Received %s on %p\n",
992                  dbus_message_get_name (message), connection);
993
994   if (dbus_message_get_is_error (message))
995     {
996       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
997         {
998           _dbus_warn ("Message has wrong sender %s\n",
999                       dbus_message_get_sender (message) ?
1000                       dbus_message_get_sender (message) : "(none)");
1001           goto out;
1002         }
1003       
1004       if (dbus_message_name_is (message,
1005                                 DBUS_ERROR_NO_MEMORY))
1006         {
1007           ; /* good, this is a valid response */
1008         }
1009       else if (dbus_message_name_is (message,
1010                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1011         {
1012           ; /* good, this is expected also */
1013         }
1014       else
1015         {
1016           _dbus_warn ("Did not expect error %s\n",
1017                       dbus_message_get_name (message));
1018           goto out;
1019         }
1020     }
1021   else
1022     {
1023       _dbus_warn ("Did not expect to successfully activate %s\n",
1024                   NONEXISTENT_SERVICE_NAME);
1025       goto out;
1026     }
1027
1028   retval = TRUE;
1029   
1030  out:
1031   if (message)
1032     dbus_message_unref (message);
1033   
1034   return retval;
1035 }
1036
1037 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1038
1039 /* returns TRUE if the correct thing happens,
1040  * but the correct thing may include OOM errors.
1041  */
1042 static dbus_bool_t
1043 check_existent_service_activation (BusContext     *context,
1044                                    DBusConnection *connection)
1045 {
1046   DBusMessage *message;
1047   dbus_int32_t serial;
1048   dbus_bool_t retval;
1049   DBusError error;
1050   
1051   dbus_error_init (&error);
1052   
1053   message = dbus_message_new (DBUS_SERVICE_DBUS,
1054                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1055
1056   if (message == NULL)
1057     return TRUE;
1058
1059   if (!dbus_message_append_args (message,
1060                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
1061                                  DBUS_TYPE_UINT32, 0,
1062                                  DBUS_TYPE_INVALID))
1063     {
1064       dbus_message_unref (message);
1065       return TRUE;
1066     }
1067   
1068   if (!dbus_connection_send (connection, message, &serial))
1069     {
1070       dbus_message_unref (message);
1071       return TRUE;
1072     }
1073
1074   dbus_message_unref (message);
1075   message = NULL;
1076
1077   bus_test_run_everything (context);
1078
1079   if (dbus_connection_get_dispatch_status (connection) ==
1080       DBUS_DISPATCH_COMPLETE)
1081     /* now wait for the message bus to hear back from the activated service */
1082     bus_test_run_bus_loop (context);
1083   
1084   /* and process everything again */
1085   bus_test_run_everything (context);
1086
1087   if (!dbus_connection_get_is_connected (connection))
1088     {
1089       _dbus_verbose ("connection was disconnected\n");
1090       return TRUE;
1091     }
1092   
1093   retval = FALSE;
1094   
1095   message = dbus_connection_pop_message (connection);
1096   if (message == NULL)
1097     {
1098       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1099                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1100       goto out;
1101     }
1102
1103   _dbus_verbose ("Received %s on %p\n",
1104                  dbus_message_get_name (message), connection);
1105
1106   if (dbus_message_get_is_error (message))
1107     {
1108       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1109         {
1110           _dbus_warn ("Message has wrong sender %s\n",
1111                       dbus_message_get_sender (message) ?
1112                       dbus_message_get_sender (message) : "(none)");
1113           goto out;
1114         }
1115       
1116       if (dbus_message_name_is (message,
1117                                 DBUS_ERROR_NO_MEMORY))
1118         {
1119           ; /* good, this is a valid response */
1120         }
1121       else if (dbus_message_name_is (message,
1122                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1123         {
1124           ; /* good, this is expected also */
1125         }
1126       else
1127         {
1128           _dbus_warn ("Did not expect error %s\n",
1129                       dbus_message_get_name (message));
1130           goto out;
1131         }
1132     }
1133   else
1134     {
1135       _dbus_warn ("Did not expect to successfully activate %s\n",
1136                   EXISTENT_SERVICE_NAME);
1137       goto out;
1138     }
1139
1140   retval = TRUE;
1141   
1142  out:
1143   if (message)
1144     dbus_message_unref (message);
1145   
1146   return retval;
1147 }
1148
1149 typedef struct
1150 {
1151   Check1Func func;
1152   BusContext *context;
1153 } Check1Data;
1154
1155 static dbus_bool_t
1156 check_oom_check1_func (void *data)
1157 {
1158   Check1Data *d = data;
1159
1160   if (! (* d->func) (d->context))
1161     return FALSE;
1162   
1163   if (!check_no_leftovers (d->context))
1164     {
1165       _dbus_warn ("Messages were left over, should be covered by test suite");
1166       return FALSE;
1167     }
1168
1169   return TRUE;
1170 }
1171
1172 static void
1173 check1_try_iterations (BusContext *context,
1174                        const char *description,
1175                        Check1Func  func)
1176 {
1177   Check1Data d;
1178
1179   d.func = func;
1180   d.context = context;
1181
1182   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
1183                                 &d))
1184     _dbus_assert_not_reached ("test failed");
1185 }
1186
1187 typedef struct
1188 {
1189   Check2Func func;
1190   BusContext *context;
1191   DBusConnection *connection;
1192 } Check2Data;
1193
1194 static dbus_bool_t
1195 check_oom_check2_func (void *data)
1196 {
1197   Check2Data *d = data;
1198
1199   if (! (* d->func) (d->context, d->connection))
1200     return FALSE;
1201   
1202   if (!check_no_leftovers (d->context))
1203     {
1204       _dbus_warn ("Messages were left over, should be covered by test suite");
1205       return FALSE;
1206     }
1207
1208   return TRUE;
1209 }
1210
1211 static void
1212 check2_try_iterations (BusContext     *context,
1213                        DBusConnection *connection,
1214                        const char     *description,
1215                        Check2Func      func)
1216 {
1217   Check2Data d;
1218
1219   d.func = func;
1220   d.context = context;
1221   d.connection = connection;
1222   
1223   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
1224                                 &d))
1225     _dbus_assert_not_reached ("test failed");
1226 }
1227
1228 dbus_bool_t
1229 bus_dispatch_test (const DBusString *test_data_dir)
1230 {
1231   BusContext *context;
1232   DBusConnection *foo;
1233   DBusConnection *bar;
1234   DBusConnection *baz;
1235   DBusError error;
1236   
1237   context = bus_context_new_test (test_data_dir,
1238                                   "valid-config-files/debug-allow-all.conf");
1239   if (context == NULL)
1240     return FALSE;
1241
1242   dbus_error_init (&error);
1243   
1244   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1245   if (foo == NULL)
1246     _dbus_assert_not_reached ("could not alloc connection");
1247
1248   if (!bus_setup_debug_client (foo))
1249     _dbus_assert_not_reached ("could not set up connection");
1250
1251   if (!check_hello_message (context, foo))
1252     _dbus_assert_not_reached ("hello message failed");
1253   
1254   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
1255   if (bar == NULL)
1256     _dbus_assert_not_reached ("could not alloc connection");
1257
1258   if (!bus_setup_debug_client (bar))
1259     _dbus_assert_not_reached ("could not set up connection");
1260
1261   if (!check_hello_message (context, bar))
1262     _dbus_assert_not_reached ("hello message failed");
1263   
1264   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
1265   if (baz == NULL)
1266     _dbus_assert_not_reached ("could not alloc connection");
1267
1268   if (!bus_setup_debug_client (baz))
1269     _dbus_assert_not_reached ("could not set up connection");
1270
1271   if (!check_hello_message (context, baz))
1272     _dbus_assert_not_reached ("hello message failed");
1273
1274 #if 0
1275   check2_try_iterations (context, foo, "existent_service_activation",
1276                          check_existent_service_activation);
1277 #endif
1278   
1279   check2_try_iterations (context, foo, "nonexistent_service_activation",
1280                          check_nonexistent_service_activation);
1281
1282   check1_try_iterations (context, "create_and_hello",
1283                          check_hello_connection);
1284   
1285   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1286
1287   kill_client_connection_unchecked (foo);
1288   kill_client_connection_unchecked (bar);
1289   kill_client_connection_unchecked (baz);
1290
1291   bus_context_unref (context);
1292   
1293   return TRUE;
1294 }
1295 #endif /* DBUS_BUILD_TESTS */