dbus-connection.c

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

Generated on Tue Jul 7 15:13:58 2009 for D-BUS by  doxygen 1.4.6