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 1.2
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 
00454 void
00455 dbus_server_ref (DBusServer *server)
00456 {
00457   _dbus_return_if_fail (server != NULL);
00458   
00459   server->refcount += 1;
00460 }
00461 
00470 void
00471 dbus_server_unref (DBusServer *server)
00472 {
00473   _dbus_return_if_fail (server != NULL);
00474 
00475   _dbus_assert (server->refcount > 0);
00476 
00477   server->refcount -= 1;
00478   if (server->refcount == 0)
00479     {
00480       _dbus_assert (server->vtable->finalize != NULL);
00481       
00482       (* server->vtable->finalize) (server);
00483     }
00484 }
00485 
00494 void
00495 dbus_server_disconnect (DBusServer *server)
00496 {
00497   _dbus_return_if_fail (server != NULL);
00498   
00499   _dbus_assert (server->vtable->disconnect != NULL);
00500 
00501   if (server->disconnected)
00502     return;
00503   
00504   (* server->vtable->disconnect) (server);
00505   server->disconnected = TRUE;
00506 }
00507 
00513 dbus_bool_t
00514 dbus_server_get_is_connected (DBusServer *server)
00515 {
00516   _dbus_return_val_if_fail (server != NULL, FALSE);
00517   
00518   return !server->disconnected;
00519 }
00520 
00528 char*
00529 dbus_server_get_address (DBusServer *server)
00530 {
00531   _dbus_return_val_if_fail (server != NULL, NULL);
00532   
00533   return _dbus_strdup (server->address);
00534 }
00535 
00548 void
00549 dbus_server_set_new_connection_function (DBusServer                *server,
00550                                          DBusNewConnectionFunction  function,
00551                                          void                      *data,
00552                                          DBusFreeFunction           free_data_function)
00553 {
00554   _dbus_return_if_fail (server != NULL);
00555   
00556   if (server->new_connection_free_data_function != NULL)
00557     (* server->new_connection_free_data_function) (server->new_connection_data);
00558   
00559   server->new_connection_function = function;
00560   server->new_connection_data = data;
00561   server->new_connection_free_data_function = free_data_function;
00562 }
00563 
00580 dbus_bool_t
00581 dbus_server_set_watch_functions (DBusServer              *server,
00582                                  DBusAddWatchFunction     add_function,
00583                                  DBusRemoveWatchFunction  remove_function,
00584                                  DBusWatchToggledFunction toggled_function,
00585                                  void                    *data,
00586                                  DBusFreeFunction         free_data_function)
00587 {
00588   _dbus_return_val_if_fail (server != NULL, FALSE);
00589   
00590   return _dbus_watch_list_set_functions (server->watches,
00591                                          add_function,
00592                                          remove_function,
00593                                          toggled_function,
00594                                          data,
00595                                          free_data_function);
00596 }
00597 
00613 dbus_bool_t
00614 dbus_server_set_timeout_functions (DBusServer                *server,
00615                                    DBusAddTimeoutFunction     add_function,
00616                                    DBusRemoveTimeoutFunction  remove_function,
00617                                    DBusTimeoutToggledFunction toggled_function,
00618                                    void                      *data,
00619                                    DBusFreeFunction           free_data_function)
00620 {
00621   _dbus_return_val_if_fail (server != NULL, FALSE);
00622   
00623   return _dbus_timeout_list_set_functions (server->timeouts,
00624                                            add_function, remove_function,
00625                                            toggled_function,
00626                                            data, free_data_function); 
00627 }
00628 
00639 dbus_bool_t
00640 dbus_server_set_auth_mechanisms (DBusServer  *server,
00641                                  const char **mechanisms)
00642 {
00643   char **copy;
00644 
00645   _dbus_return_val_if_fail (server != NULL, FALSE);
00646   
00647   if (mechanisms != NULL)
00648     {
00649       copy = _dbus_dup_string_array (mechanisms);
00650       if (copy == NULL)
00651         return FALSE;
00652     }
00653   else
00654     copy = NULL;
00655 
00656   dbus_free_string_array (server->auth_mechanisms);
00657   server->auth_mechanisms = copy;
00658 
00659   return TRUE;
00660 }
00661 
00662 
00663 static DBusDataSlotAllocator slot_allocator;
00664 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
00665 
00680 dbus_bool_t
00681 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
00682 {
00683   return _dbus_data_slot_allocator_alloc (&slot_allocator,
00684                                           _DBUS_LOCK_NAME (server_slots),
00685                                           slot_p);
00686 }
00687 
00699 void
00700 dbus_server_free_data_slot (dbus_int32_t *slot_p)
00701 {
00702   _dbus_return_if_fail (*slot_p >= 0);
00703   
00704   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00705 }
00706 
00720 dbus_bool_t
00721 dbus_server_set_data (DBusServer       *server,
00722                       int               slot,
00723                       void             *data,
00724                       DBusFreeFunction  free_data_func)
00725 {
00726   DBusFreeFunction old_free_func;
00727   void *old_data;
00728   dbus_bool_t retval;
00729 
00730   _dbus_return_val_if_fail (server != NULL, FALSE);
00731   
00732 #if 0
00733   dbus_mutex_lock (server->mutex);
00734 #endif
00735   
00736   retval = _dbus_data_slot_list_set (&slot_allocator,
00737                                      &server->slot_list,
00738                                      slot, data, free_data_func,
00739                                      &old_free_func, &old_data);
00740 
00741 #if 0
00742   dbus_mutex_unlock (server->mutex);
00743 #endif
00744   
00745   if (retval)
00746     {
00747       /* Do the actual free outside the server lock */
00748       if (old_free_func)
00749         (* old_free_func) (old_data);
00750     }
00751 
00752   return retval;
00753 }
00754 
00763 void*
00764 dbus_server_get_data (DBusServer   *server,
00765                       int           slot)
00766 {
00767   void *res;
00768 
00769   _dbus_return_val_if_fail (server != NULL, NULL);
00770   
00771 #if 0
00772   dbus_mutex_lock (server->mutex);
00773 #endif
00774   
00775   res = _dbus_data_slot_list_get (&slot_allocator,
00776                                   &server->slot_list,
00777                                   slot);
00778 
00779 #if 0
00780   dbus_mutex_unlock (server->mutex);
00781 #endif
00782   
00783   return res;
00784 }
00785 

Generated on Tue Feb 10 18:14:07 2004 for D-BUS by doxygen 1.3.5