dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
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-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-list.h"
00033 #include "dbus-hash.h"
00034 #include "dbus-message-internal.h"
00035 #include "dbus-threads.h"
00036 #include "dbus-protocol.h"
00037 #include "dbus-dataslot.h"
00038 #include "dbus-string.h"
00039 #include "dbus-pending-call.h"
00040 #include "dbus-object-tree.h"
00041 #include "dbus-threads-internal.h"
00042 
00043 #ifdef DBUS_DISABLE_CHECKS
00044 #define TOOK_LOCK_CHECK(connection)
00045 #define RELEASING_LOCK_CHECK(connection)
00046 #define HAVE_LOCK_CHECK(connection)
00047 #else
00048 #define TOOK_LOCK_CHECK(connection) do {                \
00049     _dbus_assert (!(connection)->have_connection_lock); \
00050     (connection)->have_connection_lock = TRUE;          \
00051   } while (0)
00052 #define RELEASING_LOCK_CHECK(connection) do {            \
00053     _dbus_assert ((connection)->have_connection_lock);   \
00054     (connection)->have_connection_lock = FALSE;          \
00055   } while (0)
00056 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00057 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00058 #endif
00059 
00060 #define TRACE_LOCKS 1
00061 
00062 #define CONNECTION_LOCK(connection)   do {                                      \
00063     if (TRACE_LOCKS) { _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME); }   \
00064     _dbus_mutex_lock ((connection)->mutex);                                      \
00065     TOOK_LOCK_CHECK (connection);                                               \
00066   } while (0)
00067 
00068 #define CONNECTION_UNLOCK(connection) do {                                              \
00069     if (TRACE_LOCKS) { _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);  }        \
00070     RELEASING_LOCK_CHECK (connection);                                                  \
00071     _dbus_mutex_unlock ((connection)->mutex);                                            \
00072   } while (0)
00073 
00074 #define DISPATCH_STATUS_NAME(s)                                            \
00075                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00076                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00077                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00078                       "???")
00079 
00157 typedef struct DBusMessageFilter DBusMessageFilter;
00158 
00162 struct DBusMessageFilter
00163 {
00164   DBusAtomic refcount; 
00165   DBusHandleMessageFunction function; 
00166   void *user_data; 
00167   DBusFreeFunction free_user_data_function; 
00168 };
00169 
00170 
00174 struct DBusPreallocatedSend
00175 {
00176   DBusConnection *connection; 
00177   DBusList *queue_link;       
00178   DBusList *counter_link;     
00179 };
00180 
00181 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00182 
00186 struct DBusConnection
00187 {
00188   DBusAtomic refcount; 
00190   DBusMutex *mutex; 
00192   DBusMutex *dispatch_mutex;     
00193   DBusCondVar *dispatch_cond;    
00194   DBusMutex *io_path_mutex;      
00195   DBusCondVar *io_path_cond;     
00197   DBusList *outgoing_messages; 
00198   DBusList *incoming_messages; 
00200   DBusMessage *message_borrowed; 
00204   int n_outgoing;              
00205   int n_incoming;              
00207   DBusCounter *outgoing_counter; 
00209   DBusTransport *transport;    
00210   DBusWatchList *watches;      
00211   DBusTimeoutList *timeouts;   
00213   DBusList *filter_list;        
00215   DBusDataSlotList slot_list;   
00217   DBusHashTable *pending_replies;  
00219   dbus_uint32_t client_serial;       
00220   DBusList *disconnect_message_link; 
00222   DBusWakeupMainFunction wakeup_main_function; 
00223   void *wakeup_main_data; 
00224   DBusFreeFunction free_wakeup_main_data; 
00226   DBusDispatchStatusFunction dispatch_status_function; 
00227   void *dispatch_status_data; 
00228   DBusFreeFunction free_dispatch_status_data; 
00230   DBusDispatchStatus last_dispatch_status; 
00232   DBusList *link_cache; 
00235   DBusObjectTree *objects; 
00237   char *server_guid; 
00239   unsigned int shareable : 1; 
00241   unsigned int dispatch_acquired : 1; 
00242   unsigned int io_path_acquired : 1;  
00244   unsigned int exit_on_disconnect : 1; 
00246 #ifndef DBUS_DISABLE_CHECKS
00247   unsigned int have_connection_lock : 1; 
00248 #endif
00249   
00250 #ifndef DBUS_DISABLE_CHECKS
00251   int generation; 
00252 #endif 
00253 };
00254 
00255 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00256 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00257                                                                               DBusDispatchStatus  new_status);
00258 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00259 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00260 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00261 
00262 static DBusMessageFilter *
00263 _dbus_message_filter_ref (DBusMessageFilter *filter)
00264 {
00265   _dbus_assert (filter->refcount.value > 0);
00266   _dbus_atomic_inc (&filter->refcount);
00267 
00268   return filter;
00269 }
00270 
00271 static void
00272 _dbus_message_filter_unref (DBusMessageFilter *filter)
00273 {
00274   _dbus_assert (filter->refcount.value > 0);
00275 
00276   if (_dbus_atomic_dec (&filter->refcount) == 1)
00277     {
00278       if (filter->free_user_data_function)
00279         (* filter->free_user_data_function) (filter->user_data);
00280       
00281       dbus_free (filter);
00282     }
00283 }
00284 
00290 void
00291 _dbus_connection_lock (DBusConnection *connection)
00292 {
00293   CONNECTION_LOCK (connection);
00294 }
00295 
00301 void
00302 _dbus_connection_unlock (DBusConnection *connection)
00303 {
00304   CONNECTION_UNLOCK (connection);
00305 }
00306 
00314 static void
00315 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00316 {
00317   if (connection->wakeup_main_function)
00318     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00319 }
00320 
00321 #ifdef DBUS_BUILD_TESTS
00322 /* For now this function isn't used */
00332 dbus_bool_t
00333 _dbus_connection_queue_received_message (DBusConnection *connection,
00334                                          DBusMessage    *message)
00335 {
00336   DBusList *link;
00337 
00338   link = _dbus_list_alloc_link (message);
00339   if (link == NULL)
00340     return FALSE;
00341 
00342   dbus_message_ref (message);
00343   _dbus_connection_queue_received_message_link (connection, link);
00344 
00345   return TRUE;
00346 }
00347 #endif
00348 
00357 void
00358 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00359                                               DBusList        *link)
00360 {
00361   DBusPendingCall *pending;
00362   dbus_int32_t reply_serial;
00363   DBusMessage *message;
00364   
00365   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00366   
00367   _dbus_list_append_link (&connection->incoming_messages,
00368                           link);
00369   message = link->data;
00370 
00371   /* If this is a reply we're waiting on, remove timeout for it */
00372   reply_serial = dbus_message_get_reply_serial (message);
00373   if (reply_serial != -1)
00374     {
00375       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00376                                              reply_serial);
00377       if (pending != NULL)
00378         {
00379           if (pending->timeout_added)
00380             _dbus_connection_remove_timeout_unlocked (connection,
00381                                                       pending->timeout);
00382 
00383           pending->timeout_added = FALSE;
00384         }
00385     }
00386   
00387   connection->n_incoming += 1;
00388 
00389   _dbus_connection_wakeup_mainloop (connection);
00390   
00391   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00392                  message,
00393                  dbus_message_get_type (message),
00394                  dbus_message_get_path (message) ?
00395                  dbus_message_get_path (message) :
00396                  "no path",
00397                  dbus_message_get_interface (message) ?
00398                  dbus_message_get_interface (message) :
00399                  "no interface",
00400                  dbus_message_get_member (message) ?
00401                  dbus_message_get_member (message) :
00402                  "no member",
00403                  dbus_message_get_signature (message),
00404                  dbus_message_get_reply_serial (message),
00405                  connection,
00406                  connection->n_incoming);
00407 }
00408 
00419 static void
00420 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00421                                                  DBusList *link)
00422 {
00423   HAVE_LOCK_CHECK (connection);
00424   
00425   _dbus_list_append_link (&connection->incoming_messages, link);
00426 
00427   connection->n_incoming += 1;
00428 
00429   _dbus_connection_wakeup_mainloop (connection);
00430   
00431   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00432                  link->data, connection, connection->n_incoming);
00433 }
00434 
00435 
00443 dbus_bool_t
00444 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00445 {
00446   HAVE_LOCK_CHECK (connection);
00447   return connection->outgoing_messages != NULL;
00448 }
00449 
00456 dbus_bool_t
00457 dbus_connection_has_messages_to_send (DBusConnection *connection)
00458 {
00459   dbus_bool_t v;
00460   
00461   _dbus_return_val_if_fail (connection != NULL, FALSE);
00462 
00463   CONNECTION_LOCK (connection);
00464   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00465   CONNECTION_UNLOCK (connection);
00466 
00467   return v;
00468 }
00469 
00477 DBusMessage*
00478 _dbus_connection_get_message_to_send (DBusConnection *connection)
00479 {
00480   HAVE_LOCK_CHECK (connection);
00481   
00482   return _dbus_list_get_last (&connection->outgoing_messages);
00483 }
00484 
00493 void
00494 _dbus_connection_message_sent (DBusConnection *connection,
00495                                DBusMessage    *message)
00496 {
00497   DBusList *link;
00498 
00499   HAVE_LOCK_CHECK (connection);
00500   
00501   /* This can be called before we even complete authentication, since
00502    * it's called on disconnect to clean up the outgoing queue.
00503    * It's also called as we successfully send each message.
00504    */
00505   
00506   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00507   _dbus_assert (link != NULL);
00508   _dbus_assert (link->data == message);
00509 
00510   /* Save this link in the link cache */
00511   _dbus_list_unlink (&connection->outgoing_messages,
00512                      link);
00513   _dbus_list_prepend_link (&connection->link_cache, link);
00514   
00515   connection->n_outgoing -= 1;
00516 
00517   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00518                  message,
00519                  dbus_message_get_type (message),
00520                  dbus_message_get_path (message) ?
00521                  dbus_message_get_path (message) :
00522                  "no path",
00523                  dbus_message_get_interface (message) ?
00524                  dbus_message_get_interface (message) :
00525                  "no interface",
00526                  dbus_message_get_member (message) ?
00527                  dbus_message_get_member (message) :
00528                  "no member",
00529                  dbus_message_get_signature (message),
00530                  connection, connection->n_outgoing);
00531 
00532   /* Save this link in the link cache also */
00533   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00534                                      &link);
00535   _dbus_list_prepend_link (&connection->link_cache, link);
00536   
00537   dbus_message_unref (message);
00538 }
00539 
00540 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00541                                                   DBusWatch     *watch);
00542 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00543                                                   DBusWatch     *watch);
00544 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00545                                                   DBusWatch     *watch,
00546                                                   dbus_bool_t    enabled);
00547 
00548 static dbus_bool_t
00549 protected_change_watch (DBusConnection         *connection,
00550                         DBusWatch              *watch,
00551                         DBusWatchAddFunction    add_function,
00552                         DBusWatchRemoveFunction remove_function,
00553                         DBusWatchToggleFunction toggle_function,
00554                         dbus_bool_t             enabled)
00555 {
00556   DBusWatchList *watches;
00557   dbus_bool_t retval;
00558   
00559   HAVE_LOCK_CHECK (connection);
00560 
00561   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00562    * drop lock and call out" one; but it has to be propagated up through all callers
00563    */
00564   
00565   watches = connection->watches;
00566   if (watches)
00567     {
00568       connection->watches = NULL;
00569       _dbus_connection_ref_unlocked (connection);
00570       CONNECTION_UNLOCK (connection);
00571 
00572       if (add_function)
00573         retval = (* add_function) (watches, watch);
00574       else if (remove_function)
00575         {
00576           retval = TRUE;
00577           (* remove_function) (watches, watch);
00578         }
00579       else
00580         {
00581           retval = TRUE;
00582           (* toggle_function) (watches, watch, enabled);
00583         }
00584       
00585       CONNECTION_LOCK (connection);
00586       connection->watches = watches;
00587       _dbus_connection_unref_unlocked (connection);
00588 
00589       return retval;
00590     }
00591   else
00592     return FALSE;
00593 }
00594      
00595 
00607 dbus_bool_t
00608 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00609                                      DBusWatch      *watch)
00610 {
00611   return protected_change_watch (connection, watch,
00612                                  _dbus_watch_list_add_watch,
00613                                  NULL, NULL, FALSE);
00614 }
00615 
00625 void
00626 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00627                                         DBusWatch      *watch)
00628 {
00629   protected_change_watch (connection, watch,
00630                           NULL,
00631                           _dbus_watch_list_remove_watch,
00632                           NULL, FALSE);
00633 }
00634 
00645 void
00646 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00647                                         DBusWatch      *watch,
00648                                         dbus_bool_t     enabled)
00649 {
00650   _dbus_assert (watch != NULL);
00651 
00652   protected_change_watch (connection, watch,
00653                           NULL, NULL,
00654                           _dbus_watch_list_toggle_watch,
00655                           enabled);
00656 }
00657 
00658 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00659                                                    DBusTimeout     *timeout);
00660 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00661                                                    DBusTimeout     *timeout);
00662 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00663                                                    DBusTimeout     *timeout,
00664                                                    dbus_bool_t      enabled);
00665 
00666 static dbus_bool_t
00667 protected_change_timeout (DBusConnection           *connection,
00668                           DBusTimeout              *timeout,
00669                           DBusTimeoutAddFunction    add_function,
00670                           DBusTimeoutRemoveFunction remove_function,
00671                           DBusTimeoutToggleFunction toggle_function,
00672                           dbus_bool_t               enabled)
00673 {
00674   DBusTimeoutList *timeouts;
00675   dbus_bool_t retval;
00676   
00677   HAVE_LOCK_CHECK (connection);
00678 
00679   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00680    * drop lock and call out" one; but it has to be propagated up through all callers
00681    */
00682   
00683   timeouts = connection->timeouts;
00684   if (timeouts)
00685     {
00686       connection->timeouts = NULL;
00687       _dbus_connection_ref_unlocked (connection);
00688       CONNECTION_UNLOCK (connection);
00689 
00690       if (add_function)
00691         retval = (* add_function) (timeouts, timeout);
00692       else if (remove_function)
00693         {
00694           retval = TRUE;
00695           (* remove_function) (timeouts, timeout);
00696         }
00697       else
00698         {
00699           retval = TRUE;
00700           (* toggle_function) (timeouts, timeout, enabled);
00701         }
00702       
00703       CONNECTION_LOCK (connection);
00704       connection->timeouts = timeouts;
00705       _dbus_connection_unref_unlocked (connection);
00706 
00707       return retval;
00708     }
00709   else
00710     return FALSE;
00711 }
00712 
00725 dbus_bool_t
00726 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00727                                        DBusTimeout    *timeout)
00728 {
00729   return protected_change_timeout (connection, timeout,
00730                                    _dbus_timeout_list_add_timeout,
00731                                    NULL, NULL, FALSE);
00732 }
00733 
00743 void
00744 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00745                                           DBusTimeout    *timeout)
00746 {
00747   protected_change_timeout (connection, timeout,
00748                             NULL,
00749                             _dbus_timeout_list_remove_timeout,
00750                             NULL, FALSE);
00751 }
00752 
00763 void
00764 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00765                                           DBusTimeout      *timeout,
00766                                           dbus_bool_t       enabled)
00767 {
00768   protected_change_timeout (connection, timeout,
00769                             NULL, NULL,
00770                             _dbus_timeout_list_toggle_timeout,
00771                             enabled);
00772 }
00773 
00774 static dbus_bool_t
00775 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00776                                                DBusPendingCall *pending)
00777 {
00778   HAVE_LOCK_CHECK (connection);
00779   
00780   _dbus_assert (pending->reply_serial != 0);
00781 
00782   if (!_dbus_connection_add_timeout_unlocked (connection, pending->timeout))
00783     return FALSE;
00784   
00785   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00786                                     pending->reply_serial,
00787                                     pending))
00788     {
00789       _dbus_connection_remove_timeout_unlocked (connection, pending->timeout);
00790 
00791       HAVE_LOCK_CHECK (connection);
00792       return FALSE;
00793     }
00794   
00795   pending->timeout_added = TRUE;
00796   pending->connection = connection;
00797 
00798   dbus_pending_call_ref (pending);
00799 
00800   HAVE_LOCK_CHECK (connection);
00801   
00802   return TRUE;
00803 }
00804 
00805 static void
00806 free_pending_call_on_hash_removal (void *data)
00807 {
00808   DBusPendingCall *pending;
00809   
00810   if (data == NULL)
00811     return;
00812 
00813   pending = data;
00814 
00815   if (pending->connection)
00816     {
00817       if (pending->timeout_added)
00818         {
00819           _dbus_connection_remove_timeout_unlocked (pending->connection,
00820                                                     pending->timeout);
00821           pending->timeout_added = FALSE;
00822         }
00823 
00824       pending->connection = NULL;
00825       
00826       dbus_pending_call_unref (pending);
00827     }
00828 }
00829 
00830 static void
00831 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00832                                                DBusPendingCall *pending)
00833 {
00834   /* Can't have a destroy notifier on the pending call if we're going to do this */
00835 
00836   dbus_pending_call_ref (pending);
00837   _dbus_hash_table_remove_int (connection->pending_replies,
00838                                pending->reply_serial);
00839   _dbus_assert (pending->connection == NULL);
00840   dbus_pending_call_unref (pending);
00841 }
00842 
00843 static void
00844 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00845                                                  DBusPendingCall *pending)
00846 {
00847   /* The idea here is to avoid finalizing the pending call
00848    * with the lock held, since there's a destroy notifier
00849    * in pending call that goes out to application code.
00850    */
00851   dbus_pending_call_ref (pending);
00852   _dbus_hash_table_remove_int (connection->pending_replies,
00853                                pending->reply_serial);
00854   _dbus_assert (pending->connection == NULL);
00855   CONNECTION_UNLOCK (connection);
00856   dbus_pending_call_unref (pending);
00857 }
00858 
00867 void
00868 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00869                                       DBusPendingCall *pending)
00870 {
00871   CONNECTION_LOCK (connection);
00872   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00873 }
00874 
00883 void
00884 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00885                                         DBusMessage     *message)
00886 {
00887   if (message == NULL)
00888     {
00889       message = pending->timeout_link->data;
00890       _dbus_list_clear (&pending->timeout_link);
00891     }
00892   else
00893     dbus_message_ref (message);
00894 
00895   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
00896                  message,
00897                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00898                  "method return" :
00899                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00900                  "error" : "other type",
00901                  pending->reply_serial);
00902   
00903   _dbus_assert (pending->reply == NULL);
00904   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00905   pending->reply = message;
00906   
00907   dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
00908   _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00909   
00910   /* Must be called unlocked since it invokes app callback */
00911   _dbus_pending_call_notify (pending);
00912   dbus_pending_call_unref (pending);
00913 }
00914 
00924 static dbus_bool_t
00925 _dbus_connection_acquire_io_path (DBusConnection *connection,
00926                                   int timeout_milliseconds)
00927 {
00928   dbus_bool_t we_acquired;
00929   
00930   HAVE_LOCK_CHECK (connection);
00931 
00932   /* We don't want the connection to vanish */
00933   _dbus_connection_ref_unlocked (connection);
00934 
00935   /* We will only touch io_path_acquired which is protected by our mutex */
00936   CONNECTION_UNLOCK (connection);
00937   
00938   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00939   _dbus_mutex_lock (connection->io_path_mutex);
00940 
00941   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00942                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00943 
00944   we_acquired = FALSE;
00945   
00946   if (connection->io_path_acquired)
00947     {
00948       if (timeout_milliseconds != -1)
00949         {
00950           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00951                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
00952           _dbus_condvar_wait_timeout (connection->io_path_cond,
00953                                       connection->io_path_mutex,
00954                                       timeout_milliseconds);
00955         }
00956       else
00957         {
00958           while (connection->io_path_acquired)
00959             {
00960               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00961               _dbus_condvar_wait (connection->io_path_cond, connection->io_path_mutex);
00962             }
00963         }
00964     }
00965   
00966   if (!connection->io_path_acquired)
00967     {
00968       we_acquired = TRUE;
00969       connection->io_path_acquired = TRUE;
00970     }
00971   
00972   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00973                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00974 
00975   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00976   _dbus_mutex_unlock (connection->io_path_mutex);
00977 
00978   CONNECTION_LOCK (connection);
00979   
00980   HAVE_LOCK_CHECK (connection);
00981 
00982   _dbus_connection_unref_unlocked (connection);
00983   
00984   return we_acquired;
00985 }
00986 
00994 static void
00995 _dbus_connection_release_io_path (DBusConnection *connection)
00996 {
00997   HAVE_LOCK_CHECK (connection);
00998   
00999   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01000   _dbus_mutex_lock (connection->io_path_mutex);
01001   
01002   _dbus_assert (connection->io_path_acquired);
01003 
01004   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01005                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01006   
01007   connection->io_path_acquired = FALSE;
01008   _dbus_condvar_wake_one (connection->io_path_cond);
01009 
01010   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01011   _dbus_mutex_unlock (connection->io_path_mutex);
01012 }
01013 
01042 void
01043 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01044                                         unsigned int    flags,
01045                                         int             timeout_milliseconds)
01046 {
01047   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01048   
01049   HAVE_LOCK_CHECK (connection);
01050   
01051   if (connection->n_outgoing == 0)
01052     flags &= ~DBUS_ITERATION_DO_WRITING;
01053 
01054   if (_dbus_connection_acquire_io_path (connection,
01055                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01056     {
01057       HAVE_LOCK_CHECK (connection);
01058       
01059       _dbus_transport_do_iteration (connection->transport,
01060                                     flags, timeout_milliseconds);
01061       _dbus_connection_release_io_path (connection);
01062     }
01063 
01064   HAVE_LOCK_CHECK (connection);
01065 
01066   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01067 }
01068 
01078 DBusConnection*
01079 _dbus_connection_new_for_transport (DBusTransport *transport)
01080 {
01081   DBusConnection *connection;
01082   DBusWatchList *watch_list;
01083   DBusTimeoutList *timeout_list;
01084   DBusHashTable *pending_replies;
01085   DBusMutex *mutex;
01086   DBusMutex *io_path_mutex;
01087   DBusMutex *dispatch_mutex;
01088   DBusCondVar *dispatch_cond;
01089   DBusCondVar *io_path_cond;
01090   DBusList *disconnect_link;
01091   DBusMessage *disconnect_message;
01092   DBusCounter *outgoing_counter;
01093   DBusObjectTree *objects;
01094   
01095   watch_list = NULL;
01096   connection = NULL;
01097   pending_replies = NULL;
01098   timeout_list = NULL;
01099   mutex = NULL;
01100   io_path_mutex = NULL;
01101   dispatch_mutex = NULL;
01102   dispatch_cond = NULL;
01103   io_path_cond = NULL;
01104   disconnect_link = NULL;
01105   disconnect_message = NULL;
01106   outgoing_counter = NULL;
01107   objects = NULL;
01108   
01109   watch_list = _dbus_watch_list_new ();
01110   if (watch_list == NULL)
01111     goto error;
01112 
01113   timeout_list = _dbus_timeout_list_new ();
01114   if (timeout_list == NULL)
01115     goto error;  
01116 
01117   pending_replies =
01118     _dbus_hash_table_new (DBUS_HASH_INT,
01119                           NULL,
01120                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01121   if (pending_replies == NULL)
01122     goto error;
01123   
01124   connection = dbus_new0 (DBusConnection, 1);
01125   if (connection == NULL)
01126     goto error;
01127 
01128   mutex = _dbus_mutex_new ();
01129   if (mutex == NULL)
01130     goto error;
01131 
01132   io_path_mutex = _dbus_mutex_new ();
01133   if (io_path_mutex == NULL)
01134     goto error;
01135 
01136   dispatch_mutex = _dbus_mutex_new ();
01137   if (dispatch_mutex == NULL)
01138     goto error;
01139   
01140   dispatch_cond = _dbus_condvar_new ();
01141   if (dispatch_cond == NULL)
01142     goto error;
01143   
01144   io_path_cond = _dbus_condvar_new ();
01145   if (io_path_cond == NULL)
01146     goto error;
01147 
01148   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01149                                                 DBUS_INTERFACE_LOCAL,
01150                                                 "Disconnected");
01151   
01152   if (disconnect_message == NULL)
01153     goto error;
01154 
01155   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01156   if (disconnect_link == NULL)
01157     goto error;
01158 
01159   outgoing_counter = _dbus_counter_new ();
01160   if (outgoing_counter == NULL)
01161     goto error;
01162 
01163   objects = _dbus_object_tree_new (connection);
01164   if (objects == NULL)
01165     goto error;
01166   
01167   if (_dbus_modify_sigpipe)
01168     _dbus_disable_sigpipe ();
01169   
01170   connection->refcount.value = 1;
01171   connection->mutex = mutex;
01172   connection->dispatch_cond = dispatch_cond;
01173   connection->dispatch_mutex = dispatch_mutex;
01174   connection->io_path_cond = io_path_cond;
01175   connection->io_path_mutex = io_path_mutex;
01176   connection->transport = transport;
01177   connection->watches = watch_list;
01178   connection->timeouts = timeout_list;
01179   connection->pending_replies = pending_replies;
01180   connection->outgoing_counter = outgoing_counter;
01181   connection->filter_list = NULL;
01182   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01183   connection->objects = objects;
01184   connection->exit_on_disconnect = FALSE;
01185   connection->shareable = FALSE;
01186 #ifndef DBUS_DISABLE_CHECKS
01187   connection->generation = _dbus_current_generation;
01188 #endif
01189   
01190   _dbus_data_slot_list_init (&connection->slot_list);
01191 
01192   connection->client_serial = 1;
01193 
01194   connection->disconnect_message_link = disconnect_link;
01195 
01196   CONNECTION_LOCK (connection);
01197   
01198   if (!_dbus_transport_set_connection (transport, connection))
01199     goto error;
01200 
01201   _dbus_transport_ref (transport);
01202 
01203   CONNECTION_UNLOCK (connection);
01204   
01205   return connection;
01206   
01207  error:
01208   if (disconnect_message != NULL)
01209     dbus_message_unref (disconnect_message);
01210   
01211   if (disconnect_link != NULL)
01212     _dbus_list_free_link (disconnect_link);
01213   
01214   if (io_path_cond != NULL)
01215     _dbus_condvar_free (io_path_cond);
01216   
01217   if (dispatch_cond != NULL)
01218     _dbus_condvar_free (dispatch_cond);
01219   
01220   if (mutex != NULL)
01221     _dbus_mutex_free (mutex);
01222 
01223   if (io_path_mutex != NULL)
01224     _dbus_mutex_free (io_path_mutex);
01225 
01226   if (dispatch_mutex != NULL)
01227     _dbus_mutex_free (dispatch_mutex);
01228   
01229   if (connection != NULL)
01230     dbus_free (connection);
01231 
01232   if (pending_replies)
01233     _dbus_hash_table_unref (pending_replies);
01234   
01235   if (watch_list)
01236     _dbus_watch_list_free (watch_list);
01237 
01238   if (timeout_list)
01239     _dbus_timeout_list_free (timeout_list);
01240 
01241   if (outgoing_counter)
01242     _dbus_counter_unref (outgoing_counter);
01243 
01244   if (objects)
01245     _dbus_object_tree_unref (objects);
01246   
01247   return NULL;
01248 }
01249 
01257 DBusConnection *
01258 _dbus_connection_ref_unlocked (DBusConnection *connection)
01259 {  
01260   _dbus_assert (connection != NULL);
01261   _dbus_assert (connection->generation == _dbus_current_generation);
01262 
01263   HAVE_LOCK_CHECK (connection);
01264   
01265 #ifdef DBUS_HAVE_ATOMIC_INT
01266   _dbus_atomic_inc (&connection->refcount);
01267 #else
01268   _dbus_assert (connection->refcount.value > 0);
01269   connection->refcount.value += 1;
01270 #endif
01271 
01272   return connection;
01273 }
01274 
01281 void
01282 _dbus_connection_unref_unlocked (DBusConnection *connection)
01283 {
01284   dbus_bool_t last_unref;
01285 
01286   HAVE_LOCK_CHECK (connection);
01287   
01288   _dbus_assert (connection != NULL);
01289 
01290   /* The connection lock is better than the global
01291    * lock in the atomic increment fallback
01292    */
01293   
01294 #ifdef DBUS_HAVE_ATOMIC_INT
01295   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01296 #else
01297   _dbus_assert (connection->refcount.value > 0);
01298 
01299   connection->refcount.value -= 1;
01300   last_unref = (connection->refcount.value == 0);  
01301 #if 0
01302   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01303 #endif
01304 #endif
01305   
01306   if (last_unref)
01307     _dbus_connection_last_unref (connection);
01308 }
01309 
01310 static dbus_uint32_t
01311 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01312 {
01313   int serial;
01314 
01315   serial = connection->client_serial++;
01316 
01317   if (connection->client_serial < 0)
01318     connection->client_serial = 1;
01319   
01320   return serial;
01321 }
01322 
01336 dbus_bool_t
01337 _dbus_connection_handle_watch (DBusWatch                   *watch,
01338                                unsigned int                 condition,
01339                                void                        *data)
01340 {
01341   DBusConnection *connection;
01342   dbus_bool_t retval;
01343   DBusDispatchStatus status;
01344 
01345   connection = data;
01346 
01347   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01348   
01349   CONNECTION_LOCK (connection);
01350   _dbus_connection_acquire_io_path (connection, -1);
01351   HAVE_LOCK_CHECK (connection);
01352   retval = _dbus_transport_handle_watch (connection->transport,
01353                                          watch, condition);
01354 
01355   _dbus_connection_release_io_path (connection);
01356 
01357   HAVE_LOCK_CHECK (connection);
01358 
01359   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01360   
01361   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01362 
01363   /* this calls out to user code */
01364   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01365 
01366   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01367   
01368   return retval;
01369 }
01370 
01371 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01372 static DBusHashTable *shared_connections = NULL;
01373 
01374 static void
01375 shared_connections_shutdown (void *data)
01376 {
01377   _DBUS_LOCK (shared_connections);
01378 
01379   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01380   _dbus_hash_table_unref (shared_connections);
01381   shared_connections = NULL;
01382   
01383   _DBUS_UNLOCK (shared_connections);
01384 }
01385 
01386 static dbus_bool_t
01387 connection_lookup_shared (DBusAddressEntry  *entry,
01388                           DBusConnection   **result)
01389 {
01390   _dbus_verbose ("checking for existing connection\n");
01391   
01392   *result = NULL;
01393   
01394   _DBUS_LOCK (shared_connections);
01395 
01396   if (shared_connections == NULL)
01397     {
01398       _dbus_verbose ("creating shared_connections hash table\n");
01399       
01400       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01401                                                  dbus_free,
01402                                                  NULL);
01403       if (shared_connections == NULL)
01404         {
01405           _DBUS_UNLOCK (shared_connections);
01406           return FALSE;
01407         }
01408 
01409       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01410         {
01411           _dbus_hash_table_unref (shared_connections);
01412           shared_connections = NULL;
01413           _DBUS_UNLOCK (shared_connections);
01414           return FALSE;
01415         }
01416 
01417       _dbus_verbose ("  successfully created shared_connections\n");
01418       
01419       _DBUS_UNLOCK (shared_connections);
01420       return TRUE; /* no point looking up in the hash we just made */
01421     }
01422   else
01423     {
01424       const char *guid;
01425 
01426       guid = dbus_address_entry_get_value (entry, "guid");
01427       
01428       if (guid != NULL)
01429         {
01430           *result = _dbus_hash_table_lookup_string (shared_connections,
01431                                                     guid);
01432 
01433           if (*result)
01434             {
01435               /* The DBusConnection can't have been disconnected
01436                * between the lookup and this code, because the
01437                * disconnection will take the shared_connections lock to
01438                * remove the connection. It can't have been finalized
01439                * since you have to disconnect prior to finalize.
01440                *
01441                * Thus it's safe to ref the connection.
01442                */
01443               dbus_connection_ref (*result);
01444 
01445               _dbus_verbose ("looked up existing connection to server guid %s\n",
01446                              guid);
01447             }
01448         }
01449       
01450       _DBUS_UNLOCK (shared_connections);
01451       return TRUE;
01452     }
01453 }
01454 
01455 static dbus_bool_t
01456 connection_record_shared_unlocked (DBusConnection *connection,
01457                                    const char     *guid)
01458 {
01459   char *guid_key;
01460   char *guid_in_connection;
01461 
01462   /* A separate copy of the key is required in the hash table, because
01463    * we don't have a lock on the connection when we are doing a hash
01464    * lookup.
01465    */
01466   
01467   _dbus_assert (connection->server_guid == NULL);
01468   _dbus_assert (connection->shareable);
01469   
01470   guid_key = _dbus_strdup (guid);
01471   if (guid_key == NULL)
01472     return FALSE;
01473 
01474   guid_in_connection = _dbus_strdup (guid);
01475   if (guid_in_connection == NULL)
01476     {
01477       dbus_free (guid_key);
01478       return FALSE;
01479     }
01480   
01481   _DBUS_LOCK (shared_connections);
01482   _dbus_assert (shared_connections != NULL);
01483   
01484   if (!_dbus_hash_table_insert_string (shared_connections,
01485                                        guid_key, connection))
01486     {
01487       dbus_free (guid_key);
01488       dbus_free (guid_in_connection);
01489       _DBUS_UNLOCK (shared_connections);
01490       return FALSE;
01491     }
01492 
01493   connection->server_guid = guid_in_connection;
01494 
01495   _dbus_verbose ("stored connection to %s to be shared\n",
01496                  connection->server_guid);
01497   
01498   _DBUS_UNLOCK (shared_connections);
01499 
01500   _dbus_assert (connection->server_guid != NULL);
01501   
01502   return TRUE;
01503 }
01504 
01505 static void
01506 connection_forget_shared_unlocked (DBusConnection *connection)
01507 {
01508   HAVE_LOCK_CHECK (connection);
01509   
01510   if (connection->server_guid == NULL)
01511     return;
01512 
01513   _dbus_verbose ("dropping connection to %s out of the shared table\n",
01514                  connection->server_guid);
01515   
01516   _DBUS_LOCK (shared_connections);
01517 
01518   if (!_dbus_hash_table_remove_string (shared_connections,
01519                                        connection->server_guid))
01520     _dbus_assert_not_reached ("connection was not in the shared table");
01521   
01522   dbus_free (connection->server_guid);
01523   connection->server_guid = NULL;
01524 
01525   _DBUS_UNLOCK (shared_connections);
01526 }
01527 
01528 static DBusConnection*
01529 connection_try_from_address_entry (DBusAddressEntry *entry,
01530                                    DBusError        *error)
01531 {
01532   DBusTransport *transport;
01533   DBusConnection *connection;
01534 
01535   transport = _dbus_transport_open (entry, error);
01536 
01537   if (transport == NULL)
01538     {
01539       _DBUS_ASSERT_ERROR_IS_SET (error);
01540       return NULL;
01541     }
01542 
01543   connection = _dbus_connection_new_for_transport (transport);
01544 
01545   _dbus_transport_unref (transport);
01546   
01547   if (connection == NULL)
01548     {
01549       _DBUS_SET_OOM (error);
01550       return NULL;
01551     }
01552 
01553 #ifndef DBUS_DISABLE_CHECKS
01554   _dbus_assert (!connection->have_connection_lock);
01555 #endif
01556   return connection;
01557 }
01558 
01559 /*
01560  * If the shared parameter is true, then any existing connection will
01561  * be used (and if a new connection is created, it will be available
01562  * for use by others). If the shared parameter is false, a new
01563  * connection will always be created, and the new connection will
01564  * never be returned to other callers.
01565  *
01566  * @param address the address
01567  * @param shared whether the connection is shared or private
01568  * @param error error return
01569  * @returns the connection or #NULL on error
01570  */
01571 static DBusConnection*
01572 _dbus_connection_open_internal (const char     *address,
01573                                 dbus_bool_t     shared,
01574                                 DBusError      *error)
01575 {
01576   DBusConnection *connection;
01577   DBusAddressEntry **entries;
01578   DBusError tmp_error;
01579   DBusError first_error;
01580   int len, i;
01581 
01582   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01583 
01584   _dbus_verbose ("opening %s connection to: %s\n",
01585                  shared ? "shared" : "private", address);
01586   
01587   if (!dbus_parse_address (address, &entries, &len, error))
01588     return NULL;
01589 
01590   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01591   
01592   connection = NULL;
01593 
01594   dbus_error_init (&tmp_error);
01595   dbus_error_init (&first_error);
01596   for (i = 0; i < len; i++)
01597     {
01598       if (shared)
01599         {
01600           if (!connection_lookup_shared (entries[i], &connection))
01601             _DBUS_SET_OOM (&tmp_error);
01602         }
01603 
01604       if (connection == NULL)
01605         {
01606           connection = connection_try_from_address_entry (entries[i],
01607                                                           &tmp_error);
01608           
01609           if (connection != NULL && shared)
01610             {
01611               const char *guid;
01612 
01613               connection->shareable = TRUE;
01614               
01615               guid = dbus_address_entry_get_value (entries[i], "guid");
01616 
01617               /* we don't have a connection lock but we know nobody
01618                * else has a handle to the connection
01619                */
01620               
01621               if (guid &&
01622                   !connection_record_shared_unlocked (connection, guid))
01623                 {
01624                   _DBUS_SET_OOM (&tmp_error);
01625                   dbus_connection_close (connection);
01626                   dbus_connection_unref (connection);
01627                   connection = NULL;
01628                 }
01629 
01630               /* but as of now the connection is possibly shared
01631                * since another thread could have pulled it from the table
01632                */
01633             }
01634         }
01635       
01636       if (connection)
01637         break;
01638 
01639       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01640       
01641       if (i == 0)
01642         dbus_move_error (&tmp_error, &first_error);
01643       else
01644         dbus_error_free (&tmp_error);
01645     }
01646 
01647   /* NOTE we don't have a lock on a possibly-shared connection object */
01648   
01649   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01650   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01651   
01652   if (connection == NULL)
01653     {
01654       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01655       dbus_move_error (&first_error, error);
01656     }
01657   else
01658     {
01659       dbus_error_free (&first_error);
01660     }
01661   
01662   dbus_address_entries_free (entries);
01663   return connection;
01664 }
01665 
01693 DBusConnection*
01694 dbus_connection_open (const char     *address,
01695                       DBusError      *error)
01696 {
01697   DBusConnection *connection;
01698 
01699   _dbus_return_val_if_fail (address != NULL, NULL);
01700   _dbus_return_val_if_error_is_set (error, NULL);
01701 
01702   connection = _dbus_connection_open_internal (address,
01703                                                TRUE,
01704                                                error);
01705 
01706   return connection;
01707 }
01708 
01723 DBusConnection*
01724 dbus_connection_open_private (const char     *address,
01725                               DBusError      *error)
01726 {
01727   DBusConnection *connection;
01728 
01729   _dbus_return_val_if_fail (address != NULL, NULL);
01730   _dbus_return_val_if_error_is_set (error, NULL);
01731 
01732   connection = _dbus_connection_open_internal (address,
01733                                                FALSE,
01734                                                error);
01735 
01736   return connection;
01737 }
01738 
01745 DBusConnection *
01746 dbus_connection_ref (DBusConnection *connection)
01747 {
01748   _dbus_return_val_if_fail (connection != NULL, NULL);
01749   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01750   
01751   /* The connection lock is better than the global
01752    * lock in the atomic increment fallback
01753    */
01754   
01755 #ifdef DBUS_HAVE_ATOMIC_INT
01756   _dbus_atomic_inc (&connection->refcount);
01757 #else
01758   CONNECTION_LOCK (connection);
01759   _dbus_assert (connection->refcount.value > 0);
01760 
01761   connection->refcount.value += 1;
01762   CONNECTION_UNLOCK (connection);
01763 #endif
01764 
01765   return connection;
01766 }
01767 
01768 static void
01769 free_outgoing_message (void *element,
01770                        void *data)
01771 {
01772   DBusMessage *message = element;
01773   DBusConnection *connection = data;
01774 
01775   _dbus_message_remove_size_counter (message,
01776                                      connection->outgoing_counter,
01777                                      NULL);
01778   dbus_message_unref (message);
01779 }
01780 
01781 /* This is run without the mutex held, but after the last reference
01782  * to the connection has been dropped we should have no thread-related
01783  * problems
01784  */
01785 static void
01786 _dbus_connection_last_unref (DBusConnection *connection)
01787 {
01788   DBusList *link;
01789 
01790   _dbus_verbose ("Finalizing connection %p\n", connection);
01791   
01792   _dbus_assert (connection->refcount.value == 0);
01793   
01794   /* You have to disconnect the connection before unref:ing it. Otherwise
01795    * you won't get the disconnected message.
01796    */
01797   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01798   _dbus_assert (connection->server_guid == NULL);
01799   
01800   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01801   _dbus_object_tree_free_all_unlocked (connection->objects);
01802   
01803   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01804   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01805   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01806   
01807   _dbus_watch_list_free (connection->watches);
01808   connection->watches = NULL;
01809   
01810   _dbus_timeout_list_free (connection->timeouts);
01811   connection->timeouts = NULL;
01812 
01813   _dbus_data_slot_list_free (&connection->slot_list);
01814   
01815   link = _dbus_list_get_first_link (&connection->filter_list);
01816   while (link != NULL)
01817     {
01818       DBusMessageFilter *filter = link->data;
01819       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01820 
01821       filter->function = NULL;
01822       _dbus_message_filter_unref (filter); /* calls app callback */
01823       link->data = NULL;
01824       
01825       link = next;
01826     }
01827   _dbus_list_clear (&connection->filter_list);
01828   
01829   /* ---- Done with stuff that invokes application callbacks */
01830 
01831   _dbus_object_tree_unref (connection->objects);  
01832 
01833   _dbus_hash_table_unref (connection->pending_replies);
01834   connection->pending_replies = NULL;
01835   
01836   _dbus_list_clear (&connection->filter_list);
01837   
01838   _dbus_list_foreach (&connection->outgoing_messages,
01839                       free_outgoing_message,
01840                       connection);
01841   _dbus_list_clear (&connection->outgoing_messages);
01842   
01843   _dbus_list_foreach (&connection->incoming_messages,
01844                       (DBusForeachFunction) dbus_message_unref,
01845                       NULL);
01846   _dbus_list_clear (&connection->incoming_messages);
01847 
01848   _dbus_counter_unref (connection->outgoing_counter);
01849 
01850   _dbus_transport_unref (connection->transport);
01851 
01852   if (connection->disconnect_message_link)
01853     {
01854       DBusMessage *message = connection->disconnect_message_link->data;
01855       dbus_message_unref (message);
01856       _dbus_list_free_link (connection->disconnect_message_link);
01857     }
01858 
01859   _dbus_list_clear (&connection->link_cache);
01860   
01861   _dbus_condvar_free (connection->dispatch_cond);
01862   _dbus_condvar_free (connection->io_path_cond);
01863 
01864   _dbus_mutex_free (connection->io_path_mutex);
01865   _dbus_mutex_free (connection->dispatch_mutex);
01866 
01867   _dbus_mutex_free (connection->mutex);
01868   
01869   dbus_free (connection);
01870 }
01871 
01883 void
01884 dbus_connection_unref (DBusConnection *connection)
01885 {
01886   dbus_bool_t last_unref;
01887 
01888   _dbus_return_if_fail (connection != NULL);
01889   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01890   
01891   /* The connection lock is better than the global
01892    * lock in the atomic increment fallback
01893    */
01894   
01895 #ifdef DBUS_HAVE_ATOMIC_INT
01896   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01897 #else
01898   CONNECTION_LOCK (connection);
01899   
01900   _dbus_assert (connection->refcount.value > 0);
01901 
01902   connection->refcount.value -= 1;
01903   last_unref = (connection->refcount.value == 0);
01904 
01905 #if 0
01906   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01907 #endif
01908   
01909   CONNECTION_UNLOCK (connection);
01910 #endif
01911   
01912   if (last_unref)
01913     _dbus_connection_last_unref (connection);
01914 }
01915 
01929 void
01930 dbus_connection_close (DBusConnection *connection)
01931 {
01932   DBusDispatchStatus status;
01933   
01934   _dbus_return_if_fail (connection != NULL);
01935   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01936 
01937   _dbus_verbose ("Disconnecting %p\n", connection);
01938   
01939   CONNECTION_LOCK (connection);
01940   
01941   _dbus_transport_disconnect (connection->transport);
01942 
01943   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01944   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01945 
01946   /* this calls out to user code */
01947   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01948 }
01949 
01956 void
01957 dbus_connection_disconnect (DBusConnection *connection)
01958 {
01959   dbus_connection_close (connection);
01960 }
01961 
01962 static dbus_bool_t
01963 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01964 {
01965   HAVE_LOCK_CHECK (connection);
01966   return _dbus_transport_get_is_connected (connection->transport);
01967 }
01968 
01979 dbus_bool_t
01980 dbus_connection_get_is_connected (DBusConnection *connection)
01981 {
01982   dbus_bool_t res;
01983 
01984   _dbus_return_val_if_fail (connection != NULL, FALSE);
01985   
01986   CONNECTION_LOCK (connection);
01987   res = _dbus_connection_get_is_connected_unlocked (connection);
01988   CONNECTION_UNLOCK (connection);
01989   
01990   return res;
01991 }
01992 
02001 dbus_bool_t
02002 dbus_connection_get_is_authenticated (DBusConnection *connection)
02003 {
02004   dbus_bool_t res;
02005 
02006   _dbus_return_val_if_fail (connection != NULL, FALSE);
02007   
02008   CONNECTION_LOCK (connection);
02009   res = _dbus_transport_get_is_authenticated (connection->transport);
02010   CONNECTION_UNLOCK (connection);
02011   
02012   return res;
02013 }
02014 
02028 void
02029 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02030                                         dbus_bool_t     exit_on_disconnect)
02031 {
02032   _dbus_return_if_fail (connection != NULL);
02033 
02034   CONNECTION_LOCK (connection);
02035   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02036   CONNECTION_UNLOCK (connection);
02037 }
02038 
02039 static DBusPreallocatedSend*
02040 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02041 {
02042   DBusPreallocatedSend *preallocated;
02043 
02044   HAVE_LOCK_CHECK (connection);
02045   
02046   _dbus_assert (connection != NULL);
02047   
02048   preallocated = dbus_new (DBusPreallocatedSend, 1);
02049   if (preallocated == NULL)
02050     return NULL;
02051 
02052   if (connection->link_cache != NULL)
02053     {
02054       preallocated->queue_link =
02055         _dbus_list_pop_first_link (&connection->link_cache);
02056       preallocated->queue_link->data = NULL;
02057     }
02058   else
02059     {
02060       preallocated->queue_link = _dbus_list_alloc_link (NULL);
02061       if (preallocated->queue_link == NULL)
02062         goto failed_0;
02063     }
02064   
02065   if (connection->link_cache != NULL)
02066     {
02067       preallocated->counter_link =
02068         _dbus_list_pop_first_link (&connection->link_cache);
02069       preallocated->counter_link->data = connection->outgoing_counter;
02070     }
02071   else
02072     {
02073       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02074       if (preallocated->counter_link == NULL)
02075         goto failed_1;
02076     }
02077 
02078   _dbus_counter_ref (preallocated->counter_link->data);
02079 
02080   preallocated->connection = connection;
02081   
02082   return preallocated;
02083   
02084  failed_1:
02085   _dbus_list_free_link (preallocated->queue_link);
02086  failed_0:
02087   dbus_free (preallocated);
02088   
02089   return NULL;
02090 }
02091 
02101 DBusPreallocatedSend*
02102 dbus_connection_preallocate_send (DBusConnection *connection)
02103 {
02104   DBusPreallocatedSend *preallocated;
02105 
02106   _dbus_return_val_if_fail (connection != NULL, NULL);
02107 
02108   CONNECTION_LOCK (connection);
02109   
02110   preallocated =
02111     _dbus_connection_preallocate_send_unlocked (connection);
02112 
02113   CONNECTION_UNLOCK (connection);
02114 
02115   return preallocated;
02116 }
02117 
02127 void
02128 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02129                                         DBusPreallocatedSend *preallocated)
02130 {
02131   _dbus_return_if_fail (connection != NULL);
02132   _dbus_return_if_fail (preallocated != NULL);  
02133   _dbus_return_if_fail (connection == preallocated->connection);
02134 
02135   _dbus_list_free_link (preallocated->queue_link);
02136   _dbus_counter_unref (preallocated->counter_link->data);
02137   _dbus_list_free_link (preallocated->counter_link);
02138   dbus_free (preallocated);
02139 }
02140 
02141 /* Called with lock held, does not update dispatch status */
02142 static void
02143 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
02144                                                        DBusPreallocatedSend *preallocated,
02145                                                        DBusMessage          *message,
02146                                                        dbus_uint32_t        *client_serial)
02147 {
02148   dbus_uint32_t serial;
02149   const char *sig;
02150 
02151   preallocated->queue_link->data = message;
02152   _dbus_list_prepend_link (&connection->outgoing_messages,
02153                            preallocated->queue_link);
02154 
02155   _dbus_message_add_size_counter_link (message,
02156                                        preallocated->counter_link);
02157 
02158   dbus_free (preallocated);
02159   preallocated = NULL;
02160   
02161   dbus_message_ref (message);
02162   
02163   connection->n_outgoing += 1;
02164 
02165   sig = dbus_message_get_signature (message);
02166   
02167   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02168                  message,
02169                  dbus_message_get_type (message),
02170                  dbus_message_get_path (message) ?
02171                  dbus_message_get_path (message) :
02172                  "no path",
02173                  dbus_message_get_interface (message) ?
02174                  dbus_message_get_interface (message) :
02175                  "no interface",
02176                  dbus_message_get_member (message) ?
02177                  dbus_message_get_member (message) :
02178                  "no member",
02179                  sig,
02180                  dbus_message_get_destination (message) ?
02181                  dbus_message_get_destination (message) :
02182                  "null",
02183                  connection,
02184                  connection->n_outgoing);
02185 
02186   if (dbus_message_get_serial (message) == 0)
02187     {
02188       serial = _dbus_connection_get_next_client_serial (connection);
02189       _dbus_message_set_serial (message, serial);
02190       if (client_serial)
02191         *client_serial = serial;
02192     }
02193   else
02194     {
02195       if (client_serial)
02196         *client_serial = dbus_message_get_serial (message);
02197     }
02198 
02199   _dbus_verbose ("Message %p serial is %u\n",
02200                  message, dbus_message_get_serial (message));
02201   
02202   _dbus_message_lock (message);
02203 
02204   /* Now we need to run an iteration to hopefully just write the messages
02205    * out immediately, and otherwise get them queued up
02206    */
02207   _dbus_connection_do_iteration_unlocked (connection,
02208                                           DBUS_ITERATION_DO_WRITING,
02209                                           -1);
02210 
02211   /* If stuff is still queued up, be sure we wake up the main loop */
02212   if (connection->n_outgoing > 0)
02213     _dbus_connection_wakeup_mainloop (connection);
02214 }
02215 
02216 static void
02217 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02218                                                DBusPreallocatedSend *preallocated,
02219                                                DBusMessage          *message,
02220                                                dbus_uint32_t        *client_serial)
02221 {
02222   DBusDispatchStatus status;
02223 
02224   HAVE_LOCK_CHECK (connection);
02225   
02226   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02227                                                          preallocated,
02228                                                          message, client_serial);
02229 
02230   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02231   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02232 
02233   /* this calls out to user code */
02234   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02235 }
02236 
02249 void
02250 dbus_connection_send_preallocated (DBusConnection       *connection,
02251                                    DBusPreallocatedSend *preallocated,
02252                                    DBusMessage          *message,
02253                                    dbus_uint32_t        *client_serial)
02254 {
02255   _dbus_return_if_fail (connection != NULL);
02256   _dbus_return_if_fail (preallocated != NULL);
02257   _dbus_return_if_fail (message != NULL);
02258   _dbus_return_if_fail (preallocated->connection == connection);
02259   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02260                         dbus_message_get_member (message) != NULL);
02261   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02262                         (dbus_message_get_interface (message) != NULL &&
02263                          dbus_message_get_member (message) != NULL));
02264   
02265   CONNECTION_LOCK (connection);
02266   _dbus_connection_send_preallocated_and_unlock (connection,
02267                                                  preallocated,
02268                                                  message, client_serial);
02269 }
02270 
02271 static dbus_bool_t
02272 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02273                                           DBusMessage    *message,
02274                                           dbus_uint32_t  *client_serial)
02275 {
02276   DBusPreallocatedSend *preallocated;
02277 
02278   _dbus_assert (connection != NULL);
02279   _dbus_assert (message != NULL);
02280   
02281   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02282   if (preallocated == NULL)
02283     return FALSE;
02284 
02285   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02286                                                          preallocated,
02287                                                          message,
02288                                                          client_serial);
02289   return TRUE;
02290 }
02291 
02292 dbus_bool_t
02293 _dbus_connection_send_and_unlock (DBusConnection *connection,
02294                                   DBusMessage    *message,
02295                                   dbus_uint32_t  *client_serial)
02296 {
02297   DBusPreallocatedSend *preallocated;
02298 
02299   _dbus_assert (connection != NULL);
02300   _dbus_assert (message != NULL);
02301   
02302   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02303   if (preallocated == NULL)
02304     {
02305       CONNECTION_UNLOCK (connection);
02306       return FALSE;
02307     }
02308 
02309   _dbus_connection_send_preallocated_and_unlock (connection,
02310                                                  preallocated,
02311                                                  message,
02312                                                  client_serial);
02313   return TRUE;
02314 }
02315 
02334 dbus_bool_t
02335 dbus_connection_send (DBusConnection *connection,
02336                       DBusMessage    *message,
02337                       dbus_uint32_t  *client_serial)
02338 {
02339   _dbus_return_val_if_fail (connection != NULL, FALSE);
02340   _dbus_return_val_if_fail (message != NULL, FALSE);
02341 
02342   CONNECTION_LOCK (connection);
02343 
02344   return _dbus_connection_send_and_unlock (connection,
02345                                            message,
02346                                            client_serial);
02347 }
02348 
02349 static dbus_bool_t
02350 reply_handler_timeout (void *data)
02351 {
02352   DBusConnection *connection;
02353   DBusDispatchStatus status;
02354   DBusPendingCall *pending = data;
02355 
02356   connection = pending->connection;
02357   
02358   CONNECTION_LOCK (connection);
02359   if (pending->timeout_link)
02360     {
02361       _dbus_connection_queue_synthesized_message_link (connection,
02362                                                        pending->timeout_link);
02363       pending->timeout_link = NULL;
02364     }
02365 
02366   _dbus_connection_remove_timeout_unlocked (connection,
02367                                             pending->timeout);
02368   pending->timeout_added = FALSE;
02369 
02370   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02371   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02372 
02373   /* Unlocks, and calls out to user code */
02374   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02375   
02376   return TRUE;
02377 }
02378 
02416 dbus_bool_t
02417 dbus_connection_send_with_reply (DBusConnection     *connection,
02418                                  DBusMessage        *message,
02419                                  DBusPendingCall   **pending_return,
02420                                  int                 timeout_milliseconds)
02421 {
02422   DBusPendingCall *pending;
02423   DBusMessage *reply;
02424   DBusList *reply_link;
02425   dbus_int32_t serial = -1;
02426   DBusDispatchStatus status;
02427 
02428   _dbus_return_val_if_fail (connection != NULL, FALSE);
02429   _dbus_return_val_if_fail (message != NULL, FALSE);
02430   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02431 
02432   if (pending_return)
02433     *pending_return = NULL;
02434   
02435   pending = _dbus_pending_call_new (connection,
02436                                     timeout_milliseconds,
02437                                     reply_handler_timeout);
02438 
02439   if (pending == NULL)
02440     return FALSE;
02441 
02442   CONNECTION_LOCK (connection);
02443   
02444   /* Assign a serial to the message */
02445   if (dbus_message_get_serial (message) == 0)
02446     {
02447       serial = _dbus_connection_get_next_client_serial (connection);
02448       _dbus_message_set_serial (message, serial);
02449     }
02450 
02451   pending->reply_serial = serial;
02452 
02453   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02454                                   "No reply within specified time");
02455   if (reply == NULL)
02456     goto error;
02457 
02458   reply_link = _dbus_list_alloc_link (reply);
02459   if (reply_link == NULL)
02460     {
02461       CONNECTION_UNLOCK (connection);
02462       dbus_message_unref (reply);
02463       goto error_unlocked;
02464     }
02465 
02466   pending->timeout_link = reply_link;
02467 
02468   /* Insert the serial in the pending replies hash;
02469    * hash takes a refcount on DBusPendingCall.
02470    * Also, add the timeout.
02471    */
02472   if (!_dbus_connection_attach_pending_call_unlocked (connection,
02473                                                       pending))
02474     goto error;
02475  
02476   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02477     {
02478       _dbus_connection_detach_pending_call_and_unlock (connection,
02479                                                        pending);
02480       goto error_unlocked;
02481     }
02482 
02483   if (pending_return)
02484     *pending_return = pending;
02485   else
02486     {
02487       _dbus_connection_detach_pending_call_unlocked (connection, pending);
02488       dbus_pending_call_unref (pending);
02489     }
02490 
02491   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02492   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02493 
02494   /* this calls out to user code */
02495   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02496 
02497   return TRUE;
02498 
02499  error:
02500   CONNECTION_UNLOCK (connection);
02501  error_unlocked:
02502   dbus_pending_call_unref (pending);
02503   return FALSE;
02504 }
02505 
02506 /* This is slightly strange since we can pop a message here without
02507  * the dispatch lock.
02508  */
02509 static DBusMessage*
02510 check_for_reply_unlocked (DBusConnection *connection,
02511                           dbus_uint32_t   client_serial)
02512 {
02513   DBusList *link;
02514 
02515   HAVE_LOCK_CHECK (connection);
02516   
02517   link = _dbus_list_get_first_link (&connection->incoming_messages);
02518 
02519   while (link != NULL)
02520     {
02521       DBusMessage *reply = link->data;
02522 
02523       if (dbus_message_get_reply_serial (reply) == client_serial)
02524         {
02525           _dbus_list_remove_link (&connection->incoming_messages, link);
02526           connection->n_incoming  -= 1;
02527           return reply;
02528         }
02529       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02530     }
02531 
02532   return NULL;
02533 }
02534 
02544 static void
02545 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02546 {
02547   if (timeout_milliseconds == -1)
02548     _dbus_sleep_milliseconds (1000);
02549   else if (timeout_milliseconds < 100)
02550     ; /* just busy loop */
02551   else if (timeout_milliseconds <= 1000)
02552     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02553   else
02554     _dbus_sleep_milliseconds (1000);
02555 }
02556 
02571 void
02572 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02573 {
02574   long start_tv_sec, start_tv_usec;
02575   long end_tv_sec, end_tv_usec;
02576   long tv_sec, tv_usec;
02577   DBusDispatchStatus status;
02578   DBusConnection *connection;
02579   dbus_uint32_t client_serial;
02580   int timeout_milliseconds;
02581 
02582   _dbus_assert (pending != NULL);
02583 
02584   if (dbus_pending_call_get_completed (pending))
02585     return;
02586 
02587   if (pending->connection == NULL)
02588     return; /* call already detached */
02589 
02590   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02591   
02592   connection = pending->connection;
02593   client_serial = pending->reply_serial;
02594 
02595   /* note that timeout_milliseconds is limited to a smallish value
02596    * in _dbus_pending_call_new() so overflows aren't possible
02597    * below
02598    */
02599   timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02600 
02601   /* Flush message queue */
02602   dbus_connection_flush (connection);
02603 
02604   CONNECTION_LOCK (connection);
02605 
02606   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02607   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02608   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02609   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02610   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02611 
02612   _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",
02613                  timeout_milliseconds,
02614                  client_serial,
02615                  start_tv_sec, start_tv_usec,
02616                  end_tv_sec, end_tv_usec);
02617 
02618   /* Now we wait... */
02619   /* always block at least once as we know we don't have the reply yet */
02620   _dbus_connection_do_iteration_unlocked (connection,
02621                                           DBUS_ITERATION_DO_READING |
02622                                           DBUS_ITERATION_BLOCK,
02623                                           timeout_milliseconds);
02624 
02625  recheck_status:
02626 
02627   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02628   
02629   HAVE_LOCK_CHECK (connection);
02630   
02631   /* queue messages and get status */
02632 
02633   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02634 
02635   /* the get_completed() is in case a dispatch() while we were blocking
02636    * got the reply instead of us.
02637    */
02638   if (dbus_pending_call_get_completed (pending))
02639     {
02640       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02641       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02642       dbus_pending_call_unref (pending);
02643       return;
02644     }
02645   
02646   if (status == DBUS_DISPATCH_DATA_REMAINS)
02647     {
02648       DBusMessage *reply;
02649       
02650       reply = check_for_reply_unlocked (connection, client_serial);
02651       if (reply != NULL)
02652         {
02653           _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02654 
02655           _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02656           
02657           _dbus_pending_call_complete_and_unlock (pending, reply);
02658           dbus_message_unref (reply);
02659 
02660           CONNECTION_LOCK (connection);
02661           status = _dbus_connection_get_dispatch_status_unlocked (connection);
02662           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02663           dbus_pending_call_unref (pending);
02664           
02665           return;
02666         }
02667     }
02668   
02669   _dbus_get_current_time (&tv_sec, &tv_usec);
02670   
02671   if (!_dbus_connection_get_is_connected_unlocked (connection))
02672     {
02673       /* FIXME send a "DBUS_ERROR_DISCONNECTED" instead, just to help
02674        * programmers understand what went wrong since the timeout is
02675        * confusing
02676        */
02677       
02678       _dbus_pending_call_complete_and_unlock (pending, NULL);
02679       dbus_pending_call_unref (pending);
02680       return;
02681     }
02682   else if (tv_sec < start_tv_sec)
02683     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02684   else if (connection->disconnect_message_link == NULL)
02685     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02686   else if (tv_sec < end_tv_sec ||
02687            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02688     {
02689       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02690         (end_tv_usec - tv_usec) / 1000;
02691       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02692       _dbus_assert (timeout_milliseconds >= 0);
02693       
02694       if (status == DBUS_DISPATCH_NEED_MEMORY)
02695         {
02696           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02697            * we may already have a reply in the buffer and just can't process
02698            * it.
02699            */
02700           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02701 
02702           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02703         }
02704       else
02705         {          
02706           /* block again, we don't have the reply buffered yet. */
02707           _dbus_connection_do_iteration_unlocked (connection,
02708                                                   DBUS_ITERATION_DO_READING |
02709                                                   DBUS_ITERATION_BLOCK,
02710                                                   timeout_milliseconds);
02711         }
02712 
02713       goto recheck_status;
02714     }
02715 
02716   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02717                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02718 
02719   _dbus_assert (!dbus_pending_call_get_completed (pending));
02720   
02721   /* unlock and call user code */
02722   _dbus_pending_call_complete_and_unlock (pending, NULL);
02723 
02724   /* update user code on dispatch status */
02725   CONNECTION_LOCK (connection);
02726   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02727   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02728   dbus_pending_call_unref (pending);
02729 }
02730 
02753 DBusMessage*
02754 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
02755                                            DBusMessage        *message,
02756                                            int                 timeout_milliseconds,
02757                                            DBusError          *error)
02758 {
02759   DBusMessage *reply;
02760   DBusPendingCall *pending;
02761   
02762   _dbus_return_val_if_fail (connection != NULL, NULL);
02763   _dbus_return_val_if_fail (message != NULL, NULL);
02764   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
02765   _dbus_return_val_if_error_is_set (error, NULL);
02766   
02767   if (!dbus_connection_send_with_reply (connection, message,
02768                                         &pending, timeout_milliseconds))
02769     {
02770       _DBUS_SET_OOM (error);
02771       return NULL;
02772     }
02773 
02774   _dbus_assert (pending != NULL);
02775   
02776   dbus_pending_call_block (pending);
02777 
02778   reply = dbus_pending_call_steal_reply (pending);
02779   dbus_pending_call_unref (pending);
02780 
02781   /* call_complete_and_unlock() called from pending_call_block() should
02782    * always fill this in.
02783    */
02784   _dbus_assert (reply != NULL);
02785   
02786    if (dbus_set_error_from_message (error, reply))
02787     {
02788       dbus_message_unref (reply);
02789       return NULL;
02790     }
02791   else
02792     return reply;
02793 }
02794 
02800 void
02801 dbus_connection_flush (DBusConnection *connection)
02802 {
02803   /* We have to specify DBUS_ITERATION_DO_READING here because
02804    * otherwise we could have two apps deadlock if they are both doing
02805    * a flush(), and the kernel buffers fill up. This could change the
02806    * dispatch status.
02807    */
02808   DBusDispatchStatus status;
02809 
02810   _dbus_return_if_fail (connection != NULL);
02811   
02812   CONNECTION_LOCK (connection);
02813   while (connection->n_outgoing > 0 &&
02814          _dbus_connection_get_is_connected_unlocked (connection))
02815     {
02816       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02817       HAVE_LOCK_CHECK (connection);
02818       _dbus_connection_do_iteration_unlocked (connection,
02819                                               DBUS_ITERATION_DO_READING |
02820                                               DBUS_ITERATION_DO_WRITING |
02821                                               DBUS_ITERATION_BLOCK,
02822                                               -1);
02823     }
02824 
02825   HAVE_LOCK_CHECK (connection);
02826   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02827   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02828 
02829   HAVE_LOCK_CHECK (connection);
02830   /* Unlocks and calls out to user code */
02831   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02832 
02833   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02834 }
02835 
02868 dbus_bool_t
02869 _dbus_connection_read_write_dispatch (DBusConnection *connection,
02870                                      int             timeout_milliseconds, 
02871                                      dbus_bool_t     dispatch)
02872 {
02873   DBusDispatchStatus dstatus;
02874   dbus_bool_t dispatched_disconnected;
02875   
02876   _dbus_return_val_if_fail (connection != NULL, FALSE);
02877   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02878   dstatus = dbus_connection_get_dispatch_status (connection);
02879 
02880   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
02881     {
02882       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02883       dbus_connection_dispatch (connection);
02884       CONNECTION_LOCK (connection);
02885     }
02886   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02887     {
02888       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02889       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02890       CONNECTION_LOCK (connection);
02891     }
02892   else
02893     {
02894       CONNECTION_LOCK (connection);
02895       if (_dbus_connection_get_is_connected_unlocked (connection))
02896         {
02897           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02898           _dbus_connection_do_iteration_unlocked (connection,
02899                                                   DBUS_ITERATION_DO_READING |
02900                                                   DBUS_ITERATION_DO_WRITING |
02901                                                   DBUS_ITERATION_BLOCK,
02902                                                   timeout_milliseconds);
02903         }
02904     }
02905   
02906   HAVE_LOCK_CHECK (connection);
02907   dispatched_disconnected = connection->n_incoming == 0 &&
02908     connection->disconnect_message_link == NULL;
02909   CONNECTION_UNLOCK (connection);
02910   return !dispatched_disconnected; /* TRUE if we have not processed disconnected */
02911 }
02912 
02913 
02945 dbus_bool_t
02946 dbus_connection_read_write_dispatch (DBusConnection *connection,
02947                                      int             timeout_milliseconds)
02948 {
02949    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
02950 }
02951 
02968 dbus_bool_t 
02969 dbus_connection_read_write (DBusConnection *connection, 
02970                             int             timeout_milliseconds) 
02971 { 
02972    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
02973 }
02974 
02994 DBusMessage*
02995 dbus_connection_borrow_message (DBusConnection *connection)
02996 {
02997   DBusDispatchStatus status;
02998   DBusMessage *message;
02999 
03000   _dbus_return_val_if_fail (connection != NULL, NULL);
03001 
03002   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03003   
03004   /* this is called for the side effect that it queues
03005    * up any messages from the transport
03006    */
03007   status = dbus_connection_get_dispatch_status (connection);
03008   if (status != DBUS_DISPATCH_DATA_REMAINS)
03009     return NULL;
03010   
03011   CONNECTION_LOCK (connection);
03012 
03013   _dbus_connection_acquire_dispatch (connection);
03014 
03015   /* While a message is outstanding, the dispatch lock is held */
03016   _dbus_assert (connection->message_borrowed == NULL);
03017 
03018   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03019   
03020   message = connection->message_borrowed;
03021 
03022   /* Note that we KEEP the dispatch lock until the message is returned */
03023   if (message == NULL)
03024     _dbus_connection_release_dispatch (connection);
03025 
03026   CONNECTION_UNLOCK (connection);
03027   
03028   return message;
03029 }
03030 
03039 void
03040 dbus_connection_return_message (DBusConnection *connection,
03041                                 DBusMessage    *message)
03042 {
03043   _dbus_return_if_fail (connection != NULL);
03044   _dbus_return_if_fail (message != NULL);
03045   _dbus_return_if_fail (message == connection->message_borrowed);
03046   _dbus_return_if_fail (connection->dispatch_acquired);
03047   
03048   CONNECTION_LOCK (connection);
03049   
03050   _dbus_assert (message == connection->message_borrowed);
03051   
03052   connection->message_borrowed = NULL;
03053 
03054   _dbus_connection_release_dispatch (connection);
03055   
03056   CONNECTION_UNLOCK (connection);
03057 }
03058 
03068 void
03069 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03070                                         DBusMessage    *message)
03071 {
03072   DBusMessage *pop_message;
03073 
03074   _dbus_return_if_fail (connection != NULL);
03075   _dbus_return_if_fail (message != NULL);
03076   _dbus_return_if_fail (message == connection->message_borrowed);
03077   _dbus_return_if_fail (connection->dispatch_acquired);
03078   
03079   CONNECTION_LOCK (connection);
03080  
03081   _dbus_assert (message == connection->message_borrowed);
03082 
03083   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03084   _dbus_assert (message == pop_message);
03085   
03086   connection->n_incoming -= 1;
03087  
03088   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03089                  message, connection->n_incoming);
03090  
03091   connection->message_borrowed = NULL;
03092 
03093   _dbus_connection_release_dispatch (connection);
03094   
03095   CONNECTION_UNLOCK (connection);
03096 }
03097 
03098 /* See dbus_connection_pop_message, but requires the caller to own
03099  * the lock before calling. May drop the lock while running.
03100  */
03101 static DBusList*
03102 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03103 {
03104   HAVE_LOCK_CHECK (connection);
03105   
03106   _dbus_assert (connection->message_borrowed == NULL);
03107   
03108   if (connection->n_incoming > 0)
03109     {
03110       DBusList *link;
03111 
03112       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03113       connection->n_incoming -= 1;
03114 
03115       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03116                      link->data,
03117                      dbus_message_get_type (link->data),
03118                      dbus_message_get_path (link->data) ?
03119                      dbus_message_get_path (link->data) :
03120                      "no path",
03121                      dbus_message_get_interface (link->data) ?
03122                      dbus_message_get_interface (link->data) :
03123                      "no interface",
03124                      dbus_message_get_member (link->data) ?
03125                      dbus_message_get_member (link->data) :
03126                      "no member",
03127                      dbus_message_get_signature (link->data),
03128                      connection, connection->n_incoming);
03129 
03130       return link;
03131     }
03132   else
03133     return NULL;
03134 }
03135 
03136 /* See dbus_connection_pop_message, but requires the caller to own
03137  * the lock before calling. May drop the lock while running.
03138  */
03139 static DBusMessage*
03140 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03141 {
03142   DBusList *link;
03143 
03144   HAVE_LOCK_CHECK (connection);
03145   
03146   link = _dbus_connection_pop_message_link_unlocked (connection);
03147 
03148   if (link != NULL)
03149     {
03150       DBusMessage *message;
03151       
03152       message = link->data;
03153       
03154       _dbus_list_free_link (link);
03155       
03156       return message;
03157     }
03158   else
03159     return NULL;
03160 }
03161 
03162 static void
03163 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03164                                                 DBusList       *message_link)
03165 {
03166   HAVE_LOCK_CHECK (connection);
03167   
03168   _dbus_assert (message_link != NULL);
03169   /* You can't borrow a message while a link is outstanding */
03170   _dbus_assert (connection->message_borrowed == NULL);
03171   /* We had to have the dispatch lock across the pop/putback */
03172   _dbus_assert (connection->dispatch_acquired);
03173 
03174   _dbus_list_prepend_link (&connection->incoming_messages,
03175                            message_link);
03176   connection->n_incoming += 1;
03177 
03178   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03179                  message_link->data,
03180                  dbus_message_get_type (message_link->data),
03181                  dbus_message_get_interface (message_link->data) ?
03182                  dbus_message_get_interface (message_link->data) :
03183                  "no interface",
03184                  dbus_message_get_member (message_link->data) ?
03185                  dbus_message_get_member (message_link->data) :
03186                  "no member",
03187                  dbus_message_get_signature (message_link->data),
03188                  connection, connection->n_incoming);
03189 }
03190 
03210 DBusMessage*
03211 dbus_connection_pop_message (DBusConnection *connection)
03212 {
03213   DBusMessage *message;
03214   DBusDispatchStatus status;
03215 
03216   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03217   
03218   /* this is called for the side effect that it queues
03219    * up any messages from the transport
03220    */
03221   status = dbus_connection_get_dispatch_status (connection);
03222   if (status != DBUS_DISPATCH_DATA_REMAINS)
03223     return NULL;
03224   
03225   CONNECTION_LOCK (connection);
03226   _dbus_connection_acquire_dispatch (connection);
03227   HAVE_LOCK_CHECK (connection);
03228   
03229   message = _dbus_connection_pop_message_unlocked (connection);
03230 
03231   _dbus_verbose ("Returning popped message %p\n", message);    
03232 
03233   _dbus_connection_release_dispatch (connection);
03234   CONNECTION_UNLOCK (connection);
03235   
03236   return message;
03237 }
03238 
03246 static void
03247 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03248 {
03249   HAVE_LOCK_CHECK (connection);
03250 
03251   _dbus_connection_ref_unlocked (connection);
03252   CONNECTION_UNLOCK (connection);
03253   
03254   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03255   _dbus_mutex_lock (connection->dispatch_mutex);
03256 
03257   while (connection->dispatch_acquired)
03258     {
03259       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03260       _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03261     }
03262   
03263   _dbus_assert (!connection->dispatch_acquired);
03264 
03265   connection->dispatch_acquired = TRUE;
03266 
03267   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03268   _dbus_mutex_unlock (connection->dispatch_mutex);
03269   
03270   CONNECTION_LOCK (connection);
03271   _dbus_connection_unref_unlocked (connection);
03272 }
03273 
03281 static void
03282 _dbus_connection_release_dispatch (DBusConnection *connection)
03283 {
03284   HAVE_LOCK_CHECK (connection);
03285   
03286   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03287   _dbus_mutex_lock (connection->dispatch_mutex);
03288   
03289   _dbus_assert (connection->dispatch_acquired);
03290 
03291   connection->dispatch_acquired = FALSE;
03292   _dbus_condvar_wake_one (connection->dispatch_cond);
03293 
03294   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03295   _dbus_mutex_unlock (connection->dispatch_mutex);
03296 }
03297 
03298 static void
03299 _dbus_connection_failed_pop (DBusConnection *connection,
03300                              DBusList       *message_link)
03301 {
03302   _dbus_list_prepend_link (&connection->incoming_messages,
03303                            message_link);
03304   connection->n_incoming += 1;
03305 }
03306 
03307 static DBusDispatchStatus
03308 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03309 {
03310   HAVE_LOCK_CHECK (connection);
03311   
03312   if (connection->n_incoming > 0)
03313     return DBUS_DISPATCH_DATA_REMAINS;
03314   else if (!_dbus_transport_queue_messages (connection->transport))
03315     return DBUS_DISPATCH_NEED_MEMORY;
03316   else
03317     {
03318       DBusDispatchStatus status;
03319       dbus_bool_t is_connected;
03320       
03321       status = _dbus_transport_get_dispatch_status (connection->transport);
03322       is_connected = _dbus_transport_get_is_connected (connection->transport);
03323 
03324       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03325                      DISPATCH_STATUS_NAME (status), is_connected);
03326       
03327       if (!is_connected)
03328         {
03329           if (status == DBUS_DISPATCH_COMPLETE &&
03330               connection->disconnect_message_link)
03331             {
03332               _dbus_verbose ("Sending disconnect message from %s\n",
03333                              _DBUS_FUNCTION_NAME);
03334 
03335               connection_forget_shared_unlocked (connection);
03336               
03337               /* We haven't sent the disconnect message already,
03338                * and all real messages have been queued up.
03339                */
03340               _dbus_connection_queue_synthesized_message_link (connection,
03341                                                                connection->disconnect_message_link);
03342               connection->disconnect_message_link = NULL;
03343 
03344               status = DBUS_DISPATCH_DATA_REMAINS;
03345             }
03346 
03347           /* Dump the outgoing queue, we aren't going to be able to
03348            * send it now, and we'd like accessors like
03349            * dbus_connection_get_outgoing_size() to be accurate.
03350            */
03351           if (connection->n_outgoing > 0)
03352             {
03353               DBusList *link;
03354               
03355               _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03356                              connection->n_outgoing);
03357               
03358               while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03359                 {
03360                   _dbus_connection_message_sent (connection, link->data);
03361                 }
03362             }
03363         }
03364       
03365       if (status != DBUS_DISPATCH_COMPLETE)
03366         return status;
03367       else if (connection->n_incoming > 0)
03368         return DBUS_DISPATCH_DATA_REMAINS;
03369       else
03370         return DBUS_DISPATCH_COMPLETE;
03371     }
03372 }
03373 
03374 static void
03375 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03376                                                     DBusDispatchStatus new_status)
03377 {
03378   dbus_bool_t changed;
03379   DBusDispatchStatusFunction function;
03380   void *data;
03381 
03382   HAVE_LOCK_CHECK (connection);
03383 
03384   _dbus_connection_ref_unlocked (connection);
03385 
03386   changed = new_status != connection->last_dispatch_status;
03387 
03388   connection->last_dispatch_status = new_status;
03389 
03390   function = connection->dispatch_status_function;
03391   data = connection->dispatch_status_data;
03392 
03393   /* We drop the lock */
03394   CONNECTION_UNLOCK (connection);
03395   
03396   if (changed && function)
03397     {
03398       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03399                      connection, new_status,
03400                      DISPATCH_STATUS_NAME (new_status));
03401       (* function) (connection, new_status, data);      
03402     }
03403   
03404   dbus_connection_unref (connection);
03405 }
03406 
03415 DBusDispatchStatus
03416 dbus_connection_get_dispatch_status (DBusConnection *connection)
03417 {
03418   DBusDispatchStatus status;
03419 
03420   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03421 
03422   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03423   
03424   CONNECTION_LOCK (connection);
03425 
03426   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03427   
03428   CONNECTION_UNLOCK (connection);
03429 
03430   return status;
03431 }
03432 
03436 static DBusHandlerResult
03437 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03438                                                  DBusMessage    *message)
03439 {
03440   if (dbus_message_is_method_call (message,
03441                                    DBUS_INTERFACE_PEER,
03442                                    "Ping"))
03443     {
03444       DBusMessage *ret;
03445       dbus_bool_t sent;
03446       
03447       ret = dbus_message_new_method_return (message);
03448       if (ret == NULL)
03449         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03450      
03451       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
03452 
03453       dbus_message_unref (ret);
03454 
03455       if (!sent)
03456         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03457       
03458       return DBUS_HANDLER_RESULT_HANDLED;
03459     }
03460                                    
03461   
03462   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03463 }
03464 
03471 static DBusHandlerResult
03472 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
03473                                                            DBusMessage    *message)
03474 {
03475   /* We just run one filter for now but have the option to run more
03476      if the spec calls for it in the future */
03477 
03478   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
03479 }
03480 
03504 DBusDispatchStatus
03505 dbus_connection_dispatch (DBusConnection *connection)
03506 {
03507   DBusMessage *message;
03508   DBusList *link, *filter_list_copy, *message_link;
03509   DBusHandlerResult result;
03510   DBusPendingCall *pending;
03511   dbus_int32_t reply_serial;
03512   DBusDispatchStatus status;
03513 
03514   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03515 
03516   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03517   
03518   CONNECTION_LOCK (connection);
03519   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03520   if (status != DBUS_DISPATCH_DATA_REMAINS)
03521     {
03522       /* unlocks and calls out to user code */
03523       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03524       return status;
03525     }
03526   
03527   /* We need to ref the connection since the callback could potentially
03528    * drop the last ref to it
03529    */
03530   _dbus_connection_ref_unlocked (connection);
03531 
03532   _dbus_connection_acquire_dispatch (connection);
03533   HAVE_LOCK_CHECK (connection);
03534 
03535   message_link = _dbus_connection_pop_message_link_unlocked (connection);
03536   if (message_link == NULL)
03537     {
03538       /* another thread dispatched our stuff */
03539 
03540       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03541       
03542       _dbus_connection_release_dispatch (connection);
03543 
03544       status = _dbus_connection_get_dispatch_status_unlocked (connection);
03545 
03546       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03547       
03548       dbus_connection_unref (connection);
03549       
03550       return status;
03551     }
03552 
03553   message = message_link->data;
03554 
03555   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03556                  message,
03557                  dbus_message_get_type (message),
03558                  dbus_message_get_interface (message) ?
03559                  dbus_message_get_interface (message) :
03560                  "no interface",
03561                  dbus_message_get_member (message) ?
03562                  dbus_message_get_member (message) :
03563                  "no member",
03564                  dbus_message_get_signature (message));
03565 
03566   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03567   
03568   /* Pending call handling must be first, because if you do
03569    * dbus_connection_send_with_reply_and_block() or
03570    * dbus_pending_call_block() then no handlers/filters will be run on
03571    * the reply. We want consistent semantics in the case where we
03572    * dbus_connection_dispatch() the reply.
03573    */
03574   
03575   reply_serial = dbus_message_get_reply_serial (message);
03576   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03577                                          reply_serial);
03578   if (pending)
03579     {
03580       _dbus_verbose ("Dispatching a pending reply\n");
03581       _dbus_pending_call_complete_and_unlock (pending, message);
03582       pending = NULL; /* it's probably unref'd */
03583       
03584       CONNECTION_LOCK (connection);
03585       _dbus_verbose ("pending call completed in dispatch\n");
03586       result = DBUS_HANDLER_RESULT_HANDLED;
03587       goto out;
03588     }
03589 
03590   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
03591   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03592     goto out;
03593  
03594   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03595     {
03596       _dbus_connection_release_dispatch (connection);
03597       HAVE_LOCK_CHECK (connection);
03598       
03599       _dbus_connection_failed_pop (connection, message_link);
03600 
03601       /* unlocks and calls user code */
03602       _dbus_connection_update_dispatch_status_and_unlock (connection,
03603                                                           DBUS_DISPATCH_NEED_MEMORY);
03604 
03605       if (pending)
03606         dbus_pending_call_unref (pending);
03607       dbus_connection_unref (connection);
03608       
03609       return DBUS_DISPATCH_NEED_MEMORY;
03610     }
03611   
03612   _dbus_list_foreach (&filter_list_copy,
03613                       (DBusForeachFunction)_dbus_message_filter_ref,
03614                       NULL);
03615 
03616   /* We're still protected from dispatch() reentrancy here
03617    * since we acquired the dispatcher
03618    */
03619   CONNECTION_UNLOCK (connection);
03620   
03621   link = _dbus_list_get_first_link (&filter_list_copy);
03622   while (link != NULL)
03623     {
03624       DBusMessageFilter *filter = link->data;
03625       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03626 
03627       _dbus_verbose ("  running filter on message %p\n", message);
03628       result = (* filter->function) (connection, message, filter->user_data);
03629 
03630       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03631         break;
03632 
03633       link = next;
03634     }
03635 
03636   _dbus_list_foreach (&filter_list_copy,
03637                       (DBusForeachFunction)_dbus_message_filter_unref,
03638                       NULL);
03639   _dbus_list_clear (&filter_list_copy);
03640   
03641   CONNECTION_LOCK (connection);
03642 
03643   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03644     {
03645       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03646       goto out;
03647     }
03648   else if (result == DBUS_HANDLER_RESULT_HANDLED)
03649     {
03650       _dbus_verbose ("filter handled message in dispatch\n");
03651       goto out;
03652     }
03653 
03654   /* We're still protected from dispatch() reentrancy here
03655    * since we acquired the dispatcher
03656    */
03657   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
03658                  message,
03659                  dbus_message_get_type (message),
03660                  dbus_message_get_interface (message) ?
03661                  dbus_message_get_interface (message) :
03662                  "no interface",
03663                  dbus_message_get_member (message) ?
03664                  dbus_message_get_member (message) :
03665                  "no member",
03666                  dbus_message_get_signature (message));
03667 
03668   HAVE_LOCK_CHECK (connection);
03669   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03670                                                   message);
03671   
03672   CONNECTION_LOCK (connection);
03673 
03674   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03675     {
03676       _dbus_verbose ("object tree handled message in dispatch\n");
03677       goto out;
03678     }
03679 
03680   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03681     {
03682       DBusMessage *reply;
03683       DBusString str;
03684       DBusPreallocatedSend *preallocated;
03685 
03686       _dbus_verbose ("  sending error %s\n",
03687                      DBUS_ERROR_UNKNOWN_METHOD);
03688       
03689       if (!_dbus_string_init (&str))
03690         {
03691           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03692           _dbus_verbose ("no memory for error string in dispatch\n");
03693           goto out;
03694         }
03695               
03696       if (!_dbus_string_append_printf (&str,
03697                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03698                                        dbus_message_get_member (message),
03699                                        dbus_message_get_signature (message),
03700                                        dbus_message_get_interface (message)))
03701         {
03702           _dbus_string_free (&str);
03703           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03704           _dbus_verbose ("no memory for error string in dispatch\n");
03705           goto out;
03706         }
03707       
03708       reply = dbus_message_new_error (message,
03709                                       DBUS_ERROR_UNKNOWN_METHOD,
03710                                       _dbus_string_get_const_data (&str));
03711       _dbus_string_free (&str);
03712 
03713       if (reply == NULL)
03714         {
03715           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03716           _dbus_verbose ("no memory for error reply in dispatch\n");
03717           goto out;
03718         }
03719       
03720       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03721 
03722       if (preallocated == NULL)
03723         {
03724           dbus_message_unref (reply);
03725           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03726           _dbus_verbose ("no memory for error send in dispatch\n");
03727           goto out;
03728         }
03729 
03730       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03731                                                              reply, NULL);
03732 
03733       dbus_message_unref (reply);
03734       
03735       result = DBUS_HANDLER_RESULT_HANDLED;
03736     }
03737   
03738   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03739                  dbus_message_get_type (message),
03740                  dbus_message_get_interface (message) ?
03741                  dbus_message_get_interface (message) :
03742                  "no interface",
03743                  dbus_message_get_member (message) ?
03744                  dbus_message_get_member (message) :
03745                  "no member",
03746                  dbus_message_get_signature (message),
03747                  connection);
03748   
03749  out:
03750   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03751     {
03752       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03753       
03754       /* Put message back, and we'll start over.
03755        * Yes this means handlers must be idempotent if they
03756        * don't return HANDLED; c'est la vie.
03757        */
03758       _dbus_connection_putback_message_link_unlocked (connection,
03759                                                       message_link);
03760     }
03761   else
03762     {
03763       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03764       
03765       if (connection->exit_on_disconnect &&
03766           dbus_message_is_signal (message,
03767                                   DBUS_INTERFACE_LOCAL,
03768                                   "Disconnected"))
03769         {
03770           _dbus_verbose ("Exiting on Disconnected signal\n");
03771           CONNECTION_UNLOCK (connection);
03772           _dbus_exit (1);
03773           _dbus_assert_not_reached ("Call to exit() returned");
03774         }
03775       
03776       _dbus_list_free_link (message_link);
03777       dbus_message_unref (message); /* don't want the message to count in max message limits
03778                                      * in computing dispatch status below
03779                                      */
03780     }
03781   
03782   _dbus_connection_release_dispatch (connection);
03783   HAVE_LOCK_CHECK (connection);
03784 
03785   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03786   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03787 
03788   /* unlocks and calls user code */
03789   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03790   
03791   dbus_connection_unref (connection);
03792   
03793   return status;
03794 }
03795 
03854 dbus_bool_t
03855 dbus_connection_set_watch_functions (DBusConnection              *connection,
03856                                      DBusAddWatchFunction         add_function,
03857                                      DBusRemoveWatchFunction      remove_function,
03858                                      DBusWatchToggledFunction     toggled_function,
03859                                      void                        *data,
03860                                      DBusFreeFunction             free_data_function)
03861 {
03862   dbus_bool_t retval;
03863   DBusWatchList *watches;
03864 
03865   _dbus_return_val_if_fail (connection != NULL, FALSE);
03866   
03867   CONNECTION_LOCK (connection);
03868 
03869 #ifndef DBUS_DISABLE_CHECKS
03870   if (connection->watches == NULL)
03871     {
03872       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03873                   _DBUS_FUNCTION_NAME);
03874       return FALSE;
03875     }
03876 #endif
03877   
03878   /* ref connection for slightly better reentrancy */
03879   _dbus_connection_ref_unlocked (connection);
03880 
03881   /* This can call back into user code, and we need to drop the
03882    * connection lock when it does. This is kind of a lame
03883    * way to do it.
03884    */
03885   watches = connection->watches;
03886   connection->watches = NULL;
03887   CONNECTION_UNLOCK (connection);
03888 
03889   retval = _dbus_watch_list_set_functions (watches,
03890                                            add_function, remove_function,
03891                                            toggled_function,
03892                                            data, free_data_function);
03893   CONNECTION_LOCK (connection);
03894   connection->watches = watches;
03895   
03896   CONNECTION_UNLOCK (connection);
03897   /* drop our paranoid refcount */
03898   dbus_connection_unref (connection);
03899   
03900   return retval;
03901 }
03902 
03936 dbus_bool_t
03937 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
03938                                          DBusAddTimeoutFunction     add_function,
03939                                          DBusRemoveTimeoutFunction  remove_function,
03940                                          DBusTimeoutToggledFunction toggled_function,
03941                                          void                      *data,
03942                                          DBusFreeFunction           free_data_function)
03943 {
03944   dbus_bool_t retval;
03945   DBusTimeoutList *timeouts;
03946 
03947   _dbus_return_val_if_fail (connection != NULL, FALSE);
03948   
03949   CONNECTION_LOCK (connection);
03950 
03951 #ifndef DBUS_DISABLE_CHECKS
03952   if (connection->timeouts == NULL)
03953     {
03954       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03955                   _DBUS_FUNCTION_NAME);
03956       return FALSE;
03957     }
03958 #endif
03959   
03960   /* ref connection for slightly better reentrancy */
03961   _dbus_connection_ref_unlocked (connection);
03962 
03963   timeouts = connection->timeouts;
03964   connection->timeouts = NULL;
03965   CONNECTION_UNLOCK (connection);
03966   
03967   retval = _dbus_timeout_list_set_functions (timeouts,
03968                                              add_function, remove_function,
03969                                              toggled_function,
03970                                              data, free_data_function);
03971   CONNECTION_LOCK (connection);
03972   connection->timeouts = timeouts;
03973   
03974   CONNECTION_UNLOCK (connection);
03975   /* drop our paranoid refcount */
03976   dbus_connection_unref (connection);
03977 
03978   return retval;
03979 }
03980 
03995 void
03996 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
03997                                           DBusWakeupMainFunction     wakeup_main_function,
03998                                           void                      *data,
03999                                           DBusFreeFunction           free_data_function)
04000 {
04001   void *old_data;
04002   DBusFreeFunction old_free_data;
04003 
04004   _dbus_return_if_fail (connection != NULL);
04005   
04006   CONNECTION_LOCK (connection);
04007   old_data = connection->wakeup_main_data;
04008   old_free_data = connection->free_wakeup_main_data;
04009 
04010   connection->wakeup_main_function = wakeup_main_function;
04011   connection->wakeup_main_data = data;
04012   connection->free_wakeup_main_data = free_data_function;
04013   
04014   CONNECTION_UNLOCK (connection);
04015 
04016   /* Callback outside the lock */
04017   if (old_free_data)
04018     (*old_free_data) (old_data);
04019 }
04020 
04037 void
04038 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04039                                               DBusDispatchStatusFunction  function,
04040                                               void                       *data,
04041                                               DBusFreeFunction            free_data_function)
04042 {
04043   void *old_data;
04044   DBusFreeFunction old_free_data;
04045 
04046   _dbus_return_if_fail (connection != NULL);
04047   
04048   CONNECTION_LOCK (connection);
04049   old_data = connection->dispatch_status_data;
04050   old_free_data = connection->free_dispatch_status_data;
04051 
04052   connection->dispatch_status_function = function;
04053   connection->dispatch_status_data = data;
04054   connection->free_dispatch_status_data = free_data_function;
04055   
04056   CONNECTION_UNLOCK (connection);
04057 
04058   /* Callback outside the lock */
04059   if (old_free_data)
04060     (*old_free_data) (old_data);
04061 }
04062 
04075 dbus_bool_t
04076 dbus_connection_get_unix_fd (DBusConnection *connection,
04077                              int            *fd)
04078 {
04079   dbus_bool_t retval;
04080 
04081   _dbus_return_val_if_fail (connection != NULL, FALSE);
04082   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04083   
04084   CONNECTION_LOCK (connection);
04085   
04086   retval = _dbus_transport_get_unix_fd (connection->transport,
04087                                         fd);
04088 
04089   CONNECTION_UNLOCK (connection);
04090 
04091   return retval;
04092 }
04093 
04105 dbus_bool_t
04106 dbus_connection_get_unix_user (DBusConnection *connection,
04107                                unsigned long  *uid)
04108 {
04109   dbus_bool_t result;
04110 
04111   _dbus_return_val_if_fail (connection != NULL, FALSE);
04112   _dbus_return_val_if_fail (uid != NULL, FALSE);
04113   
04114   CONNECTION_LOCK (connection);
04115 
04116   if (!_dbus_transport_get_is_authenticated (connection->transport))
04117     result = FALSE;
04118   else
04119     result = _dbus_transport_get_unix_user (connection->transport,
04120                                             uid);
04121   CONNECTION_UNLOCK (connection);
04122 
04123   return result;
04124 }
04125 
04136 dbus_bool_t
04137 dbus_connection_get_unix_process_id (DBusConnection *connection,
04138                                      unsigned long  *pid)
04139 {
04140   dbus_bool_t result;
04141 
04142   _dbus_return_val_if_fail (connection != NULL, FALSE);
04143   _dbus_return_val_if_fail (pid != NULL, FALSE);
04144   
04145   CONNECTION_LOCK (connection);
04146 
04147   if (!_dbus_transport_get_is_authenticated (connection->transport))
04148     result = FALSE;
04149   else
04150     result = _dbus_transport_get_unix_process_id (connection->transport,
04151                                                   pid);
04152   CONNECTION_UNLOCK (connection);
04153 
04154   return result;
04155 }
04156 
04173 void
04174 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04175                                         DBusAllowUnixUserFunction   function,
04176                                         void                       *data,
04177                                         DBusFreeFunction            free_data_function)
04178 {
04179   void *old_data = NULL;
04180   DBusFreeFunction old_free_function = NULL;
04181 
04182   _dbus_return_if_fail (connection != NULL);
04183   
04184   CONNECTION_LOCK (connection);
04185   _dbus_transport_set_unix_user_function (connection->transport,
04186                                           function, data, free_data_function,
04187                                           &old_data, &old_free_function);
04188   CONNECTION_UNLOCK (connection);
04189 
04190   if (old_free_function != NULL)
04191     (* old_free_function) (old_data);    
04192 }
04193 
04215 dbus_bool_t
04216 dbus_connection_add_filter (DBusConnection            *connection,
04217                             DBusHandleMessageFunction  function,
04218                             void                      *user_data,
04219                             DBusFreeFunction           free_data_function)
04220 {
04221   DBusMessageFilter *filter;
04222   
04223   _dbus_return_val_if_fail (connection != NULL, FALSE);
04224   _dbus_return_val_if_fail (function != NULL, FALSE);
04225 
04226   filter = dbus_new0 (DBusMessageFilter, 1);
04227   if (filter == NULL)
04228     return FALSE;
04229 
04230   filter->refcount.value = 1;
04231   
04232   CONNECTION_LOCK (connection);
04233 
04234   if (!_dbus_list_append (&connection->filter_list,
04235                           filter))
04236     {
04237       _dbus_message_filter_unref (filter);
04238       CONNECTION_UNLOCK (connection);
04239       return FALSE;
04240     }
04241 
04242   /* Fill in filter after all memory allocated,
04243    * so we don't run the free_user_data_function
04244    * if the add_filter() fails
04245    */
04246   
04247   filter->function = function;
04248   filter->user_data = user_data;
04249   filter->free_user_data_function = free_data_function;
04250         
04251   CONNECTION_UNLOCK (connection);
04252   return TRUE;
04253 }
04254 
04267 void
04268 dbus_connection_remove_filter (DBusConnection            *connection,
04269                                DBusHandleMessageFunction  function,
04270                                void                      *user_data)
04271 {
04272   DBusList *link;
04273   DBusMessageFilter *filter;
04274   
04275   _dbus_return_if_fail (connection != NULL);
04276   _dbus_return_if_fail (function != NULL);
04277   
04278   CONNECTION_LOCK (connection);
04279 
04280   filter = NULL;
04281   
04282   link = _dbus_list_get_last_link (&connection->filter_list);
04283   while (link != NULL)
04284     {
04285       filter = link->data;
04286 
04287       if (filter->function == function &&
04288           filter->user_data == user_data)
04289         {
04290           _dbus_list_remove_link (&connection->filter_list, link);
04291           filter->function = NULL;
04292           
04293           break;
04294         }
04295         
04296       link = _dbus_list_get_prev_link (&connection->filter_list, link);
04297     }
04298   
04299   CONNECTION_UNLOCK (connection);
04300 
04301 #ifndef DBUS_DISABLE_CHECKS
04302   if (filter == NULL)
04303     {
04304       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04305                   function, user_data);
04306       return;
04307     }
04308 #endif
04309   
04310   /* Call application code */
04311   if (filter->free_user_data_function)
04312     (* filter->free_user_data_function) (filter->user_data);
04313 
04314   filter->free_user_data_function = NULL;
04315   filter->user_data = NULL;
04316   
04317   _dbus_message_filter_unref (filter);
04318 }
04319 
04331 dbus_bool_t
04332 dbus_connection_register_object_path (DBusConnection              *connection,
04333                                       const char                  *path,
04334                                       const DBusObjectPathVTable  *vtable,
04335                                       void                        *user_data)
04336 {
04337   char **decomposed_path;
04338   dbus_bool_t retval;
04339   
04340   _dbus_return_val_if_fail (connection != NULL, FALSE);
04341   _dbus_return_val_if_fail (path != NULL, FALSE);
04342   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04343   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04344 
04345   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04346     return FALSE;
04347 
04348   CONNECTION_LOCK (connection);
04349 
04350   retval = _dbus_object_tree_register (connection->objects,
04351                                        FALSE,
04352                                        (const char **) decomposed_path, vtable,
04353                                        user_data);
04354 
04355   CONNECTION_UNLOCK (connection);
04356 
04357   dbus_free_string_array (decomposed_path);
04358 
04359   return retval;
04360 }
04361 
04374 dbus_bool_t
04375 dbus_connection_register_fallback (DBusConnection              *connection,
04376                                    const char                  *path,
04377                                    const DBusObjectPathVTable  *vtable,
04378                                    void                        *user_data)
04379 {
04380   char **decomposed_path;
04381   dbus_bool_t retval;
04382   
04383   _dbus_return_val_if_fail (connection != NULL, FALSE);
04384   _dbus_return_val_if_fail (path != NULL, FALSE);
04385   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04386   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04387 
04388   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04389     return FALSE;
04390 
04391   CONNECTION_LOCK (connection);
04392 
04393   retval = _dbus_object_tree_register (connection->objects,
04394                                        TRUE,
04395                                        (const char **) decomposed_path, vtable,
04396                                        user_data);
04397 
04398   CONNECTION_UNLOCK (connection);
04399 
04400   dbus_free_string_array (decomposed_path);
04401 
04402   return retval;
04403 }
04404 
04414 dbus_bool_t
04415 dbus_connection_unregister_object_path (DBusConnection              *connection,
04416                                         const char                  *path)
04417 {
04418   char **decomposed_path;
04419 
04420   _dbus_return_val_if_fail (connection != NULL, FALSE);
04421   _dbus_return_val_if_fail (path != NULL, FALSE);
04422   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04423 
04424   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04425       return FALSE;
04426 
04427   CONNECTION_LOCK (connection);
04428 
04429   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04430 
04431   dbus_free_string_array (decomposed_path);
04432 
04433   return TRUE;
04434 }
04435 
04446 dbus_bool_t
04447 dbus_connection_get_object_path_data (DBusConnection *connection,
04448                                       const char     *path,
04449                                       void          **data_p)
04450 {
04451   char **decomposed_path;
04452 
04453   _dbus_return_val_if_fail (connection != NULL, FALSE);
04454   _dbus_return_val_if_fail (path != NULL, FALSE);
04455   _dbus_return_val_if_fail (data_p != NULL, FALSE);
04456 
04457   *data_p = NULL;
04458   
04459   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04460     return FALSE;
04461   
04462   CONNECTION_LOCK (connection);
04463 
04464   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04465 
04466   CONNECTION_UNLOCK (connection);
04467 
04468   dbus_free_string_array (decomposed_path);
04469 
04470   return TRUE;
04471 }
04472 
04483 dbus_bool_t
04484 dbus_connection_list_registered (DBusConnection              *connection,
04485                                  const char                  *parent_path,
04486                                  char                      ***child_entries)
04487 {
04488   char **decomposed_path;
04489   dbus_bool_t retval;
04490   _dbus_return_val_if_fail (connection != NULL, FALSE);
04491   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04492   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04493   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04494 
04495   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04496     return FALSE;
04497 
04498   CONNECTION_LOCK (connection);
04499 
04500   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04501                                                          (const char **) decomposed_path,
04502                                                          child_entries);
04503   dbus_free_string_array (decomposed_path);
04504 
04505   return retval;
04506 }
04507 
04508 static DBusDataSlotAllocator slot_allocator;
04509 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04510 
04525 dbus_bool_t
04526 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04527 {
04528   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04529                                           _DBUS_LOCK_NAME (connection_slots),
04530                                           slot_p);
04531 }
04532 
04544 void
04545 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04546 {
04547   _dbus_return_if_fail (*slot_p >= 0);
04548   
04549   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04550 }
04551 
04565 dbus_bool_t
04566 dbus_connection_set_data (DBusConnection   *connection,
04567                           dbus_int32_t      slot,
04568                           void             *data,
04569                           DBusFreeFunction  free_data_func)
04570 {
04571   DBusFreeFunction old_free_func;
04572   void *old_data;
04573   dbus_bool_t retval;
04574 
04575   _dbus_return_val_if_fail (connection != NULL, FALSE);
04576   _dbus_return_val_if_fail (slot >= 0, FALSE);
04577   
04578   CONNECTION_LOCK (connection);
04579 
04580   retval = _dbus_data_slot_list_set (&slot_allocator,
04581                                      &connection->slot_list,
04582                                      slot, data, free_data_func,
04583                                      &old_free_func, &old_data);
04584   
04585   CONNECTION_UNLOCK (connection);
04586 
04587   if (retval)
04588     {
04589       /* Do the actual free outside the connection lock */
04590       if (old_free_func)
04591         (* old_free_func) (old_data);
04592     }
04593 
04594   return retval;
04595 }
04596 
04605 void*
04606 dbus_connection_get_data (DBusConnection   *connection,
04607                           dbus_int32_t      slot)
04608 {
04609   void *res;
04610 
04611   _dbus_return_val_if_fail (connection != NULL, NULL);
04612   
04613   CONNECTION_LOCK (connection);
04614 
04615   res = _dbus_data_slot_list_get (&slot_allocator,
04616                                   &connection->slot_list,
04617                                   slot);
04618   
04619   CONNECTION_UNLOCK (connection);
04620 
04621   return res;
04622 }
04623 
04630 void
04631 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04632 {  
04633   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04634 }
04635 
04644 void
04645 dbus_connection_set_max_message_size (DBusConnection *connection,
04646                                       long            size)
04647 {
04648   _dbus_return_if_fail (connection != NULL);
04649   
04650   CONNECTION_LOCK (connection);
04651   _dbus_transport_set_max_message_size (connection->transport,
04652                                         size);
04653   CONNECTION_UNLOCK (connection);
04654 }
04655 
04662 long
04663 dbus_connection_get_max_message_size (DBusConnection *connection)
04664 {
04665   long res;
04666 
04667   _dbus_return_val_if_fail (connection != NULL, 0);
04668   
04669   CONNECTION_LOCK (connection);
04670   res = _dbus_transport_get_max_message_size (connection->transport);
04671   CONNECTION_UNLOCK (connection);
04672   return res;
04673 }
04674 
04700 void
04701 dbus_connection_set_max_received_size (DBusConnection *connection,
04702                                        long            size)
04703 {
04704   _dbus_return_if_fail (connection != NULL);
04705   
04706   CONNECTION_LOCK (connection);
04707   _dbus_transport_set_max_received_size (connection->transport,
04708                                          size);
04709   CONNECTION_UNLOCK (connection);
04710 }
04711 
04718 long
04719 dbus_connection_get_max_received_size (DBusConnection *connection)
04720 {
04721   long res;
04722 
04723   _dbus_return_val_if_fail (connection != NULL, 0);
04724   
04725   CONNECTION_LOCK (connection);
04726   res = _dbus_transport_get_max_received_size (connection->transport);
04727   CONNECTION_UNLOCK (connection);
04728   return res;
04729 }
04730 
04741 long
04742 dbus_connection_get_outgoing_size (DBusConnection *connection)
04743 {
04744   long res;
04745 
04746   _dbus_return_val_if_fail (connection != NULL, 0);
04747   
04748   CONNECTION_LOCK (connection);
04749   res = _dbus_counter_get_value (connection->outgoing_counter);
04750   CONNECTION_UNLOCK (connection);
04751   return res;
04752 }
04753 

Generated on Wed Feb 27 10:13:37 2008 for D-BUS by  doxygen 1.4.6