Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-connection.c DBusConnection 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 <config.h>
00025 #include "dbus-connection.h"
00026 #include "dbus-list.h"
00027 #include "dbus-timeout.h"
00028 #include "dbus-transport.h"
00029 #include "dbus-watch.h"
00030 #include "dbus-connection-internal.h"
00031 #include "dbus-list.h"
00032 #include "dbus-hash.h"
00033 #include "dbus-message-internal.h"
00034 #include "dbus-threads.h"
00035 #include "dbus-protocol.h"
00036 #include "dbus-dataslot.h"
00037 #include "dbus-string.h"
00038 #include "dbus-pending-call.h"
00039 #include "dbus-object-tree.h"
00040 
00041 #if 0
00042 #define CONNECTION_LOCK(connection)   do {                      \
00043     _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME);        \
00044     dbus_mutex_lock ((connection)->mutex);                      \
00045   } while (0)
00046 #define CONNECTION_UNLOCK(connection) do {                      \
00047     _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);      \
00048     dbus_mutex_unlock ((connection)->mutex);                    \
00049   } while (0)
00050 #else
00051 #define CONNECTION_LOCK(connection)    dbus_mutex_lock ((connection)->mutex)
00052 #define CONNECTION_UNLOCK(connection)  dbus_mutex_unlock ((connection)->mutex)
00053 #endif
00054 
00132 typedef struct DBusMessageFilter DBusMessageFilter;
00133 
00137 struct DBusMessageFilter
00138 {
00139   DBusAtomic refcount; 
00140   DBusHandleMessageFunction function; 
00141   void *user_data; 
00142   DBusFreeFunction free_user_data_function; 
00143 };
00144 
00145 
00149 struct DBusPreallocatedSend
00150 {
00151   DBusConnection *connection; 
00152   DBusList *queue_link;       
00153   DBusList *counter_link;     
00154 };
00155 
00156 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00157 
00161 struct DBusConnection
00162 {
00163   DBusAtomic refcount; 
00165   DBusMutex *mutex; 
00167   dbus_bool_t dispatch_acquired; 
00168   DBusCondVar *dispatch_cond;    
00170   dbus_bool_t io_path_acquired;  
00171   DBusCondVar *io_path_cond;     
00173   DBusList *outgoing_messages; 
00174   DBusList *incoming_messages; 
00176   DBusMessage *message_borrowed; 
00177   DBusCondVar *message_returned_cond; 
00179   int n_outgoing;              
00180   int n_incoming;              
00182   DBusCounter *outgoing_counter; 
00184   DBusTransport *transport;    
00185   DBusWatchList *watches;      
00186   DBusTimeoutList *timeouts;   
00188   DBusList *filter_list;        
00190   DBusDataSlotList slot_list;   
00192   DBusHashTable *pending_replies;  
00194   dbus_uint32_t client_serial;       
00195   DBusList *disconnect_message_link; 
00197   DBusWakeupMainFunction wakeup_main_function; 
00198   void *wakeup_main_data; 
00199   DBusFreeFunction free_wakeup_main_data; 
00201   DBusDispatchStatusFunction dispatch_status_function; 
00202   void *dispatch_status_data; 
00203   DBusFreeFunction free_dispatch_status_data; 
00205   DBusDispatchStatus last_dispatch_status; 
00207   DBusList *link_cache; 
00210   DBusObjectTree *objects; 
00212   unsigned int exit_on_disconnect : 1; 
00213 };
00214 
00215 static void               _dbus_connection_remove_timeout_locked             (DBusConnection     *connection,
00216                                                                               DBusTimeout        *timeout);
00217 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00218 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00219                                                                               DBusDispatchStatus  new_status);
00220 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00221 
00222 static void
00223 _dbus_message_filter_ref (DBusMessageFilter *filter)
00224 {
00225   _dbus_assert (filter->refcount.value > 0);
00226   _dbus_atomic_inc (&filter->refcount);
00227 }
00228 
00229 static void
00230 _dbus_message_filter_unref (DBusMessageFilter *filter)
00231 {
00232   _dbus_assert (filter->refcount.value > 0);
00233 
00234   if (_dbus_atomic_dec (&filter->refcount) == 1)
00235     {
00236       if (filter->free_user_data_function)
00237         (* filter->free_user_data_function) (filter->user_data);
00238       
00239       dbus_free (filter);
00240     }
00241 }
00242 
00248 void
00249 _dbus_connection_lock (DBusConnection *connection)
00250 {
00251   CONNECTION_LOCK (connection);
00252 }
00253 
00259 void
00260 _dbus_connection_unlock (DBusConnection *connection)
00261 {
00262   CONNECTION_UNLOCK (connection);
00263 }
00264 
00272 static void
00273 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00274 {
00275   if (connection->wakeup_main_function)
00276     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00277 }
00278 
00279 #ifdef DBUS_BUILD_TESTS
00280 /* For now this function isn't used */
00290 dbus_bool_t
00291 _dbus_connection_queue_received_message (DBusConnection *connection,
00292                                          DBusMessage    *message)
00293 {
00294   DBusList *link;
00295 
00296   link = _dbus_list_alloc_link (message);
00297   if (link == NULL)
00298     return FALSE;
00299 
00300   dbus_message_ref (message);
00301   _dbus_connection_queue_received_message_link (connection, link);
00302 
00303   return TRUE;
00304 }
00305 #endif
00306 
00315 void
00316 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00317                                               DBusList        *link)
00318 {
00319   DBusPendingCall *pending;
00320   dbus_int32_t reply_serial;
00321   DBusMessage *message;
00322   
00323   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00324   
00325   _dbus_list_append_link (&connection->incoming_messages,
00326                           link);
00327   message = link->data;
00328 
00329   /* If this is a reply we're waiting on, remove timeout for it */
00330   reply_serial = dbus_message_get_reply_serial (message);
00331   if (reply_serial != -1)
00332     {
00333       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00334                                              reply_serial);
00335       if (pending != NULL)
00336         {
00337           if (pending->timeout_added)
00338             _dbus_connection_remove_timeout_locked (connection,
00339                                                     pending->timeout);
00340 
00341           pending->timeout_added = FALSE;
00342         }
00343     }
00344   
00345   connection->n_incoming += 1;
00346 
00347   _dbus_connection_wakeup_mainloop (connection);
00348   
00349   _dbus_verbose ("Message %p (%d %s '%s') added to incoming queue %p, %d incoming\n",
00350                  message,
00351                  dbus_message_get_type (message),
00352                  dbus_message_get_interface (message) ?
00353                  dbus_message_get_interface (message) :
00354                  "no interface",
00355                  dbus_message_get_signature (message),
00356                  connection,
00357                  connection->n_incoming);
00358 }
00359 
00370 static void
00371 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00372                                                  DBusList *link)
00373 {
00374   _dbus_list_append_link (&connection->incoming_messages, link);
00375 
00376   connection->n_incoming += 1;
00377 
00378   _dbus_connection_wakeup_mainloop (connection);
00379   
00380   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00381                  link->data, connection, connection->n_incoming);
00382 }
00383 
00384 
00391 dbus_bool_t
00392 _dbus_connection_have_messages_to_send (DBusConnection *connection)
00393 {
00394   return connection->outgoing_messages != NULL;
00395 }
00396 
00404 DBusMessage*
00405 _dbus_connection_get_message_to_send (DBusConnection *connection)
00406 {
00407   return _dbus_list_get_last (&connection->outgoing_messages);
00408 }
00409 
00418 void
00419 _dbus_connection_message_sent (DBusConnection *connection,
00420                                DBusMessage    *message)
00421 {
00422   DBusList *link;
00423   
00424   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00425   
00426   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00427   _dbus_assert (link != NULL);
00428   _dbus_assert (link->data == message);
00429 
00430   /* Save this link in the link cache */
00431   _dbus_list_unlink (&connection->outgoing_messages,
00432                      link);
00433   _dbus_list_prepend_link (&connection->link_cache, link);
00434   
00435   connection->n_outgoing -= 1;
00436 
00437   _dbus_verbose ("Message %p (%d %s '%s') removed from outgoing queue %p, %d left to send\n",
00438                  message,
00439                  dbus_message_get_type (message),
00440                  dbus_message_get_interface (message) ?
00441                  dbus_message_get_interface (message) :
00442                  "no interface",
00443                  dbus_message_get_signature (message),
00444                  connection, connection->n_outgoing);
00445 
00446   /* Save this link in the link cache also */
00447   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00448                                      &link);
00449   _dbus_list_prepend_link (&connection->link_cache, link);
00450   
00451   dbus_message_unref (message);
00452   
00453   if (connection->n_outgoing == 0)
00454     _dbus_transport_messages_pending (connection->transport,
00455                                       connection->n_outgoing);  
00456 }
00457 
00468 dbus_bool_t
00469 _dbus_connection_add_watch (DBusConnection *connection,
00470                             DBusWatch      *watch)
00471 {
00472   if (connection->watches) /* null during finalize */
00473     return _dbus_watch_list_add_watch (connection->watches,
00474                                        watch);
00475   else
00476     return FALSE;
00477 }
00478 
00487 void
00488 _dbus_connection_remove_watch (DBusConnection *connection,
00489                                DBusWatch      *watch)
00490 {
00491   if (connection->watches) /* null during finalize */
00492     _dbus_watch_list_remove_watch (connection->watches,
00493                                    watch);
00494 }
00495 
00505 void
00506 _dbus_connection_toggle_watch (DBusConnection *connection,
00507                                DBusWatch      *watch,
00508                                dbus_bool_t     enabled)
00509 {
00510   if (connection->watches) /* null during finalize */
00511     _dbus_watch_list_toggle_watch (connection->watches,
00512                                    watch, enabled);
00513 }
00514 
00526 dbus_bool_t
00527 _dbus_connection_add_timeout (DBusConnection *connection,
00528                               DBusTimeout    *timeout)
00529 {
00530  if (connection->timeouts) /* null during finalize */
00531     return _dbus_timeout_list_add_timeout (connection->timeouts,
00532                                            timeout);
00533   else
00534     return FALSE;  
00535 }
00536 
00545 void
00546 _dbus_connection_remove_timeout (DBusConnection *connection,
00547                                  DBusTimeout    *timeout)
00548 {
00549   if (connection->timeouts) /* null during finalize */
00550     _dbus_timeout_list_remove_timeout (connection->timeouts,
00551                                        timeout);
00552 }
00553 
00554 static void
00555 _dbus_connection_remove_timeout_locked (DBusConnection *connection,
00556                                         DBusTimeout    *timeout)
00557 {
00558   CONNECTION_LOCK (connection);
00559   _dbus_connection_remove_timeout (connection, timeout);
00560   CONNECTION_UNLOCK (connection);
00561 }
00562 
00572 void
00573 _dbus_connection_toggle_timeout (DBusConnection *connection,
00574                                  DBusTimeout      *timeout,
00575                                  dbus_bool_t     enabled)
00576 {
00577   if (connection->timeouts) /* null during finalize */
00578     _dbus_timeout_list_toggle_timeout (connection->timeouts,
00579                                        timeout, enabled);
00580 }
00581 
00582 static dbus_bool_t
00583 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00584                                                DBusPendingCall *pending)
00585 {
00586   _dbus_assert (pending->reply_serial != 0);
00587 
00588   if (!_dbus_connection_add_timeout (connection, pending->timeout))
00589     return FALSE;
00590   
00591   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00592                                     pending->reply_serial,
00593                                     pending))
00594     {
00595       _dbus_connection_remove_timeout (connection, pending->timeout);
00596       return FALSE;
00597     }
00598   
00599   pending->timeout_added = TRUE;
00600   pending->connection = connection;
00601 
00602   dbus_pending_call_ref (pending);
00603   
00604   return TRUE;
00605 }
00606 
00607 static void
00608 free_pending_call_on_hash_removal (void *data)
00609 {
00610   DBusPendingCall *pending;
00611   
00612   if (data == NULL)
00613     return;
00614 
00615   pending = data;
00616 
00617   if (pending->connection)
00618     {
00619       if (pending->timeout_added)
00620         {
00621           _dbus_connection_remove_timeout (pending->connection,
00622                                            pending->timeout);
00623           pending->timeout_added = FALSE;
00624         }
00625 
00626       pending->connection = NULL;
00627       
00628       dbus_pending_call_unref (pending);
00629     }
00630 }
00631 
00632 static void
00633 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00634                                                  DBusPendingCall *pending)
00635 {
00636   /* The idea here is to avoid finalizing the pending call
00637    * with the lock held, since there's a destroy notifier
00638    * in pending call that goes out to application code.
00639    */
00640   dbus_pending_call_ref (pending);
00641   _dbus_hash_table_remove_int (connection->pending_replies,
00642                                pending->reply_serial);
00643   CONNECTION_UNLOCK (connection);
00644   dbus_pending_call_unref (pending);
00645 }
00646 
00655 void
00656 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00657                                       DBusPendingCall *pending)
00658 {
00659   CONNECTION_LOCK (connection);
00660   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00661 }
00662 
00671 void
00672 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00673                                         DBusMessage     *message)
00674 {
00675   if (message == NULL)
00676     {
00677       message = pending->timeout_link->data;
00678       _dbus_list_clear (&pending->timeout_link);
00679     }
00680   else
00681     dbus_message_ref (message);
00682 
00683   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
00684                  message,
00685                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00686                  "method return" :
00687                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00688                  "error" : "other type",
00689                  pending->reply_serial);
00690   
00691   _dbus_assert (pending->reply == NULL);
00692   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00693   pending->reply = message;
00694   
00695   dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
00696   _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00697   
00698   /* Must be called unlocked since it invokes app callback */
00699   _dbus_pending_call_notify (pending);
00700   dbus_pending_call_unref (pending);
00701 }
00702 
00712 static dbus_bool_t
00713 _dbus_connection_acquire_io_path (DBusConnection *connection,
00714                                   int timeout_milliseconds)
00715 {
00716   dbus_bool_t res = TRUE;
00717 
00718   if (connection->io_path_acquired)
00719     {
00720       if (timeout_milliseconds != -1) 
00721         res = dbus_condvar_wait_timeout (connection->io_path_cond,
00722                                          connection->mutex,
00723                                          timeout_milliseconds);
00724       else
00725         dbus_condvar_wait (connection->io_path_cond, connection->mutex);
00726     }
00727   
00728   if (res)
00729     {
00730       _dbus_assert (!connection->io_path_acquired);
00731 
00732       connection->io_path_acquired = TRUE;
00733     }
00734   
00735   return res;
00736 }
00737 
00745 static void
00746 _dbus_connection_release_io_path (DBusConnection *connection)
00747 {
00748   _dbus_assert (connection->io_path_acquired);
00749 
00750   connection->io_path_acquired = FALSE;
00751   dbus_condvar_wake_one (connection->io_path_cond);
00752 }
00753 
00754 
00781 void
00782 _dbus_connection_do_iteration (DBusConnection *connection,
00783                                unsigned int    flags,
00784                                int             timeout_milliseconds)
00785 {
00786   if (connection->n_outgoing == 0)
00787     flags &= ~DBUS_ITERATION_DO_WRITING;
00788 
00789   if (_dbus_connection_acquire_io_path (connection,
00790                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
00791     {
00792       _dbus_transport_do_iteration (connection->transport,
00793                                     flags, timeout_milliseconds);
00794       _dbus_connection_release_io_path (connection);
00795     }
00796 }
00797 
00807 DBusConnection*
00808 _dbus_connection_new_for_transport (DBusTransport *transport)
00809 {
00810   DBusConnection *connection;
00811   DBusWatchList *watch_list;
00812   DBusTimeoutList *timeout_list;
00813   DBusHashTable *pending_replies;
00814   DBusMutex *mutex;
00815   DBusCondVar *message_returned_cond;
00816   DBusCondVar *dispatch_cond;
00817   DBusCondVar *io_path_cond;
00818   DBusList *disconnect_link;
00819   DBusMessage *disconnect_message;
00820   DBusCounter *outgoing_counter;
00821   DBusObjectTree *objects;
00822   
00823   watch_list = NULL;
00824   connection = NULL;
00825   pending_replies = NULL;
00826   timeout_list = NULL;
00827   mutex = NULL;
00828   message_returned_cond = NULL;
00829   dispatch_cond = NULL;
00830   io_path_cond = NULL;
00831   disconnect_link = NULL;
00832   disconnect_message = NULL;
00833   outgoing_counter = NULL;
00834   objects = NULL;
00835   
00836   watch_list = _dbus_watch_list_new ();
00837   if (watch_list == NULL)
00838     goto error;
00839 
00840   timeout_list = _dbus_timeout_list_new ();
00841   if (timeout_list == NULL)
00842     goto error;  
00843 
00844   pending_replies =
00845     _dbus_hash_table_new (DBUS_HASH_INT,
00846                           NULL,
00847                           (DBusFreeFunction)free_pending_call_on_hash_removal);
00848   if (pending_replies == NULL)
00849     goto error;
00850   
00851   connection = dbus_new0 (DBusConnection, 1);
00852   if (connection == NULL)
00853     goto error;
00854 
00855   mutex = dbus_mutex_new ();
00856   if (mutex == NULL)
00857     goto error;
00858   
00859   message_returned_cond = dbus_condvar_new ();
00860   if (message_returned_cond == NULL)
00861     goto error;
00862   
00863   dispatch_cond = dbus_condvar_new ();
00864   if (dispatch_cond == NULL)
00865     goto error;
00866   
00867   io_path_cond = dbus_condvar_new ();
00868   if (io_path_cond == NULL)
00869     goto error;
00870 
00871   disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL,
00872                                                 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
00873                                                 "Disconnected");
00874   
00875   if (disconnect_message == NULL)
00876     goto error;
00877 
00878   disconnect_link = _dbus_list_alloc_link (disconnect_message);
00879   if (disconnect_link == NULL)
00880     goto error;
00881 
00882   outgoing_counter = _dbus_counter_new ();
00883   if (outgoing_counter == NULL)
00884     goto error;
00885 
00886   objects = _dbus_object_tree_new (connection);
00887   if (objects == NULL)
00888     goto error;
00889   
00890   if (_dbus_modify_sigpipe)
00891     _dbus_disable_sigpipe ();
00892   
00893   connection->refcount.value = 1;
00894   connection->mutex = mutex;
00895   connection->dispatch_cond = dispatch_cond;
00896   connection->io_path_cond = io_path_cond;
00897   connection->message_returned_cond = message_returned_cond;
00898   connection->transport = transport;
00899   connection->watches = watch_list;
00900   connection->timeouts = timeout_list;
00901   connection->pending_replies = pending_replies;
00902   connection->outgoing_counter = outgoing_counter;
00903   connection->filter_list = NULL;
00904   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
00905   connection->objects = objects;
00906   connection->exit_on_disconnect = FALSE;
00907   
00908   _dbus_data_slot_list_init (&connection->slot_list);
00909 
00910   connection->client_serial = 1;
00911 
00912   connection->disconnect_message_link = disconnect_link;
00913   
00914   if (!_dbus_transport_set_connection (transport, connection))
00915     goto error;
00916 
00917   _dbus_transport_ref (transport);  
00918   
00919   return connection;
00920   
00921  error:
00922   if (disconnect_message != NULL)
00923     dbus_message_unref (disconnect_message);
00924   
00925   if (disconnect_link != NULL)
00926     _dbus_list_free_link (disconnect_link);
00927   
00928   if (io_path_cond != NULL)
00929     dbus_condvar_free (io_path_cond);
00930   
00931   if (dispatch_cond != NULL)
00932     dbus_condvar_free (dispatch_cond);
00933   
00934   if (message_returned_cond != NULL)
00935     dbus_condvar_free (message_returned_cond);
00936   
00937   if (mutex != NULL)
00938     dbus_mutex_free (mutex);
00939 
00940   if (connection != NULL)
00941     dbus_free (connection);
00942 
00943   if (pending_replies)
00944     _dbus_hash_table_unref (pending_replies);
00945   
00946   if (watch_list)
00947     _dbus_watch_list_free (watch_list);
00948 
00949   if (timeout_list)
00950     _dbus_timeout_list_free (timeout_list);
00951 
00952   if (outgoing_counter)
00953     _dbus_counter_unref (outgoing_counter);
00954 
00955   if (objects)
00956     _dbus_object_tree_unref (objects);
00957   
00958   return NULL;
00959 }
00960 
00967 void
00968 _dbus_connection_ref_unlocked (DBusConnection *connection)
00969 {
00970 #ifdef DBUS_HAVE_ATOMIC_INT
00971   _dbus_atomic_inc (&connection->refcount);
00972 #else
00973   _dbus_assert (connection->refcount.value > 0);
00974   connection->refcount.value += 1;
00975 #endif
00976 }
00977 
00984 void
00985 _dbus_connection_unref_unlocked (DBusConnection *connection)
00986 {
00987   dbus_bool_t last_unref;
00988 
00989   _dbus_return_if_fail (connection != NULL);
00990 
00991   /* The connection lock is better than the global
00992    * lock in the atomic increment fallback
00993    */
00994   
00995 #ifdef DBUS_HAVE_ATOMIC_INT
00996   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
00997 #else  
00998   _dbus_assert (connection->refcount.value > 0);
00999 
01000   connection->refcount.value -= 1;
01001   last_unref = (connection->refcount.value == 0);
01002 #if 0
01003   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01004 #endif
01005 #endif
01006   
01007   if (last_unref)
01008     _dbus_connection_last_unref (connection);
01009 }
01010 
01011 static dbus_uint32_t
01012 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01013 {
01014   int serial;
01015 
01016   serial = connection->client_serial++;
01017 
01018   if (connection->client_serial < 0)
01019     connection->client_serial = 1;
01020   
01021   return serial;
01022 }
01023 
01037 dbus_bool_t
01038 _dbus_connection_handle_watch (DBusWatch                   *watch,
01039                                unsigned int                 condition,
01040                                void                        *data)
01041 {
01042   DBusConnection *connection;
01043   dbus_bool_t retval;
01044   DBusDispatchStatus status;
01045 
01046   connection = data;
01047   
01048   CONNECTION_LOCK (connection);
01049   _dbus_connection_acquire_io_path (connection, -1);
01050   retval = _dbus_transport_handle_watch (connection->transport,
01051                                          watch, condition);
01052   _dbus_connection_release_io_path (connection);
01053 
01054   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01055 
01056   /* this calls out to user code */
01057   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01058   
01059   return retval;
01060 }
01061 
01086 DBusConnection*
01087 dbus_connection_open (const char     *address,
01088                       DBusError      *error)
01089 {
01090   DBusConnection *connection;
01091   DBusTransport *transport;
01092 
01093   _dbus_return_val_if_fail (address != NULL, NULL);
01094   _dbus_return_val_if_error_is_set (error, NULL);
01095   
01096   transport = _dbus_transport_open (address, error);
01097   if (transport == NULL)
01098     {
01099       _DBUS_ASSERT_ERROR_IS_SET (error);
01100       return NULL;
01101     }
01102   
01103   connection = _dbus_connection_new_for_transport (transport);
01104 
01105   _dbus_transport_unref (transport);
01106   
01107   if (connection == NULL)
01108     {
01109       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01110       return NULL;
01111     }
01112   
01113   return connection;
01114 }
01115 
01121 void
01122 dbus_connection_ref (DBusConnection *connection)
01123 {
01124   _dbus_return_if_fail (connection != NULL);
01125 
01126   /* The connection lock is better than the global
01127    * lock in the atomic increment fallback
01128    */
01129   
01130 #ifdef DBUS_HAVE_ATOMIC_INT
01131   _dbus_atomic_inc (&connection->refcount);
01132 #else
01133   CONNECTION_LOCK (connection);
01134   _dbus_assert (connection->refcount.value > 0);
01135 
01136   connection->refcount.value += 1;
01137   CONNECTION_UNLOCK (connection);
01138 #endif
01139 }
01140 
01141 static void
01142 free_outgoing_message (void *element,
01143                        void *data)
01144 {
01145   DBusMessage *message = element;
01146   DBusConnection *connection = data;
01147 
01148   _dbus_message_remove_size_counter (message,
01149                                      connection->outgoing_counter,
01150                                      NULL);
01151   dbus_message_unref (message);
01152 }
01153 
01154 /* This is run without the mutex held, but after the last reference
01155  * to the connection has been dropped we should have no thread-related
01156  * problems
01157  */
01158 static void
01159 _dbus_connection_last_unref (DBusConnection *connection)
01160 {
01161   DBusList *link;
01162 
01163   _dbus_verbose ("Finalizing connection %p\n", connection);
01164   
01165   _dbus_assert (connection->refcount.value == 0);
01166   
01167   /* You have to disconnect the connection before unref:ing it. Otherwise
01168    * you won't get the disconnected message.
01169    */
01170   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01171 
01172   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01173   _dbus_object_tree_free_all_unlocked (connection->objects);
01174   
01175   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01176   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01177   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01178   
01179   _dbus_watch_list_free (connection->watches);
01180   connection->watches = NULL;
01181   
01182   _dbus_timeout_list_free (connection->timeouts);
01183   connection->timeouts = NULL;
01184 
01185   _dbus_data_slot_list_free (&connection->slot_list);
01186   
01187   link = _dbus_list_get_first_link (&connection->filter_list);
01188   while (link != NULL)
01189     {
01190       DBusMessageFilter *filter = link->data;
01191       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01192 
01193       filter->function = NULL;
01194       _dbus_message_filter_unref (filter); /* calls app callback */
01195       link->data = NULL;
01196       
01197       link = next;
01198     }
01199   _dbus_list_clear (&connection->filter_list);
01200   
01201   /* ---- Done with stuff that invokes application callbacks */
01202 
01203   _dbus_object_tree_unref (connection->objects);  
01204 
01205   _dbus_hash_table_unref (connection->pending_replies);
01206   connection->pending_replies = NULL;
01207   
01208   _dbus_list_clear (&connection->filter_list);
01209   
01210   _dbus_list_foreach (&connection->outgoing_messages,
01211                       free_outgoing_message,
01212                       connection);
01213   _dbus_list_clear (&connection->outgoing_messages);
01214   
01215   _dbus_list_foreach (&connection->incoming_messages,
01216                       (DBusForeachFunction) dbus_message_unref,
01217                       NULL);
01218   _dbus_list_clear (&connection->incoming_messages);
01219 
01220   _dbus_counter_unref (connection->outgoing_counter);
01221   
01222   _dbus_transport_unref (connection->transport);
01223 
01224   if (connection->disconnect_message_link)
01225     {
01226       DBusMessage *message = connection->disconnect_message_link->data;
01227       dbus_message_unref (message);
01228       _dbus_list_free_link (connection->disconnect_message_link);
01229     }
01230 
01231   _dbus_list_clear (&connection->link_cache);
01232   
01233   dbus_condvar_free (connection->dispatch_cond);
01234   dbus_condvar_free (connection->io_path_cond);
01235   dbus_condvar_free (connection->message_returned_cond);  
01236   
01237   dbus_mutex_free (connection->mutex);
01238   
01239   dbus_free (connection);
01240 }
01241 
01253 void
01254 dbus_connection_unref (DBusConnection *connection)
01255 {
01256   dbus_bool_t last_unref;
01257 
01258   _dbus_return_if_fail (connection != NULL);
01259 
01260   /* The connection lock is better than the global
01261    * lock in the atomic increment fallback
01262    */
01263   
01264 #ifdef DBUS_HAVE_ATOMIC_INT
01265   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01266 #else
01267   CONNECTION_LOCK (connection);
01268   
01269   _dbus_assert (connection->refcount.value > 0);
01270 
01271   connection->refcount.value -= 1;
01272   last_unref = (connection->refcount.value == 0);
01273 
01274 #if 0
01275   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01276 #endif
01277   
01278   CONNECTION_UNLOCK (connection);
01279 #endif
01280   
01281   if (last_unref)
01282     _dbus_connection_last_unref (connection);
01283 }
01284 
01298 void
01299 dbus_connection_disconnect (DBusConnection *connection)
01300 {
01301   DBusDispatchStatus status;
01302   
01303   _dbus_return_if_fail (connection != NULL);
01304   
01305   CONNECTION_LOCK (connection);
01306   _dbus_transport_disconnect (connection->transport);
01307   
01308   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01309 
01310   /* this calls out to user code */
01311   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01312 }
01313 
01314 static dbus_bool_t
01315 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01316 {
01317   return _dbus_transport_get_is_connected (connection->transport);
01318 }
01319 
01330 dbus_bool_t
01331 dbus_connection_get_is_connected (DBusConnection *connection)
01332 {
01333   dbus_bool_t res;
01334 
01335   _dbus_return_val_if_fail (connection != NULL, FALSE);
01336   
01337   CONNECTION_LOCK (connection);
01338   res = _dbus_connection_get_is_connected_unlocked (connection);
01339   CONNECTION_UNLOCK (connection);
01340   
01341   return res;
01342 }
01343 
01352 dbus_bool_t
01353 dbus_connection_get_is_authenticated (DBusConnection *connection)
01354 {
01355   dbus_bool_t res;
01356 
01357   _dbus_return_val_if_fail (connection != NULL, FALSE);
01358   
01359   CONNECTION_LOCK (connection);
01360   res = _dbus_transport_get_is_authenticated (connection->transport);
01361   CONNECTION_UNLOCK (connection);
01362   
01363   return res;
01364 }
01365 
01379 void
01380 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
01381                                         dbus_bool_t     exit_on_disconnect)
01382 {
01383   _dbus_return_if_fail (connection != NULL);
01384 
01385   CONNECTION_LOCK (connection);
01386   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
01387   CONNECTION_UNLOCK (connection);
01388 }
01389 
01390 static DBusPreallocatedSend*
01391 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01392 {
01393   DBusPreallocatedSend *preallocated;
01394 
01395   _dbus_return_val_if_fail (connection != NULL, NULL);
01396   
01397   preallocated = dbus_new (DBusPreallocatedSend, 1);
01398   if (preallocated == NULL)
01399     return NULL;
01400 
01401   if (connection->link_cache != NULL)
01402     {
01403       preallocated->queue_link =
01404         _dbus_list_pop_first_link (&connection->link_cache);
01405       preallocated->queue_link->data = NULL;
01406     }
01407   else
01408     {
01409       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01410       if (preallocated->queue_link == NULL)
01411         goto failed_0;
01412     }
01413   
01414   if (connection->link_cache != NULL)
01415     {
01416       preallocated->counter_link =
01417         _dbus_list_pop_first_link (&connection->link_cache);
01418       preallocated->counter_link->data = connection->outgoing_counter;
01419     }
01420   else
01421     {
01422       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01423       if (preallocated->counter_link == NULL)
01424         goto failed_1;
01425     }
01426 
01427   _dbus_counter_ref (preallocated->counter_link->data);
01428 
01429   preallocated->connection = connection;
01430   
01431   return preallocated;
01432   
01433  failed_1:
01434   _dbus_list_free_link (preallocated->queue_link);
01435  failed_0:
01436   dbus_free (preallocated);
01437   
01438   return NULL;
01439 }
01440 
01450 DBusPreallocatedSend*
01451 dbus_connection_preallocate_send (DBusConnection *connection)
01452 {
01453   DBusPreallocatedSend *preallocated;
01454 
01455   _dbus_return_val_if_fail (connection != NULL, NULL);
01456 
01457   CONNECTION_LOCK (connection);
01458   
01459   preallocated =
01460     _dbus_connection_preallocate_send_unlocked (connection);
01461 
01462   CONNECTION_UNLOCK (connection);
01463 
01464   return preallocated;
01465 }
01466 
01476 void
01477 dbus_connection_free_preallocated_send (DBusConnection       *connection,
01478                                         DBusPreallocatedSend *preallocated)
01479 {
01480   _dbus_return_if_fail (connection != NULL);
01481   _dbus_return_if_fail (preallocated != NULL);  
01482   _dbus_return_if_fail (connection == preallocated->connection);
01483 
01484   _dbus_list_free_link (preallocated->queue_link);
01485   _dbus_counter_unref (preallocated->counter_link->data);
01486   _dbus_list_free_link (preallocated->counter_link);
01487   dbus_free (preallocated);
01488 }
01489 
01490 static void
01491 _dbus_connection_send_preallocated_unlocked (DBusConnection       *connection,
01492                                              DBusPreallocatedSend *preallocated,
01493                                              DBusMessage          *message,
01494                                              dbus_uint32_t        *client_serial)
01495 {
01496   dbus_uint32_t serial;
01497 
01498   preallocated->queue_link->data = message;
01499   _dbus_list_prepend_link (&connection->outgoing_messages,
01500                            preallocated->queue_link);
01501 
01502   _dbus_message_add_size_counter_link (message,
01503                                        preallocated->counter_link);
01504 
01505   dbus_free (preallocated);
01506   preallocated = NULL;
01507   
01508   dbus_message_ref (message);
01509   
01510   connection->n_outgoing += 1;
01511 
01512   _dbus_verbose ("Message %p (%d %s '%s') added to outgoing queue %p, %d pending to send\n",
01513                  message,
01514                  dbus_message_get_type (message),
01515                  dbus_message_get_interface (message) ?
01516                  dbus_message_get_interface (message) :
01517                  "no interface",
01518                  dbus_message_get_signature (message),
01519                  connection,
01520                  connection->n_outgoing);
01521 
01522   if (dbus_message_get_serial (message) == 0)
01523     {
01524       serial = _dbus_connection_get_next_client_serial (connection);
01525       _dbus_message_set_serial (message, serial);
01526       if (client_serial)
01527         *client_serial = serial;
01528     }
01529   else
01530     {
01531       if (client_serial)
01532         *client_serial = dbus_message_get_serial (message);
01533     }
01534   
01535   _dbus_message_lock (message);
01536 
01537   if (connection->n_outgoing == 1)
01538     _dbus_transport_messages_pending (connection->transport,
01539                                       connection->n_outgoing);
01540   
01541   _dbus_connection_wakeup_mainloop (connection);
01542 }
01543 
01556 void
01557 dbus_connection_send_preallocated (DBusConnection       *connection,
01558                                    DBusPreallocatedSend *preallocated,
01559                                    DBusMessage          *message,
01560                                    dbus_uint32_t        *client_serial)
01561 {
01562   _dbus_return_if_fail (connection != NULL);
01563   _dbus_return_if_fail (preallocated != NULL);
01564   _dbus_return_if_fail (message != NULL);
01565   _dbus_return_if_fail (preallocated->connection == connection);
01566   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
01567                         (dbus_message_get_interface (message) != NULL &&
01568                          dbus_message_get_member (message) != NULL));
01569   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
01570                         (dbus_message_get_interface (message) != NULL &&
01571                          dbus_message_get_member (message) != NULL));
01572   
01573   CONNECTION_LOCK (connection);
01574   _dbus_connection_send_preallocated_unlocked (connection,
01575                                                preallocated,
01576                                                message, client_serial);
01577   CONNECTION_UNLOCK (connection);  
01578 }
01579 
01580 static dbus_bool_t
01581 _dbus_connection_send_unlocked (DBusConnection *connection,
01582                                 DBusMessage    *message,
01583                                 dbus_uint32_t  *client_serial)
01584 {
01585   DBusPreallocatedSend *preallocated;
01586 
01587   _dbus_assert (connection != NULL);
01588   _dbus_assert (message != NULL);
01589   
01590   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01591   if (preallocated == NULL)
01592     return FALSE;
01593 
01594 
01595   _dbus_connection_send_preallocated_unlocked (connection,
01596                                                preallocated,
01597                                                message,
01598                                                client_serial);
01599   return TRUE;
01600 }
01601 
01620 dbus_bool_t
01621 dbus_connection_send (DBusConnection *connection,
01622                       DBusMessage    *message,
01623                       dbus_uint32_t  *client_serial)
01624 {
01625   _dbus_return_val_if_fail (connection != NULL, FALSE);
01626   _dbus_return_val_if_fail (message != NULL, FALSE);
01627 
01628   CONNECTION_LOCK (connection);
01629 
01630   if (!_dbus_connection_send_unlocked (connection, message, client_serial))
01631     {
01632       CONNECTION_UNLOCK (connection);
01633       return FALSE;
01634     }
01635 
01636   CONNECTION_UNLOCK (connection);
01637   return TRUE;
01638 }
01639 
01640 static dbus_bool_t
01641 reply_handler_timeout (void *data)
01642 {
01643   DBusConnection *connection;
01644   DBusDispatchStatus status;
01645   DBusPendingCall *pending = data;
01646 
01647   connection = pending->connection;
01648   
01649   CONNECTION_LOCK (connection);
01650   if (pending->timeout_link)
01651     {
01652       _dbus_connection_queue_synthesized_message_link (connection,
01653                                                        pending->timeout_link);
01654       pending->timeout_link = NULL;
01655     }
01656 
01657   _dbus_connection_remove_timeout (connection,
01658                                    pending->timeout);
01659   pending->timeout_added = FALSE;
01660 
01661   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01662 
01663   /* Unlocks, and calls out to user code */
01664   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01665   
01666   return TRUE;
01667 }
01668 
01706 dbus_bool_t
01707 dbus_connection_send_with_reply (DBusConnection     *connection,
01708                                  DBusMessage        *message,
01709                                  DBusPendingCall   **pending_return,
01710                                  int                 timeout_milliseconds)
01711 {
01712   DBusPendingCall *pending;
01713   DBusMessage *reply;
01714   DBusList *reply_link;
01715   dbus_int32_t serial = -1;
01716 
01717   _dbus_return_val_if_fail (connection != NULL, FALSE);
01718   _dbus_return_val_if_fail (message != NULL, FALSE);
01719   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01720 
01721   if (pending_return)
01722     *pending_return = NULL;
01723   
01724   pending = _dbus_pending_call_new (connection,
01725                                     timeout_milliseconds,
01726                                     reply_handler_timeout);
01727 
01728   if (pending == NULL)
01729     return FALSE;
01730 
01731   CONNECTION_LOCK (connection);
01732   
01733   /* Assign a serial to the message */
01734   if (dbus_message_get_serial (message) == 0)
01735     {
01736       serial = _dbus_connection_get_next_client_serial (connection);
01737       _dbus_message_set_serial (message, serial);
01738     }
01739 
01740   pending->reply_serial = serial;
01741 
01742   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
01743                                   "No reply within specified time");
01744   if (!reply)
01745     {
01746       CONNECTION_UNLOCK (connection);
01747       dbus_pending_call_unref (pending);
01748       return FALSE;
01749     }
01750 
01751   reply_link = _dbus_list_alloc_link (reply);
01752   if (!reply)
01753     {
01754       CONNECTION_UNLOCK (connection);
01755       dbus_message_unref (reply);
01756       dbus_pending_call_unref (pending);
01757       return FALSE;
01758     }
01759 
01760   pending->timeout_link = reply_link;
01761 
01762   /* Insert the serial in the pending replies hash;
01763    * hash takes a refcount on DBusPendingCall.
01764    * Also, add the timeout.
01765    */
01766   if (!_dbus_connection_attach_pending_call_unlocked (connection,
01767                                                       pending))
01768     {
01769       CONNECTION_UNLOCK (connection);
01770       dbus_pending_call_unref (pending);
01771       return FALSE;
01772     }
01773   
01774   if (!_dbus_connection_send_unlocked (connection, message, NULL))
01775     {
01776       _dbus_connection_detach_pending_call_and_unlock (connection,
01777                                                        pending);
01778       return FALSE;
01779     }
01780 
01781   if (pending_return)
01782     {
01783       dbus_pending_call_ref (pending);
01784       *pending_return = pending;
01785     }
01786 
01787   CONNECTION_UNLOCK (connection);
01788   
01789   return TRUE;
01790 }
01791 
01792 static DBusMessage*
01793 check_for_reply_unlocked (DBusConnection *connection,
01794                           dbus_uint32_t   client_serial)
01795 {
01796   DBusList *link;
01797   
01798   link = _dbus_list_get_first_link (&connection->incoming_messages);
01799 
01800   while (link != NULL)
01801     {
01802       DBusMessage *reply = link->data;
01803 
01804       if (dbus_message_get_reply_serial (reply) == client_serial)
01805         {
01806           _dbus_list_remove_link (&connection->incoming_messages, link);
01807           connection->n_incoming  -= 1;
01808           dbus_message_ref (reply);
01809           return reply;
01810         }
01811       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
01812     }
01813 
01814   return NULL;
01815 }
01816 
01834 DBusMessage*
01835 _dbus_connection_block_for_reply (DBusConnection     *connection,
01836                                   dbus_uint32_t       client_serial,
01837                                   int                 timeout_milliseconds)
01838 {
01839   long start_tv_sec, start_tv_usec;
01840   long end_tv_sec, end_tv_usec;
01841   long tv_sec, tv_usec;
01842   DBusDispatchStatus status;
01843 
01844   _dbus_return_val_if_fail (connection != NULL, NULL);
01845   _dbus_return_val_if_fail (client_serial != 0, NULL);
01846   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01847   
01848   if (timeout_milliseconds == -1)
01849     timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
01850 
01851   /* it would probably seem logical to pass in _DBUS_INT_MAX
01852    * for infinite timeout, but then math below would get
01853    * all overflow-prone, so smack that down.
01854    */
01855   if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
01856     timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
01857   
01858   /* Flush message queue */
01859   dbus_connection_flush (connection);
01860 
01861   CONNECTION_LOCK (connection);
01862 
01863   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
01864   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
01865   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
01866   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
01867   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
01868 
01869   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n",
01870                  timeout_milliseconds,
01871                  client_serial,
01872                  start_tv_sec, start_tv_usec,
01873                  end_tv_sec, end_tv_usec);
01874   
01875   /* Now we wait... */
01876   /* THREAD TODO: This is busted. What if a dispatch() or pop_message
01877    * gets the message before we do?
01878    */
01879   /* always block at least once as we know we don't have the reply yet */
01880   _dbus_connection_do_iteration (connection,
01881                                  DBUS_ITERATION_DO_READING |
01882                                  DBUS_ITERATION_BLOCK,
01883                                  timeout_milliseconds);
01884 
01885  recheck_status:
01886 
01887   /* queue messages and get status */
01888   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01889 
01890   if (status == DBUS_DISPATCH_DATA_REMAINS)
01891     {
01892       DBusMessage *reply;
01893       
01894       reply = check_for_reply_unlocked (connection, client_serial);
01895       if (reply != NULL)
01896         {          
01897           status = _dbus_connection_get_dispatch_status_unlocked (connection);
01898 
01899           _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
01900 
01901           /* Unlocks, and calls out to user code */
01902           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01903           
01904           return reply;
01905         }
01906     }
01907   
01908   _dbus_get_current_time (&tv_sec, &tv_usec);
01909   
01910   if (tv_sec < start_tv_sec)
01911     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
01912   else if (connection->disconnect_message_link == NULL)
01913     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
01914   else if (tv_sec < end_tv_sec ||
01915            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
01916     {
01917       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
01918         (end_tv_usec - tv_usec) / 1000;
01919       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
01920       _dbus_assert (timeout_milliseconds >= 0);
01921       
01922       if (status == DBUS_DISPATCH_NEED_MEMORY)
01923         {
01924           /* Try sleeping a bit, as we aren't sure we need to block for reading,
01925            * we may already have a reply in the buffer and just can't process
01926            * it.
01927            */
01928           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
01929           
01930           if (timeout_milliseconds < 100)
01931             ; /* just busy loop */
01932           else if (timeout_milliseconds <= 1000)
01933             _dbus_sleep_milliseconds (timeout_milliseconds / 3);
01934           else
01935             _dbus_sleep_milliseconds (1000);
01936         }
01937       else
01938         {          
01939           /* block again, we don't have the reply buffered yet. */
01940           _dbus_connection_do_iteration (connection,
01941                                          DBUS_ITERATION_DO_READING |
01942                                          DBUS_ITERATION_BLOCK,
01943                                          timeout_milliseconds);
01944         }
01945 
01946       goto recheck_status;
01947     }
01948 
01949   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
01950                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
01951 
01952   /* unlocks and calls out to user code */
01953   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01954 
01955   return NULL;
01956 }
01957 
01980 DBusMessage *
01981 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
01982                                            DBusMessage        *message,
01983                                            int                 timeout_milliseconds,
01984                                            DBusError          *error)
01985 {
01986   dbus_uint32_t client_serial;
01987   DBusMessage *reply;
01988   
01989   _dbus_return_val_if_fail (connection != NULL, NULL);
01990   _dbus_return_val_if_fail (message != NULL, NULL);
01991   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);  
01992   _dbus_return_val_if_error_is_set (error, NULL);
01993   
01994   if (!dbus_connection_send (connection, message, &client_serial))
01995     {
01996       _DBUS_SET_OOM (error);
01997       return NULL;
01998     }
01999 
02000   reply = _dbus_connection_block_for_reply (connection,
02001                                             client_serial,
02002                                             timeout_milliseconds);
02003   
02004   if (reply == NULL)
02005     {
02006       if (dbus_connection_get_is_connected (connection))
02007         dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
02008       else
02009         dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
02010 
02011       return NULL;
02012     }
02013   else if (dbus_set_error_from_message (error, reply))
02014     {
02015       dbus_message_unref (reply);
02016       return NULL;
02017     }
02018   else
02019     return reply;
02020 }
02021 
02027 void
02028 dbus_connection_flush (DBusConnection *connection)
02029 {
02030   /* We have to specify DBUS_ITERATION_DO_READING here because
02031    * otherwise we could have two apps deadlock if they are both doing
02032    * a flush(), and the kernel buffers fill up. This could change the
02033    * dispatch status.
02034    */
02035   DBusDispatchStatus status;
02036 
02037   _dbus_return_if_fail (connection != NULL);
02038   
02039   CONNECTION_LOCK (connection);
02040   while (connection->n_outgoing > 0 &&
02041          _dbus_connection_get_is_connected_unlocked (connection))
02042     _dbus_connection_do_iteration (connection,
02043                                    DBUS_ITERATION_DO_READING |
02044                                    DBUS_ITERATION_DO_WRITING |
02045                                    DBUS_ITERATION_BLOCK,
02046                                    -1);
02047 
02048   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02049 
02050   /* Unlocks and calls out to user code */
02051   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02052 }
02053 
02054 /* Call with mutex held. Will drop it while waiting and re-acquire
02055  * before returning
02056  */
02057 static void
02058 _dbus_connection_wait_for_borrowed (DBusConnection *connection)
02059 {
02060   _dbus_assert (connection->message_borrowed != NULL);
02061 
02062   while (connection->message_borrowed != NULL)
02063     dbus_condvar_wait (connection->message_returned_cond, connection->mutex);
02064 }
02065 
02080 DBusMessage*
02081 dbus_connection_borrow_message  (DBusConnection *connection)
02082 {
02083   DBusMessage *message;
02084   DBusDispatchStatus status;
02085 
02086   _dbus_return_val_if_fail (connection != NULL, NULL);
02087   /* can't borrow during dispatch */
02088   _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL);
02089   
02090   /* this is called for the side effect that it queues
02091    * up any messages from the transport
02092    */
02093   status = dbus_connection_get_dispatch_status (connection);
02094   if (status != DBUS_DISPATCH_DATA_REMAINS)
02095     return NULL;
02096   
02097   CONNECTION_LOCK (connection);
02098 
02099   if (connection->message_borrowed != NULL)
02100     _dbus_connection_wait_for_borrowed (connection);
02101   
02102   message = _dbus_list_get_first (&connection->incoming_messages);
02103 
02104   if (message) 
02105     connection->message_borrowed = message;
02106   
02107   CONNECTION_UNLOCK (connection);
02108   return message;
02109 }
02110 
02118 void
02119 dbus_connection_return_message (DBusConnection *connection,
02120                                 DBusMessage    *message)
02121 {
02122   _dbus_return_if_fail (connection != NULL);
02123   _dbus_return_if_fail (message != NULL);
02124   /* can't borrow during dispatch */
02125   _dbus_return_if_fail (!connection->dispatch_acquired);
02126   
02127   CONNECTION_LOCK (connection);
02128   
02129   _dbus_assert (message == connection->message_borrowed);
02130   
02131   connection->message_borrowed = NULL;
02132   dbus_condvar_wake_all (connection->message_returned_cond);
02133   
02134   CONNECTION_UNLOCK (connection);
02135 }
02136 
02146 void
02147 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02148                                         DBusMessage    *message)
02149 {
02150   DBusMessage *pop_message;
02151 
02152   _dbus_return_if_fail (connection != NULL);
02153   _dbus_return_if_fail (message != NULL);
02154   /* can't borrow during dispatch */
02155   _dbus_return_if_fail (!connection->dispatch_acquired);
02156   
02157   CONNECTION_LOCK (connection);
02158  
02159   _dbus_assert (message == connection->message_borrowed);
02160 
02161   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
02162   _dbus_assert (message == pop_message);
02163   
02164   connection->n_incoming -= 1;
02165  
02166   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
02167                  message, connection->n_incoming);
02168  
02169   connection->message_borrowed = NULL;
02170   dbus_condvar_wake_all (connection->message_returned_cond);
02171   
02172   CONNECTION_UNLOCK (connection);
02173 }
02174 
02175 /* See dbus_connection_pop_message, but requires the caller to own
02176  * the lock before calling. May drop the lock while running.
02177  */
02178 static DBusList*
02179 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
02180 {
02181   if (connection->message_borrowed != NULL)
02182     _dbus_connection_wait_for_borrowed (connection);
02183   
02184   if (connection->n_incoming > 0)
02185     {
02186       DBusList *link;
02187 
02188       link = _dbus_list_pop_first_link (&connection->incoming_messages);
02189       connection->n_incoming -= 1;
02190 
02191       _dbus_verbose ("Message %p (%d %s '%s') removed from incoming queue %p, %d incoming\n",
02192                      link->data,
02193                      dbus_message_get_type (link->data),
02194                      dbus_message_get_interface (link->data) ?
02195                      dbus_message_get_interface (link->data) :
02196                      "no interface",
02197                      dbus_message_get_signature (link->data),
02198                      connection, connection->n_incoming);
02199 
02200       return link;
02201     }
02202   else
02203     return NULL;
02204 }
02205 
02206 /* See dbus_connection_pop_message, but requires the caller to own
02207  * the lock before calling. May drop the lock while running.
02208  */
02209 static DBusMessage*
02210 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
02211 {
02212   DBusList *link;
02213   
02214   link = _dbus_connection_pop_message_link_unlocked (connection);
02215 
02216   if (link != NULL)
02217     {
02218       DBusMessage *message;
02219       
02220       message = link->data;
02221       
02222       _dbus_list_free_link (link);
02223       
02224       return message;
02225     }
02226   else
02227     return NULL;
02228 }
02229 
02230 static void
02231 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
02232                                                 DBusList       *message_link)
02233 {
02234   _dbus_assert (message_link != NULL);
02235   /* You can't borrow a message while a link is outstanding */
02236   _dbus_assert (connection->message_borrowed == NULL);
02237 
02238   _dbus_list_prepend_link (&connection->incoming_messages,
02239                            message_link);
02240   connection->n_incoming += 1;
02241 
02242   _dbus_verbose ("Message %p (%d %s '%s') put back into queue %p, %d incoming\n",
02243                  message_link->data,
02244                  dbus_message_get_type (message_link->data),
02245                  dbus_message_get_interface (message_link->data) ?
02246                  dbus_message_get_interface (message_link->data) :
02247                  "no interface",
02248                  dbus_message_get_signature (message_link->data),
02249                  connection, connection->n_incoming);
02250 }
02251 
02266 DBusMessage*
02267 dbus_connection_pop_message (DBusConnection *connection)
02268 {
02269   DBusMessage *message;
02270   DBusDispatchStatus status;
02271 
02272   /* this is called for the side effect that it queues
02273    * up any messages from the transport
02274    */
02275   status = dbus_connection_get_dispatch_status (connection);
02276   if (status != DBUS_DISPATCH_DATA_REMAINS)
02277     return NULL;
02278   
02279   CONNECTION_LOCK (connection);
02280 
02281   message = _dbus_connection_pop_message_unlocked (connection);
02282 
02283   _dbus_verbose ("Returning popped message %p\n", message);    
02284   
02285   CONNECTION_UNLOCK (connection);
02286   
02287   return message;
02288 }
02289 
02298 static void
02299 _dbus_connection_acquire_dispatch (DBusConnection *connection)
02300 {
02301   if (connection->dispatch_acquired)
02302     dbus_condvar_wait (connection->dispatch_cond, connection->mutex);
02303   _dbus_assert (!connection->dispatch_acquired);
02304 
02305   connection->dispatch_acquired = TRUE;
02306 }
02307 
02315 static void
02316 _dbus_connection_release_dispatch (DBusConnection *connection)
02317 {
02318   _dbus_assert (connection->dispatch_acquired);
02319 
02320   connection->dispatch_acquired = FALSE;
02321   dbus_condvar_wake_one (connection->dispatch_cond);
02322 }
02323 
02324 static void
02325 _dbus_connection_failed_pop (DBusConnection *connection,
02326                              DBusList       *message_link)
02327 {
02328   _dbus_list_prepend_link (&connection->incoming_messages,
02329                            message_link);
02330   connection->n_incoming += 1;
02331 }
02332 
02333 static DBusDispatchStatus
02334 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
02335 {
02336   if (connection->n_incoming > 0)
02337     return DBUS_DISPATCH_DATA_REMAINS;
02338   else if (!_dbus_transport_queue_messages (connection->transport))
02339     return DBUS_DISPATCH_NEED_MEMORY;
02340   else
02341     {
02342       DBusDispatchStatus status;
02343       
02344       status = _dbus_transport_get_dispatch_status (connection->transport);
02345 
02346       if (status == DBUS_DISPATCH_COMPLETE &&
02347           connection->disconnect_message_link &&
02348           !_dbus_transport_get_is_connected (connection->transport))
02349         {
02350           /* We haven't sent the disconnect message already,
02351            * and all real messages have been queued up.
02352            */
02353           _dbus_connection_queue_synthesized_message_link (connection,
02354                                                            connection->disconnect_message_link);
02355           connection->disconnect_message_link = NULL;
02356         }
02357       
02358       if (status != DBUS_DISPATCH_COMPLETE)
02359         return status;
02360       else if (connection->n_incoming > 0)
02361         return DBUS_DISPATCH_DATA_REMAINS;
02362       else
02363         return DBUS_DISPATCH_COMPLETE;
02364     }
02365 }
02366 
02367 static void
02368 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
02369                                                     DBusDispatchStatus new_status)
02370 {
02371   dbus_bool_t changed;
02372   DBusDispatchStatusFunction function;
02373   void *data;
02374 
02375   /* We have the lock */
02376 
02377   _dbus_connection_ref_unlocked (connection);
02378 
02379   changed = new_status != connection->last_dispatch_status;
02380 
02381   connection->last_dispatch_status = new_status;
02382 
02383   function = connection->dispatch_status_function;
02384   data = connection->dispatch_status_data;
02385 
02386   /* We drop the lock */
02387   CONNECTION_UNLOCK (connection);
02388   
02389   if (changed && function)
02390     {
02391       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
02392                      connection, new_status,
02393                      new_status == DBUS_DISPATCH_COMPLETE ? "complete" :
02394                      new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" :
02395                      new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :
02396                      "???");
02397       (* function) (connection, new_status, data);      
02398     }
02399   
02400   dbus_connection_unref (connection);
02401 }
02402 
02411 DBusDispatchStatus
02412 dbus_connection_get_dispatch_status (DBusConnection *connection)
02413 {
02414   DBusDispatchStatus status;
02415 
02416   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02417   
02418   CONNECTION_LOCK (connection);
02419 
02420   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02421   
02422   CONNECTION_UNLOCK (connection);
02423 
02424   return status;
02425 }
02426 
02454 DBusDispatchStatus
02455 dbus_connection_dispatch (DBusConnection *connection)
02456 {
02457   DBusMessage *message;
02458   DBusList *link, *filter_list_copy, *message_link;
02459   DBusHandlerResult result;
02460   DBusPendingCall *pending;
02461   dbus_int32_t reply_serial;
02462   DBusDispatchStatus status;
02463 
02464   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02465 
02466   CONNECTION_LOCK (connection);
02467   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02468   if (status != DBUS_DISPATCH_DATA_REMAINS)
02469     {
02470       /* unlocks and calls out to user code */
02471       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02472       return status;
02473     }
02474   
02475   /* We need to ref the connection since the callback could potentially
02476    * drop the last ref to it
02477    */
02478   _dbus_connection_ref_unlocked (connection);
02479 
02480   _dbus_connection_acquire_dispatch (connection);
02481   
02482   /* This call may drop the lock during the execution (if waiting for
02483    * borrowed messages to be returned) but the order of message
02484    * dispatch if several threads call dispatch() is still
02485    * protected by the lock, since only one will get the lock, and that
02486    * one will finish the message dispatching
02487    */
02488   message_link = _dbus_connection_pop_message_link_unlocked (connection);
02489   if (message_link == NULL)
02490     {
02491       /* another thread dispatched our stuff */
02492 
02493       _dbus_connection_release_dispatch (connection);
02494 
02495       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02496 
02497       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02498       
02499       dbus_connection_unref (connection);
02500       
02501       return status;
02502     }
02503 
02504   message = message_link->data;
02505   
02506   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02507 
02508   reply_serial = dbus_message_get_reply_serial (message);
02509   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
02510                                          reply_serial);
02511   
02512   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
02513     {
02514       _dbus_connection_release_dispatch (connection);
02515 
02516       _dbus_connection_failed_pop (connection, message_link);
02517 
02518       /* unlocks and calls user code */
02519       _dbus_connection_update_dispatch_status_and_unlock (connection,
02520                                                           DBUS_DISPATCH_NEED_MEMORY);
02521 
02522       dbus_connection_unref (connection);
02523       
02524       return DBUS_DISPATCH_NEED_MEMORY;
02525     }
02526   
02527   _dbus_list_foreach (&filter_list_copy,
02528                       (DBusForeachFunction)_dbus_message_filter_ref,
02529                       NULL);
02530 
02531   /* We're still protected from dispatch() reentrancy here
02532    * since we acquired the dispatcher
02533    */
02534   CONNECTION_UNLOCK (connection);
02535   
02536   link = _dbus_list_get_first_link (&filter_list_copy);
02537   while (link != NULL)
02538     {
02539       DBusMessageFilter *filter = link->data;
02540       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
02541 
02542       _dbus_verbose ("  running filter on message %p\n", message);
02543       result = (* filter->function) (connection, message, filter->user_data);
02544 
02545       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02546         break;
02547 
02548       link = next;
02549     }
02550 
02551   _dbus_list_foreach (&filter_list_copy,
02552                       (DBusForeachFunction)_dbus_message_filter_unref,
02553                       NULL);
02554   _dbus_list_clear (&filter_list_copy);
02555   
02556   CONNECTION_LOCK (connection);
02557 
02558   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02559     goto out;
02560   
02561   /* Did a reply we were waiting on get filtered? */
02562   if (pending && result == DBUS_HANDLER_RESULT_HANDLED)
02563     {
02564       /* Queue the timeout immediately! */
02565       if (pending->timeout_link)
02566         {
02567           _dbus_connection_queue_synthesized_message_link (connection,
02568                                                            pending->timeout_link);
02569           pending->timeout_link = NULL;
02570         }
02571       else
02572         {
02573           /* We already queued the timeout? Then it was filtered! */
02574           _dbus_warn ("The timeout error with reply serial %d was filtered, so the DBusPendingCall will never stop pending.\n", reply_serial);
02575         }
02576     }
02577   
02578   if (result == DBUS_HANDLER_RESULT_HANDLED)
02579     goto out;
02580   
02581   if (pending)
02582     {
02583       _dbus_pending_call_complete_and_unlock (pending, message);
02584 
02585       pending = NULL;
02586       
02587       CONNECTION_LOCK (connection);
02588       goto out;
02589     }
02590 
02591   /* We're still protected from dispatch() reentrancy here
02592    * since we acquired the dispatcher
02593    */
02594   _dbus_verbose ("  running object path dispatch on message %p (%d %s '%s')\n",
02595                  message,
02596                  dbus_message_get_type (message),
02597                  dbus_message_get_interface (message) ?
02598                  dbus_message_get_interface (message) :
02599                  "no interface",
02600                  dbus_message_get_signature (message));
02601   
02602   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
02603                                                   message);
02604   
02605   CONNECTION_LOCK (connection);
02606 
02607   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02608     goto out;
02609 
02610   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
02611     {
02612       DBusMessage *reply;
02613       DBusString str;
02614       DBusPreallocatedSend *preallocated;
02615 
02616       _dbus_verbose ("  sending error %s\n",
02617                      DBUS_ERROR_UNKNOWN_METHOD);
02618       
02619       if (!_dbus_string_init (&str))
02620         {
02621           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02622           goto out;
02623         }
02624               
02625       if (!_dbus_string_append_printf (&str,
02626                                        "Method \"%s\" on interface \"%s\" doesn't exist\n",
02627                                        dbus_message_get_member (message),
02628                                        dbus_message_get_interface (message)))
02629         {
02630           _dbus_string_free (&str);
02631           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02632           goto out;
02633         }
02634       
02635       reply = dbus_message_new_error (message,
02636                                       DBUS_ERROR_UNKNOWN_METHOD,
02637                                       _dbus_string_get_const_data (&str));
02638       _dbus_string_free (&str);
02639 
02640       if (reply == NULL)
02641         {
02642           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02643           goto out;
02644         }
02645       
02646       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02647 
02648       if (preallocated == NULL)
02649         {
02650           dbus_message_unref (reply);
02651           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02652           goto out;
02653         }
02654 
02655       _dbus_connection_send_preallocated_unlocked (connection, preallocated,
02656                                                    reply, NULL);
02657 
02658       dbus_message_unref (reply);
02659       
02660       result = DBUS_HANDLER_RESULT_HANDLED;
02661     }
02662   
02663   _dbus_verbose ("  done dispatching %p (%d %s '%s') on connection %p\n", message,
02664                  dbus_message_get_type (message),
02665                  dbus_message_get_interface (message) ?
02666                  dbus_message_get_interface (message) :
02667                  "no interface",
02668                  dbus_message_get_signature (message),
02669                  connection);
02670   
02671  out:
02672   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02673     {
02674       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
02675       
02676       /* Put message back, and we'll start over.
02677        * Yes this means handlers must be idempotent if they
02678        * don't return HANDLED; c'est la vie.
02679        */
02680       _dbus_connection_putback_message_link_unlocked (connection,
02681                                                       message_link);
02682     }
02683   else
02684     {
02685       _dbus_verbose ("Done with message in %s\n", _DBUS_FUNCTION_NAME);
02686       
02687       if (connection->exit_on_disconnect &&
02688           dbus_message_is_signal (message,
02689                                   DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
02690                                   "Disconnected"))
02691         {
02692           _dbus_verbose ("Exiting on Disconnected signal\n");
02693           CONNECTION_UNLOCK (connection);
02694           _dbus_exit (1);
02695           _dbus_assert_not_reached ("Call to exit() returned");
02696         }
02697       
02698       _dbus_list_free_link (message_link);
02699       dbus_message_unref (message); /* don't want the message to count in max message limits
02700                                      * in computing dispatch status below
02701                                      */
02702     }
02703   
02704   _dbus_connection_release_dispatch (connection);
02705   
02706   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02707 
02708   /* unlocks and calls user code */
02709   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02710   
02711   dbus_connection_unref (connection);
02712   
02713   return status;
02714 }
02715 
02774 dbus_bool_t
02775 dbus_connection_set_watch_functions (DBusConnection              *connection,
02776                                      DBusAddWatchFunction         add_function,
02777                                      DBusRemoveWatchFunction      remove_function,
02778                                      DBusWatchToggledFunction     toggled_function,
02779                                      void                        *data,
02780                                      DBusFreeFunction             free_data_function)
02781 {
02782   dbus_bool_t retval;
02783 
02784   _dbus_return_val_if_fail (connection != NULL, FALSE);
02785   
02786   CONNECTION_LOCK (connection);
02787   /* ref connection for slightly better reentrancy */
02788   _dbus_connection_ref_unlocked (connection);
02789 
02790   /* FIXME this can call back into user code, and we need to drop the
02791    * connection lock when it does.
02792    */
02793   retval = _dbus_watch_list_set_functions (connection->watches,
02794                                            add_function, remove_function,
02795                                            toggled_function,
02796                                            data, free_data_function);
02797   
02798   CONNECTION_UNLOCK (connection);
02799   /* drop our paranoid refcount */
02800   dbus_connection_unref (connection);
02801 
02802   return retval;
02803 }
02804 
02838 dbus_bool_t
02839 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
02840                                          DBusAddTimeoutFunction     add_function,
02841                                          DBusRemoveTimeoutFunction  remove_function,
02842                                          DBusTimeoutToggledFunction toggled_function,
02843                                          void                      *data,
02844                                          DBusFreeFunction           free_data_function)
02845 {
02846   dbus_bool_t retval;
02847 
02848   _dbus_return_val_if_fail (connection != NULL, FALSE);
02849   
02850   CONNECTION_LOCK (connection);
02851   /* ref connection for slightly better reentrancy */
02852   _dbus_connection_ref_unlocked (connection);
02853   
02854   retval = _dbus_timeout_list_set_functions (connection->timeouts,
02855                                              add_function, remove_function,
02856                                              toggled_function,
02857                                              data, free_data_function);
02858   
02859   CONNECTION_UNLOCK (connection);
02860   /* drop our paranoid refcount */
02861   dbus_connection_unref (connection);
02862 
02863   return retval;
02864 }
02865 
02880 void
02881 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
02882                                           DBusWakeupMainFunction     wakeup_main_function,
02883                                           void                      *data,
02884                                           DBusFreeFunction           free_data_function)
02885 {
02886   void *old_data;
02887   DBusFreeFunction old_free_data;
02888 
02889   _dbus_return_if_fail (connection != NULL);
02890   
02891   CONNECTION_LOCK (connection);
02892   old_data = connection->wakeup_main_data;
02893   old_free_data = connection->free_wakeup_main_data;
02894 
02895   connection->wakeup_main_function = wakeup_main_function;
02896   connection->wakeup_main_data = data;
02897   connection->free_wakeup_main_data = free_data_function;
02898   
02899   CONNECTION_UNLOCK (connection);
02900 
02901   /* Callback outside the lock */
02902   if (old_free_data)
02903     (*old_free_data) (old_data);
02904 }
02905 
02922 void
02923 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
02924                                               DBusDispatchStatusFunction  function,
02925                                               void                       *data,
02926                                               DBusFreeFunction            free_data_function)
02927 {
02928   void *old_data;
02929   DBusFreeFunction old_free_data;
02930 
02931   _dbus_return_if_fail (connection != NULL);
02932   
02933   CONNECTION_LOCK (connection);
02934   old_data = connection->dispatch_status_data;
02935   old_free_data = connection->free_dispatch_status_data;
02936 
02937   connection->dispatch_status_function = function;
02938   connection->dispatch_status_data = data;
02939   connection->free_dispatch_status_data = free_data_function;
02940   
02941   CONNECTION_UNLOCK (connection);
02942 
02943   /* Callback outside the lock */
02944   if (old_free_data)
02945     (*old_free_data) (old_data);
02946 }
02947 
02959 dbus_bool_t
02960 dbus_connection_get_unix_user (DBusConnection *connection,
02961                                unsigned long  *uid)
02962 {
02963   dbus_bool_t result;
02964 
02965   _dbus_return_val_if_fail (connection != NULL, FALSE);
02966   _dbus_return_val_if_fail (uid != NULL, FALSE);
02967   
02968   CONNECTION_LOCK (connection);
02969 
02970   if (!_dbus_transport_get_is_authenticated (connection->transport))
02971     result = FALSE;
02972   else
02973     result = _dbus_transport_get_unix_user (connection->transport,
02974                                             uid);
02975   CONNECTION_UNLOCK (connection);
02976 
02977   return result;
02978 }
02979 
02996 void
02997 dbus_connection_set_unix_user_function (DBusConnection             *connection,
02998                                         DBusAllowUnixUserFunction   function,
02999                                         void                       *data,
03000                                         DBusFreeFunction            free_data_function)
03001 {
03002   void *old_data = NULL;
03003   DBusFreeFunction old_free_function = NULL;
03004 
03005   _dbus_return_if_fail (connection != NULL);
03006   
03007   CONNECTION_LOCK (connection);
03008   _dbus_transport_set_unix_user_function (connection->transport,
03009                                           function, data, free_data_function,
03010                                           &old_data, &old_free_function);
03011   CONNECTION_UNLOCK (connection);
03012 
03013   if (old_free_function != NULL)
03014     (* old_free_function) (old_data);    
03015 }
03016 
03038 dbus_bool_t
03039 dbus_connection_add_filter (DBusConnection            *connection,
03040                             DBusHandleMessageFunction  function,
03041                             void                      *user_data,
03042                             DBusFreeFunction           free_data_function)
03043 {
03044   DBusMessageFilter *filter;
03045   
03046   _dbus_return_val_if_fail (connection != NULL, FALSE);
03047   _dbus_return_val_if_fail (function != NULL, FALSE);
03048 
03049   filter = dbus_new0 (DBusMessageFilter, 1);
03050   if (filter == NULL)
03051     return FALSE;
03052 
03053   filter->refcount.value = 1;
03054   
03055   CONNECTION_LOCK (connection);
03056 
03057   if (!_dbus_list_append (&connection->filter_list,
03058                           filter))
03059     {
03060       _dbus_message_filter_unref (filter);
03061       CONNECTION_UNLOCK (connection);
03062       return FALSE;
03063     }
03064 
03065   /* Fill in filter after all memory allocated,
03066    * so we don't run the free_user_data_function
03067    * if the add_filter() fails
03068    */
03069   
03070   filter->function = function;
03071   filter->user_data = user_data;
03072   filter->free_user_data_function = free_data_function;
03073         
03074   CONNECTION_UNLOCK (connection);
03075   return TRUE;
03076 }
03077 
03090 void
03091 dbus_connection_remove_filter (DBusConnection            *connection,
03092                                DBusHandleMessageFunction  function,
03093                                void                      *user_data)
03094 {
03095   DBusList *link;
03096   DBusMessageFilter *filter;
03097   
03098   _dbus_return_if_fail (connection != NULL);
03099   _dbus_return_if_fail (function != NULL);
03100   
03101   CONNECTION_LOCK (connection);
03102 
03103   filter = NULL;
03104   
03105   link = _dbus_list_get_last_link (&connection->filter_list);
03106   while (link != NULL)
03107     {
03108       filter = link->data;
03109 
03110       if (filter->function == function &&
03111           filter->user_data == user_data)
03112         {
03113           _dbus_list_remove_link (&connection->filter_list, link);
03114           filter->function = NULL;
03115           
03116           break;
03117         }
03118         
03119       link = _dbus_list_get_prev_link (&connection->filter_list, link);
03120     }
03121   
03122   CONNECTION_UNLOCK (connection);
03123 
03124 #ifndef DBUS_DISABLE_CHECKS
03125   if (filter == NULL)
03126     {
03127       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
03128                   function, user_data);
03129       return;
03130     }
03131 #endif
03132   
03133   /* Call application code */
03134   if (filter->free_user_data_function)
03135     (* filter->free_user_data_function) (filter->user_data);
03136 
03137   filter->free_user_data_function = NULL;
03138   filter->user_data = NULL;
03139   
03140   _dbus_message_filter_unref (filter);
03141 }
03142 
03154 dbus_bool_t
03155 dbus_connection_register_object_path (DBusConnection              *connection,
03156                                       const char                 **path,
03157                                       const DBusObjectPathVTable  *vtable,
03158                                       void                        *user_data)
03159 {
03160   dbus_bool_t retval;
03161   
03162   _dbus_return_val_if_fail (connection != NULL, FALSE);
03163   _dbus_return_val_if_fail (path != NULL, FALSE);
03164   _dbus_return_val_if_fail (path[0] != NULL, FALSE);
03165   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03166 
03167   CONNECTION_LOCK (connection);
03168 
03169   retval = _dbus_object_tree_register (connection->objects,
03170                                        FALSE,
03171                                        path, vtable,
03172                                        user_data);
03173 
03174   CONNECTION_UNLOCK (connection);
03175 
03176   return retval;
03177 }
03178 
03191 dbus_bool_t
03192 dbus_connection_register_fallback (DBusConnection              *connection,
03193                                    const char                 **path,
03194                                    const DBusObjectPathVTable  *vtable,
03195                                    void                        *user_data)
03196 {
03197   dbus_bool_t retval;
03198   
03199   _dbus_return_val_if_fail (connection != NULL, FALSE);
03200   _dbus_return_val_if_fail (path != NULL, FALSE);
03201   _dbus_return_val_if_fail (path[0] != NULL, FALSE);
03202   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03203 
03204   CONNECTION_LOCK (connection);
03205 
03206   retval = _dbus_object_tree_register (connection->objects,
03207                                        TRUE,
03208                                        path, vtable,
03209                                        user_data);
03210 
03211   CONNECTION_UNLOCK (connection);
03212 
03213   return retval;
03214 }
03215 
03224 void
03225 dbus_connection_unregister_object_path (DBusConnection              *connection,
03226                                         const char                 **path)
03227 {
03228   _dbus_return_if_fail (connection != NULL);
03229   _dbus_return_if_fail (path != NULL);
03230   _dbus_return_if_fail (path[0] != NULL);
03231 
03232   CONNECTION_LOCK (connection);
03233 
03234   return _dbus_object_tree_unregister_and_unlock (connection->objects,
03235                                                   path);
03236 }
03237 
03248 dbus_bool_t
03249 dbus_connection_list_registered (DBusConnection              *connection,
03250                                  const char                 **parent_path,
03251                                  char                      ***child_entries)
03252 {
03253   _dbus_return_val_if_fail (connection != NULL, FALSE);
03254   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
03255   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
03256 
03257   CONNECTION_LOCK (connection);
03258 
03259   return _dbus_object_tree_list_registered_and_unlock (connection->objects,
03260                                                        parent_path,
03261                                                        child_entries);
03262 }
03263 
03264 static DBusDataSlotAllocator slot_allocator;
03265 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
03266 
03281 dbus_bool_t
03282 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
03283 {
03284   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03285                                           _DBUS_LOCK_NAME (connection_slots),
03286                                           slot_p);
03287 }
03288 
03300 void
03301 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
03302 {
03303   _dbus_return_if_fail (*slot_p >= 0);
03304   
03305   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03306 }
03307 
03321 dbus_bool_t
03322 dbus_connection_set_data (DBusConnection   *connection,
03323                           dbus_int32_t      slot,
03324                           void             *data,
03325                           DBusFreeFunction  free_data_func)
03326 {
03327   DBusFreeFunction old_free_func;
03328   void *old_data;
03329   dbus_bool_t retval;
03330 
03331   _dbus_return_val_if_fail (connection != NULL, FALSE);
03332   _dbus_return_val_if_fail (slot >= 0, FALSE);
03333   
03334   CONNECTION_LOCK (connection);
03335 
03336   retval = _dbus_data_slot_list_set (&slot_allocator,
03337                                      &connection->slot_list,
03338                                      slot, data, free_data_func,
03339                                      &old_free_func, &old_data);
03340   
03341   CONNECTION_UNLOCK (connection);
03342 
03343   if (retval)
03344     {
03345       /* Do the actual free outside the connection lock */
03346       if (old_free_func)
03347         (* old_free_func) (old_data);
03348     }
03349 
03350   return retval;
03351 }
03352 
03361 void*
03362 dbus_connection_get_data (DBusConnection   *connection,
03363                           dbus_int32_t      slot)
03364 {
03365   void *res;
03366 
03367   _dbus_return_val_if_fail (connection != NULL, NULL);
03368   
03369   CONNECTION_LOCK (connection);
03370 
03371   res = _dbus_data_slot_list_get (&slot_allocator,
03372                                   &connection->slot_list,
03373                                   slot);
03374   
03375   CONNECTION_UNLOCK (connection);
03376 
03377   return res;
03378 }
03379 
03386 void
03387 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
03388 {  
03389   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
03390 }
03391 
03400 void
03401 dbus_connection_set_max_message_size (DBusConnection *connection,
03402                                       long            size)
03403 {
03404   _dbus_return_if_fail (connection != NULL);
03405   
03406   CONNECTION_LOCK (connection);
03407   _dbus_transport_set_max_message_size (connection->transport,
03408                                         size);
03409   CONNECTION_UNLOCK (connection);
03410 }
03411 
03418 long
03419 dbus_connection_get_max_message_size (DBusConnection *connection)
03420 {
03421   long res;
03422 
03423   _dbus_return_val_if_fail (connection != NULL, 0);
03424   
03425   CONNECTION_LOCK (connection);
03426   res = _dbus_transport_get_max_message_size (connection->transport);
03427   CONNECTION_UNLOCK (connection);
03428   return res;
03429 }
03430 
03456 void
03457 dbus_connection_set_max_received_size (DBusConnection *connection,
03458                                        long            size)
03459 {
03460   _dbus_return_if_fail (connection != NULL);
03461   
03462   CONNECTION_LOCK (connection);
03463   _dbus_transport_set_max_received_size (connection->transport,
03464                                          size);
03465   CONNECTION_UNLOCK (connection);
03466 }
03467 
03474 long
03475 dbus_connection_get_max_received_size (DBusConnection *connection)
03476 {
03477   long res;
03478 
03479   _dbus_return_val_if_fail (connection != NULL, 0);
03480   
03481   CONNECTION_LOCK (connection);
03482   res = _dbus_transport_get_max_received_size (connection->transport);
03483   CONNECTION_UNLOCK (connection);
03484   return res;
03485 }
03486 
03497 long
03498 dbus_connection_get_outgoing_size (DBusConnection *connection)
03499 {
03500   long res;
03501 
03502   _dbus_return_val_if_fail (connection != NULL, 0);
03503   
03504   CONNECTION_LOCK (connection);
03505   res = _dbus_counter_get_value (connection->outgoing_counter);
03506   CONNECTION_UNLOCK (connection);
03507   return res;
03508 }
03509 

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