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

Generated on Wed Oct 22 14:05:03 2003 for D-BUS by doxygen1.3-rc3