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

dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002, 2003, 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 (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_interface (message) ?
00396                  dbus_message_get_interface (message) :
00397                  "no interface",
00398                  dbus_message_get_member (message) ?
00399                  dbus_message_get_member (message) :
00400                  "no member",
00401                  dbus_message_get_signature (message),
00402                  dbus_message_get_reply_serial (message),
00403                  connection,
00404                  connection->n_incoming);
00405 }
00406 
00417 static void
00418 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00419                                                  DBusList *link)
00420 {
00421   HAVE_LOCK_CHECK (connection);
00422   
00423   _dbus_list_append_link (&connection->incoming_messages, link);
00424 
00425   connection->n_incoming += 1;
00426 
00427   _dbus_connection_wakeup_mainloop (connection);
00428   
00429   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00430                  link->data, connection, connection->n_incoming);
00431 }
00432 
00433 
00441 dbus_bool_t
00442 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00443 {
00444   HAVE_LOCK_CHECK (connection);
00445   return connection->outgoing_messages != NULL;
00446 }
00447 
00454 dbus_bool_t
00455 dbus_connection_has_messages_to_send (DBusConnection *connection)
00456 {
00457   dbus_bool_t v;
00458   
00459   _dbus_return_val_if_fail (connection != NULL, FALSE);
00460 
00461   CONNECTION_LOCK (connection);
00462   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00463   CONNECTION_UNLOCK (connection);
00464 
00465   return v;
00466 }
00467 
00475 DBusMessage*
00476 _dbus_connection_get_message_to_send (DBusConnection *connection)
00477 {
00478   HAVE_LOCK_CHECK (connection);
00479   
00480   return _dbus_list_get_last (&connection->outgoing_messages);
00481 }
00482 
00491 void
00492 _dbus_connection_message_sent (DBusConnection *connection,
00493                                DBusMessage    *message)
00494 {
00495   DBusList *link;
00496 
00497   HAVE_LOCK_CHECK (connection);
00498   
00499   /* This can be called before we even complete authentication, since
00500    * it's called on disconnect to clean up the outgoing queue.
00501    * It's also called as we successfully send each message.
00502    */
00503   
00504   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00505   _dbus_assert (link != NULL);
00506   _dbus_assert (link->data == message);
00507 
00508   /* Save this link in the link cache */
00509   _dbus_list_unlink (&connection->outgoing_messages,
00510                      link);
00511   _dbus_list_prepend_link (&connection->link_cache, link);
00512   
00513   connection->n_outgoing -= 1;
00514 
00515   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00516                  message,
00517                  dbus_message_get_type (message),
00518                  dbus_message_get_path (message),
00519                  dbus_message_get_interface (message) ?
00520                  dbus_message_get_interface (message) :
00521                  "no interface",
00522                  dbus_message_get_member (message) ?
00523                  dbus_message_get_member (message) :
00524                  "no member",
00525                  dbus_message_get_signature (message),
00526                  connection, connection->n_outgoing);
00527 
00528   /* Save this link in the link cache also */
00529   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00530                                      &link);
00531   _dbus_list_prepend_link (&connection->link_cache, link);
00532   
00533   dbus_message_unref (message);
00534 }
00535 
00536 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00537                                                   DBusWatch     *watch);
00538 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00539                                                   DBusWatch     *watch);
00540 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00541                                                   DBusWatch     *watch,
00542                                                   dbus_bool_t    enabled);
00543 
00544 static dbus_bool_t
00545 protected_change_watch (DBusConnection         *connection,
00546                         DBusWatch              *watch,
00547                         DBusWatchAddFunction    add_function,
00548                         DBusWatchRemoveFunction remove_function,
00549                         DBusWatchToggleFunction toggle_function,
00550                         dbus_bool_t             enabled)
00551 {
00552   DBusWatchList *watches;
00553   dbus_bool_t retval;
00554   
00555   HAVE_LOCK_CHECK (connection);
00556 
00557   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00558    * drop lock and call out" one; but it has to be propagated up through all callers
00559    */
00560   
00561   watches = connection->watches;
00562   if (watches)
00563     {
00564       connection->watches = NULL;
00565       _dbus_connection_ref_unlocked (connection);
00566       CONNECTION_UNLOCK (connection);
00567 
00568       if (add_function)
00569         retval = (* add_function) (watches, watch);
00570       else if (remove_function)
00571         {
00572           retval = TRUE;
00573           (* remove_function) (watches, watch);
00574         }
00575       else
00576         {
00577           retval = TRUE;
00578           (* toggle_function) (watches, watch, enabled);
00579         }
00580       
00581       CONNECTION_LOCK (connection);
00582       connection->watches = watches;
00583       _dbus_connection_unref_unlocked (connection);
00584 
00585       return retval;
00586     }
00587   else
00588     return FALSE;
00589 }
00590      
00591 
00602 dbus_bool_t
00603 _dbus_connection_add_watch (DBusConnection *connection,
00604                             DBusWatch      *watch)
00605 {
00606   return protected_change_watch (connection, watch,
00607                                  _dbus_watch_list_add_watch,
00608                                  NULL, NULL, FALSE);
00609 }
00610 
00619 void
00620 _dbus_connection_remove_watch (DBusConnection *connection,
00621                                DBusWatch      *watch)
00622 {
00623   protected_change_watch (connection, watch,
00624                           NULL,
00625                           _dbus_watch_list_remove_watch,
00626                           NULL, FALSE);
00627 }
00628 
00639 void
00640 _dbus_connection_toggle_watch (DBusConnection *connection,
00641                                DBusWatch      *watch,
00642                                dbus_bool_t     enabled)
00643 {
00644   _dbus_assert (watch != NULL);
00645 
00646   protected_change_watch (connection, watch,
00647                           NULL, NULL,
00648                           _dbus_watch_list_toggle_watch,
00649                           enabled);
00650 }
00651 
00652 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00653                                                    DBusTimeout     *timeout);
00654 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00655                                                    DBusTimeout     *timeout);
00656 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00657                                                    DBusTimeout     *timeout,
00658                                                    dbus_bool_t      enabled);
00659 
00660 static dbus_bool_t
00661 protected_change_timeout (DBusConnection           *connection,
00662                           DBusTimeout              *timeout,
00663                           DBusTimeoutAddFunction    add_function,
00664                           DBusTimeoutRemoveFunction remove_function,
00665                           DBusTimeoutToggleFunction toggle_function,
00666                           dbus_bool_t               enabled)
00667 {
00668   DBusTimeoutList *timeouts;
00669   dbus_bool_t retval;
00670   
00671   HAVE_LOCK_CHECK (connection);
00672 
00673   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00674    * drop lock and call out" one; but it has to be propagated up through all callers
00675    */
00676   
00677   timeouts = connection->timeouts;
00678   if (timeouts)
00679     {
00680       connection->timeouts = NULL;
00681       _dbus_connection_ref_unlocked (connection);
00682       CONNECTION_UNLOCK (connection);
00683 
00684       if (add_function)
00685         retval = (* add_function) (timeouts, timeout);
00686       else if (remove_function)
00687         {
00688           retval = TRUE;
00689           (* remove_function) (timeouts, timeout);
00690         }
00691       else
00692         {
00693           retval = TRUE;
00694           (* toggle_function) (timeouts, timeout, enabled);
00695         }
00696       
00697       CONNECTION_LOCK (connection);
00698       connection->timeouts = timeouts;
00699       _dbus_connection_unref_unlocked (connection);
00700 
00701       return retval;
00702     }
00703   else
00704     return FALSE;
00705 }
00706 
00718 dbus_bool_t
00719 _dbus_connection_add_timeout (DBusConnection *connection,
00720                               DBusTimeout    *timeout)
00721 {
00722   return protected_change_timeout (connection, timeout,
00723                                    _dbus_timeout_list_add_timeout,
00724                                    NULL, NULL, FALSE);
00725 }
00726 
00735 void
00736 _dbus_connection_remove_timeout (DBusConnection *connection,
00737                                  DBusTimeout    *timeout)
00738 {
00739   protected_change_timeout (connection, timeout,
00740                             NULL,
00741                             _dbus_timeout_list_remove_timeout,
00742                             NULL, FALSE);
00743 }
00744 
00754 void
00755 _dbus_connection_toggle_timeout (DBusConnection   *connection,
00756                                  DBusTimeout      *timeout,
00757                                  dbus_bool_t       enabled)
00758 {
00759   protected_change_timeout (connection, timeout,
00760                             NULL, NULL,
00761                             _dbus_timeout_list_toggle_timeout,
00762                             enabled);
00763 }
00764 
00765 static dbus_bool_t
00766 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00767                                                DBusPendingCall *pending)
00768 {
00769   HAVE_LOCK_CHECK (connection);
00770   
00771   _dbus_assert (pending->reply_serial != 0);
00772 
00773   if (!_dbus_connection_add_timeout (connection, pending->timeout))
00774     return FALSE;
00775   
00776   if (!_dbus_hash_table_insert_int (connection->pending_replies,
00777                                     pending->reply_serial,
00778                                     pending))
00779     {
00780       _dbus_connection_remove_timeout (connection, pending->timeout);
00781 
00782       HAVE_LOCK_CHECK (connection);
00783       return FALSE;
00784     }
00785   
00786   pending->timeout_added = TRUE;
00787   pending->connection = connection;
00788 
00789   dbus_pending_call_ref (pending);
00790 
00791   HAVE_LOCK_CHECK (connection);
00792   
00793   return TRUE;
00794 }
00795 
00796 static void
00797 free_pending_call_on_hash_removal (void *data)
00798 {
00799   DBusPendingCall *pending;
00800   
00801   if (data == NULL)
00802     return;
00803 
00804   pending = data;
00805 
00806   if (pending->connection)
00807     {
00808       if (pending->timeout_added)
00809         {
00810           _dbus_connection_remove_timeout (pending->connection,
00811                                            pending->timeout);
00812           pending->timeout_added = FALSE;
00813         }
00814 
00815       pending->connection = NULL;
00816       
00817       dbus_pending_call_unref (pending);
00818     }
00819 }
00820 
00821 static void
00822 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00823                                                DBusPendingCall *pending)
00824 {
00825   /* Can't have a destroy notifier on the pending call if we're going to do this */
00826 
00827   dbus_pending_call_ref (pending);
00828   _dbus_hash_table_remove_int (connection->pending_replies,
00829                                pending->reply_serial);
00830   _dbus_assert (pending->connection == NULL);
00831   dbus_pending_call_unref (pending);
00832 }
00833 
00834 static void
00835 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00836                                                  DBusPendingCall *pending)
00837 {
00838   /* The idea here is to avoid finalizing the pending call
00839    * with the lock held, since there's a destroy notifier
00840    * in pending call that goes out to application code.
00841    */
00842   dbus_pending_call_ref (pending);
00843   _dbus_hash_table_remove_int (connection->pending_replies,
00844                                pending->reply_serial);
00845   _dbus_assert (pending->connection == NULL);
00846   CONNECTION_UNLOCK (connection);
00847   dbus_pending_call_unref (pending);
00848 }
00849 
00858 void
00859 _dbus_connection_remove_pending_call (DBusConnection  *connection,
00860                                       DBusPendingCall *pending)
00861 {
00862   CONNECTION_LOCK (connection);
00863   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00864 }
00865 
00874 void
00875 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00876                                         DBusMessage     *message)
00877 {
00878   if (message == NULL)
00879     {
00880       message = pending->timeout_link->data;
00881       _dbus_list_clear (&pending->timeout_link);
00882     }
00883   else
00884     dbus_message_ref (message);
00885 
00886   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
00887                  message,
00888                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00889                  "method return" :
00890                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00891                  "error" : "other type",
00892                  pending->reply_serial);
00893   
00894   _dbus_assert (pending->reply == NULL);
00895   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00896   pending->reply = message;
00897   
00898   dbus_pending_call_ref (pending); /* in case there's no app with a ref held */
00899   _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00900   
00901   /* Must be called unlocked since it invokes app callback */
00902   _dbus_pending_call_notify (pending);
00903   dbus_pending_call_unref (pending);
00904 }
00905 
00915 static dbus_bool_t
00916 _dbus_connection_acquire_io_path (DBusConnection *connection,
00917                                   int timeout_milliseconds)
00918 {
00919   dbus_bool_t we_acquired;
00920   
00921   HAVE_LOCK_CHECK (connection);
00922 
00923   /* We don't want the connection to vanish */
00924   _dbus_connection_ref_unlocked (connection);
00925 
00926   /* We will only touch io_path_acquired which is protected by our mutex */
00927   CONNECTION_UNLOCK (connection);
00928   
00929   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00930   _dbus_mutex_lock (connection->io_path_mutex);
00931 
00932   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00933                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00934 
00935   we_acquired = FALSE;
00936   
00937   if (connection->io_path_acquired)
00938     {
00939       if (timeout_milliseconds != -1)
00940         {
00941           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00942                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
00943           _dbus_condvar_wait_timeout (connection->io_path_cond,
00944                                       connection->io_path_mutex,
00945                                       timeout_milliseconds);
00946         }
00947       else
00948         {
00949           while (connection->io_path_acquired)
00950             {
00951               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00952               _dbus_condvar_wait (connection->io_path_cond, connection->io_path_mutex);
00953             }
00954         }
00955     }
00956   
00957   if (!connection->io_path_acquired)
00958     {
00959       we_acquired = TRUE;
00960       connection->io_path_acquired = TRUE;
00961     }
00962   
00963   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00964                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00965 
00966   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00967   _dbus_mutex_unlock (connection->io_path_mutex);
00968 
00969   CONNECTION_LOCK (connection);
00970   
00971   HAVE_LOCK_CHECK (connection);
00972 
00973   _dbus_connection_unref_unlocked (connection);
00974   
00975   return we_acquired;
00976 }
00977 
00985 static void
00986 _dbus_connection_release_io_path (DBusConnection *connection)
00987 {
00988   HAVE_LOCK_CHECK (connection);
00989   
00990   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00991   _dbus_mutex_lock (connection->io_path_mutex);
00992   
00993   _dbus_assert (connection->io_path_acquired);
00994 
00995   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
00996                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
00997   
00998   connection->io_path_acquired = FALSE;
00999   _dbus_condvar_wake_one (connection->io_path_cond);
01000 
01001   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01002   _dbus_mutex_unlock (connection->io_path_mutex);
01003 }
01004 
01033 void
01034 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01035                                         unsigned int    flags,
01036                                         int             timeout_milliseconds)
01037 {
01038   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01039   
01040   HAVE_LOCK_CHECK (connection);
01041   
01042   if (connection->n_outgoing == 0)
01043     flags &= ~DBUS_ITERATION_DO_WRITING;
01044 
01045   if (_dbus_connection_acquire_io_path (connection,
01046                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01047     {
01048       HAVE_LOCK_CHECK (connection);
01049       
01050       _dbus_transport_do_iteration (connection->transport,
01051                                     flags, timeout_milliseconds);
01052       _dbus_connection_release_io_path (connection);
01053     }
01054 
01055   HAVE_LOCK_CHECK (connection);
01056 
01057   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01058 }
01059 
01069 DBusConnection*
01070 _dbus_connection_new_for_transport (DBusTransport *transport)
01071 {
01072   DBusConnection *connection;
01073   DBusWatchList *watch_list;
01074   DBusTimeoutList *timeout_list;
01075   DBusHashTable *pending_replies;
01076   DBusMutex *mutex;
01077   DBusMutex *io_path_mutex;
01078   DBusMutex *dispatch_mutex;
01079   DBusCondVar *dispatch_cond;
01080   DBusCondVar *io_path_cond;
01081   DBusList *disconnect_link;
01082   DBusMessage *disconnect_message;
01083   DBusCounter *outgoing_counter;
01084   DBusObjectTree *objects;
01085   
01086   watch_list = NULL;
01087   connection = NULL;
01088   pending_replies = NULL;
01089   timeout_list = NULL;
01090   mutex = NULL;
01091   io_path_mutex = NULL;
01092   dispatch_mutex = NULL;
01093   dispatch_cond = NULL;
01094   io_path_cond = NULL;
01095   disconnect_link = NULL;
01096   disconnect_message = NULL;
01097   outgoing_counter = NULL;
01098   objects = NULL;
01099   
01100   watch_list = _dbus_watch_list_new ();
01101   if (watch_list == NULL)
01102     goto error;
01103 
01104   timeout_list = _dbus_timeout_list_new ();
01105   if (timeout_list == NULL)
01106     goto error;  
01107 
01108   pending_replies =
01109     _dbus_hash_table_new (DBUS_HASH_INT,
01110                           NULL,
01111                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01112   if (pending_replies == NULL)
01113     goto error;
01114   
01115   connection = dbus_new0 (DBusConnection, 1);
01116   if (connection == NULL)
01117     goto error;
01118 
01119   mutex = _dbus_mutex_new ();
01120   if (mutex == NULL)
01121     goto error;
01122 
01123   io_path_mutex = _dbus_mutex_new ();
01124   if (io_path_mutex == NULL)
01125     goto error;
01126 
01127   dispatch_mutex = _dbus_mutex_new ();
01128   if (dispatch_mutex == NULL)
01129     goto error;
01130   
01131   dispatch_cond = _dbus_condvar_new ();
01132   if (dispatch_cond == NULL)
01133     goto error;
01134   
01135   io_path_cond = _dbus_condvar_new ();
01136   if (io_path_cond == NULL)
01137     goto error;
01138 
01139   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01140                                                 DBUS_INTERFACE_LOCAL,
01141                                                 "Disconnected");
01142   
01143   if (disconnect_message == NULL)
01144     goto error;
01145 
01146   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01147   if (disconnect_link == NULL)
01148     goto error;
01149 
01150   outgoing_counter = _dbus_counter_new ();
01151   if (outgoing_counter == NULL)
01152     goto error;
01153 
01154   objects = _dbus_object_tree_new (connection);
01155   if (objects == NULL)
01156     goto error;
01157   
01158   if (_dbus_modify_sigpipe)
01159     _dbus_disable_sigpipe ();
01160   
01161   connection->refcount.value = 1;
01162   connection->mutex = mutex;
01163   connection->dispatch_cond = dispatch_cond;
01164   connection->dispatch_mutex = dispatch_mutex;
01165   connection->io_path_cond = io_path_cond;
01166   connection->io_path_mutex = io_path_mutex;
01167   connection->transport = transport;
01168   connection->watches = watch_list;
01169   connection->timeouts = timeout_list;
01170   connection->pending_replies = pending_replies;
01171   connection->outgoing_counter = outgoing_counter;
01172   connection->filter_list = NULL;
01173   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01174   connection->objects = objects;
01175   connection->exit_on_disconnect = FALSE;
01176   connection->shareable = FALSE;
01177 #ifndef DBUS_DISABLE_CHECKS
01178   connection->generation = _dbus_current_generation;
01179 #endif
01180   
01181   _dbus_data_slot_list_init (&connection->slot_list);
01182 
01183   connection->client_serial = 1;
01184 
01185   connection->disconnect_message_link = disconnect_link;
01186 
01187   CONNECTION_LOCK (connection);
01188   
01189   if (!_dbus_transport_set_connection (transport, connection))
01190     goto error;
01191 
01192   _dbus_transport_ref (transport);
01193 
01194   CONNECTION_UNLOCK (connection);
01195   
01196   return connection;
01197   
01198  error:
01199   if (disconnect_message != NULL)
01200     dbus_message_unref (disconnect_message);
01201   
01202   if (disconnect_link != NULL)
01203     _dbus_list_free_link (disconnect_link);
01204   
01205   if (io_path_cond != NULL)
01206     _dbus_condvar_free (io_path_cond);
01207   
01208   if (dispatch_cond != NULL)
01209     _dbus_condvar_free (dispatch_cond);
01210   
01211   if (mutex != NULL)
01212     _dbus_mutex_free (mutex);
01213 
01214   if (io_path_mutex != NULL)
01215     _dbus_mutex_free (io_path_mutex);
01216 
01217   if (dispatch_mutex != NULL)
01218     _dbus_mutex_free (dispatch_mutex);
01219   
01220   if (connection != NULL)
01221     dbus_free (connection);
01222 
01223   if (pending_replies)
01224     _dbus_hash_table_unref (pending_replies);
01225   
01226   if (watch_list)
01227     _dbus_watch_list_free (watch_list);
01228 
01229   if (timeout_list)
01230     _dbus_timeout_list_free (timeout_list);
01231 
01232   if (outgoing_counter)
01233     _dbus_counter_unref (outgoing_counter);
01234 
01235   if (objects)
01236     _dbus_object_tree_unref (objects);
01237   
01238   return NULL;
01239 }
01240 
01248 DBusConnection *
01249 _dbus_connection_ref_unlocked (DBusConnection *connection)
01250 {  
01251   _dbus_assert (connection != NULL);
01252   _dbus_assert (connection->generation == _dbus_current_generation);
01253 
01254   HAVE_LOCK_CHECK (connection);
01255   
01256 #ifdef DBUS_HAVE_ATOMIC_INT
01257   _dbus_atomic_inc (&connection->refcount);
01258 #else
01259   _dbus_assert (connection->refcount.value > 0);
01260   connection->refcount.value += 1;
01261 #endif
01262 
01263   return connection;
01264 }
01265 
01272 void
01273 _dbus_connection_unref_unlocked (DBusConnection *connection)
01274 {
01275   dbus_bool_t last_unref;
01276 
01277   HAVE_LOCK_CHECK (connection);
01278   
01279   _dbus_assert (connection != NULL);
01280 
01281   /* The connection lock is better than the global
01282    * lock in the atomic increment fallback
01283    */
01284   
01285 #ifdef DBUS_HAVE_ATOMIC_INT
01286   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01287 #else
01288   _dbus_assert (connection->refcount.value > 0);
01289 
01290   connection->refcount.value -= 1;
01291   last_unref = (connection->refcount.value == 0);  
01292 #if 0
01293   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01294 #endif
01295 #endif
01296   
01297   if (last_unref)
01298     _dbus_connection_last_unref (connection);
01299 }
01300 
01301 static dbus_uint32_t
01302 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01303 {
01304   int serial;
01305 
01306   serial = connection->client_serial++;
01307 
01308   if (connection->client_serial < 0)
01309     connection->client_serial = 1;
01310   
01311   return serial;
01312 }
01313 
01327 dbus_bool_t
01328 _dbus_connection_handle_watch (DBusWatch                   *watch,
01329                                unsigned int                 condition,
01330                                void                        *data)
01331 {
01332   DBusConnection *connection;
01333   dbus_bool_t retval;
01334   DBusDispatchStatus status;
01335 
01336   connection = data;
01337 
01338   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01339   
01340   CONNECTION_LOCK (connection);
01341   _dbus_connection_acquire_io_path (connection, -1);
01342   HAVE_LOCK_CHECK (connection);
01343   retval = _dbus_transport_handle_watch (connection->transport,
01344                                          watch, condition);
01345 
01346   _dbus_connection_release_io_path (connection);
01347 
01348   HAVE_LOCK_CHECK (connection);
01349 
01350   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01351   
01352   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01353 
01354   /* this calls out to user code */
01355   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01356 
01357   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01358   
01359   return retval;
01360 }
01361 
01362 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01363 static DBusHashTable *shared_connections = NULL;
01364 
01365 static void
01366 shared_connections_shutdown (void *data)
01367 {
01368   _DBUS_LOCK (shared_connections);
01369 
01370   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01371   _dbus_hash_table_unref (shared_connections);
01372   shared_connections = NULL;
01373   
01374   _DBUS_UNLOCK (shared_connections);
01375 }
01376 
01377 static dbus_bool_t
01378 connection_lookup_shared (DBusAddressEntry  *entry,
01379                           DBusConnection   **result)
01380 {
01381   _dbus_verbose ("checking for existing connection\n");
01382   
01383   *result = NULL;
01384   
01385   _DBUS_LOCK (shared_connections);
01386 
01387   if (shared_connections == NULL)
01388     {
01389       _dbus_verbose ("creating shared_connections hash table\n");
01390       
01391       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01392                                                  dbus_free,
01393                                                  NULL);
01394       if (shared_connections == NULL)
01395         {
01396           _DBUS_UNLOCK (shared_connections);
01397           return FALSE;
01398         }
01399 
01400       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01401         {
01402           _dbus_hash_table_unref (shared_connections);
01403           shared_connections = NULL;
01404           _DBUS_UNLOCK (shared_connections);
01405           return FALSE;
01406         }
01407 
01408       _dbus_verbose ("  successfully created shared_connections\n");
01409       
01410       _DBUS_UNLOCK (shared_connections);
01411       return TRUE; /* no point looking up in the hash we just made */
01412     }
01413   else
01414     {
01415       const char *guid;
01416 
01417       guid = dbus_address_entry_get_value (entry, "guid");
01418       
01419       if (guid != NULL)
01420         {
01421           *result = _dbus_hash_table_lookup_string (shared_connections,
01422                                                     guid);
01423 
01424           if (*result)
01425             {
01426               /* The DBusConnection can't have been disconnected
01427                * between the lookup and this code, because the
01428                * disconnection will take the shared_connections lock to
01429                * remove the connection. It can't have been finalized
01430                * since you have to disconnect prior to finalize.
01431                *
01432                * Thus it's safe to ref the connection.
01433                */
01434               dbus_connection_ref (*result);
01435 
01436               _dbus_verbose ("looked up existing connection to server guid %s\n",
01437                              guid);
01438             }
01439         }
01440       
01441       _DBUS_UNLOCK (shared_connections);
01442       return TRUE;
01443     }
01444 }
01445 
01446 static dbus_bool_t
01447 connection_record_shared_unlocked (DBusConnection *connection,
01448                                    const char     *guid)
01449 {
01450   char *guid_key;
01451   char *guid_in_connection;
01452 
01453   /* A separate copy of the key is required in the hash table, because
01454    * we don't have a lock on the connection when we are doing a hash
01455    * lookup.
01456    */
01457   
01458   _dbus_assert (connection->server_guid == NULL);
01459   _dbus_assert (connection->shareable);
01460   
01461   guid_key = _dbus_strdup (guid);
01462   if (guid_key == NULL)
01463     return FALSE;
01464 
01465   guid_in_connection = _dbus_strdup (guid);
01466   if (guid_in_connection == NULL)
01467     {
01468       dbus_free (guid_key);
01469       return FALSE;
01470     }
01471   
01472   _DBUS_LOCK (shared_connections);
01473   _dbus_assert (shared_connections != NULL);
01474   
01475   if (!_dbus_hash_table_insert_string (shared_connections,
01476                                        guid_key, connection))
01477     {
01478       dbus_free (guid_key);
01479       dbus_free (guid_in_connection);
01480       _DBUS_UNLOCK (shared_connections);
01481       return FALSE;
01482     }
01483 
01484   connection->server_guid = guid_in_connection;
01485 
01486   _dbus_verbose ("stored connection to %s to be shared\n",
01487                  connection->server_guid);
01488   
01489   _DBUS_UNLOCK (shared_connections);
01490 
01491   _dbus_assert (connection->server_guid != NULL);
01492   
01493   return TRUE;
01494 }
01495 
01496 static void
01497 connection_forget_shared_unlocked (DBusConnection *connection)
01498 {
01499   HAVE_LOCK_CHECK (connection);
01500   
01501   if (connection->server_guid == NULL)
01502     return;
01503 
01504   _dbus_verbose ("dropping connection to %s out of the shared table\n",
01505                  connection->server_guid);
01506   
01507   _DBUS_LOCK (shared_connections);
01508 
01509   if (!_dbus_hash_table_remove_string (shared_connections,
01510                                        connection->server_guid))
01511     _dbus_assert_not_reached ("connection was not in the shared table");
01512   
01513   dbus_free (connection->server_guid);
01514   connection->server_guid = NULL;
01515 
01516   _DBUS_UNLOCK (shared_connections);
01517 }
01518 
01519 static DBusConnection*
01520 connection_try_from_address_entry (DBusAddressEntry *entry,
01521                                    DBusError        *error)
01522 {
01523   DBusTransport *transport;
01524   DBusConnection *connection;
01525 
01526   transport = _dbus_transport_open (entry, error);
01527 
01528   if (transport == NULL)
01529     {
01530       _DBUS_ASSERT_ERROR_IS_SET (error);
01531       return NULL;
01532     }
01533 
01534   connection = _dbus_connection_new_for_transport (transport);
01535 
01536   _dbus_transport_unref (transport);
01537   
01538   if (connection == NULL)
01539     {
01540       _DBUS_SET_OOM (error);
01541       return NULL;
01542     }
01543 
01544 #ifndef DBUS_DISABLE_CHECKS
01545   _dbus_assert (!connection->have_connection_lock);
01546 #endif
01547   return connection;
01548 }
01549 
01550 /*
01551  * If the shared parameter is true, then any existing connection will
01552  * be used (and if a new connection is created, it will be available
01553  * for use by others). If the shared parameter is false, a new
01554  * connection will always be created, and the new connection will
01555  * never be returned to other callers.
01556  *
01557  * @param address the address
01558  * @param shared whether the connection is shared or private
01559  * @param error error return
01560  * @returns the connection or #NULL on error
01561  */
01562 static DBusConnection*
01563 _dbus_connection_open_internal (const char     *address,
01564                                 dbus_bool_t     shared,
01565                                 DBusError      *error)
01566 {
01567   DBusConnection *connection;
01568   DBusAddressEntry **entries;
01569   DBusError tmp_error;
01570   DBusError first_error;
01571   int len, i;
01572 
01573   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01574 
01575   _dbus_verbose ("opening %s connection to: %s\n",
01576                  shared ? "shared" : "private", address);
01577   
01578   if (!dbus_parse_address (address, &entries, &len, error))
01579     return NULL;
01580 
01581   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01582   
01583   connection = NULL;
01584 
01585   dbus_error_init (&tmp_error);
01586   dbus_error_init (&first_error);
01587   for (i = 0; i < len; i++)
01588     {
01589       if (shared)
01590         {
01591           if (!connection_lookup_shared (entries[i], &connection))
01592             _DBUS_SET_OOM (&tmp_error);
01593         }
01594 
01595       if (connection == NULL)
01596         {
01597           connection = connection_try_from_address_entry (entries[i],
01598                                                           &tmp_error);
01599           
01600           if (connection != NULL && shared)
01601             {
01602               const char *guid;
01603 
01604               connection->shareable = TRUE;
01605               
01606               guid = dbus_address_entry_get_value (entries[i], "guid");
01607 
01608               /* we don't have a connection lock but we know nobody
01609                * else has a handle to the connection
01610                */
01611               
01612               if (guid &&
01613                   !connection_record_shared_unlocked (connection, guid))
01614                 {
01615                   _DBUS_SET_OOM (&tmp_error);
01616                   dbus_connection_close (connection);
01617                   dbus_connection_unref (connection);
01618                   connection = NULL;
01619                 }
01620 
01621               /* but as of now the connection is possibly shared
01622                * since another thread could have pulled it from the table
01623                */
01624             }
01625         }
01626       
01627       if (connection)
01628         break;
01629 
01630       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01631       
01632       if (i == 0)
01633         dbus_move_error (&tmp_error, &first_error);
01634       else
01635         dbus_error_free (&tmp_error);
01636     }
01637 
01638   /* NOTE we don't have a lock on a possibly-shared connection object */
01639   
01640   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01641   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01642   
01643   if (connection == NULL)
01644     {
01645       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01646       dbus_move_error (&first_error, error);
01647     }
01648   else
01649     {
01650       dbus_error_free (&first_error);
01651     }
01652   
01653   dbus_address_entries_free (entries);
01654   return connection;
01655 }
01656 
01684 DBusConnection*
01685 dbus_connection_open (const char     *address,
01686                       DBusError      *error)
01687 {
01688   DBusConnection *connection;
01689 
01690   _dbus_return_val_if_fail (address != NULL, NULL);
01691   _dbus_return_val_if_error_is_set (error, NULL);
01692 
01693   connection = _dbus_connection_open_internal (address,
01694                                                TRUE,
01695                                                error);
01696 
01697   return connection;
01698 }
01699 
01714 DBusConnection*
01715 dbus_connection_open_private (const char     *address,
01716                               DBusError      *error)
01717 {
01718   DBusConnection *connection;
01719 
01720   _dbus_return_val_if_fail (address != NULL, NULL);
01721   _dbus_return_val_if_error_is_set (error, NULL);
01722 
01723   connection = _dbus_connection_open_internal (address,
01724                                                FALSE,
01725                                                error);
01726 
01727   return connection;
01728 }
01729 
01736 DBusConnection *
01737 dbus_connection_ref (DBusConnection *connection)
01738 {
01739   _dbus_return_val_if_fail (connection != NULL, NULL);
01740   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01741   
01742   /* The connection lock is better than the global
01743    * lock in the atomic increment fallback
01744    */
01745   
01746 #ifdef DBUS_HAVE_ATOMIC_INT
01747   _dbus_atomic_inc (&connection->refcount);
01748 #else
01749   CONNECTION_LOCK (connection);
01750   _dbus_assert (connection->refcount.value > 0);
01751 
01752   connection->refcount.value += 1;
01753   CONNECTION_UNLOCK (connection);
01754 #endif
01755 
01756   return connection;
01757 }
01758 
01759 static void
01760 free_outgoing_message (void *element,
01761                        void *data)
01762 {
01763   DBusMessage *message = element;
01764   DBusConnection *connection = data;
01765 
01766   _dbus_message_remove_size_counter (message,
01767                                      connection->outgoing_counter,
01768                                      NULL);
01769   dbus_message_unref (message);
01770 }
01771 
01772 /* This is run without the mutex held, but after the last reference
01773  * to the connection has been dropped we should have no thread-related
01774  * problems
01775  */
01776 static void
01777 _dbus_connection_last_unref (DBusConnection *connection)
01778 {
01779   DBusList *link;
01780 
01781   _dbus_verbose ("Finalizing connection %p\n", connection);
01782   
01783   _dbus_assert (connection->refcount.value == 0);
01784   
01785   /* You have to disconnect the connection before unref:ing it. Otherwise
01786    * you won't get the disconnected message.
01787    */
01788   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01789   _dbus_assert (connection->server_guid == NULL);
01790   
01791   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01792   _dbus_object_tree_free_all_unlocked (connection->objects);
01793   
01794   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01795   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01796   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01797   
01798   _dbus_watch_list_free (connection->watches);
01799   connection->watches = NULL;
01800   
01801   _dbus_timeout_list_free (connection->timeouts);
01802   connection->timeouts = NULL;
01803 
01804   _dbus_data_slot_list_free (&connection->slot_list);
01805   
01806   link = _dbus_list_get_first_link (&connection->filter_list);
01807   while (link != NULL)
01808     {
01809       DBusMessageFilter *filter = link->data;
01810       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01811 
01812       filter->function = NULL;
01813       _dbus_message_filter_unref (filter); /* calls app callback */
01814       link->data = NULL;
01815       
01816       link = next;
01817     }
01818   _dbus_list_clear (&connection->filter_list);
01819   
01820   /* ---- Done with stuff that invokes application callbacks */
01821 
01822   _dbus_object_tree_unref (connection->objects);  
01823 
01824   _dbus_hash_table_unref (connection->pending_replies);
01825   connection->pending_replies = NULL;
01826   
01827   _dbus_list_clear (&connection->filter_list);
01828   
01829   _dbus_list_foreach (&connection->outgoing_messages,
01830                       free_outgoing_message,
01831                       connection);
01832   _dbus_list_clear (&connection->outgoing_messages);
01833   
01834   _dbus_list_foreach (&connection->incoming_messages,
01835                       (DBusForeachFunction) dbus_message_unref,
01836                       NULL);
01837   _dbus_list_clear (&connection->incoming_messages);
01838 
01839   _dbus_counter_unref (connection->outgoing_counter);
01840 
01841   _dbus_transport_unref (connection->transport);
01842 
01843   if (connection->disconnect_message_link)
01844     {
01845       DBusMessage *message = connection->disconnect_message_link->data;
01846       dbus_message_unref (message);
01847       _dbus_list_free_link (connection->disconnect_message_link);
01848     }
01849 
01850   _dbus_list_clear (&connection->link_cache);
01851   
01852   _dbus_condvar_free (connection->dispatch_cond);
01853   _dbus_condvar_free (connection->io_path_cond);
01854 
01855   _dbus_mutex_free (connection->io_path_mutex);
01856   _dbus_mutex_free (connection->dispatch_mutex);
01857 
01858   _dbus_mutex_free (connection->mutex);
01859   
01860   dbus_free (connection);
01861 }
01862 
01874 void
01875 dbus_connection_unref (DBusConnection *connection)
01876 {
01877   dbus_bool_t last_unref;
01878 
01879   _dbus_return_if_fail (connection != NULL);
01880   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01881   
01882   /* The connection lock is better than the global
01883    * lock in the atomic increment fallback
01884    */
01885   
01886 #ifdef DBUS_HAVE_ATOMIC_INT
01887   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01888 #else
01889   CONNECTION_LOCK (connection);
01890   
01891   _dbus_assert (connection->refcount.value > 0);
01892 
01893   connection->refcount.value -= 1;
01894   last_unref = (connection->refcount.value == 0);
01895 
01896 #if 0
01897   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01898 #endif
01899   
01900   CONNECTION_UNLOCK (connection);
01901 #endif
01902   
01903   if (last_unref)
01904     _dbus_connection_last_unref (connection);
01905 }
01906 
01920 void
01921 dbus_connection_close (DBusConnection *connection)
01922 {
01923   DBusDispatchStatus status;
01924   
01925   _dbus_return_if_fail (connection != NULL);
01926   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01927 
01928   _dbus_verbose ("Disconnecting %p\n", connection);
01929   
01930   CONNECTION_LOCK (connection);
01931   
01932   _dbus_transport_disconnect (connection->transport);
01933 
01934   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01935   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01936 
01937   /* this calls out to user code */
01938   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01939 }
01940 
01947 void
01948 dbus_connection_disconnect (DBusConnection *connection)
01949 {
01950   dbus_connection_close (connection);
01951 }
01952 
01953 static dbus_bool_t
01954 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01955 {
01956   HAVE_LOCK_CHECK (connection);
01957   return _dbus_transport_get_is_connected (connection->transport);
01958 }
01959 
01970 dbus_bool_t
01971 dbus_connection_get_is_connected (DBusConnection *connection)
01972 {
01973   dbus_bool_t res;
01974 
01975   _dbus_return_val_if_fail (connection != NULL, FALSE);
01976   
01977   CONNECTION_LOCK (connection);
01978   res = _dbus_connection_get_is_connected_unlocked (connection);
01979   CONNECTION_UNLOCK (connection);
01980   
01981   return res;
01982 }
01983 
01992 dbus_bool_t
01993 dbus_connection_get_is_authenticated (DBusConnection *connection)
01994 {
01995   dbus_bool_t res;
01996 
01997   _dbus_return_val_if_fail (connection != NULL, FALSE);
01998   
01999   CONNECTION_LOCK (connection);
02000   res = _dbus_transport_get_is_authenticated (connection->transport);
02001   CONNECTION_UNLOCK (connection);
02002   
02003   return res;
02004 }
02005 
02019 void
02020 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02021                                         dbus_bool_t     exit_on_disconnect)
02022 {
02023   _dbus_return_if_fail (connection != NULL);
02024 
02025   CONNECTION_LOCK (connection);
02026   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02027   CONNECTION_UNLOCK (connection);
02028 }
02029 
02030 static DBusPreallocatedSend*
02031 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02032 {
02033   DBusPreallocatedSend *preallocated;
02034 
02035   HAVE_LOCK_CHECK (connection);
02036   
02037   _dbus_assert (connection != NULL);
02038   
02039   preallocated = dbus_new (DBusPreallocatedSend, 1);
02040   if (preallocated == NULL)
02041     return NULL;
02042 
02043   if (connection->link_cache != NULL)
02044     {
02045       preallocated->queue_link =
02046         _dbus_list_pop_first_link (&connection->link_cache);
02047       preallocated->queue_link->data = NULL;
02048     }
02049   else
02050     {
02051       preallocated->queue_link = _dbus_list_alloc_link (NULL);
02052       if (preallocated->queue_link == NULL)
02053         goto failed_0;
02054     }
02055   
02056   if (connection->link_cache != NULL)
02057     {
02058       preallocated->counter_link =
02059         _dbus_list_pop_first_link (&connection->link_cache);
02060       preallocated->counter_link->data = connection->outgoing_counter;
02061     }
02062   else
02063     {
02064       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02065       if (preallocated->counter_link == NULL)
02066         goto failed_1;
02067     }
02068 
02069   _dbus_counter_ref (preallocated->counter_link->data);
02070 
02071   preallocated->connection = connection;
02072   
02073   return preallocated;
02074   
02075  failed_1:
02076   _dbus_list_free_link (preallocated->queue_link);
02077  failed_0:
02078   dbus_free (preallocated);
02079   
02080   return NULL;
02081 }
02082 
02092 DBusPreallocatedSend*
02093 dbus_connection_preallocate_send (DBusConnection *connection)
02094 {
02095   DBusPreallocatedSend *preallocated;
02096 
02097   _dbus_return_val_if_fail (connection != NULL, NULL);
02098 
02099   CONNECTION_LOCK (connection);
02100   
02101   preallocated =
02102     _dbus_connection_preallocate_send_unlocked (connection);
02103 
02104   CONNECTION_UNLOCK (connection);
02105 
02106   return preallocated;
02107 }
02108 
02118 void
02119 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02120                                         DBusPreallocatedSend *preallocated)
02121 {
02122   _dbus_return_if_fail (connection != NULL);
02123   _dbus_return_if_fail (preallocated != NULL);  
02124   _dbus_return_if_fail (connection == preallocated->connection);
02125 
02126   _dbus_list_free_link (preallocated->queue_link);
02127   _dbus_counter_unref (preallocated->counter_link->data);
02128   _dbus_list_free_link (preallocated->counter_link);
02129   dbus_free (preallocated);
02130 }
02131 
02132 /* Called with lock held, does not update dispatch status */
02133 static void
02134 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
02135                                                        DBusPreallocatedSend *preallocated,
02136                                                        DBusMessage          *message,
02137                                                        dbus_uint32_t        *client_serial)
02138 {
02139   dbus_uint32_t serial;
02140   const char *sig;
02141 
02142   preallocated->queue_link->data = message;
02143   _dbus_list_prepend_link (&connection->outgoing_messages,
02144                            preallocated->queue_link);
02145 
02146   _dbus_message_add_size_counter_link (message,
02147                                        preallocated->counter_link);
02148 
02149   dbus_free (preallocated);
02150   preallocated = NULL;
02151   
02152   dbus_message_ref (message);
02153   
02154   connection->n_outgoing += 1;
02155 
02156   sig = dbus_message_get_signature (message);
02157   
02158   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02159                  message,
02160                  dbus_message_get_type (message),
02161                  dbus_message_get_path (message),
02162                  dbus_message_get_interface (message) ?
02163                  dbus_message_get_interface (message) :
02164                  "no interface",
02165                  dbus_message_get_member (message) ?
02166                  dbus_message_get_member (message) :
02167                  "no member",
02168                  sig,
02169                  dbus_message_get_destination (message) ?
02170                  dbus_message_get_destination (message) :
02171                  "null",
02172                  connection,
02173                  connection->n_outgoing);
02174 
02175   if (dbus_message_get_serial (message) == 0)
02176     {
02177       serial = _dbus_connection_get_next_client_serial (connection);
02178       _dbus_message_set_serial (message, serial);
02179       if (client_serial)
02180         *client_serial = serial;
02181     }
02182   else
02183     {
02184       if (client_serial)
02185         *client_serial = dbus_message_get_serial (message);
02186     }
02187 
02188   _dbus_verbose ("Message %p serial is %u\n",
02189                  message, dbus_message_get_serial (message));
02190   
02191   _dbus_message_lock (message);
02192 
02193   /* Now we need to run an iteration to hopefully just write the messages
02194    * out immediately, and otherwise get them queued up
02195    */
02196   _dbus_connection_do_iteration_unlocked (connection,
02197                                           DBUS_ITERATION_DO_WRITING,
02198                                           -1);
02199 
02200   /* If stuff is still queued up, be sure we wake up the main loop */
02201   if (connection->n_outgoing > 0)
02202     _dbus_connection_wakeup_mainloop (connection);
02203 }
02204 
02205 static void
02206 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02207                                                DBusPreallocatedSend *preallocated,
02208                                                DBusMessage          *message,
02209                                                dbus_uint32_t        *client_serial)
02210 {
02211   DBusDispatchStatus status;
02212 
02213   HAVE_LOCK_CHECK (connection);
02214   
02215   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02216                                                          preallocated,
02217                                                          message, client_serial);
02218 
02219   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02220   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02221 
02222   /* this calls out to user code */
02223   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02224 }
02225 
02238 void
02239 dbus_connection_send_preallocated (DBusConnection       *connection,
02240                                    DBusPreallocatedSend *preallocated,
02241                                    DBusMessage          *message,
02242                                    dbus_uint32_t        *client_serial)
02243 {
02244   _dbus_return_if_fail (connection != NULL);
02245   _dbus_return_if_fail (preallocated != NULL);
02246   _dbus_return_if_fail (message != NULL);
02247   _dbus_return_if_fail (preallocated->connection == connection);
02248   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02249                         (dbus_message_get_interface (message) != NULL &&
02250                          dbus_message_get_member (message) != NULL));
02251   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02252                         (dbus_message_get_interface (message) != NULL &&
02253                          dbus_message_get_member (message) != NULL));
02254   
02255   CONNECTION_LOCK (connection);
02256   _dbus_connection_send_preallocated_and_unlock (connection,
02257                                                  preallocated,
02258                                                  message, client_serial);
02259 }
02260 
02261 static dbus_bool_t
02262 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02263                                           DBusMessage    *message,
02264                                           dbus_uint32_t  *client_serial)
02265 {
02266   DBusPreallocatedSend *preallocated;
02267 
02268   _dbus_assert (connection != NULL);
02269   _dbus_assert (message != NULL);
02270   
02271   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02272   if (preallocated == NULL)
02273     return FALSE;
02274 
02275   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02276                                                          preallocated,
02277                                                          message,
02278                                                          client_serial);
02279   return TRUE;
02280 }
02281 
02282 dbus_bool_t
02283 _dbus_connection_send_and_unlock (DBusConnection *connection,
02284                                   DBusMessage    *message,
02285                                   dbus_uint32_t  *client_serial)
02286 {
02287   DBusPreallocatedSend *preallocated;
02288 
02289   _dbus_assert (connection != NULL);
02290   _dbus_assert (message != NULL);
02291   
02292   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02293   if (preallocated == NULL)
02294     {
02295       CONNECTION_UNLOCK (connection);
02296       return FALSE;
02297     }
02298 
02299   _dbus_connection_send_preallocated_and_unlock (connection,
02300                                                  preallocated,
02301                                                  message,
02302                                                  client_serial);
02303   return TRUE;
02304 }
02305 
02324 dbus_bool_t
02325 dbus_connection_send (DBusConnection *connection,
02326                       DBusMessage    *message,
02327                       dbus_uint32_t  *client_serial)
02328 {
02329   _dbus_return_val_if_fail (connection != NULL, FALSE);
02330   _dbus_return_val_if_fail (message != NULL, FALSE);
02331 
02332   CONNECTION_LOCK (connection);
02333 
02334   return _dbus_connection_send_and_unlock (connection,
02335                                            message,
02336                                            client_serial);
02337 }
02338 
02339 static dbus_bool_t
02340 reply_handler_timeout (void *data)
02341 {
02342   DBusConnection *connection;
02343   DBusDispatchStatus status;
02344   DBusPendingCall *pending = data;
02345 
02346   connection = pending->connection;
02347   
02348   CONNECTION_LOCK (connection);
02349   if (pending->timeout_link)
02350     {
02351       _dbus_connection_queue_synthesized_message_link (connection,
02352                                                        pending->timeout_link);
02353       pending->timeout_link = NULL;
02354     }
02355 
02356   _dbus_connection_remove_timeout (connection,
02357                                    pending->timeout);
02358   pending->timeout_added = FALSE;
02359 
02360   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02361   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02362 
02363   /* Unlocks, and calls out to user code */
02364   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02365   
02366   return TRUE;
02367 }
02368 
02406 dbus_bool_t
02407 dbus_connection_send_with_reply (DBusConnection     *connection,
02408                                  DBusMessage        *message,
02409                                  DBusPendingCall   **pending_return,
02410                                  int                 timeout_milliseconds)
02411 {
02412   DBusPendingCall *pending;
02413   DBusMessage *reply;
02414   DBusList *reply_link;
02415   dbus_int32_t serial = -1;
02416   DBusDispatchStatus status;
02417 
02418   _dbus_return_val_if_fail (connection != NULL, FALSE);
02419   _dbus_return_val_if_fail (message != NULL, FALSE);
02420   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02421 
02422   if (pending_return)
02423     *pending_return = NULL;
02424   
02425   pending = _dbus_pending_call_new (connection,
02426                                     timeout_milliseconds,
02427                                     reply_handler_timeout);
02428 
02429   if (pending == NULL)
02430     return FALSE;
02431 
02432   CONNECTION_LOCK (connection);
02433   
02434   /* Assign a serial to the message */
02435   if (dbus_message_get_serial (message) == 0)
02436     {
02437       serial = _dbus_connection_get_next_client_serial (connection);
02438       _dbus_message_set_serial (message, serial);
02439     }
02440 
02441   pending->reply_serial = serial;
02442 
02443   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02444                                   "No reply within specified time");
02445   if (reply == NULL)
02446     goto error;
02447 
02448   reply_link = _dbus_list_alloc_link (reply);
02449   if (reply_link == NULL)
02450     {
02451       CONNECTION_UNLOCK (connection);
02452       dbus_message_unref (reply);
02453       goto error_unlocked;
02454     }
02455 
02456   pending->timeout_link = reply_link;
02457 
02458   /* Insert the serial in the pending replies hash;
02459    * hash takes a refcount on DBusPendingCall.
02460    * Also, add the timeout.
02461    */
02462   if (!_dbus_connection_attach_pending_call_unlocked (connection,
02463                                                       pending))
02464     goto error;
02465  
02466   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02467     {
02468       _dbus_connection_detach_pending_call_and_unlock (connection,
02469                                                        pending);
02470       goto error_unlocked;
02471     }
02472 
02473   if (pending_return)
02474     *pending_return = pending;
02475   else
02476     {
02477       _dbus_connection_detach_pending_call_unlocked (connection, pending);
02478       dbus_pending_call_unref (pending);
02479     }
02480 
02481   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02482   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02483 
02484   /* this calls out to user code */
02485   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02486 
02487   return TRUE;
02488 
02489  error:
02490   CONNECTION_UNLOCK (connection);
02491  error_unlocked:
02492   dbus_pending_call_unref (pending);
02493   return FALSE;
02494 }
02495 
02496 /* This is slightly strange since we can pop a message here without
02497  * the dispatch lock.
02498  */
02499 static DBusMessage*
02500 check_for_reply_unlocked (DBusConnection *connection,
02501                           dbus_uint32_t   client_serial)
02502 {
02503   DBusList *link;
02504 
02505   HAVE_LOCK_CHECK (connection);
02506   
02507   link = _dbus_list_get_first_link (&connection->incoming_messages);
02508 
02509   while (link != NULL)
02510     {
02511       DBusMessage *reply = link->data;
02512 
02513       if (dbus_message_get_reply_serial (reply) == client_serial)
02514         {
02515           _dbus_list_remove_link (&connection->incoming_messages, link);
02516           connection->n_incoming  -= 1;
02517           return reply;
02518         }
02519       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02520     }
02521 
02522   return NULL;
02523 }
02524 
02534 static void
02535 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02536 {
02537   if (timeout_milliseconds == -1)
02538     _dbus_sleep_milliseconds (1000);
02539   else if (timeout_milliseconds < 100)
02540     ; /* just busy loop */
02541   else if (timeout_milliseconds <= 1000)
02542     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02543   else
02544     _dbus_sleep_milliseconds (1000);
02545 }
02546 
02561 void
02562 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02563 {
02564   long start_tv_sec, start_tv_usec;
02565   long end_tv_sec, end_tv_usec;
02566   long tv_sec, tv_usec;
02567   DBusDispatchStatus status;
02568   DBusConnection *connection;
02569   dbus_uint32_t client_serial;
02570   int timeout_milliseconds;
02571 
02572   _dbus_assert (pending != NULL);
02573 
02574   if (dbus_pending_call_get_completed (pending))
02575     return;
02576 
02577   if (pending->connection == NULL)
02578     return; /* call already detached */
02579 
02580   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02581   
02582   connection = pending->connection;
02583   client_serial = pending->reply_serial;
02584 
02585   /* note that timeout_milliseconds is limited to a smallish value
02586    * in _dbus_pending_call_new() so overflows aren't possible
02587    * below
02588    */
02589   timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02590 
02591   /* Flush message queue */
02592   dbus_connection_flush (connection);
02593 
02594   CONNECTION_LOCK (connection);
02595 
02596   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02597   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02598   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02599   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02600   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02601 
02602   _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",
02603                  timeout_milliseconds,
02604                  client_serial,
02605                  start_tv_sec, start_tv_usec,
02606                  end_tv_sec, end_tv_usec);
02607 
02608   /* Now we wait... */
02609   /* always block at least once as we know we don't have the reply yet */
02610   _dbus_connection_do_iteration_unlocked (connection,
02611                                           DBUS_ITERATION_DO_READING |
02612                                           DBUS_ITERATION_BLOCK,
02613                                           timeout_milliseconds);
02614 
02615  recheck_status:
02616 
02617   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02618   
02619   HAVE_LOCK_CHECK (connection);
02620   
02621   /* queue messages and get status */
02622 
02623   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02624 
02625   /* the get_completed() is in case a dispatch() while we were blocking
02626    * got the reply instead of us.
02627    */
02628   if (dbus_pending_call_get_completed (pending))
02629     {
02630       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02631       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02632       dbus_pending_call_unref (pending);
02633       return;
02634     }
02635   
02636   if (status == DBUS_DISPATCH_DATA_REMAINS)
02637     {
02638       DBusMessage *reply;
02639       
02640       reply = check_for_reply_unlocked (connection, client_serial);
02641       if (reply != NULL)
02642         {
02643           _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02644 
02645           _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02646           
02647           _dbus_pending_call_complete_and_unlock (pending, reply);
02648           dbus_message_unref (reply);
02649 
02650           CONNECTION_LOCK (connection);
02651           status = _dbus_connection_get_dispatch_status_unlocked (connection);
02652           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02653           dbus_pending_call_unref (pending);
02654           
02655           return;
02656         }
02657     }
02658   
02659   _dbus_get_current_time (&tv_sec, &tv_usec);
02660   
02661   if (!_dbus_connection_get_is_connected_unlocked (connection))
02662     {
02663       /* FIXME send a "DBUS_ERROR_DISCONNECTED" instead, just to help
02664        * programmers understand what went wrong since the timeout is
02665        * confusing
02666        */
02667       
02668       _dbus_pending_call_complete_and_unlock (pending, NULL);
02669       dbus_pending_call_unref (pending);
02670       return;
02671     }
02672   else if (tv_sec < start_tv_sec)
02673     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02674   else if (connection->disconnect_message_link == NULL)
02675     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02676   else if (tv_sec < end_tv_sec ||
02677            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02678     {
02679       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02680         (end_tv_usec - tv_usec) / 1000;
02681       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02682       _dbus_assert (timeout_milliseconds >= 0);
02683       
02684       if (status == DBUS_DISPATCH_NEED_MEMORY)
02685         {
02686           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02687            * we may already have a reply in the buffer and just can't process
02688            * it.
02689            */
02690           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02691 
02692           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02693         }
02694       else
02695         {          
02696           /* block again, we don't have the reply buffered yet. */
02697           _dbus_connection_do_iteration_unlocked (connection,
02698                                                   DBUS_ITERATION_DO_READING |
02699                                                   DBUS_ITERATION_BLOCK,
02700                                                   timeout_milliseconds);
02701         }
02702 
02703       goto recheck_status;
02704     }
02705 
02706   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02707                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02708 
02709   _dbus_assert (!dbus_pending_call_get_completed (pending));
02710   
02711   /* unlock and call user code */
02712   _dbus_pending_call_complete_and_unlock (pending, NULL);
02713 
02714   /* update user code on dispatch status */
02715   CONNECTION_LOCK (connection);
02716   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02717   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02718   dbus_pending_call_unref (pending);
02719 }
02720 
02743 DBusMessage*
02744 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
02745                                            DBusMessage        *message,
02746                                            int                 timeout_milliseconds,
02747                                            DBusError          *error)
02748 {
02749   DBusMessage *reply;
02750   DBusPendingCall *pending;
02751   
02752   _dbus_return_val_if_fail (connection != NULL, NULL);
02753   _dbus_return_val_if_fail (message != NULL, NULL);
02754   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);  
02755   _dbus_return_val_if_error_is_set (error, NULL);
02756   
02757   if (!dbus_connection_send_with_reply (connection, message,
02758                                         &pending, timeout_milliseconds))
02759     {
02760       _DBUS_SET_OOM (error);
02761       return NULL;
02762     }
02763 
02764   _dbus_assert (pending != NULL);
02765   
02766   dbus_pending_call_block (pending);
02767 
02768   reply = dbus_pending_call_steal_reply (pending);
02769   dbus_pending_call_unref (pending);
02770 
02771   /* call_complete_and_unlock() called from pending_call_block() should
02772    * always fill this in.
02773    */
02774   _dbus_assert (reply != NULL);
02775   
02776    if (dbus_set_error_from_message (error, reply))
02777     {
02778       dbus_message_unref (reply);
02779       return NULL;
02780     }
02781   else
02782     return reply;
02783 }
02784 
02790 void
02791 dbus_connection_flush (DBusConnection *connection)
02792 {
02793   /* We have to specify DBUS_ITERATION_DO_READING here because
02794    * otherwise we could have two apps deadlock if they are both doing
02795    * a flush(), and the kernel buffers fill up. This could change the
02796    * dispatch status.
02797    */
02798   DBusDispatchStatus status;
02799 
02800   _dbus_return_if_fail (connection != NULL);
02801   
02802   CONNECTION_LOCK (connection);
02803   while (connection->n_outgoing > 0 &&
02804          _dbus_connection_get_is_connected_unlocked (connection))
02805     {
02806       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02807       HAVE_LOCK_CHECK (connection);
02808       _dbus_connection_do_iteration_unlocked (connection,
02809                                               DBUS_ITERATION_DO_READING |
02810                                               DBUS_ITERATION_DO_WRITING |
02811                                               DBUS_ITERATION_BLOCK,
02812                                               -1);
02813     }
02814 
02815   HAVE_LOCK_CHECK (connection);
02816   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02817   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02818 
02819   HAVE_LOCK_CHECK (connection);
02820   /* Unlocks and calls out to user code */
02821   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02822 
02823   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02824 }
02825 
02857 dbus_bool_t
02858 dbus_connection_read_write_dispatch (DBusConnection *connection,
02859                                      int             timeout_milliseconds)
02860 {
02861   DBusDispatchStatus dstatus;
02862   dbus_bool_t dispatched_disconnected;
02863   
02864   _dbus_return_val_if_fail (connection != NULL, FALSE);
02865   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02866   dstatus = dbus_connection_get_dispatch_status (connection);
02867 
02868   if (dstatus == DBUS_DISPATCH_DATA_REMAINS)
02869     {
02870       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02871       dbus_connection_dispatch (connection);
02872       CONNECTION_LOCK (connection);
02873     }
02874   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02875     {
02876       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02877       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02878       CONNECTION_LOCK (connection);
02879     }
02880   else
02881     {
02882       CONNECTION_LOCK (connection);
02883       if (_dbus_connection_get_is_connected_unlocked (connection))
02884         {
02885           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02886           _dbus_connection_do_iteration_unlocked (connection,
02887                                                   DBUS_ITERATION_DO_READING |
02888                                                   DBUS_ITERATION_DO_WRITING |
02889                                                   DBUS_ITERATION_BLOCK,
02890                                                   timeout_milliseconds);
02891         }
02892     }
02893   
02894   HAVE_LOCK_CHECK (connection);
02895   dispatched_disconnected = connection->n_incoming == 0 &&
02896     connection->disconnect_message_link == NULL;
02897   CONNECTION_UNLOCK (connection);
02898   return !dispatched_disconnected; /* TRUE if we have not processed disconnected */
02899 }
02900 
02920 DBusMessage*
02921 dbus_connection_borrow_message (DBusConnection *connection)
02922 {
02923   DBusDispatchStatus status;
02924   DBusMessage *message;
02925 
02926   _dbus_return_val_if_fail (connection != NULL, NULL);
02927 
02928   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02929   
02930   /* this is called for the side effect that it queues
02931    * up any messages from the transport
02932    */
02933   status = dbus_connection_get_dispatch_status (connection);
02934   if (status != DBUS_DISPATCH_DATA_REMAINS)
02935     return NULL;
02936   
02937   CONNECTION_LOCK (connection);
02938 
02939   _dbus_connection_acquire_dispatch (connection);
02940 
02941   /* While a message is outstanding, the dispatch lock is held */
02942   _dbus_assert (connection->message_borrowed == NULL);
02943 
02944   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
02945   
02946   message = connection->message_borrowed;
02947 
02948   /* Note that we KEEP the dispatch lock until the message is returned */
02949   if (message == NULL)
02950     _dbus_connection_release_dispatch (connection);
02951 
02952   CONNECTION_UNLOCK (connection);
02953   
02954   return message;
02955 }
02956 
02965 void
02966 dbus_connection_return_message (DBusConnection *connection,
02967                                 DBusMessage    *message)
02968 {
02969   _dbus_return_if_fail (connection != NULL);
02970   _dbus_return_if_fail (message != NULL);
02971   _dbus_return_if_fail (message == connection->message_borrowed);
02972   _dbus_return_if_fail (connection->dispatch_acquired);
02973   
02974   CONNECTION_LOCK (connection);
02975   
02976   _dbus_assert (message == connection->message_borrowed);
02977   
02978   connection->message_borrowed = NULL;
02979 
02980   _dbus_connection_release_dispatch (connection);
02981   
02982   CONNECTION_UNLOCK (connection);
02983 }
02984 
02994 void
02995 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02996                                         DBusMessage    *message)
02997 {
02998   DBusMessage *pop_message;
02999 
03000   _dbus_return_if_fail (connection != NULL);
03001   _dbus_return_if_fail (message != NULL);
03002   _dbus_return_if_fail (message == connection->message_borrowed);
03003   _dbus_return_if_fail (connection->dispatch_acquired);
03004   
03005   CONNECTION_LOCK (connection);
03006  
03007   _dbus_assert (message == connection->message_borrowed);
03008 
03009   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03010   _dbus_assert (message == pop_message);
03011   
03012   connection->n_incoming -= 1;
03013  
03014   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03015                  message, connection->n_incoming);
03016  
03017   connection->message_borrowed = NULL;
03018 
03019   _dbus_connection_release_dispatch (connection);
03020   
03021   CONNECTION_UNLOCK (connection);
03022 }
03023 
03024 /* See dbus_connection_pop_message, but requires the caller to own
03025  * the lock before calling. May drop the lock while running.
03026  */
03027 static DBusList*
03028 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03029 {
03030   HAVE_LOCK_CHECK (connection);
03031   
03032   _dbus_assert (connection->message_borrowed == NULL);
03033   
03034   if (connection->n_incoming > 0)
03035     {
03036       DBusList *link;
03037 
03038       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03039       connection->n_incoming -= 1;
03040 
03041       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03042                      link->data,
03043                      dbus_message_get_type (link->data),
03044                      dbus_message_get_path (link->data), 
03045                      dbus_message_get_interface (link->data) ?
03046                      dbus_message_get_interface (link->data) :
03047                      "no interface",
03048                      dbus_message_get_member (link->data) ?
03049                      dbus_message_get_member (link->data) :
03050                      "no member",
03051                      dbus_message_get_signature (link->data),
03052                      connection, connection->n_incoming);
03053 
03054       return link;
03055     }
03056   else
03057     return NULL;
03058 }
03059 
03060 /* See dbus_connection_pop_message, but requires the caller to own
03061  * the lock before calling. May drop the lock while running.
03062  */
03063 static DBusMessage*
03064 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03065 {
03066   DBusList *link;
03067 
03068   HAVE_LOCK_CHECK (connection);
03069   
03070   link = _dbus_connection_pop_message_link_unlocked (connection);
03071 
03072   if (link != NULL)
03073     {
03074       DBusMessage *message;
03075       
03076       message = link->data;
03077       
03078       _dbus_list_free_link (link);
03079       
03080       return message;
03081     }
03082   else
03083     return NULL;
03084 }
03085 
03086 static void
03087 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03088                                                 DBusList       *message_link)
03089 {
03090   HAVE_LOCK_CHECK (connection);
03091   
03092   _dbus_assert (message_link != NULL);
03093   /* You can't borrow a message while a link is outstanding */
03094   _dbus_assert (connection->message_borrowed == NULL);
03095   /* We had to have the dispatch lock across the pop/putback */
03096   _dbus_assert (connection->dispatch_acquired);
03097 
03098   _dbus_list_prepend_link (&connection->incoming_messages,
03099                            message_link);
03100   connection->n_incoming += 1;
03101 
03102   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03103                  message_link->data,
03104                  dbus_message_get_type (message_link->data),
03105                  dbus_message_get_interface (message_link->data) ?
03106                  dbus_message_get_interface (message_link->data) :
03107                  "no interface",
03108                  dbus_message_get_member (message_link->data) ?
03109                  dbus_message_get_member (message_link->data) :
03110                  "no member",
03111                  dbus_message_get_signature (message_link->data),
03112                  connection, connection->n_incoming);
03113 }
03114 
03134 DBusMessage*
03135 dbus_connection_pop_message (DBusConnection *connection)
03136 {
03137   DBusMessage *message;
03138   DBusDispatchStatus status;
03139 
03140   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03141   
03142   /* this is called for the side effect that it queues
03143    * up any messages from the transport
03144    */
03145   status = dbus_connection_get_dispatch_status (connection);
03146   if (status != DBUS_DISPATCH_DATA_REMAINS)
03147     return NULL;
03148   
03149   CONNECTION_LOCK (connection);
03150   _dbus_connection_acquire_dispatch (connection);
03151   HAVE_LOCK_CHECK (connection);
03152   
03153   message = _dbus_connection_pop_message_unlocked (connection);
03154 
03155   _dbus_verbose ("Returning popped message %p\n", message);    
03156 
03157   _dbus_connection_release_dispatch (connection);
03158   CONNECTION_UNLOCK (connection);
03159   
03160   return message;
03161 }
03162 
03170 static void
03171 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03172 {
03173   HAVE_LOCK_CHECK (connection);
03174 
03175   _dbus_connection_ref_unlocked (connection);
03176   CONNECTION_UNLOCK (connection);
03177   
03178   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03179   _dbus_mutex_lock (connection->dispatch_mutex);
03180 
03181   while (connection->dispatch_acquired)
03182     {
03183       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03184       _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03185     }
03186   
03187   _dbus_assert (!connection->dispatch_acquired);
03188 
03189   connection->dispatch_acquired = TRUE;
03190 
03191   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03192   _dbus_mutex_unlock (connection->dispatch_mutex);
03193   
03194   CONNECTION_LOCK (connection);
03195   _dbus_connection_unref_unlocked (connection);
03196 }
03197 
03205 static void
03206 _dbus_connection_release_dispatch (DBusConnection *connection)
03207 {
03208   HAVE_LOCK_CHECK (connection);
03209   
03210   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03211   _dbus_mutex_lock (connection->dispatch_mutex);
03212   
03213   _dbus_assert (connection->dispatch_acquired);
03214 
03215   connection->dispatch_acquired = FALSE;
03216   _dbus_condvar_wake_one (connection->dispatch_cond);
03217 
03218   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03219   _dbus_mutex_unlock (connection->dispatch_mutex);
03220 }
03221 
03222 static void
03223 _dbus_connection_failed_pop (DBusConnection *connection,
03224                              DBusList       *message_link)
03225 {
03226   _dbus_list_prepend_link (&connection->incoming_messages,
03227                            message_link);
03228   connection->n_incoming += 1;
03229 }
03230 
03231 static DBusDispatchStatus
03232 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03233 {
03234   HAVE_LOCK_CHECK (connection);
03235   
03236   if (connection->n_incoming > 0)
03237     return DBUS_DISPATCH_DATA_REMAINS;
03238   else if (!_dbus_transport_queue_messages (connection->transport))
03239     return DBUS_DISPATCH_NEED_MEMORY;
03240   else
03241     {
03242       DBusDispatchStatus status;
03243       dbus_bool_t is_connected;
03244       
03245       status = _dbus_transport_get_dispatch_status (connection->transport);
03246       is_connected = _dbus_transport_get_is_connected (connection->transport);
03247 
03248       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03249                      DISPATCH_STATUS_NAME (status), is_connected);
03250       
03251       if (!is_connected)
03252         {
03253           if (status == DBUS_DISPATCH_COMPLETE &&
03254               connection->disconnect_message_link)
03255             {
03256               _dbus_verbose ("Sending disconnect message from %s\n",
03257                              _DBUS_FUNCTION_NAME);
03258 
03259               connection_forget_shared_unlocked (connection);
03260               
03261               /* We haven't sent the disconnect message already,
03262                * and all real messages have been queued up.
03263                */
03264               _dbus_connection_queue_synthesized_message_link (connection,
03265                                                                connection->disconnect_message_link);
03266               connection->disconnect_message_link = NULL;
03267             }
03268 
03269           /* Dump the outgoing queue, we aren't going to be able to
03270            * send it now, and we'd like accessors like
03271            * dbus_connection_get_outgoing_size() to be accurate.
03272            */
03273           if (connection->n_outgoing > 0)
03274             {
03275               DBusList *link;
03276               
03277               _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03278                              connection->n_outgoing);
03279               
03280               while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03281                 {
03282                   _dbus_connection_message_sent (connection, link->data);
03283                 }
03284             }
03285         }
03286       
03287       if (status != DBUS_DISPATCH_COMPLETE)
03288         return status;
03289       else if (connection->n_incoming > 0)
03290         return DBUS_DISPATCH_DATA_REMAINS;
03291       else
03292         return DBUS_DISPATCH_COMPLETE;
03293     }
03294 }
03295 
03296 static void
03297 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03298                                                     DBusDispatchStatus new_status)
03299 {
03300   dbus_bool_t changed;
03301   DBusDispatchStatusFunction function;
03302   void *data;
03303 
03304   HAVE_LOCK_CHECK (connection);
03305 
03306   _dbus_connection_ref_unlocked (connection);
03307 
03308   changed = new_status != connection->last_dispatch_status;
03309 
03310   connection->last_dispatch_status = new_status;
03311 
03312   function = connection->dispatch_status_function;
03313   data = connection->dispatch_status_data;
03314 
03315   /* We drop the lock */
03316   CONNECTION_UNLOCK (connection);
03317   
03318   if (changed && function)
03319     {
03320       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03321                      connection, new_status,
03322                      DISPATCH_STATUS_NAME (new_status));
03323       (* function) (connection, new_status, data);      
03324     }
03325   
03326   dbus_connection_unref (connection);
03327 }
03328 
03337 DBusDispatchStatus
03338 dbus_connection_get_dispatch_status (DBusConnection *connection)
03339 {
03340   DBusDispatchStatus status;
03341 
03342   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03343 
03344   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03345   
03346   CONNECTION_LOCK (connection);
03347 
03348   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03349   
03350   CONNECTION_UNLOCK (connection);
03351 
03352   return status;
03353 }
03354 
03358 static DBusHandlerResult
03359 _dbus_connection_peer_filter (DBusConnection *connection,
03360                               DBusMessage    *message)
03361 {
03362   if (dbus_message_is_method_call (message,
03363                                    DBUS_INTERFACE_PEER,
03364                                    "Ping"))
03365     {
03366       DBusMessage *ret;
03367       dbus_bool_t sent;
03368       
03369       ret = dbus_message_new_method_return (message);
03370       if (ret == NULL)
03371         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03372       
03373       sent = dbus_connection_send (connection, ret, NULL);
03374       dbus_message_unref (ret);
03375 
03376       if (!sent)
03377         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03378       
03379       return DBUS_HANDLER_RESULT_HANDLED;
03380     }
03381                                    
03382   
03383   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03384 }
03385 
03392 static DBusHandlerResult
03393 _dbus_connection_run_builtin_filters (DBusConnection *connection,
03394                                       DBusMessage    *message)
03395 {
03396   /* We just run one filter for now but have the option to run more
03397      if the spec calls for it in the future */
03398 
03399   return _dbus_connection_peer_filter (connection, message);
03400 }
03401 
03425 DBusDispatchStatus
03426 dbus_connection_dispatch (DBusConnection *connection)
03427 {
03428   DBusMessage *message;
03429   DBusList *link, *filter_list_copy, *message_link;
03430   DBusHandlerResult result;
03431   DBusPendingCall *pending;
03432   dbus_int32_t reply_serial;
03433   DBusDispatchStatus status;
03434 
03435   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03436 
03437   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03438   
03439   CONNECTION_LOCK (connection);
03440   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03441   if (status != DBUS_DISPATCH_DATA_REMAINS)
03442     {
03443       /* unlocks and calls out to user code */
03444       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03445       return status;
03446     }
03447   
03448   /* We need to ref the connection since the callback could potentially
03449    * drop the last ref to it
03450    */
03451   _dbus_connection_ref_unlocked (connection);
03452 
03453   _dbus_connection_acquire_dispatch (connection);
03454   HAVE_LOCK_CHECK (connection);
03455 
03456   message_link = _dbus_connection_pop_message_link_unlocked (connection);
03457   if (message_link == NULL)
03458     {
03459       /* another thread dispatched our stuff */
03460 
03461       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03462       
03463       _dbus_connection_release_dispatch (connection);
03464 
03465       status = _dbus_connection_get_dispatch_status_unlocked (connection);
03466 
03467       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03468       
03469       dbus_connection_unref (connection);
03470       
03471       return status;
03472     }
03473 
03474   message = message_link->data;
03475 
03476   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03477                  message,
03478                  dbus_message_get_type (message),
03479                  dbus_message_get_interface (message) ?
03480                  dbus_message_get_interface (message) :
03481                  "no interface",
03482                  dbus_message_get_member (message) ?
03483                  dbus_message_get_member (message) :
03484                  "no member",
03485                  dbus_message_get_signature (message));
03486 
03487   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03488   
03489   /* Pending call handling must be first, because if you do
03490    * dbus_connection_send_with_reply_and_block() or
03491    * dbus_pending_call_block() then no handlers/filters will be run on
03492    * the reply. We want consistent semantics in the case where we
03493    * dbus_connection_dispatch() the reply.
03494    */
03495   
03496   reply_serial = dbus_message_get_reply_serial (message);
03497   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03498                                          reply_serial);
03499   if (pending)
03500     {
03501       _dbus_verbose ("Dispatching a pending reply\n");
03502       _dbus_pending_call_complete_and_unlock (pending, message);
03503       pending = NULL; /* it's probably unref'd */
03504       
03505       CONNECTION_LOCK (connection);
03506       _dbus_verbose ("pending call completed in dispatch\n");
03507       result = DBUS_HANDLER_RESULT_HANDLED;
03508       goto out;
03509     }
03510  
03511   result = _dbus_connection_run_builtin_filters (connection, message);
03512   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03513     goto out;
03514  
03515   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03516     {
03517       _dbus_connection_release_dispatch (connection);
03518       HAVE_LOCK_CHECK (connection);
03519       
03520       _dbus_connection_failed_pop (connection, message_link);
03521 
03522       /* unlocks and calls user code */
03523       _dbus_connection_update_dispatch_status_and_unlock (connection,
03524                                                           DBUS_DISPATCH_NEED_MEMORY);
03525 
03526       if (pending)
03527         dbus_pending_call_unref (pending);
03528       dbus_connection_unref (connection);
03529       
03530       return DBUS_DISPATCH_NEED_MEMORY;
03531     }
03532   
03533   _dbus_list_foreach (&filter_list_copy,
03534                       (DBusForeachFunction)_dbus_message_filter_ref,
03535                       NULL);
03536 
03537   /* We're still protected from dispatch() reentrancy here
03538    * since we acquired the dispatcher
03539    */
03540   CONNECTION_UNLOCK (connection);
03541   
03542   link = _dbus_list_get_first_link (&filter_list_copy);
03543   while (link != NULL)
03544     {
03545       DBusMessageFilter *filter = link->data;
03546       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03547 
03548       _dbus_verbose ("  running filter on message %p\n", message);
03549       result = (* filter->function) (connection, message, filter->user_data);
03550 
03551       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03552         break;
03553 
03554       link = next;
03555     }
03556 
03557   _dbus_list_foreach (&filter_list_copy,
03558                       (DBusForeachFunction)_dbus_message_filter_unref,
03559                       NULL);
03560   _dbus_list_clear (&filter_list_copy);
03561   
03562   CONNECTION_LOCK (connection);
03563 
03564   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03565     {
03566       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03567       goto out;
03568     }
03569   else if (result == DBUS_HANDLER_RESULT_HANDLED)
03570     {
03571       _dbus_verbose ("filter handled message in dispatch\n");
03572       goto out;
03573     }
03574 
03575   /* We're still protected from dispatch() reentrancy here
03576    * since we acquired the dispatcher
03577    */
03578   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
03579                  message,
03580                  dbus_message_get_type (message),
03581                  dbus_message_get_interface (message) ?
03582                  dbus_message_get_interface (message) :
03583                  "no interface",
03584                  dbus_message_get_member (message) ?
03585                  dbus_message_get_member (message) :
03586                  "no member",
03587                  dbus_message_get_signature (message));
03588 
03589   HAVE_LOCK_CHECK (connection);
03590   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03591                                                   message);
03592   
03593   CONNECTION_LOCK (connection);
03594 
03595   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03596     {
03597       _dbus_verbose ("object tree handled message in dispatch\n");
03598       goto out;
03599     }
03600 
03601   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03602     {
03603       DBusMessage *reply;
03604       DBusString str;
03605       DBusPreallocatedSend *preallocated;
03606 
03607       _dbus_verbose ("  sending error %s\n",
03608                      DBUS_ERROR_UNKNOWN_METHOD);
03609       
03610       if (!_dbus_string_init (&str))
03611         {
03612           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03613           _dbus_verbose ("no memory for error string in dispatch\n");
03614           goto out;
03615         }
03616               
03617       if (!_dbus_string_append_printf (&str,
03618                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03619                                        dbus_message_get_member (message),
03620                                        dbus_message_get_signature (message),
03621                                        dbus_message_get_interface (message)))
03622         {
03623           _dbus_string_free (&str);
03624           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03625           _dbus_verbose ("no memory for error string in dispatch\n");
03626           goto out;
03627         }
03628       
03629       reply = dbus_message_new_error (message,
03630                                       DBUS_ERROR_UNKNOWN_METHOD,
03631                                       _dbus_string_get_const_data (&str));
03632       _dbus_string_free (&str);
03633 
03634       if (reply == NULL)
03635         {
03636           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03637           _dbus_verbose ("no memory for error reply in dispatch\n");
03638           goto out;
03639         }
03640       
03641       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03642 
03643       if (preallocated == NULL)
03644         {
03645           dbus_message_unref (reply);
03646           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03647           _dbus_verbose ("no memory for error send in dispatch\n");
03648           goto out;
03649         }
03650 
03651       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03652                                                              reply, NULL);
03653 
03654       dbus_message_unref (reply);
03655       
03656       result = DBUS_HANDLER_RESULT_HANDLED;
03657     }
03658   
03659   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03660                  dbus_message_get_type (message),
03661                  dbus_message_get_interface (message) ?
03662                  dbus_message_get_interface (message) :
03663                  "no interface",
03664                  dbus_message_get_member (message) ?
03665                  dbus_message_get_member (message) :
03666                  "no member",
03667                  dbus_message_get_signature (message),
03668                  connection);
03669   
03670  out:
03671   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03672     {
03673       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03674       
03675       /* Put message back, and we'll start over.
03676        * Yes this means handlers must be idempotent if they
03677        * don't return HANDLED; c'est la vie.
03678        */
03679       _dbus_connection_putback_message_link_unlocked (connection,
03680                                                       message_link);
03681     }
03682   else
03683     {
03684       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03685       
03686       if (connection->exit_on_disconnect &&
03687           dbus_message_is_signal (message,
03688                                   DBUS_INTERFACE_LOCAL,
03689                                   "Disconnected"))
03690         {
03691           _dbus_verbose ("Exiting on Disconnected signal\n");
03692           CONNECTION_UNLOCK (connection);
03693           _dbus_exit (1);
03694           _dbus_assert_not_reached ("Call to exit() returned");
03695         }
03696       
03697       _dbus_list_free_link (message_link);
03698       dbus_message_unref (message); /* don't want the message to count in max message limits
03699                                      * in computing dispatch status below
03700                                      */
03701     }
03702   
03703   _dbus_connection_release_dispatch (connection);
03704   HAVE_LOCK_CHECK (connection);
03705 
03706   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03707   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03708 
03709   /* unlocks and calls user code */
03710   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03711   
03712   dbus_connection_unref (connection);
03713   
03714   return status;
03715 }
03716 
03775 dbus_bool_t
03776 dbus_connection_set_watch_functions (DBusConnection              *connection,
03777                                      DBusAddWatchFunction         add_function,
03778                                      DBusRemoveWatchFunction      remove_function,
03779                                      DBusWatchToggledFunction     toggled_function,
03780                                      void                        *data,
03781                                      DBusFreeFunction             free_data_function)
03782 {
03783   dbus_bool_t retval;
03784   DBusWatchList *watches;
03785 
03786   _dbus_return_val_if_fail (connection != NULL, FALSE);
03787   
03788   CONNECTION_LOCK (connection);
03789 
03790 #ifndef DBUS_DISABLE_CHECKS
03791   if (connection->watches == NULL)
03792     {
03793       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03794                   _DBUS_FUNCTION_NAME);
03795       return FALSE;
03796     }
03797 #endif
03798   
03799   /* ref connection for slightly better reentrancy */
03800   _dbus_connection_ref_unlocked (connection);
03801 
03802   /* This can call back into user code, and we need to drop the
03803    * connection lock when it does. This is kind of a lame
03804    * way to do it.
03805    */
03806   watches = connection->watches;
03807   connection->watches = NULL;
03808   CONNECTION_UNLOCK (connection);
03809 
03810   retval = _dbus_watch_list_set_functions (watches,
03811                                            add_function, remove_function,
03812                                            toggled_function,
03813                                            data, free_data_function);
03814   CONNECTION_LOCK (connection);
03815   connection->watches = watches;
03816   
03817   CONNECTION_UNLOCK (connection);
03818   /* drop our paranoid refcount */
03819   dbus_connection_unref (connection);
03820   
03821   return retval;
03822 }
03823 
03857 dbus_bool_t
03858 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
03859                                          DBusAddTimeoutFunction     add_function,
03860                                          DBusRemoveTimeoutFunction  remove_function,
03861                                          DBusTimeoutToggledFunction toggled_function,
03862                                          void                      *data,
03863                                          DBusFreeFunction           free_data_function)
03864 {
03865   dbus_bool_t retval;
03866   DBusTimeoutList *timeouts;
03867 
03868   _dbus_return_val_if_fail (connection != NULL, FALSE);
03869   
03870   CONNECTION_LOCK (connection);
03871 
03872 #ifndef DBUS_DISABLE_CHECKS
03873   if (connection->timeouts == NULL)
03874     {
03875       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03876                   _DBUS_FUNCTION_NAME);
03877       return FALSE;
03878     }
03879 #endif
03880   
03881   /* ref connection for slightly better reentrancy */
03882   _dbus_connection_ref_unlocked (connection);
03883 
03884   timeouts = connection->timeouts;
03885   connection->timeouts = NULL;
03886   CONNECTION_UNLOCK (connection);
03887   
03888   retval = _dbus_timeout_list_set_functions (timeouts,
03889                                              add_function, remove_function,
03890                                              toggled_function,
03891                                              data, free_data_function);
03892   CONNECTION_LOCK (connection);
03893   connection->timeouts = timeouts;
03894   
03895   CONNECTION_UNLOCK (connection);
03896   /* drop our paranoid refcount */
03897   dbus_connection_unref (connection);
03898 
03899   return retval;
03900 }
03901 
03916 void
03917 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
03918                                           DBusWakeupMainFunction     wakeup_main_function,
03919                                           void                      *data,
03920                                           DBusFreeFunction           free_data_function)
03921 {
03922   void *old_data;
03923   DBusFreeFunction old_free_data;
03924 
03925   _dbus_return_if_fail (connection != NULL);
03926   
03927   CONNECTION_LOCK (connection);
03928   old_data = connection->wakeup_main_data;
03929   old_free_data = connection->free_wakeup_main_data;
03930 
03931   connection->wakeup_main_function = wakeup_main_function;
03932   connection->wakeup_main_data = data;
03933   connection->free_wakeup_main_data = free_data_function;
03934   
03935   CONNECTION_UNLOCK (connection);
03936 
03937   /* Callback outside the lock */
03938   if (old_free_data)
03939     (*old_free_data) (old_data);
03940 }
03941 
03958 void
03959 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
03960                                               DBusDispatchStatusFunction  function,
03961                                               void                       *data,
03962                                               DBusFreeFunction            free_data_function)
03963 {
03964   void *old_data;
03965   DBusFreeFunction old_free_data;
03966 
03967   _dbus_return_if_fail (connection != NULL);
03968   
03969   CONNECTION_LOCK (connection);
03970   old_data = connection->dispatch_status_data;
03971   old_free_data = connection->free_dispatch_status_data;
03972 
03973   connection->dispatch_status_function = function;
03974   connection->dispatch_status_data = data;
03975   connection->free_dispatch_status_data = free_data_function;
03976   
03977   CONNECTION_UNLOCK (connection);
03978 
03979   /* Callback outside the lock */
03980   if (old_free_data)
03981     (*old_free_data) (old_data);
03982 }
03983 
03996 dbus_bool_t
03997 dbus_connection_get_unix_fd (DBusConnection *connection,
03998                              int            *fd)
03999 {
04000   dbus_bool_t retval;
04001 
04002   _dbus_return_val_if_fail (connection != NULL, FALSE);
04003   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04004   
04005   CONNECTION_LOCK (connection);
04006   
04007   retval = _dbus_transport_get_unix_fd (connection->transport,
04008                                         fd);
04009 
04010   CONNECTION_UNLOCK (connection);
04011 
04012   return retval;
04013 }
04014 
04026 dbus_bool_t
04027 dbus_connection_get_unix_user (DBusConnection *connection,
04028                                unsigned long  *uid)
04029 {
04030   dbus_bool_t result;
04031 
04032   _dbus_return_val_if_fail (connection != NULL, FALSE);
04033   _dbus_return_val_if_fail (uid != NULL, FALSE);
04034   
04035   CONNECTION_LOCK (connection);
04036 
04037   if (!_dbus_transport_get_is_authenticated (connection->transport))
04038     result = FALSE;
04039   else
04040     result = _dbus_transport_get_unix_user (connection->transport,
04041                                             uid);
04042   CONNECTION_UNLOCK (connection);
04043 
04044   return result;
04045 }
04046 
04057 dbus_bool_t
04058 dbus_connection_get_unix_process_id (DBusConnection *connection,
04059                                      unsigned long  *pid)
04060 {
04061   dbus_bool_t result;
04062 
04063   _dbus_return_val_if_fail (connection != NULL, FALSE);
04064   _dbus_return_val_if_fail (pid != NULL, FALSE);
04065   
04066   CONNECTION_LOCK (connection);
04067 
04068   if (!_dbus_transport_get_is_authenticated (connection->transport))
04069     result = FALSE;
04070   else
04071     result = _dbus_transport_get_unix_process_id (connection->transport,
04072                                                   pid);
04073   CONNECTION_UNLOCK (connection);
04074 
04075   return result;
04076 }
04077 
04094 void
04095 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04096                                         DBusAllowUnixUserFunction   function,
04097                                         void                       *data,
04098                                         DBusFreeFunction            free_data_function)
04099 {
04100   void *old_data = NULL;
04101   DBusFreeFunction old_free_function = NULL;
04102 
04103   _dbus_return_if_fail (connection != NULL);
04104   
04105   CONNECTION_LOCK (connection);
04106   _dbus_transport_set_unix_user_function (connection->transport,
04107                                           function, data, free_data_function,
04108                                           &old_data, &old_free_function);
04109   CONNECTION_UNLOCK (connection);
04110 
04111   if (old_free_function != NULL)
04112     (* old_free_function) (old_data);    
04113 }
04114 
04136 dbus_bool_t
04137 dbus_connection_add_filter (DBusConnection            *connection,
04138                             DBusHandleMessageFunction  function,
04139                             void                      *user_data,
04140                             DBusFreeFunction           free_data_function)
04141 {
04142   DBusMessageFilter *filter;
04143   
04144   _dbus_return_val_if_fail (connection != NULL, FALSE);
04145   _dbus_return_val_if_fail (function != NULL, FALSE);
04146 
04147   filter = dbus_new0 (DBusMessageFilter, 1);
04148   if (filter == NULL)
04149     return FALSE;
04150 
04151   filter->refcount.value = 1;
04152   
04153   CONNECTION_LOCK (connection);
04154 
04155   if (!_dbus_list_append (&connection->filter_list,
04156                           filter))
04157     {
04158       _dbus_message_filter_unref (filter);
04159       CONNECTION_UNLOCK (connection);
04160       return FALSE;
04161     }
04162 
04163   /* Fill in filter after all memory allocated,
04164    * so we don't run the free_user_data_function
04165    * if the add_filter() fails
04166    */
04167   
04168   filter->function = function;
04169   filter->user_data = user_data;
04170   filter->free_user_data_function = free_data_function;
04171         
04172   CONNECTION_UNLOCK (connection);
04173   return TRUE;
04174 }
04175 
04188 void
04189 dbus_connection_remove_filter (DBusConnection            *connection,
04190                                DBusHandleMessageFunction  function,
04191                                void                      *user_data)
04192 {
04193   DBusList *link;
04194   DBusMessageFilter *filter;
04195   
04196   _dbus_return_if_fail (connection != NULL);
04197   _dbus_return_if_fail (function != NULL);
04198   
04199   CONNECTION_LOCK (connection);
04200 
04201   filter = NULL;
04202   
04203   link = _dbus_list_get_last_link (&connection->filter_list);
04204   while (link != NULL)
04205     {
04206       filter = link->data;
04207 
04208       if (filter->function == function &&
04209           filter->user_data == user_data)
04210         {
04211           _dbus_list_remove_link (&connection->filter_list, link);
04212           filter->function = NULL;
04213           
04214           break;
04215         }
04216         
04217       link = _dbus_list_get_prev_link (&connection->filter_list, link);
04218     }
04219   
04220   CONNECTION_UNLOCK (connection);
04221 
04222 #ifndef DBUS_DISABLE_CHECKS
04223   if (filter == NULL)
04224     {
04225       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04226                   function, user_data);
04227       return;
04228     }
04229 #endif
04230   
04231   /* Call application code */
04232   if (filter->free_user_data_function)
04233     (* filter->free_user_data_function) (filter->user_data);
04234 
04235   filter->free_user_data_function = NULL;
04236   filter->user_data = NULL;
04237   
04238   _dbus_message_filter_unref (filter);
04239 }
04240 
04252 dbus_bool_t
04253 dbus_connection_register_object_path (DBusConnection              *connection,
04254                                       const char                  *path,
04255                                       const DBusObjectPathVTable  *vtable,
04256                                       void                        *user_data)
04257 {
04258   char **decomposed_path;
04259   dbus_bool_t retval;
04260   
04261   _dbus_return_val_if_fail (connection != NULL, FALSE);
04262   _dbus_return_val_if_fail (path != NULL, FALSE);
04263   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04264   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04265 
04266   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04267     return FALSE;
04268 
04269   CONNECTION_LOCK (connection);
04270 
04271   retval = _dbus_object_tree_register (connection->objects,
04272                                        FALSE,
04273                                        (const char **) decomposed_path, vtable,
04274                                        user_data);
04275 
04276   CONNECTION_UNLOCK (connection);
04277 
04278   dbus_free_string_array (decomposed_path);
04279 
04280   return retval;
04281 }
04282 
04295 dbus_bool_t
04296 dbus_connection_register_fallback (DBusConnection              *connection,
04297                                    const char                  *path,
04298                                    const DBusObjectPathVTable  *vtable,
04299                                    void                        *user_data)
04300 {
04301   char **decomposed_path;
04302   dbus_bool_t retval;
04303   
04304   _dbus_return_val_if_fail (connection != NULL, FALSE);
04305   _dbus_return_val_if_fail (path != NULL, FALSE);
04306   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04307   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04308 
04309   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04310     return FALSE;
04311 
04312   CONNECTION_LOCK (connection);
04313 
04314   retval = _dbus_object_tree_register (connection->objects,
04315                                        TRUE,
04316                                        (const char **) decomposed_path, vtable,
04317                                        user_data);
04318 
04319   CONNECTION_UNLOCK (connection);
04320 
04321   dbus_free_string_array (decomposed_path);
04322 
04323   return retval;
04324 }
04325 
04335 dbus_bool_t
04336 dbus_connection_unregister_object_path (DBusConnection              *connection,
04337                                         const char                  *path)
04338 {
04339   char **decomposed_path;
04340 
04341   _dbus_return_val_if_fail (connection != NULL, FALSE);
04342   _dbus_return_val_if_fail (path != NULL, FALSE);
04343   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04344 
04345   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04346       return FALSE;
04347 
04348   CONNECTION_LOCK (connection);
04349 
04350   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04351 
04352   dbus_free_string_array (decomposed_path);
04353 
04354   return TRUE;
04355 }
04356 
04367 dbus_bool_t
04368 dbus_connection_get_object_path_data (DBusConnection *connection,
04369                                       const char     *path,
04370                                       void          **data_p)
04371 {
04372   char **decomposed_path;
04373 
04374   _dbus_return_val_if_fail (connection != NULL, FALSE);
04375   _dbus_return_val_if_fail (path != NULL, FALSE);
04376   _dbus_return_val_if_fail (data_p != NULL, FALSE);
04377 
04378   *data_p = NULL;
04379   
04380   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04381     return FALSE;
04382   
04383   CONNECTION_LOCK (connection);
04384 
04385   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04386 
04387   CONNECTION_UNLOCK (connection);
04388 
04389   dbus_free_string_array (decomposed_path);
04390 
04391   return TRUE;
04392 }
04393 
04404 dbus_bool_t
04405 dbus_connection_list_registered (DBusConnection              *connection,
04406                                  const char                  *parent_path,
04407                                  char                      ***child_entries)
04408 {
04409   char **decomposed_path;
04410   dbus_bool_t retval;
04411   _dbus_return_val_if_fail (connection != NULL, FALSE);
04412   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04413   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04414   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04415 
04416   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04417     return FALSE;
04418 
04419   CONNECTION_LOCK (connection);
04420 
04421   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04422                                                          (const char **) decomposed_path,
04423                                                          child_entries);
04424   dbus_free_string_array (decomposed_path);
04425 
04426   return retval;
04427 }
04428 
04429 static DBusDataSlotAllocator slot_allocator;
04430 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04431 
04446 dbus_bool_t
04447 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04448 {
04449   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04450                                           _DBUS_LOCK_NAME (connection_slots),
04451                                           slot_p);
04452 }
04453 
04465 void
04466 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04467 {
04468   _dbus_return_if_fail (*slot_p >= 0);
04469   
04470   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04471 }
04472 
04486 dbus_bool_t
04487 dbus_connection_set_data (DBusConnection   *connection,
04488                           dbus_int32_t      slot,
04489                           void             *data,
04490                           DBusFreeFunction  free_data_func)
04491 {
04492   DBusFreeFunction old_free_func;
04493   void *old_data;
04494   dbus_bool_t retval;
04495 
04496   _dbus_return_val_if_fail (connection != NULL, FALSE);
04497   _dbus_return_val_if_fail (slot >= 0, FALSE);
04498   
04499   CONNECTION_LOCK (connection);
04500 
04501   retval = _dbus_data_slot_list_set (&slot_allocator,
04502                                      &connection->slot_list,
04503                                      slot, data, free_data_func,
04504                                      &old_free_func, &old_data);
04505   
04506   CONNECTION_UNLOCK (connection);
04507 
04508   if (retval)
04509     {
04510       /* Do the actual free outside the connection lock */
04511       if (old_free_func)
04512         (* old_free_func) (old_data);
04513     }
04514 
04515   return retval;
04516 }
04517 
04526 void*
04527 dbus_connection_get_data (DBusConnection   *connection,
04528                           dbus_int32_t      slot)
04529 {
04530   void *res;
04531 
04532   _dbus_return_val_if_fail (connection != NULL, NULL);
04533   
04534   CONNECTION_LOCK (connection);
04535 
04536   res = _dbus_data_slot_list_get (&slot_allocator,
04537                                   &connection->slot_list,
04538                                   slot);
04539   
04540   CONNECTION_UNLOCK (connection);
04541 
04542   return res;
04543 }
04544 
04551 void
04552 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04553 {  
04554   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04555 }
04556 
04565 void
04566 dbus_connection_set_max_message_size (DBusConnection *connection,
04567                                       long            size)
04568 {
04569   _dbus_return_if_fail (connection != NULL);
04570   
04571   CONNECTION_LOCK (connection);
04572   _dbus_transport_set_max_message_size (connection->transport,
04573                                         size);
04574   CONNECTION_UNLOCK (connection);
04575 }
04576 
04583 long
04584 dbus_connection_get_max_message_size (DBusConnection *connection)
04585 {
04586   long res;
04587 
04588   _dbus_return_val_if_fail (connection != NULL, 0);
04589   
04590   CONNECTION_LOCK (connection);
04591   res = _dbus_transport_get_max_message_size (connection->transport);
04592   CONNECTION_UNLOCK (connection);
04593   return res;
04594 }
04595 
04621 void
04622 dbus_connection_set_max_received_size (DBusConnection *connection,
04623                                        long            size)
04624 {
04625   _dbus_return_if_fail (connection != NULL);
04626   
04627   CONNECTION_LOCK (connection);
04628   _dbus_transport_set_max_received_size (connection->transport,
04629                                          size);
04630   CONNECTION_UNLOCK (connection);
04631 }
04632 
04639 long
04640 dbus_connection_get_max_received_size (DBusConnection *connection)
04641 {
04642   long res;
04643 
04644   _dbus_return_val_if_fail (connection != NULL, 0);
04645   
04646   CONNECTION_LOCK (connection);
04647   res = _dbus_transport_get_max_received_size (connection->transport);
04648   CONNECTION_UNLOCK (connection);
04649   return res;
04650 }
04651 
04662 long
04663 dbus_connection_get_outgoing_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_counter_get_value (connection->outgoing_counter);
04671   CONNECTION_UNLOCK (connection);
04672   return res;
04673 }
04674 

Generated on Fri Sep 30 19:45:34 2005 for D-BUS by  doxygen 1.4.4