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