• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-server.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-server.c DBusServer object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */ 
00023 
00024 #include "dbus-server.h"
00025 #include "dbus-server-unix.h"
00026 #include "dbus-server-socket.h"
00027 #include "dbus-string.h"
00028 #ifdef DBUS_BUILD_TESTS
00029 #include "dbus-server-debug-pipe.h"
00030 #endif
00031 #include "dbus-address.h"
00032 #include "dbus-protocol.h"
00033 
00055 /* this is a little fragile since it assumes the address doesn't
00056  * already have a guid, but it shouldn't
00057  */
00058 static char*
00059 copy_address_with_guid_appended (const DBusString *address,
00060                                  const DBusString *guid_hex)
00061 {
00062   DBusString with_guid;
00063   char *retval;
00064   
00065   if (!_dbus_string_init (&with_guid))
00066     return NULL;
00067 
00068   if (!_dbus_string_copy (address, 0, &with_guid,
00069                           _dbus_string_get_length (&with_guid)) ||
00070       !_dbus_string_append (&with_guid, ",guid=") ||
00071       !_dbus_string_copy (guid_hex, 0,
00072                           &with_guid, _dbus_string_get_length (&with_guid)))
00073     {
00074       _dbus_string_free (&with_guid);
00075       return NULL;
00076     }
00077 
00078   retval = NULL;
00079   _dbus_string_steal_data (&with_guid, &retval);
00080 
00081   _dbus_string_free (&with_guid);
00082       
00083   return retval; /* may be NULL if steal_data failed */
00084 }
00085 
00095 dbus_bool_t
00096 _dbus_server_init_base (DBusServer             *server,
00097                         const DBusServerVTable *vtable,
00098                         const DBusString       *address)
00099 {
00100   server->vtable = vtable;
00101   server->refcount.value = 1;
00102 
00103   server->address = NULL;
00104   server->watches = NULL;
00105   server->timeouts = NULL;
00106 
00107   if (!_dbus_string_init (&server->guid_hex))
00108     return FALSE;
00109 
00110   _dbus_generate_uuid (&server->guid);
00111 
00112   if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
00113     goto failed;
00114   
00115   server->address = copy_address_with_guid_appended (address,
00116                                                      &server->guid_hex);
00117   if (server->address == NULL)
00118     goto failed;
00119   
00120   _dbus_mutex_new_at_location (&server->mutex);
00121   if (server->mutex == NULL)
00122     goto failed;
00123   
00124   server->watches = _dbus_watch_list_new ();
00125   if (server->watches == NULL)
00126     goto failed;
00127 
00128   server->timeouts = _dbus_timeout_list_new ();
00129   if (server->timeouts == NULL)
00130     goto failed;
00131 
00132   _dbus_data_slot_list_init (&server->slot_list);
00133 
00134   _dbus_verbose ("Initialized server on address %s\n", server->address);
00135   
00136   return TRUE;
00137 
00138  failed:
00139   _dbus_mutex_free_at_location (&server->mutex);
00140   server->mutex = NULL;
00141   if (server->watches)
00142     {
00143       _dbus_watch_list_free (server->watches);
00144       server->watches = NULL;
00145     }
00146   if (server->timeouts)
00147     {
00148       _dbus_timeout_list_free (server->timeouts);
00149       server->timeouts = NULL;
00150     }
00151   if (server->address)
00152     {
00153       dbus_free (server->address);
00154       server->address = NULL;
00155     }
00156   _dbus_string_free (&server->guid_hex);
00157   
00158   return FALSE;
00159 }
00160 
00167 void
00168 _dbus_server_finalize_base (DBusServer *server)
00169 {
00170   /* We don't have the lock, but nobody should be accessing
00171    * concurrently since they don't have a ref
00172    */
00173 #ifndef DBUS_DISABLE_CHECKS
00174   _dbus_assert (!server->have_server_lock);
00175 #endif
00176   _dbus_assert (server->disconnected);
00177   
00178   /* calls out to application code... */
00179   _dbus_data_slot_list_free (&server->slot_list);
00180 
00181   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00182 
00183   _dbus_watch_list_free (server->watches);
00184   _dbus_timeout_list_free (server->timeouts);
00185 
00186   _dbus_mutex_free_at_location (&server->mutex);
00187   
00188   dbus_free (server->address);
00189 
00190   dbus_free_string_array (server->auth_mechanisms);
00191 
00192   _dbus_string_free (&server->guid_hex);
00193 }
00194 
00195 
00197 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00198                                                   DBusWatch     *watch);
00200 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00201                                                   DBusWatch     *watch);
00203 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00204                                                   DBusWatch     *watch,
00205                                                   dbus_bool_t    enabled);
00206 
00207 static dbus_bool_t
00208 protected_change_watch (DBusServer             *server,
00209                         DBusWatch              *watch,
00210                         DBusWatchAddFunction    add_function,
00211                         DBusWatchRemoveFunction remove_function,
00212                         DBusWatchToggleFunction toggle_function,
00213                         dbus_bool_t             enabled)
00214 {
00215   DBusWatchList *watches;
00216   dbus_bool_t retval;
00217   
00218   HAVE_LOCK_CHECK (server);
00219 
00220   /* This isn't really safe or reasonable; a better pattern is the "do
00221    * everything, then drop lock and call out" one; but it has to be
00222    * propagated up through all callers
00223    */
00224   
00225   watches = server->watches;
00226   if (watches)
00227     {
00228       server->watches = NULL;
00229       _dbus_server_ref_unlocked (server);
00230       SERVER_UNLOCK (server);
00231 
00232       if (add_function)
00233         retval = (* add_function) (watches, watch);
00234       else if (remove_function)
00235         {
00236           retval = TRUE;
00237           (* remove_function) (watches, watch);
00238         }
00239       else
00240         {
00241           retval = TRUE;
00242           (* toggle_function) (watches, watch, enabled);
00243         }
00244       
00245       SERVER_LOCK (server);
00246       server->watches = watches;
00247       _dbus_server_unref_unlocked (server);
00248 
00249       return retval;
00250     }
00251   else
00252     return FALSE;
00253 }
00254 
00262 dbus_bool_t
00263 _dbus_server_add_watch (DBusServer *server,
00264                         DBusWatch  *watch)
00265 {
00266   HAVE_LOCK_CHECK (server);
00267   return protected_change_watch (server, watch,
00268                                  _dbus_watch_list_add_watch,
00269                                  NULL, NULL, FALSE);
00270 }
00271 
00278 void
00279 _dbus_server_remove_watch  (DBusServer *server,
00280                             DBusWatch  *watch)
00281 {
00282   HAVE_LOCK_CHECK (server);
00283   protected_change_watch (server, watch,
00284                           NULL,
00285                           _dbus_watch_list_remove_watch,
00286                           NULL, FALSE);
00287 }
00288 
00296 void
00297 _dbus_server_toggle_all_watches (DBusServer  *server,
00298                                 dbus_bool_t  enabled)
00299 {
00300   _dbus_watch_list_toggle_all_watches (server->watches, enabled);
00301 }
00302 
00304 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00305                                                    DBusTimeout     *timeout);
00307 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00308                                                    DBusTimeout     *timeout);
00310 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00311                                                    DBusTimeout     *timeout,
00312                                                    dbus_bool_t      enabled);
00313 
00314 
00315 static dbus_bool_t
00316 protected_change_timeout (DBusServer               *server,
00317                           DBusTimeout              *timeout,
00318                           DBusTimeoutAddFunction    add_function,
00319                           DBusTimeoutRemoveFunction remove_function,
00320                           DBusTimeoutToggleFunction toggle_function,
00321                           dbus_bool_t               enabled)
00322 {
00323   DBusTimeoutList *timeouts;
00324   dbus_bool_t retval;
00325   
00326   HAVE_LOCK_CHECK (server);
00327 
00328   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00329    * drop lock and call out" one; but it has to be propagated up through all callers
00330    */
00331   
00332   timeouts = server->timeouts;
00333   if (timeouts)
00334     {
00335       server->timeouts = NULL;
00336       _dbus_server_ref_unlocked (server);
00337       SERVER_UNLOCK (server);
00338 
00339       if (add_function)
00340         retval = (* add_function) (timeouts, timeout);
00341       else if (remove_function)
00342         {
00343           retval = TRUE;
00344           (* remove_function) (timeouts, timeout);
00345         }
00346       else
00347         {
00348           retval = TRUE;
00349           (* toggle_function) (timeouts, timeout, enabled);
00350         }
00351       
00352       SERVER_LOCK (server);
00353       server->timeouts = timeouts;
00354       _dbus_server_unref_unlocked (server);
00355 
00356       return retval;
00357     }
00358   else
00359     return FALSE;
00360 }
00361 
00371 dbus_bool_t
00372 _dbus_server_add_timeout (DBusServer  *server,
00373                           DBusTimeout *timeout)
00374 {
00375   return protected_change_timeout (server, timeout,
00376                                    _dbus_timeout_list_add_timeout,
00377                                    NULL, NULL, FALSE);
00378 }
00379 
00386 void
00387 _dbus_server_remove_timeout (DBusServer  *server,
00388                              DBusTimeout *timeout)
00389 {
00390   protected_change_timeout (server, timeout,
00391                             NULL,
00392                             _dbus_timeout_list_remove_timeout,
00393                             NULL, FALSE);
00394 }
00395 
00405 void
00406 _dbus_server_toggle_timeout (DBusServer  *server,
00407                              DBusTimeout *timeout,
00408                              dbus_bool_t  enabled)
00409 {
00410   protected_change_timeout (server, timeout,
00411                             NULL, NULL,
00412                             _dbus_timeout_list_toggle_timeout,
00413                             enabled);
00414 }
00415 
00416 
00422 void
00423 _dbus_server_ref_unlocked (DBusServer *server)
00424 {
00425   _dbus_assert (server != NULL);
00426   _dbus_assert (server->refcount.value > 0);
00427   
00428   HAVE_LOCK_CHECK (server);
00429 
00430 #ifdef DBUS_HAVE_ATOMIC_INT
00431   _dbus_atomic_inc (&server->refcount);
00432 #else
00433   _dbus_assert (server->refcount.value > 0);
00434 
00435   server->refcount.value += 1;
00436 #endif
00437 }
00438 
00444 void
00445 _dbus_server_unref_unlocked (DBusServer *server)
00446 {
00447   dbus_bool_t last_unref;
00448 
00449   /* Keep this in sync with dbus_server_unref */
00450   
00451   _dbus_assert (server != NULL);
00452   _dbus_assert (server->refcount.value > 0);
00453 
00454   HAVE_LOCK_CHECK (server);
00455   
00456 #ifdef DBUS_HAVE_ATOMIC_INT
00457   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00458 #else
00459   _dbus_assert (server->refcount.value > 0);
00460 
00461   server->refcount.value -= 1;
00462   last_unref = (server->refcount.value == 0);
00463 #endif
00464   
00465   if (last_unref)
00466     {
00467       _dbus_assert (server->disconnected);
00468       
00469       SERVER_UNLOCK (server);
00470       
00471       _dbus_assert (server->vtable->finalize != NULL);
00472       
00473       (* server->vtable->finalize) (server);
00474     }
00475 }
00476 
00498 static const struct {
00499   DBusServerListenResult (* func) (DBusAddressEntry *entry,
00500                                    DBusServer      **server_p,
00501                                    DBusError        *error);
00502 } listen_funcs[] = {
00503   { _dbus_server_listen_socket }
00504   , { _dbus_server_listen_platform_specific }
00505 #ifdef DBUS_BUILD_TESTS
00506   , { _dbus_server_listen_debug_pipe }
00507 #endif
00508 };
00509 
00530 DBusServer*
00531 dbus_server_listen (const char     *address,
00532                     DBusError      *error)
00533 {
00534   DBusServer *server;
00535   DBusAddressEntry **entries;
00536   int len, i;
00537   DBusError first_connect_error = DBUS_ERROR_INIT;
00538   dbus_bool_t handled_once;
00539   
00540   _dbus_return_val_if_fail (address != NULL, NULL);
00541   _dbus_return_val_if_error_is_set (error, NULL);
00542   
00543   if (!dbus_parse_address (address, &entries, &len, error))
00544     return NULL;
00545 
00546   server = NULL;
00547   handled_once = FALSE;
00548 
00549   for (i = 0; i < len; i++)
00550     {
00551       int j;
00552 
00553       for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
00554         {
00555           DBusServerListenResult result;
00556           DBusError tmp_error = DBUS_ERROR_INIT;
00557 
00558           result = (* listen_funcs[j].func) (entries[i],
00559                                              &server,
00560                                              &tmp_error);
00561 
00562           if (result == DBUS_SERVER_LISTEN_OK)
00563             {
00564               _dbus_assert (server != NULL);
00565               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00566               handled_once = TRUE;
00567               goto out;
00568             }
00569           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
00570             {
00571               _dbus_assert (server == NULL);
00572               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00573               dbus_move_error (&tmp_error, error);
00574               handled_once = TRUE;
00575               goto out;
00576             }
00577           else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
00578             {
00579               _dbus_assert (server == NULL);
00580               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00581 
00582               /* keep trying addresses */
00583             }
00584           else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
00585             {
00586               _dbus_assert (server == NULL);
00587               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00588               if (!dbus_error_is_set (&first_connect_error))
00589                 dbus_move_error (&tmp_error, &first_connect_error);
00590               else
00591                 dbus_error_free (&tmp_error);
00592 
00593               handled_once = TRUE;
00594               
00595               /* keep trying addresses */
00596             }
00597         }
00598 
00599       _dbus_assert (server == NULL);
00600       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00601     }
00602 
00603  out:
00604 
00605   if (!handled_once)
00606     {
00607       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00608       if (len > 0)
00609         dbus_set_error (error,
00610                        DBUS_ERROR_BAD_ADDRESS,
00611                        "Unknown address type '%s'",
00612                        dbus_address_entry_get_method (entries[0]));
00613       else
00614         dbus_set_error (error,
00615                         DBUS_ERROR_BAD_ADDRESS,
00616                         "Empty address '%s'",
00617                         address);
00618     }
00619   
00620   dbus_address_entries_free (entries);
00621 
00622   if (server == NULL)
00623     {
00624       _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
00625                    dbus_error_is_set (error));
00626       
00627       if (error && dbus_error_is_set (error))
00628         {
00629           /* already set the error */
00630         }
00631       else
00632         {
00633           /* didn't set the error but either error should be
00634            * NULL or first_connect_error should be set.
00635            */
00636           _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
00637           dbus_move_error (&first_connect_error, error);
00638         }
00639 
00640       _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
00641       _DBUS_ASSERT_ERROR_IS_SET (error);
00642 
00643       return NULL;
00644     }
00645   else
00646     {
00647       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00648       return server;
00649     }
00650 }
00651 
00658 DBusServer *
00659 dbus_server_ref (DBusServer *server)
00660 {
00661   _dbus_return_val_if_fail (server != NULL, NULL);
00662   _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
00663 
00664 #ifdef DBUS_HAVE_ATOMIC_INT
00665   _dbus_atomic_inc (&server->refcount);
00666 #else
00667   SERVER_LOCK (server);
00668   _dbus_assert (server->refcount.value > 0);
00669 
00670   server->refcount.value += 1;
00671   SERVER_UNLOCK (server);
00672 #endif
00673 
00674   return server;
00675 }
00676 
00685 void
00686 dbus_server_unref (DBusServer *server)
00687 {
00688   dbus_bool_t last_unref;
00689 
00690   /* keep this in sync with unref_unlocked */
00691   
00692   _dbus_return_if_fail (server != NULL);
00693   _dbus_return_if_fail (server->refcount.value > 0);
00694 
00695 #ifdef DBUS_HAVE_ATOMIC_INT
00696   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00697 #else
00698   SERVER_LOCK (server);
00699   
00700   _dbus_assert (server->refcount.value > 0);
00701 
00702   server->refcount.value -= 1;
00703   last_unref = (server->refcount.value == 0);
00704   
00705   SERVER_UNLOCK (server);
00706 #endif
00707   
00708   if (last_unref)
00709     {
00710       /* lock not held! */
00711       _dbus_assert (server->disconnected);
00712       
00713       _dbus_assert (server->vtable->finalize != NULL);
00714       
00715       (* server->vtable->finalize) (server);
00716     }
00717 }
00718 
00727 void
00728 dbus_server_disconnect (DBusServer *server)
00729 {
00730   _dbus_return_if_fail (server != NULL);
00731   _dbus_return_if_fail (server->refcount.value > 0);
00732 
00733   SERVER_LOCK (server);
00734   _dbus_server_ref_unlocked (server);
00735   
00736   _dbus_assert (server->vtable->disconnect != NULL);
00737 
00738   if (!server->disconnected)
00739     {
00740       /* this has to be first so recursive calls to disconnect don't happen */
00741       server->disconnected = TRUE;
00742       
00743       (* server->vtable->disconnect) (server);
00744     }
00745 
00746   SERVER_UNLOCK (server);
00747   dbus_server_unref (server);
00748 }
00749 
00755 dbus_bool_t
00756 dbus_server_get_is_connected (DBusServer *server)
00757 {
00758   dbus_bool_t retval;
00759   
00760   _dbus_return_val_if_fail (server != NULL, FALSE);
00761 
00762   SERVER_LOCK (server);
00763   retval = !server->disconnected;
00764   SERVER_UNLOCK (server);
00765 
00766   return retval;
00767 }
00768 
00776 char*
00777 dbus_server_get_address (DBusServer *server)
00778 {
00779   char *retval;
00780   
00781   _dbus_return_val_if_fail (server != NULL, NULL);
00782 
00783   SERVER_LOCK (server);
00784   retval = _dbus_strdup (server->address);
00785   SERVER_UNLOCK (server);
00786 
00787   return retval;
00788 }
00789 
00812 char*
00813 dbus_server_get_id (DBusServer *server)
00814 {
00815   char *retval;
00816   
00817   _dbus_return_val_if_fail (server != NULL, NULL);
00818 
00819   SERVER_LOCK (server);
00820   retval = NULL;
00821   _dbus_string_copy_data (&server->guid_hex, &retval);
00822   SERVER_UNLOCK (server);
00823 
00824   return retval;
00825 }
00826 
00847 void
00848 dbus_server_set_new_connection_function (DBusServer                *server,
00849                                          DBusNewConnectionFunction  function,
00850                                          void                      *data,
00851                                          DBusFreeFunction           free_data_function)
00852 {
00853   DBusFreeFunction old_free_function;
00854   void *old_data;
00855   
00856   _dbus_return_if_fail (server != NULL);
00857 
00858   SERVER_LOCK (server);
00859   old_free_function = server->new_connection_free_data_function;
00860   old_data = server->new_connection_data;
00861   
00862   server->new_connection_function = function;
00863   server->new_connection_data = data;
00864   server->new_connection_free_data_function = free_data_function;
00865   SERVER_UNLOCK (server);
00866     
00867   if (old_free_function != NULL)
00868     (* old_free_function) (old_data);
00869 }
00870 
00887 dbus_bool_t
00888 dbus_server_set_watch_functions (DBusServer              *server,
00889                                  DBusAddWatchFunction     add_function,
00890                                  DBusRemoveWatchFunction  remove_function,
00891                                  DBusWatchToggledFunction toggled_function,
00892                                  void                    *data,
00893                                  DBusFreeFunction         free_data_function)
00894 {
00895   dbus_bool_t result;
00896   DBusWatchList *watches;
00897   
00898   _dbus_return_val_if_fail (server != NULL, FALSE);
00899 
00900   SERVER_LOCK (server);
00901   watches = server->watches;
00902   server->watches = NULL;
00903   if (watches)
00904     {
00905       SERVER_UNLOCK (server);
00906       result = _dbus_watch_list_set_functions (watches,
00907                                                add_function,
00908                                                remove_function,
00909                                                toggled_function,
00910                                                data,
00911                                                free_data_function);
00912       SERVER_LOCK (server);
00913     }
00914   else
00915     {
00916       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00917       result = FALSE;
00918     }
00919   server->watches = watches;
00920   SERVER_UNLOCK (server);
00921   
00922   return result;
00923 }
00924 
00940 dbus_bool_t
00941 dbus_server_set_timeout_functions (DBusServer                *server,
00942                                    DBusAddTimeoutFunction     add_function,
00943                                    DBusRemoveTimeoutFunction  remove_function,
00944                                    DBusTimeoutToggledFunction toggled_function,
00945                                    void                      *data,
00946                                    DBusFreeFunction           free_data_function)
00947 {
00948   dbus_bool_t result;
00949   DBusTimeoutList *timeouts;
00950   
00951   _dbus_return_val_if_fail (server != NULL, FALSE);
00952 
00953   SERVER_LOCK (server);
00954   timeouts = server->timeouts;
00955   server->timeouts = NULL;
00956   if (timeouts)
00957     {
00958       SERVER_UNLOCK (server);
00959       result = _dbus_timeout_list_set_functions (timeouts,
00960                                                  add_function,
00961                                                  remove_function,
00962                                                  toggled_function,
00963                                                  data,
00964                                                  free_data_function);
00965       SERVER_LOCK (server);
00966     }
00967   else
00968     {
00969       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00970       result = FALSE;
00971     }
00972   server->timeouts = timeouts;
00973   SERVER_UNLOCK (server);
00974   
00975   return result;
00976 }
00977 
00991 dbus_bool_t
00992 dbus_server_set_auth_mechanisms (DBusServer  *server,
00993                                  const char **mechanisms)
00994 {
00995   char **copy;
00996 
00997   _dbus_return_val_if_fail (server != NULL, FALSE);
00998 
00999   SERVER_LOCK (server);
01000   
01001   if (mechanisms != NULL)
01002     {
01003       copy = _dbus_dup_string_array (mechanisms);
01004       if (copy == NULL)
01005         return FALSE;
01006     }
01007   else
01008     copy = NULL;
01009 
01010   dbus_free_string_array (server->auth_mechanisms);
01011   server->auth_mechanisms = copy;
01012 
01013   SERVER_UNLOCK (server);
01014   
01015   return TRUE;
01016 }
01017 
01018 
01019 static DBusDataSlotAllocator slot_allocator;
01020 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01021 
01036 dbus_bool_t
01037 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01038 {
01039   return _dbus_data_slot_allocator_alloc (&slot_allocator,
01040                                           (DBusMutex **)&_DBUS_LOCK_NAME (server_slots),
01041                                           slot_p);
01042 }
01043 
01055 void
01056 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01057 {
01058   _dbus_return_if_fail (*slot_p >= 0);
01059   
01060   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01061 }
01062 
01076 dbus_bool_t
01077 dbus_server_set_data (DBusServer       *server,
01078                       int               slot,
01079                       void             *data,
01080                       DBusFreeFunction  free_data_func)
01081 {
01082   DBusFreeFunction old_free_func;
01083   void *old_data;
01084   dbus_bool_t retval;
01085 
01086   _dbus_return_val_if_fail (server != NULL, FALSE);
01087 
01088   SERVER_LOCK (server);
01089   
01090   retval = _dbus_data_slot_list_set (&slot_allocator,
01091                                      &server->slot_list,
01092                                      slot, data, free_data_func,
01093                                      &old_free_func, &old_data);
01094 
01095 
01096   SERVER_UNLOCK (server);
01097   
01098   if (retval)
01099     {
01100       /* Do the actual free outside the server lock */
01101       if (old_free_func)
01102         (* old_free_func) (old_data);
01103     }
01104 
01105   return retval;
01106 }
01107 
01116 void*
01117 dbus_server_get_data (DBusServer   *server,
01118                       int           slot)
01119 {
01120   void *res;
01121 
01122   _dbus_return_val_if_fail (server != NULL, NULL);
01123   
01124   SERVER_LOCK (server);
01125   
01126   res = _dbus_data_slot_list_get (&slot_allocator,
01127                                   &server->slot_list,
01128                                   slot);
01129 
01130   SERVER_UNLOCK (server);
01131   
01132   return res;
01133 }
01134 
01137 #ifdef DBUS_BUILD_TESTS
01138 #include "dbus-test.h"
01139 #include <string.h>
01140 
01141 dbus_bool_t
01142 _dbus_server_test (void)
01143 {
01144   const char *valid_addresses[] = {
01145     "tcp:port=1234",
01146     "tcp:host=localhost,port=1234",
01147     "tcp:host=localhost,port=1234;tcp:port=5678",
01148 #ifdef DBUS_UNIX
01149     "unix:path=./boogie",
01150     "tcp:port=1234;unix:path=./boogie",
01151 #endif
01152   };
01153 
01154   DBusServer *server;
01155   int i;
01156   
01157   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01158     {
01159       DBusError error = DBUS_ERROR_INIT;
01160       char *address;
01161       char *id;
01162 
01163       server = dbus_server_listen (valid_addresses[i], &error);
01164       if (server == NULL)
01165         {
01166           _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
01167           dbus_error_free (&error);
01168           _dbus_assert_not_reached ("Failed to listen for valid address.");
01169         }
01170 
01171       id = dbus_server_get_id (server);
01172       _dbus_assert (id != NULL);
01173       address = dbus_server_get_address (server);
01174       _dbus_assert (address != NULL);
01175 
01176       if (strstr (address, id) == NULL)
01177         {
01178           _dbus_warn ("server id '%s' is not in the server address '%s'\n",
01179                       id, address);
01180           _dbus_assert_not_reached ("bad server id or address");
01181         }
01182 
01183       dbus_free (id);
01184       dbus_free (address);
01185       
01186       dbus_server_disconnect (server);
01187       dbus_server_unref (server);
01188     }
01189 
01190   return TRUE;
01191 }
01192 
01193 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Nov 19 2014 17:15:21 for D-Bus by  doxygen 1.7.1