Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | 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 *message_returned_cond;
01080   DBusCondVar *dispatch_cond;
01081   DBusCondVar *io_path_cond;
01082   DBusList *disconnect_link;
01083   DBusMessage *disconnect_message;
01084   DBusCounter *outgoing_counter;
01085   DBusObjectTree *objects;
01086   
01087   watch_list = NULL;
01088   connection = NULL;
01089   pending_replies = NULL;
01090   timeout_list = NULL;
01091   mutex = NULL;
01092   io_path_mutex = NULL;
01093   dispatch_mutex = NULL;
01094   message_returned_cond = NULL;
01095   dispatch_cond = NULL;
01096   io_path_cond = NULL;
01097   disconnect_link = NULL;
01098   disconnect_message = NULL;
01099   outgoing_counter = NULL;
01100   objects = NULL;
01101   
01102   watch_list = _dbus_watch_list_new ();
01103   if (watch_list == NULL)
01104     goto error;
01105 
01106   timeout_list = _dbus_timeout_list_new ();
01107   if (timeout_list == NULL)
01108     goto error;  
01109 
01110   pending_replies =
01111     _dbus_hash_table_new (DBUS_HASH_INT,
01112                           NULL,
01113                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01114   if (pending_replies == NULL)
01115     goto error;
01116   
01117   connection = dbus_new0 (DBusConnection, 1);
01118   if (connection == NULL)
01119     goto error;
01120 
01121   mutex = _dbus_mutex_new ();
01122   if (mutex == NULL)
01123     goto error;
01124 
01125   io_path_mutex = _dbus_mutex_new ();
01126   if (io_path_mutex == NULL)
01127     goto error;
01128 
01129   dispatch_mutex = _dbus_mutex_new ();
01130   if (dispatch_mutex == NULL)
01131     goto error;
01132   
01133   message_returned_cond = _dbus_condvar_new ();
01134   if (message_returned_cond == NULL)
01135     goto error;
01136   
01137   dispatch_cond = _dbus_condvar_new ();
01138   if (dispatch_cond == NULL)
01139     goto error;
01140   
01141   io_path_cond = _dbus_condvar_new ();
01142   if (io_path_cond == NULL)
01143     goto error;
01144 
01145   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01146                                                 DBUS_INTERFACE_LOCAL,
01147                                                 "Disconnected");
01148   
01149   if (disconnect_message == NULL)
01150     goto error;
01151 
01152   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01153   if (disconnect_link == NULL)
01154     goto error;
01155 
01156   outgoing_counter = _dbus_counter_new ();
01157   if (outgoing_counter == NULL)
01158     goto error;
01159 
01160   objects = _dbus_object_tree_new (connection);
01161   if (objects == NULL)
01162     goto error;
01163   
01164   if (_dbus_modify_sigpipe)
01165     _dbus_disable_sigpipe ();
01166   
01167   connection->refcount.value = 1;
01168   connection->mutex = mutex;
01169   connection->dispatch_cond = dispatch_cond;
01170   connection->dispatch_mutex = dispatch_mutex;
01171   connection->io_path_cond = io_path_cond;
01172   connection->io_path_mutex = io_path_mutex;
01173   connection->transport = transport;
01174   connection->watches = watch_list;
01175   connection->timeouts = timeout_list;
01176   connection->pending_replies = pending_replies;
01177   connection->outgoing_counter = outgoing_counter;
01178   connection->filter_list = NULL;
01179   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01180   connection->objects = objects;
01181   connection->exit_on_disconnect = FALSE;
01182   connection->shareable = FALSE;
01183 #ifndef DBUS_DISABLE_CHECKS
01184   connection->generation = _dbus_current_generation;
01185 #endif
01186   
01187   _dbus_data_slot_list_init (&connection->slot_list);
01188 
01189   connection->client_serial = 1;
01190 
01191   connection->disconnect_message_link = disconnect_link;
01192 
01193   CONNECTION_LOCK (connection);
01194   
01195   if (!_dbus_transport_set_connection (transport, connection))
01196     goto error;
01197 
01198   _dbus_transport_ref (transport);
01199 
01200   CONNECTION_UNLOCK (connection);
01201   
01202   return connection;
01203   
01204  error:
01205   if (disconnect_message != NULL)
01206     dbus_message_unref (disconnect_message);
01207   
01208   if (disconnect_link != NULL)
01209     _dbus_list_free_link (disconnect_link);
01210   
01211   if (io_path_cond != NULL)
01212     _dbus_condvar_free (io_path_cond);
01213   
01214   if (dispatch_cond != NULL)
01215     _dbus_condvar_free (dispatch_cond);
01216   
01217   if (message_returned_cond != NULL)
01218     _dbus_condvar_free (message_returned_cond);
01219   
01220   if (mutex != NULL)
01221     _dbus_mutex_free (mutex);
01222 
01223   if (io_path_mutex != NULL)
01224     _dbus_mutex_free (io_path_mutex);
01225 
01226   if (dispatch_mutex != NULL)
01227     _dbus_mutex_free (dispatch_mutex);
01228   
01229   if (connection != NULL)
01230     dbus_free (connection);
01231 
01232   if (pending_replies)
01233     _dbus_hash_table_unref (pending_replies);
01234   
01235   if (watch_list)
01236     _dbus_watch_list_free (watch_list);
01237 
01238   if (timeout_list)
01239     _dbus_timeout_list_free (timeout_list);
01240 
01241   if (outgoing_counter)
01242     _dbus_counter_unref (outgoing_counter);
01243 
01244   if (objects)
01245     _dbus_object_tree_unref (objects);
01246   
01247   return NULL;
01248 }
01249 
01257 DBusConnection *
01258 _dbus_connection_ref_unlocked (DBusConnection *connection)
01259 {  
01260   _dbus_assert (connection != NULL);
01261   _dbus_assert (connection->generation == _dbus_current_generation);
01262 
01263   HAVE_LOCK_CHECK (connection);
01264   
01265 #ifdef DBUS_HAVE_ATOMIC_INT
01266   _dbus_atomic_inc (&connection->refcount);
01267 #else
01268   _dbus_assert (connection->refcount.value > 0);
01269   connection->refcount.value += 1;
01270 #endif
01271 
01272   return connection;
01273 }
01274 
01281 void
01282 _dbus_connection_unref_unlocked (DBusConnection *connection)
01283 {
01284   dbus_bool_t last_unref;
01285 
01286   HAVE_LOCK_CHECK (connection);
01287   
01288   _dbus_assert (connection != NULL);
01289 
01290   /* The connection lock is better than the global
01291    * lock in the atomic increment fallback
01292    */
01293   
01294 #ifdef DBUS_HAVE_ATOMIC_INT
01295   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01296 #else
01297   _dbus_assert (connection->refcount.value > 0);
01298 
01299   connection->refcount.value -= 1;
01300   last_unref = (connection->refcount.value == 0);  
01301 #if 0
01302   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01303 #endif
01304 #endif
01305   
01306   if (last_unref)
01307     _dbus_connection_last_unref (connection);
01308 }
01309 
01310 static dbus_uint32_t
01311 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01312 {
01313   int serial;
01314 
01315   serial = connection->client_serial++;
01316 
01317   if (connection->client_serial < 0)
01318     connection->client_serial = 1;
01319   
01320   return serial;
01321 }
01322 
01336 dbus_bool_t
01337 _dbus_connection_handle_watch (DBusWatch                   *watch,
01338                                unsigned int                 condition,
01339                                void                        *data)
01340 {
01341   DBusConnection *connection;
01342   dbus_bool_t retval;
01343   DBusDispatchStatus status;
01344 
01345   connection = data;
01346 
01347   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01348   
01349   CONNECTION_LOCK (connection);
01350   _dbus_connection_acquire_io_path (connection, -1);
01351   HAVE_LOCK_CHECK (connection);
01352   retval = _dbus_transport_handle_watch (connection->transport,
01353                                          watch, condition);
01354 
01355   _dbus_connection_release_io_path (connection);
01356 
01357   HAVE_LOCK_CHECK (connection);
01358 
01359   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01360   
01361   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01362 
01363   /* this calls out to user code */
01364   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01365 
01366   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01367   
01368   return retval;
01369 }
01370 
01371 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01372 static DBusHashTable *shared_connections = NULL;
01373 
01374 static void
01375 shared_connections_shutdown (void *data)
01376 {
01377   _DBUS_LOCK (shared_connections);
01378 
01379   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01380   _dbus_hash_table_unref (shared_connections);
01381   shared_connections = NULL;
01382   
01383   _DBUS_UNLOCK (shared_connections);
01384 }
01385 
01386 static dbus_bool_t
01387 connection_lookup_shared (DBusAddressEntry  *entry,
01388                           DBusConnection   **result)
01389 {
01390   _dbus_verbose ("checking for existing connection\n");
01391   
01392   *result = NULL;
01393   
01394   _DBUS_LOCK (shared_connections);
01395 
01396   if (shared_connections == NULL)
01397     {
01398       _dbus_verbose ("creating shared_connections hash table\n");
01399       
01400       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01401                                                  dbus_free,
01402                                                  NULL);
01403       if (shared_connections == NULL)
01404         {
01405           _DBUS_UNLOCK (shared_connections);
01406           return FALSE;
01407         }
01408 
01409       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01410         {
01411           _dbus_hash_table_unref (shared_connections);
01412           shared_connections = NULL;
01413           _DBUS_UNLOCK (shared_connections);
01414           return FALSE;
01415         }
01416 
01417       _dbus_verbose ("  successfully created shared_connections\n");
01418       
01419       _DBUS_UNLOCK (shared_connections);
01420       return TRUE; /* no point looking up in the hash we just made */
01421     }
01422   else
01423     {
01424       const char *guid;
01425 
01426       guid = dbus_address_entry_get_value (entry, "guid");
01427       
01428       if (guid != NULL)
01429         {
01430           *result = _dbus_hash_table_lookup_string (shared_connections,
01431                                                     guid);
01432 
01433           if (*result)
01434             {
01435               /* The DBusConnection can't have been disconnected
01436                * between the lookup and this code, because the
01437                * disconnection will take the shared_connections lock to
01438                * remove the connection. It can't have been finalized
01439                * since you have to disconnect prior to finalize.
01440                *
01441                * Thus it's safe to ref the connection.
01442                */
01443               dbus_connection_ref (*result);
01444 
01445               _dbus_verbose ("looked up existing connection to server guid %s\n",
01446                              guid);
01447             }
01448         }
01449       
01450       _DBUS_UNLOCK (shared_connections);
01451       return TRUE;
01452     }
01453 }
01454 
01455 static dbus_bool_t
01456 connection_record_shared_unlocked (DBusConnection *connection,
01457                                    const char     *guid)
01458 {
01459   char *guid_key;
01460   char *guid_in_connection;
01461 
01462   /* A separate copy of the key is required in the hash table, because
01463    * we don't have a lock on the connection when we are doing a hash
01464    * lookup.
01465    */
01466   
01467   _dbus_assert (connection->server_guid == NULL);
01468   _dbus_assert (connection->shareable);
01469   
01470   guid_key = _dbus_strdup (guid);
01471   if (guid_key == NULL)
01472     return FALSE;
01473 
01474   guid_in_connection = _dbus_strdup (guid);
01475   if (guid_in_connection == NULL)
01476     {
01477       dbus_free (guid_key);
01478       return FALSE;
01479     }
01480   
01481   _DBUS_LOCK (shared_connections);
01482   _dbus_assert (shared_connections != NULL);
01483   
01484   if (!_dbus_hash_table_insert_string (shared_connections,
01485                                        guid_key, connection))
01486     {
01487       dbus_free (guid_key);
01488       dbus_free (guid_in_connection);
01489       _DBUS_UNLOCK (shared_connections);
01490       return FALSE;
01491     }
01492 
01493   connection->server_guid = guid_in_connection;
01494 
01495   _dbus_verbose ("stored connection to %s to be shared\n",
01496                  connection->server_guid);
01497   
01498   _DBUS_UNLOCK (shared_connections);
01499 
01500   _dbus_assert (connection->server_guid != NULL);
01501   
01502   return TRUE;
01503 }
01504 
01505 static void
01506 connection_forget_shared_unlocked (DBusConnection *connection)
01507 {
01508   HAVE_LOCK_CHECK (connection);
01509   
01510   if (connection->server_guid == NULL)
01511     return;
01512 
01513   _dbus_verbose ("dropping connection to %s out of the shared table\n",
01514                  connection->server_guid);
01515   
01516   _DBUS_LOCK (shared_connections);
01517 
01518   if (!_dbus_hash_table_remove_string (shared_connections,
01519                                        connection->server_guid))
01520     _dbus_assert_not_reached ("connection was not in the shared table");
01521   
01522   dbus_free (connection->server_guid);
01523   connection->server_guid = NULL;
01524 
01525   _DBUS_UNLOCK (shared_connections);
01526 }
01527 
01528 static DBusConnection*
01529 connection_try_from_address_entry (DBusAddressEntry *entry,
01530                                    DBusError        *error)
01531 {
01532   DBusTransport *transport;
01533   DBusConnection *connection;
01534 
01535   transport = _dbus_transport_open (entry, error);
01536 
01537   if (transport == NULL)
01538     {
01539       _DBUS_ASSERT_ERROR_IS_SET (error);
01540       return NULL;
01541     }
01542 
01543   connection = _dbus_connection_new_for_transport (transport);
01544 
01545   _dbus_transport_unref (transport);
01546   
01547   if (connection == NULL)
01548     {
01549       _DBUS_SET_OOM (error);
01550       return NULL;
01551     }
01552 
01553 #ifndef DBUS_DISABLE_CHECKS
01554   _dbus_assert (!connection->have_connection_lock);
01555 #endif
01556   return connection;
01557 }
01558 
01559 /*
01560  * If the shared parameter is true, then any existing connection will
01561  * be used (and if a new connection is created, it will be available
01562  * for use by others). If the shared parameter is false, a new
01563  * connection will always be created, and the new connection will
01564  * never be returned to other callers.
01565  *
01566  * @param address the address
01567  * @param shared whether the connection is shared or private
01568  * @param error error return
01569  * @returns the connection or #NULL on error
01570  */
01571 static DBusConnection*
01572 _dbus_connection_open_internal (const char     *address,
01573                                 dbus_bool_t     shared,
01574                                 DBusError      *error)
01575 {
01576   DBusConnection *connection;
01577   DBusAddressEntry **entries;
01578   DBusError tmp_error;
01579   DBusError first_error;
01580   int len, i;
01581 
01582   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01583 
01584   _dbus_verbose ("opening %s connection to: %s\n",
01585                  shared ? "shared" : "private", address);
01586   
01587   if (!dbus_parse_address (address, &entries, &len, error))
01588     return NULL;
01589 
01590   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01591   
01592   connection = NULL;
01593 
01594   dbus_error_init (&tmp_error);
01595   dbus_error_init (&first_error);
01596   for (i = 0; i < len; i++)
01597     {
01598       if (shared)
01599         {
01600           if (!connection_lookup_shared (entries[i], &connection))
01601             _DBUS_SET_OOM (&tmp_error);
01602         }
01603 
01604       if (connection == NULL)
01605         {
01606           connection = connection_try_from_address_entry (entries[i],
01607                                                           &tmp_error);
01608           
01609           if (connection != NULL && shared)
01610             {
01611               const char *guid;
01612 
01613               connection->shareable = TRUE;
01614               
01615               guid = dbus_address_entry_get_value (entries[i], "guid");
01616 
01617               /* we don't have a connection lock but we know nobody
01618                * else has a handle to the connection
01619                */
01620               
01621               if (guid &&
01622                   !connection_record_shared_unlocked (connection, guid))
01623                 {
01624                   _DBUS_SET_OOM (&tmp_error);
01625                   dbus_connection_close (connection);
01626                   dbus_connection_unref (connection);
01627                   connection = NULL;
01628                 }
01629 
01630               /* but as of now the connection is possibly shared
01631                * since another thread could have pulled it from the table
01632                */
01633             }
01634         }
01635       
01636       if (connection)
01637         break;
01638 
01639       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01640       
01641       if (i == 0)
01642         dbus_move_error (&tmp_error, &first_error);
01643       else
01644         dbus_error_free (&tmp_error);
01645     }
01646 
01647   /* NOTE we don't have a lock on a possibly-shared connection object */
01648   
01649   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01650   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01651   
01652   if (connection == NULL)
01653     {
01654       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01655       dbus_move_error (&first_error, error);
01656     }
01657   else
01658     {
01659       dbus_error_free (&first_error);
01660     }
01661   
01662   dbus_address_entries_free (entries);
01663   return connection;
01664 }
01665 
01693 DBusConnection*
01694 dbus_connection_open (const char     *address,
01695                       DBusError      *error)
01696 {
01697   DBusConnection *connection;
01698 
01699   _dbus_return_val_if_fail (address != NULL, NULL);
01700   _dbus_return_val_if_error_is_set (error, NULL);
01701 
01702   connection = _dbus_connection_open_internal (address,
01703                                                TRUE,
01704                                                error);
01705 
01706   return connection;
01707 }
01708 
01723 DBusConnection*
01724 dbus_connection_open_private (const char     *address,
01725                               DBusError      *error)
01726 {
01727   DBusConnection *connection;
01728 
01729   _dbus_return_val_if_fail (address != NULL, NULL);
01730   _dbus_return_val_if_error_is_set (error, NULL);
01731 
01732   connection = _dbus_connection_open_internal (address,
01733                                                FALSE,
01734                                                error);
01735 
01736   return connection;
01737 }
01738 
01745 DBusConnection *
01746 dbus_connection_ref (DBusConnection *connection)
01747 {
01748   _dbus_return_val_if_fail (connection != NULL, NULL);
01749   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01750   
01751   /* The connection lock is better than the global
01752    * lock in the atomic increment fallback
01753    */
01754   
01755 #ifdef DBUS_HAVE_ATOMIC_INT
01756   _dbus_atomic_inc (&connection->refcount);
01757 #else
01758   CONNECTION_LOCK (connection);
01759   _dbus_assert (connection->refcount.value > 0);
01760 
01761   connection->refcount.value += 1;
01762   CONNECTION_UNLOCK (connection);
01763 #endif
01764 
01765   return connection;
01766 }
01767 
01768 static void
01769 free_outgoing_message (void *element,
01770                        void *data)
01771 {
01772   DBusMessage *message = element;
01773   DBusConnection *connection = data;
01774 
01775   _dbus_message_remove_size_counter (message,
01776                                      connection->outgoing_counter,
01777                                      NULL);
01778   dbus_message_unref (message);
01779 }
01780 
01781 /* This is run without the mutex held, but after the last reference
01782  * to the connection has been dropped we should have no thread-related
01783  * problems
01784  */
01785 static void
01786 _dbus_connection_last_unref (DBusConnection *connection)
01787 {
01788   DBusList *link;
01789 
01790   _dbus_verbose ("Finalizing connection %p\n", connection);
01791   
01792   _dbus_assert (connection->refcount.value == 0);
01793   
01794   /* You have to disconnect the connection before unref:ing it. Otherwise
01795    * you won't get the disconnected message.
01796    */
01797   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01798   _dbus_assert (connection->server_guid == NULL);
01799   
01800   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
01801   _dbus_object_tree_free_all_unlocked (connection->objects);
01802   
01803   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01804   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01805   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01806   
01807   _dbus_watch_list_free (connection->watches);
01808   connection->watches = NULL;
01809   
01810   _dbus_timeout_list_free (connection->timeouts);
01811   connection->timeouts = NULL;
01812 
01813   _dbus_data_slot_list_free (&connection->slot_list);
01814   
01815   link = _dbus_list_get_first_link (&connection->filter_list);
01816   while (link != NULL)
01817     {
01818       DBusMessageFilter *filter = link->data;
01819       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01820 
01821       filter->function = NULL;
01822       _dbus_message_filter_unref (filter); /* calls app callback */
01823       link->data = NULL;
01824       
01825       link = next;
01826     }
01827   _dbus_list_clear (&connection->filter_list);
01828   
01829   /* ---- Done with stuff that invokes application callbacks */
01830 
01831   _dbus_object_tree_unref (connection->objects);  
01832 
01833   _dbus_hash_table_unref (connection->pending_replies);
01834   connection->pending_replies = NULL;
01835   
01836   _dbus_list_clear (&connection->filter_list);
01837   
01838   _dbus_list_foreach (&connection->outgoing_messages,
01839                       free_outgoing_message,
01840                       connection);
01841   _dbus_list_clear (&connection->outgoing_messages);
01842   
01843   _dbus_list_foreach (&connection->incoming_messages,
01844                       (DBusForeachFunction) dbus_message_unref,
01845                       NULL);
01846   _dbus_list_clear (&connection->incoming_messages);
01847 
01848   _dbus_counter_unref (connection->outgoing_counter);
01849 
01850   _dbus_transport_unref (connection->transport);
01851 
01852   if (connection->disconnect_message_link)
01853     {
01854       DBusMessage *message = connection->disconnect_message_link->data;
01855       dbus_message_unref (message);
01856       _dbus_list_free_link (connection->disconnect_message_link);
01857     }
01858 
01859   _dbus_list_clear (&connection->link_cache);
01860   
01861   _dbus_condvar_free (connection->dispatch_cond);
01862   _dbus_condvar_free (connection->io_path_cond);
01863 
01864   _dbus_mutex_free (connection->io_path_mutex);
01865   _dbus_mutex_free (connection->dispatch_mutex);
01866 
01867   _dbus_mutex_free (connection->mutex);
01868   
01869   dbus_free (connection);
01870 }
01871 
01883 void
01884 dbus_connection_unref (DBusConnection *connection)
01885 {
01886   dbus_bool_t last_unref;
01887 
01888   _dbus_return_if_fail (connection != NULL);
01889   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01890   
01891   /* The connection lock is better than the global
01892    * lock in the atomic increment fallback
01893    */
01894   
01895 #ifdef DBUS_HAVE_ATOMIC_INT
01896   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01897 #else
01898   CONNECTION_LOCK (connection);
01899   
01900   _dbus_assert (connection->refcount.value > 0);
01901 
01902   connection->refcount.value -= 1;
01903   last_unref = (connection->refcount.value == 0);
01904 
01905 #if 0
01906   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01907 #endif
01908   
01909   CONNECTION_UNLOCK (connection);
01910 #endif
01911   
01912   if (last_unref)
01913     _dbus_connection_last_unref (connection);
01914 }
01915 
01929 void
01930 dbus_connection_close (DBusConnection *connection)
01931 {
01932   DBusDispatchStatus status;
01933   
01934   _dbus_return_if_fail (connection != NULL);
01935   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01936 
01937   _dbus_verbose ("Disconnecting %p\n", connection);
01938   
01939   CONNECTION_LOCK (connection);
01940   
01941   _dbus_transport_disconnect (connection->transport);
01942 
01943   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01944   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01945 
01946   /* this calls out to user code */
01947   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01948 }
01949 
01956 void
01957 dbus_connection_disconnect (DBusConnection *connection)
01958 {
01959   dbus_connection_close (connection);
01960 }
01961 
01962 static dbus_bool_t
01963 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01964 {
01965   HAVE_LOCK_CHECK (connection);
01966   return _dbus_transport_get_is_connected (connection->transport);
01967 }
01968 
01979 dbus_bool_t
01980 dbus_connection_get_is_connected (DBusConnection *connection)
01981 {
01982   dbus_bool_t res;
01983 
01984   _dbus_return_val_if_fail (connection != NULL, FALSE);
01985   
01986   CONNECTION_LOCK (connection);
01987   res = _dbus_connection_get_is_connected_unlocked (connection);
01988   CONNECTION_UNLOCK (connection);
01989   
01990   return res;
01991 }
01992 
02001 dbus_bool_t
02002 dbus_connection_get_is_authenticated (DBusConnection *connection)
02003 {
02004   dbus_bool_t res;
02005 
02006   _dbus_return_val_if_fail (connection != NULL, FALSE);
02007   
02008   CONNECTION_LOCK (connection);
02009   res = _dbus_transport_get_is_authenticated (connection->transport);
02010   CONNECTION_UNLOCK (connection);
02011   
02012   return res;
02013 }
02014 
02028 void
02029 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02030                                         dbus_bool_t     exit_on_disconnect)
02031 {
02032   _dbus_return_if_fail (connection != NULL);
02033 
02034   CONNECTION_LOCK (connection);
02035   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02036   CONNECTION_UNLOCK (connection);
02037 }
02038 
02039 static DBusPreallocatedSend*
02040 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02041 {
02042   DBusPreallocatedSend *preallocated;
02043 
02044   HAVE_LOCK_CHECK (connection);
02045   
02046   _dbus_assert (connection != NULL);
02047   
02048   preallocated = dbus_new (DBusPreallocatedSend, 1);
02049   if (preallocated == NULL)
02050     return NULL;
02051 
02052   if (connection->link_cache != NULL)
02053     {
02054       preallocated->queue_link =
02055         _dbus_list_pop_first_link (&connection->link_cache);
02056       preallocated->queue_link->data = NULL;
02057     }
02058   else
02059     {
02060       preallocated->queue_link = _dbus_list_alloc_link (NULL);
02061       if (preallocated->queue_link == NULL)
02062         goto failed_0;
02063     }
02064   
02065   if (connection->link_cache != NULL)
02066     {
02067       preallocated->counter_link =
02068         _dbus_list_pop_first_link (&connection->link_cache);
02069       preallocated->counter_link->data = connection->outgoing_counter;
02070     }
02071   else
02072     {
02073       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02074       if (preallocated->counter_link == NULL)
02075         goto failed_1;
02076     }
02077 
02078   _dbus_counter_ref (preallocated->counter_link->data);
02079 
02080   preallocated->connection = connection;
02081   
02082   return preallocated;
02083   
02084  failed_1:
02085   _dbus_list_free_link (preallocated->queue_link);
02086  failed_0:
02087   dbus_free (preallocated);
02088   
02089   return NULL;
02090 }
02091 
02101 DBusPreallocatedSend*
02102 dbus_connection_preallocate_send (DBusConnection *connection)
02103 {
02104   DBusPreallocatedSend *preallocated;
02105 
02106   _dbus_return_val_if_fail (connection != NULL, NULL);
02107 
02108   CONNECTION_LOCK (connection);
02109   
02110   preallocated =
02111     _dbus_connection_preallocate_send_unlocked (connection);
02112 
02113   CONNECTION_UNLOCK (connection);
02114 
02115   return preallocated;
02116 }
02117 
02127 void
02128 dbus_connection_free_preallocated_send (DBusConnection       *connection,
02129                                         DBusPreallocatedSend *preallocated)
02130 {
02131   _dbus_return_if_fail (connection != NULL);
02132   _dbus_return_if_fail (preallocated != NULL);  
02133   _dbus_return_if_fail (connection == preallocated->connection);
02134 
02135   _dbus_list_free_link (preallocated->queue_link);
02136   _dbus_counter_unref (preallocated->counter_link->data);
02137   _dbus_list_free_link (preallocated->counter_link);
02138   dbus_free (preallocated);
02139 }
02140 
02141 /* Called with lock held, does not update dispatch status */
02142 static void
02143 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
02144                                                        DBusPreallocatedSend *preallocated,
02145                                                        DBusMessage          *message,
02146                                                        dbus_uint32_t        *client_serial)
02147 {
02148   dbus_uint32_t serial;
02149   const char *sig;
02150 
02151   preallocated->queue_link->data = message;
02152   _dbus_list_prepend_link (&connection->outgoing_messages,
02153                            preallocated->queue_link);
02154 
02155   _dbus_message_add_size_counter_link (message,
02156                                        preallocated->counter_link);
02157 
02158   dbus_free (preallocated);
02159   preallocated = NULL;
02160   
02161   dbus_message_ref (message);
02162   
02163   connection->n_outgoing += 1;
02164 
02165   sig = dbus_message_get_signature (message);
02166   
02167   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02168                  message,
02169                  dbus_message_get_type (message),
02170                  dbus_message_get_path (message),
02171                  dbus_message_get_interface (message) ?
02172                  dbus_message_get_interface (message) :
02173                  "no interface",
02174                  dbus_message_get_member (message) ?
02175                  dbus_message_get_member (message) :
02176                  "no member",
02177                  sig,
02178                  dbus_message_get_destination (message) ?
02179                  dbus_message_get_destination (message) :
02180                  "null",
02181                  connection,
02182                  connection->n_outgoing);
02183 
02184   if (dbus_message_get_serial (message) == 0)
02185     {
02186       serial = _dbus_connection_get_next_client_serial (connection);
02187       _dbus_message_set_serial (message, serial);
02188       if (client_serial)
02189         *client_serial = serial;
02190     }
02191   else
02192     {
02193       if (client_serial)
02194         *client_serial = dbus_message_get_serial (message);
02195     }
02196 
02197   _dbus_verbose ("Message %p serial is %u\n",
02198                  message, dbus_message_get_serial (message));
02199   
02200   _dbus_message_lock (message);
02201 
02202   /* Now we need to run an iteration to hopefully just write the messages
02203    * out immediately, and otherwise get them queued up
02204    */
02205   _dbus_connection_do_iteration_unlocked (connection,
02206                                           DBUS_ITERATION_DO_WRITING,
02207                                           -1);
02208 
02209   /* If stuff is still queued up, be sure we wake up the main loop */
02210   if (connection->n_outgoing > 0)
02211     _dbus_connection_wakeup_mainloop (connection);
02212 }
02213 
02214 static void
02215 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02216                                                DBusPreallocatedSend *preallocated,
02217                                                DBusMessage          *message,
02218                                                dbus_uint32_t        *client_serial)
02219 {
02220   DBusDispatchStatus status;
02221 
02222   HAVE_LOCK_CHECK (connection);
02223   
02224   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02225                                                          preallocated,
02226                                                          message, client_serial);
02227 
02228   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02229   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02230 
02231   /* this calls out to user code */
02232   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02233 }
02234 
02247 void
02248 dbus_connection_send_preallocated (DBusConnection       *connection,
02249                                    DBusPreallocatedSend *preallocated,
02250                                    DBusMessage          *message,
02251                                    dbus_uint32_t        *client_serial)
02252 {
02253   _dbus_return_if_fail (connection != NULL);
02254   _dbus_return_if_fail (preallocated != NULL);
02255   _dbus_return_if_fail (message != NULL);
02256   _dbus_return_if_fail (preallocated->connection == connection);
02257   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02258                         (dbus_message_get_interface (message) != NULL &&
02259                          dbus_message_get_member (message) != NULL));
02260   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02261                         (dbus_message_get_interface (message) != NULL &&
02262                          dbus_message_get_member (message) != NULL));
02263   
02264   CONNECTION_LOCK (connection);
02265   _dbus_connection_send_preallocated_and_unlock (connection,
02266                                                  preallocated,
02267                                                  message, client_serial);
02268 }
02269 
02270 static dbus_bool_t
02271 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02272                                           DBusMessage    *message,
02273                                           dbus_uint32_t  *client_serial)
02274 {
02275   DBusPreallocatedSend *preallocated;
02276 
02277   _dbus_assert (connection != NULL);
02278   _dbus_assert (message != NULL);
02279   
02280   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02281   if (preallocated == NULL)
02282     return FALSE;
02283 
02284   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02285                                                          preallocated,
02286                                                          message,
02287                                                          client_serial);
02288   return TRUE;
02289 }
02290 
02291 dbus_bool_t
02292 _dbus_connection_send_and_unlock (DBusConnection *connection,
02293                                   DBusMessage    *message,
02294                                   dbus_uint32_t  *client_serial)
02295 {
02296   DBusPreallocatedSend *preallocated;
02297 
02298   _dbus_assert (connection != NULL);
02299   _dbus_assert (message != NULL);
02300   
02301   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02302   if (preallocated == NULL)
02303     {
02304       CONNECTION_UNLOCK (connection);
02305       return FALSE;
02306     }
02307 
02308   _dbus_connection_send_preallocated_and_unlock (connection,
02309                                                  preallocated,
02310                                                  message,
02311                                                  client_serial);
02312   return TRUE;
02313 }
02314 
02333 dbus_bool_t
02334 dbus_connection_send (DBusConnection *connection,
02335                       DBusMessage    *message,
02336                       dbus_uint32_t  *client_serial)
02337 {
02338   _dbus_return_val_if_fail (connection != NULL, FALSE);
02339   _dbus_return_val_if_fail (message != NULL, FALSE);
02340 
02341   CONNECTION_LOCK (connection);
02342 
02343   return _dbus_connection_send_and_unlock (connection,
02344                                            message,
02345                                            client_serial);
02346 }
02347 
02348 static dbus_bool_t
02349 reply_handler_timeout (void *data)
02350 {
02351   DBusConnection *connection;
02352   DBusDispatchStatus status;
02353   DBusPendingCall *pending = data;
02354 
02355   connection = pending->connection;
02356   
02357   CONNECTION_LOCK (connection);
02358   if (pending->timeout_link)
02359     {
02360       _dbus_connection_queue_synthesized_message_link (connection,
02361                                                        pending->timeout_link);
02362       pending->timeout_link = NULL;
02363     }
02364 
02365   _dbus_connection_remove_timeout (connection,
02366                                    pending->timeout);
02367   pending->timeout_added = FALSE;
02368 
02369   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02370   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02371 
02372   /* Unlocks, and calls out to user code */
02373   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02374   
02375   return TRUE;
02376 }
02377 
02415 dbus_bool_t
02416 dbus_connection_send_with_reply (DBusConnection     *connection,
02417                                  DBusMessage        *message,
02418                                  DBusPendingCall   **pending_return,
02419                                  int                 timeout_milliseconds)
02420 {
02421   DBusPendingCall *pending;
02422   DBusMessage *reply;
02423   DBusList *reply_link;
02424   dbus_int32_t serial = -1;
02425   DBusDispatchStatus status;
02426 
02427   _dbus_return_val_if_fail (connection != NULL, FALSE);
02428   _dbus_return_val_if_fail (message != NULL, FALSE);
02429   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02430 
02431   if (pending_return)
02432     *pending_return = NULL;
02433   
02434   pending = _dbus_pending_call_new (connection,
02435                                     timeout_milliseconds,
02436                                     reply_handler_timeout);
02437 
02438   if (pending == NULL)
02439     return FALSE;
02440 
02441   CONNECTION_LOCK (connection);
02442   
02443   /* Assign a serial to the message */
02444   if (dbus_message_get_serial (message) == 0)
02445     {
02446       serial = _dbus_connection_get_next_client_serial (connection);
02447       _dbus_message_set_serial (message, serial);
02448     }
02449 
02450   pending->reply_serial = serial;
02451 
02452   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02453                                   "No reply within specified time");
02454   if (reply == NULL)
02455     goto error;
02456 
02457   reply_link = _dbus_list_alloc_link (reply);
02458   if (reply_link == NULL)
02459     {
02460       CONNECTION_UNLOCK (connection);
02461       dbus_message_unref (reply);
02462       goto error_unlocked;
02463     }
02464 
02465   pending->timeout_link = reply_link;
02466 
02467   /* Insert the serial in the pending replies hash;
02468    * hash takes a refcount on DBusPendingCall.
02469    * Also, add the timeout.
02470    */
02471   if (!_dbus_connection_attach_pending_call_unlocked (connection,
02472                                                       pending))
02473     goto error;
02474  
02475   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02476     {
02477       _dbus_connection_detach_pending_call_and_unlock (connection,
02478                                                        pending);
02479       goto error_unlocked;
02480     }
02481 
02482   if (pending_return)
02483     *pending_return = pending;
02484   else
02485     {
02486       _dbus_connection_detach_pending_call_unlocked (connection, pending);
02487       dbus_pending_call_unref (pending);
02488     }
02489 
02490   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02491   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02492 
02493   /* this calls out to user code */
02494   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02495 
02496   return TRUE;
02497 
02498  error:
02499   CONNECTION_UNLOCK (connection);
02500  error_unlocked:
02501   dbus_pending_call_unref (pending);
02502   return FALSE;
02503 }
02504 
02505 /* This is slightly strange since we can pop a message here without
02506  * the dispatch lock.
02507  */
02508 static DBusMessage*
02509 check_for_reply_unlocked (DBusConnection *connection,
02510                           dbus_uint32_t   client_serial)
02511 {
02512   DBusList *link;
02513 
02514   HAVE_LOCK_CHECK (connection);
02515   
02516   link = _dbus_list_get_first_link (&connection->incoming_messages);
02517 
02518   while (link != NULL)
02519     {
02520       DBusMessage *reply = link->data;
02521 
02522       if (dbus_message_get_reply_serial (reply) == client_serial)
02523         {
02524           _dbus_list_remove_link (&connection->incoming_messages, link);
02525           connection->n_incoming  -= 1;
02526           return reply;
02527         }
02528       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02529     }
02530 
02531   return NULL;
02532 }
02533 
02543 static void
02544 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02545 {
02546   if (timeout_milliseconds == -1)
02547     _dbus_sleep_milliseconds (1000);
02548   else if (timeout_milliseconds < 100)
02549     ; /* just busy loop */
02550   else if (timeout_milliseconds <= 1000)
02551     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02552   else
02553     _dbus_sleep_milliseconds (1000);
02554 }
02555 
02570 void
02571 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02572 {
02573   long start_tv_sec, start_tv_usec;
02574   long end_tv_sec, end_tv_usec;
02575   long tv_sec, tv_usec;
02576   DBusDispatchStatus status;
02577   DBusConnection *connection;
02578   dbus_uint32_t client_serial;
02579   int timeout_milliseconds;
02580 
02581   _dbus_assert (pending != NULL);
02582 
02583   if (dbus_pending_call_get_completed (pending))
02584     return;
02585 
02586   if (pending->connection == NULL)
02587     return; /* call already detached */
02588 
02589   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02590   
02591   connection = pending->connection;
02592   client_serial = pending->reply_serial;
02593 
02594   /* note that timeout_milliseconds is limited to a smallish value
02595    * in _dbus_pending_call_new() so overflows aren't possible
02596    * below
02597    */
02598   timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02599 
02600   /* Flush message queue */
02601   dbus_connection_flush (connection);
02602 
02603   CONNECTION_LOCK (connection);
02604 
02605   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02606   end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02607   end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02608   end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02609   end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02610 
02611   _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",
02612                  timeout_milliseconds,
02613                  client_serial,
02614                  start_tv_sec, start_tv_usec,
02615                  end_tv_sec, end_tv_usec);
02616 
02617   /* Now we wait... */
02618   /* always block at least once as we know we don't have the reply yet */
02619   _dbus_connection_do_iteration_unlocked (connection,
02620                                           DBUS_ITERATION_DO_READING |
02621                                           DBUS_ITERATION_BLOCK,
02622                                           timeout_milliseconds);
02623 
02624  recheck_status:
02625 
02626   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02627   
02628   HAVE_LOCK_CHECK (connection);
02629   
02630   /* queue messages and get status */
02631 
02632   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02633 
02634   /* the get_completed() is in case a dispatch() while we were blocking
02635    * got the reply instead of us.
02636    */
02637   if (dbus_pending_call_get_completed (pending))
02638     {
02639       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02640       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02641       dbus_pending_call_unref (pending);
02642       return;
02643     }
02644   
02645   if (status == DBUS_DISPATCH_DATA_REMAINS)
02646     {
02647       DBusMessage *reply;
02648       
02649       reply = check_for_reply_unlocked (connection, client_serial);
02650       if (reply != NULL)
02651         {
02652           _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02653 
02654           _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02655           
02656           _dbus_pending_call_complete_and_unlock (pending, reply);
02657           dbus_message_unref (reply);
02658 
02659           CONNECTION_LOCK (connection);
02660           status = _dbus_connection_get_dispatch_status_unlocked (connection);
02661           _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02662           dbus_pending_call_unref (pending);
02663           
02664           return;
02665         }
02666     }
02667   
02668   _dbus_get_current_time (&tv_sec, &tv_usec);
02669   
02670   if (!_dbus_connection_get_is_connected_unlocked (connection))
02671     {
02672       /* FIXME send a "DBUS_ERROR_DISCONNECTED" instead, just to help
02673        * programmers understand what went wrong since the timeout is
02674        * confusing
02675        */
02676       
02677       _dbus_pending_call_complete_and_unlock (pending, NULL);
02678       dbus_pending_call_unref (pending);
02679       return;
02680     }
02681   else if (tv_sec < start_tv_sec)
02682     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02683   else if (connection->disconnect_message_link == NULL)
02684     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02685   else if (tv_sec < end_tv_sec ||
02686            (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02687     {
02688       timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02689         (end_tv_usec - tv_usec) / 1000;
02690       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02691       _dbus_assert (timeout_milliseconds >= 0);
02692       
02693       if (status == DBUS_DISPATCH_NEED_MEMORY)
02694         {
02695           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02696            * we may already have a reply in the buffer and just can't process
02697            * it.
02698            */
02699           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02700 
02701           _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02702         }
02703       else
02704         {          
02705           /* block again, we don't have the reply buffered yet. */
02706           _dbus_connection_do_iteration_unlocked (connection,
02707                                                   DBUS_ITERATION_DO_READING |
02708                                                   DBUS_ITERATION_BLOCK,
02709                                                   timeout_milliseconds);
02710         }
02711 
02712       goto recheck_status;
02713     }
02714 
02715   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02716                  (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02717 
02718   _dbus_assert (!dbus_pending_call_get_completed (pending));
02719   
02720   /* unlock and call user code */
02721   _dbus_pending_call_complete_and_unlock (pending, NULL);
02722 
02723   /* update user code on dispatch status */
02724   CONNECTION_LOCK (connection);
02725   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02726   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02727   dbus_pending_call_unref (pending);
02728 }
02729 
02752 DBusMessage*
02753 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
02754                                            DBusMessage        *message,
02755                                            int                 timeout_milliseconds,
02756                                            DBusError          *error)
02757 {
02758   DBusMessage *reply;
02759   DBusPendingCall *pending;
02760   
02761   _dbus_return_val_if_fail (connection != NULL, NULL);
02762   _dbus_return_val_if_fail (message != NULL, NULL);
02763   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);  
02764   _dbus_return_val_if_error_is_set (error, NULL);
02765   
02766   if (!dbus_connection_send_with_reply (connection, message,
02767                                         &pending, timeout_milliseconds))
02768     {
02769       _DBUS_SET_OOM (error);
02770       return NULL;
02771     }
02772 
02773   _dbus_assert (pending != NULL);
02774   
02775   dbus_pending_call_block (pending);
02776 
02777   reply = dbus_pending_call_steal_reply (pending);
02778   dbus_pending_call_unref (pending);
02779 
02780   /* call_complete_and_unlock() called from pending_call_block() should
02781    * always fill this in.
02782    */
02783   _dbus_assert (reply != NULL);
02784   
02785    if (dbus_set_error_from_message (error, reply))
02786     {
02787       dbus_message_unref (reply);
02788       return NULL;
02789     }
02790   else
02791     return reply;
02792 }
02793 
02799 void
02800 dbus_connection_flush (DBusConnection *connection)
02801 {
02802   /* We have to specify DBUS_ITERATION_DO_READING here because
02803    * otherwise we could have two apps deadlock if they are both doing
02804    * a flush(), and the kernel buffers fill up. This could change the
02805    * dispatch status.
02806    */
02807   DBusDispatchStatus status;
02808 
02809   _dbus_return_if_fail (connection != NULL);
02810   
02811   CONNECTION_LOCK (connection);
02812   while (connection->n_outgoing > 0 &&
02813          _dbus_connection_get_is_connected_unlocked (connection))
02814     {
02815       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02816       HAVE_LOCK_CHECK (connection);
02817       _dbus_connection_do_iteration_unlocked (connection,
02818                                               DBUS_ITERATION_DO_READING |
02819                                               DBUS_ITERATION_DO_WRITING |
02820                                               DBUS_ITERATION_BLOCK,
02821                                               -1);
02822     }
02823 
02824   HAVE_LOCK_CHECK (connection);
02825   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02826   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02827 
02828   HAVE_LOCK_CHECK (connection);
02829   /* Unlocks and calls out to user code */
02830   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02831 
02832   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02833 }
02834 
02866 dbus_bool_t
02867 dbus_connection_read_write_dispatch (DBusConnection *connection,
02868                                      int             timeout_milliseconds)
02869 {
02870   DBusDispatchStatus dstatus;
02871   dbus_bool_t dispatched_disconnected;
02872   
02873   _dbus_return_val_if_fail (connection != NULL, FALSE);
02874   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02875   dstatus = dbus_connection_get_dispatch_status (connection);
02876 
02877   if (dstatus == DBUS_DISPATCH_DATA_REMAINS)
02878     {
02879       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02880       dbus_connection_dispatch (connection);
02881       CONNECTION_LOCK (connection);
02882     }
02883   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02884     {
02885       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02886       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02887       CONNECTION_LOCK (connection);
02888     }
02889   else
02890     {
02891       CONNECTION_LOCK (connection);
02892       if (_dbus_connection_get_is_connected_unlocked (connection))
02893         {
02894           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02895           _dbus_connection_do_iteration_unlocked (connection,
02896                                                   DBUS_ITERATION_DO_READING |
02897                                                   DBUS_ITERATION_DO_WRITING |
02898                                                   DBUS_ITERATION_BLOCK,
02899                                                   timeout_milliseconds);
02900         }
02901     }
02902   
02903   HAVE_LOCK_CHECK (connection);
02904   dispatched_disconnected = connection->n_incoming == 0 &&
02905     connection->disconnect_message_link == NULL;
02906   CONNECTION_UNLOCK (connection);
02907   return !dispatched_disconnected; /* TRUE if we have not processed disconnected */
02908 }
02909 
02929 DBusMessage*
02930 dbus_connection_borrow_message (DBusConnection *connection)
02931 {
02932   DBusDispatchStatus status;
02933   DBusMessage *message;
02934 
02935   _dbus_return_val_if_fail (connection != NULL, NULL);
02936 
02937   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02938   
02939   /* this is called for the side effect that it queues
02940    * up any messages from the transport
02941    */
02942   status = dbus_connection_get_dispatch_status (connection);
02943   if (status != DBUS_DISPATCH_DATA_REMAINS)
02944     return NULL;
02945   
02946   CONNECTION_LOCK (connection);
02947 
02948   _dbus_connection_acquire_dispatch (connection);
02949 
02950   /* While a message is outstanding, the dispatch lock is held */
02951   _dbus_assert (connection->message_borrowed == NULL);
02952 
02953   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
02954   
02955   message = connection->message_borrowed;
02956 
02957   /* Note that we KEEP the dispatch lock until the message is returned */
02958   if (message == NULL)
02959     _dbus_connection_release_dispatch (connection);
02960 
02961   CONNECTION_UNLOCK (connection);
02962   
02963   return message;
02964 }
02965 
02974 void
02975 dbus_connection_return_message (DBusConnection *connection,
02976                                 DBusMessage    *message)
02977 {
02978   _dbus_return_if_fail (connection != NULL);
02979   _dbus_return_if_fail (message != NULL);
02980   _dbus_return_if_fail (message == connection->message_borrowed);
02981   _dbus_return_if_fail (connection->dispatch_acquired);
02982   
02983   CONNECTION_LOCK (connection);
02984   
02985   _dbus_assert (message == connection->message_borrowed);
02986   
02987   connection->message_borrowed = NULL;
02988 
02989   _dbus_connection_release_dispatch (connection);
02990   
02991   CONNECTION_UNLOCK (connection);
02992 }
02993 
03003 void
03004 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03005                                         DBusMessage    *message)
03006 {
03007   DBusMessage *pop_message;
03008 
03009   _dbus_return_if_fail (connection != NULL);
03010   _dbus_return_if_fail (message != NULL);
03011   _dbus_return_if_fail (message == connection->message_borrowed);
03012   _dbus_return_if_fail (connection->dispatch_acquired);
03013   
03014   CONNECTION_LOCK (connection);
03015  
03016   _dbus_assert (message == connection->message_borrowed);
03017 
03018   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03019   _dbus_assert (message == pop_message);
03020   
03021   connection->n_incoming -= 1;
03022  
03023   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03024                  message, connection->n_incoming);
03025  
03026   connection->message_borrowed = NULL;
03027 
03028   _dbus_connection_release_dispatch (connection);
03029   
03030   CONNECTION_UNLOCK (connection);
03031 }
03032 
03033 /* See dbus_connection_pop_message, but requires the caller to own
03034  * the lock before calling. May drop the lock while running.
03035  */
03036 static DBusList*
03037 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03038 {
03039   HAVE_LOCK_CHECK (connection);
03040   
03041   _dbus_assert (connection->message_borrowed == NULL);
03042   
03043   if (connection->n_incoming > 0)
03044     {
03045       DBusList *link;
03046 
03047       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03048       connection->n_incoming -= 1;
03049 
03050       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03051                      link->data,
03052                      dbus_message_get_type (link->data),
03053                      dbus_message_get_path (link->data), 
03054                      dbus_message_get_interface (link->data) ?
03055                      dbus_message_get_interface (link->data) :
03056                      "no interface",
03057                      dbus_message_get_member (link->data) ?
03058                      dbus_message_get_member (link->data) :
03059                      "no member",
03060                      dbus_message_get_signature (link->data),
03061                      connection, connection->n_incoming);
03062 
03063       return link;
03064     }
03065   else
03066     return NULL;
03067 }
03068 
03069 /* See dbus_connection_pop_message, but requires the caller to own
03070  * the lock before calling. May drop the lock while running.
03071  */
03072 static DBusMessage*
03073 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03074 {
03075   DBusList *link;
03076 
03077   HAVE_LOCK_CHECK (connection);
03078   
03079   link = _dbus_connection_pop_message_link_unlocked (connection);
03080 
03081   if (link != NULL)
03082     {
03083       DBusMessage *message;
03084       
03085       message = link->data;
03086       
03087       _dbus_list_free_link (link);
03088       
03089       return message;
03090     }
03091   else
03092     return NULL;
03093 }
03094 
03095 static void
03096 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03097                                                 DBusList       *message_link)
03098 {
03099   HAVE_LOCK_CHECK (connection);
03100   
03101   _dbus_assert (message_link != NULL);
03102   /* You can't borrow a message while a link is outstanding */
03103   _dbus_assert (connection->message_borrowed == NULL);
03104   /* We had to have the dispatch lock across the pop/putback */
03105   _dbus_assert (connection->dispatch_acquired);
03106 
03107   _dbus_list_prepend_link (&connection->incoming_messages,
03108                            message_link);
03109   connection->n_incoming += 1;
03110 
03111   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03112                  message_link->data,
03113                  dbus_message_get_type (message_link->data),
03114                  dbus_message_get_interface (message_link->data) ?
03115                  dbus_message_get_interface (message_link->data) :
03116                  "no interface",
03117                  dbus_message_get_member (message_link->data) ?
03118                  dbus_message_get_member (message_link->data) :
03119                  "no member",
03120                  dbus_message_get_signature (message_link->data),
03121                  connection, connection->n_incoming);
03122 }
03123 
03143 DBusMessage*
03144 dbus_connection_pop_message (DBusConnection *connection)
03145 {
03146   DBusMessage *message;
03147   DBusDispatchStatus status;
03148 
03149   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03150   
03151   /* this is called for the side effect that it queues
03152    * up any messages from the transport
03153    */
03154   status = dbus_connection_get_dispatch_status (connection);
03155   if (status != DBUS_DISPATCH_DATA_REMAINS)
03156     return NULL;
03157   
03158   CONNECTION_LOCK (connection);
03159   _dbus_connection_acquire_dispatch (connection);
03160   HAVE_LOCK_CHECK (connection);
03161   
03162   message = _dbus_connection_pop_message_unlocked (connection);
03163 
03164   _dbus_verbose ("Returning popped message %p\n", message);    
03165 
03166   _dbus_connection_release_dispatch (connection);
03167   CONNECTION_UNLOCK (connection);
03168   
03169   return message;
03170 }
03171 
03179 static void
03180 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03181 {
03182   HAVE_LOCK_CHECK (connection);
03183 
03184   _dbus_connection_ref_unlocked (connection);
03185   CONNECTION_UNLOCK (connection);
03186   
03187   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03188   _dbus_mutex_lock (connection->dispatch_mutex);
03189 
03190   while (connection->dispatch_acquired)
03191     {
03192       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03193       _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03194     }
03195   
03196   _dbus_assert (!connection->dispatch_acquired);
03197 
03198   connection->dispatch_acquired = TRUE;
03199 
03200   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03201   _dbus_mutex_unlock (connection->dispatch_mutex);
03202   
03203   CONNECTION_LOCK (connection);
03204   _dbus_connection_unref_unlocked (connection);
03205 }
03206 
03214 static void
03215 _dbus_connection_release_dispatch (DBusConnection *connection)
03216 {
03217   HAVE_LOCK_CHECK (connection);
03218   
03219   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03220   _dbus_mutex_lock (connection->dispatch_mutex);
03221   
03222   _dbus_assert (connection->dispatch_acquired);
03223 
03224   connection->dispatch_acquired = FALSE;
03225   _dbus_condvar_wake_one (connection->dispatch_cond);
03226 
03227   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03228   _dbus_mutex_unlock (connection->dispatch_mutex);
03229 }
03230 
03231 static void
03232 _dbus_connection_failed_pop (DBusConnection *connection,
03233                              DBusList       *message_link)
03234 {
03235   _dbus_list_prepend_link (&connection->incoming_messages,
03236                            message_link);
03237   connection->n_incoming += 1;
03238 }
03239 
03240 static DBusDispatchStatus
03241 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03242 {
03243   HAVE_LOCK_CHECK (connection);
03244   
03245   if (connection->n_incoming > 0)
03246     return DBUS_DISPATCH_DATA_REMAINS;
03247   else if (!_dbus_transport_queue_messages (connection->transport))
03248     return DBUS_DISPATCH_NEED_MEMORY;
03249   else
03250     {
03251       DBusDispatchStatus status;
03252       dbus_bool_t is_connected;
03253       
03254       status = _dbus_transport_get_dispatch_status (connection->transport);
03255       is_connected = _dbus_transport_get_is_connected (connection->transport);
03256 
03257       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03258                      DISPATCH_STATUS_NAME (status), is_connected);
03259       
03260       if (!is_connected)
03261         {
03262           if (status == DBUS_DISPATCH_COMPLETE &&
03263               connection->disconnect_message_link)
03264             {
03265               _dbus_verbose ("Sending disconnect message from %s\n",
03266                              _DBUS_FUNCTION_NAME);
03267 
03268               connection_forget_shared_unlocked (connection);
03269               
03270               /* We haven't sent the disconnect message already,
03271                * and all real messages have been queued up.
03272                */
03273               _dbus_connection_queue_synthesized_message_link (connection,
03274                                                                connection->disconnect_message_link);
03275               connection->disconnect_message_link = NULL;
03276             }
03277 
03278           /* Dump the outgoing queue, we aren't going to be able to
03279            * send it now, and we'd like accessors like
03280            * dbus_connection_get_outgoing_size() to be accurate.
03281            */
03282           if (connection->n_outgoing > 0)
03283             {
03284               DBusList *link;
03285               
03286               _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03287                              connection->n_outgoing);
03288               
03289               while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03290                 {
03291                   _dbus_connection_message_sent (connection, link->data);
03292                 }
03293             }
03294         }
03295       
03296       if (status != DBUS_DISPATCH_COMPLETE)
03297         return status;
03298       else if (connection->n_incoming > 0)
03299         return DBUS_DISPATCH_DATA_REMAINS;
03300       else
03301         return DBUS_DISPATCH_COMPLETE;
03302     }
03303 }
03304 
03305 static void
03306 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
03307                                                     DBusDispatchStatus new_status)
03308 {
03309   dbus_bool_t changed;
03310   DBusDispatchStatusFunction function;
03311   void *data;
03312 
03313   HAVE_LOCK_CHECK (connection);
03314 
03315   _dbus_connection_ref_unlocked (connection);
03316 
03317   changed = new_status != connection->last_dispatch_status;
03318 
03319   connection->last_dispatch_status = new_status;
03320 
03321   function = connection->dispatch_status_function;
03322   data = connection->dispatch_status_data;
03323 
03324   /* We drop the lock */
03325   CONNECTION_UNLOCK (connection);
03326   
03327   if (changed && function)
03328     {
03329       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03330                      connection, new_status,
03331                      DISPATCH_STATUS_NAME (new_status));
03332       (* function) (connection, new_status, data);      
03333     }
03334   
03335   dbus_connection_unref (connection);
03336 }
03337 
03346 DBusDispatchStatus
03347 dbus_connection_get_dispatch_status (DBusConnection *connection)
03348 {
03349   DBusDispatchStatus status;
03350 
03351   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03352 
03353   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03354   
03355   CONNECTION_LOCK (connection);
03356 
03357   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03358   
03359   CONNECTION_UNLOCK (connection);
03360 
03361   return status;
03362 }
03363 
03367 static DBusHandlerResult
03368 _dbus_connection_peer_filter (DBusConnection *connection,
03369                               DBusMessage    *message)
03370 {
03371   if (dbus_message_is_method_call (message,
03372                                    DBUS_INTERFACE_PEER,
03373                                    "Ping"))
03374     {
03375       DBusMessage *ret;
03376       dbus_bool_t sent;
03377       
03378       ret = dbus_message_new_method_return (message);
03379       if (ret == NULL)
03380         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03381       
03382       sent = dbus_connection_send (connection, ret, NULL);
03383       dbus_message_unref (ret);
03384 
03385       if (!sent)
03386         return DBUS_HANDLER_RESULT_NEED_MEMORY;
03387       
03388       return DBUS_HANDLER_RESULT_HANDLED;
03389     }
03390                                    
03391   
03392   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03393 }
03394 
03401 static DBusHandlerResult
03402 _dbus_connection_run_builtin_filters (DBusConnection *connection,
03403                                       DBusMessage    *message)
03404 {
03405   /* We just run one filter for now but have the option to run more
03406      if the spec calls for it in the future */
03407 
03408   return _dbus_connection_peer_filter (connection, message);
03409 }
03410 
03434 DBusDispatchStatus
03435 dbus_connection_dispatch (DBusConnection *connection)
03436 {
03437   DBusMessage *message;
03438   DBusList *link, *filter_list_copy, *message_link;
03439   DBusHandlerResult result;
03440   DBusPendingCall *pending;
03441   dbus_int32_t reply_serial;
03442   DBusDispatchStatus status;
03443 
03444   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03445 
03446   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03447   
03448   CONNECTION_LOCK (connection);
03449   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03450   if (status != DBUS_DISPATCH_DATA_REMAINS)
03451     {
03452       /* unlocks and calls out to user code */
03453       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03454       return status;
03455     }
03456   
03457   /* We need to ref the connection since the callback could potentially
03458    * drop the last ref to it
03459    */
03460   _dbus_connection_ref_unlocked (connection);
03461 
03462   _dbus_connection_acquire_dispatch (connection);
03463   HAVE_LOCK_CHECK (connection);
03464 
03465   message_link = _dbus_connection_pop_message_link_unlocked (connection);
03466   if (message_link == NULL)
03467     {
03468       /* another thread dispatched our stuff */
03469 
03470       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03471       
03472       _dbus_connection_release_dispatch (connection);
03473 
03474       status = _dbus_connection_get_dispatch_status_unlocked (connection);
03475 
03476       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03477       
03478       dbus_connection_unref (connection);
03479       
03480       return status;
03481     }
03482 
03483   message = message_link->data;
03484 
03485   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03486                  message,
03487                  dbus_message_get_type (message),
03488                  dbus_message_get_interface (message) ?
03489                  dbus_message_get_interface (message) :
03490                  "no interface",
03491                  dbus_message_get_member (message) ?
03492                  dbus_message_get_member (message) :
03493                  "no member",
03494                  dbus_message_get_signature (message));
03495 
03496   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03497   
03498   /* Pending call handling must be first, because if you do
03499    * dbus_connection_send_with_reply_and_block() or
03500    * dbus_pending_call_block() then no handlers/filters will be run on
03501    * the reply. We want consistent semantics in the case where we
03502    * dbus_connection_dispatch() the reply.
03503    */
03504   
03505   reply_serial = dbus_message_get_reply_serial (message);
03506   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03507                                          reply_serial);
03508   if (pending)
03509     {
03510       _dbus_verbose ("Dispatching a pending reply\n");
03511       _dbus_pending_call_complete_and_unlock (pending, message);
03512       pending = NULL; /* it's probably unref'd */
03513       
03514       CONNECTION_LOCK (connection);
03515       _dbus_verbose ("pending call completed in dispatch\n");
03516       result = DBUS_HANDLER_RESULT_HANDLED;
03517       goto out;
03518     }
03519  
03520   result = _dbus_connection_run_builtin_filters (connection, message);
03521   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03522     goto out;
03523  
03524   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03525     {
03526       _dbus_connection_release_dispatch (connection);
03527       HAVE_LOCK_CHECK (connection);
03528       
03529       _dbus_connection_failed_pop (connection, message_link);
03530 
03531       /* unlocks and calls user code */
03532       _dbus_connection_update_dispatch_status_and_unlock (connection,
03533                                                           DBUS_DISPATCH_NEED_MEMORY);
03534 
03535       if (pending)
03536         dbus_pending_call_unref (pending);
03537       dbus_connection_unref (connection);
03538       
03539       return DBUS_DISPATCH_NEED_MEMORY;
03540     }
03541   
03542   _dbus_list_foreach (&filter_list_copy,
03543                       (DBusForeachFunction)_dbus_message_filter_ref,
03544                       NULL);
03545 
03546   /* We're still protected from dispatch() reentrancy here
03547    * since we acquired the dispatcher
03548    */
03549   CONNECTION_UNLOCK (connection);
03550   
03551   link = _dbus_list_get_first_link (&filter_list_copy);
03552   while (link != NULL)
03553     {
03554       DBusMessageFilter *filter = link->data;
03555       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03556 
03557       _dbus_verbose ("  running filter on message %p\n", message);
03558       result = (* filter->function) (connection, message, filter->user_data);
03559 
03560       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03561         break;
03562 
03563       link = next;
03564     }
03565 
03566   _dbus_list_foreach (&filter_list_copy,
03567                       (DBusForeachFunction)_dbus_message_filter_unref,
03568                       NULL);
03569   _dbus_list_clear (&filter_list_copy);
03570   
03571   CONNECTION_LOCK (connection);
03572 
03573   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03574     {
03575       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03576       goto out;
03577     }
03578   else if (result == DBUS_HANDLER_RESULT_HANDLED)
03579     {
03580       _dbus_verbose ("filter handled message in dispatch\n");
03581       goto out;
03582     }
03583 
03584   /* We're still protected from dispatch() reentrancy here
03585    * since we acquired the dispatcher
03586    */
03587   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
03588                  message,
03589                  dbus_message_get_type (message),
03590                  dbus_message_get_interface (message) ?
03591                  dbus_message_get_interface (message) :
03592                  "no interface",
03593                  dbus_message_get_member (message) ?
03594                  dbus_message_get_member (message) :
03595                  "no member",
03596                  dbus_message_get_signature (message));
03597 
03598   HAVE_LOCK_CHECK (connection);
03599   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03600                                                   message);
03601   
03602   CONNECTION_LOCK (connection);
03603 
03604   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03605     {
03606       _dbus_verbose ("object tree handled message in dispatch\n");
03607       goto out;
03608     }
03609 
03610   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03611     {
03612       DBusMessage *reply;
03613       DBusString str;
03614       DBusPreallocatedSend *preallocated;
03615 
03616       _dbus_verbose ("  sending error %s\n",
03617                      DBUS_ERROR_UNKNOWN_METHOD);
03618       
03619       if (!_dbus_string_init (&str))
03620         {
03621           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03622           _dbus_verbose ("no memory for error string in dispatch\n");
03623           goto out;
03624         }
03625               
03626       if (!_dbus_string_append_printf (&str,
03627                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03628                                        dbus_message_get_member (message),
03629                                        dbus_message_get_signature (message),
03630                                        dbus_message_get_interface (message)))
03631         {
03632           _dbus_string_free (&str);
03633           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03634           _dbus_verbose ("no memory for error string in dispatch\n");
03635           goto out;
03636         }
03637       
03638       reply = dbus_message_new_error (message,
03639                                       DBUS_ERROR_UNKNOWN_METHOD,
03640                                       _dbus_string_get_const_data (&str));
03641       _dbus_string_free (&str);
03642 
03643       if (reply == NULL)
03644         {
03645           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03646           _dbus_verbose ("no memory for error reply in dispatch\n");
03647           goto out;
03648         }
03649       
03650       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03651 
03652       if (preallocated == NULL)
03653         {
03654           dbus_message_unref (reply);
03655           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03656           _dbus_verbose ("no memory for error send in dispatch\n");
03657           goto out;
03658         }
03659 
03660       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03661                                                              reply, NULL);
03662 
03663       dbus_message_unref (reply);
03664       
03665       result = DBUS_HANDLER_RESULT_HANDLED;
03666     }
03667   
03668   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03669                  dbus_message_get_type (message),
03670                  dbus_message_get_interface (message) ?
03671                  dbus_message_get_interface (message) :
03672                  "no interface",
03673                  dbus_message_get_member (message) ?
03674                  dbus_message_get_member (message) :
03675                  "no member",
03676                  dbus_message_get_signature (message),
03677                  connection);
03678   
03679  out:
03680   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03681     {
03682       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03683       
03684       /* Put message back, and we'll start over.
03685        * Yes this means handlers must be idempotent if they
03686        * don't return HANDLED; c'est la vie.
03687        */
03688       _dbus_connection_putback_message_link_unlocked (connection,
03689                                                       message_link);
03690     }
03691   else
03692     {
03693       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03694       
03695       if (connection->exit_on_disconnect &&
03696           dbus_message_is_signal (message,
03697                                   DBUS_INTERFACE_LOCAL,
03698                                   "Disconnected"))
03699         {
03700           _dbus_verbose ("Exiting on Disconnected signal\n");
03701           CONNECTION_UNLOCK (connection);
03702           _dbus_exit (1);
03703           _dbus_assert_not_reached ("Call to exit() returned");
03704         }
03705       
03706       _dbus_list_free_link (message_link);
03707       dbus_message_unref (message); /* don't want the message to count in max message limits
03708                                      * in computing dispatch status below
03709                                      */
03710     }
03711   
03712   _dbus_connection_release_dispatch (connection);
03713   HAVE_LOCK_CHECK (connection);
03714 
03715   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03716   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03717 
03718   /* unlocks and calls user code */
03719   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03720   
03721   dbus_connection_unref (connection);
03722   
03723   return status;
03724 }
03725 
03784 dbus_bool_t
03785 dbus_connection_set_watch_functions (DBusConnection              *connection,
03786                                      DBusAddWatchFunction         add_function,
03787                                      DBusRemoveWatchFunction      remove_function,
03788                                      DBusWatchToggledFunction     toggled_function,
03789                                      void                        *data,
03790                                      DBusFreeFunction             free_data_function)
03791 {
03792   dbus_bool_t retval;
03793   DBusWatchList *watches;
03794 
03795   _dbus_return_val_if_fail (connection != NULL, FALSE);
03796   
03797   CONNECTION_LOCK (connection);
03798 
03799 #ifndef DBUS_DISABLE_CHECKS
03800   if (connection->watches == NULL)
03801     {
03802       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03803                   _DBUS_FUNCTION_NAME);
03804       return FALSE;
03805     }
03806 #endif
03807   
03808   /* ref connection for slightly better reentrancy */
03809   _dbus_connection_ref_unlocked (connection);
03810 
03811   /* This can call back into user code, and we need to drop the
03812    * connection lock when it does. This is kind of a lame
03813    * way to do it.
03814    */
03815   watches = connection->watches;
03816   connection->watches = NULL;
03817   CONNECTION_UNLOCK (connection);
03818 
03819   retval = _dbus_watch_list_set_functions (watches,
03820                                            add_function, remove_function,
03821                                            toggled_function,
03822                                            data, free_data_function);
03823   CONNECTION_LOCK (connection);
03824   connection->watches = watches;
03825   
03826   CONNECTION_UNLOCK (connection);
03827   /* drop our paranoid refcount */
03828   dbus_connection_unref (connection);
03829   
03830   return retval;
03831 }
03832 
03866 dbus_bool_t
03867 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
03868                                          DBusAddTimeoutFunction     add_function,
03869                                          DBusRemoveTimeoutFunction  remove_function,
03870                                          DBusTimeoutToggledFunction toggled_function,
03871                                          void                      *data,
03872                                          DBusFreeFunction           free_data_function)
03873 {
03874   dbus_bool_t retval;
03875   DBusTimeoutList *timeouts;
03876 
03877   _dbus_return_val_if_fail (connection != NULL, FALSE);
03878   
03879   CONNECTION_LOCK (connection);
03880 
03881 #ifndef DBUS_DISABLE_CHECKS
03882   if (connection->timeouts == NULL)
03883     {
03884       _dbus_warn ("Re-entrant call to %s is not allowed\n",
03885                   _DBUS_FUNCTION_NAME);
03886       return FALSE;
03887     }
03888 #endif
03889   
03890   /* ref connection for slightly better reentrancy */
03891   _dbus_connection_ref_unlocked (connection);
03892 
03893   timeouts = connection->timeouts;
03894   connection->timeouts = NULL;
03895   CONNECTION_UNLOCK (connection);
03896   
03897   retval = _dbus_timeout_list_set_functions (timeouts,
03898                                              add_function, remove_function,
03899                                              toggled_function,
03900                                              data, free_data_function);
03901   CONNECTION_LOCK (connection);
03902   connection->timeouts = timeouts;
03903   
03904   CONNECTION_UNLOCK (connection);
03905   /* drop our paranoid refcount */
03906   dbus_connection_unref (connection);
03907 
03908   return retval;
03909 }
03910 
03925 void
03926 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
03927                                           DBusWakeupMainFunction     wakeup_main_function,
03928                                           void                      *data,
03929                                           DBusFreeFunction           free_data_function)
03930 {
03931   void *old_data;
03932   DBusFreeFunction old_free_data;
03933 
03934   _dbus_return_if_fail (connection != NULL);
03935   
03936   CONNECTION_LOCK (connection);
03937   old_data = connection->wakeup_main_data;
03938   old_free_data = connection->free_wakeup_main_data;
03939 
03940   connection->wakeup_main_function = wakeup_main_function;
03941   connection->wakeup_main_data = data;
03942   connection->free_wakeup_main_data = free_data_function;
03943   
03944   CONNECTION_UNLOCK (connection);
03945 
03946   /* Callback outside the lock */
03947   if (old_free_data)
03948     (*old_free_data) (old_data);
03949 }
03950 
03967 void
03968 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
03969                                               DBusDispatchStatusFunction  function,
03970                                               void                       *data,
03971                                               DBusFreeFunction            free_data_function)
03972 {
03973   void *old_data;
03974   DBusFreeFunction old_free_data;
03975 
03976   _dbus_return_if_fail (connection != NULL);
03977   
03978   CONNECTION_LOCK (connection);
03979   old_data = connection->dispatch_status_data;
03980   old_free_data = connection->free_dispatch_status_data;
03981 
03982   connection->dispatch_status_function = function;
03983   connection->dispatch_status_data = data;
03984   connection->free_dispatch_status_data = free_data_function;
03985   
03986   CONNECTION_UNLOCK (connection);
03987 
03988   /* Callback outside the lock */
03989   if (old_free_data)
03990     (*old_free_data) (old_data);
03991 }
03992 
04005 dbus_bool_t
04006 dbus_connection_get_unix_fd (DBusConnection *connection,
04007                              int            *fd)
04008 {
04009   dbus_bool_t retval;
04010 
04011   _dbus_return_val_if_fail (connection != NULL, FALSE);
04012   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04013   
04014   CONNECTION_LOCK (connection);
04015   
04016   retval = _dbus_transport_get_unix_fd (connection->transport,
04017                                         fd);
04018 
04019   CONNECTION_UNLOCK (connection);
04020 
04021   return retval;
04022 }
04023 
04035 dbus_bool_t
04036 dbus_connection_get_unix_user (DBusConnection *connection,
04037                                unsigned long  *uid)
04038 {
04039   dbus_bool_t result;
04040 
04041   _dbus_return_val_if_fail (connection != NULL, FALSE);
04042   _dbus_return_val_if_fail (uid != NULL, FALSE);
04043   
04044   CONNECTION_LOCK (connection);
04045 
04046   if (!_dbus_transport_get_is_authenticated (connection->transport))
04047     result = FALSE;
04048   else
04049     result = _dbus_transport_get_unix_user (connection->transport,
04050                                             uid);
04051   CONNECTION_UNLOCK (connection);
04052 
04053   return result;
04054 }
04055 
04066 dbus_bool_t
04067 dbus_connection_get_unix_process_id (DBusConnection *connection,
04068                                      unsigned long  *pid)
04069 {
04070   dbus_bool_t result;
04071 
04072   _dbus_return_val_if_fail (connection != NULL, FALSE);
04073   _dbus_return_val_if_fail (pid != NULL, FALSE);
04074   
04075   CONNECTION_LOCK (connection);
04076 
04077   if (!_dbus_transport_get_is_authenticated (connection->transport))
04078     result = FALSE;
04079   else
04080     result = _dbus_transport_get_unix_process_id (connection->transport,
04081                                                   pid);
04082   CONNECTION_UNLOCK (connection);
04083 
04084   return result;
04085 }
04086 
04103 void
04104 dbus_connection_set_unix_user_function (DBusConnection             *connection,
04105                                         DBusAllowUnixUserFunction   function,
04106                                         void                       *data,
04107                                         DBusFreeFunction            free_data_function)
04108 {
04109   void *old_data = NULL;
04110   DBusFreeFunction old_free_function = NULL;
04111 
04112   _dbus_return_if_fail (connection != NULL);
04113   
04114   CONNECTION_LOCK (connection);
04115   _dbus_transport_set_unix_user_function (connection->transport,
04116                                           function, data, free_data_function,
04117                                           &old_data, &old_free_function);
04118   CONNECTION_UNLOCK (connection);
04119 
04120   if (old_free_function != NULL)
04121     (* old_free_function) (old_data);    
04122 }
04123 
04145 dbus_bool_t
04146 dbus_connection_add_filter (DBusConnection            *connection,
04147                             DBusHandleMessageFunction  function,
04148                             void                      *user_data,
04149                             DBusFreeFunction           free_data_function)
04150 {
04151   DBusMessageFilter *filter;
04152   
04153   _dbus_return_val_if_fail (connection != NULL, FALSE);
04154   _dbus_return_val_if_fail (function != NULL, FALSE);
04155 
04156   filter = dbus_new0 (DBusMessageFilter, 1);
04157   if (filter == NULL)
04158     return FALSE;
04159 
04160   filter->refcount.value = 1;
04161   
04162   CONNECTION_LOCK (connection);
04163 
04164   if (!_dbus_list_append (&connection->filter_list,
04165                           filter))
04166     {
04167       _dbus_message_filter_unref (filter);
04168       CONNECTION_UNLOCK (connection);
04169       return FALSE;
04170     }
04171 
04172   /* Fill in filter after all memory allocated,
04173    * so we don't run the free_user_data_function
04174    * if the add_filter() fails
04175    */
04176   
04177   filter->function = function;
04178   filter->user_data = user_data;
04179   filter->free_user_data_function = free_data_function;
04180         
04181   CONNECTION_UNLOCK (connection);
04182   return TRUE;
04183 }
04184 
04197 void
04198 dbus_connection_remove_filter (DBusConnection            *connection,
04199                                DBusHandleMessageFunction  function,
04200                                void                      *user_data)
04201 {
04202   DBusList *link;
04203   DBusMessageFilter *filter;
04204   
04205   _dbus_return_if_fail (connection != NULL);
04206   _dbus_return_if_fail (function != NULL);
04207   
04208   CONNECTION_LOCK (connection);
04209 
04210   filter = NULL;
04211   
04212   link = _dbus_list_get_last_link (&connection->filter_list);
04213   while (link != NULL)
04214     {
04215       filter = link->data;
04216 
04217       if (filter->function == function &&
04218           filter->user_data == user_data)
04219         {
04220           _dbus_list_remove_link (&connection->filter_list, link);
04221           filter->function = NULL;
04222           
04223           break;
04224         }
04225         
04226       link = _dbus_list_get_prev_link (&connection->filter_list, link);
04227     }
04228   
04229   CONNECTION_UNLOCK (connection);
04230 
04231 #ifndef DBUS_DISABLE_CHECKS
04232   if (filter == NULL)
04233     {
04234       _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04235                   function, user_data);
04236       return;
04237     }
04238 #endif
04239   
04240   /* Call application code */
04241   if (filter->free_user_data_function)
04242     (* filter->free_user_data_function) (filter->user_data);
04243 
04244   filter->free_user_data_function = NULL;
04245   filter->user_data = NULL;
04246   
04247   _dbus_message_filter_unref (filter);
04248 }
04249 
04261 dbus_bool_t
04262 dbus_connection_register_object_path (DBusConnection              *connection,
04263                                       const char                  *path,
04264                                       const DBusObjectPathVTable  *vtable,
04265                                       void                        *user_data)
04266 {
04267   char **decomposed_path;
04268   dbus_bool_t retval;
04269   
04270   _dbus_return_val_if_fail (connection != NULL, FALSE);
04271   _dbus_return_val_if_fail (path != NULL, FALSE);
04272   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04273   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04274 
04275   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04276     return FALSE;
04277 
04278   CONNECTION_LOCK (connection);
04279 
04280   retval = _dbus_object_tree_register (connection->objects,
04281                                        FALSE,
04282                                        (const char **) decomposed_path, vtable,
04283                                        user_data);
04284 
04285   CONNECTION_UNLOCK (connection);
04286 
04287   dbus_free_string_array (decomposed_path);
04288 
04289   return retval;
04290 }
04291 
04304 dbus_bool_t
04305 dbus_connection_register_fallback (DBusConnection              *connection,
04306                                    const char                  *path,
04307                                    const DBusObjectPathVTable  *vtable,
04308                                    void                        *user_data)
04309 {
04310   char **decomposed_path;
04311   dbus_bool_t retval;
04312   
04313   _dbus_return_val_if_fail (connection != NULL, FALSE);
04314   _dbus_return_val_if_fail (path != NULL, FALSE);
04315   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04316   _dbus_return_val_if_fail (vtable != NULL, FALSE);
04317 
04318   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04319     return FALSE;
04320 
04321   CONNECTION_LOCK (connection);
04322 
04323   retval = _dbus_object_tree_register (connection->objects,
04324                                        TRUE,
04325                                        (const char **) decomposed_path, vtable,
04326                                        user_data);
04327 
04328   CONNECTION_UNLOCK (connection);
04329 
04330   dbus_free_string_array (decomposed_path);
04331 
04332   return retval;
04333 }
04334 
04344 dbus_bool_t
04345 dbus_connection_unregister_object_path (DBusConnection              *connection,
04346                                         const char                  *path)
04347 {
04348   char **decomposed_path;
04349 
04350   _dbus_return_val_if_fail (connection != NULL, FALSE);
04351   _dbus_return_val_if_fail (path != NULL, FALSE);
04352   _dbus_return_val_if_fail (path[0] == '/', FALSE);
04353 
04354   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04355       return FALSE;
04356 
04357   CONNECTION_LOCK (connection);
04358 
04359   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04360 
04361   dbus_free_string_array (decomposed_path);
04362 
04363   return TRUE;
04364 }
04365 
04376 dbus_bool_t
04377 dbus_connection_get_object_path_data (DBusConnection *connection,
04378                                       const char     *path,
04379                                       void          **data_p)
04380 {
04381   char **decomposed_path;
04382 
04383   _dbus_return_val_if_fail (connection != NULL, FALSE);
04384   _dbus_return_val_if_fail (path != NULL, FALSE);
04385   _dbus_return_val_if_fail (data_p != NULL, FALSE);
04386 
04387   *data_p = NULL;
04388   
04389   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04390     return FALSE;
04391   
04392   CONNECTION_LOCK (connection);
04393 
04394   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04395 
04396   CONNECTION_UNLOCK (connection);
04397 
04398   dbus_free_string_array (decomposed_path);
04399 
04400   return TRUE;
04401 }
04402 
04413 dbus_bool_t
04414 dbus_connection_list_registered (DBusConnection              *connection,
04415                                  const char                  *parent_path,
04416                                  char                      ***child_entries)
04417 {
04418   char **decomposed_path;
04419   dbus_bool_t retval;
04420   _dbus_return_val_if_fail (connection != NULL, FALSE);
04421   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04422   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04423   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04424 
04425   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04426     return FALSE;
04427 
04428   CONNECTION_LOCK (connection);
04429 
04430   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04431                                                          (const char **) decomposed_path,
04432                                                          child_entries);
04433   dbus_free_string_array (decomposed_path);
04434 
04435   return retval;
04436 }
04437 
04438 static DBusDataSlotAllocator slot_allocator;
04439 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04440 
04455 dbus_bool_t
04456 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04457 {
04458   return _dbus_data_slot_allocator_alloc (&slot_allocator,
04459                                           _DBUS_LOCK_NAME (connection_slots),
04460                                           slot_p);
04461 }
04462 
04474 void
04475 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04476 {
04477   _dbus_return_if_fail (*slot_p >= 0);
04478   
04479   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04480 }
04481 
04495 dbus_bool_t
04496 dbus_connection_set_data (DBusConnection   *connection,
04497                           dbus_int32_t      slot,
04498                           void             *data,
04499                           DBusFreeFunction  free_data_func)
04500 {
04501   DBusFreeFunction old_free_func;
04502   void *old_data;
04503   dbus_bool_t retval;
04504 
04505   _dbus_return_val_if_fail (connection != NULL, FALSE);
04506   _dbus_return_val_if_fail (slot >= 0, FALSE);
04507   
04508   CONNECTION_LOCK (connection);
04509 
04510   retval = _dbus_data_slot_list_set (&slot_allocator,
04511                                      &connection->slot_list,
04512                                      slot, data, free_data_func,
04513                                      &old_free_func, &old_data);
04514   
04515   CONNECTION_UNLOCK (connection);
04516 
04517   if (retval)
04518     {
04519       /* Do the actual free outside the connection lock */
04520       if (old_free_func)
04521         (* old_free_func) (old_data);
04522     }
04523 
04524   return retval;
04525 }
04526 
04535 void*
04536 dbus_connection_get_data (DBusConnection   *connection,
04537                           dbus_int32_t      slot)
04538 {
04539   void *res;
04540 
04541   _dbus_return_val_if_fail (connection != NULL, NULL);
04542   
04543   CONNECTION_LOCK (connection);
04544 
04545   res = _dbus_data_slot_list_get (&slot_allocator,
04546                                   &connection->slot_list,
04547                                   slot);
04548   
04549   CONNECTION_UNLOCK (connection);
04550 
04551   return res;
04552 }
04553 
04560 void
04561 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04562 {  
04563   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04564 }
04565 
04574 void
04575 dbus_connection_set_max_message_size (DBusConnection *connection,
04576                                       long            size)
04577 {
04578   _dbus_return_if_fail (connection != NULL);
04579   
04580   CONNECTION_LOCK (connection);
04581   _dbus_transport_set_max_message_size (connection->transport,
04582                                         size);
04583   CONNECTION_UNLOCK (connection);
04584 }
04585 
04592 long
04593 dbus_connection_get_max_message_size (DBusConnection *connection)
04594 {
04595   long res;
04596 
04597   _dbus_return_val_if_fail (connection != NULL, 0);
04598   
04599   CONNECTION_LOCK (connection);
04600   res = _dbus_transport_get_max_message_size (connection->transport);
04601   CONNECTION_UNLOCK (connection);
04602   return res;
04603 }
04604 
04630 void
04631 dbus_connection_set_max_received_size (DBusConnection *connection,
04632                                        long            size)
04633 {
04634   _dbus_return_if_fail (connection != NULL);
04635   
04636   CONNECTION_LOCK (connection);
04637   _dbus_transport_set_max_received_size (connection->transport,
04638                                          size);
04639   CONNECTION_UNLOCK (connection);
04640 }
04641 
04648 long
04649 dbus_connection_get_max_received_size (DBusConnection *connection)
04650 {
04651   long res;
04652 
04653   _dbus_return_val_if_fail (connection != NULL, 0);
04654   
04655   CONNECTION_LOCK (connection);
04656   res = _dbus_transport_get_max_received_size (connection->transport);
04657   CONNECTION_UNLOCK (connection);
04658   return res;
04659 }
04660 
04671 long
04672 dbus_connection_get_outgoing_size (DBusConnection *connection)
04673 {
04674   long res;
04675 
04676   _dbus_return_val_if_fail (connection != NULL, 0);
04677   
04678   CONNECTION_LOCK (connection);
04679   res = _dbus_counter_get_value (connection->outgoing_counter);
04680   CONNECTION_UNLOCK (connection);
04681   return res;
04682 }
04683 

Generated on Tue Sep 13 01:28:06 2005 for D-BUS by  doxygen 1.4.4