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 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-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 
00194 DBusMessageHandler *
00195 dbus_message_handler_ref (DBusMessageHandler *handler)
00196 {
00197   _dbus_return_if_fail (handler != NULL);
00198 
00199   _dbus_atomic_inc (&handler->refcount);
00200 
00201   return handler;
00202 }
00203 
00210 void
00211 dbus_message_handler_unref (DBusMessageHandler *handler)
00212 {
00213   dbus_bool_t last_unref;
00214 
00215   _dbus_return_if_fail (handler != NULL);
00216 
00217   last_unref = (_dbus_atomic_dec (&handler->refcount) == 1);
00218   
00219   if (last_unref)
00220     {
00221       DBusList *link;
00222       
00223       if (handler->free_user_data)
00224         (* handler->free_user_data) (handler->user_data);
00225        
00226       link = _dbus_list_get_first_link (&handler->connections);
00227        while (link != NULL)
00228          {
00229            DBusConnection *connection = link->data;
00230 
00231            _dbus_connection_handler_destroyed_locked (connection, handler);
00232            
00233            link = _dbus_list_get_next_link (&handler->connections, link);
00234          }
00235 
00236        _dbus_list_clear (&handler->connections);
00237 
00238        dbus_free (handler);
00239     }
00240 }
00241 
00249 void*
00250 dbus_message_handler_get_data (DBusMessageHandler *handler)
00251 {
00252   void* user_data;
00253 
00254   _dbus_return_val_if_fail (handler != NULL, NULL);
00255   
00256   _DBUS_LOCK (message_handler);
00257   user_data = handler->user_data;
00258   _DBUS_UNLOCK (message_handler);
00259   return user_data;
00260 }
00261 
00271 void
00272 dbus_message_handler_set_data (DBusMessageHandler *handler,
00273                                void               *user_data,
00274                                DBusFreeFunction    free_user_data)
00275 {
00276   DBusFreeFunction old_free_func;
00277   void *old_user_data;
00278 
00279   _dbus_return_if_fail (handler != NULL);
00280   
00281   _DBUS_LOCK (message_handler);
00282   old_free_func = handler->free_user_data;
00283   old_user_data = handler->user_data;
00284 
00285   handler->user_data = user_data;
00286   handler->free_user_data = free_user_data;
00287   _DBUS_UNLOCK (message_handler);
00288 
00289   if (old_free_func)
00290     (* old_free_func) (old_user_data);
00291 
00292 }
00293 
00301 void
00302 dbus_message_handler_set_function (DBusMessageHandler        *handler,
00303                                    DBusHandleMessageFunction  function)
00304 {
00305   _dbus_return_if_fail (handler != NULL);
00306   
00307   _DBUS_LOCK (message_handler);
00308   handler->function = function;
00309   _DBUS_UNLOCK (message_handler);
00310 }
00311 
00314 #ifdef DBUS_BUILD_TESTS
00315 static DBusHandlerResult
00316 test_handler (DBusMessageHandler *handler,
00317               DBusConnection     *connection,
00318               DBusMessage        *message,
00319               void               *user_data)
00320 {
00321   return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
00322 }
00323 
00324 static void
00325 free_test_data (void *data)
00326 {
00327   /* does nothing */
00328 }
00329 
00336 dbus_bool_t
00337 _dbus_message_handler_test (const char *test_data_dir)
00338 {
00339   DBusMessageHandler *handler;
00340 
00341 #define TEST_DATA ((void*) 0xcafebabe)
00342   
00343   handler = dbus_message_handler_new (test_handler,
00344                                       TEST_DATA,
00345                                       free_test_data);
00346 
00347   _dbus_assert (handler != NULL);
00348   _dbus_assert (handler->function == test_handler);
00349 
00350   if (dbus_message_handler_get_data (handler) != TEST_DATA)
00351     _dbus_assert_not_reached ("got wrong data");
00352 
00353   dbus_message_handler_set_data (handler, NULL, NULL);
00354   if (dbus_message_handler_get_data (handler) != NULL)
00355     _dbus_assert_not_reached ("got wrong data after set");  
00356   
00357   dbus_message_handler_set_function (handler, NULL);
00358   _dbus_assert (handler->function == NULL);
00359 
00360   dbus_message_handler_ref (handler);
00361   dbus_message_handler_unref (handler);
00362   dbus_message_handler_unref (handler);
00363   
00364   return TRUE;
00365 }
00366 #endif /* DBUS_BUILD_TESTS */

Generated on Wed Jun 2 06:01:33 2004 for D-BUS by doxygen1.2.15