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

Generated on Mon Sep 29 21:31:02 2003 for D-BUS by doxygen1.2.15