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