Main Page | Modules | Data Structures | File List | 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 Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.0
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 
00063 dbus_bool_t
00064 _dbus_server_init_base (DBusServer             *server,
00065                         const DBusServerVTable *vtable,
00066                         const DBusString       *address)
00067 {
00068   server->vtable = vtable;
00069   server->refcount = 1;
00070 
00071   server->address = NULL;
00072   server->watches = NULL;
00073   server->timeouts = NULL;
00074   
00075   if (!_dbus_string_copy_data (address, &server->address))
00076     goto failed;
00077   
00078   server->watches = _dbus_watch_list_new ();
00079   if (server->watches == NULL)
00080     goto failed;
00081 
00082   server->timeouts = _dbus_timeout_list_new ();
00083   if (server->timeouts == NULL)
00084     goto failed;
00085 
00086   _dbus_data_slot_list_init (&server->slot_list);
00087 
00088   _dbus_verbose ("Initialized server on address %s\n", server->address);
00089   
00090   return TRUE;
00091 
00092  failed:
00093   if (server->watches)
00094     {
00095       _dbus_watch_list_free (server->watches);
00096       server->watches = NULL;
00097     }
00098   if (server->timeouts)
00099     {
00100       _dbus_timeout_list_free (server->timeouts);
00101       server->timeouts = NULL;
00102     }
00103   if (server->address)
00104     {
00105       dbus_free (server->address);
00106       server->address = NULL;
00107     }
00108   
00109   return FALSE;
00110 }
00111 
00118 void
00119 _dbus_server_finalize_base (DBusServer *server)
00120 {
00121   /* calls out to application code... */
00122   _dbus_data_slot_list_free (&server->slot_list);
00123 
00124   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
00125 
00126   if (!server->disconnected)
00127     dbus_server_disconnect (server);
00128 
00129   _dbus_watch_list_free (server->watches);
00130   _dbus_timeout_list_free (server->timeouts);
00131 
00132   dbus_free (server->address);
00133 
00134   dbus_free_string_array (server->auth_mechanisms);
00135 }
00136 
00144 dbus_bool_t
00145 _dbus_server_add_watch (DBusServer *server,
00146                         DBusWatch  *watch)
00147 {
00148   return _dbus_watch_list_add_watch (server->watches, watch);
00149 }
00150 
00157 void
00158 _dbus_server_remove_watch  (DBusServer *server,
00159                             DBusWatch  *watch)
00160 {
00161   _dbus_watch_list_remove_watch (server->watches, watch);
00162 }
00163 
00173 void
00174 _dbus_server_toggle_watch (DBusServer  *server,
00175                            DBusWatch   *watch,
00176                            dbus_bool_t  enabled)
00177 {
00178   if (server->watches) /* null during finalize */
00179     _dbus_watch_list_toggle_watch (server->watches,
00180                                    watch, enabled);
00181 }
00182 
00192 dbus_bool_t
00193 _dbus_server_add_timeout (DBusServer  *server,
00194                           DBusTimeout *timeout)
00195 {
00196   return _dbus_timeout_list_add_timeout (server->timeouts, timeout);
00197 }
00198 
00205 void
00206 _dbus_server_remove_timeout (DBusServer  *server,
00207                              DBusTimeout *timeout)
00208 {
00209   _dbus_timeout_list_remove_timeout (server->timeouts, timeout);  
00210 }
00211 
00221 void
00222 _dbus_server_toggle_timeout (DBusServer  *server,
00223                              DBusTimeout *timeout,
00224                              dbus_bool_t  enabled)
00225 {
00226   if (server->timeouts) /* null during finalize */
00227     _dbus_timeout_list_toggle_timeout (server->timeouts,
00228                                        timeout, enabled);
00229 }
00230 
00231 
00269 DBusServer*
00270 dbus_server_listen (const char     *address,
00271                     DBusError      *error)
00272 {
00273   DBusServer *server;
00274   DBusAddressEntry **entries;
00275   int len, i;
00276   const char *address_problem_type;
00277   const char *address_problem_field;
00278   const char *address_problem_other;
00279 
00280   _dbus_return_val_if_fail (address != NULL, NULL);
00281   _dbus_return_val_if_error_is_set (error, NULL);
00282   
00283   if (!dbus_parse_address (address, &entries, &len, error))
00284     return NULL;
00285 
00286   server = NULL;
00287   address_problem_type = NULL;
00288   address_problem_field = NULL;
00289   address_problem_other = NULL;
00290   
00291   for (i = 0; i < len; i++)
00292     {
00293       const char *method = dbus_address_entry_get_method (entries[i]);
00294 
00295       if (strcmp (method, "unix") == 0)
00296         {
00297           const char *path = dbus_address_entry_get_value (entries[i], "path");
00298           const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
00299           const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
00300           
00301           if (path == NULL && tmpdir == NULL && abstract == NULL)
00302             {
00303               address_problem_type = "unix";
00304               address_problem_field = "path or tmpdir or abstract";
00305               goto bad_address;
00306             }
00307 
00308           if ((path && tmpdir) ||
00309               (path && abstract) ||
00310               (tmpdir && abstract))
00311             {
00312               address_problem_other = "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time";
00313               goto bad_address;
00314             }
00315 
00316           if (tmpdir != NULL)
00317             {
00318               DBusString full_path;
00319               DBusString filename;
00320               
00321               if (!_dbus_string_init (&full_path))
00322                 {
00323                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00324                   goto out;
00325                 }
00326                   
00327               if (!_dbus_string_init (&filename))
00328                 {
00329                   _dbus_string_free (&full_path);
00330                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00331                   goto out;
00332                 }
00333               
00334               if (!_dbus_string_append (&filename,
00335                                         "dbus-") ||
00336                   !_dbus_generate_random_ascii (&filename, 10) ||
00337                   !_dbus_string_append (&full_path, tmpdir) ||
00338                   !_dbus_concat_dir_and_file (&full_path, &filename))
00339                 {
00340                   _dbus_string_free (&full_path);
00341                   _dbus_string_free (&filename);
00342                   dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
00343                   goto out;
00344                 }
00345               
00346               /* FIXME - we will unconditionally unlink() the path if
00347                * we don't support abstract namespace.  unlink() does
00348                * not follow symlinks, but would like independent
00349                * confirmation this is safe enough. See also
00350                * _dbus_listen_unix_socket() and comments therein.
00351                */
00352 
00353               /* Always use abstract namespace if possible with tmpdir */
00354               
00355               server =
00356                 _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
00357 #ifdef HAVE_ABSTRACT_SOCKETS
00358                                                     TRUE,
00359 #else
00360                                                     FALSE,
00361 #endif
00362                                                     error);
00363 
00364               _dbus_string_free (&full_path);
00365               _dbus_string_free (&filename);
00366             }
00367           else
00368             {
00369               if (path)
00370                 server = _dbus_server_new_for_domain_socket (path, FALSE, error);
00371               else
00372                 server = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
00373             }
00374         }
00375       else if (strcmp (method, "tcp") == 0)
00376         {
00377           const char *host = dbus_address_entry_get_value (entries[i], "host");
00378           const char *port = dbus_address_entry_get_value (entries[i], "port");
00379           DBusString  str;
00380           long lport;
00381           dbus_bool_t sresult;
00382           
00383           if (port == NULL)
00384             {
00385               address_problem_type = "tcp";
00386               address_problem_field = "port";
00387               goto bad_address;
00388             }
00389 
00390           _dbus_string_init_const (&str, port);
00391           sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
00392           _dbus_string_free (&str);
00393           
00394           if (sresult == FALSE || lport <= 0 || lport > 65535)
00395             {
00396               address_problem_other = "Port is not an integer between 0 and 65535";
00397               goto bad_address;
00398             }
00399           
00400           server = _dbus_server_new_for_tcp_socket (host, lport, error);
00401 
00402           if (server)
00403             break;
00404         }
00405 #ifdef DBUS_BUILD_TESTS
00406       else if (strcmp (method, "debug-pipe") == 0)
00407         {
00408           const char *name = dbus_address_entry_get_value (entries[i], "name");
00409 
00410           if (name == NULL)
00411             {
00412               address_problem_type = "debug-pipe";
00413               address_problem_field = "name";
00414               goto bad_address;
00415             }
00416 
00417           server = _dbus_server_debug_pipe_new (name, error);
00418         }
00419 #endif
00420       else
00421         {
00422           address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
00423           goto bad_address;
00424         }
00425       
00426       if (server)
00427         break;
00428     }
00429 
00430  out:
00431   
00432   dbus_address_entries_free (entries);
00433   return server;
00434 
00435  bad_address:
00436   dbus_address_entries_free (entries);
00437   if (address_problem_type != NULL)
00438     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00439                     "Server address of type %s was missing argument %s",
00440                     address_problem_type, address_problem_field);
00441   else
00442     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
00443                     "Could not parse server address: %s",
00444                     address_problem_other);
00445 
00446   return NULL;
00447 }
00448 
00455 DBusServer *
00456 dbus_server_ref (DBusServer *server)
00457 {
00458   _dbus_return_if_fail (server != NULL);
00459   
00460   server->refcount += 1;
00461 
00462   return server;
00463 }
00464 
00473 void
00474 dbus_server_unref (DBusServer *server)
00475 {
00476   _dbus_return_if_fail (server != NULL);
00477 
00478   _dbus_assert (server->refcount > 0);
00479 
00480   server->refcount -= 1;
00481   if (server->refcount == 0)
00482     {
00483       _dbus_assert (server->vtable->finalize != NULL);
00484       
00485       (* server->vtable->finalize) (server);
00486     }
00487 }
00488 
00497 void
00498 dbus_server_disconnect (DBusServer *server)
00499 {
00500   _dbus_return_if_fail (server != NULL);
00501   
00502   _dbus_assert (server->vtable->disconnect != NULL);
00503 
00504   if (server->disconnected)
00505     return;
00506   
00507   (* server->vtable->disconnect) (server);
00508   server->disconnected = TRUE;
00509 }
00510 
00516 dbus_bool_t
00517 dbus_server_get_is_connected (DBusServer *server)
00518 {
00519   _dbus_return_val_if_fail (server != NULL, FALSE);
00520   
00521   return !server->disconnected;
00522 }
00523 
00531 char*
00532 dbus_server_get_address (DBusServer *server)
00533 {
00534   _dbus_return_val_if_fail (server != NULL, NULL);
00535   
00536   return _dbus_strdup (server->address);
00537 }
00538 
00551 void
00552 dbus_server_set_new_connection_function (DBusServer                *server,
00553                                          DBusNewConnectionFunction  function,
00554                                          void                      *data,
00555                                          DBusFreeFunction           free_data_function)
00556 {
00557   _dbus_return_if_fail (server != NULL);
00558   
00559   if (server->new_connection_free_data_function != NULL)
00560     (* server->new_connection_free_data_function) (server->new_connection_data);
00561   
00562   server->new_connection_function = function;
00563   server->new_connection_data = data;
00564   server->new_connection_free_data_function = free_data_function;
00565 }
00566 
00583 dbus_bool_t
00584 dbus_server_set_watch_functions (DBusServer              *server,
00585                                  DBusAddWatchFunction     add_function,
00586                                  DBusRemoveWatchFunction  remove_function,
00587                                  DBusWatchToggledFunction toggled_function,
00588                                  void                    *data,
00589                                  DBusFreeFunction         free_data_function)
00590 {
00591   _dbus_return_val_if_fail (server != NULL, FALSE);
00592   
00593   return _dbus_watch_list_set_functions (server->watches,
00594                                          add_function,
00595                                          remove_function,
00596                                          toggled_function,
00597                                          data,
00598                                          free_data_function);
00599 }
00600 
00616 dbus_bool_t
00617 dbus_server_set_timeout_functions (DBusServer                *server,
00618                                    DBusAddTimeoutFunction     add_function,
00619                                    DBusRemoveTimeoutFunction  remove_function,
00620                                    DBusTimeoutToggledFunction toggled_function,
00621                                    void                      *data,
00622                                    DBusFreeFunction           free_data_function)
00623 {
00624   _dbus_return_val_if_fail (server != NULL, FALSE);
00625   
00626   return _dbus_timeout_list_set_functions (server->timeouts,
00627                                            add_function, remove_function,
00628                                            toggled_function,
00629                                            data, free_data_function); 
00630 }
00631 
00642 dbus_bool_t
00643 dbus_server_set_auth_mechanisms (DBusServer  *server,
00644                                  const char **mechanisms)
00645 {
00646   char **copy;
00647 
00648   _dbus_return_val_if_fail (server != NULL, FALSE);
00649   
00650   if (mechanisms != NULL)
00651     {
00652       copy = _dbus_dup_string_array (mechanisms);
00653       if (copy == NULL)
00654         return FALSE;
00655     }
00656   else
00657     copy = NULL;
00658 
00659   dbus_free_string_array (server->auth_mechanisms);
00660   server->auth_mechanisms = copy;
00661 
00662   return TRUE;
00663 }
00664 
00665 
00666 static DBusDataSlotAllocator slot_allocator;
00667 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
00668 
00683 dbus_bool_t
00684 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
00685 {
00686   return _dbus_data_slot_allocator_alloc (&slot_allocator,
00687                                           _DBUS_LOCK_NAME (server_slots),
00688                                           slot_p);
00689 }
00690 
00702 void
00703 dbus_server_free_data_slot (dbus_int32_t *slot_p)
00704 {
00705   _dbus_return_if_fail (*slot_p >= 0);
00706   
00707   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00708 }
00709 
00723 dbus_bool_t
00724 dbus_server_set_data (DBusServer       *server,
00725                       int               slot,
00726                       void             *data,
00727                       DBusFreeFunction  free_data_func)
00728 {
00729   DBusFreeFunction old_free_func;
00730   void *old_data;
00731   dbus_bool_t retval;
00732 
00733   _dbus_return_val_if_fail (server != NULL, FALSE);
00734   
00735 #if 0
00736   dbus_mutex_lock (server->mutex);
00737 #endif
00738   
00739   retval = _dbus_data_slot_list_set (&slot_allocator,
00740                                      &server->slot_list,
00741                                      slot, data, free_data_func,
00742                                      &old_free_func, &old_data);
00743 
00744 #if 0
00745   dbus_mutex_unlock (server->mutex);
00746 #endif
00747   
00748   if (retval)
00749     {
00750       /* Do the actual free outside the server lock */
00751       if (old_free_func)
00752         (* old_free_func) (old_data);
00753     }
00754 
00755   return retval;
00756 }
00757 
00766 void*
00767 dbus_server_get_data (DBusServer   *server,
00768                       int           slot)
00769 {
00770   void *res;
00771 
00772   _dbus_return_val_if_fail (server != NULL, NULL);
00773   
00774 #if 0
00775   dbus_mutex_lock (server->mutex);
00776 #endif
00777   
00778   res = _dbus_data_slot_list_get (&slot_allocator,
00779                                   &server->slot_list,
00780                                   slot);
00781 
00782 #if 0
00783   dbus_mutex_unlock (server->mutex);
00784 #endif
00785   
00786   return res;
00787 }
00788 

Generated on Sun Mar 21 03:52:05 2004 for D-BUS by doxygen 1.3.6-20040222