Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dispatch.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dispatch.c  Message dispatcher
00003  *
00004  * Copyright (C) 2003  CodeFactory AB
00005  * Copyright (C) 2003  Red Hat, Inc.
00006  *
00007  * Licensed under the Academic Free License version 1.2
00008  * 
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include "dispatch.h"
00026 #include "connection.h"
00027 #include "driver.h"
00028 #include "services.h"
00029 #include "utils.h"
00030 #include "bus.h"
00031 #include "test.h"
00032 #include <dbus/dbus-internals.h>
00033 #include <string.h>
00034 
00035 static dbus_int32_t message_handler_slot = -1;
00036 
00037 typedef struct
00038 {
00039   BusContext     *context;
00040   DBusConnection *sender;
00041   DBusMessage    *message;
00042   BusTransaction *transaction;
00043   DBusError      *error;
00044 } SendMessageData;
00045 
00046 static dbus_bool_t
00047 send_one_message (DBusConnection *connection, void *data)
00048 {
00049   SendMessageData *d = data;
00050 
00051   if (!bus_context_check_security_policy (d->context,
00052                                           d->sender,
00053                                           connection,
00054                                           d->message,
00055                                           NULL))
00056     return TRUE; /* silently don't send it */
00057   
00058   if (!bus_transaction_send (d->transaction,
00059                              connection,
00060                              d->message))
00061     {
00062       BUS_SET_OOM (d->error);
00063       return FALSE;
00064     }
00065 
00066   return TRUE;
00067 }
00068 
00069 dbus_bool_t
00070 bus_dispatch_broadcast_message (BusTransaction *transaction,
00071                                 DBusConnection *sender,
00072                                 DBusMessage    *message,
00073                                 DBusError      *error)
00074 {
00075   DBusError tmp_error;
00076   SendMessageData d;
00077   BusConnections *connections;
00078 
00079   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00080   
00081   _dbus_assert (dbus_message_get_sender (message) != NULL);
00082 
00083   connections = bus_transaction_get_connections (transaction);
00084   
00085   dbus_error_init (&tmp_error);
00086   d.sender = sender;
00087   d.context = bus_transaction_get_context (transaction);
00088   d.message = message;
00089   d.transaction = transaction;
00090   d.error = &tmp_error;
00091   
00092   bus_connections_foreach_active (connections, send_one_message, &d);
00093 
00094   if (dbus_error_is_set (&tmp_error))
00095     {
00096       dbus_move_error (&tmp_error, error);
00097       return FALSE;
00098     }
00099   else
00100     return TRUE;
00101 }
00102 
00103 static void
00104 bus_dispatch (DBusConnection *connection,
00105               DBusMessage    *message)
00106 {
00107   const char *sender, *service_name, *message_name;
00108   DBusError error;
00109   BusTransaction *transaction;
00110   BusContext *context;
00111   
00112   transaction = NULL;
00113   dbus_error_init (&error);
00114   
00115   context = bus_connection_get_context (connection);
00116   _dbus_assert (context != NULL);
00117   
00118   /* If we can't even allocate an OOM error, we just go to sleep
00119    * until we can.
00120    */
00121   while (!bus_connection_preallocate_oom_error (connection))
00122     _dbus_wait_for_memory ();
00123   
00124   /* Ref connection in case we disconnect it at some point in here */
00125   dbus_connection_ref (connection);
00126 
00127   service_name = dbus_message_get_destination (message);
00128   message_name = dbus_message_get_name (message);
00129 
00130   _dbus_assert (message_name != NULL); /* DBusMessageLoader is supposed to check this */
00131 
00132   _dbus_verbose ("DISPATCH: %s to %s\n",
00133                  message_name, service_name ? service_name : "peer");
00134   
00135   /* If service_name is NULL, this is a message to the bus daemon, not
00136    * intended to actually go "on the bus"; e.g. a peer-to-peer
00137    * ping. Handle these immediately, especially disconnection
00138    * messages. There are no security policy checks on these.
00139    */
00140   if (service_name == NULL)
00141     {      
00142       if (strcmp (message_name, DBUS_MESSAGE_LOCAL_DISCONNECT) == 0)
00143         bus_connection_disconnected (connection);
00144 
00145       /* DBusConnection also handles some of these automatically, we leave
00146        * it to do so.
00147        */
00148       goto out;
00149     }
00150 
00151   _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
00152   
00153   /* Create our transaction */
00154   transaction = bus_transaction_new (context);
00155   if (transaction == NULL)
00156     {
00157       BUS_SET_OOM (&error);
00158       goto out;
00159     }
00160   
00161   /* Assign a sender to the message */
00162   if (bus_connection_is_active (connection))
00163     {
00164       sender = bus_connection_get_name (connection);
00165       _dbus_assert (sender != NULL);
00166 
00167       if (!dbus_message_set_sender (message, sender))
00168         {
00169           BUS_SET_OOM (&error);
00170           goto out;
00171         }
00172 
00173       /* We need to refetch the service name here, because
00174        * dbus_message_set_sender can cause the header to be
00175        * reallocated, and thus the service_name pointer will become
00176        * invalid.
00177        */
00178       service_name = dbus_message_get_destination (message);
00179     }
00180 
00181   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
00182     {
00183       if (!bus_context_check_security_policy (context,
00184                                               connection, NULL, message, &error))
00185         {
00186           _dbus_verbose ("Security policy rejected message\n");
00187           goto out;
00188         }
00189 
00190       _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
00191       if (!bus_driver_handle_message (connection, transaction, message, &error))
00192         goto out;
00193     }
00194   else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
00195     {
00196       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
00197       dbus_connection_disconnect (connection);
00198     }
00199   /* FIXME what if we un-special-case this service and just have a flag
00200    * on services that all service owners will get messages to it, not just
00201    * the primary owner.
00202    */
00203   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
00204     {
00205       if (!bus_dispatch_broadcast_message (transaction, connection, message, &error))
00206         goto out;
00207     }
00208   else  /* route to named service */
00209     {
00210       DBusString service_string;
00211       BusService *service;
00212       BusRegistry *registry;
00213 
00214       registry = bus_connection_get_registry (connection);
00215       
00216       _dbus_string_init_const (&service_string, service_name);
00217       service = bus_registry_lookup (registry, &service_string);
00218 
00219       if (service == NULL)
00220         {
00221           dbus_set_error (&error,
00222                           DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
00223                           "Service \"%s\" does not exist",
00224                           service_name);
00225           goto out;
00226         }
00227       else
00228         {
00229           DBusConnection *recipient;
00230           
00231           recipient = bus_service_get_primary_owner (service);
00232           _dbus_assert (recipient != NULL);
00233           
00234           if (!bus_context_check_security_policy (context,
00235                                                   connection, recipient, message, &error))
00236             goto out;
00237           
00238           /* Dispatch the message */
00239           if (!bus_transaction_send (transaction, recipient, message))
00240             {
00241               BUS_SET_OOM (&error);
00242               goto out;
00243             }
00244         }
00245     }
00246   
00247  out:
00248   if (dbus_error_is_set (&error))
00249     {
00250       if (!dbus_connection_get_is_connected (connection))
00251         {
00252           /* If we disconnected it, we won't bother to send it any error
00253            * messages.
00254            */
00255           _dbus_verbose ("Not sending error to connection we disconnected\n");
00256         }
00257       else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00258         {
00259           bus_connection_send_oom_error (connection, message);
00260 
00261           /* cancel transaction due to OOM */
00262           if (transaction != NULL)
00263             {
00264               bus_transaction_cancel_and_free (transaction);
00265               transaction = NULL;
00266             }
00267         }
00268       else
00269         {
00270           /* Try to send the real error, if no mem to do that, send
00271            * the OOM error
00272            */
00273           _dbus_assert (transaction != NULL);
00274           
00275           if (!bus_transaction_send_error_reply (transaction, connection,
00276                                                  &error, message))
00277             {
00278               bus_connection_send_oom_error (connection, message);
00279               
00280               /* cancel transaction due to OOM */
00281               if (transaction != NULL)
00282                 {
00283                   bus_transaction_cancel_and_free (transaction);
00284                   transaction = NULL;
00285                 }
00286             }
00287         }
00288       
00289       dbus_error_free (&error);
00290     }
00291 
00292   if (transaction != NULL)
00293     {
00294       bus_transaction_execute_and_free (transaction);
00295     }
00296 
00297   dbus_connection_unref (connection);
00298 }
00299 
00300 static DBusHandlerResult
00301 bus_dispatch_message_handler (DBusMessageHandler *handler,
00302                               DBusConnection     *connection,
00303                               DBusMessage        *message,
00304                               void               *user_data)
00305 {
00306   bus_dispatch (connection, message);
00307   
00308   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
00309 }
00310 
00311 static void
00312 free_message_handler (void *data)
00313 {
00314   DBusMessageHandler *handler = data;
00315   
00316   _dbus_assert (message_handler_slot >= 0);
00317   
00318   dbus_message_handler_unref (handler);
00319   dbus_connection_free_data_slot (&message_handler_slot);
00320 }
00321 
00322 dbus_bool_t
00323 bus_dispatch_add_connection (DBusConnection *connection)
00324 {
00325   DBusMessageHandler *handler;
00326 
00327   if (!dbus_connection_allocate_data_slot (&message_handler_slot))
00328     return FALSE;
00329   
00330   handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);  
00331   if (handler == NULL)
00332     {
00333       dbus_connection_free_data_slot (&message_handler_slot);
00334       return FALSE;
00335     }    
00336   
00337   if (!dbus_connection_add_filter (connection, handler))
00338     {
00339       dbus_message_handler_unref (handler);
00340       dbus_connection_free_data_slot (&message_handler_slot);
00341       
00342       return FALSE;
00343     }
00344 
00345   _dbus_assert (message_handler_slot >= 0);
00346   
00347   if (!dbus_connection_set_data (connection,
00348                                  message_handler_slot,
00349                                  handler,
00350                                  free_message_handler))
00351     {
00352       dbus_message_handler_unref (handler);
00353       dbus_connection_free_data_slot (&message_handler_slot);
00354 
00355       return FALSE;
00356     }
00357 
00358   return TRUE;
00359 }
00360 
00361 void
00362 bus_dispatch_remove_connection (DBusConnection *connection)
00363 {
00364   /* Here we tell the bus driver that we want to get off. */
00365   bus_driver_remove_connection (connection);
00366 
00367   dbus_connection_set_data (connection,
00368                             message_handler_slot,
00369                             NULL, NULL);
00370 }
00371 
00372 #ifdef DBUS_BUILD_TESTS
00373 
00374 typedef dbus_bool_t (* Check1Func) (BusContext     *context);
00375 typedef dbus_bool_t (* Check2Func) (BusContext     *context,
00376                                     DBusConnection *connection);
00377 
00378 static dbus_bool_t check_no_leftovers (BusContext *context);
00379 
00380 static void
00381 block_connection_until_message_from_bus (BusContext     *context,
00382                                          DBusConnection *connection)
00383 {
00384   while (dbus_connection_get_dispatch_status (connection) ==
00385          DBUS_DISPATCH_COMPLETE &&
00386          dbus_connection_get_is_connected (connection))
00387     {
00388       bus_test_run_bus_loop (context, TRUE);
00389       bus_test_run_clients_loop (FALSE);
00390     }
00391 }
00392 
00393 /* compensate for fact that pop_message() can return #NULL due to OOM */
00394 static DBusMessage*
00395 pop_message_waiting_for_memory (DBusConnection *connection)
00396 {
00397   while (dbus_connection_get_dispatch_status (connection) ==
00398          DBUS_DISPATCH_NEED_MEMORY)
00399     _dbus_wait_for_memory ();
00400 
00401   return dbus_connection_pop_message (connection);
00402 }
00403 
00404 typedef struct
00405 {
00406   const char *expected_service_name;
00407   dbus_bool_t failed;
00408 } CheckServiceDeletedData;
00409 
00410 static dbus_bool_t
00411 check_service_deleted_foreach (DBusConnection *connection,
00412                                void           *data)
00413 {
00414   CheckServiceDeletedData *d = data;
00415   DBusMessage *message;
00416   DBusError error;
00417   char *service_name;
00418 
00419   dbus_error_init (&error);
00420   d->failed = TRUE;
00421   service_name = NULL;
00422   
00423   message = pop_message_waiting_for_memory (connection);
00424   if (message == NULL)
00425     {
00426       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
00427                   connection, DBUS_MESSAGE_SERVICE_DELETED);
00428       goto out;
00429     }
00430   else if (!dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_DELETED))
00431     {
00432       _dbus_warn ("Received message %s on %p, expecting %s\n",
00433                   dbus_message_get_name (message),
00434                   connection, DBUS_MESSAGE_SERVICE_DELETED);
00435       goto out;
00436     }
00437   else
00438     {
00439       if (!dbus_message_get_args (message, &error,
00440                                   DBUS_TYPE_STRING, &service_name,
00441                                   DBUS_TYPE_INVALID))
00442         {
00443           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00444             {
00445               _dbus_verbose ("no memory to get service name arg\n");
00446             }
00447           else
00448             {
00449               _dbus_assert (dbus_error_is_set (&error));
00450               _dbus_warn ("Did not get the expected single string argument\n");
00451               goto out;
00452             }
00453         }
00454       else if (strcmp (service_name, d->expected_service_name) != 0)
00455         {
00456           _dbus_warn ("expected deletion of service %s, got deletion of %s\n",
00457                       d->expected_service_name,
00458                       service_name);
00459           goto out;
00460         }
00461     }
00462 
00463   d->failed = FALSE;
00464   
00465  out:
00466   dbus_free (service_name);
00467   dbus_error_free (&error);
00468   
00469   if (message)
00470     dbus_message_unref (message);
00471 
00472   return !d->failed;
00473 }
00474 
00475 static void
00476 kill_client_connection (BusContext     *context,
00477                         DBusConnection *connection)
00478 {
00479   char *base_service;
00480   const char *s;
00481   CheckServiceDeletedData csdd;
00482 
00483   _dbus_verbose ("killing connection %p\n", connection);
00484   
00485   s = dbus_bus_get_base_service (connection);
00486   _dbus_assert (s != NULL);
00487 
00488   while ((base_service = _dbus_strdup (s)) == NULL)
00489     _dbus_wait_for_memory ();
00490 
00491   dbus_connection_ref (connection);
00492   
00493   /* kick in the disconnect handler that unrefs the connection */
00494   dbus_connection_disconnect (connection);
00495 
00496   bus_test_run_everything (context);
00497   
00498   _dbus_assert (bus_test_client_listed (connection));
00499   
00500   /* Run disconnect handler in test.c */
00501   if (bus_connection_dispatch_one_message (connection))
00502     _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
00503   
00504   _dbus_assert (!dbus_connection_get_is_connected (connection));
00505   dbus_connection_unref (connection);
00506   connection = NULL;
00507   _dbus_assert (!bus_test_client_listed (connection));
00508   
00509   csdd.expected_service_name = base_service;
00510   csdd.failed = FALSE;
00511 
00512   bus_test_clients_foreach (check_service_deleted_foreach,
00513                             &csdd);
00514 
00515   dbus_free (base_service);
00516   
00517   if (csdd.failed)
00518     _dbus_assert_not_reached ("didn't get the expected ServiceDeleted messages");
00519   
00520   if (!check_no_leftovers (context))
00521     _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
00522 }
00523 
00524 static void
00525 kill_client_connection_unchecked (DBusConnection *connection)
00526 {
00527   /* This kills the connection without expecting it to affect
00528    * the rest of the bus.
00529    */  
00530   _dbus_verbose ("Unchecked kill of connection %p\n", connection);
00531 
00532   dbus_connection_ref (connection);
00533   dbus_connection_disconnect (connection);
00534   /* dispatching disconnect handler will unref once */
00535   if (bus_connection_dispatch_one_message (connection))
00536     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
00537 
00538   _dbus_assert (!bus_test_client_listed (connection));
00539   dbus_connection_unref (connection);
00540 }
00541 
00542 typedef struct
00543 {
00544   dbus_bool_t failed;
00545 } CheckNoMessagesData;
00546 
00547 static dbus_bool_t
00548 check_no_messages_foreach (DBusConnection *connection,
00549                            void           *data)
00550 {
00551   CheckNoMessagesData *d = data;
00552   DBusMessage *message;
00553 
00554   message = pop_message_waiting_for_memory (connection);
00555   if (message != NULL)
00556     {
00557       _dbus_warn ("Received message %s on %p, expecting no messages\n",
00558                   dbus_message_get_name (message), connection);
00559       d->failed = TRUE;
00560     }
00561 
00562   if (message)
00563     dbus_message_unref (message);
00564   return !d->failed;
00565 }
00566 
00567 typedef struct
00568 {
00569   DBusConnection *skip_connection;
00570   const char *expected_service_name;
00571   dbus_bool_t failed;
00572 } CheckServiceCreatedData;
00573 
00574 static dbus_bool_t
00575 check_service_created_foreach (DBusConnection *connection,
00576                                void           *data)
00577 {
00578   CheckServiceCreatedData *d = data;
00579   DBusMessage *message;
00580   DBusError error;
00581   char *service_name;
00582 
00583   if (connection == d->skip_connection)
00584     return TRUE;
00585 
00586   dbus_error_init (&error);
00587   d->failed = TRUE;
00588   service_name = NULL;
00589   
00590   message = pop_message_waiting_for_memory (connection);
00591   if (message == NULL)
00592     {
00593       _dbus_warn ("Did not receive a message on %p, expecting %s\n",
00594                   connection, DBUS_MESSAGE_SERVICE_CREATED);
00595       goto out;
00596     }
00597   else if (!dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
00598     {
00599       _dbus_warn ("Received message %s on %p, expecting %s\n",
00600                   dbus_message_get_name (message),
00601                   connection, DBUS_MESSAGE_SERVICE_CREATED);
00602       goto out;
00603     }
00604   else
00605     {
00606       if (!dbus_message_get_args (message, &error,
00607                                   DBUS_TYPE_STRING, &service_name,
00608                                   DBUS_TYPE_INVALID))
00609         {
00610           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00611             {
00612               _dbus_verbose ("no memory to get service name arg\n");
00613             }
00614           else
00615             {
00616               _dbus_assert (dbus_error_is_set (&error));
00617               _dbus_warn ("Did not get the expected single string argument\n");
00618               goto out;
00619             }
00620         }
00621       else if (strcmp (service_name, d->expected_service_name) != 0)
00622         {
00623           _dbus_warn ("expected creation of service %s, got creation of %s\n",
00624                       d->expected_service_name,
00625                       service_name);
00626           goto out;
00627         }
00628     }
00629 
00630   d->failed = FALSE;
00631   
00632  out:
00633   dbus_free (service_name);
00634   dbus_error_free (&error);
00635   
00636   if (message)
00637     dbus_message_unref (message);
00638 
00639   return !d->failed;
00640 }
00641 
00642 static dbus_bool_t
00643 check_no_leftovers (BusContext *context)
00644 {
00645   CheckNoMessagesData nmd;
00646 
00647   nmd.failed = FALSE;
00648   bus_test_clients_foreach (check_no_messages_foreach,
00649                             &nmd);
00650   
00651   if (nmd.failed)
00652     return FALSE;
00653   else
00654     return TRUE;
00655 }
00656 
00657 /* returns TRUE if the correct thing happens,
00658  * but the correct thing may include OOM errors.
00659  */
00660 static dbus_bool_t
00661 check_hello_message (BusContext     *context,
00662                      DBusConnection *connection)
00663 {
00664   DBusMessage *message;
00665   dbus_int32_t serial;
00666   dbus_bool_t retval;
00667   DBusError error;
00668   char *name;
00669   char *acquired;
00670 
00671   retval = FALSE;
00672   dbus_error_init (&error);
00673   name = NULL;
00674   acquired = NULL;
00675   message = NULL;
00676   
00677   message = dbus_message_new (DBUS_MESSAGE_HELLO,
00678                               DBUS_SERVICE_DBUS);
00679 
00680   if (message == NULL)
00681     return TRUE;
00682 
00683   if (!dbus_connection_send (connection, message, &serial))
00684     {
00685       dbus_message_unref (message);
00686       return TRUE;
00687     }
00688 
00689   dbus_message_unref (message);
00690   message = NULL;
00691 
00692   /* send our message */
00693   bus_test_run_clients_loop (TRUE);
00694 
00695   dbus_connection_ref (connection); /* because we may get disconnected */
00696   block_connection_until_message_from_bus (context, connection);
00697 
00698   if (!dbus_connection_get_is_connected (connection))
00699     {
00700       _dbus_verbose ("connection was disconnected\n");
00701       
00702       dbus_connection_unref (connection);
00703       
00704       return TRUE;
00705     }
00706 
00707   dbus_connection_unref (connection);
00708   
00709   message = pop_message_waiting_for_memory (connection);
00710   if (message == NULL)
00711     {
00712       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
00713                   DBUS_MESSAGE_HELLO, serial, connection);
00714       goto out;
00715     }
00716 
00717   _dbus_verbose ("Received %s on %p\n",
00718                  dbus_message_get_name (message), connection);
00719 
00720   if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
00721     {
00722       _dbus_warn ("Message has wrong sender %s\n",
00723                   dbus_message_get_sender (message) ?
00724                   dbus_message_get_sender (message) : "(none)");
00725       goto out;
00726     }
00727   
00728   if (dbus_message_get_is_error (message))
00729     {
00730       if (dbus_message_has_name (message,
00731                                  DBUS_ERROR_NO_MEMORY))
00732         {
00733           ; /* good, this is a valid response */
00734         }
00735       else
00736         {
00737           _dbus_warn ("Did not expect error %s\n",
00738                       dbus_message_get_name (message));
00739           goto out;
00740         }
00741     }
00742   else
00743     {
00744       CheckServiceCreatedData scd;
00745       
00746       if (dbus_message_has_name (message,
00747                                  DBUS_MESSAGE_HELLO))
00748         {
00749           ; /* good, expected */
00750         }
00751       else
00752         {
00753           _dbus_warn ("Did not expect reply %s\n",
00754                       dbus_message_get_name (message));
00755           goto out;
00756         }
00757 
00758     retry_get_hello_name:
00759       if (!dbus_message_get_args (message, &error,
00760                                   DBUS_TYPE_STRING, &name,
00761                                   DBUS_TYPE_INVALID))
00762         {
00763           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00764             {
00765               _dbus_verbose ("no memory to get service name arg from hello\n");
00766               dbus_error_free (&error);
00767               _dbus_wait_for_memory ();
00768               goto retry_get_hello_name;
00769             }
00770           else
00771             {
00772               _dbus_assert (dbus_error_is_set (&error));
00773               _dbus_warn ("Did not get the expected single string argument to hello\n");
00774               goto out;
00775             }
00776         }
00777 
00778       _dbus_verbose ("Got hello name: %s\n", name);
00779 
00780       while (!dbus_bus_set_base_service (connection, name))
00781         _dbus_wait_for_memory ();
00782       
00783       scd.skip_connection = NULL;
00784       scd.failed = FALSE;
00785       scd.expected_service_name = name;
00786       bus_test_clients_foreach (check_service_created_foreach,
00787                                 &scd);
00788       
00789       if (scd.failed)
00790         goto out;
00791       
00792       /* Client should also have gotten ServiceAcquired */
00793       dbus_message_unref (message);
00794       message = pop_message_waiting_for_memory (connection);
00795       if (message == NULL)
00796         {
00797           _dbus_warn ("Expecting %s, got nothing\n",
00798                       DBUS_MESSAGE_SERVICE_ACQUIRED);
00799           goto out;
00800         }
00801       
00802     retry_get_acquired_name:
00803       if (!dbus_message_get_args (message, &error,
00804                                   DBUS_TYPE_STRING, &acquired,
00805                                   DBUS_TYPE_INVALID))
00806         {
00807           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
00808             {
00809               _dbus_verbose ("no memory to get service name arg from acquired\n");
00810               dbus_error_free (&error);
00811               _dbus_wait_for_memory ();
00812               goto retry_get_acquired_name;
00813             }
00814           else
00815             {
00816               _dbus_assert (dbus_error_is_set (&error));
00817               _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
00818               goto out;
00819             }
00820         }
00821 
00822       _dbus_verbose ("Got acquired name: %s\n", acquired);
00823 
00824       if (strcmp (acquired, name) != 0)
00825         {
00826           _dbus_warn ("Acquired name is %s but expected %s\n",
00827                       acquired, name);
00828           goto out;
00829         }
00830     }
00831 
00832   if (!check_no_leftovers (context))
00833     goto out;
00834   
00835   retval = TRUE;
00836   
00837  out:
00838   dbus_error_free (&error);
00839   
00840   dbus_free (name);
00841   dbus_free (acquired);
00842   
00843   if (message)
00844     dbus_message_unref (message);
00845   
00846   return retval;
00847 }
00848 
00849 /* returns TRUE if the correct thing happens,
00850  * but the correct thing may include OOM errors.
00851  */
00852 static dbus_bool_t
00853 check_hello_connection (BusContext *context)
00854 {
00855   DBusConnection *connection;
00856   DBusError error;
00857 
00858   dbus_error_init (&error);
00859 
00860   connection = dbus_connection_open ("debug-pipe:name=test-server", &error);
00861   if (connection == NULL)
00862     {
00863       _DBUS_ASSERT_ERROR_IS_SET (&error);
00864       dbus_error_free (&error);
00865       return TRUE;
00866     }
00867 
00868   if (!bus_setup_debug_client (connection))
00869     {
00870       dbus_connection_disconnect (connection);
00871       dbus_connection_unref (connection);
00872       return TRUE;
00873     }
00874 
00875   if (!check_hello_message (context, connection))
00876     return FALSE;
00877 
00878   if (dbus_bus_get_base_service (connection) == NULL)
00879     {
00880       /* We didn't successfully register, so we can't
00881        * do the usual kill_client_connection() checks
00882        */
00883       kill_client_connection_unchecked (connection);
00884     }
00885   else
00886     {
00887       kill_client_connection (context, connection);
00888     }
00889 
00890   return TRUE;
00891 }
00892 
00893 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
00894 
00895 /* returns TRUE if the correct thing happens,
00896  * but the correct thing may include OOM errors.
00897  */
00898 static dbus_bool_t
00899 check_nonexistent_service_activation (BusContext     *context,
00900                                       DBusConnection *connection)
00901 {
00902   DBusMessage *message;
00903   dbus_int32_t serial;
00904   dbus_bool_t retval;
00905   DBusError error;
00906   
00907   dbus_error_init (&error);
00908   
00909   message = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
00910                               DBUS_SERVICE_DBUS);
00911 
00912   if (message == NULL)
00913     return TRUE;
00914 
00915   if (!dbus_message_append_args (message,
00916                                  DBUS_TYPE_STRING, NONEXISTENT_SERVICE_NAME,
00917                                  DBUS_TYPE_UINT32, 0,
00918                                  DBUS_TYPE_INVALID))
00919     {
00920       dbus_message_unref (message);
00921       return TRUE;
00922     }
00923   
00924   if (!dbus_connection_send (connection, message, &serial))
00925     {
00926       dbus_message_unref (message);
00927       return TRUE;
00928     }
00929 
00930   dbus_message_unref (message);
00931   message = NULL;
00932 
00933   bus_test_run_everything (context);
00934   block_connection_until_message_from_bus (context, connection);
00935   bus_test_run_everything (context);
00936 
00937   if (!dbus_connection_get_is_connected (connection))
00938     {
00939       _dbus_verbose ("connection was disconnected\n");
00940       return TRUE;
00941     }
00942   
00943   retval = FALSE;
00944   
00945   message = pop_message_waiting_for_memory (connection);
00946   if (message == NULL)
00947     {
00948       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
00949                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
00950       goto out;
00951     }
00952 
00953   _dbus_verbose ("Received %s on %p\n",
00954                  dbus_message_get_name (message), connection);
00955 
00956   if (dbus_message_get_is_error (message))
00957     {
00958       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
00959         {
00960           _dbus_warn ("Message has wrong sender %s\n",
00961                       dbus_message_get_sender (message) ?
00962                       dbus_message_get_sender (message) : "(none)");
00963           goto out;
00964         }
00965       
00966       if (dbus_message_has_name (message,
00967                                  DBUS_ERROR_NO_MEMORY))
00968         {
00969           ; /* good, this is a valid response */
00970         }
00971       else if (dbus_message_has_name (message,
00972                                       DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
00973         {
00974           ; /* good, this is expected also */
00975         }
00976       else
00977         {
00978           _dbus_warn ("Did not expect error %s\n",
00979                       dbus_message_get_name (message));
00980           goto out;
00981         }
00982     }
00983   else
00984     {
00985       _dbus_warn ("Did not expect to successfully activate %s\n",
00986                   NONEXISTENT_SERVICE_NAME);
00987       goto out;
00988     }
00989 
00990   retval = TRUE;
00991   
00992  out:
00993   if (message)
00994     dbus_message_unref (message);
00995   
00996   return retval;
00997 }
00998 
00999 static dbus_bool_t
01000 check_base_service_activated (BusContext     *context,
01001                               DBusConnection *connection,
01002                               DBusMessage    *initial_message,
01003                               char          **base_service_p)
01004 {
01005   DBusMessage *message;
01006   dbus_bool_t retval;
01007   DBusError error;
01008   char *base_service;
01009   
01010   base_service = NULL;
01011   retval = FALSE;
01012   
01013   dbus_error_init (&error);
01014 
01015   message = initial_message;
01016   dbus_message_ref (message);  
01017 
01018   if (dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
01019     {
01020       char *service_name;
01021       CheckServiceCreatedData scd;
01022 
01023     reget_service_name_arg:
01024       if (!dbus_message_get_args (message, &error,
01025                                   DBUS_TYPE_STRING, &service_name,
01026                                   DBUS_TYPE_INVALID))
01027         {
01028           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
01029             {
01030               dbus_error_free (&error);
01031               _dbus_wait_for_memory ();
01032               goto reget_service_name_arg;
01033             }
01034           else
01035             {
01036               _dbus_warn ("Message %s doesn't have a service name: %s\n",
01037                           dbus_message_get_name (message),
01038                           error.message);
01039               dbus_error_free (&error);
01040               goto out;
01041             }
01042         }
01043 
01044       if (*service_name != ':')
01045         {
01046           _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
01047                       service_name);
01048           goto out;
01049         }
01050               
01051       base_service = service_name;
01052       service_name = NULL;
01053       
01054       scd.skip_connection = connection;
01055       scd.failed = FALSE;
01056       scd.expected_service_name = base_service;
01057       bus_test_clients_foreach (check_service_created_foreach,
01058                                 &scd);
01059       
01060       if (scd.failed)
01061         goto out;
01062     }
01063   else
01064     {
01065       _dbus_warn ("Expected to get base service ServiceCreated, instead got %s\n",
01066                   dbus_message_get_name (message));
01067       goto out;
01068     }
01069 
01070   retval = TRUE;
01071 
01072   if (base_service_p)
01073     {
01074       *base_service_p = base_service;
01075       base_service = NULL;
01076     }
01077   
01078  out:
01079   if (message)
01080     dbus_message_unref (message);
01081 
01082   if (base_service)
01083     dbus_free (base_service);
01084   
01085   return retval;
01086 }
01087 
01088 static dbus_bool_t
01089 check_service_activated (BusContext     *context,
01090                          DBusConnection *connection,
01091                          const char     *activated_name,
01092                          const char     *base_service_name,
01093                          DBusMessage    *initial_message)
01094 {
01095   DBusMessage *message;
01096   dbus_bool_t retval;
01097   DBusError error;
01098   dbus_uint32_t activation_result;
01099   
01100   retval = FALSE;
01101   
01102   dbus_error_init (&error);
01103 
01104   message = initial_message;
01105   dbus_message_ref (message);
01106 
01107   if (dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
01108     {
01109       char *service_name;
01110       CheckServiceCreatedData scd;
01111 
01112     reget_service_name_arg:
01113       if (!dbus_message_get_args (message, &error,
01114                                   DBUS_TYPE_STRING, &service_name,
01115                                   DBUS_TYPE_INVALID))
01116         {
01117           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
01118             {
01119               dbus_error_free (&error);
01120               _dbus_wait_for_memory ();
01121               goto reget_service_name_arg;
01122             }
01123           else
01124             {
01125               _dbus_warn ("Message %s doesn't have a service name: %s\n",
01126                           dbus_message_get_name (message),
01127                           error.message);
01128               dbus_error_free (&error);
01129               goto out;
01130             }
01131         }
01132 
01133       if (strcmp (service_name, activated_name) != 0)
01134         {
01135           _dbus_warn ("Expected to see service %s created, saw %s instead\n",
01136                       activated_name, service_name);
01137           dbus_free (service_name);
01138           goto out;
01139         }
01140       
01141       scd.skip_connection = connection;
01142       scd.failed = FALSE;
01143       scd.expected_service_name = service_name;
01144       bus_test_clients_foreach (check_service_created_foreach,
01145                                 &scd);
01146           
01147       dbus_free (service_name);
01148 
01149       if (scd.failed)
01150         goto out;
01151           
01152       dbus_message_unref (message);
01153       message = pop_message_waiting_for_memory (connection);
01154       if (message == NULL)
01155         {
01156           _dbus_warn ("Expected a reply to %s, got nothing\n",
01157                       DBUS_MESSAGE_ACTIVATE_SERVICE);
01158           goto out;
01159         }
01160     }
01161   else
01162     {
01163       _dbus_warn ("Expected to get service %s ServiceCreated, instead got %s\n",
01164                   activated_name, dbus_message_get_name (message));
01165       goto out;
01166     }
01167   
01168   if (!dbus_message_has_name (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
01169     {
01170       _dbus_warn ("Expected reply to %s, got message %s instead\n",
01171                   DBUS_MESSAGE_ACTIVATE_SERVICE,
01172                   dbus_message_get_name (message));
01173       goto out;
01174     }
01175 
01176   activation_result = 0;
01177   if (!dbus_message_get_args (message, &error,
01178                               DBUS_TYPE_UINT32, &activation_result,
01179                               DBUS_TYPE_INVALID))
01180     {
01181       if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
01182         {
01183           _dbus_warn ("Did not have activation result first argument to %s: %s\n",
01184                       DBUS_MESSAGE_ACTIVATE_SERVICE, error.message);
01185           dbus_error_free (&error);
01186           goto out;
01187         }
01188 
01189       dbus_error_free (&error);
01190     }
01191   else
01192     {
01193       if (activation_result == DBUS_ACTIVATION_REPLY_ACTIVATED)
01194         ; /* Good */
01195       else if (activation_result == DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE)
01196         ; /* Good also */
01197       else
01198         {
01199           _dbus_warn ("Activation result was 0x%x, no good.\n",
01200                       activation_result);
01201           goto out;
01202         }
01203     }
01204 
01205   dbus_message_unref (message);
01206   message = NULL;
01207       
01208   if (!check_no_leftovers (context))
01209     {
01210       _dbus_warn ("Messages were left over after verifying existent activation results\n");
01211       goto out;
01212     }
01213 
01214   retval = TRUE;
01215   
01216  out:
01217   if (message)
01218     dbus_message_unref (message);
01219   
01220   return retval;
01221 }
01222 
01223 static dbus_bool_t
01224 check_service_deactivated (BusContext     *context,
01225                            DBusConnection *connection,
01226                            const char     *activated_name,
01227                            const char     *base_service)
01228 {
01229   DBusMessage *message;
01230   dbus_bool_t retval;
01231   DBusError error;
01232   CheckServiceDeletedData csdd;
01233 
01234   message = NULL;
01235   retval = FALSE;
01236   
01237   dbus_error_init (&error);
01238 
01239   /* Now we are expecting ServiceDeleted messages for the base
01240    * service and the activated_name.  The base service
01241    * notification is required to come last.
01242    */
01243   csdd.expected_service_name = activated_name;
01244   csdd.failed = FALSE;
01245   bus_test_clients_foreach (check_service_deleted_foreach,
01246                             &csdd);      
01247 
01248   if (csdd.failed)
01249     goto out;
01250       
01251   csdd.expected_service_name = base_service;
01252   csdd.failed = FALSE;
01253   bus_test_clients_foreach (check_service_deleted_foreach,
01254                             &csdd);
01255 
01256   if (csdd.failed)
01257     goto out;
01258       
01259   if (!check_no_leftovers (context))
01260     {
01261       _dbus_warn ("Messages were left over after verifying results of service exiting\n");
01262       goto out;
01263     }
01264 
01265   retval = TRUE;
01266   
01267  out:
01268   if (message)
01269     dbus_message_unref (message);
01270   
01271   return retval;
01272 }
01273 
01274 static dbus_bool_t
01275 check_send_exit_to_service (BusContext     *context,
01276                             DBusConnection *connection,
01277                             const char     *service_name,
01278                             const char     *base_service)
01279 {
01280   dbus_bool_t got_error;
01281   DBusMessage *message;
01282   dbus_int32_t serial;
01283   dbus_bool_t retval;
01284   
01285   _dbus_verbose ("Sending exit message to the test service\n");
01286 
01287   retval = FALSE;
01288   
01289   /* Kill off the test service by sending it a quit message */
01290   message = dbus_message_new ("org.freedesktop.DBus.TestSuiteExit",
01291                               service_name);
01292       
01293   if (message == NULL)
01294     {
01295       /* Do this again; we still need the service to exit... */
01296       if (!check_send_exit_to_service (context, connection,
01297                                        service_name, base_service))
01298         goto out;
01299       
01300       return TRUE;
01301     }
01302       
01303   if (!dbus_connection_send (connection, message, &serial))
01304     {
01305       dbus_message_unref (message);
01306 
01307       /* Do this again; we still need the service to exit... */
01308       if (!check_send_exit_to_service (context, connection,
01309                                        service_name, base_service))
01310         goto out;
01311       
01312       return TRUE;
01313     }
01314 
01315   dbus_message_unref (message);
01316   message = NULL;
01317 
01318   /* send message */
01319   bus_test_run_clients_loop (TRUE);
01320 
01321   /* read it in and write it out to test service */
01322   bus_test_run_bus_loop (context, FALSE);
01323 
01324   /* see if we got an error during message bus dispatching */
01325   bus_test_run_clients_loop (FALSE);
01326   message = dbus_connection_borrow_message (connection);
01327   got_error = message != NULL && dbus_message_get_is_error (message);
01328   if (message)
01329     {
01330       dbus_connection_return_message (connection, message);
01331       message = NULL;
01332     }
01333           
01334   if (!got_error)
01335     {
01336       /* If no error, wait for the test service to exit */
01337       block_connection_until_message_from_bus (context, connection);
01338               
01339       bus_test_run_everything (context);
01340     }
01341 
01342   if (got_error)
01343     {
01344       message = pop_message_waiting_for_memory (connection);
01345       _dbus_assert (message != NULL);
01346 
01347       if (!dbus_message_get_is_error (message))
01348         {
01349           _dbus_warn ("expecting an error reply to asking test service to exit, got %s\n",
01350                       dbus_message_get_name (message));
01351           goto out;
01352         }
01353       else if (!dbus_message_has_name (message, DBUS_ERROR_NO_MEMORY))
01354         {
01355           _dbus_warn ("not expecting error %s when asking test service to exit\n",
01356                       dbus_message_get_name (message));
01357           goto out;
01358         }
01359 
01360       _dbus_verbose ("Got error %s when asking test service to exit\n",
01361                      dbus_message_get_name (message));
01362 
01363       /* Do this again; we still need the service to exit... */
01364       if (!check_send_exit_to_service (context, connection,
01365                                        service_name, base_service))
01366         goto out;
01367     }
01368   else
01369     {
01370       if (!check_service_deactivated (context, connection,
01371                                       service_name, base_service))
01372         goto out;
01373     }
01374 
01375   retval = TRUE;
01376   
01377  out:
01378   if (message)
01379     dbus_message_unref (message);
01380   
01381   return retval;
01382 }
01383 
01384 static dbus_bool_t
01385 check_got_error (BusContext     *context,
01386                  DBusConnection *connection,
01387                  const char     *first_error_name,
01388                  ...)
01389 {
01390   DBusMessage *message;
01391   dbus_bool_t retval;
01392   va_list ap;
01393   dbus_bool_t error_found;
01394   const char *error_name;
01395   
01396   retval = FALSE;
01397   
01398   message = pop_message_waiting_for_memory (connection);
01399   if (message == NULL)
01400     {
01401       _dbus_warn ("Did not get an expected error\n");
01402       goto out;
01403     }
01404 
01405   if (!dbus_message_get_is_error (message))
01406     {
01407       _dbus_warn ("Expected an error, got %s\n",
01408                   dbus_message_get_name (message));
01409       goto out;
01410     }
01411 
01412   error_found = FALSE;
01413 
01414   va_start (ap, first_error_name);
01415   error_name = first_error_name;
01416   while (error_name != NULL)
01417     {
01418       if (dbus_message_has_name (message, error_name))
01419         {
01420           error_found = TRUE;
01421           break;
01422         }
01423       error_name = va_arg (ap, char*);
01424     }
01425   va_end (ap);
01426 
01427   if (!error_found)
01428     {
01429       _dbus_warn ("Expected error %s or other, got %s instead\n",
01430                   first_error_name,
01431                   dbus_message_get_name (message));
01432       goto out;
01433     }
01434 
01435   retval = TRUE;
01436   
01437  out:
01438   if (message)
01439     dbus_message_unref (message);
01440   
01441   return retval;
01442 }
01443           
01444 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
01445 
01446 /* returns TRUE if the correct thing happens,
01447  * but the correct thing may include OOM errors.
01448  */
01449 static dbus_bool_t
01450 check_existent_service_activation (BusContext     *context,
01451                                    DBusConnection *connection)
01452 {
01453   DBusMessage *message;
01454   dbus_int32_t serial;
01455   dbus_bool_t retval;
01456   DBusError error;
01457   char *base_service;
01458 
01459   base_service = NULL;
01460   
01461   dbus_error_init (&error);
01462   
01463   message = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
01464                               DBUS_SERVICE_DBUS);
01465 
01466   if (message == NULL)
01467     return TRUE;
01468 
01469   if (!dbus_message_append_args (message,
01470                                  DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
01471                                  DBUS_TYPE_UINT32, 0,
01472                                  DBUS_TYPE_INVALID))
01473     {
01474       dbus_message_unref (message);
01475       return TRUE;
01476     }
01477   
01478   if (!dbus_connection_send (connection, message, &serial))
01479     {
01480       dbus_message_unref (message);
01481       return TRUE;
01482     }
01483 
01484   dbus_message_unref (message);
01485   message = NULL;
01486 
01487   bus_test_run_everything (context);
01488 
01489   /* now wait for the message bus to hear back from the activated
01490    * service.
01491    */
01492   block_connection_until_message_from_bus (context, connection);
01493 
01494   bus_test_run_everything (context);
01495 
01496   if (!dbus_connection_get_is_connected (connection))
01497     {
01498       _dbus_verbose ("connection was disconnected\n");
01499       return TRUE;
01500     }
01501   
01502   retval = FALSE;
01503   
01504   message = pop_message_waiting_for_memory (connection);
01505   if (message == NULL)
01506     {
01507       _dbus_warn ("Did not receive any messages after %s %d on %p\n",
01508                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
01509       goto out;
01510     }
01511 
01512   _dbus_verbose ("Received %s on %p after sending %s\n",
01513                  dbus_message_get_name (message), connection,
01514                  DBUS_MESSAGE_ACTIVATE_SERVICE);
01515 
01516   if (dbus_message_get_is_error (message))
01517     {
01518       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
01519         {
01520           _dbus_warn ("Message has wrong sender %s\n",
01521                       dbus_message_get_sender (message) ?
01522                       dbus_message_get_sender (message) : "(none)");
01523           goto out;
01524         }
01525       
01526       if (dbus_message_has_name (message,
01527                                  DBUS_ERROR_NO_MEMORY))
01528         {
01529           ; /* good, this is a valid response */
01530         }
01531       else if (dbus_message_has_name (message,
01532                                       DBUS_ERROR_SPAWN_CHILD_EXITED))
01533         {
01534           ; /* good, this is expected also */
01535         }
01536       else
01537         {
01538           _dbus_warn ("Did not expect error %s\n",
01539                       dbus_message_get_name (message));
01540           goto out;
01541         }
01542     }
01543   else
01544     {
01545       dbus_bool_t got_service_deleted;
01546       dbus_bool_t got_error;
01547       
01548       if (!check_base_service_activated (context, connection,
01549                                          message, &base_service))
01550         goto out;
01551 
01552       dbus_message_unref (message);
01553       message = NULL;
01554 
01555       /* We may need to block here for the test service to exit or finish up */
01556       block_connection_until_message_from_bus (context, connection);
01557       
01558       message = dbus_connection_borrow_message (connection);
01559       if (message == NULL)
01560         {
01561           _dbus_warn ("Did not receive any messages after base service creation notification\n");
01562           goto out;
01563         }
01564 
01565       got_service_deleted = dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_DELETED);
01566       got_error = dbus_message_get_is_error (message);
01567       
01568       dbus_connection_return_message (connection, message);
01569       message = NULL;
01570 
01571       if (got_error)
01572         {
01573           if (!check_got_error (context, connection,
01574                                 DBUS_ERROR_SPAWN_CHILD_EXITED,
01575                                 DBUS_ERROR_NO_MEMORY,
01576                                 NULL))
01577             goto out;
01578 
01579           /* A service deleted should be coming along now after this error.
01580            * We can also get the error *after* the service deleted.
01581            */
01582           got_service_deleted = TRUE;
01583         }
01584       
01585       if (got_service_deleted)
01586         {
01587           /* The service started up and got a base address, but then
01588            * failed to register under EXISTENT_SERVICE_NAME
01589            */
01590           CheckServiceDeletedData csdd;
01591           
01592           csdd.expected_service_name = base_service;
01593           csdd.failed = FALSE;
01594           bus_test_clients_foreach (check_service_deleted_foreach,
01595                                     &csdd);
01596 
01597           if (csdd.failed)
01598             goto out;
01599 
01600           /* Now we should get an error about the service exiting
01601            * if we didn't get it before.
01602            */
01603           if (!got_error)
01604             {
01605               block_connection_until_message_from_bus (context, connection);
01606               
01607               /* and process everything again */
01608               bus_test_run_everything (context);
01609               
01610               if (!check_got_error (context, connection,
01611                                     DBUS_ERROR_SPAWN_CHILD_EXITED,
01612                                     NULL))
01613                 goto out;
01614             }
01615         }
01616       else
01617         {
01618           message = pop_message_waiting_for_memory (connection);
01619           if (message == NULL)
01620             {
01621               _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
01622               goto out;
01623             }
01624           
01625           if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
01626                                         base_service, message))
01627             goto out;
01628           
01629           dbus_message_unref (message);
01630           message = NULL;
01631 
01632 
01633           if (!check_no_leftovers (context))
01634             {
01635               _dbus_warn ("Messages were left over after successful activation\n");
01636               goto out;
01637             }
01638 
01639           if (!check_send_exit_to_service (context, connection,
01640                                            EXISTENT_SERVICE_NAME, base_service))
01641             goto out;
01642         }
01643     }
01644   
01645   retval = TRUE;
01646   
01647  out:
01648   if (message)
01649     dbus_message_unref (message);
01650 
01651   if (base_service)
01652     dbus_free (base_service);
01653   
01654   return retval;
01655 }
01656 
01657 /* returns TRUE if the correct thing happens,
01658  * but the correct thing may include OOM errors.
01659  */
01660 static dbus_bool_t
01661 check_segfault_service_activation (BusContext     *context,
01662                                    DBusConnection *connection)
01663 {
01664   DBusMessage *message;
01665   dbus_int32_t serial;
01666   dbus_bool_t retval;
01667   DBusError error;
01668   
01669   dbus_error_init (&error);
01670   
01671   message = dbus_message_new (DBUS_MESSAGE_ACTIVATE_SERVICE,
01672                               DBUS_SERVICE_DBUS);
01673 
01674   if (message == NULL)
01675     return TRUE;
01676 
01677   if (!dbus_message_append_args (message,
01678                                  DBUS_TYPE_STRING,
01679                                  "org.freedesktop.DBus.TestSuiteSegfaultService",
01680                                  DBUS_TYPE_UINT32, 0,
01681                                  DBUS_TYPE_INVALID))
01682     {
01683       dbus_message_unref (message);
01684       return TRUE;
01685     }
01686   
01687   if (!dbus_connection_send (connection, message, &serial))
01688     {
01689       dbus_message_unref (message);
01690       return TRUE;
01691     }
01692 
01693   dbus_message_unref (message);
01694   message = NULL;
01695 
01696   bus_test_run_everything (context);
01697   block_connection_until_message_from_bus (context, connection);
01698   bus_test_run_everything (context);
01699 
01700   if (!dbus_connection_get_is_connected (connection))
01701     {
01702       _dbus_verbose ("connection was disconnected\n");
01703       return TRUE;
01704     }
01705   
01706   retval = FALSE;
01707   
01708   message = pop_message_waiting_for_memory (connection);
01709   if (message == NULL)
01710     {
01711       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
01712                   DBUS_MESSAGE_ACTIVATE_SERVICE, serial, connection);
01713       goto out;
01714     }
01715 
01716   _dbus_verbose ("Received %s on %p\n",
01717                  dbus_message_get_name (message), connection);
01718 
01719   if (dbus_message_get_is_error (message))
01720     {
01721       if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
01722         {
01723           _dbus_warn ("Message has wrong sender %s\n",
01724                       dbus_message_get_sender (message) ?
01725                       dbus_message_get_sender (message) : "(none)");
01726           goto out;
01727         }
01728       
01729       if (dbus_message_has_name (message,
01730                                 DBUS_ERROR_NO_MEMORY))
01731         {
01732           ; /* good, this is a valid response */
01733         }
01734       else if (dbus_message_has_name (message,
01735                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED))
01736         {
01737           ; /* good, this is expected also */
01738         }
01739       else
01740         {
01741           _dbus_warn ("Did not expect error %s\n",
01742                       dbus_message_get_name (message));
01743           goto out;
01744         }
01745     }
01746   else
01747     {
01748       _dbus_warn ("Did not expect to successfully activate segfault service\n");
01749       goto out;
01750     }
01751 
01752   retval = TRUE;
01753   
01754  out:
01755   if (message)
01756     dbus_message_unref (message);
01757   
01758   return retval;
01759 }
01760 
01761 typedef struct
01762 {
01763   Check1Func func;
01764   BusContext *context;
01765 } Check1Data;
01766 
01767 static dbus_bool_t
01768 check_oom_check1_func (void *data)
01769 {
01770   Check1Data *d = data;
01771 
01772   if (! (* d->func) (d->context))
01773     return FALSE;
01774   
01775   if (!check_no_leftovers (d->context))
01776     {
01777       _dbus_warn ("Messages were left over, should be covered by test suite\n");
01778       return FALSE;
01779     }
01780 
01781   return TRUE;
01782 }
01783 
01784 static void
01785 check1_try_iterations (BusContext *context,
01786                        const char *description,
01787                        Check1Func  func)
01788 {
01789   Check1Data d;
01790 
01791   d.func = func;
01792   d.context = context;
01793 
01794   if (!_dbus_test_oom_handling (description, check_oom_check1_func,
01795                                 &d))
01796     _dbus_assert_not_reached ("test failed");
01797 }
01798 
01799 typedef struct
01800 {
01801   Check2Func func;
01802   BusContext *context;
01803   DBusConnection *connection;
01804 } Check2Data;
01805 
01806 static dbus_bool_t
01807 check_oom_check2_func (void *data)
01808 {
01809   Check2Data *d = data;
01810 
01811   if (! (* d->func) (d->context, d->connection))
01812     return FALSE;
01813   
01814   if (!check_no_leftovers (d->context))
01815     {
01816       _dbus_warn ("Messages were left over, should be covered by test suite");
01817       return FALSE;
01818     }
01819 
01820   return TRUE;
01821 }
01822 
01823 static void
01824 check2_try_iterations (BusContext     *context,
01825                        DBusConnection *connection,
01826                        const char     *description,
01827                        Check2Func      func)
01828 {
01829   Check2Data d;
01830 
01831   d.func = func;
01832   d.context = context;
01833   d.connection = connection;
01834   
01835   if (!_dbus_test_oom_handling (description, check_oom_check2_func,
01836                                 &d))
01837     _dbus_assert_not_reached ("test failed");
01838 }
01839 
01840 dbus_bool_t
01841 bus_dispatch_test (const DBusString *test_data_dir)
01842 {
01843   BusContext *context;
01844   DBusConnection *foo;
01845   DBusConnection *bar;
01846   DBusConnection *baz;
01847   DBusError error;
01848 
01849   dbus_error_init (&error);
01850   
01851   context = bus_context_new_test (test_data_dir,
01852                                   "valid-config-files/debug-allow-all.conf");
01853   if (context == NULL)
01854     return FALSE;
01855   
01856   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
01857   if (foo == NULL)
01858     _dbus_assert_not_reached ("could not alloc connection");
01859 
01860   if (!bus_setup_debug_client (foo))
01861     _dbus_assert_not_reached ("could not set up connection");
01862 
01863   if (!check_hello_message (context, foo))
01864     _dbus_assert_not_reached ("hello message failed");
01865   
01866   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
01867   if (bar == NULL)
01868     _dbus_assert_not_reached ("could not alloc connection");
01869 
01870   if (!bus_setup_debug_client (bar))
01871     _dbus_assert_not_reached ("could not set up connection");
01872 
01873   if (!check_hello_message (context, bar))
01874     _dbus_assert_not_reached ("hello message failed");
01875   
01876   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
01877   if (baz == NULL)
01878     _dbus_assert_not_reached ("could not alloc connection");
01879 
01880   if (!bus_setup_debug_client (baz))
01881     _dbus_assert_not_reached ("could not set up connection");
01882 
01883   if (!check_hello_message (context, baz))
01884     _dbus_assert_not_reached ("hello message failed");
01885 
01886   if (!check_no_leftovers (context))
01887     {
01888       _dbus_warn ("Messages were left over after setting up initial connections");
01889       _dbus_assert_not_reached ("initial connection setup failed");
01890     }
01891   
01892   check1_try_iterations (context, "create_and_hello",
01893                          check_hello_connection);
01894   
01895   check2_try_iterations (context, foo, "nonexistent_service_activation",
01896                          check_nonexistent_service_activation);
01897 
01898   check2_try_iterations (context, foo, "segfault_service_activation",
01899                          check_segfault_service_activation);
01900   
01901   check2_try_iterations (context, foo, "existent_service_activation",
01902                          check_existent_service_activation);
01903   
01904   _dbus_verbose ("Disconnecting foo, bar, and baz\n");
01905 
01906   kill_client_connection_unchecked (foo);
01907   kill_client_connection_unchecked (bar);
01908   kill_client_connection_unchecked (baz);
01909 
01910   bus_context_unref (context);
01911   
01912   return TRUE;
01913 }
01914 
01915 dbus_bool_t
01916 bus_dispatch_sha1_test (const DBusString *test_data_dir)
01917 {
01918   BusContext *context;
01919   DBusConnection *foo;
01920   DBusError error;
01921 
01922   dbus_error_init (&error);
01923   
01924   /* Test SHA1 authentication */
01925   _dbus_verbose ("Testing SHA1 context\n");
01926   
01927   context = bus_context_new_test (test_data_dir,
01928                                   "valid-config-files/debug-allow-all-sha1.conf");
01929   if (context == NULL)
01930     return FALSE;
01931 
01932   foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
01933   if (foo == NULL)
01934     _dbus_assert_not_reached ("could not alloc connection");
01935 
01936   if (!bus_setup_debug_client (foo))
01937     _dbus_assert_not_reached ("could not set up connection");
01938 
01939   if (!check_hello_message (context, foo))
01940     _dbus_assert_not_reached ("hello message failed");
01941 
01942   if (!check_no_leftovers (context))
01943     {
01944       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
01945       _dbus_assert_not_reached ("initial connection setup failed");
01946     }
01947   
01948   check1_try_iterations (context, "create_and_hello_sha1",
01949                          check_hello_connection);
01950 
01951   kill_client_connection_unchecked (foo);
01952 
01953   bus_context_unref (context);
01954 
01955   return TRUE;
01956 }
01957 
01958 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Oct 22 14:05:05 2003 for D-BUS by doxygen1.3-rc3