2003-04-07 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 "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 static dbus_bool_t
1038 check_service_activated (BusContext     *context,
1039                          DBusConnection *connection,
1040                          const char     *activated_name,
1041                          dbus_bool_t     require_base_service,
1042                          DBusMessage    *initial_message,
1043                          char          **base_service_p)
1044 {
1045   DBusMessage *message;
1046   dbus_bool_t retval;
1047   DBusError error;
1048   char *base_service;
1049   dbus_uint32_t activation_result;
1050   dbus_bool_t already_saw_base_created;
1051   
1052   base_service = NULL;
1053   retval = FALSE;
1054   
1055   dbus_error_init (&error);
1056
1057   message = initial_message;
1058   dbus_message_ref (message);
1059   
1060   /* This is kind of a mess since we get the creation of
1061    * the base service only if the activated service didn't
1062    * already exist. Right now the test kills and restarts
1063    * the service each time, so the mess is pointless.
1064    */
1065   already_saw_base_created = FALSE;
1066
1067  recheck_service_created:
1068   if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
1069     {
1070       char *service_name;
1071       CheckServiceCreatedData scd;
1072           
1073       if (!dbus_message_get_args (message, &error,
1074                                   DBUS_TYPE_STRING, &service_name,
1075                                   DBUS_TYPE_INVALID))
1076         {
1077           _dbus_warn ("Message %s doesn't have a service name: %s\n",
1078                       dbus_message_get_name (message),
1079                       error.message);
1080           dbus_error_free (&error);
1081           goto out;
1082         }
1083
1084       if (!already_saw_base_created && *service_name == ':')
1085         {
1086           /* This is a base service name, mop up all the
1087            * other messages about it
1088            */
1089               
1090           base_service = service_name;
1091           service_name = NULL;
1092               
1093           scd.skip_connection = connection;
1094           scd.failed = FALSE;
1095           scd.expected_service_name = base_service;
1096           bus_test_clients_foreach (check_service_created_foreach,
1097                                     &scd);
1098               
1099           if (scd.failed)
1100             goto out;
1101
1102           already_saw_base_created = TRUE;
1103
1104           dbus_message_unref (message);
1105           message = dbus_connection_pop_message (connection);
1106           if (message == NULL)
1107             {
1108               _dbus_warn ("Expected a ServiceCreated for the activated service, got nothing\n");
1109               goto out;
1110             }
1111               
1112           goto recheck_service_created;
1113         }
1114       else if (require_base_service)
1115         {
1116           _dbus_warn ("Did not get a ServiceCreated for a base service\n");
1117           goto out;
1118         }
1119
1120       if (strcmp (service_name, activated_name) != 0)
1121         {
1122           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1123                       activated_name, service_name);
1124           dbus_free (service_name);
1125           goto out;
1126         }
1127       
1128       scd.skip_connection = connection;
1129       scd.failed = FALSE;
1130       scd.expected_service_name = service_name;
1131       bus_test_clients_foreach (check_service_created_foreach,
1132                                 &scd);
1133           
1134       dbus_free (service_name);
1135
1136       if (scd.failed)
1137         goto out;
1138           
1139       dbus_message_unref (message);
1140       message = dbus_connection_pop_message (connection);
1141       if (message == NULL)
1142         {
1143           _dbus_warn ("Expected a reply to %s, got nothing\n",
1144                       DBUS_MESSAGE_ACTIVATE_SERVICE);
1145           goto out;
1146         }
1147     }
1148       
1149   if (!dbus_message_name_is (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
1150     {
1151       _dbus_warn ("Expected reply to %s, got message %s instead\n",
1152                   DBUS_MESSAGE_ACTIVATE_SERVICE,
1153                   dbus_message_get_name (message));
1154       goto out;
1155     }
1156
1157   activation_result = 0;
1158   if (!dbus_message_get_args (message, &error,
1159                               DBUS_TYPE_UINT32, &activation_result,
1160                               DBUS_TYPE_INVALID))
1161     {
1162       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1163         {
1164           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1165                       DBUS_MESSAGE_ACTIVATE_SERVICE, error.message);
1166           dbus_error_free (&error);
1167           goto out;
1168         }
1169
1170       dbus_error_free (&error);
1171     }
1172   else
1173     {
1174       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
1175         ; /* Good */
1176       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
1177         ; /* Good also */
1178       else
1179         {
1180           _dbus_warn ("Activation result was 0x%x, no good.\n",
1181                       activation_result);
1182           goto out;
1183         }
1184     }
1185
1186   dbus_message_unref (message);
1187   message = NULL;
1188       
1189   if (!check_no_leftovers (context))
1190     {
1191       _dbus_warn ("Messages were left over after verifying existent activation results\n");
1192       goto out;
1193     }
1194
1195   retval = TRUE;
1196
1197   if (base_service_p)
1198     {
1199       *base_service_p = base_service;
1200       base_service = NULL;
1201     }
1202   
1203  out:
1204   if (message)
1205     dbus_message_unref (message);
1206
1207   if (base_service)
1208     dbus_free (base_service);
1209   
1210   return retval;
1211 }
1212
1213 static dbus_bool_t
1214 check_service_deactivated (BusContext     *context,
1215                            DBusConnection *connection,
1216                            const char     *activated_name,
1217                            const char     *base_service)
1218 {
1219   DBusMessage *message;
1220   dbus_bool_t retval;
1221   DBusError error;
1222   CheckServiceDeletedData csdd;
1223
1224   message = NULL;
1225   retval = FALSE;
1226   
1227   dbus_error_init (&error);
1228
1229   /* Now we are expecting ServiceDeleted messages for the base
1230    * service and the activated_name.  The base service
1231    * notification is required to come second.
1232    */
1233   csdd.expected_service_name = activated_name;
1234   csdd.failed = FALSE;
1235   bus_test_clients_foreach (check_service_deleted_foreach,
1236                             &csdd);      
1237
1238   if (csdd.failed)
1239     goto out;
1240       
1241   csdd.expected_service_name = base_service;
1242   csdd.failed = FALSE;
1243   bus_test_clients_foreach (check_service_deleted_foreach,
1244                             &csdd);
1245
1246   if (csdd.failed)
1247     goto out;
1248       
1249   if (!check_no_leftovers (context))
1250     {
1251       _dbus_warn ("Messages were left over after verifying results of service exiting\n");
1252       goto out;
1253     }
1254   
1255  out:
1256   if (message)
1257     dbus_message_unref (message);
1258   
1259   return retval;
1260 }
1261
1262 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
1263
1264 /* returns TRUE if the correct thing happens,
1265  * but the correct thing may include OOM errors.
1266  */
1267 static dbus_bool_t
1268 check_existent_service_activation (BusContext     *context,
1269                                    DBusConnection *connection)
1270 {
1271   DBusMessage *message;
1272   dbus_int32_t serial;
1273   dbus_bool_t retval;
1274   DBusError error;
1275   char *base_service;
1276
1277   base_service = NULL;
1278   
1279   dbus_error_init (&error);
1280   
1281   message = dbus_message_new (DBUS_SERVICE_DBUS,
1282                               DBUS_MESSAGE_ACTIVATE_SERVICE);
1283
1284   if (message == NULL)
1285     return TRUE;
1286
1287   if (!dbus_message_append_args (message,
1288                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
1289                                  DBUS_TYPE_UINT32, 0,
1290                                  DBUS_TYPE_INVALID))
1291     {
1292       dbus_message_unref (message);
1293       return TRUE;
1294     }
1295   
1296   if (!dbus_connection_send (connection, message, &serial))
1297     {
1298       dbus_message_unref (message);
1299       return TRUE;
1300     }
1301
1302   dbus_message_unref (message);
1303   message = NULL;
1304
1305   bus_test_run_everything (context);
1306
1307   if (dbus_connection_get_dispatch_status (connection) ==
1308       DBUS_DISPATCH_COMPLETE)
1309     /* now wait for the message bus to hear back from the activated service */
1310     bus_test_run_bus_loop (context, TRUE);
1311   
1312   /* and process everything again */
1313   bus_test_run_everything (context);
1314
1315   if (!dbus_connection_get_is_connected (connection))
1316     {
1317       _dbus_verbose ("connection was disconnected\n");
1318       return TRUE;
1319     }
1320   
1321   retval = FALSE;
1322   
1323   message = dbus_connection_pop_message (connection);
1324   if (message == NULL)
1325     {
1326       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1327                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
1328       goto out;
1329     }
1330
1331   _dbus_verbose ("Received %s on %p\n",
1332                  dbus_message_get_name (message), connection);
1333
1334   if (dbus_message_get_is_error (message))
1335     {
1336       if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
1337         {
1338           _dbus_warn ("Message has wrong sender %s\n",
1339                       dbus_message_get_sender (message) ?
1340                       dbus_message_get_sender (message) : "(none)");
1341           goto out;
1342         }
1343       
1344       if (dbus_message_name_is (message,
1345                                 DBUS_ERROR_NO_MEMORY))
1346         {
1347           ; /* good, this is a valid response */
1348         }
1349       else if (dbus_message_name_is (message,
1350                                      DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
1351         {
1352           ; /* good, this is expected also */
1353         }
1354       else
1355         {
1356           _dbus_warn ("Did not expect error %s\n",
1357                       dbus_message_get_name (message));
1358           goto out;
1359         }
1360     }
1361   else
1362     {
1363       if (!check_service_activated (context, connection,
1364                                     EXISTENT_SERVICE_NAME, TRUE,
1365                                     message, &base_service))
1366         goto out;
1367
1368       dbus_message_unref (message);
1369       message = NULL;
1370   
1371       /* Now kill off the test service by sending it a quit message */
1372       message = dbus_message_new (EXISTENT_SERVICE_NAME,
1373                                   "org.freedesktop.DBus.TestSuiteExit");
1374       
1375       if (message == NULL)
1376         {
1377           dbus_free (base_service);
1378           return TRUE;
1379         }
1380       
1381       if (!dbus_connection_send (connection, message, &serial))
1382         {
1383           dbus_message_unref (message);
1384           dbus_free (base_service);
1385           return TRUE;
1386         }
1387
1388       dbus_message_unref (message);
1389       message = NULL;
1390
1391       /* send message */
1392       bus_test_run_clients_loop (TRUE);
1393
1394       /* read it in and write it out to test service */
1395       bus_test_run_bus_loop (context, FALSE);
1396       
1397       if (dbus_connection_get_dispatch_status (connection) ==
1398           DBUS_DISPATCH_COMPLETE)
1399         /* now wait for the message bus to hear back from the activated service exiting */
1400         bus_test_run_bus_loop (context, TRUE);
1401       
1402       /* and process everything again */
1403       bus_test_run_everything (context);
1404
1405       if (!check_service_deactivated (context, connection,
1406                                       EXISTENT_SERVICE_NAME, base_service))
1407         goto out;
1408     }
1409
1410   retval = TRUE;
1411   
1412  out:
1413   if (message)
1414     dbus_message_unref (message);
1415
1416   if (base_service)
1417     dbus_free (base_service);
1418   
1419   return retval;
1420 }
1421
1422 typedef struct
1423 {
1424   Check1Func func;
1425   BusContext *context;
1426 } Check1Data;
1427
1428 static dbus_bool_t
1429 check_oom_check1_func (void *data)
1430 {
1431   Check1Data *d = data;
1432
1433   if (! (* d->func) (d->context))
1434     return FALSE;
1435   
1436   if (!check_no_leftovers (d->context))
1437     {
1438       _dbus_warn ("Messages were left over, should be covered by test suite\n");
1439       return FALSE;
1440     }
1441
1442   return TRUE;
1443 }
1444
1445 static void
1446 check1_try_iterations (BusContext *context,
1447                        const char *description,
1448                        Check1Func  func)
1449 {
1450   Check1Data d;
1451
1452   d.func = func;
1453   d.context = context;
1454
1455   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
1456                                 &d))
1457     _dbus_assert_not_reached ("test failed");
1458 }
1459
1460 typedef struct
1461 {
1462   Check2Func func;
1463   BusContext *context;
1464   DBusConnection *connection;
1465 } Check2Data;
1466
1467 static dbus_bool_t
1468 check_oom_check2_func (void *data)
1469 {
1470   Check2Data *d = data;
1471
1472   if (! (* d->func) (d->context, d->connection))
1473     return FALSE;
1474   
1475   if (!check_no_leftovers (d->context))
1476     {
1477       _dbus_warn ("Messages were left over, should be covered by test suite");
1478       return FALSE;
1479     }
1480
1481   return TRUE;
1482 }
1483
1484 static void
1485 check2_try_iterations (BusContext     *context,
1486                        DBusConnection *connection,
1487                        const char     *description,
1488                        Check2Func      func)
1489 {
1490   Check2Data d;
1491
1492   d.func = func;
1493   d.context = context;
1494   d.connection = connection;
1495   
1496   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
1497                                 &d))
1498     _dbus_assert_not_reached ("test failed");
1499 }
1500
1501 dbus_bool_t
1502 bus_dispatch_test (const DBusString *test_data_dir)
1503 {
1504   BusContext *context;
1505   DBusConnection *foo;
1506   DBusConnection *bar;
1507   DBusConnection *baz;
1508   DBusError error;
1509   
1510   context = bus_context_new_test (test_data_dir,
1511                                   "valid-config-files/debug-allow-all.conf");
1512   if (context == NULL)
1513     return FALSE;
1514
1515   dbus_error_init (&error);
1516   
1517   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
1518   if (foo == NULL)
1519     _dbus_assert_not_reached ("could not alloc connection");
1520
1521   if (!bus_setup_debug_client (foo))
1522     _dbus_assert_not_reached ("could not set up connection");
1523
1524   if (!check_hello_message (context, foo))
1525     _dbus_assert_not_reached ("hello message failed");
1526   
1527   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
1528   if (bar == NULL)
1529     _dbus_assert_not_reached ("could not alloc connection");
1530
1531   if (!bus_setup_debug_client (bar))
1532     _dbus_assert_not_reached ("could not set up connection");
1533
1534   if (!check_hello_message (context, bar))
1535     _dbus_assert_not_reached ("hello message failed");
1536   
1537   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
1538   if (baz == NULL)
1539     _dbus_assert_not_reached ("could not alloc connection");
1540
1541   if (!bus_setup_debug_client (baz))
1542     _dbus_assert_not_reached ("could not set up connection");
1543
1544   if (!check_hello_message (context, baz))
1545     _dbus_assert_not_reached ("hello message failed");
1546
1547 #if 0
1548   check2_try_iterations (context, foo, "existent_service_activation",
1549                          check_existent_service_activation);
1550 #endif
1551   
1552   check2_try_iterations (context, foo, "nonexistent_service_activation",
1553                          check_nonexistent_service_activation);
1554
1555   check1_try_iterations (context, "create_and_hello",
1556                          check_hello_connection);
1557   
1558   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
1559
1560   kill_client_connection_unchecked (foo);
1561   kill_client_connection_unchecked (bar);
1562   kill_client_connection_unchecked (baz);
1563
1564   bus_context_unref (context);
1565   
1566   return TRUE;
1567 }
1568 #endif /* DBUS_BUILD_TESTS */