Home | History | Annotate | Download | only in dbus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
      2 /* dbus-server.c DBusServer object
      3  *
      4  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
      5  *
      6  * Licensed under the Academic Free License version 2.1
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation; either version 2 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #include <config.h>
     25 #include "dbus-server.h"
     26 #include "dbus-server-unix.h"
     27 #include "dbus-server-socket.h"
     28 #include "dbus-string.h"
     29 #ifdef DBUS_BUILD_TESTS
     30 #include "dbus-server-debug-pipe.h"
     31 #endif
     32 #include "dbus-address.h"
     33 #include "dbus-protocol.h"
     34 
     35 /**
     36  * @defgroup DBusServer DBusServer
     37  * @ingroup  DBus
     38  * @brief Server that listens for new connections.
     39  *
     40  * A DBusServer represents a server that other applications
     41  * can connect to. Each connection from another application
     42  * is represented by a #DBusConnection.
     43  *
     44  * @todo Thread safety hasn't been tested much for #DBusServer
     45  * @todo Need notification to apps of disconnection, may matter for some transports
     46  */
     47 
     48 /**
     49  * @defgroup DBusServerInternals DBusServer implementation details
     50  * @ingroup  DBusInternals
     51  * @brief Implementation details of DBusServer
     52  *
     53  * @{
     54  */
     55 
     56 #ifndef _dbus_server_trace_ref
     57 void
     58 _dbus_server_trace_ref (DBusServer *server,
     59     int old_refcount,
     60     int new_refcount,
     61     const char *why)
     62 {
     63   static int enabled = -1;
     64 
     65   _dbus_trace_ref ("DBusServer", server, old_refcount, new_refcount, why,
     66       "DBUS_SERVER_TRACE", &enabled);
     67 }
     68 #endif
     69 
     70 /* this is a little fragile since it assumes the address doesn't
     71  * already have a guid, but it shouldn't
     72  */
     73 static char*
     74 copy_address_with_guid_appended (const DBusString *address,
     75                                  const DBusString *guid_hex)
     76 {
     77   DBusString with_guid;
     78   char *retval;
     79 
     80   if (!_dbus_string_init (&with_guid))
     81     return NULL;
     82 
     83   if (!_dbus_string_copy (address, 0, &with_guid,
     84                           _dbus_string_get_length (&with_guid)) ||
     85       !_dbus_string_append (&with_guid, ",guid=") ||
     86       !_dbus_string_copy (guid_hex, 0,
     87                           &with_guid, _dbus_string_get_length (&with_guid)))
     88     {
     89       _dbus_string_free (&with_guid);
     90       return NULL;
     91     }
     92 
     93   retval = NULL;
     94   _dbus_string_steal_data (&with_guid, &retval);
     95 
     96   _dbus_string_free (&with_guid);
     97 
     98   return retval; /* may be NULL if steal_data failed */
     99 }
    100 
    101 /**
    102  * Initializes the members of the DBusServer base class.
    103  * Chained up to by subclass constructors.
    104  *
    105  * @param server the server.
    106  * @param vtable the vtable for the subclass.
    107  * @param address the server's address
    108  * @returns #TRUE on success.
    109  */
    110 dbus_bool_t
    111 _dbus_server_init_base (DBusServer             *server,
    112                         const DBusServerVTable *vtable,
    113                         const DBusString       *address)
    114 {
    115   server->vtable = vtable;
    116 
    117 #ifdef DBUS_DISABLE_ASSERT
    118   _dbus_atomic_inc (&server->refcount);
    119 #else
    120     {
    121       dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
    122 
    123       _dbus_assert (old_refcount == 0);
    124     }
    125 #endif
    126 
    127   server->address = NULL;
    128   server->watches = NULL;
    129   server->timeouts = NULL;
    130   server->published_address = FALSE;
    131 
    132   if (!_dbus_string_init (&server->guid_hex))
    133     return FALSE;
    134 
    135   _dbus_generate_uuid (&server->guid);
    136 
    137   if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
    138     goto failed;
    139 
    140   server->address = copy_address_with_guid_appended (address,
    141                                                      &server->guid_hex);
    142   if (server->address == NULL)
    143     goto failed;
    144 
    145   _dbus_rmutex_new_at_location (&server->mutex);
    146   if (server->mutex == NULL)
    147     goto failed;
    148 
    149   server->watches = _dbus_watch_list_new ();
    150   if (server->watches == NULL)
    151     goto failed;
    152 
    153   server->timeouts = _dbus_timeout_list_new ();
    154   if (server->timeouts == NULL)
    155     goto failed;
    156 
    157   _dbus_data_slot_list_init (&server->slot_list);
    158 
    159   _dbus_verbose ("Initialized server on address %s\n", server->address);
    160 
    161   return TRUE;
    162 
    163  failed:
    164   _dbus_rmutex_free_at_location (&server->mutex);
    165   server->mutex = NULL;
    166   if (server->watches)
    167     {
    168       _dbus_watch_list_free (server->watches);
    169       server->watches = NULL;
    170     }
    171   if (server->timeouts)
    172     {
    173       _dbus_timeout_list_free (server->timeouts);
    174       server->timeouts = NULL;
    175     }
    176   if (server->address)
    177     {
    178       dbus_free (server->address);
    179       server->address = NULL;
    180     }
    181   _dbus_string_free (&server->guid_hex);
    182 
    183   return FALSE;
    184 }
    185 
    186 /**
    187  * Finalizes the members of the DBusServer base class.
    188  * Chained up to by subclass finalizers.
    189  *
    190  * @param server the server.
    191  */
    192 void
    193 _dbus_server_finalize_base (DBusServer *server)
    194 {
    195   /* We don't have the lock, but nobody should be accessing
    196    * concurrently since they don't have a ref
    197    */
    198 #ifndef DBUS_DISABLE_CHECKS
    199   _dbus_assert (!server->have_server_lock);
    200 #endif
    201   _dbus_assert (server->disconnected);
    202 
    203   /* calls out to application code... */
    204   _dbus_data_slot_list_free (&server->slot_list);
    205 
    206   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
    207 
    208   _dbus_watch_list_free (server->watches);
    209   _dbus_timeout_list_free (server->timeouts);
    210 
    211   _dbus_rmutex_free_at_location (&server->mutex);
    212 
    213   dbus_free (server->address);
    214 
    215   dbus_free_string_array (server->auth_mechanisms);
    216 
    217   _dbus_string_free (&server->guid_hex);
    218 }
    219 
    220 
    221 /** Function to be called in protected_change_watch() with refcount held */
    222 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
    223                                                   DBusWatch     *watch);
    224 /** Function to be called in protected_change_watch() with refcount held */
    225 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
    226                                                   DBusWatch     *watch);
    227 /** Function to be called in protected_change_watch() with refcount held */
    228 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
    229                                                   DBusWatch     *watch,
    230                                                   dbus_bool_t    enabled);
    231 
    232 static dbus_bool_t
    233 protected_change_watch (DBusServer             *server,
    234                         DBusWatch              *watch,
    235                         DBusWatchAddFunction    add_function,
    236                         DBusWatchRemoveFunction remove_function,
    237                         DBusWatchToggleFunction toggle_function,
    238                         dbus_bool_t             enabled)
    239 {
    240   DBusWatchList *watches;
    241   dbus_bool_t retval;
    242 
    243   HAVE_LOCK_CHECK (server);
    244 
    245   /* This isn't really safe or reasonable; a better pattern is the "do
    246    * everything, then drop lock and call out" one; but it has to be
    247    * propagated up through all callers
    248    */
    249 
    250   watches = server->watches;
    251   if (watches)
    252     {
    253       server->watches = NULL;
    254       _dbus_server_ref_unlocked (server);
    255       SERVER_UNLOCK (server);
    256 
    257       if (add_function)
    258         retval = (* add_function) (watches, watch);
    259       else if (remove_function)
    260         {
    261           retval = TRUE;
    262           (* remove_function) (watches, watch);
    263         }
    264       else
    265         {
    266           retval = TRUE;
    267           (* toggle_function) (watches, watch, enabled);
    268         }
    269 
    270       SERVER_LOCK (server);
    271       server->watches = watches;
    272       _dbus_server_unref_unlocked (server);
    273 
    274       return retval;
    275     }
    276   else
    277     return FALSE;
    278 }
    279 
    280 /**
    281  * Adds a watch for this server, chaining out to application-provided
    282  * watch handlers.
    283  *
    284  * @param server the server.
    285  * @param watch the watch to add.
    286  */
    287 dbus_bool_t
    288 _dbus_server_add_watch (DBusServer *server,
    289                         DBusWatch  *watch)
    290 {
    291   HAVE_LOCK_CHECK (server);
    292   return protected_change_watch (server, watch,
    293                                  _dbus_watch_list_add_watch,
    294                                  NULL, NULL, FALSE);
    295 }
    296 
    297 /**
    298  * Removes a watch previously added with _dbus_server_remove_watch().
    299  *
    300  * @param server the server.
    301  * @param watch the watch to remove.
    302  */
    303 void
    304 _dbus_server_remove_watch  (DBusServer *server,
    305                             DBusWatch  *watch)
    306 {
    307   HAVE_LOCK_CHECK (server);
    308   protected_change_watch (server, watch,
    309                           NULL,
    310                           _dbus_watch_list_remove_watch,
    311                           NULL, FALSE);
    312 }
    313 
    314 /**
    315  * Toggles a watch and notifies app via server's
    316  * DBusWatchToggledFunction if available. It's an error to call this
    317  * function on a watch that was not previously added.
    318  *
    319  * @param server the server.
    320  * @param watch the watch to toggle.
    321  * @param enabled whether to enable or disable
    322  */
    323 void
    324 _dbus_server_toggle_watch (DBusServer  *server,
    325                            DBusWatch   *watch,
    326                            dbus_bool_t  enabled)
    327 {
    328   _dbus_assert (watch != NULL);
    329 
    330   HAVE_LOCK_CHECK (server);
    331   protected_change_watch (server, watch,
    332                           NULL, NULL,
    333                           _dbus_watch_list_toggle_watch,
    334                           enabled);
    335 }
    336 
    337 /** Function to be called in protected_change_timeout() with refcount held */
    338 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
    339                                                    DBusTimeout     *timeout);
    340 /** Function to be called in protected_change_timeout() with refcount held */
    341 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
    342                                                    DBusTimeout     *timeout);
    343 /** Function to be called in protected_change_timeout() with refcount held */
    344 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
    345                                                    DBusTimeout     *timeout,
    346                                                    dbus_bool_t      enabled);
    347 
    348 
    349 static dbus_bool_t
    350 protected_change_timeout (DBusServer               *server,
    351                           DBusTimeout              *timeout,
    352                           DBusTimeoutAddFunction    add_function,
    353                           DBusTimeoutRemoveFunction remove_function,
    354                           DBusTimeoutToggleFunction toggle_function,
    355                           dbus_bool_t               enabled)
    356 {
    357   DBusTimeoutList *timeouts;
    358   dbus_bool_t retval;
    359 
    360   HAVE_LOCK_CHECK (server);
    361 
    362   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
    363    * drop lock and call out" one; but it has to be propagated up through all callers
    364    */
    365 
    366   timeouts = server->timeouts;
    367   if (timeouts)
    368     {
    369       server->timeouts = NULL;
    370       _dbus_server_ref_unlocked (server);
    371       SERVER_UNLOCK (server);
    372 
    373       if (add_function)
    374         retval = (* add_function) (timeouts, timeout);
    375       else if (remove_function)
    376         {
    377           retval = TRUE;
    378           (* remove_function) (timeouts, timeout);
    379         }
    380       else
    381         {
    382           retval = TRUE;
    383           (* toggle_function) (timeouts, timeout, enabled);
    384         }
    385 
    386       SERVER_LOCK (server);
    387       server->timeouts = timeouts;
    388       _dbus_server_unref_unlocked (server);
    389 
    390       return retval;
    391     }
    392   else
    393     return FALSE;
    394 }
    395 
    396 /**
    397  * Adds a timeout for this server, chaining out to
    398  * application-provided timeout handlers. The timeout should be
    399  * repeatedly handled with dbus_timeout_handle() at its given interval
    400  * until it is removed.
    401  *
    402  * @param server the server.
    403  * @param timeout the timeout to add.
    404  */
    405 dbus_bool_t
    406 _dbus_server_add_timeout (DBusServer  *server,
    407 			  DBusTimeout *timeout)
    408 {
    409   return protected_change_timeout (server, timeout,
    410                                    _dbus_timeout_list_add_timeout,
    411                                    NULL, NULL, FALSE);
    412 }
    413 
    414 /**
    415  * Removes a timeout previously added with _dbus_server_add_timeout().
    416  *
    417  * @param server the server.
    418  * @param timeout the timeout to remove.
    419  */
    420 void
    421 _dbus_server_remove_timeout (DBusServer  *server,
    422 			     DBusTimeout *timeout)
    423 {
    424   protected_change_timeout (server, timeout,
    425                             NULL,
    426                             _dbus_timeout_list_remove_timeout,
    427                             NULL, FALSE);
    428 }
    429 
    430 /**
    431  * Toggles a timeout and notifies app via server's
    432  * DBusTimeoutToggledFunction if available. It's an error to call this
    433  * function on a timeout that was not previously added.
    434  *
    435  * @param server the server.
    436  * @param timeout the timeout to toggle.
    437  * @param enabled whether to enable or disable
    438  */
    439 void
    440 _dbus_server_toggle_timeout (DBusServer  *server,
    441                              DBusTimeout *timeout,
    442                              dbus_bool_t  enabled)
    443 {
    444   protected_change_timeout (server, timeout,
    445                             NULL, NULL,
    446                             _dbus_timeout_list_toggle_timeout,
    447                             enabled);
    448 }
    449 
    450 
    451 /**
    452  * Like dbus_server_ref() but does not acquire the lock (must already be held)
    453  *
    454  * @param server the server.
    455  */
    456 void
    457 _dbus_server_ref_unlocked (DBusServer *server)
    458 {
    459   dbus_int32_t old_refcount;
    460 
    461   _dbus_assert (server != NULL);
    462   HAVE_LOCK_CHECK (server);
    463 
    464   old_refcount = _dbus_atomic_inc (&server->refcount);
    465   _dbus_assert (old_refcount > 0);
    466   _dbus_server_trace_ref (server, old_refcount, old_refcount + 1,
    467       "ref_unlocked");
    468 }
    469 
    470 /**
    471  * Like dbus_server_unref() but does not acquire the lock (must already be held)
    472  *
    473  * @param server the server.
    474  */
    475 void
    476 _dbus_server_unref_unlocked (DBusServer *server)
    477 {
    478   dbus_int32_t old_refcount;
    479 
    480   /* Keep this in sync with dbus_server_unref */
    481 
    482   _dbus_assert (server != NULL);
    483 
    484   HAVE_LOCK_CHECK (server);
    485 
    486   old_refcount = _dbus_atomic_dec (&server->refcount);
    487   _dbus_assert (old_refcount > 0);
    488 
    489   _dbus_server_trace_ref (server, old_refcount, old_refcount - 1,
    490       "unref_unlocked");
    491 
    492   if (old_refcount == 1)
    493     {
    494       _dbus_assert (server->disconnected);
    495 
    496       SERVER_UNLOCK (server);
    497 
    498       _dbus_assert (server->vtable->finalize != NULL);
    499 
    500       (* server->vtable->finalize) (server);
    501     }
    502 }
    503 
    504 /** @} */
    505 
    506 /**
    507  * @addtogroup DBusServer
    508  *
    509  * @{
    510  */
    511 
    512 
    513 /**
    514  * @typedef DBusServer
    515  *
    516  * An opaque object representing a server that listens for
    517  * connections from other applications. Each time a connection
    518  * is made, a new DBusConnection is created and made available
    519  * via an application-provided DBusNewConnectionFunction.
    520  * The DBusNewConnectionFunction is provided with
    521  * dbus_server_set_new_connection_function().
    522  *
    523  */
    524 
    525 static const struct {
    526   DBusServerListenResult (* func) (DBusAddressEntry *entry,
    527                                    DBusServer      **server_p,
    528                                    DBusError        *error);
    529 } listen_funcs[] = {
    530   { _dbus_server_listen_socket }
    531   , { _dbus_server_listen_platform_specific }
    532 #ifdef DBUS_BUILD_TESTS
    533   , { _dbus_server_listen_debug_pipe }
    534 #endif
    535 };
    536 
    537 /**
    538  * Listens for new connections on the given address.  If there are
    539  * multiple semicolon-separated address entries in the address, tries
    540  * each one and listens on the first one that works.
    541  *
    542  * Returns #NULL and sets error if listening fails for any reason.
    543  * Otherwise returns a new #DBusServer.
    544  * dbus_server_set_new_connection_function(),
    545  * dbus_server_set_watch_functions(), and
    546  * dbus_server_set_timeout_functions() should be called immediately to
    547  * render the server fully functional.
    548  *
    549  * To free the server, applications must call first
    550  * dbus_server_disconnect() and then dbus_server_unref().
    551  *
    552  * @param address the address of this server.
    553  * @param error location to store reason for failure.
    554  * @returns a new #DBusServer, or #NULL on failure.
    555  *
    556  */
    557 DBusServer*
    558 dbus_server_listen (const char     *address,
    559                     DBusError      *error)
    560 {
    561   DBusServer *server;
    562   DBusAddressEntry **entries;
    563   int len, i;
    564   DBusError first_connect_error = DBUS_ERROR_INIT;
    565   dbus_bool_t handled_once;
    566 
    567   _dbus_return_val_if_fail (address != NULL, NULL);
    568   _dbus_return_val_if_error_is_set (error, NULL);
    569 
    570   if (!dbus_parse_address (address, &entries, &len, error))
    571     return NULL;
    572 
    573   server = NULL;
    574   handled_once = FALSE;
    575 
    576   for (i = 0; i < len; i++)
    577     {
    578       int j;
    579 
    580       for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
    581         {
    582           DBusServerListenResult result;
    583           DBusError tmp_error = DBUS_ERROR_INIT;
    584 
    585           result = (* listen_funcs[j].func) (entries[i],
    586                                              &server,
    587                                              &tmp_error);
    588 
    589           if (result == DBUS_SERVER_LISTEN_OK)
    590             {
    591               _dbus_assert (server != NULL);
    592               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
    593               handled_once = TRUE;
    594               goto out;
    595             }
    596           else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
    597             {
    598               _dbus_assert (server == NULL);
    599               dbus_set_error (error,
    600                        DBUS_ERROR_ADDRESS_IN_USE,
    601                        "Address '%s' already used",
    602                        dbus_address_entry_get_method (entries[0]));
    603               handled_once = TRUE;
    604               goto out;
    605             }
    606           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
    607             {
    608               _dbus_assert (server == NULL);
    609               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
    610               dbus_move_error (&tmp_error, error);
    611               handled_once = TRUE;
    612               goto out;
    613             }
    614           else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
    615             {
    616               _dbus_assert (server == NULL);
    617               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
    618 
    619               /* keep trying addresses */
    620             }
    621           else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
    622             {
    623               _dbus_assert (server == NULL);
    624               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
    625               if (!dbus_error_is_set (&first_connect_error))
    626                 dbus_move_error (&tmp_error, &first_connect_error);
    627               else
    628                 dbus_error_free (&tmp_error);
    629 
    630               handled_once = TRUE;
    631 
    632               /* keep trying addresses */
    633             }
    634         }
    635 
    636       _dbus_assert (server == NULL);
    637       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    638     }
    639 
    640  out:
    641 
    642   if (!handled_once)
    643     {
    644       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    645       if (len > 0)
    646         dbus_set_error (error,
    647                        DBUS_ERROR_BAD_ADDRESS,
    648                        "Unknown address type '%s'",
    649                        dbus_address_entry_get_method (entries[0]));
    650       else
    651         dbus_set_error (error,
    652                         DBUS_ERROR_BAD_ADDRESS,
    653                         "Empty address '%s'",
    654                         address);
    655     }
    656 
    657   dbus_address_entries_free (entries);
    658 
    659   if (server == NULL)
    660     {
    661       _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
    662                    dbus_error_is_set (error));
    663 
    664       if (error && dbus_error_is_set (error))
    665         {
    666           /* already set the error */
    667         }
    668       else
    669         {
    670           /* didn't set the error but either error should be
    671            * NULL or first_connect_error should be set.
    672            */
    673           _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
    674           dbus_move_error (&first_connect_error, error);
    675         }
    676 
    677       _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
    678       _DBUS_ASSERT_ERROR_IS_SET (error);
    679 
    680       return NULL;
    681     }
    682   else
    683     {
    684       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
    685       return server;
    686     }
    687 }
    688 
    689 /**
    690  * Increments the reference count of a DBusServer.
    691  *
    692  * @param server the server.
    693  * @returns the server
    694  */
    695 DBusServer *
    696 dbus_server_ref (DBusServer *server)
    697 {
    698   dbus_int32_t old_refcount;
    699 
    700   _dbus_return_val_if_fail (server != NULL, NULL);
    701 
    702   /* can't get the refcount without a side-effect */
    703   old_refcount = _dbus_atomic_inc (&server->refcount);
    704 
    705 #ifndef DBUS_DISABLE_CHECKS
    706   if (_DBUS_UNLIKELY (old_refcount <= 0))
    707     {
    708       /* undo side-effect first */
    709       _dbus_atomic_dec (&server->refcount);
    710       _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
    711                                _DBUS_FUNCTION_NAME, "old_refcount > 0",
    712                                __FILE__, __LINE__);
    713       return NULL;
    714     }
    715 #endif
    716 
    717   _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref");
    718 
    719   return server;
    720 }
    721 
    722 /**
    723  * Decrements the reference count of a DBusServer.  Finalizes the
    724  * server if the reference count reaches zero.
    725  *
    726  * The server must be disconnected before the refcount reaches zero.
    727  *
    728  * @param server the server.
    729  */
    730 void
    731 dbus_server_unref (DBusServer *server)
    732 {
    733   dbus_int32_t old_refcount;
    734 
    735   /* keep this in sync with unref_unlocked */
    736 
    737   _dbus_return_if_fail (server != NULL);
    738 
    739   /* can't get the refcount without a side-effect */
    740   old_refcount = _dbus_atomic_dec (&server->refcount);
    741 
    742 #ifndef DBUS_DISABLE_CHECKS
    743   if (_DBUS_UNLIKELY (old_refcount <= 0))
    744     {
    745       /* undo side-effect first */
    746       _dbus_atomic_inc (&server->refcount);
    747       _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
    748                                _DBUS_FUNCTION_NAME, "old_refcount > 0",
    749                                __FILE__, __LINE__);
    750       return;
    751     }
    752 #endif
    753 
    754   _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref");
    755 
    756   if (old_refcount == 1)
    757     {
    758       /* lock not held! */
    759       _dbus_assert (server->disconnected);
    760 
    761       _dbus_assert (server->vtable->finalize != NULL);
    762 
    763       (* server->vtable->finalize) (server);
    764     }
    765 }
    766 
    767 /**
    768  * Releases the server's address and stops listening for
    769  * new clients. If called more than once, only the first
    770  * call has an effect. Does not modify the server's
    771  * reference count.
    772  *
    773  * @param server the server.
    774  */
    775 void
    776 dbus_server_disconnect (DBusServer *server)
    777 {
    778   _dbus_return_if_fail (server != NULL);
    779 
    780 #ifdef DBUS_DISABLE_CHECKS
    781   _dbus_atomic_inc (&server->refcount);
    782 #else
    783     {
    784       dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
    785 
    786       _dbus_return_if_fail (old_refcount > 0);
    787     }
    788 #endif
    789 
    790   SERVER_LOCK (server);
    791 
    792   _dbus_assert (server->vtable->disconnect != NULL);
    793 
    794   if (!server->disconnected)
    795     {
    796       /* this has to be first so recursive calls to disconnect don't happen */
    797       server->disconnected = TRUE;
    798 
    799       (* server->vtable->disconnect) (server);
    800     }
    801 
    802   SERVER_UNLOCK (server);
    803   dbus_server_unref (server);
    804 }
    805 
    806 /**
    807  * Returns #TRUE if the server is still listening for new connections.
    808  *
    809  * @param server the server.
    810  */
    811 dbus_bool_t
    812 dbus_server_get_is_connected (DBusServer *server)
    813 {
    814   dbus_bool_t retval;
    815 
    816   _dbus_return_val_if_fail (server != NULL, FALSE);
    817 
    818   SERVER_LOCK (server);
    819   retval = !server->disconnected;
    820   SERVER_UNLOCK (server);
    821 
    822   return retval;
    823 }
    824 
    825 /**
    826  * Returns the address of the server, as a newly-allocated
    827  * string which must be freed by the caller.
    828  *
    829  * @param server the server
    830  * @returns the address or #NULL if no memory
    831  */
    832 char*
    833 dbus_server_get_address (DBusServer *server)
    834 {
    835   char *retval;
    836 
    837   _dbus_return_val_if_fail (server != NULL, NULL);
    838 
    839   SERVER_LOCK (server);
    840   retval = _dbus_strdup (server->address);
    841   SERVER_UNLOCK (server);
    842 
    843   return retval;
    844 }
    845 
    846 /**
    847  * Returns the unique ID of the server, as a newly-allocated
    848  * string which must be freed by the caller. This ID is
    849  * normally used by clients to tell when two #DBusConnection
    850  * would be equivalent (because the server address passed
    851  * to dbus_connection_open() will have the same guid in the
    852  * two cases). dbus_connection_open() can re-use an existing
    853  * connection with the same ID instead of opening a new
    854  * connection.
    855  *
    856  * This is an ID unique to each #DBusServer. Remember that
    857  * a #DBusServer represents only one mode of connecting,
    858  * so e.g. a bus daemon can listen on multiple addresses
    859  * which will mean it has multiple #DBusServer each with
    860  * their own ID.
    861  *
    862  * The ID is not a UUID in the sense of RFC4122; the details
    863  * are explained in the D-Bus specification.
    864  *
    865  * @param server the server
    866  * @returns the id of the server or #NULL if no memory
    867  */
    868 char*
    869 dbus_server_get_id (DBusServer *server)
    870 {
    871   char *retval;
    872 
    873   _dbus_return_val_if_fail (server != NULL, NULL);
    874 
    875   SERVER_LOCK (server);
    876   retval = NULL;
    877   _dbus_string_copy_data (&server->guid_hex, &retval);
    878   SERVER_UNLOCK (server);
    879 
    880   return retval;
    881 }
    882 
    883 /**
    884  * Sets a function to be used for handling new connections.  The given
    885  * function is passed each new connection as the connection is
    886  * created. If the new connection function increments the connection's
    887  * reference count, the connection will stay alive. Otherwise, the
    888  * connection will be unreferenced and closed. The new connection
    889  * function may also close the connection itself, which is considered
    890  * good form if the connection is not wanted.
    891  *
    892  * The connection here is private in the sense of
    893  * dbus_connection_open_private(), so if the new connection function
    894  * keeps a reference it must arrange for the connection to be closed.
    895  * i.e. libdbus does not own this connection once the new connection
    896  * function takes a reference.
    897  *
    898  * @param server the server.
    899  * @param function a function to handle new connections.
    900  * @param data data to pass to the new connection handler.
    901  * @param free_data_function function to free the data.
    902  */
    903 void
    904 dbus_server_set_new_connection_function (DBusServer                *server,
    905                                          DBusNewConnectionFunction  function,
    906                                          void                      *data,
    907                                          DBusFreeFunction           free_data_function)
    908 {
    909   DBusFreeFunction old_free_function;
    910   void *old_data;
    911 
    912   _dbus_return_if_fail (server != NULL);
    913 
    914   SERVER_LOCK (server);
    915   old_free_function = server->new_connection_free_data_function;
    916   old_data = server->new_connection_data;
    917 
    918   server->new_connection_function = function;
    919   server->new_connection_data = data;
    920   server->new_connection_free_data_function = free_data_function;
    921   SERVER_UNLOCK (server);
    922 
    923   if (old_free_function != NULL)
    924     (* old_free_function) (old_data);
    925 }
    926 
    927 /**
    928  * Sets the watch functions for the server. These functions are
    929  * responsible for making the application's main loop aware of file
    930  * descriptors that need to be monitored for events.
    931  *
    932  * This function behaves exactly like dbus_connection_set_watch_functions();
    933  * see the documentation for that routine.
    934  *
    935  * @param server the server.
    936  * @param add_function function to begin monitoring a new descriptor.
    937  * @param remove_function function to stop monitoring a descriptor.
    938  * @param toggled_function function to notify when the watch is enabled/disabled
    939  * @param data data to pass to add_function and remove_function.
    940  * @param free_data_function function to be called to free the data.
    941  * @returns #FALSE on failure (no memory)
    942  */
    943 dbus_bool_t
    944 dbus_server_set_watch_functions (DBusServer              *server,
    945                                  DBusAddWatchFunction     add_function,
    946                                  DBusRemoveWatchFunction  remove_function,
    947                                  DBusWatchToggledFunction toggled_function,
    948                                  void                    *data,
    949                                  DBusFreeFunction         free_data_function)
    950 {
    951   dbus_bool_t result;
    952   DBusWatchList *watches;
    953 
    954   _dbus_return_val_if_fail (server != NULL, FALSE);
    955 
    956   SERVER_LOCK (server);
    957   watches = server->watches;
    958   server->watches = NULL;
    959   if (watches)
    960     {
    961       SERVER_UNLOCK (server);
    962       result = _dbus_watch_list_set_functions (watches,
    963                                                add_function,
    964                                                remove_function,
    965                                                toggled_function,
    966                                                data,
    967                                                free_data_function);
    968       SERVER_LOCK (server);
    969     }
    970   else
    971     {
    972       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
    973       result = FALSE;
    974     }
    975   server->watches = watches;
    976   SERVER_UNLOCK (server);
    977 
    978   return result;
    979 }
    980 
    981 /**
    982  * Sets the timeout functions for the server. These functions are
    983  * responsible for making the application's main loop aware of timeouts.
    984  *
    985  * This function behaves exactly like dbus_connection_set_timeout_functions();
    986  * see the documentation for that routine.
    987  *
    988  * @param server the server.
    989  * @param add_function function to add a timeout.
    990  * @param remove_function function to remove a timeout.
    991  * @param toggled_function function to notify when the timeout is enabled/disabled
    992  * @param data data to pass to add_function and remove_function.
    993  * @param free_data_function function to be called to free the data.
    994  * @returns #FALSE on failure (no memory)
    995  */
    996 dbus_bool_t
    997 dbus_server_set_timeout_functions (DBusServer                *server,
    998 				   DBusAddTimeoutFunction     add_function,
    999 				   DBusRemoveTimeoutFunction  remove_function,
   1000                                    DBusTimeoutToggledFunction toggled_function,
   1001 				   void                      *data,
   1002 				   DBusFreeFunction           free_data_function)
   1003 {
   1004   dbus_bool_t result;
   1005   DBusTimeoutList *timeouts;
   1006 
   1007   _dbus_return_val_if_fail (server != NULL, FALSE);
   1008 
   1009   SERVER_LOCK (server);
   1010   timeouts = server->timeouts;
   1011   server->timeouts = NULL;
   1012   if (timeouts)
   1013     {
   1014       SERVER_UNLOCK (server);
   1015       result = _dbus_timeout_list_set_functions (timeouts,
   1016                                                  add_function,
   1017                                                  remove_function,
   1018                                                  toggled_function,
   1019                                                  data,
   1020                                                  free_data_function);
   1021       SERVER_LOCK (server);
   1022     }
   1023   else
   1024     {
   1025       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
   1026       result = FALSE;
   1027     }
   1028   server->timeouts = timeouts;
   1029   SERVER_UNLOCK (server);
   1030 
   1031   return result;
   1032 }
   1033 
   1034 /**
   1035  * Sets the authentication mechanisms that this server offers to
   1036  * clients, as a #NULL-terminated array of mechanism names. This
   1037  * function only affects connections created <em>after</em> it is
   1038  * called.  Pass #NULL instead of an array to use all available
   1039  * mechanisms (this is the default behavior).
   1040  *
   1041  * The D-Bus specification describes some of the supported mechanisms.
   1042  *
   1043  * @param server the server
   1044  * @param mechanisms #NULL-terminated array of mechanisms
   1045  * @returns #FALSE if no memory
   1046  */
   1047 dbus_bool_t
   1048 dbus_server_set_auth_mechanisms (DBusServer  *server,
   1049                                  const char **mechanisms)
   1050 {
   1051   char **copy;
   1052 
   1053   _dbus_return_val_if_fail (server != NULL, FALSE);
   1054 
   1055   SERVER_LOCK (server);
   1056 
   1057   if (mechanisms != NULL)
   1058     {
   1059       copy = _dbus_dup_string_array (mechanisms);
   1060       if (copy == NULL)
   1061         return FALSE;
   1062     }
   1063   else
   1064     copy = NULL;
   1065 
   1066   dbus_free_string_array (server->auth_mechanisms);
   1067   server->auth_mechanisms = copy;
   1068 
   1069   SERVER_UNLOCK (server);
   1070 
   1071   return TRUE;
   1072 }
   1073 
   1074 
   1075 static DBusDataSlotAllocator slot_allocator;
   1076 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
   1077 
   1078 /**
   1079  * Allocates an integer ID to be used for storing application-specific
   1080  * data on any DBusServer. The allocated ID may then be used
   1081  * with dbus_server_set_data() and dbus_server_get_data().
   1082  * The slot must be initialized with -1. If a nonnegative
   1083  * slot is passed in, the refcount is incremented on that
   1084  * slot, rather than creating a new slot.
   1085  *
   1086  * The allocated slot is global, i.e. all DBusServer objects will have
   1087  * a slot with the given integer ID reserved.
   1088  *
   1089  * @param slot_p address of global variable storing the slot ID
   1090  * @returns #FALSE on no memory
   1091  */
   1092 dbus_bool_t
   1093 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
   1094 {
   1095   return _dbus_data_slot_allocator_alloc (&slot_allocator,
   1096                                           (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots),
   1097                                           slot_p);
   1098 }
   1099 
   1100 /**
   1101  * Deallocates a global ID for server data slots.
   1102  * dbus_server_get_data() and dbus_server_set_data()
   1103  * may no longer be used with this slot.
   1104  * Existing data stored on existing DBusServer objects
   1105  * will be freed when the server is finalized,
   1106  * but may not be retrieved (and may only be replaced
   1107  * if someone else reallocates the slot).
   1108  *
   1109  * @param slot_p address of the slot to deallocate
   1110  */
   1111 void
   1112 dbus_server_free_data_slot (dbus_int32_t *slot_p)
   1113 {
   1114   _dbus_return_if_fail (*slot_p >= 0);
   1115 
   1116   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
   1117 }
   1118 
   1119 /**
   1120  * Stores a pointer on a DBusServer, along
   1121  * with an optional function to be used for freeing
   1122  * the data when the data is set again, or when
   1123  * the server is finalized. The slot number
   1124  * must have been allocated with dbus_server_allocate_data_slot().
   1125  *
   1126  * @param server the server
   1127  * @param slot the slot number
   1128  * @param data the data to store
   1129  * @param free_data_func finalizer function for the data
   1130  * @returns #TRUE if there was enough memory to store the data
   1131  */
   1132 dbus_bool_t
   1133 dbus_server_set_data (DBusServer       *server,
   1134                       int               slot,
   1135                       void             *data,
   1136                       DBusFreeFunction  free_data_func)
   1137 {
   1138   DBusFreeFunction old_free_func;
   1139   void *old_data;
   1140   dbus_bool_t retval;
   1141 
   1142   _dbus_return_val_if_fail (server != NULL, FALSE);
   1143 
   1144   SERVER_LOCK (server);
   1145 
   1146   retval = _dbus_data_slot_list_set (&slot_allocator,
   1147                                      &server->slot_list,
   1148                                      slot, data, free_data_func,
   1149                                      &old_free_func, &old_data);
   1150 
   1151 
   1152   SERVER_UNLOCK (server);
   1153 
   1154   if (retval)
   1155     {
   1156       /* Do the actual free outside the server lock */
   1157       if (old_free_func)
   1158         (* old_free_func) (old_data);
   1159     }
   1160 
   1161   return retval;
   1162 }
   1163 
   1164 /**
   1165  * Retrieves data previously set with dbus_server_set_data().
   1166  * The slot must still be allocated (must not have been freed).
   1167  *
   1168  * @param server the server
   1169  * @param slot the slot to get data from
   1170  * @returns the data, or #NULL if not found
   1171  */
   1172 void*
   1173 dbus_server_get_data (DBusServer   *server,
   1174                       int           slot)
   1175 {
   1176   void *res;
   1177 
   1178   _dbus_return_val_if_fail (server != NULL, NULL);
   1179 
   1180   SERVER_LOCK (server);
   1181 
   1182   res = _dbus_data_slot_list_get (&slot_allocator,
   1183                                   &server->slot_list,
   1184                                   slot);
   1185 
   1186   SERVER_UNLOCK (server);
   1187 
   1188   return res;
   1189 }
   1190 
   1191 /** @} */
   1192 
   1193 #ifdef DBUS_BUILD_TESTS
   1194 #include "dbus-test.h"
   1195 #include <string.h>
   1196 
   1197 dbus_bool_t
   1198 _dbus_server_test (void)
   1199 {
   1200   const char *valid_addresses[] = {
   1201     "tcp:port=1234",
   1202     "tcp:host=localhost,port=1234",
   1203     "tcp:host=localhost,port=1234;tcp:port=5678",
   1204 #ifdef DBUS_UNIX
   1205     "unix:path=./boogie",
   1206     "tcp:port=1234;unix:path=./boogie",
   1207 #endif
   1208   };
   1209 
   1210   DBusServer *server;
   1211   int i;
   1212 
   1213   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
   1214     {
   1215       DBusError error = DBUS_ERROR_INIT;
   1216       char *address;
   1217       char *id;
   1218 
   1219       server = dbus_server_listen (valid_addresses[i], &error);
   1220       if (server == NULL)
   1221         {
   1222           _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
   1223           dbus_error_free (&error);
   1224           _dbus_assert_not_reached ("Failed to listen for valid address.");
   1225         }
   1226 
   1227       id = dbus_server_get_id (server);
   1228       _dbus_assert (id != NULL);
   1229       address = dbus_server_get_address (server);
   1230       _dbus_assert (address != NULL);
   1231 
   1232       if (strstr (address, id) == NULL)
   1233         {
   1234           _dbus_warn ("server id '%s' is not in the server address '%s'\n",
   1235                       id, address);
   1236           _dbus_assert_not_reached ("bad server id or address");
   1237         }
   1238 
   1239       dbus_free (id);
   1240       dbus_free (address);
   1241 
   1242       dbus_server_disconnect (server);
   1243       dbus_server_unref (server);
   1244     }
   1245 
   1246   return TRUE;
   1247 }
   1248 
   1249 #endif /* DBUS_BUILD_TESTS */
   1250