• 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 
00103 #ifdef DBUS_DISABLE_ASSERT
00104   _dbus_atomic_inc (&server->refcount);
00105 #else
00106     {
00107       dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
00108 
00109       _dbus_assert (old_refcount == 0);
00110     }
00111 #endif
00112 
00113   server->address = NULL;
00114   server->watches = NULL;
00115   server->timeouts = NULL;
00116   server->published_address = FALSE;
00117 
00118   if (!_dbus_string_init (&server->guid_hex))
00119     return FALSE;
00120 
00121   _dbus_generate_uuid (&server->guid);
00122 
00123   if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
00124     goto failed;
00125   
00126   server->address = copy_address_with_guid_appended (address,
00127                                                      &server->guid_hex);
00128   if (server->address == NULL)
00129     goto failed;
00130   
00131   _dbus_mutex_new_at_location (&server->mutex);
00132   if (server->mutex == NULL)
00133     goto failed;
00134   
00135   server->watches = _dbus_watch_list_new ();
00136   if (server->watches == NULL)
00137     goto failed;
00138 
00139   server->timeouts = _dbus_timeout_list_new ();
00140   if (server->timeouts == NULL)
00141     goto failed;
00142 
00143   _dbus_data_slot_list_init (&server->slot_list);
00144 
00145   _dbus_verbose ("Initialized server on address %s\n", server->address);
00146   
00147   return TRUE;
00148 
00149  failed:
00150   _dbus_mutex_free_at_location (&server->mutex);
00151   server->mutex = NULL;
00152   if (server->watches)
00153     {
00154       _dbus_watch_list_free (server->watches);
00155       server->watches = NULL;
00156     }
00157   if (server->timeouts)
00158     {
00159       _dbus_timeout_list_free (server->timeouts);
00160       server->timeouts = NULL;
00161     }
00162   if (server->address)
00163     {
00164       dbus_free (server->address);
00165       server->address = NULL;
00166     }
00167   _dbus_string_free (&server->guid_hex);
00168   
00169   return FALSE;
00170 }
00171 
00178 void
00179 _dbus_server_finalize_base (DBusServer *server)
00180 {
00181   /* We don't have the lock, but nobody should be accessing
00182    * concurrently since they don't have a ref
00183    */
00184 #ifndef DBUS_DISABLE_CHECKS
00185   _dbus_assert (!server->have_server_lock);
00186 #endif
00187   _dbus_assert (server->disconnected);
00188   
00189   /* calls out to application code... */
00190   _dbus_data_slot_list_free (&server->slot_list);
00191 
00192   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00193 
00194   _dbus_watch_list_free (server->watches);
00195   _dbus_timeout_list_free (server->timeouts);
00196 
00197   _dbus_mutex_free_at_location (&server->mutex);
00198   
00199   dbus_free (server->address);
00200 
00201   dbus_free_string_array (server->auth_mechanisms);
00202 
00203   _dbus_string_free (&server->guid_hex);
00204 }
00205 
00206 
00208 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00209                                                   DBusWatch     *watch);
00211 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00212                                                   DBusWatch     *watch);
00214 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00215                                                   DBusWatch     *watch,
00216                                                   dbus_bool_t    enabled);
00217 
00218 static dbus_bool_t
00219 protected_change_watch (DBusServer             *server,
00220                         DBusWatch              *watch,
00221                         DBusWatchAddFunction    add_function,
00222                         DBusWatchRemoveFunction remove_function,
00223                         DBusWatchToggleFunction toggle_function,
00224                         dbus_bool_t             enabled)
00225 {
00226   DBusWatchList *watches;
00227   dbus_bool_t retval;
00228   
00229   HAVE_LOCK_CHECK (server);
00230 
00231   /* This isn't really safe or reasonable; a better pattern is the "do
00232    * everything, then drop lock and call out" one; but it has to be
00233    * propagated up through all callers
00234    */
00235   
00236   watches = server->watches;
00237   if (watches)
00238     {
00239       server->watches = NULL;
00240       _dbus_server_ref_unlocked (server);
00241       SERVER_UNLOCK (server);
00242 
00243       if (add_function)
00244         retval = (* add_function) (watches, watch);
00245       else if (remove_function)
00246         {
00247           retval = TRUE;
00248           (* remove_function) (watches, watch);
00249         }
00250       else
00251         {
00252           retval = TRUE;
00253           (* toggle_function) (watches, watch, enabled);
00254         }
00255       
00256       SERVER_LOCK (server);
00257       server->watches = watches;
00258       _dbus_server_unref_unlocked (server);
00259 
00260       return retval;
00261     }
00262   else
00263     return FALSE;
00264 }
00265 
00273 dbus_bool_t
00274 _dbus_server_add_watch (DBusServer *server,
00275                         DBusWatch  *watch)
00276 {
00277   HAVE_LOCK_CHECK (server);
00278   return protected_change_watch (server, watch,
00279                                  _dbus_watch_list_add_watch,
00280                                  NULL, NULL, FALSE);
00281 }
00282 
00289 void
00290 _dbus_server_remove_watch  (DBusServer *server,
00291                             DBusWatch  *watch)
00292 {
00293   HAVE_LOCK_CHECK (server);
00294   protected_change_watch (server, watch,
00295                           NULL,
00296                           _dbus_watch_list_remove_watch,
00297                           NULL, FALSE);
00298 }
00299 
00309 void
00310 _dbus_server_toggle_watch (DBusServer  *server,
00311                            DBusWatch   *watch,
00312                            dbus_bool_t  enabled)
00313 {
00314   _dbus_assert (watch != NULL);
00315 
00316   HAVE_LOCK_CHECK (server);
00317   protected_change_watch (server, watch,
00318                           NULL, NULL,
00319                           _dbus_watch_list_toggle_watch,
00320                           enabled);
00321 }
00322 
00324 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00325                                                    DBusTimeout     *timeout);
00327 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00328                                                    DBusTimeout     *timeout);
00330 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00331                                                    DBusTimeout     *timeout,
00332                                                    dbus_bool_t      enabled);
00333 
00334 
00335 static dbus_bool_t
00336 protected_change_timeout (DBusServer               *server,
00337                           DBusTimeout              *timeout,
00338                           DBusTimeoutAddFunction    add_function,
00339                           DBusTimeoutRemoveFunction remove_function,
00340                           DBusTimeoutToggleFunction toggle_function,
00341                           dbus_bool_t               enabled)
00342 {
00343   DBusTimeoutList *timeouts;
00344   dbus_bool_t retval;
00345   
00346   HAVE_LOCK_CHECK (server);
00347 
00348   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00349    * drop lock and call out" one; but it has to be propagated up through all callers
00350    */
00351   
00352   timeouts = server->timeouts;
00353   if (timeouts)
00354     {
00355       server->timeouts = NULL;
00356       _dbus_server_ref_unlocked (server);
00357       SERVER_UNLOCK (server);
00358 
00359       if (add_function)
00360         retval = (* add_function) (timeouts, timeout);
00361       else if (remove_function)
00362         {
00363           retval = TRUE;
00364           (* remove_function) (timeouts, timeout);
00365         }
00366       else
00367         {
00368           retval = TRUE;
00369           (* toggle_function) (timeouts, timeout, enabled);
00370         }
00371       
00372       SERVER_LOCK (server);
00373       server->timeouts = timeouts;
00374       _dbus_server_unref_unlocked (server);
00375 
00376       return retval;
00377     }
00378   else
00379     return FALSE;
00380 }
00381 
00391 dbus_bool_t
00392 _dbus_server_add_timeout (DBusServer  *server,
00393                           DBusTimeout *timeout)
00394 {
00395   return protected_change_timeout (server, timeout,
00396                                    _dbus_timeout_list_add_timeout,
00397                                    NULL, NULL, FALSE);
00398 }
00399 
00406 void
00407 _dbus_server_remove_timeout (DBusServer  *server,
00408                              DBusTimeout *timeout)
00409 {
00410   protected_change_timeout (server, timeout,
00411                             NULL,
00412                             _dbus_timeout_list_remove_timeout,
00413                             NULL, FALSE);
00414 }
00415 
00425 void
00426 _dbus_server_toggle_timeout (DBusServer  *server,
00427                              DBusTimeout *timeout,
00428                              dbus_bool_t  enabled)
00429 {
00430   protected_change_timeout (server, timeout,
00431                             NULL, NULL,
00432                             _dbus_timeout_list_toggle_timeout,
00433                             enabled);
00434 }
00435 
00436 
00442 void
00443 _dbus_server_ref_unlocked (DBusServer *server)
00444 {
00445   _dbus_assert (server != NULL);
00446   HAVE_LOCK_CHECK (server);
00447 
00448 #ifdef DBUS_DISABLE_ASSERT
00449   _dbus_atomic_inc (&server->refcount);
00450 #else
00451     {
00452       dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
00453 
00454       _dbus_assert (old_refcount > 0);
00455     }
00456 #endif
00457 }
00458 
00464 void
00465 _dbus_server_unref_unlocked (DBusServer *server)
00466 {
00467   dbus_int32_t old_refcount;
00468 
00469   /* Keep this in sync with dbus_server_unref */
00470 
00471   _dbus_assert (server != NULL);
00472 
00473   HAVE_LOCK_CHECK (server);
00474 
00475   old_refcount = _dbus_atomic_dec (&server->refcount);
00476   _dbus_assert (old_refcount > 0);
00477 
00478   if (old_refcount == 1)
00479     {
00480       _dbus_assert (server->disconnected);
00481       
00482       SERVER_UNLOCK (server);
00483       
00484       _dbus_assert (server->vtable->finalize != NULL);
00485       
00486       (* server->vtable->finalize) (server);
00487     }
00488 }
00489 
00511 static const struct {
00512   DBusServerListenResult (* func) (DBusAddressEntry *entry,
00513                                    DBusServer      **server_p,
00514                                    DBusError        *error);
00515 } listen_funcs[] = {
00516   { _dbus_server_listen_socket }
00517   , { _dbus_server_listen_platform_specific }
00518 #ifdef DBUS_BUILD_TESTS
00519   , { _dbus_server_listen_debug_pipe }
00520 #endif
00521 };
00522 
00543 DBusServer*
00544 dbus_server_listen (const char     *address,
00545                     DBusError      *error)
00546 {
00547   DBusServer *server;
00548   DBusAddressEntry **entries;
00549   int len, i;
00550   DBusError first_connect_error = DBUS_ERROR_INIT;
00551   dbus_bool_t handled_once;
00552   
00553   _dbus_return_val_if_fail (address != NULL, NULL);
00554   _dbus_return_val_if_error_is_set (error, NULL);
00555   
00556   if (!dbus_parse_address (address, &entries, &len, error))
00557     return NULL;
00558 
00559   server = NULL;
00560   handled_once = FALSE;
00561 
00562   for (i = 0; i < len; i++)
00563     {
00564       int j;
00565 
00566       for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
00567         {
00568           DBusServerListenResult result;
00569           DBusError tmp_error = DBUS_ERROR_INIT;
00570 
00571           result = (* listen_funcs[j].func) (entries[i],
00572                                              &server,
00573                                              &tmp_error);
00574 
00575           if (result == DBUS_SERVER_LISTEN_OK)
00576             {
00577               _dbus_assert (server != NULL);
00578               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00579               handled_once = TRUE;
00580               goto out;
00581             }
00582           else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
00583             {
00584               _dbus_assert (server == NULL);
00585               dbus_set_error (error,
00586                        DBUS_ERROR_ADDRESS_IN_USE,
00587                        "Address '%s' already used",
00588                        dbus_address_entry_get_method (entries[0]));
00589               handled_once = TRUE;
00590               goto out;
00591             }
00592           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
00593             {
00594               _dbus_assert (server == NULL);
00595               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00596               dbus_move_error (&tmp_error, error);
00597               handled_once = TRUE;
00598               goto out;
00599             }
00600           else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
00601             {
00602               _dbus_assert (server == NULL);
00603               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00604 
00605               /* keep trying addresses */
00606             }
00607           else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
00608             {
00609               _dbus_assert (server == NULL);
00610               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00611               if (!dbus_error_is_set (&first_connect_error))
00612                 dbus_move_error (&tmp_error, &first_connect_error);
00613               else
00614                 dbus_error_free (&tmp_error);
00615 
00616               handled_once = TRUE;
00617               
00618               /* keep trying addresses */
00619             }
00620         }
00621 
00622       _dbus_assert (server == NULL);
00623       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00624     }
00625 
00626  out:
00627 
00628   if (!handled_once)
00629     {
00630       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00631       if (len > 0)
00632         dbus_set_error (error,
00633                        DBUS_ERROR_BAD_ADDRESS,
00634                        "Unknown address type '%s'",
00635                        dbus_address_entry_get_method (entries[0]));
00636       else
00637         dbus_set_error (error,
00638                         DBUS_ERROR_BAD_ADDRESS,
00639                         "Empty address '%s'",
00640                         address);
00641     }
00642   
00643   dbus_address_entries_free (entries);
00644 
00645   if (server == NULL)
00646     {
00647       _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
00648                    dbus_error_is_set (error));
00649       
00650       if (error && dbus_error_is_set (error))
00651         {
00652           /* already set the error */
00653         }
00654       else
00655         {
00656           /* didn't set the error but either error should be
00657            * NULL or first_connect_error should be set.
00658            */
00659           _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
00660           dbus_move_error (&first_connect_error, error);
00661         }
00662 
00663       _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
00664       _DBUS_ASSERT_ERROR_IS_SET (error);
00665 
00666       return NULL;
00667     }
00668   else
00669     {
00670       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00671       return server;
00672     }
00673 }
00674 
00681 DBusServer *
00682 dbus_server_ref (DBusServer *server)
00683 {
00684   _dbus_return_val_if_fail (server != NULL, NULL);
00685 
00686 #ifdef DBUS_DISABLE_CHECKS
00687   _dbus_atomic_inc (&server->refcount);
00688 #else
00689     {
00690       dbus_int32_t old_refcount;
00691 
00692       /* can't get the refcount without a side-effect */
00693       old_refcount = _dbus_atomic_inc (&server->refcount);
00694 
00695       if (_DBUS_UNLIKELY (old_refcount <= 0))
00696         {
00697           /* undo side-effect first */
00698           _dbus_atomic_dec (&server->refcount);
00699           _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
00700                                    _DBUS_FUNCTION_NAME, "old_refcount > 0",
00701                                    __FILE__, __LINE__);
00702           return NULL;
00703         }
00704     }
00705 #endif
00706 
00707   return server;
00708 }
00709 
00718 void
00719 dbus_server_unref (DBusServer *server)
00720 {
00721   dbus_int32_t old_refcount;
00722 
00723   /* keep this in sync with unref_unlocked */
00724 
00725   _dbus_return_if_fail (server != NULL);
00726 
00727   /* can't get the refcount without a side-effect */
00728   old_refcount = _dbus_atomic_dec (&server->refcount);
00729 
00730 #ifndef DBUS_DISABLE_CHECKS
00731   if (_DBUS_UNLIKELY (old_refcount <= 0))
00732     {
00733       /* undo side-effect first */
00734       _dbus_atomic_inc (&server->refcount);
00735       _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
00736                                _DBUS_FUNCTION_NAME, "old_refcount > 0",
00737                                __FILE__, __LINE__);
00738       return;
00739     }
00740 #endif
00741 
00742   if (old_refcount == 1)
00743     {
00744       /* lock not held! */
00745       _dbus_assert (server->disconnected);
00746       
00747       _dbus_assert (server->vtable->finalize != NULL);
00748       
00749       (* server->vtable->finalize) (server);
00750     }
00751 }
00752 
00761 void
00762 dbus_server_disconnect (DBusServer *server)
00763 {
00764   _dbus_return_if_fail (server != NULL);
00765 
00766 #ifdef DBUS_DISABLE_CHECKS
00767   _dbus_atomic_inc (&server->refcount);
00768 #else
00769     {
00770       dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
00771 
00772       _dbus_return_if_fail (old_refcount > 0);
00773     }
00774 #endif
00775 
00776   SERVER_LOCK (server);
00777 
00778   _dbus_assert (server->vtable->disconnect != NULL);
00779 
00780   if (!server->disconnected)
00781     {
00782       /* this has to be first so recursive calls to disconnect don't happen */
00783       server->disconnected = TRUE;
00784       
00785       (* server->vtable->disconnect) (server);
00786     }
00787 
00788   SERVER_UNLOCK (server);
00789   dbus_server_unref (server);
00790 }
00791 
00797 dbus_bool_t
00798 dbus_server_get_is_connected (DBusServer *server)
00799 {
00800   dbus_bool_t retval;
00801   
00802   _dbus_return_val_if_fail (server != NULL, FALSE);
00803 
00804   SERVER_LOCK (server);
00805   retval = !server->disconnected;
00806   SERVER_UNLOCK (server);
00807 
00808   return retval;
00809 }
00810 
00818 char*
00819 dbus_server_get_address (DBusServer *server)
00820 {
00821   char *retval;
00822   
00823   _dbus_return_val_if_fail (server != NULL, NULL);
00824 
00825   SERVER_LOCK (server);
00826   retval = _dbus_strdup (server->address);
00827   SERVER_UNLOCK (server);
00828 
00829   return retval;
00830 }
00831 
00854 char*
00855 dbus_server_get_id (DBusServer *server)
00856 {
00857   char *retval;
00858   
00859   _dbus_return_val_if_fail (server != NULL, NULL);
00860 
00861   SERVER_LOCK (server);
00862   retval = NULL;
00863   _dbus_string_copy_data (&server->guid_hex, &retval);
00864   SERVER_UNLOCK (server);
00865 
00866   return retval;
00867 }
00868 
00889 void
00890 dbus_server_set_new_connection_function (DBusServer                *server,
00891                                          DBusNewConnectionFunction  function,
00892                                          void                      *data,
00893                                          DBusFreeFunction           free_data_function)
00894 {
00895   DBusFreeFunction old_free_function;
00896   void *old_data;
00897   
00898   _dbus_return_if_fail (server != NULL);
00899 
00900   SERVER_LOCK (server);
00901   old_free_function = server->new_connection_free_data_function;
00902   old_data = server->new_connection_data;
00903   
00904   server->new_connection_function = function;
00905   server->new_connection_data = data;
00906   server->new_connection_free_data_function = free_data_function;
00907   SERVER_UNLOCK (server);
00908     
00909   if (old_free_function != NULL)
00910     (* old_free_function) (old_data);
00911 }
00912 
00929 dbus_bool_t
00930 dbus_server_set_watch_functions (DBusServer              *server,
00931                                  DBusAddWatchFunction     add_function,
00932                                  DBusRemoveWatchFunction  remove_function,
00933                                  DBusWatchToggledFunction toggled_function,
00934                                  void                    *data,
00935                                  DBusFreeFunction         free_data_function)
00936 {
00937   dbus_bool_t result;
00938   DBusWatchList *watches;
00939   
00940   _dbus_return_val_if_fail (server != NULL, FALSE);
00941 
00942   SERVER_LOCK (server);
00943   watches = server->watches;
00944   server->watches = NULL;
00945   if (watches)
00946     {
00947       SERVER_UNLOCK (server);
00948       result = _dbus_watch_list_set_functions (watches,
00949                                                add_function,
00950                                                remove_function,
00951                                                toggled_function,
00952                                                data,
00953                                                free_data_function);
00954       SERVER_LOCK (server);
00955     }
00956   else
00957     {
00958       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00959       result = FALSE;
00960     }
00961   server->watches = watches;
00962   SERVER_UNLOCK (server);
00963   
00964   return result;
00965 }
00966 
00982 dbus_bool_t
00983 dbus_server_set_timeout_functions (DBusServer                *server,
00984                                    DBusAddTimeoutFunction     add_function,
00985                                    DBusRemoveTimeoutFunction  remove_function,
00986                                    DBusTimeoutToggledFunction toggled_function,
00987                                    void                      *data,
00988                                    DBusFreeFunction           free_data_function)
00989 {
00990   dbus_bool_t result;
00991   DBusTimeoutList *timeouts;
00992   
00993   _dbus_return_val_if_fail (server != NULL, FALSE);
00994 
00995   SERVER_LOCK (server);
00996   timeouts = server->timeouts;
00997   server->timeouts = NULL;
00998   if (timeouts)
00999     {
01000       SERVER_UNLOCK (server);
01001       result = _dbus_timeout_list_set_functions (timeouts,
01002                                                  add_function,
01003                                                  remove_function,
01004                                                  toggled_function,
01005                                                  data,
01006                                                  free_data_function);
01007       SERVER_LOCK (server);
01008     }
01009   else
01010     {
01011       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
01012       result = FALSE;
01013     }
01014   server->timeouts = timeouts;
01015   SERVER_UNLOCK (server);
01016   
01017   return result;
01018 }
01019 
01033 dbus_bool_t
01034 dbus_server_set_auth_mechanisms (DBusServer  *server,
01035                                  const char **mechanisms)
01036 {
01037   char **copy;
01038 
01039   _dbus_return_val_if_fail (server != NULL, FALSE);
01040 
01041   SERVER_LOCK (server);
01042   
01043   if (mechanisms != NULL)
01044     {
01045       copy = _dbus_dup_string_array (mechanisms);
01046       if (copy == NULL)
01047         return FALSE;
01048     }
01049   else
01050     copy = NULL;
01051 
01052   dbus_free_string_array (server->auth_mechanisms);
01053   server->auth_mechanisms = copy;
01054 
01055   SERVER_UNLOCK (server);
01056   
01057   return TRUE;
01058 }
01059 
01060 
01061 static DBusDataSlotAllocator slot_allocator;
01062 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01063 
01078 dbus_bool_t
01079 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01080 {
01081   return _dbus_data_slot_allocator_alloc (&slot_allocator,
01082                                           (DBusMutex **)&_DBUS_LOCK_NAME (server_slots),
01083                                           slot_p);
01084 }
01085 
01097 void
01098 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01099 {
01100   _dbus_return_if_fail (*slot_p >= 0);
01101   
01102   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01103 }
01104 
01118 dbus_bool_t
01119 dbus_server_set_data (DBusServer       *server,
01120                       int               slot,
01121                       void             *data,
01122                       DBusFreeFunction  free_data_func)
01123 {
01124   DBusFreeFunction old_free_func;
01125   void *old_data;
01126   dbus_bool_t retval;
01127 
01128   _dbus_return_val_if_fail (server != NULL, FALSE);
01129 
01130   SERVER_LOCK (server);
01131   
01132   retval = _dbus_data_slot_list_set (&slot_allocator,
01133                                      &server->slot_list,
01134                                      slot, data, free_data_func,
01135                                      &old_free_func, &old_data);
01136 
01137 
01138   SERVER_UNLOCK (server);
01139   
01140   if (retval)
01141     {
01142       /* Do the actual free outside the server lock */
01143       if (old_free_func)
01144         (* old_free_func) (old_data);
01145     }
01146 
01147   return retval;
01148 }
01149 
01158 void*
01159 dbus_server_get_data (DBusServer   *server,
01160                       int           slot)
01161 {
01162   void *res;
01163 
01164   _dbus_return_val_if_fail (server != NULL, NULL);
01165   
01166   SERVER_LOCK (server);
01167   
01168   res = _dbus_data_slot_list_get (&slot_allocator,
01169                                   &server->slot_list,
01170                                   slot);
01171 
01172   SERVER_UNLOCK (server);
01173   
01174   return res;
01175 }
01176 
01179 #ifdef DBUS_BUILD_TESTS
01180 #include "dbus-test.h"
01181 #include <string.h>
01182 
01183 dbus_bool_t
01184 _dbus_server_test (void)
01185 {
01186   const char *valid_addresses[] = {
01187     "tcp:port=1234",
01188     "tcp:host=localhost,port=1234",
01189     "tcp:host=localhost,port=1234;tcp:port=5678",
01190 #ifdef DBUS_UNIX
01191     "unix:path=./boogie",
01192     "tcp:port=1234;unix:path=./boogie",
01193 #endif
01194   };
01195 
01196   DBusServer *server;
01197   int i;
01198   
01199   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01200     {
01201       DBusError error = DBUS_ERROR_INIT;
01202       char *address;
01203       char *id;
01204 
01205       server = dbus_server_listen (valid_addresses[i], &error);
01206       if (server == NULL)
01207         {
01208           _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
01209           dbus_error_free (&error);
01210           _dbus_assert_not_reached ("Failed to listen for valid address.");
01211         }
01212 
01213       id = dbus_server_get_id (server);
01214       _dbus_assert (id != NULL);
01215       address = dbus_server_get_address (server);
01216       _dbus_assert (address != NULL);
01217 
01218       if (strstr (address, id) == NULL)
01219         {
01220           _dbus_warn ("server id '%s' is not in the server address '%s'\n",
01221                       id, address);
01222           _dbus_assert_not_reached ("bad server id or address");
01223         }
01224 
01225       dbus_free (id);
01226       dbus_free (address);
01227       
01228       dbus_server_disconnect (server);
01229       dbus_server_unref (server);
01230     }
01231 
01232   return TRUE;
01233 }
01234 
01235 #endif /* DBUS_BUILD_TESTS */

Generated on Fri Jul 11 2014 20:41:50 for D-Bus by  doxygen 1.7.1