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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 
00298 void
00299 _dbus_server_toggle_watch (DBusServer  *server,
00300                            DBusWatch   *watch,
00301                            dbus_bool_t  enabled)
00302 {
00303   _dbus_assert (watch != NULL);
00304 
00305   HAVE_LOCK_CHECK (server);
00306   protected_change_watch (server, watch,
00307                           NULL, NULL,
00308                           _dbus_watch_list_toggle_watch,
00309                           enabled);
00310 }
00311 
00313 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00314                                                    DBusTimeout     *timeout);
00316 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00317                                                    DBusTimeout     *timeout);
00319 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00320                                                    DBusTimeout     *timeout,
00321                                                    dbus_bool_t      enabled);
00322 
00323 
00324 static dbus_bool_t
00325 protected_change_timeout (DBusServer               *server,
00326                           DBusTimeout              *timeout,
00327                           DBusTimeoutAddFunction    add_function,
00328                           DBusTimeoutRemoveFunction remove_function,
00329                           DBusTimeoutToggleFunction toggle_function,
00330                           dbus_bool_t               enabled)
00331 {
00332   DBusTimeoutList *timeouts;
00333   dbus_bool_t retval;
00334   
00335   HAVE_LOCK_CHECK (server);
00336 
00337   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00338    * drop lock and call out" one; but it has to be propagated up through all callers
00339    */
00340   
00341   timeouts = server->timeouts;
00342   if (timeouts)
00343     {
00344       server->timeouts = NULL;
00345       _dbus_server_ref_unlocked (server);
00346       SERVER_UNLOCK (server);
00347 
00348       if (add_function)
00349         retval = (* add_function) (timeouts, timeout);
00350       else if (remove_function)
00351         {
00352           retval = TRUE;
00353           (* remove_function) (timeouts, timeout);
00354         }
00355       else
00356         {
00357           retval = TRUE;
00358           (* toggle_function) (timeouts, timeout, enabled);
00359         }
00360       
00361       SERVER_LOCK (server);
00362       server->timeouts = timeouts;
00363       _dbus_server_unref_unlocked (server);
00364 
00365       return retval;
00366     }
00367   else
00368     return FALSE;
00369 }
00370 
00380 dbus_bool_t
00381 _dbus_server_add_timeout (DBusServer  *server,
00382                           DBusTimeout *timeout)
00383 {
00384   return protected_change_timeout (server, timeout,
00385                                    _dbus_timeout_list_add_timeout,
00386                                    NULL, NULL, FALSE);
00387 }
00388 
00395 void
00396 _dbus_server_remove_timeout (DBusServer  *server,
00397                              DBusTimeout *timeout)
00398 {
00399   protected_change_timeout (server, timeout,
00400                             NULL,
00401                             _dbus_timeout_list_remove_timeout,
00402                             NULL, FALSE);
00403 }
00404 
00414 void
00415 _dbus_server_toggle_timeout (DBusServer  *server,
00416                              DBusTimeout *timeout,
00417                              dbus_bool_t  enabled)
00418 {
00419   protected_change_timeout (server, timeout,
00420                             NULL, NULL,
00421                             _dbus_timeout_list_toggle_timeout,
00422                             enabled);
00423 }
00424 
00425 
00431 void
00432 _dbus_server_ref_unlocked (DBusServer *server)
00433 {
00434   _dbus_assert (server != NULL);
00435   _dbus_assert (server->refcount.value > 0);
00436   
00437   HAVE_LOCK_CHECK (server);
00438 
00439 #ifdef DBUS_HAVE_ATOMIC_INT
00440   _dbus_atomic_inc (&server->refcount);
00441 #else
00442   _dbus_assert (server->refcount.value > 0);
00443 
00444   server->refcount.value += 1;
00445 #endif
00446 }
00447 
00453 void
00454 _dbus_server_unref_unlocked (DBusServer *server)
00455 {
00456   dbus_bool_t last_unref;
00457 
00458   /* Keep this in sync with dbus_server_unref */
00459   
00460   _dbus_assert (server != NULL);
00461   _dbus_assert (server->refcount.value > 0);
00462 
00463   HAVE_LOCK_CHECK (server);
00464   
00465 #ifdef DBUS_HAVE_ATOMIC_INT
00466   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00467 #else
00468   _dbus_assert (server->refcount.value > 0);
00469 
00470   server->refcount.value -= 1;
00471   last_unref = (server->refcount.value == 0);
00472 #endif
00473   
00474   if (last_unref)
00475     {
00476       _dbus_assert (server->disconnected);
00477       
00478       SERVER_UNLOCK (server);
00479       
00480       _dbus_assert (server->vtable->finalize != NULL);
00481       
00482       (* server->vtable->finalize) (server);
00483     }
00484 }
00485 
00507 static const struct {
00508   DBusServerListenResult (* func) (DBusAddressEntry *entry,
00509                                    DBusServer      **server_p,
00510                                    DBusError        *error);
00511 } listen_funcs[] = {
00512   { _dbus_server_listen_socket }
00513   , { _dbus_server_listen_platform_specific }
00514 #ifdef DBUS_BUILD_TESTS
00515   , { _dbus_server_listen_debug_pipe }
00516 #endif
00517 };
00518 
00539 DBusServer*
00540 dbus_server_listen (const char     *address,
00541                     DBusError      *error)
00542 {
00543   DBusServer *server;
00544   DBusAddressEntry **entries;
00545   int len, i;
00546   DBusError first_connect_error;
00547   dbus_bool_t handled_once;
00548   
00549   _dbus_return_val_if_fail (address != NULL, NULL);
00550   _dbus_return_val_if_error_is_set (error, NULL);
00551   
00552   if (!dbus_parse_address (address, &entries, &len, error))
00553     return NULL;
00554 
00555   server = NULL;
00556   dbus_error_init (&first_connect_error);
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;
00567       
00568           dbus_error_init (&tmp_error);
00569           result = (* listen_funcs[j].func) (entries[i],
00570                                              &server,
00571                                              &tmp_error);
00572 
00573           if (result == DBUS_SERVER_LISTEN_OK)
00574             {
00575               _dbus_assert (server != NULL);
00576               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00577               handled_once = TRUE;
00578               goto out;
00579             }
00580           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
00581             {
00582               _dbus_assert (server == NULL);
00583               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00584               dbus_move_error (&tmp_error, error);
00585               handled_once = TRUE;
00586               goto out;
00587             }
00588           else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
00589             {
00590               _dbus_assert (server == NULL);
00591               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
00592 
00593               /* keep trying addresses */
00594             }
00595           else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
00596             {
00597               _dbus_assert (server == NULL);
00598               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
00599               if (!dbus_error_is_set (&first_connect_error))
00600                 dbus_move_error (&tmp_error, &first_connect_error);
00601               else
00602                 dbus_error_free (&tmp_error);
00603 
00604               handled_once = TRUE;
00605               
00606               /* keep trying addresses */
00607             }
00608         }
00609 
00610       _dbus_assert (server == NULL);
00611       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00612     }
00613 
00614  out:
00615 
00616   if (!handled_once)
00617     {
00618       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00619       if (len > 0)
00620         dbus_set_error (error,
00621                        DBUS_ERROR_BAD_ADDRESS,
00622                        "Unknown address type '%s'",
00623                        dbus_address_entry_get_method (entries[0]));
00624       else
00625         dbus_set_error (error,
00626                         DBUS_ERROR_BAD_ADDRESS,
00627                         "Empty address '%s'",
00628                         address);
00629     }
00630   
00631   dbus_address_entries_free (entries);
00632 
00633   if (server == NULL)
00634     {
00635       _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
00636                    dbus_error_is_set (error));
00637       
00638       if (error && dbus_error_is_set (error))
00639         {
00640           /* already set the error */
00641         }
00642       else
00643         {
00644           /* didn't set the error but either error should be
00645            * NULL or first_connect_error should be set.
00646            */
00647           _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
00648           dbus_move_error (&first_connect_error, error);
00649         }
00650 
00651       _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
00652       _DBUS_ASSERT_ERROR_IS_SET (error);
00653 
00654       return NULL;
00655     }
00656   else
00657     {
00658       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00659       return server;
00660     }
00661 }
00662 
00669 DBusServer *
00670 dbus_server_ref (DBusServer *server)
00671 {
00672   _dbus_return_val_if_fail (server != NULL, NULL);
00673   _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
00674 
00675 #ifdef DBUS_HAVE_ATOMIC_INT
00676   _dbus_atomic_inc (&server->refcount);
00677 #else
00678   SERVER_LOCK (server);
00679   _dbus_assert (server->refcount.value > 0);
00680 
00681   server->refcount.value += 1;
00682   SERVER_UNLOCK (server);
00683 #endif
00684 
00685   return server;
00686 }
00687 
00696 void
00697 dbus_server_unref (DBusServer *server)
00698 {
00699   dbus_bool_t last_unref;
00700 
00701   /* keep this in sync with unref_unlocked */
00702   
00703   _dbus_return_if_fail (server != NULL);
00704   _dbus_return_if_fail (server->refcount.value > 0);
00705 
00706 #ifdef DBUS_HAVE_ATOMIC_INT
00707   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00708 #else
00709   SERVER_LOCK (server);
00710   
00711   _dbus_assert (server->refcount.value > 0);
00712 
00713   server->refcount.value -= 1;
00714   last_unref = (server->refcount.value == 0);
00715   
00716   SERVER_UNLOCK (server);
00717 #endif
00718   
00719   if (last_unref)
00720     {
00721       /* lock not held! */
00722       _dbus_assert (server->disconnected);
00723       
00724       _dbus_assert (server->vtable->finalize != NULL);
00725       
00726       (* server->vtable->finalize) (server);
00727     }
00728 }
00729 
00738 void
00739 dbus_server_disconnect (DBusServer *server)
00740 {
00741   _dbus_return_if_fail (server != NULL);
00742   _dbus_return_if_fail (server->refcount.value > 0);
00743 
00744   SERVER_LOCK (server);
00745   _dbus_server_ref_unlocked (server);
00746   
00747   _dbus_assert (server->vtable->disconnect != NULL);
00748 
00749   if (!server->disconnected)
00750     {
00751       /* this has to be first so recursive calls to disconnect don't happen */
00752       server->disconnected = TRUE;
00753       
00754       (* server->vtable->disconnect) (server);
00755     }
00756 
00757   SERVER_UNLOCK (server);
00758   dbus_server_unref (server);
00759 }
00760 
00766 dbus_bool_t
00767 dbus_server_get_is_connected (DBusServer *server)
00768 {
00769   dbus_bool_t retval;
00770   
00771   _dbus_return_val_if_fail (server != NULL, FALSE);
00772 
00773   SERVER_LOCK (server);
00774   retval = !server->disconnected;
00775   SERVER_UNLOCK (server);
00776 
00777   return retval;
00778 }
00779 
00787 char*
00788 dbus_server_get_address (DBusServer *server)
00789 {
00790   char *retval;
00791   
00792   _dbus_return_val_if_fail (server != NULL, NULL);
00793 
00794   SERVER_LOCK (server);
00795   retval = _dbus_strdup (server->address);
00796   SERVER_UNLOCK (server);
00797 
00798   return retval;
00799 }
00800 
00823 char*
00824 dbus_server_get_id (DBusServer *server)
00825 {
00826   char *retval;
00827   
00828   _dbus_return_val_if_fail (server != NULL, NULL);
00829 
00830   SERVER_LOCK (server);
00831   retval = NULL;
00832   _dbus_string_copy_data (&server->guid_hex, &retval);
00833   SERVER_UNLOCK (server);
00834 
00835   return retval;
00836 }
00837 
00858 void
00859 dbus_server_set_new_connection_function (DBusServer                *server,
00860                                          DBusNewConnectionFunction  function,
00861                                          void                      *data,
00862                                          DBusFreeFunction           free_data_function)
00863 {
00864   DBusFreeFunction old_free_function;
00865   void *old_data;
00866   
00867   _dbus_return_if_fail (server != NULL);
00868 
00869   SERVER_LOCK (server);
00870   old_free_function = server->new_connection_free_data_function;
00871   old_data = server->new_connection_data;
00872   
00873   server->new_connection_function = function;
00874   server->new_connection_data = data;
00875   server->new_connection_free_data_function = free_data_function;
00876   SERVER_UNLOCK (server);
00877     
00878   if (old_free_function != NULL)
00879     (* old_free_function) (old_data);
00880 }
00881 
00898 dbus_bool_t
00899 dbus_server_set_watch_functions (DBusServer              *server,
00900                                  DBusAddWatchFunction     add_function,
00901                                  DBusRemoveWatchFunction  remove_function,
00902                                  DBusWatchToggledFunction toggled_function,
00903                                  void                    *data,
00904                                  DBusFreeFunction         free_data_function)
00905 {
00906   dbus_bool_t result;
00907   DBusWatchList *watches;
00908   
00909   _dbus_return_val_if_fail (server != NULL, FALSE);
00910 
00911   SERVER_LOCK (server);
00912   watches = server->watches;
00913   server->watches = NULL;
00914   if (watches)
00915     {
00916       SERVER_UNLOCK (server);
00917       result = _dbus_watch_list_set_functions (watches,
00918                                                add_function,
00919                                                remove_function,
00920                                                toggled_function,
00921                                                data,
00922                                                free_data_function);
00923       SERVER_LOCK (server);
00924     }
00925   else
00926     {
00927       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00928       result = FALSE;
00929     }
00930   server->watches = watches;
00931   SERVER_UNLOCK (server);
00932   
00933   return result;
00934 }
00935 
00951 dbus_bool_t
00952 dbus_server_set_timeout_functions (DBusServer                *server,
00953                                    DBusAddTimeoutFunction     add_function,
00954                                    DBusRemoveTimeoutFunction  remove_function,
00955                                    DBusTimeoutToggledFunction toggled_function,
00956                                    void                      *data,
00957                                    DBusFreeFunction           free_data_function)
00958 {
00959   dbus_bool_t result;
00960   DBusTimeoutList *timeouts;
00961   
00962   _dbus_return_val_if_fail (server != NULL, FALSE);
00963 
00964   SERVER_LOCK (server);
00965   timeouts = server->timeouts;
00966   server->timeouts = NULL;
00967   if (timeouts)
00968     {
00969       SERVER_UNLOCK (server);
00970       result = _dbus_timeout_list_set_functions (timeouts,
00971                                                  add_function,
00972                                                  remove_function,
00973                                                  toggled_function,
00974                                                  data,
00975                                                  free_data_function);
00976       SERVER_LOCK (server);
00977     }
00978   else
00979     {
00980       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00981       result = FALSE;
00982     }
00983   server->timeouts = timeouts;
00984   SERVER_UNLOCK (server);
00985   
00986   return result;
00987 }
00988 
01002 dbus_bool_t
01003 dbus_server_set_auth_mechanisms (DBusServer  *server,
01004                                  const char **mechanisms)
01005 {
01006   char **copy;
01007 
01008   _dbus_return_val_if_fail (server != NULL, FALSE);
01009 
01010   SERVER_LOCK (server);
01011   
01012   if (mechanisms != NULL)
01013     {
01014       copy = _dbus_dup_string_array (mechanisms);
01015       if (copy == NULL)
01016         return FALSE;
01017     }
01018   else
01019     copy = NULL;
01020 
01021   dbus_free_string_array (server->auth_mechanisms);
01022   server->auth_mechanisms = copy;
01023 
01024   SERVER_UNLOCK (server);
01025   
01026   return TRUE;
01027 }
01028 
01029 
01030 static DBusDataSlotAllocator slot_allocator;
01031 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01032 
01047 dbus_bool_t
01048 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01049 {
01050   return _dbus_data_slot_allocator_alloc (&slot_allocator,
01051                                           (DBusMutex **)&_DBUS_LOCK_NAME (server_slots),
01052                                           slot_p);
01053 }
01054 
01066 void
01067 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01068 {
01069   _dbus_return_if_fail (*slot_p >= 0);
01070   
01071   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01072 }
01073 
01087 dbus_bool_t
01088 dbus_server_set_data (DBusServer       *server,
01089                       int               slot,
01090                       void             *data,
01091                       DBusFreeFunction  free_data_func)
01092 {
01093   DBusFreeFunction old_free_func;
01094   void *old_data;
01095   dbus_bool_t retval;
01096 
01097   _dbus_return_val_if_fail (server != NULL, FALSE);
01098 
01099   SERVER_LOCK (server);
01100   
01101   retval = _dbus_data_slot_list_set (&slot_allocator,
01102                                      &server->slot_list,
01103                                      slot, data, free_data_func,
01104                                      &old_free_func, &old_data);
01105 
01106 
01107   SERVER_UNLOCK (server);
01108   
01109   if (retval)
01110     {
01111       /* Do the actual free outside the server lock */
01112       if (old_free_func)
01113         (* old_free_func) (old_data);
01114     }
01115 
01116   return retval;
01117 }
01118 
01127 void*
01128 dbus_server_get_data (DBusServer   *server,
01129                       int           slot)
01130 {
01131   void *res;
01132 
01133   _dbus_return_val_if_fail (server != NULL, NULL);
01134   
01135   SERVER_LOCK (server);
01136   
01137   res = _dbus_data_slot_list_get (&slot_allocator,
01138                                   &server->slot_list,
01139                                   slot);
01140 
01141   SERVER_UNLOCK (server);
01142   
01143   return res;
01144 }
01145 
01148 #ifdef DBUS_BUILD_TESTS
01149 #include "dbus-test.h"
01150 #include <string.h>
01151 
01152 dbus_bool_t
01153 _dbus_server_test (void)
01154 {
01155   const char *valid_addresses[] = {
01156     "tcp:port=1234",
01157     "tcp:host=localhost,port=1234",
01158     "tcp:host=localhost,port=1234;tcp:port=5678",
01159 #ifdef DBUS_UNIX
01160     "unix:path=./boogie",
01161     "tcp:port=1234;unix:path=./boogie",
01162 #endif
01163   };
01164 
01165   DBusServer *server;
01166   int i;
01167   
01168   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01169     {
01170       DBusError error;
01171       char *address;
01172       char *id;
01173       
01174       dbus_error_init (&error);
01175       server = dbus_server_listen (valid_addresses[i], &error);
01176       if (server == NULL)
01177         {
01178           _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
01179           dbus_error_free (&error);
01180           _dbus_assert_not_reached ("Failed to listen for valid address.");
01181         }
01182 
01183       id = dbus_server_get_id (server);
01184       _dbus_assert (id != NULL);
01185       address = dbus_server_get_address (server);
01186       _dbus_assert (address != NULL);
01187 
01188       if (strstr (address, id) == NULL)
01189         {
01190           _dbus_warn ("server id '%s' is not in the server address '%s'\n",
01191                       id, address);
01192           _dbus_assert_not_reached ("bad server id or address");
01193         }
01194 
01195       dbus_free (id);
01196       dbus_free (address);
01197       
01198       dbus_server_disconnect (server);
01199       dbus_server_unref (server);
01200     }
01201 
01202   return TRUE;
01203 }
01204 
01205 #endif /* DBUS_BUILD_TESTS */

Generated on Mon Feb 1 19:15:26 2010 for D-Bus by  doxygen 1.4.7