• 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 <config.h>
00025 #include "dbus-server.h"
00026 #include "dbus-server-unix.h"
00027 #include "dbus-server-socket.h"
00028 #include "dbus-string.h"
00029 #ifdef DBUS_BUILD_TESTS
00030 #include "dbus-server-debug-pipe.h"
00031 #endif
00032 #include "dbus-address.h"
00033 #include "dbus-protocol.h"
00034 
00056 /* this is a little fragile since it assumes the address doesn't
00057  * already have a guid, but it shouldn't
00058  */
00059 static char*
00060 copy_address_with_guid_appended (const DBusString *address,
00061                                  const DBusString *guid_hex)
00062 {
00063   DBusString with_guid;
00064   char *retval;
00065   
00066   if (!_dbus_string_init (&with_guid))
00067     return NULL;
00068 
00069   if (!_dbus_string_copy (address, 0, &with_guid,
00070                           _dbus_string_get_length (&with_guid)) ||
00071       !_dbus_string_append (&with_guid, ",guid=") ||
00072       !_dbus_string_copy (guid_hex, 0,
00073                           &with_guid, _dbus_string_get_length (&with_guid)))
00074     {
00075       _dbus_string_free (&with_guid);
00076       return NULL;
00077     }
00078 
00079   retval = NULL;
00080   _dbus_string_steal_data (&with_guid, &retval);
00081 
00082   _dbus_string_free (&with_guid);
00083       
00084   return retval; /* may be NULL if steal_data failed */
00085 }
00086 
00096 dbus_bool_t
00097 _dbus_server_init_base (DBusServer             *server,
00098                         const DBusServerVTable *vtable,
00099                         const DBusString       *address)
00100 {
00101   server->vtable = vtable;
00102   server->refcount.value = 1;
00103 
00104   server->address = NULL;
00105   server->watches = NULL;
00106   server->timeouts = NULL;
00107 
00108   if (!_dbus_string_init (&server->guid_hex))
00109     return FALSE;
00110 
00111   _dbus_generate_uuid (&server->guid);
00112 
00113   if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
00114     goto failed;
00115   
00116   server->address = copy_address_with_guid_appended (address,
00117                                                      &server->guid_hex);
00118   if (server->address == NULL)
00119     goto failed;
00120   
00121   _dbus_mutex_new_at_location (&server->mutex);
00122   if (server->mutex == NULL)
00123     goto failed;
00124   
00125   server->watches = _dbus_watch_list_new ();
00126   if (server->watches == NULL)
00127     goto failed;
00128 
00129   server->timeouts = _dbus_timeout_list_new ();
00130   if (server->timeouts == NULL)
00131     goto failed;
00132 
00133   _dbus_data_slot_list_init (&server->slot_list);
00134 
00135   _dbus_verbose ("Initialized server on address %s\n", server->address);
00136   
00137   return TRUE;
00138 
00139  failed:
00140   _dbus_mutex_free_at_location (&server->mutex);
00141   server->mutex = NULL;
00142   if (server->watches)
00143     {
00144       _dbus_watch_list_free (server->watches);
00145       server->watches = NULL;
00146     }
00147   if (server->timeouts)
00148     {
00149       _dbus_timeout_list_free (server->timeouts);
00150       server->timeouts = NULL;
00151     }
00152   if (server->address)
00153     {
00154       dbus_free (server->address);
00155       server->address = NULL;
00156     }
00157   _dbus_string_free (&server->guid_hex);
00158   
00159   return FALSE;
00160 }
00161 
00168 void
00169 _dbus_server_finalize_base (DBusServer *server)
00170 {
00171   /* We don't have the lock, but nobody should be accessing
00172    * concurrently since they don't have a ref
00173    */
00174 #ifndef DBUS_DISABLE_CHECKS
00175   _dbus_assert (!server->have_server_lock);
00176 #endif
00177   _dbus_assert (server->disconnected);
00178   
00179   /* calls out to application code... */
00180   _dbus_data_slot_list_free (&server->slot_list);
00181 
00182   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00183 
00184   _dbus_watch_list_free (server->watches);
00185   _dbus_timeout_list_free (server->timeouts);
00186 
00187   _dbus_mutex_free_at_location (&server->mutex);
00188   
00189   dbus_free (server->address);
00190 
00191   dbus_free_string_array (server->auth_mechanisms);
00192 
00193   _dbus_string_free (&server->guid_hex);
00194 }
00195 
00196 
00198 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00199                                                   DBusWatch     *watch);
00201 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00202                                                   DBusWatch     *watch);
00204 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00205                                                   DBusWatch     *watch,
00206                                                   dbus_bool_t    enabled);
00207 
00208 static dbus_bool_t
00209 protected_change_watch (DBusServer             *server,
00210                         DBusWatch              *watch,
00211                         DBusWatchAddFunction    add_function,
00212                         DBusWatchRemoveFunction remove_function,
00213                         DBusWatchToggleFunction toggle_function,
00214                         dbus_bool_t             enabled)
00215 {
00216   DBusWatchList *watches;
00217   dbus_bool_t retval;
00218   
00219   HAVE_LOCK_CHECK (server);
00220 
00221   /* This isn't really safe or reasonable; a better pattern is the "do
00222    * everything, then drop lock and call out" one; but it has to be
00223    * propagated up through all callers
00224    */
00225   
00226   watches = server->watches;
00227   if (watches)
00228     {
00229       server->watches = NULL;
00230       _dbus_server_ref_unlocked (server);
00231       SERVER_UNLOCK (server);
00232 
00233       if (add_function)
00234         retval = (* add_function) (watches, watch);
00235       else if (remove_function)
00236         {
00237           retval = TRUE;
00238           (* remove_function) (watches, watch);
00239         }
00240       else
00241         {
00242           retval = TRUE;
00243           (* toggle_function) (watches, watch, enabled);
00244         }
00245       
00246       SERVER_LOCK (server);
00247       server->watches = watches;
00248       _dbus_server_unref_unlocked (server);
00249 
00250       return retval;
00251     }
00252   else
00253     return FALSE;
00254 }
00255 
00263 dbus_bool_t
00264 _dbus_server_add_watch (DBusServer *server,
00265                         DBusWatch  *watch)
00266 {
00267   HAVE_LOCK_CHECK (server);
00268   return protected_change_watch (server, watch,
00269                                  _dbus_watch_list_add_watch,
00270                                  NULL, NULL, FALSE);
00271 }
00272 
00279 void
00280 _dbus_server_remove_watch  (DBusServer *server,
00281                             DBusWatch  *watch)
00282 {
00283   HAVE_LOCK_CHECK (server);
00284   protected_change_watch (server, watch,
00285                           NULL,
00286                           _dbus_watch_list_remove_watch,
00287                           NULL, FALSE);
00288 }
00289 
00299 void
00300 _dbus_server_toggle_watch (DBusServer  *server,
00301                            DBusWatch   *watch,
00302                            dbus_bool_t  enabled)
00303 {
00304   _dbus_assert (watch != NULL);
00305 
00306   HAVE_LOCK_CHECK (server);
00307   protected_change_watch (server, watch,
00308                           NULL, NULL,
00309                           _dbus_watch_list_toggle_watch,
00310                           enabled);
00311 }
00312 
00314 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00315                                                    DBusTimeout     *timeout);
00317 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00318                                                    DBusTimeout     *timeout);
00320 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00321                                                    DBusTimeout     *timeout,
00322                                                    dbus_bool_t      enabled);
00323 
00324 
00325 static dbus_bool_t
00326 protected_change_timeout (DBusServer               *server,
00327                           DBusTimeout              *timeout,
00328                           DBusTimeoutAddFunction    add_function,
00329                           DBusTimeoutRemoveFunction remove_function,
00330                           DBusTimeoutToggleFunction toggle_function,
00331                           dbus_bool_t               enabled)
00332 {
00333   DBusTimeoutList *timeouts;
00334   dbus_bool_t retval;
00335   
00336   HAVE_LOCK_CHECK (server);
00337 
00338   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00339    * drop lock and call out" one; but it has to be propagated up through all callers
00340    */
00341   
00342   timeouts = server->timeouts;
00343   if (timeouts)
00344     {
00345       server->timeouts = NULL;
00346       _dbus_server_ref_unlocked (server);
00347       SERVER_UNLOCK (server);
00348 
00349       if (add_function)
00350         retval = (* add_function) (timeouts, timeout);
00351       else if (remove_function)
00352         {
00353           retval = TRUE;
00354           (* remove_function) (timeouts, timeout);
00355         }
00356       else
00357         {
00358           retval = TRUE;
00359           (* toggle_function) (timeouts, timeout, enabled);
00360         }
00361       
00362       SERVER_LOCK (server);
00363       server->timeouts = timeouts;
00364       _dbus_server_unref_unlocked (server);
00365 
00366       return retval;
00367     }
00368   else
00369     return FALSE;
00370 }
00371 
00381 dbus_bool_t
00382 _dbus_server_add_timeout (DBusServer  *server,
00383                           DBusTimeout *timeout)
00384 {
00385   return protected_change_timeout (server, timeout,
00386                                    _dbus_timeout_list_add_timeout,
00387                                    NULL, NULL, FALSE);
00388 }
00389 
00396 void
00397 _dbus_server_remove_timeout (DBusServer  *server,
00398                              DBusTimeout *timeout)
00399 {
00400   protected_change_timeout (server, timeout,
00401                             NULL,
00402                             _dbus_timeout_list_remove_timeout,
00403                             NULL, FALSE);
00404 }
00405 
00415 void
00416 _dbus_server_toggle_timeout (DBusServer  *server,
00417                              DBusTimeout *timeout,
00418                              dbus_bool_t  enabled)
00419 {
00420   protected_change_timeout (server, timeout,
00421                             NULL, NULL,
00422                             _dbus_timeout_list_toggle_timeout,
00423                             enabled);
00424 }
00425 
00426 
00432 void
00433 _dbus_server_ref_unlocked (DBusServer *server)
00434 {
00435   _dbus_assert (server != NULL);
00436   _dbus_assert (server->refcount.value > 0);
00437   
00438   HAVE_LOCK_CHECK (server);
00439 
00440 #ifdef DBUS_HAVE_ATOMIC_INT
00441   _dbus_atomic_inc (&server->refcount);
00442 #else
00443   _dbus_assert (server->refcount.value > 0);
00444 
00445   server->refcount.value += 1;
00446 #endif
00447 }
00448 
00454 void
00455 _dbus_server_unref_unlocked (DBusServer *server)
00456 {
00457   dbus_bool_t last_unref;
00458 
00459   /* Keep this in sync with dbus_server_unref */
00460   
00461   _dbus_assert (server != NULL);
00462   _dbus_assert (server->refcount.value > 0);
00463 
00464   HAVE_LOCK_CHECK (server);
00465   
00466 #ifdef DBUS_HAVE_ATOMIC_INT
00467   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00468 #else
00469   _dbus_assert (server->refcount.value > 0);
00470 
00471   server->refcount.value -= 1;
00472   last_unref = (server->refcount.value == 0);
00473 #endif
00474   
00475   if (last_unref)
00476     {
00477       _dbus_assert (server->disconnected);
00478       
00479       SERVER_UNLOCK (server);
00480       
00481       _dbus_assert (server->vtable->finalize != NULL);
00482       
00483       (* server->vtable->finalize) (server);
00484     }
00485 }
00486 
00508 static const struct {
00509   DBusServerListenResult (* func) (DBusAddressEntry *entry,
00510                                    DBusServer      **server_p,
00511                                    DBusError        *error);
00512 } listen_funcs[] = {
00513   { _dbus_server_listen_socket }
00514   , { _dbus_server_listen_platform_specific }
00515 #ifdef DBUS_BUILD_TESTS
00516   , { _dbus_server_listen_debug_pipe }
00517 #endif
00518 };
00519 
00540 DBusServer*
00541 dbus_server_listen (const char     *address,
00542                     DBusError      *error)
00543 {
00544   DBusServer *server;
00545   DBusAddressEntry **entries;
00546   int len, i;
00547   DBusError first_connect_error = DBUS_ERROR_INIT;
00548   dbus_bool_t handled_once;
00549   
00550   _dbus_return_val_if_fail (address != NULL, NULL);
00551   _dbus_return_val_if_error_is_set (error, NULL);
00552   
00553   if (!dbus_parse_address (address, &entries, &len, error))
00554     return NULL;
00555 
00556   server = NULL;
00557   handled_once = FALSE;
00558 
00559   for (i = 0; i < len; i++)
00560     {
00561       int j;
00562 
00563       for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
00564         {
00565           DBusServerListenResult result;
00566           DBusError tmp_error = DBUS_ERROR_INIT;
00567 
00568           result = (* listen_funcs[j].func) (entries[i],
00569                                              &server,
00570                                              &tmp_error);
00571 
00572           if (result == DBUS_SERVER_LISTEN_OK)
00573             {
00574               _dbus_assert (server != NULL);
00575               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00576               handled_once = TRUE;
00577               goto out;
00578             }
00579           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
00580             {
00581               _dbus_assert (server == NULL);
00582               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00583               dbus_move_error (&tmp_error, error);
00584               handled_once = TRUE;
00585               goto out;
00586             }
00587           else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
00588             {
00589               _dbus_assert (server == NULL);
00590               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00591 
00592               /* keep trying addresses */
00593             }
00594           else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
00595             {
00596               _dbus_assert (server == NULL);
00597               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00598               if (!dbus_error_is_set (&first_connect_error))
00599                 dbus_move_error (&tmp_error, &first_connect_error);
00600               else
00601                 dbus_error_free (&tmp_error);
00602 
00603               handled_once = TRUE;
00604               
00605               /* keep trying addresses */
00606             }
00607         }
00608 
00609       _dbus_assert (server == NULL);
00610       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00611     }
00612 
00613  out:
00614 
00615   if (!handled_once)
00616     {
00617       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00618       if (len > 0)
00619         dbus_set_error (error,
00620                        DBUS_ERROR_BAD_ADDRESS,
00621                        "Unknown address type '%s'",
00622                        dbus_address_entry_get_method (entries[0]));
00623       else
00624         dbus_set_error (error,
00625                         DBUS_ERROR_BAD_ADDRESS,
00626                         "Empty address '%s'",
00627                         address);
00628     }
00629   
00630   dbus_address_entries_free (entries);
00631 
00632   if (server == NULL)
00633     {
00634       _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
00635                    dbus_error_is_set (error));
00636       
00637       if (error && dbus_error_is_set (error))
00638         {
00639           /* already set the error */
00640         }
00641       else
00642         {
00643           /* didn't set the error but either error should be
00644            * NULL or first_connect_error should be set.
00645            */
00646           _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
00647           dbus_move_error (&first_connect_error, error);
00648         }
00649 
00650       _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
00651       _DBUS_ASSERT_ERROR_IS_SET (error);
00652 
00653       return NULL;
00654     }
00655   else
00656     {
00657       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00658       return server;
00659     }
00660 }
00661 
00668 DBusServer *
00669 dbus_server_ref (DBusServer *server)
00670 {
00671   _dbus_return_val_if_fail (server != NULL, NULL);
00672   _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
00673 
00674 #ifdef DBUS_HAVE_ATOMIC_INT
00675   _dbus_atomic_inc (&server->refcount);
00676 #else
00677   SERVER_LOCK (server);
00678   _dbus_assert (server->refcount.value > 0);
00679 
00680   server->refcount.value += 1;
00681   SERVER_UNLOCK (server);
00682 #endif
00683 
00684   return server;
00685 }
00686 
00695 void
00696 dbus_server_unref (DBusServer *server)
00697 {
00698   dbus_bool_t last_unref;
00699 
00700   /* keep this in sync with unref_unlocked */
00701   
00702   _dbus_return_if_fail (server != NULL);
00703   _dbus_return_if_fail (server->refcount.value > 0);
00704 
00705 #ifdef DBUS_HAVE_ATOMIC_INT
00706   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00707 #else
00708   SERVER_LOCK (server);
00709   
00710   _dbus_assert (server->refcount.value > 0);
00711 
00712   server->refcount.value -= 1;
00713   last_unref = (server->refcount.value == 0);
00714   
00715   SERVER_UNLOCK (server);
00716 #endif
00717   
00718   if (last_unref)
00719     {
00720       /* lock not held! */
00721       _dbus_assert (server->disconnected);
00722       
00723       _dbus_assert (server->vtable->finalize != NULL);
00724       
00725       (* server->vtable->finalize) (server);
00726     }
00727 }
00728 
00737 void
00738 dbus_server_disconnect (DBusServer *server)
00739 {
00740   _dbus_return_if_fail (server != NULL);
00741   _dbus_return_if_fail (server->refcount.value > 0);
00742 
00743   SERVER_LOCK (server);
00744   _dbus_server_ref_unlocked (server);
00745   
00746   _dbus_assert (server->vtable->disconnect != NULL);
00747 
00748   if (!server->disconnected)
00749     {
00750       /* this has to be first so recursive calls to disconnect don't happen */
00751       server->disconnected = TRUE;
00752       
00753       (* server->vtable->disconnect) (server);
00754     }
00755 
00756   SERVER_UNLOCK (server);
00757   dbus_server_unref (server);
00758 }
00759 
00765 dbus_bool_t
00766 dbus_server_get_is_connected (DBusServer *server)
00767 {
00768   dbus_bool_t retval;
00769   
00770   _dbus_return_val_if_fail (server != NULL, FALSE);
00771 
00772   SERVER_LOCK (server);
00773   retval = !server->disconnected;
00774   SERVER_UNLOCK (server);
00775 
00776   return retval;
00777 }
00778 
00786 char*
00787 dbus_server_get_address (DBusServer *server)
00788 {
00789   char *retval;
00790   
00791   _dbus_return_val_if_fail (server != NULL, NULL);
00792 
00793   SERVER_LOCK (server);
00794   retval = _dbus_strdup (server->address);
00795   SERVER_UNLOCK (server);
00796 
00797   return retval;
00798 }
00799 
00822 char*
00823 dbus_server_get_id (DBusServer *server)
00824 {
00825   char *retval;
00826   
00827   _dbus_return_val_if_fail (server != NULL, NULL);
00828 
00829   SERVER_LOCK (server);
00830   retval = NULL;
00831   _dbus_string_copy_data (&server->guid_hex, &retval);
00832   SERVER_UNLOCK (server);
00833 
00834   return retval;
00835 }
00836 
00857 void
00858 dbus_server_set_new_connection_function (DBusServer                *server,
00859                                          DBusNewConnectionFunction  function,
00860                                          void                      *data,
00861                                          DBusFreeFunction           free_data_function)
00862 {
00863   DBusFreeFunction old_free_function;
00864   void *old_data;
00865   
00866   _dbus_return_if_fail (server != NULL);
00867 
00868   SERVER_LOCK (server);
00869   old_free_function = server->new_connection_free_data_function;
00870   old_data = server->new_connection_data;
00871   
00872   server->new_connection_function = function;
00873   server->new_connection_data = data;
00874   server->new_connection_free_data_function = free_data_function;
00875   SERVER_UNLOCK (server);
00876     
00877   if (old_free_function != NULL)
00878     (* old_free_function) (old_data);
00879 }
00880 
00897 dbus_bool_t
00898 dbus_server_set_watch_functions (DBusServer              *server,
00899                                  DBusAddWatchFunction     add_function,
00900                                  DBusRemoveWatchFunction  remove_function,
00901                                  DBusWatchToggledFunction toggled_function,
00902                                  void                    *data,
00903                                  DBusFreeFunction         free_data_function)
00904 {
00905   dbus_bool_t result;
00906   DBusWatchList *watches;
00907   
00908   _dbus_return_val_if_fail (server != NULL, FALSE);
00909 
00910   SERVER_LOCK (server);
00911   watches = server->watches;
00912   server->watches = NULL;
00913   if (watches)
00914     {
00915       SERVER_UNLOCK (server);
00916       result = _dbus_watch_list_set_functions (watches,
00917                                                add_function,
00918                                                remove_function,
00919                                                toggled_function,
00920                                                data,
00921                                                free_data_function);
00922       SERVER_LOCK (server);
00923     }
00924   else
00925     {
00926       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00927       result = FALSE;
00928     }
00929   server->watches = watches;
00930   SERVER_UNLOCK (server);
00931   
00932   return result;
00933 }
00934 
00950 dbus_bool_t
00951 dbus_server_set_timeout_functions (DBusServer                *server,
00952                                    DBusAddTimeoutFunction     add_function,
00953                                    DBusRemoveTimeoutFunction  remove_function,
00954                                    DBusTimeoutToggledFunction toggled_function,
00955                                    void                      *data,
00956                                    DBusFreeFunction           free_data_function)
00957 {
00958   dbus_bool_t result;
00959   DBusTimeoutList *timeouts;
00960   
00961   _dbus_return_val_if_fail (server != NULL, FALSE);
00962 
00963   SERVER_LOCK (server);
00964   timeouts = server->timeouts;
00965   server->timeouts = NULL;
00966   if (timeouts)
00967     {
00968       SERVER_UNLOCK (server);
00969       result = _dbus_timeout_list_set_functions (timeouts,
00970                                                  add_function,
00971                                                  remove_function,
00972                                                  toggled_function,
00973                                                  data,
00974                                                  free_data_function);
00975       SERVER_LOCK (server);
00976     }
00977   else
00978     {
00979       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00980       result = FALSE;
00981     }
00982   server->timeouts = timeouts;
00983   SERVER_UNLOCK (server);
00984   
00985   return result;
00986 }
00987 
01001 dbus_bool_t
01002 dbus_server_set_auth_mechanisms (DBusServer  *server,
01003                                  const char **mechanisms)
01004 {
01005   char **copy;
01006 
01007   _dbus_return_val_if_fail (server != NULL, FALSE);
01008 
01009   SERVER_LOCK (server);
01010   
01011   if (mechanisms != NULL)
01012     {
01013       copy = _dbus_dup_string_array (mechanisms);
01014       if (copy == NULL)
01015         return FALSE;
01016     }
01017   else
01018     copy = NULL;
01019 
01020   dbus_free_string_array (server->auth_mechanisms);
01021   server->auth_mechanisms = copy;
01022 
01023   SERVER_UNLOCK (server);
01024   
01025   return TRUE;
01026 }
01027 
01028 
01029 static DBusDataSlotAllocator slot_allocator;
01030 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01031 
01046 dbus_bool_t
01047 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01048 {
01049   return _dbus_data_slot_allocator_alloc (&slot_allocator,
01050                                           (DBusMutex **)&_DBUS_LOCK_NAME (server_slots),
01051                                           slot_p);
01052 }
01053 
01065 void
01066 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01067 {
01068   _dbus_return_if_fail (*slot_p >= 0);
01069   
01070   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01071 }
01072 
01086 dbus_bool_t
01087 dbus_server_set_data (DBusServer       *server,
01088                       int               slot,
01089                       void             *data,
01090                       DBusFreeFunction  free_data_func)
01091 {
01092   DBusFreeFunction old_free_func;
01093   void *old_data;
01094   dbus_bool_t retval;
01095 
01096   _dbus_return_val_if_fail (server != NULL, FALSE);
01097 
01098   SERVER_LOCK (server);
01099   
01100   retval = _dbus_data_slot_list_set (&slot_allocator,
01101                                      &server->slot_list,
01102                                      slot, data, free_data_func,
01103                                      &old_free_func, &old_data);
01104 
01105 
01106   SERVER_UNLOCK (server);
01107   
01108   if (retval)
01109     {
01110       /* Do the actual free outside the server lock */
01111       if (old_free_func)
01112         (* old_free_func) (old_data);
01113     }
01114 
01115   return retval;
01116 }
01117 
01126 void*
01127 dbus_server_get_data (DBusServer   *server,
01128                       int           slot)
01129 {
01130   void *res;
01131 
01132   _dbus_return_val_if_fail (server != NULL, NULL);
01133   
01134   SERVER_LOCK (server);
01135   
01136   res = _dbus_data_slot_list_get (&slot_allocator,
01137                                   &server->slot_list,
01138                                   slot);
01139 
01140   SERVER_UNLOCK (server);
01141   
01142   return res;
01143 }
01144 
01147 #ifdef DBUS_BUILD_TESTS
01148 #include "dbus-test.h"
01149 #include <string.h>
01150 
01151 dbus_bool_t
01152 _dbus_server_test (void)
01153 {
01154   const char *valid_addresses[] = {
01155     "tcp:port=1234",
01156     "tcp:host=localhost,port=1234",
01157     "tcp:host=localhost,port=1234;tcp:port=5678",
01158 #ifdef DBUS_UNIX
01159     "unix:path=./boogie",
01160     "tcp:port=1234;unix:path=./boogie",
01161 #endif
01162   };
01163 
01164   DBusServer *server;
01165   int i;
01166   
01167   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01168     {
01169       DBusError error = DBUS_ERROR_INIT;
01170       char *address;
01171       char *id;
01172 
01173       server = dbus_server_listen (valid_addresses[i], &error);
01174       if (server == NULL)
01175         {
01176           _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
01177           dbus_error_free (&error);
01178           _dbus_assert_not_reached ("Failed to listen for valid address.");
01179         }
01180 
01181       id = dbus_server_get_id (server);
01182       _dbus_assert (id != NULL);
01183       address = dbus_server_get_address (server);
01184       _dbus_assert (address != NULL);
01185 
01186       if (strstr (address, id) == NULL)
01187         {
01188           _dbus_warn ("server id '%s' is not in the server address '%s'\n",
01189                       id, address);
01190           _dbus_assert_not_reached ("bad server id or address");
01191         }
01192 
01193       dbus_free (id);
01194       dbus_free (address);
01195       
01196       dbus_server_disconnect (server);
01197       dbus_server_unref (server);
01198     }
01199 
01200   return TRUE;
01201 }
01202 
01203 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Dec 21 2010 for D-Bus by  doxygen 1.7.1