Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | Data Fields | Related Pages

dbus-server.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-server.c DBusServer object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */ 
00023 
00024 #include "dbus-server.h"
00025 #include "dbus-server-unix.h"
00026 #include "dbus-string.h"
00027 #ifdef DBUS_BUILD_TESTS
00028 #include "dbus-server-debug-pipe.h"
00029 #endif
00030 #include "dbus-address.h"
00031 #include "dbus-protocol.h"
00032 
00055 static void
00056 init_guid (DBusGUID *guid)
00057 {
00058   long now;
00059   char *p;
00060   int ts_size;
00061 
00062   _dbus_get_current_time (&now, NULL);
00063 
00064   guid->as_uint32s[0] = now;
00065 
00066   ts_size = sizeof (guid->as_uint32s[0]);
00067   p = ((char*)guid->as_bytes) + ts_size;
00068   
00069   _dbus_generate_random_bytes_buffer (p,
00070                                       sizeof (guid->as_bytes) - ts_size);
00071 }
00072 
00073 /* this is a little fragile since it assumes the address doesn't
00074  * already have a guid, but it shouldn't
00075  */
00076 static char*
00077 copy_address_with_guid_appended (const DBusString *address,
00078                                  const DBusString *guid_hex)
00079 {
00080   DBusString with_guid;
00081   char *retval;
00082   
00083   if (!_dbus_string_init (&with_guid))
00084     return NULL;
00085 
00086   if (!_dbus_string_copy (address, 0, &with_guid,
00087                           _dbus_string_get_length (&with_guid)) ||
00088       !_dbus_string_append (&with_guid, ",guid=") ||
00089       !_dbus_string_copy (guid_hex, 0,
00090                           &with_guid, _dbus_string_get_length (&with_guid)))
00091     {
00092       _dbus_string_free (&with_guid);
00093       return NULL;
00094     }
00095 
00096   retval = NULL;
00097   _dbus_string_steal_data (&with_guid, &retval);
00098 
00099   _dbus_string_free (&with_guid);
00100       
00101   return retval; /* may be NULL if steal_data failed */
00102 }
00103 
00113 dbus_bool_t
00114 _dbus_server_init_base (DBusServer             *server,
00115                         const DBusServerVTable *vtable,
00116                         const DBusString       *address)
00117 {
00118   DBusString guid_raw;
00119   
00120   server->vtable = vtable;
00121   server->refcount.value = 1;
00122 
00123   server->address = NULL;
00124   server->watches = NULL;
00125   server->timeouts = NULL;
00126 
00127   if (!_dbus_string_init (&server->guid_hex))
00128     return FALSE;
00129 
00130   init_guid (&server->guid);
00131 
00132   _dbus_string_init_const_len (&guid_raw, (signed char*) server->guid.as_bytes,
00133                                sizeof (server->guid.as_bytes));
00134   if (!_dbus_string_hex_encode (&guid_raw, 0,
00135                                 &server->guid_hex,
00136                                 _dbus_string_get_length (&server->guid_hex)))
00137     goto failed;
00138   
00139   server->address = copy_address_with_guid_appended (address,
00140                                                      &server->guid_hex);
00141   if (server->address == NULL)
00142     goto failed;
00143   
00144   server->mutex = _dbus_mutex_new ();
00145   if (server->mutex == NULL)
00146     goto failed;
00147   
00148   server->watches = _dbus_watch_list_new ();
00149   if (server->watches == NULL)
00150     goto failed;
00151 
00152   server->timeouts = _dbus_timeout_list_new ();
00153   if (server->timeouts == NULL)
00154     goto failed;
00155 
00156   _dbus_data_slot_list_init (&server->slot_list);
00157 
00158   _dbus_verbose ("Initialized server on address %s\n", server->address);
00159   
00160   return TRUE;
00161 
00162  failed:
00163   if (server->mutex)
00164     {
00165       _dbus_mutex_free (server->mutex);
00166       server->mutex = NULL;
00167     }
00168   if (server->watches)
00169     {
00170       _dbus_watch_list_free (server->watches);
00171       server->watches = NULL;
00172     }
00173   if (server->timeouts)
00174     {
00175       _dbus_timeout_list_free (server->timeouts);
00176       server->timeouts = NULL;
00177     }
00178   if (server->address)
00179     {
00180       dbus_free (server->address);
00181       server->address = NULL;
00182     }
00183   _dbus_string_free (&server->guid_hex);
00184   
00185   return FALSE;
00186 }
00187 
00194 void
00195 _dbus_server_finalize_base (DBusServer *server)
00196 {
00197   /* We don't have the lock, but nobody should be accessing
00198    * concurrently since they don't have a ref
00199    */
00200 #ifndef DBUS_DISABLE_CHECKS
00201   _dbus_assert (!server->have_server_lock);
00202 #endif
00203   _dbus_assert (server->disconnected);
00204   
00205   /* calls out to application code... */
00206   _dbus_data_slot_list_free (&server->slot_list);
00207 
00208   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00209 
00210   _dbus_watch_list_free (server->watches);
00211   _dbus_timeout_list_free (server->timeouts);
00212 
00213   _dbus_mutex_free (server->mutex);
00214   
00215   dbus_free (server->address);
00216 
00217   dbus_free_string_array (server->auth_mechanisms);
00218 
00219   _dbus_string_free (&server->guid_hex);
00220 }
00221 
00222 
00223 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00224                                                   DBusWatch     *watch);
00225 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00226                                                   DBusWatch     *watch);
00227 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00228                                                   DBusWatch     *watch,
00229                                                   dbus_bool_t    enabled);
00230 
00231 static dbus_bool_t
00232 protected_change_watch (DBusServer             *server,
00233                         DBusWatch              *watch,
00234                         DBusWatchAddFunction    add_function,
00235                         DBusWatchRemoveFunction remove_function,
00236                         DBusWatchToggleFunction toggle_function,
00237                         dbus_bool_t             enabled)
00238 {
00239   DBusWatchList *watches;
00240   dbus_bool_t retval;
00241   
00242   HAVE_LOCK_CHECK (server);
00243 
00244   /* This isn't really safe or reasonable; a better pattern is the "do
00245    * everything, then drop lock and call out" one; but it has to be
00246    * propagated up through all callers
00247    */
00248   
00249   watches = server->watches;
00250   if (watches)
00251     {
00252       server->watches = NULL;
00253       _dbus_server_ref_unlocked (server);
00254       SERVER_UNLOCK (server);
00255 
00256       if (add_function)
00257         retval = (* add_function) (watches, watch);
00258       else if (remove_function)
00259         {
00260           retval = TRUE;
00261           (* remove_function) (watches, watch);
00262         }
00263       else
00264         {
00265           retval = TRUE;
00266           (* toggle_function) (watches, watch, enabled);
00267         }
00268       
00269       SERVER_LOCK (server);
00270       server->watches = watches;
00271       _dbus_server_unref_unlocked (server);
00272 
00273       return retval;
00274     }
00275   else
00276     return FALSE;
00277 }
00278 
00286 dbus_bool_t
00287 _dbus_server_add_watch (DBusServer *server,
00288                         DBusWatch  *watch)
00289 {
00290   HAVE_LOCK_CHECK (server);
00291   return protected_change_watch (server, watch,
00292                                  _dbus_watch_list_add_watch,
00293                                  NULL, NULL, FALSE);
00294 }
00295 
00302 void
00303 _dbus_server_remove_watch  (DBusServer *server,
00304                             DBusWatch  *watch)
00305 {
00306   HAVE_LOCK_CHECK (server);
00307   protected_change_watch (server, watch,
00308                           NULL,
00309                           _dbus_watch_list_remove_watch,
00310                           NULL, FALSE);
00311 }
00312 
00322 void
00323 _dbus_server_toggle_watch (DBusServer  *server,
00324                            DBusWatch   *watch,
00325                            dbus_bool_t  enabled)
00326 {
00327   _dbus_assert (watch != NULL);
00328 
00329   HAVE_LOCK_CHECK (server);
00330   protected_change_watch (server, watch,
00331                           NULL, NULL,
00332                           _dbus_watch_list_toggle_watch,
00333                           enabled);
00334 }
00335 
00336 
00337 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00338                                                    DBusTimeout     *timeout);
00339 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00340                                                    DBusTimeout     *timeout);
00341 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00342                                                    DBusTimeout     *timeout,
00343                                                    dbus_bool_t      enabled);
00344 
00345 
00346 static dbus_bool_t
00347 protected_change_timeout (DBusServer               *server,
00348                           DBusTimeout              *timeout,
00349                           DBusTimeoutAddFunction    add_function,
00350                           DBusTimeoutRemoveFunction remove_function,
00351                           DBusTimeoutToggleFunction toggle_function,
00352                           dbus_bool_t               enabled)
00353 {
00354   DBusTimeoutList *timeouts;
00355   dbus_bool_t retval;
00356   
00357   HAVE_LOCK_CHECK (server);
00358 
00359   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00360    * drop lock and call out" one; but it has to be propagated up through all callers
00361    */
00362   
00363   timeouts = server->timeouts;
00364   if (timeouts)
00365     {
00366       server->timeouts = NULL;
00367       _dbus_server_ref_unlocked (server);
00368       SERVER_UNLOCK (server);
00369 
00370       if (add_function)
00371         retval = (* add_function) (timeouts, timeout);
00372       else if (remove_function)
00373         {
00374           retval = TRUE;
00375           (* remove_function) (timeouts, timeout);
00376         }
00377       else
00378         {
00379           retval = TRUE;
00380           (* toggle_function) (timeouts, timeout, enabled);
00381         }
00382       
00383       SERVER_LOCK (server);
00384       server->timeouts = timeouts;
00385       _dbus_server_unref_unlocked (server);
00386 
00387       return retval;
00388     }
00389   else
00390     return FALSE;
00391 }
00392 
00402 dbus_bool_t
00403 _dbus_server_add_timeout (DBusServer  *server,
00404                           DBusTimeout *timeout)
00405 {
00406   return protected_change_timeout (server, timeout,
00407                                    _dbus_timeout_list_add_timeout,
00408                                    NULL, NULL, FALSE);
00409 }
00410 
00417 void
00418 _dbus_server_remove_timeout (DBusServer  *server,
00419                              DBusTimeout *timeout)
00420 {
00421   protected_change_timeout (server, timeout,
00422                             NULL,
00423                             _dbus_timeout_list_remove_timeout,
00424                             NULL, FALSE);
00425 }
00426 
00436 void
00437 _dbus_server_toggle_timeout (DBusServer  *server,
00438                              DBusTimeout *timeout,
00439                              dbus_bool_t  enabled)
00440 {
00441   protected_change_timeout (server, timeout,
00442                             NULL, NULL,
00443                             _dbus_timeout_list_toggle_timeout,
00444                             enabled);
00445 }
00446 
00447 
00485 DBusServer*
00486 dbus_server_listen (const char     *address,
00487                     DBusError      *error)
00488 {
00489   DBusServer *server;
00490   DBusAddressEntry **entries;
00491   int len, i;
00492   const char *address_problem_type;
00493   const char *address_problem_field;
00494   const char *address_problem_other;
00495 
00496   _dbus_return_val_if_fail (address != NULL, NULL);
00497   _dbus_return_val_if_error_is_set (error, NULL);
00498   
00499   if (!dbus_parse_address (address, &entries, &len, error))
00500     return NULL;
00501 
00502   server = NULL;
00503   address_problem_type = NULL;
00504   address_problem_field = NULL;
00505   address_problem_other = NULL;
00506   
00507   for (i = 0; i < len; i++)
00508     {
00509       const char *method;
00510 
00511       method = dbus_address_entry_get_method (entries[i]);
00512 
00513       if (strcmp (method, "unix") == 0)
00514         {
00515           const char *path = dbus_address_entry_get_value (entries[i], "path");
00516           const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
00517           const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
00518           
00519           if (path == NULL && tmpdir == NULL && abstract == NULL)
00520             {
00521               address_problem_type = "unix";
00522               address_problem_field = "path or tmpdir or abstract";
00523               goto bad_address;
00524             }
00525 
00526           if ((path && tmpdir) ||
00527               (path && abstract) ||
00528               (tmpdir && abstract))
00529             {
00530               address_problem_other = "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time";
00531               goto bad_address;
00532             }
00533 
00534           if (tmpdir != NULL)
00535             {
00536               DBusString full_path;
00537               DBusString filename;
00538               
00539               if (!_dbus_string_init (&full_path))
00540                 {
00541                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00542                   goto out;
00543                 }
00544                   
00545               if (!_dbus_string_init (&filename))
00546                 {
00547                   _dbus_string_free (&full_path);
00548                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00549                   goto out;
00550                 }
00551               
00552               if (!_dbus_string_append (&filename,
00553                                         "dbus-") ||
00554                   !_dbus_generate_random_ascii (&filename, 10) ||
00555                   !_dbus_string_append (&full_path, tmpdir) ||
00556                   !_dbus_concat_dir_and_file (&full_path, &filename))
00557                 {
00558                   _dbus_string_free (&full_path);
00559                   _dbus_string_free (&filename);
00560                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00561                   goto out;
00562                 }
00563               
00564               /* FIXME - we will unconditionally unlink() the path if
00565                * we don't support abstract namespace.  unlink() does
00566                * not follow symlinks, but would like independent
00567                * confirmation this is safe enough. See also
00568                * _dbus_listen_unix_socket() and comments therein.
00569                */
00570 
00571               /* Always use abstract namespace if possible with tmpdir */
00572               
00573               server =
00574                 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
00575 #ifdef HAVE_ABSTRACT_SOCKETS
00576                                                     TRUE,
00577 #else
00578                                                     FALSE,
00579 #endif
00580                                                     error);
00581 
00582               _dbus_string_free (&full_path);
00583               _dbus_string_free (&filename);
00584             }
00585           else
00586             {
00587               if (path)
00588                 server = _dbus_server_new_for_domain_socket (path, FALSE, error);
00589               else
00590                 server = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
00591             }
00592         }
00593       else if (strcmp (method, "tcp") == 0)
00594         {
00595           const char *host = dbus_address_entry_get_value (entries[i], "host");
00596           const char *port = dbus_address_entry_get_value (entries[i], "port");
00597           DBusString  str;
00598           long lport;
00599           dbus_bool_t sresult;
00600           
00601           if (port == NULL)
00602             {
00603               address_problem_type = "tcp";
00604               address_problem_field = "port";
00605               goto bad_address;
00606             }
00607 
00608           _dbus_string_init_const (&str, port);
00609           sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
00610           _dbus_string_free (&str);
00611           
00612           if (sresult == FALSE || lport <= 0 || lport > 65535)
00613             {
00614               address_problem_other = "Port is not an integer between 0 and 65535";
00615               goto bad_address;
00616             }
00617           
00618           server = _dbus_server_new_for_tcp_socket (host, lport, error);
00619 
00620           if (server)
00621             break;
00622         }
00623 #ifdef DBUS_BUILD_TESTS
00624       else if (strcmp (method, "debug-pipe") == 0)
00625         {
00626           const char *name = dbus_address_entry_get_value (entries[i], "name");
00627 
00628           if (name == NULL)
00629             {
00630               address_problem_type = "debug-pipe";
00631               address_problem_field = "name";
00632               goto bad_address;
00633             }
00634 
00635           server = _dbus_server_debug_pipe_new (name, error);
00636         }
00637 #endif
00638       else
00639         {
00640           address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
00641           goto bad_address;
00642         }
00643       
00644       if (server)
00645         break;
00646     }
00647 
00648  out:
00649   
00650   dbus_address_entries_free (entries);
00651   return server;
00652 
00653  bad_address:
00654   dbus_address_entries_free (entries);
00655   if (address_problem_type != NULL)
00656     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00657                     "Server address of type %s was missing argument %s",
00658                     address_problem_type, address_problem_field);
00659   else
00660     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00661                     "Could not parse server address: %s",
00662                     address_problem_other);
00663 
00664   return NULL;
00665 }
00666 
00673 DBusServer *
00674 dbus_server_ref (DBusServer *server)
00675 {
00676   _dbus_return_val_if_fail (server != NULL, NULL);
00677   _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
00678 
00679 #ifdef DBUS_HAVE_ATOMIC_INT
00680   _dbus_atomic_inc (&server->refcount);
00681 #else
00682   SERVER_LOCK (server);
00683   _dbus_assert (server->refcount.value > 0);
00684 
00685   server->refcount.value += 1;
00686   SERVER_UNLOCK (server);
00687 #endif
00688 
00689   return server;
00690 }
00691 
00700 void
00701 dbus_server_unref (DBusServer *server)
00702 {
00703   dbus_bool_t last_unref;
00704   
00705   _dbus_return_if_fail (server != NULL);
00706   _dbus_return_if_fail (server->refcount.value > 0);
00707 
00708 #ifdef DBUS_HAVE_ATOMIC_INT
00709   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00710 #else
00711   SERVER_LOCK (server);
00712   
00713   _dbus_assert (server->refcount.value > 0);
00714 
00715   server->refcount.value -= 1;
00716   last_unref = (server->refcount.value == 0);
00717   
00718   SERVER_UNLOCK (server);
00719 #endif
00720   
00721   if (last_unref)
00722     {
00723       /* lock not held! */
00724       _dbus_assert (server->disconnected);
00725       
00726       _dbus_assert (server->vtable->finalize != NULL);
00727       
00728       (* server->vtable->finalize) (server);
00729     }
00730 }
00731 
00737 void
00738 _dbus_server_ref_unlocked (DBusServer *server)
00739 {
00740   _dbus_assert (server != NULL);
00741   _dbus_assert (server->refcount.value > 0);
00742   
00743   HAVE_LOCK_CHECK (server);
00744 
00745 #ifdef DBUS_HAVE_ATOMIC_INT
00746   _dbus_atomic_inc (&server->refcount);
00747 #else
00748   _dbus_assert (server->refcount.value > 0);
00749 
00750   server->refcount.value += 1;
00751 #endif
00752 }
00753 
00759 void
00760 _dbus_server_unref_unlocked (DBusServer *server)
00761 {
00762   dbus_bool_t last_unref;
00763   
00764   _dbus_assert (server != NULL);
00765   _dbus_assert (server->refcount.value > 0);
00766 
00767   HAVE_LOCK_CHECK (server);
00768   
00769 #ifdef DBUS_HAVE_ATOMIC_INT
00770   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
00771 #else
00772   _dbus_assert (server->refcount.value > 0);
00773 
00774   server->refcount.value -= 1;
00775   last_unref = (server->refcount.value == 0);
00776 #endif
00777   
00778   if (last_unref)
00779     {
00780       _dbus_assert (server->disconnected);
00781       
00782       SERVER_UNLOCK (server);
00783       
00784       _dbus_assert (server->vtable->finalize != NULL);
00785       
00786       (* server->vtable->finalize) (server);
00787     }
00788 }
00789 
00798 void
00799 dbus_server_disconnect (DBusServer *server)
00800 {
00801   _dbus_return_if_fail (server != NULL);
00802   _dbus_return_if_fail (server->refcount.value > 0);
00803 
00804   SERVER_LOCK (server);
00805   _dbus_server_ref_unlocked (server);
00806   
00807   _dbus_assert (server->vtable->disconnect != NULL);
00808 
00809   if (!server->disconnected)
00810     {
00811       /* this has to be first so recursive calls to disconnect don't happen */
00812       server->disconnected = TRUE;
00813       
00814       (* server->vtable->disconnect) (server);
00815     }
00816 
00817   SERVER_UNLOCK (server);
00818   dbus_server_unref (server);
00819 }
00820 
00826 dbus_bool_t
00827 dbus_server_get_is_connected (DBusServer *server)
00828 {
00829   dbus_bool_t retval;
00830   
00831   _dbus_return_val_if_fail (server != NULL, FALSE);
00832 
00833   SERVER_LOCK (server);
00834   retval = !server->disconnected;
00835   SERVER_UNLOCK (server);
00836 
00837   return retval;
00838 }
00839 
00847 char*
00848 dbus_server_get_address (DBusServer *server)
00849 {
00850   char *retval;
00851   
00852   _dbus_return_val_if_fail (server != NULL, NULL);
00853 
00854   SERVER_LOCK (server);
00855   retval = _dbus_strdup (server->address);
00856   SERVER_UNLOCK (server);
00857 
00858   return retval;
00859 }
00860 
00873 void
00874 dbus_server_set_new_connection_function (DBusServer                *server,
00875                                          DBusNewConnectionFunction  function,
00876                                          void                      *data,
00877                                          DBusFreeFunction           free_data_function)
00878 {
00879   DBusFreeFunction old_free_function;
00880   void *old_data;
00881   
00882   _dbus_return_if_fail (server != NULL);
00883 
00884   SERVER_LOCK (server);
00885   old_free_function = server->new_connection_free_data_function;
00886   old_data = server->new_connection_data;
00887   
00888   server->new_connection_function = function;
00889   server->new_connection_data = data;
00890   server->new_connection_free_data_function = free_data_function;
00891   SERVER_UNLOCK (server);
00892     
00893   if (old_free_function != NULL)
00894     (* old_free_function) (old_data);
00895 }
00896 
00913 dbus_bool_t
00914 dbus_server_set_watch_functions (DBusServer              *server,
00915                                  DBusAddWatchFunction     add_function,
00916                                  DBusRemoveWatchFunction  remove_function,
00917                                  DBusWatchToggledFunction toggled_function,
00918                                  void                    *data,
00919                                  DBusFreeFunction         free_data_function)
00920 {
00921   dbus_bool_t result;
00922   DBusWatchList *watches;
00923   
00924   _dbus_return_val_if_fail (server != NULL, FALSE);
00925 
00926   SERVER_LOCK (server);
00927   watches = server->watches;
00928   server->watches = NULL;
00929   if (watches)
00930     {
00931       SERVER_UNLOCK (server);
00932       result = _dbus_watch_list_set_functions (watches,
00933                                                add_function,
00934                                                remove_function,
00935                                                toggled_function,
00936                                                data,
00937                                                free_data_function);
00938       SERVER_LOCK (server);
00939     }
00940   else
00941     {
00942       _dbus_warn ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00943       result = FALSE;
00944     }
00945   server->watches = watches;
00946   SERVER_UNLOCK (server);
00947   
00948   return result;
00949 }
00950 
00966 dbus_bool_t
00967 dbus_server_set_timeout_functions (DBusServer                *server,
00968                                    DBusAddTimeoutFunction     add_function,
00969                                    DBusRemoveTimeoutFunction  remove_function,
00970                                    DBusTimeoutToggledFunction toggled_function,
00971                                    void                      *data,
00972                                    DBusFreeFunction           free_data_function)
00973 {
00974   dbus_bool_t result;
00975   DBusTimeoutList *timeouts;
00976   
00977   _dbus_return_val_if_fail (server != NULL, FALSE);
00978 
00979   SERVER_LOCK (server);
00980   timeouts = server->timeouts;
00981   server->timeouts = NULL;
00982   if (timeouts)
00983     {
00984       SERVER_UNLOCK (server);
00985       result = _dbus_timeout_list_set_functions (timeouts,
00986                                                  add_function,
00987                                                  remove_function,
00988                                                  toggled_function,
00989                                                  data,
00990                                                  free_data_function);
00991       SERVER_LOCK (server);
00992     }
00993   else
00994     {
00995       _dbus_warn ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
00996       result = FALSE;
00997     }
00998   server->timeouts = timeouts;
00999   SERVER_UNLOCK (server);
01000   
01001   return result;
01002 }
01003 
01014 dbus_bool_t
01015 dbus_server_set_auth_mechanisms (DBusServer  *server,
01016                                  const char **mechanisms)
01017 {
01018   char **copy;
01019 
01020   _dbus_return_val_if_fail (server != NULL, FALSE);
01021 
01022   SERVER_LOCK (server);
01023   
01024   if (mechanisms != NULL)
01025     {
01026       copy = _dbus_dup_string_array (mechanisms);
01027       if (copy == NULL)
01028         return FALSE;
01029     }
01030   else
01031     copy = NULL;
01032 
01033   dbus_free_string_array (server->auth_mechanisms);
01034   server->auth_mechanisms = copy;
01035 
01036   SERVER_UNLOCK (server);
01037   
01038   return TRUE;
01039 }
01040 
01041 
01042 static DBusDataSlotAllocator slot_allocator;
01043 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
01044 
01059 dbus_bool_t
01060 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
01061 {
01062   return _dbus_data_slot_allocator_alloc (&slot_allocator,
01063                                           _DBUS_LOCK_NAME (server_slots),
01064                                           slot_p);
01065 }
01066 
01078 void
01079 dbus_server_free_data_slot (dbus_int32_t *slot_p)
01080 {
01081   _dbus_return_if_fail (*slot_p >= 0);
01082   
01083   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
01084 }
01085 
01099 dbus_bool_t
01100 dbus_server_set_data (DBusServer       *server,
01101                       int               slot,
01102                       void             *data,
01103                       DBusFreeFunction  free_data_func)
01104 {
01105   DBusFreeFunction old_free_func;
01106   void *old_data;
01107   dbus_bool_t retval;
01108 
01109   _dbus_return_val_if_fail (server != NULL, FALSE);
01110 
01111   SERVER_LOCK (server);
01112   
01113   retval = _dbus_data_slot_list_set (&slot_allocator,
01114                                      &server->slot_list,
01115                                      slot, data, free_data_func,
01116                                      &old_free_func, &old_data);
01117 
01118 
01119   SERVER_UNLOCK (server);
01120   
01121   if (retval)
01122     {
01123       /* Do the actual free outside the server lock */
01124       if (old_free_func)
01125         (* old_free_func) (old_data);
01126     }
01127 
01128   return retval;
01129 }
01130 
01139 void*
01140 dbus_server_get_data (DBusServer   *server,
01141                       int           slot)
01142 {
01143   void *res;
01144 
01145   _dbus_return_val_if_fail (server != NULL, NULL);
01146   
01147   SERVER_LOCK (server);
01148   
01149   res = _dbus_data_slot_list_get (&slot_allocator,
01150                                   &server->slot_list,
01151                                   slot);
01152 
01153   SERVER_UNLOCK (server);
01154   
01155   return res;
01156 }
01157 
01160 #ifdef DBUS_BUILD_TESTS
01161 #include "dbus-test.h"
01162 
01163 dbus_bool_t
01164 _dbus_server_test (void)
01165 {
01166   const char *valid_addresses[] = {
01167     "tcp:port=1234",
01168     "unix:path=./boogie",
01169     "tcp:host=localhost,port=1234",
01170     "tcp:host=localhost,port=1234;tcp:port=5678",
01171     "tcp:port=1234;unix:path=./boogie",
01172   };
01173 
01174   DBusServer *server;
01175   int i;
01176   
01177   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
01178     {
01179       server = dbus_server_listen (valid_addresses[i], NULL);
01180       if (server == NULL)
01181         _dbus_assert_not_reached ("Failed to listen for valid address.");
01182 
01183       dbus_server_disconnect (server);
01184       dbus_server_unref (server);
01185 
01186       /* Try disconnecting before unreffing */
01187       server = dbus_server_listen (valid_addresses[i], NULL);
01188       if (server == NULL)
01189         _dbus_assert_not_reached ("Failed to listen for valid address.");
01190 
01191       dbus_server_disconnect (server);
01192       dbus_server_unref (server);
01193     }
01194 
01195   return TRUE;
01196 }
01197 
01198 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Sep 13 01:28:07 2005 for D-BUS by  doxygen 1.4.4