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 2.0
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 #include <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 DBusMessageFilter *
00223 _dbus_message_filter_ref (DBusMessageFilter *filter)
00224 {
00225   _dbus_assert (filter->refcount.value > 0);
00226   _dbus_atomic_inc (&filter->refcount);
00227 
00228   return filter;
00229 }
00230 
00231 static void
00232 _dbus_message_filter_unref (DBusMessageFilter *filter)
00233 {
00234   _dbus_assert (filter->refcount.value > 0);
00235 
00236   if (_dbus_atomic_dec (&filter->refcount) == 1)
00237     {
00238       if (filter->free_user_data_function)
00239         (* filter->free_user_data_function) (filter->user_data);
00240       
00241       dbus_free (filter);
00242     }
00243 }
00244 
00250 void
00251 _dbus_connection_lock (DBusConnection *connection)
00252 {
00253   CONNECTION_LOCK (connection);
00254 }
00255 
00261 void
00262 _dbus_connection_unlock (DBusConnection *connection)
00263 {
00264   CONNECTION_UNLOCK (connection);
00265 }
00266 
00274 static void
00275 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00276 {
00277   if (connection->wakeup_main_function)
00278     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00279 }
00280 
00281 #ifdef DBUS_BUILD_TESTS
00282 /* For now this function isn't used */
00292 dbus_bool_t
00293 _dbus_connection_queue_received_message (DBusConnection *connection,
00294                                          DBusMessage    *message)
00295 {
00296   DBusList *link;
00297 
00298   link = _dbus_list_alloc_link (message);
00299   if (link == NULL)
00300     return FALSE;
00301 
00302   dbus_message_ref (message);
00303   _dbus_connection_queue_received_message_link (connection, link);
00304 
00305   return TRUE;
00306 }
00307 #endif
00308 
00317 void
00318 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00319                                               DBusList        *link)
00320 {
00321   DBusPendingCall *pending;
00322   dbus_int32_t reply_serial;
00323   DBusMessage *message;
00324   
00325   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00326   
00327   _dbus_list_append_link (&connection->incoming_messages,
00328                           link);
00329   message = link->data;
00330 
00331   /* If this is a reply we're waiting on, remove timeout for it */
00332   reply_serial = dbus_message_get_reply_serial (message);
00333   if (reply_serial != -1)
00334     {
00335       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00336                                              reply_serial);
00337       if (pending != NULL)
00338         {
00339           if (pending->timeout_added)
00340             _dbus_connection_remove_timeout_locked (connection,
00341                                                     pending->timeout);
00342 
00343           pending->timeout_added = FALSE;
00344         }
00345     }
00346   
00347   connection->n_incoming += 1;
00348 
00349   _dbus_connection_wakeup_mainloop (connection);
00350   
00351   _dbus_verbose ("Message %p (%d %s '%s') added to incoming queue %p, %d incoming\n",
00352                  message,
00353                  dbus_message_get_type (message),
00354                  dbus_message_get_interface (message) ?
00355                  dbus_message_get_interface (message) :
00356                  "no interface",
00357                  dbus_message_get_signature (message),
00358                  connection,
00359                  connection->n_incoming);
00360 }
00361 
00372 static void
00373 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00374                                                  DBusList *link)
00375 {
00376   _dbus_list_append_link (&connection->incoming_messages, link);
00377 
00378   connection->n_incoming += 1;
00379 
00380   _dbus_connection_wakeup_mainloop (connection);
00381   
00382   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00383                  link->data, connection, connection->n_incoming);
00384 }
00385 
00386 
00393 dbus_bool_t
00394 _dbus_connection_have_messages_to_send (DBusConnection *connection)
00395 {
00396   return connection->outgoing_messages != NULL;
00397 }
00398 
00406 DBusMessage*
00407 _dbus_connection_get_message_to_send (DBusConnection *connection)
00408 {
00409   return _dbus_list_get_last (&connection->outgoing_messages);
00410 }
00411 
00420 void
00421 _dbus_connection_message_sent (DBusConnection *connection,
00422                                DBusMessage    *message)
00423 {
00424   DBusList *link;
00425   
00426   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00427   
00428   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00429   _dbus_assert (link != NULL);
00430   _dbus_assert (link->data == message);
00431 
00432   /* Save this link in the link cache */
00433   _dbus_list_unlink (&connection->outgoing_messages,
00434                      link);
00435   _dbus_list_prepend_link (&connection->link_cache, link);
00436   
00437   connection->n_outgoing -= 1;
00438 
00439   _dbus_verbose ("Message %p (%d %s '%s') removed from outgoing queue %p, %d left to send\n",
00440                  message,
00441                  dbus_message_get_type (message),
00442                  dbus_message_get_interface (message) ?
00443                  dbus_message_get_interface (message) :
00444                  "no interface",
00445                  dbus_message_get_signature (message),
00446                  connection, connection->n_outgoing);
00447 
00448   /* Save this link in the link cache also */
00449   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00450                                      &link);
00451   _dbus_list_prepend_link (&connection->link_cache, link);
00452   
00453   dbus_message_unref (message);
00454   
00455   if (connection->n_outgoing == 0)
00456     _dbus_transport_messages_pending (connection->transport,
00457                                       connection->n_outgoing);  
00458 }
00459 
00470 dbus_bool_t
00471 _dbus_connection_add_watch (DBusConnection *connection,
00472                             DBusWatch      *watch)
00473 {
00474   if (connection->watches) /* null during finalize */
00475     return _dbus_watch_list_add_watch (connection->watches,
00476                                        watch);
00477   else
00478     return FALSE;
00479 }
00480 
00489 void
00490 _dbus_connection_remove_watch (DBusConnection *connection,
00491                                DBusWatch      *watch)
00492 {
00493   if (connection->watches) /* null during finalize */
00494     _dbus_watch_list_remove_watch (connection->watches,
00495                                    watch);
00496 }
00497 
00507 void
00508 _dbus_connection_toggle_watch (DBusConnection *connection,
00509                                DBusWatch      *watch,
00510                                dbus_bool_t     enabled)
00511 {
00512   if (connection->watches) /* null during finalize */
00513     _dbus_watch_list_toggle_watch (connection->watches,
00514                                    watch, enabled);
00515 }
00516 
00528 dbus_bool_t
00529 _dbus_connection_add_timeout (DBusConnection *connection,
00530                               DBusTimeout    *timeout)
00531 {
00532  if (connection->timeouts) /* null during finalize */
00533     return _dbus_timeout_list_add_timeout (connection->timeouts,
00534                                            timeout);
00535   else
00536     return FALSE;  
00537 }
00538 
00547 void
00548 _dbus_connection_remove_timeout (DBusConnection *connection,
00549                                  DBusTimeout    *timeout)
00550 {
00551   if (connection->timeouts) /* null during finalize */
00552     _dbus_timeout_list_remove_timeout (connection->timeouts,
00553                                        timeout);
00554 }
00555 
00556 static void
00557 _dbus_connection_remove_timeout_locked (DBusConnection *connection,
00558                                         DBusTimeout    *timeout)
00559 {
00560   CONNECTION_LOCK (connection);
00561   _dbus_connection_remove_timeout (connection, timeout);
00562   CONNECTION_UNLOCK (connection);
00563 }
00564 
00574 void
00575 _dbus_connection_toggle_timeout (DBusConnection *connection,
00576                                  DBusTimeout      *timeout,
00577                                  dbus_bool_t     enabled)
00578 {
00579   if (connection->timeouts) /* null during finalize */
00580     _dbus_timeout_list_toggle_timeout (connection->timeouts,
00581                                        timeout, enabled);
00582 }
00583 
00584 static dbus_bool_t
00585 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00586                                                DBusPendingCall *pending)
00587 {
00588   _dbus_assert (pending->reply_serial != 0);
00589 
00590   if (!_dbus_connection_add_timeout (connection, pending->timeout))
00591     return FALSE;
00592   
00593   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00594                                     pending->reply_serial,
00595                                     pending))
00596     {
00597       _dbus_connection_remove_timeout (connection, pending->timeout);
00598       return FALSE;
00599     }
00600   
00601   pending->timeout_added = TRUE;
00602   pending->connection = connection;
00603 
00604   dbus_pending_call_ref (pending);
00605   
00606   return TRUE;
00607 }
00608 
00609 static void
00610 free_pending_call_on_hash_removal (void *data)
00611 {
00612   DBusPendingCall *pending;
00613   
00614   if (data == NULL)
00615     return;
00616 
00617   pending = data;
00618 
00619   if (pending->connection)
00620     {
00621       if (pending->timeout_added)
00622         {
00623           _dbus_connection_remove_timeout (pending->connection,
00624                                            pending->timeout);
00625           pending->timeout_added = FALSE;
00626         }
00627 
00628       pending->connection = NULL;
00629       
00630       dbus_pending_call_unref (pending);
00631     }
00632 }
00633 
00634 static void
00635 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00636                                                  DBusPendingCall *pending)
00637 {
00638   /* The idea here is to avoid finalizing the pending call
00639    * with the lock held, since there's a destroy notifier
00640    * in pending call that goes out to application code.
00641    */
00642   dbus_pending_call_ref (pending);
00643   _dbus_hash_table_remove_int (connection->pending_replies,
00644                                pending->reply_serial);
00645   CONNECTION_UNLOCK (connection);
00646   dbus_pending_call_unref (pending);
00647 }
00648 
00657 void
00658 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00659                                       DBusPendingCall *pending)
00660 {
00661   CONNECTION_LOCK (connection);
00662   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00663 }
00664 
00673 void
00674 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00675                                         DBusMessage     *message)
00676 {
00677   if (message == NULL)
00678     {
00679       message = pending->timeout_link->data;
00680       _dbus_list_clear (&pending->timeout_link);
00681     }
00682   else
00683     dbus_message_ref (message);
00684 
00685   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
00686                  message,
00687                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00688                  "method return" :
00689                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00690                  "error" : "other type",
00691                  pending->reply_serial);
00692   
00693   _dbus_assert (pending->reply == NULL);
00694   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00695   pending->reply = message;
00696   
00697   dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
00698   _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00699   
00700   /* Must be called unlocked since it invokes app callback */
00701   _dbus_pending_call_notify (pending);
00702   dbus_pending_call_unref (pending);
00703 }
00704 
00714 static dbus_bool_t
00715 _dbus_connection_acquire_io_path (DBusConnection *connection,
00716                                   int timeout_milliseconds)
00717 {
00718   dbus_bool_t res = TRUE;
00719 
00720   if (connection->io_path_acquired)
00721     {
00722       if (timeout_milliseconds != -1) 
00723         res = dbus_condvar_wait_timeout (connection->io_path_cond,
00724                                          connection->mutex,
00725                                          timeout_milliseconds);
00726       else
00727         dbus_condvar_wait (connection->io_path_cond, connection->mutex);
00728     }
00729   
00730   if (res)
00731     {
00732       _dbus_assert (!connection->io_path_acquired);
00733 
00734       connection->io_path_acquired = TRUE;
00735     }
00736   
00737   return res;
00738 }
00739 
00747 static void
00748 _dbus_connection_release_io_path (DBusConnection *connection)
00749 {
00750   _dbus_assert (connection->io_path_acquired);
00751 
00752   connection->io_path_acquired = FALSE;
00753   dbus_condvar_wake_one (connection->io_path_cond);
00754 }
00755 
00756 
00783 void
00784 _dbus_connection_do_iteration (DBusConnection *connection,
00785                                unsigned int    flags,
00786                                int             timeout_milliseconds)
00787 {
00788   if (connection->n_outgoing == 0)
00789     flags &= ~DBUS_ITERATION_DO_WRITING;
00790 
00791   if (_dbus_connection_acquire_io_path (connection,
00792                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
00793     {
00794       _dbus_transport_do_iteration (connection->transport,
00795                                     flags, timeout_milliseconds);
00796       _dbus_connection_release_io_path (connection);
00797     }
00798 }
00799 
00809 DBusConnection*
00810 _dbus_connection_new_for_transport (DBusTransport *transport)
00811 {
00812   DBusConnection *connection;
00813   DBusWatchList *watch_list;
00814   DBusTimeoutList *timeout_list;
00815   DBusHashTable *pending_replies;
00816   DBusMutex *mutex;
00817   DBusCondVar *message_returned_cond;
00818   DBusCondVar *dispatch_cond;
00819   DBusCondVar *io_path_cond;
00820   DBusList *disconnect_link;
00821   DBusMessage *disconnect_message;
00822   DBusCounter *outgoing_counter;
00823   DBusObjectTree *objects;
00824   
00825   watch_list = NULL;
00826   connection = NULL;
00827   pending_replies = NULL;
00828   timeout_list = NULL;
00829   mutex = NULL;
00830   message_returned_cond = NULL;
00831   dispatch_cond = NULL;
00832   io_path_cond = NULL;
00833   disconnect_link = NULL;
00834   disconnect_message = NULL;
00835   outgoing_counter = NULL;
00836   objects = NULL;
00837   
00838   watch_list = _dbus_watch_list_new ();
00839   if (watch_list == NULL)
00840     goto error;
00841 
00842   timeout_list = _dbus_timeout_list_new ();
00843   if (timeout_list == NULL)
00844     goto error;  
00845 
00846   pending_replies =
00847     _dbus_hash_table_new (DBUS_HASH_INT,
00848                           NULL,
00849                           (DBusFreeFunction)free_pending_call_on_hash_removal);
00850   if (pending_replies == NULL)
00851     goto error;
00852   
00853   connection = dbus_new0 (DBusConnection, 1);
00854   if (connection == NULL)
00855     goto error;
00856 
00857   mutex = dbus_mutex_new ();
00858   if (mutex == NULL)
00859     goto error;
00860   
00861   message_returned_cond = dbus_condvar_new ();
00862   if (message_returned_cond == NULL)
00863     goto error;
00864   
00865   dispatch_cond = dbus_condvar_new ();
00866   if (dispatch_cond == NULL)
00867     goto error;
00868   
00869   io_path_cond = dbus_condvar_new ();
00870   if (io_path_cond == NULL)
00871     goto error;
00872 
00873   disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL,
00874                                                 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
00875                                                 "Disconnected");
00876   
00877   if (disconnect_message == NULL)
00878     goto error;
00879 
00880   disconnect_link = _dbus_list_alloc_link (disconnect_message);
00881   if (disconnect_link == NULL)
00882     goto error;
00883 
00884   outgoing_counter = _dbus_counter_new ();
00885   if (outgoing_counter == NULL)
00886     goto error;
00887 
00888   objects = _dbus_object_tree_new (connection);
00889   if (objects == NULL)
00890     goto error;
00891   
00892   if (_dbus_modify_sigpipe)
00893     _dbus_disable_sigpipe ();
00894   
00895   connection->refcount.value = 1;
00896   connection->mutex = mutex;
00897   connection->dispatch_cond = dispatch_cond;
00898   connection->io_path_cond = io_path_cond;
00899   connection->message_returned_cond = message_returned_cond;
00900   connection->transport = transport;
00901   connection->watches = watch_list;
00902   connection->timeouts = timeout_list;
00903   connection->pending_replies = pending_replies;
00904   connection->outgoing_counter = outgoing_counter;
00905   connection->filter_list = NULL;
00906   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
00907   connection->objects = objects;
00908   connection->exit_on_disconnect = FALSE;
00909   
00910   _dbus_data_slot_list_init (&connection->slot_list);
00911 
00912   connection->client_serial = 1;
00913 
00914   connection->disconnect_message_link = disconnect_link;
00915   
00916   if (!_dbus_transport_set_connection (transport, connection))
00917     goto error;
00918 
00919   _dbus_transport_ref (transport);  
00920   
00921   return connection;
00922   
00923  error:
00924   if (disconnect_message != NULL)
00925     dbus_message_unref (disconnect_message);
00926   
00927   if (disconnect_link != NULL)
00928     _dbus_list_free_link (disconnect_link);
00929   
00930   if (io_path_cond != NULL)
00931     dbus_condvar_free (io_path_cond);
00932   
00933   if (dispatch_cond != NULL)
00934     dbus_condvar_free (dispatch_cond);
00935   
00936   if (message_returned_cond != NULL)
00937     dbus_condvar_free (message_returned_cond);
00938   
00939   if (mutex != NULL)
00940     dbus_mutex_free (mutex);
00941 
00942   if (connection != NULL)
00943     dbus_free (connection);
00944 
00945   if (pending_replies)
00946     _dbus_hash_table_unref (pending_replies);
00947   
00948   if (watch_list)
00949     _dbus_watch_list_free (watch_list);
00950 
00951   if (timeout_list)
00952     _dbus_timeout_list_free (timeout_list);
00953 
00954   if (outgoing_counter)
00955     _dbus_counter_unref (outgoing_counter);
00956 
00957   if (objects)
00958     _dbus_object_tree_unref (objects);
00959   
00960   return NULL;
00961 }
00962 
00970 DBusConnection *
00971 _dbus_connection_ref_unlocked (DBusConnection *connection)
00972 {
00973 #ifdef DBUS_HAVE_ATOMIC_INT
00974   _dbus_atomic_inc (&connection->refcount);
00975 #else
00976   _dbus_assert (connection->refcount.value > 0);
00977   connection->refcount.value += 1;
00978 #endif
00979 
00980   return connection;
00981 }
00982 
00989 void
00990 _dbus_connection_unref_unlocked (DBusConnection *connection)
00991 {
00992   dbus_bool_t last_unref;
00993 
00994   _dbus_return_if_fail (connection != NULL);
00995 
00996   /* The connection lock is better than the global
00997    * lock in the atomic increment fallback
00998    */
00999   
01000 #ifdef DBUS_HAVE_ATOMIC_INT
01001   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01002 #else  
01003   _dbus_assert (connection->refcount.value > 0);
01004 
01005   connection->refcount.value -= 1;
01006   last_unref = (connection->refcount.value == 0);
01007 #if 0
01008   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01009 #endif
01010 #endif
01011   
01012   if (last_unref)
01013     _dbus_connection_last_unref (connection);
01014 }
01015 
01016 static dbus_uint32_t
01017 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01018 {
01019   int serial;
01020 
01021   serial = connection->client_serial++;
01022 
01023   if (connection->client_serial < 0)
01024     connection->client_serial = 1;
01025   
01026   return serial;
01027 }
01028 
01042 dbus_bool_t
01043 _dbus_connection_handle_watch (DBusWatch                   *watch,
01044                                unsigned int                 condition,
01045                                void                        *data)
01046 {
01047   DBusConnection *connection;
01048   dbus_bool_t retval;
01049   DBusDispatchStatus status;
01050 
01051   connection = data;
01052   
01053   CONNECTION_LOCK (connection);
01054   _dbus_connection_acquire_io_path (connection, -1);
01055   retval = _dbus_transport_handle_watch (connection->transport,
01056                                          watch, condition);
01057   _dbus_connection_release_io_path (connection);
01058 
01059   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01060 
01061   /* this calls out to user code */
01062   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01063   
01064   return retval;
01065 }
01066 
01091 DBusConnection*
01092 dbus_connection_open (const char     *address,
01093                       DBusError      *error)
01094 {
01095   DBusConnection *connection;
01096   DBusTransport *transport;
01097 
01098   _dbus_return_val_if_fail (address != NULL, NULL);
01099   _dbus_return_val_if_error_is_set (error, NULL);
01100   
01101   transport = _dbus_transport_open (address, error);
01102   if (transport == NULL)
01103     {
01104       _DBUS_ASSERT_ERROR_IS_SET (error);
01105       return NULL;
01106     }
01107   
01108   connection = _dbus_connection_new_for_transport (transport);
01109 
01110   _dbus_transport_unref (transport);
01111   
01112   if (connection == NULL)
01113     {
01114       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01115       return NULL;
01116     }
01117   
01118   return connection;
01119 }
01120 
01127 DBusConnection *
01128 dbus_connection_ref (DBusConnection *connection)
01129 {
01130   _dbus_return_val_if_fail (connection != NULL, NULL);
01131 
01132   /* The connection lock is better than the global
01133    * lock in the atomic increment fallback
01134    */
01135   
01136 #ifdef DBUS_HAVE_ATOMIC_INT
01137   _dbus_atomic_inc (&connection->refcount);
01138 #else
01139   CONNECTION_LOCK (connection);
01140   _dbus_assert (connection->refcount.value > 0);
01141 
01142   connection->refcount.value += 1;
01143   CONNECTION_UNLOCK (connection);
01144 #endif
01145 
01146   return connection;
01147 }
01148 
01149 static void
01150 free_outgoing_message (void *element,
01151                        void *data)
01152 {
01153   DBusMessage *message = element;
01154   DBusConnection *connection = data;
01155 
01156   _dbus_message_remove_size_counter (message,
01157                                      connection->outgoing_counter,
01158                                      NULL);
01159   dbus_message_unref (message);
01160 }
01161 
01162 /* This is run without the mutex held, but after the last reference
01163  * to the connection has been dropped we should have no thread-related
01164  * problems
01165  */
01166 static void
01167 _dbus_connection_last_unref (DBusConnection *connection)
01168 {
01169   DBusList *link;
01170 
01171   _dbus_verbose ("Finalizing connection %p\n", connection);
01172   
01173   _dbus_assert (connection->refcount.value == 0);
01174   
01175   /* You have to disconnect the connection before unref:ing it. Otherwise
01176    * you won't get the disconnected message.
01177    */
01178   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01179 
01180   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01181   _dbus_object_tree_free_all_unlocked (connection->objects);
01182   
01183   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01184   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01185   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01186   
01187   _dbus_watch_list_free (connection->watches);
01188   connection->watches = NULL;
01189   
01190   _dbus_timeout_list_free (connection->timeouts);
01191   connection->timeouts = NULL;
01192 
01193   _dbus_data_slot_list_free (&connection->slot_list);
01194   
01195   link = _dbus_list_get_first_link (&connection->filter_list);
01196   while (link != NULL)
01197     {
01198       DBusMessageFilter *filter = link->data;
01199       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01200 
01201       filter->function = NULL;
01202       _dbus_message_filter_unref (filter); /* calls app callback */
01203       link->data = NULL;
01204       
01205       link = next;
01206     }
01207   _dbus_list_clear (&connection->filter_list);
01208   
01209   /* ---- Done with stuff that invokes application callbacks */
01210 
01211   _dbus_object_tree_unref (connection->objects);  
01212 
01213   _dbus_hash_table_unref (connection->pending_replies);
01214   connection->pending_replies = NULL;
01215   
01216   _dbus_list_clear (&connection->filter_list);
01217   
01218   _dbus_list_foreach (&connection->outgoing_messages,
01219                       free_outgoing_message,
01220                       connection);
01221   _dbus_list_clear (&connection->outgoing_messages);
01222   
01223   _dbus_list_foreach (&connection->incoming_messages,
01224                       (DBusForeachFunction) dbus_message_unref,
01225                       NULL);
01226   _dbus_list_clear (&connection->incoming_messages);
01227 
01228   _dbus_counter_unref (connection->outgoing_counter);
01229   
01230   _dbus_transport_unref (connection->transport);
01231 
01232   if (connection->disconnect_message_link)
01233     {
01234       DBusMessage *message = connection->disconnect_message_link->data;
01235       dbus_message_unref (message);
01236       _dbus_list_free_link (connection->disconnect_message_link);
01237     }
01238 
01239   _dbus_list_clear (&connection->link_cache);
01240   
01241   dbus_condvar_free (connection->dispatch_cond);
01242   dbus_condvar_free (connection->io_path_cond);
01243   dbus_condvar_free (connection->message_returned_cond);  
01244   
01245   dbus_mutex_free (connection->mutex);
01246   
01247   dbus_free (connection);
01248 }
01249 
01261 void
01262 dbus_connection_unref (DBusConnection *connection)
01263 {
01264   dbus_bool_t last_unref;
01265 
01266   _dbus_return_if_fail (connection != NULL);
01267 
01268   /* The connection lock is better than the global
01269    * lock in the atomic increment fallback
01270    */
01271   
01272 #ifdef DBUS_HAVE_ATOMIC_INT
01273   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01274 #else
01275   CONNECTION_LOCK (connection);
01276   
01277   _dbus_assert (connection->refcount.value > 0);
01278 
01279   connection->refcount.value -= 1;
01280   last_unref = (connection->refcount.value == 0);
01281 
01282 #if 0
01283   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01284 #endif
01285   
01286   CONNECTION_UNLOCK (connection);
01287 #endif
01288   
01289   if (last_unref)
01290     _dbus_connection_last_unref (connection);
01291 }
01292 
01306 void
01307 dbus_connection_disconnect (DBusConnection *connection)
01308 {
01309   DBusDispatchStatus status;
01310   
01311   _dbus_return_if_fail (connection != NULL);
01312   
01313   CONNECTION_LOCK (connection);
01314   _dbus_transport_disconnect (connection->transport);
01315   
01316   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01317 
01318   /* this calls out to user code */
01319   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01320 }
01321 
01322 static dbus_bool_t
01323 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01324 {
01325   return _dbus_transport_get_is_connected (connection->transport);
01326 }
01327 
01338 dbus_bool_t
01339 dbus_connection_get_is_connected (DBusConnection *connection)
01340 {
01341   dbus_bool_t res;
01342 
01343   _dbus_return_val_if_fail (connection != NULL, FALSE);
01344   
01345   CONNECTION_LOCK (connection);
01346   res = _dbus_connection_get_is_connected_unlocked (connection);
01347   CONNECTION_UNLOCK (connection);
01348   
01349   return res;
01350 }
01351 
01360 dbus_bool_t
01361 dbus_connection_get_is_authenticated (DBusConnection *connection)
01362 {
01363   dbus_bool_t res;
01364 
01365   _dbus_return_val_if_fail (connection != NULL, FALSE);
01366   
01367   CONNECTION_LOCK (connection);
01368   res = _dbus_transport_get_is_authenticated (connection->transport);
01369   CONNECTION_UNLOCK (connection);
01370   
01371   return res;
01372 }
01373 
01387 void
01388 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
01389                                         dbus_bool_t     exit_on_disconnect)
01390 {
01391   _dbus_return_if_fail (connection != NULL);
01392 
01393   CONNECTION_LOCK (connection);
01394   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
01395   CONNECTION_UNLOCK (connection);
01396 }
01397 
01398 static DBusPreallocatedSend*
01399 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01400 {
01401   DBusPreallocatedSend *preallocated;
01402 
01403   _dbus_return_val_if_fail (connection != NULL, NULL);
01404   
01405   preallocated = dbus_new (DBusPreallocatedSend, 1);
01406   if (preallocated == NULL)
01407     return NULL;
01408 
01409   if (connection->link_cache != NULL)
01410     {
01411       preallocated->queue_link =
01412         _dbus_list_pop_first_link (&connection->link_cache);
01413       preallocated->queue_link->data = NULL;
01414     }
01415   else
01416     {
01417       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01418       if (preallocated->queue_link == NULL)
01419         goto failed_0;
01420     }
01421   
01422   if (connection->link_cache != NULL)
01423     {
01424       preallocated->counter_link =
01425         _dbus_list_pop_first_link (&connection->link_cache);
01426       preallocated->counter_link->data = connection->outgoing_counter;
01427     }
01428   else
01429     {
01430       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01431       if (preallocated->counter_link == NULL)
01432         goto failed_1;
01433     }
01434 
01435   _dbus_counter_ref (preallocated->counter_link->data);
01436 
01437   preallocated->connection = connection;
01438   
01439   return preallocated;
01440   
01441  failed_1:
01442   _dbus_list_free_link (preallocated->queue_link);
01443  failed_0:
01444   dbus_free (preallocated);
01445   
01446   return NULL;
01447 }
01448 
01458 DBusPreallocatedSend*
01459 dbus_connection_preallocate_send (DBusConnection *connection)
01460 {
01461   DBusPreallocatedSend *preallocated;
01462 
01463   _dbus_return_val_if_fail (connection != NULL, NULL);
01464 
01465   CONNECTION_LOCK (connection);
01466   
01467   preallocated =
01468     _dbus_connection_preallocate_send_unlocked (connection);
01469 
01470   CONNECTION_UNLOCK (connection);
01471 
01472   return preallocated;
01473 }
01474 
01484 void
01485 dbus_connection_free_preallocated_send (DBusConnection       *connection,
01486                                         DBusPreallocatedSend *preallocated)
01487 {
01488   _dbus_return_if_fail (connection != NULL);
01489   _dbus_return_if_fail (preallocated != NULL);  
01490   _dbus_return_if_fail (connection == preallocated->connection);
01491 
01492   _dbus_list_free_link (preallocated->queue_link);
01493   _dbus_counter_unref (preallocated->counter_link->data);
01494   _dbus_list_free_link (preallocated->counter_link);
01495   dbus_free (preallocated);
01496 }
01497 
01498 static void
01499 _dbus_connection_send_preallocated_unlocked (DBusConnection       *connection,
01500                                              DBusPreallocatedSend *preallocated,
01501                                              DBusMessage          *message,
01502                                              dbus_uint32_t        *client_serial)
01503 {
01504   dbus_uint32_t serial;
01505 
01506   preallocated->queue_link->data = message;
01507   _dbus_list_prepend_link (&connection->outgoing_messages,
01508                            preallocated->queue_link);
01509 
01510   _dbus_message_add_size_counter_link (message,
01511                                        preallocated->counter_link);
01512 
01513   dbus_free (preallocated);
01514   preallocated = NULL;
01515   
01516   dbus_message_ref (message);
01517   
01518   connection->n_outgoing += 1;
01519 
01520   _dbus_verbose ("Message %p (%d %s '%s') added to outgoing queue %p, %d pending to send\n",
01521                  message,
01522                  dbus_message_get_type (message),
01523                  dbus_message_get_interface (message) ?
01524                  dbus_message_get_interface (message) :
01525                  "no interface",
01526                  dbus_message_get_signature (message),
01527                  connection,
01528                  connection->n_outgoing);
01529 
01530   if (dbus_message_get_serial (message) == 0)
01531     {
01532       serial = _dbus_connection_get_next_client_serial (connection);
01533       _dbus_message_set_serial (message, serial);
01534       if (client_serial)
01535         *client_serial = serial;
01536     }
01537   else
01538     {
01539       if (client_serial)
01540         *client_serial = dbus_message_get_serial (message);
01541     }
01542   
01543   _dbus_message_lock (message);
01544 
01545   if (connection->n_outgoing == 1)
01546     _dbus_transport_messages_pending (connection->transport,
01547                                       connection->n_outgoing);
01548   
01549   _dbus_connection_wakeup_mainloop (connection);
01550 }
01551 
01564 void
01565 dbus_connection_send_preallocated (DBusConnection       *connection,
01566                                    DBusPreallocatedSend *preallocated,
01567                                    DBusMessage          *message,
01568                                    dbus_uint32_t        *client_serial)
01569 {
01570   _dbus_return_if_fail (connection != NULL);
01571   _dbus_return_if_fail (preallocated != NULL);
01572   _dbus_return_if_fail (message != NULL);
01573   _dbus_return_if_fail (preallocated->connection == connection);
01574   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
01575                         (dbus_message_get_interface (message) != NULL &&
01576                          dbus_message_get_member (message) != NULL));
01577   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
01578                         (dbus_message_get_interface (message) != NULL &&
01579                          dbus_message_get_member (message) != NULL));
01580   
01581   CONNECTION_LOCK (connection);
01582   _dbus_connection_send_preallocated_unlocked (connection,
01583                                                preallocated,
01584                                                message, client_serial);
01585   CONNECTION_UNLOCK (connection);  
01586 }
01587 
01588 static dbus_bool_t
01589 _dbus_connection_send_unlocked (DBusConnection *connection,
01590                                 DBusMessage    *message,
01591                                 dbus_uint32_t  *client_serial)
01592 {
01593   DBusPreallocatedSend *preallocated;
01594 
01595   _dbus_assert (connection != NULL);
01596   _dbus_assert (message != NULL);
01597   
01598   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
01599   if (preallocated == NULL)
01600     return FALSE;
01601 
01602 
01603   _dbus_connection_send_preallocated_unlocked (connection,
01604                                                preallocated,
01605                                                message,
01606                                                client_serial);
01607   return TRUE;
01608 }
01609 
01628 dbus_bool_t
01629 dbus_connection_send (DBusConnection *connection,
01630                       DBusMessage    *message,
01631                       dbus_uint32_t  *client_serial)
01632 {
01633   _dbus_return_val_if_fail (connection != NULL, FALSE);
01634   _dbus_return_val_if_fail (message != NULL, FALSE);
01635 
01636   CONNECTION_LOCK (connection);
01637 
01638   if (!_dbus_connection_send_unlocked (connection, message, client_serial))
01639     {
01640       CONNECTION_UNLOCK (connection);
01641       return FALSE;
01642     }
01643 
01644   CONNECTION_UNLOCK (connection);
01645   return TRUE;
01646 }
01647 
01648 static dbus_bool_t
01649 reply_handler_timeout (void *data)
01650 {
01651   DBusConnection *connection;
01652   DBusDispatchStatus status;
01653   DBusPendingCall *pending = data;
01654 
01655   connection = pending->connection;
01656   
01657   CONNECTION_LOCK (connection);
01658   if (pending->timeout_link)
01659     {
01660       _dbus_connection_queue_synthesized_message_link (connection,
01661                                                        pending->timeout_link);
01662       pending->timeout_link = NULL;
01663     }
01664 
01665   _dbus_connection_remove_timeout (connection,
01666                                    pending->timeout);
01667   pending->timeout_added = FALSE;
01668 
01669   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01670 
01671   /* Unlocks, and calls out to user code */
01672   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01673   
01674   return TRUE;
01675 }
01676 
01714 dbus_bool_t
01715 dbus_connection_send_with_reply (DBusConnection     *connection,
01716                                  DBusMessage        *message,
01717                                  DBusPendingCall   **pending_return,
01718                                  int                 timeout_milliseconds)
01719 {
01720   DBusPendingCall *pending;
01721   DBusMessage *reply;
01722   DBusList *reply_link;
01723   dbus_int32_t serial = -1;
01724 
01725   _dbus_return_val_if_fail (connection != NULL, FALSE);
01726   _dbus_return_val_if_fail (message != NULL, FALSE);
01727   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01728 
01729   if (pending_return)
01730     *pending_return = NULL;
01731   
01732   pending = _dbus_pending_call_new (connection,
01733                                     timeout_milliseconds,
01734                                     reply_handler_timeout);
01735 
01736   if (pending == NULL)
01737     return FALSE;
01738 
01739   CONNECTION_LOCK (connection);
01740   
01741   /* Assign a serial to the message */
01742   if (dbus_message_get_serial (message) == 0)
01743     {
01744       serial = _dbus_connection_get_next_client_serial (connection);
01745       _dbus_message_set_serial (message, serial);
01746     }
01747 
01748   pending->reply_serial = serial;
01749 
01750   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
01751                                   "No reply within specified time");
01752   if (!reply)
01753     {
01754       CONNECTION_UNLOCK (connection);
01755       dbus_pending_call_unref (pending);
01756       return FALSE;
01757     }
01758 
01759   reply_link = _dbus_list_alloc_link (reply);
01760   if (!reply)
01761     {
01762       CONNECTION_UNLOCK (connection);
01763       dbus_message_unref (reply);
01764       dbus_pending_call_unref (pending);
01765       return FALSE;
01766     }
01767 
01768   pending->timeout_link = reply_link;
01769 
01770   /* Insert the serial in the pending replies hash;
01771    * hash takes a refcount on DBusPendingCall.
01772    * Also, add the timeout.
01773    */
01774   if (!_dbus_connection_attach_pending_call_unlocked (connection,
01775                                                       pending))
01776     {
01777       CONNECTION_UNLOCK (connection);
01778       dbus_pending_call_unref (pending);
01779       return FALSE;
01780     }
01781   
01782   if (!_dbus_connection_send_unlocked (connection, message, NULL))
01783     {
01784       _dbus_connection_detach_pending_call_and_unlock (connection,
01785                                                        pending);
01786       return FALSE;
01787     }
01788 
01789   if (pending_return)
01790     {
01791       dbus_pending_call_ref (pending);
01792       *pending_return = pending;
01793     }
01794 
01795   CONNECTION_UNLOCK (connection);
01796   
01797   return TRUE;
01798 }
01799 
01800 static DBusMessage*
01801 check_for_reply_unlocked (DBusConnection *connection,
01802                           dbus_uint32_t   client_serial)
01803 {
01804   DBusList *link;
01805   
01806   link = _dbus_list_get_first_link (&connection->incoming_messages);
01807 
01808   while (link != NULL)
01809     {
01810       DBusMessage *reply = link->data;
01811 
01812       if (dbus_message_get_reply_serial (reply) == client_serial)
01813         {
01814           _dbus_list_remove_link (&connection->incoming_messages, link);
01815           connection->n_incoming  -= 1;
01816           dbus_message_ref (reply);
01817           return reply;
01818         }
01819       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
01820     }
01821 
01822   return NULL;
01823 }
01824 
01842 DBusMessage*
01843 _dbus_connection_block_for_reply (DBusConnection     *connection,
01844                                   dbus_uint32_t       client_serial,
01845                                   int                 timeout_milliseconds)
01846 {
01847   long start_tv_sec, start_tv_usec;
01848   long end_tv_sec, end_tv_usec;
01849   long tv_sec, tv_usec;
01850   DBusDispatchStatus status;
01851 
01852   _dbus_return_val_if_fail (connection != NULL, NULL);
01853   _dbus_return_val_if_fail (client_serial != 0, NULL);
01854   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
01855   
01856   if (timeout_milliseconds == -1)
01857     timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
01858 
01859   /* it would probably seem logical to pass in _DBUS_INT_MAX
01860    * for infinite timeout, but then math below would get
01861    * all overflow-prone, so smack that down.
01862    */
01863   if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
01864     timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
01865   
01866   /* Flush message queue */
01867   dbus_connection_flush (connection);
01868 
01869   CONNECTION_LOCK (connection);
01870 
01871   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
01872   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
01873   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
01874   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
01875   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
01876 
01877   _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",
01878                  timeout_milliseconds,
01879                  client_serial,
01880                  start_tv_sec, start_tv_usec,
01881                  end_tv_sec, end_tv_usec);
01882   
01883   /* Now we wait... */
01884   /* THREAD TODO: This is busted. What if a dispatch() or pop_message
01885    * gets the message before we do?
01886    */
01887   /* always block at least once as we know we don't have the reply yet */
01888   _dbus_connection_do_iteration (connection,
01889                                  DBUS_ITERATION_DO_READING |
01890                                  DBUS_ITERATION_BLOCK,
01891                                  timeout_milliseconds);
01892 
01893  recheck_status:
01894 
01895   /* queue messages and get status */
01896   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01897 
01898   if (status == DBUS_DISPATCH_DATA_REMAINS)
01899     {
01900       DBusMessage *reply;
01901       
01902       reply = check_for_reply_unlocked (connection, client_serial);
01903       if (reply != NULL)
01904         {          
01905           status = _dbus_connection_get_dispatch_status_unlocked (connection);
01906 
01907           _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
01908 
01909           /* Unlocks, and calls out to user code */
01910           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01911           
01912           return reply;
01913         }
01914     }
01915   
01916   _dbus_get_current_time (&tv_sec, &tv_usec);
01917   
01918   if (!_dbus_connection_get_is_connected_unlocked (connection))
01919     return NULL;
01920   else if (tv_sec < start_tv_sec)
01921     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
01922   else if (connection->disconnect_message_link == NULL)
01923     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
01924   else if (tv_sec < end_tv_sec ||
01925            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
01926     {
01927       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
01928         (end_tv_usec - tv_usec) / 1000;
01929       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
01930       _dbus_assert (timeout_milliseconds >= 0);
01931       
01932       if (status == DBUS_DISPATCH_NEED_MEMORY)
01933         {
01934           /* Try sleeping a bit, as we aren't sure we need to block for reading,
01935            * we may already have a reply in the buffer and just can't process
01936            * it.
01937            */
01938           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
01939           
01940           if (timeout_milliseconds < 100)
01941             ; /* just busy loop */
01942           else if (timeout_milliseconds <= 1000)
01943             _dbus_sleep_milliseconds (timeout_milliseconds / 3);
01944           else
01945             _dbus_sleep_milliseconds (1000);
01946         }
01947       else
01948         {          
01949           /* block again, we don't have the reply buffered yet. */
01950           _dbus_connection_do_iteration (connection,
01951                                          DBUS_ITERATION_DO_READING |
01952                                          DBUS_ITERATION_BLOCK,
01953                                          timeout_milliseconds);
01954         }
01955 
01956       goto recheck_status;
01957     }
01958 
01959   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
01960                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
01961 
01962   /* unlocks and calls out to user code */
01963   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01964 
01965   return NULL;
01966 }
01967 
01990 DBusMessage *
01991 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
01992                                            DBusMessage        *message,
01993                                            int                 timeout_milliseconds,
01994                                            DBusError          *error)
01995 {
01996   dbus_uint32_t client_serial;
01997   DBusMessage *reply;
01998   
01999   _dbus_return_val_if_fail (connection != NULL, NULL);
02000   _dbus_return_val_if_fail (message != NULL, NULL);
02001   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);  
02002   _dbus_return_val_if_error_is_set (error, NULL);
02003   
02004   if (!dbus_connection_send (connection, message, &client_serial))
02005     {
02006       _DBUS_SET_OOM (error);
02007       return NULL;
02008     }
02009 
02010   reply = _dbus_connection_block_for_reply (connection,
02011                                             client_serial,
02012                                             timeout_milliseconds);
02013   
02014   if (reply == NULL)
02015     {
02016       if (dbus_connection_get_is_connected (connection))
02017         dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
02018       else
02019         dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
02020 
02021       return NULL;
02022     }
02023   else if (dbus_set_error_from_message (error, reply))
02024     {
02025       dbus_message_unref (reply);
02026       return NULL;
02027     }
02028   else
02029     return reply;
02030 }
02031 
02037 void
02038 dbus_connection_flush (DBusConnection *connection)
02039 {
02040   /* We have to specify DBUS_ITERATION_DO_READING here because
02041    * otherwise we could have two apps deadlock if they are both doing
02042    * a flush(), and the kernel buffers fill up. This could change the
02043    * dispatch status.
02044    */
02045   DBusDispatchStatus status;
02046 
02047   _dbus_return_if_fail (connection != NULL);
02048   
02049   CONNECTION_LOCK (connection);
02050   while (connection->n_outgoing > 0 &&
02051          _dbus_connection_get_is_connected_unlocked (connection))
02052     _dbus_connection_do_iteration (connection,
02053                                    DBUS_ITERATION_DO_READING |
02054                                    DBUS_ITERATION_DO_WRITING |
02055                                    DBUS_ITERATION_BLOCK,
02056                                    -1);
02057 
02058   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02059 
02060   /* Unlocks and calls out to user code */
02061   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02062 }
02063 
02064 /* Call with mutex held. Will drop it while waiting and re-acquire
02065  * before returning
02066  */
02067 static void
02068 _dbus_connection_wait_for_borrowed (DBusConnection *connection)
02069 {
02070   _dbus_assert (connection->message_borrowed != NULL);
02071 
02072   while (connection->message_borrowed != NULL)
02073     dbus_condvar_wait (connection->message_returned_cond, connection->mutex);
02074 }
02075 
02090 DBusMessage*
02091 dbus_connection_borrow_message  (DBusConnection *connection)
02092 {
02093   DBusMessage *message;
02094   DBusDispatchStatus status;
02095 
02096   _dbus_return_val_if_fail (connection != NULL, NULL);
02097   /* can't borrow during dispatch */
02098   _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL);
02099   
02100   /* this is called for the side effect that it queues
02101    * up any messages from the transport
02102    */
02103   status = dbus_connection_get_dispatch_status (connection);
02104   if (status != DBUS_DISPATCH_DATA_REMAINS)
02105     return NULL;
02106   
02107   CONNECTION_LOCK (connection);
02108 
02109   if (connection->message_borrowed != NULL)
02110     _dbus_connection_wait_for_borrowed (connection);
02111   
02112   message = _dbus_list_get_first (&connection->incoming_messages);
02113 
02114   if (message) 
02115     connection->message_borrowed = message;
02116   
02117   CONNECTION_UNLOCK (connection);
02118   return message;
02119 }
02120 
02128 void
02129 dbus_connection_return_message (DBusConnection *connection,
02130                                 DBusMessage    *message)
02131 {
02132   _dbus_return_if_fail (connection != NULL);
02133   _dbus_return_if_fail (message != NULL);
02134   /* can't borrow during dispatch */
02135   _dbus_return_if_fail (!connection->dispatch_acquired);
02136   
02137   CONNECTION_LOCK (connection);
02138   
02139   _dbus_assert (message == connection->message_borrowed);
02140   
02141   connection->message_borrowed = NULL;
02142   dbus_condvar_wake_all (connection->message_returned_cond);
02143   
02144   CONNECTION_UNLOCK (connection);
02145 }
02146 
02156 void
02157 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02158                                         DBusMessage    *message)
02159 {
02160   DBusMessage *pop_message;
02161 
02162   _dbus_return_if_fail (connection != NULL);
02163   _dbus_return_if_fail (message != NULL);
02164   /* can't borrow during dispatch */
02165   _dbus_return_if_fail (!connection->dispatch_acquired);
02166   
02167   CONNECTION_LOCK (connection);
02168  
02169   _dbus_assert (message == connection->message_borrowed);
02170 
02171   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
02172   _dbus_assert (message == pop_message);
02173   
02174   connection->n_incoming -= 1;
02175  
02176   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
02177                  message, connection->n_incoming);
02178  
02179   connection->message_borrowed = NULL;
02180   dbus_condvar_wake_all (connection->message_returned_cond);
02181   
02182   CONNECTION_UNLOCK (connection);
02183 }
02184 
02185 /* See dbus_connection_pop_message, but requires the caller to own
02186  * the lock before calling. May drop the lock while running.
02187  */
02188 static DBusList*
02189 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
02190 {
02191   if (connection->message_borrowed != NULL)
02192     _dbus_connection_wait_for_borrowed (connection);
02193   
02194   if (connection->n_incoming > 0)
02195     {
02196       DBusList *link;
02197 
02198       link = _dbus_list_pop_first_link (&connection->incoming_messages);
02199       connection->n_incoming -= 1;
02200 
02201       _dbus_verbose ("Message %p (%d %s '%s') removed from incoming queue %p, %d incoming\n",
02202                      link->data,
02203                      dbus_message_get_type (link->data),
02204                      dbus_message_get_interface (link->data) ?
02205                      dbus_message_get_interface (link->data) :
02206                      "no interface",
02207                      dbus_message_get_signature (link->data),
02208                      connection, connection->n_incoming);
02209 
02210       return link;
02211     }
02212   else
02213     return NULL;
02214 }
02215 
02216 /* See dbus_connection_pop_message, but requires the caller to own
02217  * the lock before calling. May drop the lock while running.
02218  */
02219 static DBusMessage*
02220 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
02221 {
02222   DBusList *link;
02223   
02224   link = _dbus_connection_pop_message_link_unlocked (connection);
02225 
02226   if (link != NULL)
02227     {
02228       DBusMessage *message;
02229       
02230       message = link->data;
02231       
02232       _dbus_list_free_link (link);
02233       
02234       return message;
02235     }
02236   else
02237     return NULL;
02238 }
02239 
02240 static void
02241 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
02242                                                 DBusList       *message_link)
02243 {
02244   _dbus_assert (message_link != NULL);
02245   /* You can't borrow a message while a link is outstanding */
02246   _dbus_assert (connection->message_borrowed == NULL);
02247 
02248   _dbus_list_prepend_link (&connection->incoming_messages,
02249                            message_link);
02250   connection->n_incoming += 1;
02251 
02252   _dbus_verbose ("Message %p (%d %s '%s') put back into queue %p, %d incoming\n",
02253                  message_link->data,
02254                  dbus_message_get_type (message_link->data),
02255                  dbus_message_get_interface (message_link->data) ?
02256                  dbus_message_get_interface (message_link->data) :
02257                  "no interface",
02258                  dbus_message_get_signature (message_link->data),
02259                  connection, connection->n_incoming);
02260 }
02261 
02276 DBusMessage*
02277 dbus_connection_pop_message (DBusConnection *connection)
02278 {
02279   DBusMessage *message;
02280   DBusDispatchStatus status;
02281 
02282   /* this is called for the side effect that it queues
02283    * up any messages from the transport
02284    */
02285   status = dbus_connection_get_dispatch_status (connection);
02286   if (status != DBUS_DISPATCH_DATA_REMAINS)
02287     return NULL;
02288   
02289   CONNECTION_LOCK (connection);
02290 
02291   message = _dbus_connection_pop_message_unlocked (connection);
02292 
02293   _dbus_verbose ("Returning popped message %p\n", message);    
02294   
02295   CONNECTION_UNLOCK (connection);
02296   
02297   return message;
02298 }
02299 
02308 static void
02309 _dbus_connection_acquire_dispatch (DBusConnection *connection)
02310 {
02311   if (connection->dispatch_acquired)
02312     dbus_condvar_wait (connection->dispatch_cond, connection->mutex);
02313   _dbus_assert (!connection->dispatch_acquired);
02314 
02315   connection->dispatch_acquired = TRUE;
02316 }
02317 
02325 static void
02326 _dbus_connection_release_dispatch (DBusConnection *connection)
02327 {
02328   _dbus_assert (connection->dispatch_acquired);
02329 
02330   connection->dispatch_acquired = FALSE;
02331   dbus_condvar_wake_one (connection->dispatch_cond);
02332 }
02333 
02334 static void
02335 _dbus_connection_failed_pop (DBusConnection *connection,
02336                              DBusList       *message_link)
02337 {
02338   _dbus_list_prepend_link (&connection->incoming_messages,
02339                            message_link);
02340   connection->n_incoming += 1;
02341 }
02342 
02343 static DBusDispatchStatus
02344 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
02345 {
02346   if (connection->n_incoming > 0)
02347     return DBUS_DISPATCH_DATA_REMAINS;
02348   else if (!_dbus_transport_queue_messages (connection->transport))
02349     return DBUS_DISPATCH_NEED_MEMORY;
02350   else
02351     {
02352       DBusDispatchStatus status;
02353       
02354       status = _dbus_transport_get_dispatch_status (connection->transport);
02355 
02356       if (status == DBUS_DISPATCH_COMPLETE &&
02357           connection->disconnect_message_link &&
02358           !_dbus_transport_get_is_connected (connection->transport))
02359         {
02360           /* We haven't sent the disconnect message already,
02361            * and all real messages have been queued up.
02362            */
02363           _dbus_connection_queue_synthesized_message_link (connection,
02364                                                            connection->disconnect_message_link);
02365           connection->disconnect_message_link = NULL;
02366         }
02367       
02368       if (status != DBUS_DISPATCH_COMPLETE)
02369         return status;
02370       else if (connection->n_incoming > 0)
02371         return DBUS_DISPATCH_DATA_REMAINS;
02372       else
02373         return DBUS_DISPATCH_COMPLETE;
02374     }
02375 }
02376 
02377 static void
02378 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
02379                                                     DBusDispatchStatus new_status)
02380 {
02381   dbus_bool_t changed;
02382   DBusDispatchStatusFunction function;
02383   void *data;
02384 
02385   /* We have the lock */
02386 
02387   _dbus_connection_ref_unlocked (connection);
02388 
02389   changed = new_status != connection->last_dispatch_status;
02390 
02391   connection->last_dispatch_status = new_status;
02392 
02393   function = connection->dispatch_status_function;
02394   data = connection->dispatch_status_data;
02395 
02396   /* We drop the lock */
02397   CONNECTION_UNLOCK (connection);
02398   
02399   if (changed && function)
02400     {
02401       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
02402                      connection, new_status,
02403                      new_status == DBUS_DISPATCH_COMPLETE ? "complete" :
02404                      new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" :
02405                      new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :
02406                      "???");
02407       (* function) (connection, new_status, data);      
02408     }
02409   
02410   dbus_connection_unref (connection);
02411 }
02412 
02421 DBusDispatchStatus
02422 dbus_connection_get_dispatch_status (DBusConnection *connection)
02423 {
02424   DBusDispatchStatus status;
02425 
02426   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02427   
02428   CONNECTION_LOCK (connection);
02429 
02430   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02431   
02432   CONNECTION_UNLOCK (connection);
02433 
02434   return status;
02435 }
02436 
02464 DBusDispatchStatus
02465 dbus_connection_dispatch (DBusConnection *connection)
02466 {
02467   DBusMessage *message;
02468   DBusList *link, *filter_list_copy, *message_link;
02469   DBusHandlerResult result;
02470   DBusPendingCall *pending;
02471   dbus_int32_t reply_serial;
02472   DBusDispatchStatus status;
02473 
02474   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
02475 
02476   CONNECTION_LOCK (connection);
02477   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02478   if (status != DBUS_DISPATCH_DATA_REMAINS)
02479     {
02480       /* unlocks and calls out to user code */
02481       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02482       return status;
02483     }
02484   
02485   /* We need to ref the connection since the callback could potentially
02486    * drop the last ref to it
02487    */
02488   _dbus_connection_ref_unlocked (connection);
02489 
02490   _dbus_connection_acquire_dispatch (connection);
02491   
02492   /* This call may drop the lock during the execution (if waiting for
02493    * borrowed messages to be returned) but the order of message
02494    * dispatch if several threads call dispatch() is still
02495    * protected by the lock, since only one will get the lock, and that
02496    * one will finish the message dispatching
02497    */
02498   message_link = _dbus_connection_pop_message_link_unlocked (connection);
02499   if (message_link == NULL)
02500     {
02501       /* another thread dispatched our stuff */
02502 
02503       _dbus_connection_release_dispatch (connection);
02504 
02505       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02506 
02507       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02508       
02509       dbus_connection_unref (connection);
02510       
02511       return status;
02512     }
02513 
02514   message = message_link->data;
02515   
02516   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
02517 
02518   reply_serial = dbus_message_get_reply_serial (message);
02519   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
02520                                          reply_serial);
02521   
02522   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
02523     {
02524       _dbus_connection_release_dispatch (connection);
02525 
02526       _dbus_connection_failed_pop (connection, message_link);
02527 
02528       /* unlocks and calls user code */
02529       _dbus_connection_update_dispatch_status_and_unlock (connection,
02530                                                           DBUS_DISPATCH_NEED_MEMORY);
02531 
02532       dbus_connection_unref (connection);
02533       
02534       return DBUS_DISPATCH_NEED_MEMORY;
02535     }
02536   
02537   _dbus_list_foreach (&filter_list_copy,
02538                       (DBusForeachFunction)_dbus_message_filter_ref,
02539                       NULL);
02540 
02541   /* We're still protected from dispatch() reentrancy here
02542    * since we acquired the dispatcher
02543    */
02544   CONNECTION_UNLOCK (connection);
02545   
02546   link = _dbus_list_get_first_link (&filter_list_copy);
02547   while (link != NULL)
02548     {
02549       DBusMessageFilter *filter = link->data;
02550       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
02551 
02552       _dbus_verbose ("  running filter on message %p\n", message);
02553       result = (* filter->function) (connection, message, filter->user_data);
02554 
02555       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02556         break;
02557 
02558       link = next;
02559     }
02560 
02561   _dbus_list_foreach (&filter_list_copy,
02562                       (DBusForeachFunction)_dbus_message_filter_unref,
02563                       NULL);
02564   _dbus_list_clear (&filter_list_copy);
02565   
02566   CONNECTION_LOCK (connection);
02567 
02568   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02569     goto out;
02570   
02571   /* Did a reply we were waiting on get filtered? */
02572   if (pending && result == DBUS_HANDLER_RESULT_HANDLED)
02573     {
02574       /* Queue the timeout immediately! */
02575       if (pending->timeout_link)
02576         {
02577           _dbus_connection_queue_synthesized_message_link (connection,
02578                                                            pending->timeout_link);
02579           pending->timeout_link = NULL;
02580         }
02581       else
02582         {
02583           /* We already queued the timeout? Then it was filtered! */
02584           _dbus_warn ("The timeout error with reply serial %d was filtered, so the DBusPendingCall will never stop pending.\n", reply_serial);
02585         }
02586     }
02587   
02588   if (result == DBUS_HANDLER_RESULT_HANDLED)
02589     goto out;
02590   
02591   if (pending)
02592     {
02593       _dbus_pending_call_complete_and_unlock (pending, message);
02594 
02595       pending = NULL;
02596       
02597       CONNECTION_LOCK (connection);
02598       goto out;
02599     }
02600 
02601   /* We're still protected from dispatch() reentrancy here
02602    * since we acquired the dispatcher
02603    */
02604   _dbus_verbose ("  running object path dispatch on message %p (%d %s '%s')\n",
02605                  message,
02606                  dbus_message_get_type (message),
02607                  dbus_message_get_interface (message) ?
02608                  dbus_message_get_interface (message) :
02609                  "no interface",
02610                  dbus_message_get_signature (message));
02611   
02612   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
02613                                                   message);
02614   
02615   CONNECTION_LOCK (connection);
02616 
02617   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
02618     goto out;
02619 
02620   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
02621     {
02622       DBusMessage *reply;
02623       DBusString str;
02624       DBusPreallocatedSend *preallocated;
02625 
02626       _dbus_verbose ("  sending error %s\n",
02627                      DBUS_ERROR_UNKNOWN_METHOD);
02628       
02629       if (!_dbus_string_init (&str))
02630         {
02631           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02632           goto out;
02633         }
02634               
02635       if (!_dbus_string_append_printf (&str,
02636                                        "Method \"%s\" on interface \"%s\" doesn't exist\n",
02637                                        dbus_message_get_member (message),
02638                                        dbus_message_get_interface (message)))
02639         {
02640           _dbus_string_free (&str);
02641           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02642           goto out;
02643         }
02644       
02645       reply = dbus_message_new_error (message,
02646                                       DBUS_ERROR_UNKNOWN_METHOD,
02647                                       _dbus_string_get_const_data (&str));
02648       _dbus_string_free (&str);
02649 
02650       if (reply == NULL)
02651         {
02652           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02653           goto out;
02654         }
02655       
02656       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02657 
02658       if (preallocated == NULL)
02659         {
02660           dbus_message_unref (reply);
02661           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
02662           goto out;
02663         }
02664 
02665       _dbus_connection_send_preallocated_unlocked (connection, preallocated,
02666                                                    reply, NULL);
02667 
02668       dbus_message_unref (reply);
02669       
02670       result = DBUS_HANDLER_RESULT_HANDLED;
02671     }
02672   
02673   _dbus_verbose ("  done dispatching %p (%d %s '%s') on connection %p\n", message,
02674                  dbus_message_get_type (message),
02675                  dbus_message_get_interface (message) ?
02676                  dbus_message_get_interface (message) :
02677                  "no interface",
02678                  dbus_message_get_signature (message),
02679                  connection);
02680   
02681  out:
02682   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
02683     {
02684       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
02685       
02686       /* Put message back, and we'll start over.
02687        * Yes this means handlers must be idempotent if they
02688        * don't return HANDLED; c'est la vie.
02689        */
02690       _dbus_connection_putback_message_link_unlocked (connection,
02691                                                       message_link);
02692     }
02693   else
02694     {
02695       _dbus_verbose ("Done with message in %s\n", _DBUS_FUNCTION_NAME);
02696       
02697       if (connection->exit_on_disconnect &&
02698           dbus_message_is_signal (message,
02699                                   DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
02700                                   "Disconnected"))
02701         {
02702           _dbus_verbose ("Exiting on Disconnected signal\n");
02703           CONNECTION_UNLOCK (connection);
02704           _dbus_exit (1);
02705           _dbus_assert_not_reached ("Call to exit() returned");
02706         }
02707       
02708       _dbus_list_free_link (message_link);
02709       dbus_message_unref (message); /* don't want the message to count in max message limits
02710                                      * in computing dispatch status below
02711                                      */
02712     }
02713   
02714   _dbus_connection_release_dispatch (connection);
02715   
02716   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02717 
02718   /* unlocks and calls user code */
02719   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02720   
02721   dbus_connection_unref (connection);
02722   
02723   return status;
02724 }
02725 
02784 dbus_bool_t
02785 dbus_connection_set_watch_functions (DBusConnection              *connection,
02786                                      DBusAddWatchFunction         add_function,
02787                                      DBusRemoveWatchFunction      remove_function,
02788                                      DBusWatchToggledFunction     toggled_function,
02789                                      void                        *data,
02790                                      DBusFreeFunction             free_data_function)
02791 {
02792   dbus_bool_t retval;
02793 
02794   _dbus_return_val_if_fail (connection != NULL, FALSE);
02795   
02796   CONNECTION_LOCK (connection);
02797   /* ref connection for slightly better reentrancy */
02798   _dbus_connection_ref_unlocked (connection);
02799 
02800   /* FIXME this can call back into user code, and we need to drop the
02801    * connection lock when it does.
02802    */
02803   retval = _dbus_watch_list_set_functions (connection->watches,
02804                                            add_function, remove_function,
02805                                            toggled_function,
02806                                            data, free_data_function);
02807   
02808   CONNECTION_UNLOCK (connection);
02809   /* drop our paranoid refcount */
02810   dbus_connection_unref (connection);
02811 
02812   return retval;
02813 }
02814 
02848 dbus_bool_t
02849 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
02850                                          DBusAddTimeoutFunction     add_function,
02851                                          DBusRemoveTimeoutFunction  remove_function,
02852                                          DBusTimeoutToggledFunction toggled_function,
02853                                          void                      *data,
02854                                          DBusFreeFunction           free_data_function)
02855 {
02856   dbus_bool_t retval;
02857 
02858   _dbus_return_val_if_fail (connection != NULL, FALSE);
02859   
02860   CONNECTION_LOCK (connection);
02861   /* ref connection for slightly better reentrancy */
02862   _dbus_connection_ref_unlocked (connection);
02863   
02864   retval = _dbus_timeout_list_set_functions (connection->timeouts,
02865                                              add_function, remove_function,
02866                                              toggled_function,
02867                                              data, free_data_function);
02868   
02869   CONNECTION_UNLOCK (connection);
02870   /* drop our paranoid refcount */
02871   dbus_connection_unref (connection);
02872 
02873   return retval;
02874 }
02875 
02890 void
02891 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
02892                                           DBusWakeupMainFunction     wakeup_main_function,
02893                                           void                      *data,
02894                                           DBusFreeFunction           free_data_function)
02895 {
02896   void *old_data;
02897   DBusFreeFunction old_free_data;
02898 
02899   _dbus_return_if_fail (connection != NULL);
02900   
02901   CONNECTION_LOCK (connection);
02902   old_data = connection->wakeup_main_data;
02903   old_free_data = connection->free_wakeup_main_data;
02904 
02905   connection->wakeup_main_function = wakeup_main_function;
02906   connection->wakeup_main_data = data;
02907   connection->free_wakeup_main_data = free_data_function;
02908   
02909   CONNECTION_UNLOCK (connection);
02910 
02911   /* Callback outside the lock */
02912   if (old_free_data)
02913     (*old_free_data) (old_data);
02914 }
02915 
02932 void
02933 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
02934                                               DBusDispatchStatusFunction  function,
02935                                               void                       *data,
02936                                               DBusFreeFunction            free_data_function)
02937 {
02938   void *old_data;
02939   DBusFreeFunction old_free_data;
02940 
02941   _dbus_return_if_fail (connection != NULL);
02942   
02943   CONNECTION_LOCK (connection);
02944   old_data = connection->dispatch_status_data;
02945   old_free_data = connection->free_dispatch_status_data;
02946 
02947   connection->dispatch_status_function = function;
02948   connection->dispatch_status_data = data;
02949   connection->free_dispatch_status_data = free_data_function;
02950   
02951   CONNECTION_UNLOCK (connection);
02952 
02953   /* Callback outside the lock */
02954   if (old_free_data)
02955     (*old_free_data) (old_data);
02956 }
02957 
02969 dbus_bool_t
02970 dbus_connection_get_unix_user (DBusConnection *connection,
02971                                unsigned long  *uid)
02972 {
02973   dbus_bool_t result;
02974 
02975   _dbus_return_val_if_fail (connection != NULL, FALSE);
02976   _dbus_return_val_if_fail (uid != NULL, FALSE);
02977   
02978   CONNECTION_LOCK (connection);
02979 
02980   if (!_dbus_transport_get_is_authenticated (connection->transport))
02981     result = FALSE;
02982   else
02983     result = _dbus_transport_get_unix_user (connection->transport,
02984                                             uid);
02985   CONNECTION_UNLOCK (connection);
02986 
02987   return result;
02988 }
02989 
03006 void
03007 dbus_connection_set_unix_user_function (DBusConnection             *connection,
03008                                         DBusAllowUnixUserFunction   function,
03009                                         void                       *data,
03010                                         DBusFreeFunction            free_data_function)
03011 {
03012   void *old_data = NULL;
03013   DBusFreeFunction old_free_function = NULL;
03014 
03015   _dbus_return_if_fail (connection != NULL);
03016   
03017   CONNECTION_LOCK (connection);
03018   _dbus_transport_set_unix_user_function (connection->transport,
03019                                           function, data, free_data_function,
03020                                           &old_data, &old_free_function);
03021   CONNECTION_UNLOCK (connection);
03022 
03023   if (old_free_function != NULL)
03024     (* old_free_function) (old_data);    
03025 }
03026 
03048 dbus_bool_t
03049 dbus_connection_add_filter (DBusConnection            *connection,
03050                             DBusHandleMessageFunction  function,
03051                             void                      *user_data,
03052                             DBusFreeFunction           free_data_function)
03053 {
03054   DBusMessageFilter *filter;
03055   
03056   _dbus_return_val_if_fail (connection != NULL, FALSE);
03057   _dbus_return_val_if_fail (function != NULL, FALSE);
03058 
03059   filter = dbus_new0 (DBusMessageFilter, 1);
03060   if (filter == NULL)
03061     return FALSE;
03062 
03063   filter->refcount.value = 1;
03064   
03065   CONNECTION_LOCK (connection);
03066 
03067   if (!_dbus_list_append (&connection->filter_list,
03068                           filter))
03069     {
03070       _dbus_message_filter_unref (filter);
03071       CONNECTION_UNLOCK (connection);
03072       return FALSE;
03073     }
03074 
03075   /* Fill in filter after all memory allocated,
03076    * so we don't run the free_user_data_function
03077    * if the add_filter() fails
03078    */
03079   
03080   filter->function = function;
03081   filter->user_data = user_data;
03082   filter->free_user_data_function = free_data_function;
03083         
03084   CONNECTION_UNLOCK (connection);
03085   return TRUE;
03086 }
03087 
03100 void
03101 dbus_connection_remove_filter (DBusConnection            *connection,
03102                                DBusHandleMessageFunction  function,
03103                                void                      *user_data)
03104 {
03105   DBusList *link;
03106   DBusMessageFilter *filter;
03107   
03108   _dbus_return_if_fail (connection != NULL);
03109   _dbus_return_if_fail (function != NULL);
03110   
03111   CONNECTION_LOCK (connection);
03112 
03113   filter = NULL;
03114   
03115   link = _dbus_list_get_last_link (&connection->filter_list);
03116   while (link != NULL)
03117     {
03118       filter = link->data;
03119 
03120       if (filter->function == function &&
03121           filter->user_data == user_data)
03122         {
03123           _dbus_list_remove_link (&connection->filter_list, link);
03124           filter->function = NULL;
03125           
03126           break;
03127         }
03128         
03129       link = _dbus_list_get_prev_link (&connection->filter_list, link);
03130     }
03131   
03132   CONNECTION_UNLOCK (connection);
03133 
03134 #ifndef DBUS_DISABLE_CHECKS
03135   if (filter == NULL)
03136     {
03137       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
03138                   function, user_data);
03139       return;
03140     }
03141 #endif
03142   
03143   /* Call application code */
03144   if (filter->free_user_data_function)
03145     (* filter->free_user_data_function) (filter->user_data);
03146 
03147   filter->free_user_data_function = NULL;
03148   filter->user_data = NULL;
03149   
03150   _dbus_message_filter_unref (filter);
03151 }
03152 
03164 dbus_bool_t
03165 dbus_connection_register_object_path (DBusConnection              *connection,
03166                                       const char                 **path,
03167                                       const DBusObjectPathVTable  *vtable,
03168                                       void                        *user_data)
03169 {
03170   dbus_bool_t retval;
03171   
03172   _dbus_return_val_if_fail (connection != NULL, FALSE);
03173   _dbus_return_val_if_fail (path != NULL, FALSE);
03174   _dbus_return_val_if_fail (path[0] != NULL, FALSE);
03175   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03176 
03177   CONNECTION_LOCK (connection);
03178 
03179   retval = _dbus_object_tree_register (connection->objects,
03180                                        FALSE,
03181                                        path, vtable,
03182                                        user_data);
03183 
03184   CONNECTION_UNLOCK (connection);
03185 
03186   return retval;
03187 }
03188 
03201 dbus_bool_t
03202 dbus_connection_register_fallback (DBusConnection              *connection,
03203                                    const char                 **path,
03204                                    const DBusObjectPathVTable  *vtable,
03205                                    void                        *user_data)
03206 {
03207   dbus_bool_t retval;
03208   
03209   _dbus_return_val_if_fail (connection != NULL, FALSE);
03210   _dbus_return_val_if_fail (path != NULL, FALSE);
03211   _dbus_return_val_if_fail (path[0] != NULL, FALSE);
03212   _dbus_return_val_if_fail (vtable != NULL, FALSE);
03213 
03214   CONNECTION_LOCK (connection);
03215 
03216   retval = _dbus_object_tree_register (connection->objects,
03217                                        TRUE,
03218                                        path, vtable,
03219                                        user_data);
03220 
03221   CONNECTION_UNLOCK (connection);
03222 
03223   return retval;
03224 }
03225 
03234 void
03235 dbus_connection_unregister_object_path (DBusConnection              *connection,
03236                                         const char                 **path)
03237 {
03238   _dbus_return_if_fail (connection != NULL);
03239   _dbus_return_if_fail (path != NULL);
03240   _dbus_return_if_fail (path[0] != NULL);
03241 
03242   CONNECTION_LOCK (connection);
03243 
03244   return _dbus_object_tree_unregister_and_unlock (connection->objects,
03245                                                   path);
03246 }
03247 
03258 dbus_bool_t
03259 dbus_connection_list_registered (DBusConnection              *connection,
03260                                  const char                 **parent_path,
03261                                  char                      ***child_entries)
03262 {
03263   _dbus_return_val_if_fail (connection != NULL, FALSE);
03264   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
03265   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
03266 
03267   CONNECTION_LOCK (connection);
03268 
03269   return _dbus_object_tree_list_registered_and_unlock (connection->objects,
03270                                                        parent_path,
03271                                                        child_entries);
03272 }
03273 
03274 static DBusDataSlotAllocator slot_allocator;
03275 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
03276 
03291 dbus_bool_t
03292 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
03293 {
03294   return _dbus_data_slot_allocator_alloc (&slot_allocator,
03295                                           _DBUS_LOCK_NAME (connection_slots),
03296                                           slot_p);
03297 }
03298 
03310 void
03311 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
03312 {
03313   _dbus_return_if_fail (*slot_p >= 0);
03314   
03315   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
03316 }
03317 
03331 dbus_bool_t
03332 dbus_connection_set_data (DBusConnection   *connection,
03333                           dbus_int32_t      slot,
03334                           void             *data,
03335                           DBusFreeFunction  free_data_func)
03336 {
03337   DBusFreeFunction old_free_func;
03338   void *old_data;
03339   dbus_bool_t retval;
03340 
03341   _dbus_return_val_if_fail (connection != NULL, FALSE);
03342   _dbus_return_val_if_fail (slot >= 0, FALSE);
03343   
03344   CONNECTION_LOCK (connection);
03345 
03346   retval = _dbus_data_slot_list_set (&slot_allocator,
03347                                      &connection->slot_list,
03348                                      slot, data, free_data_func,
03349                                      &old_free_func, &old_data);
03350   
03351   CONNECTION_UNLOCK (connection);
03352 
03353   if (retval)
03354     {
03355       /* Do the actual free outside the connection lock */
03356       if (old_free_func)
03357         (* old_free_func) (old_data);
03358     }
03359 
03360   return retval;
03361 }
03362 
03371 void*
03372 dbus_connection_get_data (DBusConnection   *connection,
03373                           dbus_int32_t      slot)
03374 {
03375   void *res;
03376 
03377   _dbus_return_val_if_fail (connection != NULL, NULL);
03378   
03379   CONNECTION_LOCK (connection);
03380 
03381   res = _dbus_data_slot_list_get (&slot_allocator,
03382                                   &connection->slot_list,
03383                                   slot);
03384   
03385   CONNECTION_UNLOCK (connection);
03386 
03387   return res;
03388 }
03389 
03396 void
03397 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
03398 {  
03399   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
03400 }
03401 
03410 void
03411 dbus_connection_set_max_message_size (DBusConnection *connection,
03412                                       long            size)
03413 {
03414   _dbus_return_if_fail (connection != NULL);
03415   
03416   CONNECTION_LOCK (connection);
03417   _dbus_transport_set_max_message_size (connection->transport,
03418                                         size);
03419   CONNECTION_UNLOCK (connection);
03420 }
03421 
03428 long
03429 dbus_connection_get_max_message_size (DBusConnection *connection)
03430 {
03431   long res;
03432 
03433   _dbus_return_val_if_fail (connection != NULL, 0);
03434   
03435   CONNECTION_LOCK (connection);
03436   res = _dbus_transport_get_max_message_size (connection->transport);
03437   CONNECTION_UNLOCK (connection);
03438   return res;
03439 }
03440 
03466 void
03467 dbus_connection_set_max_received_size (DBusConnection *connection,
03468                                        long            size)
03469 {
03470   _dbus_return_if_fail (connection != NULL);
03471   
03472   CONNECTION_LOCK (connection);
03473   _dbus_transport_set_max_received_size (connection->transport,
03474                                          size);
03475   CONNECTION_UNLOCK (connection);
03476 }
03477 
03484 long
03485 dbus_connection_get_max_received_size (DBusConnection *connection)
03486 {
03487   long res;
03488 
03489   _dbus_return_val_if_fail (connection != NULL, 0);
03490   
03491   CONNECTION_LOCK (connection);
03492   res = _dbus_transport_get_max_received_size (connection->transport);
03493   CONNECTION_UNLOCK (connection);
03494   return res;
03495 }
03496 
03507 long
03508 dbus_connection_get_outgoing_size (DBusConnection *connection)
03509 {
03510   long res;
03511 
03512   _dbus_return_val_if_fail (connection != NULL, 0);
03513   
03514   CONNECTION_LOCK (connection);
03515   res = _dbus_counter_get_value (connection->outgoing_counter);
03516   CONNECTION_UNLOCK (connection);
03517   return res;
03518 }
03519 

Generated on Sun Mar 21 03:52:04 2004 for D-BUS by doxygen 1.3.6-20040222