Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-message-handler.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-message-handler.c Sender/receiver of messages.
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-internals.h"
00025 #include "dbus-message-handler.h"
00026 #include "dbus-list.h"
00027 #include "dbus-threads.h"
00028 #include "dbus-test.h"
00029 #include "dbus-connection-internal.h"
00030 
00041 _DBUS_DEFINE_GLOBAL_LOCK (message_handler);
00042 
00048 struct DBusMessageHandler
00049 {
00050   DBusAtomic refcount;                            
00052   DBusHandleMessageFunction function;             
00053   void                     *user_data;            
00054   DBusFreeFunction          free_user_data;       
00056   DBusList *connections;                          
00057 };
00058 
00068 dbus_bool_t
00069 _dbus_message_handler_add_connection (DBusMessageHandler *handler,
00070                                       DBusConnection     *connection)
00071 {
00072   dbus_bool_t res;
00073   
00074   _DBUS_LOCK (message_handler);
00075   /* This is a bit wasteful - we just put the connection in the list
00076    * once per time it's added. :-/
00077    */
00078   if (!_dbus_list_prepend (&handler->connections, connection))
00079     res = FALSE;
00080   else
00081     res = TRUE;
00082 
00083   _DBUS_UNLOCK (message_handler);
00084   
00085   return res;
00086 }
00087 
00093 void
00094 _dbus_message_handler_remove_connection (DBusMessageHandler *handler,
00095                                          DBusConnection     *connection)
00096 {
00097   _DBUS_LOCK (message_handler);
00098   if (!_dbus_list_remove (&handler->connections, connection))
00099     _dbus_warn ("Function _dbus_message_handler_remove_connection() called when the connection hadn't been added\n");
00100   _DBUS_UNLOCK (message_handler);
00101 }
00102 
00103 
00114 DBusHandlerResult
00115 _dbus_message_handler_handle_message (DBusMessageHandler        *handler,
00116                                       DBusConnection            *connection,
00117                                       DBusMessage               *message)
00118 {
00119   DBusHandleMessageFunction function;
00120   void  *user_data;
00121   
00122   _DBUS_LOCK (message_handler);
00123   function = handler->function;
00124   user_data = handler->user_data;
00125   _DBUS_UNLOCK (message_handler);
00126   
00127   /* This function doesn't ref handler/connection/message
00128    * since that's done in dbus_connection_dispatch().
00129    */
00130   if (function != NULL)
00131     return (* function) (handler, connection, message, user_data);
00132   else
00133     return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
00134 }
00135 
00167 DBusMessageHandler*
00168 dbus_message_handler_new (DBusHandleMessageFunction function,
00169                           void                     *user_data,
00170                           DBusFreeFunction          free_user_data)
00171 {
00172   DBusMessageHandler *handler;
00173 
00174   handler = dbus_new (DBusMessageHandler, 1);
00175 
00176   if (handler == NULL)
00177     return NULL;
00178   
00179   handler->refcount.value = 1;
00180   handler->function = function;
00181   handler->user_data = user_data;
00182   handler->free_user_data = free_user_data;
00183   handler->connections = NULL;
00184 
00185   return handler;
00186 }
00187 
00193 void
00194 dbus_message_handler_ref (DBusMessageHandler *handler)
00195 {
00196   _dbus_return_if_fail (handler != NULL);
00197 
00198   _dbus_atomic_inc (&handler->refcount);
00199 }
00200 
00207 void
00208 dbus_message_handler_unref (DBusMessageHandler *handler)
00209 {
00210   dbus_bool_t last_unref;
00211 
00212   _dbus_return_if_fail (handler != NULL);
00213 
00214   last_unref = (_dbus_atomic_dec (&handler->refcount) == 1);
00215   
00216   if (last_unref)
00217     {
00218       DBusList *link;
00219       
00220       if (handler->free_user_data)
00221         (* handler->free_user_data) (handler->user_data);
00222        
00223       link = _dbus_list_get_first_link (&handler->connections);
00224        while (link != NULL)
00225          {
00226            DBusConnection *connection = link->data;
00227 
00228            _dbus_connection_handler_destroyed_locked (connection, handler);
00229            
00230            link = _dbus_list_get_next_link (&handler->connections, link);
00231          }
00232 
00233        _dbus_list_clear (&handler->connections);
00234 
00235        dbus_free (handler);
00236     }
00237 }
00238 
00246 void*
00247 dbus_message_handler_get_data (DBusMessageHandler *handler)
00248 {
00249   void* user_data;
00250 
00251   _dbus_return_val_if_fail (handler != NULL, NULL);
00252   
00253   _DBUS_LOCK (message_handler);
00254   user_data = handler->user_data;
00255   _DBUS_UNLOCK (message_handler);
00256   return user_data;
00257 }
00258 
00268 void
00269 dbus_message_handler_set_data (DBusMessageHandler *handler,
00270                                void               *user_data,
00271                                DBusFreeFunction    free_user_data)
00272 {
00273   DBusFreeFunction old_free_func;
00274   void *old_user_data;
00275 
00276   _dbus_return_if_fail (handler != NULL);
00277   
00278   _DBUS_LOCK (message_handler);
00279   old_free_func = handler->free_user_data;
00280   old_user_data = handler->user_data;
00281 
00282   handler->user_data = user_data;
00283   handler->free_user_data = free_user_data;
00284   _DBUS_UNLOCK (message_handler);
00285 
00286   if (old_free_func)
00287     (* old_free_func) (old_user_data);
00288 
00289 }
00290 
00298 void
00299 dbus_message_handler_set_function (DBusMessageHandler        *handler,
00300                                    DBusHandleMessageFunction  function)
00301 {
00302   _dbus_return_if_fail (handler != NULL);
00303   
00304   _DBUS_LOCK (message_handler);
00305   handler->function = function;
00306   _DBUS_UNLOCK (message_handler);
00307 }
00308 
00311 #ifdef DBUS_BUILD_TESTS
00312 static DBusHandlerResult
00313 test_handler (DBusMessageHandler *handler,
00314               DBusConnection     *connection,
00315               DBusMessage        *message,
00316               void               *user_data)
00317 {
00318   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
00319 }
00320 
00321 static void
00322 free_test_data (void *data)
00323 {
00324   /* does nothing */
00325 }
00326 
00333 dbus_bool_t
00334 _dbus_message_handler_test (const char *test_data_dir)
00335 {
00336   DBusMessageHandler *handler;
00337 
00338 #define TEST_DATA ((void*) 0xcafebabe)
00339   
00340   handler = dbus_message_handler_new (test_handler,
00341                                       TEST_DATA,
00342                                       free_test_data);
00343 
00344   _dbus_assert (handler != NULL);
00345   _dbus_assert (handler->function == test_handler);
00346 
00347   if (dbus_message_handler_get_data (handler) != TEST_DATA)
00348     _dbus_assert_not_reached ("got wrong data");
00349 
00350   dbus_message_handler_set_data (handler, NULL, NULL);
00351   if (dbus_message_handler_get_data (handler) != NULL)
00352     _dbus_assert_not_reached ("got wrong data after set");  
00353   
00354   dbus_message_handler_set_function (handler, NULL);
00355   _dbus_assert (handler->function == NULL);
00356 
00357   dbus_message_handler_ref (handler);
00358   dbus_message_handler_unref (handler);
00359   dbus_message_handler_unref (handler);
00360   
00361   return TRUE;
00362 }
00363 #endif /* DBUS_BUILD_TESTS */

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