D-Bus 1.2.24

dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-connection.c DBusConnection object
00003  *
00004  * Copyright (C) 2002-2006  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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-pending-call-internal.h"
00033 #include "dbus-list.h"
00034 #include "dbus-hash.h"
00035 #include "dbus-message-internal.h"
00036 #include "dbus-threads.h"
00037 #include "dbus-protocol.h"
00038 #include "dbus-dataslot.h"
00039 #include "dbus-string.h"
00040 #include "dbus-pending-call.h"
00041 #include "dbus-object-tree.h"
00042 #include "dbus-threads-internal.h"
00043 #include "dbus-bus.h"
00044 
00045 #ifdef DBUS_DISABLE_CHECKS
00046 #define TOOK_LOCK_CHECK(connection)
00047 #define RELEASING_LOCK_CHECK(connection)
00048 #define HAVE_LOCK_CHECK(connection)
00049 #else
00050 #define TOOK_LOCK_CHECK(connection) do {                \
00051     _dbus_assert (!(connection)->have_connection_lock); \
00052     (connection)->have_connection_lock = TRUE;          \
00053   } while (0)
00054 #define RELEASING_LOCK_CHECK(connection) do {            \
00055     _dbus_assert ((connection)->have_connection_lock);   \
00056     (connection)->have_connection_lock = FALSE;          \
00057   } while (0)
00058 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00059 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00060 #endif
00061 
00062 #define TRACE_LOCKS 1
00063 
00064 #define CONNECTION_LOCK(connection)   do {                                      \
00065     if (TRACE_LOCKS) { _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME); }   \
00066     _dbus_mutex_lock ((connection)->mutex);                                      \
00067     TOOK_LOCK_CHECK (connection);                                               \
00068   } while (0)
00069 
00070 #define CONNECTION_UNLOCK(connection) do {                                              \
00071     if (TRACE_LOCKS) { _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);  }        \
00072     RELEASING_LOCK_CHECK (connection);                                                  \
00073     _dbus_mutex_unlock ((connection)->mutex);                                            \
00074   } while (0)
00075 
00076 #define DISPATCH_STATUS_NAME(s)                                            \
00077                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00078                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00079                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00080                       "???")
00081 
00202 typedef struct DBusMessageFilter DBusMessageFilter;
00203 
00207 struct DBusMessageFilter
00208 {
00209   DBusAtomic refcount; 
00210   DBusHandleMessageFunction function; 
00211   void *user_data; 
00212   DBusFreeFunction free_user_data_function; 
00213 };
00214 
00215 
00219 struct DBusPreallocatedSend
00220 {
00221   DBusConnection *connection; 
00222   DBusList *queue_link;       
00223   DBusList *counter_link;     
00224 };
00225 
00226 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00227 
00231 struct DBusConnection
00232 {
00233   DBusAtomic refcount; 
00235   DBusMutex *mutex; 
00237   DBusMutex *dispatch_mutex;     
00238   DBusCondVar *dispatch_cond;    
00239   DBusMutex *io_path_mutex;      
00240   DBusCondVar *io_path_cond;     
00242   DBusList *outgoing_messages; 
00243   DBusList *incoming_messages; 
00245   DBusMessage *message_borrowed; 
00249   int n_outgoing;              
00250   int n_incoming;              
00252   DBusCounter *outgoing_counter; 
00254   DBusTransport *transport;    
00255   DBusWatchList *watches;      
00256   DBusTimeoutList *timeouts;   
00258   DBusList *filter_list;        
00260   DBusDataSlotList slot_list;   
00262   DBusHashTable *pending_replies;  
00264   dbus_uint32_t client_serial;       
00265   DBusList *disconnect_message_link; 
00267   DBusWakeupMainFunction wakeup_main_function; 
00268   void *wakeup_main_data; 
00269   DBusFreeFunction free_wakeup_main_data; 
00271   DBusDispatchStatusFunction dispatch_status_function; 
00272   void *dispatch_status_data; 
00273   DBusFreeFunction free_dispatch_status_data; 
00275   DBusDispatchStatus last_dispatch_status; 
00277   DBusList *link_cache; 
00280   DBusObjectTree *objects; 
00282   char *server_guid; 
00284   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00285    * from connection->mutex and all bitfields in a word have to be read/written together.
00286    * So you can't have a different lock for different bitfields in the same word.
00287    */
00288   dbus_bool_t dispatch_acquired; 
00289   dbus_bool_t io_path_acquired;  
00291   unsigned int shareable : 1; 
00293   unsigned int exit_on_disconnect : 1; 
00295   unsigned int route_peer_messages : 1; 
00297   unsigned int disconnected_message_arrived : 1;   
00301   unsigned int disconnected_message_processed : 1; 
00305 #ifndef DBUS_DISABLE_CHECKS
00306   unsigned int have_connection_lock : 1; 
00307 #endif
00308   
00309 #ifndef DBUS_DISABLE_CHECKS
00310   int generation; 
00311 #endif 
00312 };
00313 
00314 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00315 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00316                                                                               DBusDispatchStatus  new_status);
00317 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00318 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00319 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00320 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00321 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00322 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00323 
00324 static DBusMessageFilter *
00325 _dbus_message_filter_ref (DBusMessageFilter *filter)
00326 {
00327   _dbus_assert (filter->refcount.value > 0);
00328   _dbus_atomic_inc (&filter->refcount);
00329 
00330   return filter;
00331 }
00332 
00333 static void
00334 _dbus_message_filter_unref (DBusMessageFilter *filter)
00335 {
00336   _dbus_assert (filter->refcount.value > 0);
00337 
00338   if (_dbus_atomic_dec (&filter->refcount) == 1)
00339     {
00340       if (filter->free_user_data_function)
00341         (* filter->free_user_data_function) (filter->user_data);
00342       
00343       dbus_free (filter);
00344     }
00345 }
00346 
00352 void
00353 _dbus_connection_lock (DBusConnection *connection)
00354 {
00355   CONNECTION_LOCK (connection);
00356 }
00357 
00363 void
00364 _dbus_connection_unlock (DBusConnection *connection)
00365 {
00366   CONNECTION_UNLOCK (connection);
00367 }
00368 
00376 static void
00377 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00378 {
00379   if (connection->wakeup_main_function)
00380     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00381 }
00382 
00383 #ifdef DBUS_BUILD_TESTS
00384 /* For now this function isn't used */
00394 dbus_bool_t
00395 _dbus_connection_queue_received_message (DBusConnection *connection,
00396                                          DBusMessage    *message)
00397 {
00398   DBusList *link;
00399 
00400   link = _dbus_list_alloc_link (message);
00401   if (link == NULL)
00402     return FALSE;
00403 
00404   dbus_message_ref (message);
00405   _dbus_connection_queue_received_message_link (connection, link);
00406 
00407   return TRUE;
00408 }
00409 
00422 void 
00423 _dbus_connection_test_get_locks (DBusConnection *connection,
00424                                  DBusMutex     **mutex_loc,
00425                                  DBusMutex     **dispatch_mutex_loc,
00426                                  DBusMutex     **io_path_mutex_loc,
00427                                  DBusCondVar   **dispatch_cond_loc,
00428                                  DBusCondVar   **io_path_cond_loc)
00429 {
00430   *mutex_loc = connection->mutex;
00431   *dispatch_mutex_loc = connection->dispatch_mutex;
00432   *io_path_mutex_loc = connection->io_path_mutex; 
00433   *dispatch_cond_loc = connection->dispatch_cond;
00434   *io_path_cond_loc = connection->io_path_cond;
00435 }
00436 #endif
00437 
00446 void
00447 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00448                                               DBusList        *link)
00449 {
00450   DBusPendingCall *pending;
00451   dbus_uint32_t reply_serial;
00452   DBusMessage *message;
00453   
00454   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00455   
00456   _dbus_list_append_link (&connection->incoming_messages,
00457                           link);
00458   message = link->data;
00459 
00460   /* If this is a reply we're waiting on, remove timeout for it */
00461   reply_serial = dbus_message_get_reply_serial (message);
00462   if (reply_serial != 0)
00463     {
00464       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00465                                              reply_serial);
00466       if (pending != NULL)
00467         {
00468           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00469             _dbus_connection_remove_timeout_unlocked (connection,
00470                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00471 
00472           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00473         }
00474     }
00475   
00476   
00477 
00478   connection->n_incoming += 1;
00479 
00480   _dbus_connection_wakeup_mainloop (connection);
00481   
00482   _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00483                  message,
00484                  dbus_message_get_type (message),
00485                  dbus_message_get_path (message) ?
00486                  dbus_message_get_path (message) :
00487                  "no path",
00488                  dbus_message_get_interface (message) ?
00489                  dbus_message_get_interface (message) :
00490                  "no interface",
00491                  dbus_message_get_member (message) ?
00492                  dbus_message_get_member (message) :
00493                  "no member",
00494                  dbus_message_get_signature (message),
00495                  dbus_message_get_reply_serial (message),
00496                  connection,
00497                  connection->n_incoming);}
00498 
00507 void
00508 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00509                                                  DBusList *link)
00510 {
00511   HAVE_LOCK_CHECK (connection);
00512   
00513   _dbus_list_append_link (&connection->incoming_messages, link);
00514 
00515   connection->n_incoming += 1;
00516 
00517   _dbus_connection_wakeup_mainloop (connection);
00518   
00519   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00520                  link->data, connection, connection->n_incoming);
00521 }
00522 
00523 
00531 dbus_bool_t
00532 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00533 {
00534   HAVE_LOCK_CHECK (connection);
00535   return connection->outgoing_messages != NULL;
00536 }
00537 
00547 dbus_bool_t
00548 dbus_connection_has_messages_to_send (DBusConnection *connection)
00549 {
00550   dbus_bool_t v;
00551   
00552   _dbus_return_val_if_fail (connection != NULL, FALSE);
00553 
00554   CONNECTION_LOCK (connection);
00555   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00556   CONNECTION_UNLOCK (connection);
00557 
00558   return v;
00559 }
00560 
00568 DBusMessage*
00569 _dbus_connection_get_message_to_send (DBusConnection *connection)
00570 {
00571   HAVE_LOCK_CHECK (connection);
00572   
00573   return _dbus_list_get_last (&connection->outgoing_messages);
00574 }
00575 
00584 void
00585 _dbus_connection_message_sent (DBusConnection *connection,
00586                                DBusMessage    *message)
00587 {
00588   DBusList *link;
00589 
00590   HAVE_LOCK_CHECK (connection);
00591   
00592   /* This can be called before we even complete authentication, since
00593    * it's called on disconnect to clean up the outgoing queue.
00594    * It's also called as we successfully send each message.
00595    */
00596   
00597   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00598   _dbus_assert (link != NULL);
00599   _dbus_assert (link->data == message);
00600 
00601   /* Save this link in the link cache */
00602   _dbus_list_unlink (&connection->outgoing_messages,
00603                      link);
00604   _dbus_list_prepend_link (&connection->link_cache, link);
00605   
00606   connection->n_outgoing -= 1;
00607 
00608   _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00609                  message,
00610                  dbus_message_get_type (message),
00611                  dbus_message_get_path (message) ?
00612                  dbus_message_get_path (message) :
00613                  "no path",
00614                  dbus_message_get_interface (message) ?
00615                  dbus_message_get_interface (message) :
00616                  "no interface",
00617                  dbus_message_get_member (message) ?
00618                  dbus_message_get_member (message) :
00619                  "no member",
00620                  dbus_message_get_signature (message),
00621                  connection, connection->n_outgoing);
00622 
00623   /* Save this link in the link cache also */
00624   _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00625                                      &link);
00626   _dbus_list_prepend_link (&connection->link_cache, link);
00627   
00628   dbus_message_unref (message);
00629 }
00630 
00632 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00633                                                   DBusWatch     *watch);
00635 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00636                                                   DBusWatch     *watch);
00638 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00639                                                   DBusWatch     *watch,
00640                                                   dbus_bool_t    enabled);
00641 
00642 static dbus_bool_t
00643 protected_change_watch (DBusConnection         *connection,
00644                         DBusWatch              *watch,
00645                         DBusWatchAddFunction    add_function,
00646                         DBusWatchRemoveFunction remove_function,
00647                         DBusWatchToggleFunction toggle_function,
00648                         dbus_bool_t             enabled)
00649 {
00650   DBusWatchList *watches;
00651   dbus_bool_t retval;
00652   
00653   HAVE_LOCK_CHECK (connection);
00654 
00655   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00656    * drop lock and call out" one; but it has to be propagated up through all callers
00657    */
00658   
00659   watches = connection->watches;
00660   if (watches)
00661     {
00662       connection->watches = NULL;
00663       _dbus_connection_ref_unlocked (connection);
00664       CONNECTION_UNLOCK (connection);
00665 
00666       if (add_function)
00667         retval = (* add_function) (watches, watch);
00668       else if (remove_function)
00669         {
00670           retval = TRUE;
00671           (* remove_function) (watches, watch);
00672         }
00673       else
00674         {
00675           retval = TRUE;
00676           (* toggle_function) (watches, watch, enabled);
00677         }
00678       
00679       CONNECTION_LOCK (connection);
00680       connection->watches = watches;
00681       _dbus_connection_unref_unlocked (connection);
00682 
00683       return retval;
00684     }
00685   else
00686     return FALSE;
00687 }
00688      
00689 
00701 dbus_bool_t
00702 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00703                                      DBusWatch      *watch)
00704 {
00705   return protected_change_watch (connection, watch,
00706                                  _dbus_watch_list_add_watch,
00707                                  NULL, NULL, FALSE);
00708 }
00709 
00719 void
00720 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00721                                         DBusWatch      *watch)
00722 {
00723   protected_change_watch (connection, watch,
00724                           NULL,
00725                           _dbus_watch_list_remove_watch,
00726                           NULL, FALSE);
00727 }
00728 
00739 void
00740 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00741                                         DBusWatch      *watch,
00742                                         dbus_bool_t     enabled)
00743 {
00744   _dbus_assert (watch != NULL);
00745 
00746   protected_change_watch (connection, watch,
00747                           NULL, NULL,
00748                           _dbus_watch_list_toggle_watch,
00749                           enabled);
00750 }
00751 
00753 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00754                                                    DBusTimeout     *timeout);
00756 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00757                                                    DBusTimeout     *timeout);
00759 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00760                                                    DBusTimeout     *timeout,
00761                                                    dbus_bool_t      enabled);
00762 
00763 static dbus_bool_t
00764 protected_change_timeout (DBusConnection           *connection,
00765                           DBusTimeout              *timeout,
00766                           DBusTimeoutAddFunction    add_function,
00767                           DBusTimeoutRemoveFunction remove_function,
00768                           DBusTimeoutToggleFunction toggle_function,
00769                           dbus_bool_t               enabled)
00770 {
00771   DBusTimeoutList *timeouts;
00772   dbus_bool_t retval;
00773   
00774   HAVE_LOCK_CHECK (connection);
00775 
00776   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
00777    * drop lock and call out" one; but it has to be propagated up through all callers
00778    */
00779   
00780   timeouts = connection->timeouts;
00781   if (timeouts)
00782     {
00783       connection->timeouts = NULL;
00784       _dbus_connection_ref_unlocked (connection);
00785       CONNECTION_UNLOCK (connection);
00786 
00787       if (add_function)
00788         retval = (* add_function) (timeouts, timeout);
00789       else if (remove_function)
00790         {
00791           retval = TRUE;
00792           (* remove_function) (timeouts, timeout);
00793         }
00794       else
00795         {
00796           retval = TRUE;
00797           (* toggle_function) (timeouts, timeout, enabled);
00798         }
00799       
00800       CONNECTION_LOCK (connection);
00801       connection->timeouts = timeouts;
00802       _dbus_connection_unref_unlocked (connection);
00803 
00804       return retval;
00805     }
00806   else
00807     return FALSE;
00808 }
00809 
00822 dbus_bool_t
00823 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00824                                        DBusTimeout    *timeout)
00825 {
00826   return protected_change_timeout (connection, timeout,
00827                                    _dbus_timeout_list_add_timeout,
00828                                    NULL, NULL, FALSE);
00829 }
00830 
00840 void
00841 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00842                                           DBusTimeout    *timeout)
00843 {
00844   protected_change_timeout (connection, timeout,
00845                             NULL,
00846                             _dbus_timeout_list_remove_timeout,
00847                             NULL, FALSE);
00848 }
00849 
00860 void
00861 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00862                                           DBusTimeout      *timeout,
00863                                           dbus_bool_t       enabled)
00864 {
00865   protected_change_timeout (connection, timeout,
00866                             NULL, NULL,
00867                             _dbus_timeout_list_toggle_timeout,
00868                             enabled);
00869 }
00870 
00871 static dbus_bool_t
00872 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00873                                                DBusPendingCall *pending)
00874 {
00875   dbus_uint32_t reply_serial;
00876   DBusTimeout *timeout;
00877 
00878   HAVE_LOCK_CHECK (connection);
00879 
00880   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00881 
00882   _dbus_assert (reply_serial != 0);
00883 
00884   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00885 
00886   if (timeout)
00887     {
00888       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00889         return FALSE;
00890       
00891       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00892                                         reply_serial,
00893                                         pending))
00894         {
00895           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00896 
00897           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00898           HAVE_LOCK_CHECK (connection);
00899           return FALSE;
00900         }
00901       
00902       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00903     }
00904   else
00905     {
00906       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00907                                         reply_serial,
00908                                         pending))
00909         {
00910           HAVE_LOCK_CHECK (connection);
00911           return FALSE;
00912         }
00913     }
00914 
00915   _dbus_pending_call_ref_unlocked (pending);
00916 
00917   HAVE_LOCK_CHECK (connection);
00918   
00919   return TRUE;
00920 }
00921 
00922 static void
00923 free_pending_call_on_hash_removal (void *data)
00924 {
00925   DBusPendingCall *pending;
00926   DBusConnection  *connection;
00927   
00928   if (data == NULL)
00929     return;
00930 
00931   pending = data;
00932 
00933   connection = _dbus_pending_call_get_connection_unlocked (pending);
00934 
00935   HAVE_LOCK_CHECK (connection);
00936   
00937   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00938     {
00939       _dbus_connection_remove_timeout_unlocked (connection,
00940                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00941       
00942       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00943     }
00944 
00945   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00946    * here, but the pending call finalizer could in principle call out to 
00947    * application code so we pretty much have to... some larger code reorg 
00948    * might be needed.
00949    */
00950   _dbus_connection_ref_unlocked (connection);
00951   _dbus_pending_call_unref_and_unlock (pending);
00952   CONNECTION_LOCK (connection);
00953   _dbus_connection_unref_unlocked (connection);
00954 }
00955 
00956 static void
00957 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00958                                                DBusPendingCall *pending)
00959 {
00960   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00961    * say the least.
00962    */
00963   _dbus_hash_table_remove_int (connection->pending_replies,
00964                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00965 }
00966 
00967 static void
00968 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
00969                                                  DBusPendingCall *pending)
00970 {
00971   /* The idea here is to avoid finalizing the pending call
00972    * with the lock held, since there's a destroy notifier
00973    * in pending call that goes out to application code.
00974    *
00975    * There's an extra unlock inside the hash table
00976    * "free pending call" function FIXME...
00977    */
00978   _dbus_pending_call_ref_unlocked (pending);
00979   _dbus_hash_table_remove_int (connection->pending_replies,
00980                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00981 
00982   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00983       _dbus_connection_remove_timeout_unlocked (connection,
00984               _dbus_pending_call_get_timeout_unlocked (pending));
00985 
00986   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00987 
00988   _dbus_pending_call_unref_and_unlock (pending);
00989 }
00990 
00999 void
01000 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01001                                       DBusPendingCall *pending)
01002 {
01003   CONNECTION_LOCK (connection);
01004   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01005 }
01006 
01016 static dbus_bool_t
01017 _dbus_connection_acquire_io_path (DBusConnection *connection,
01018                                   int             timeout_milliseconds)
01019 {
01020   dbus_bool_t we_acquired;
01021   
01022   HAVE_LOCK_CHECK (connection);
01023 
01024   /* We don't want the connection to vanish */
01025   _dbus_connection_ref_unlocked (connection);
01026 
01027   /* We will only touch io_path_acquired which is protected by our mutex */
01028   CONNECTION_UNLOCK (connection);
01029   
01030   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01031   _dbus_mutex_lock (connection->io_path_mutex);
01032 
01033   _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
01034                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
01035 
01036   we_acquired = FALSE;
01037   
01038   if (connection->io_path_acquired)
01039     {
01040       if (timeout_milliseconds != -1)
01041         {
01042           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
01043                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
01044 
01045           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01046                                            connection->io_path_mutex,
01047                                            timeout_milliseconds))
01048             {
01049               /* We timed out before anyone signaled. */
01050               /* (writing the loop to handle the !timedout case by
01051                * waiting longer if needed is a pain since dbus
01052                * wraps pthread_cond_timedwait to take a relative
01053                * time instead of absolute, something kind of stupid
01054                * on our part. for now it doesn't matter, we will just
01055                * end up back here eventually.)
01056                */
01057             }
01058         }
01059       else
01060         {
01061           while (connection->io_path_acquired)
01062             {
01063               _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
01064               _dbus_condvar_wait (connection->io_path_cond, 
01065                                   connection->io_path_mutex);
01066             }
01067         }
01068     }
01069   
01070   if (!connection->io_path_acquired)
01071     {
01072       we_acquired = TRUE;
01073       connection->io_path_acquired = TRUE;
01074     }
01075   
01076   _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
01077                  _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
01078 
01079   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01080   _dbus_mutex_unlock (connection->io_path_mutex);
01081 
01082   CONNECTION_LOCK (connection);
01083   
01084   HAVE_LOCK_CHECK (connection);
01085 
01086   _dbus_connection_unref_unlocked (connection);
01087   
01088   return we_acquired;
01089 }
01090 
01098 static void
01099 _dbus_connection_release_io_path (DBusConnection *connection)
01100 {
01101   HAVE_LOCK_CHECK (connection);
01102   
01103   _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01104   _dbus_mutex_lock (connection->io_path_mutex);
01105   
01106   _dbus_assert (connection->io_path_acquired);
01107 
01108   _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01109                  _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01110   
01111   connection->io_path_acquired = FALSE;
01112   _dbus_condvar_wake_one (connection->io_path_cond);
01113 
01114   _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01115   _dbus_mutex_unlock (connection->io_path_mutex);
01116 }
01117 
01146 void
01147 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01148                                         unsigned int    flags,
01149                                         int             timeout_milliseconds)
01150 {
01151   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01152   
01153   HAVE_LOCK_CHECK (connection);
01154   
01155   if (connection->n_outgoing == 0)
01156     flags &= ~DBUS_ITERATION_DO_WRITING;
01157 
01158   if (_dbus_connection_acquire_io_path (connection,
01159                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01160     {
01161       HAVE_LOCK_CHECK (connection);
01162       
01163       _dbus_transport_do_iteration (connection->transport,
01164                                     flags, timeout_milliseconds);
01165       _dbus_connection_release_io_path (connection);
01166     }
01167 
01168   HAVE_LOCK_CHECK (connection);
01169 
01170   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01171 }
01172 
01182 DBusConnection*
01183 _dbus_connection_new_for_transport (DBusTransport *transport)
01184 {
01185   DBusConnection *connection;
01186   DBusWatchList *watch_list;
01187   DBusTimeoutList *timeout_list;
01188   DBusHashTable *pending_replies;
01189   DBusList *disconnect_link;
01190   DBusMessage *disconnect_message;
01191   DBusCounter *outgoing_counter;
01192   DBusObjectTree *objects;
01193   
01194   watch_list = NULL;
01195   connection = NULL;
01196   pending_replies = NULL;
01197   timeout_list = NULL;
01198   disconnect_link = NULL;
01199   disconnect_message = NULL;
01200   outgoing_counter = NULL;
01201   objects = NULL;
01202   
01203   watch_list = _dbus_watch_list_new ();
01204   if (watch_list == NULL)
01205     goto error;
01206 
01207   timeout_list = _dbus_timeout_list_new ();
01208   if (timeout_list == NULL)
01209     goto error;  
01210 
01211   pending_replies =
01212     _dbus_hash_table_new (DBUS_HASH_INT,
01213                           NULL,
01214                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01215   if (pending_replies == NULL)
01216     goto error;
01217   
01218   connection = dbus_new0 (DBusConnection, 1);
01219   if (connection == NULL)
01220     goto error;
01221 
01222   _dbus_mutex_new_at_location (&connection->mutex);
01223   if (connection->mutex == NULL)
01224     goto error;
01225 
01226   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01227   if (connection->io_path_mutex == NULL)
01228     goto error;
01229 
01230   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01231   if (connection->dispatch_mutex == NULL)
01232     goto error;
01233   
01234   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01235   if (connection->dispatch_cond == NULL)
01236     goto error;
01237   
01238   _dbus_condvar_new_at_location (&connection->io_path_cond);
01239   if (connection->io_path_cond == NULL)
01240     goto error;
01241 
01242   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01243                                                 DBUS_INTERFACE_LOCAL,
01244                                                 "Disconnected");
01245   
01246   if (disconnect_message == NULL)
01247     goto error;
01248 
01249   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01250   if (disconnect_link == NULL)
01251     goto error;
01252 
01253   outgoing_counter = _dbus_counter_new ();
01254   if (outgoing_counter == NULL)
01255     goto error;
01256 
01257   objects = _dbus_object_tree_new (connection);
01258   if (objects == NULL)
01259     goto error;
01260   
01261   if (_dbus_modify_sigpipe)
01262     _dbus_disable_sigpipe ();
01263   
01264   connection->refcount.value = 1;
01265   connection->transport = transport;
01266   connection->watches = watch_list;
01267   connection->timeouts = timeout_list;
01268   connection->pending_replies = pending_replies;
01269   connection->outgoing_counter = outgoing_counter;
01270   connection->filter_list = NULL;
01271   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01272   connection->objects = objects;
01273   connection->exit_on_disconnect = FALSE;
01274   connection->shareable = FALSE;
01275   connection->route_peer_messages = FALSE;
01276   connection->disconnected_message_arrived = FALSE;
01277   connection->disconnected_message_processed = FALSE;
01278   
01279 #ifndef DBUS_DISABLE_CHECKS
01280   connection->generation = _dbus_current_generation;
01281 #endif
01282   
01283   _dbus_data_slot_list_init (&connection->slot_list);
01284 
01285   connection->client_serial = 1;
01286 
01287   connection->disconnect_message_link = disconnect_link;
01288 
01289   CONNECTION_LOCK (connection);
01290   
01291   if (!_dbus_transport_set_connection (transport, connection))
01292     {
01293       CONNECTION_UNLOCK (connection);
01294 
01295       goto error;
01296     }
01297 
01298   _dbus_transport_ref (transport);
01299 
01300   CONNECTION_UNLOCK (connection);
01301   
01302   return connection;
01303   
01304  error:
01305   if (disconnect_message != NULL)
01306     dbus_message_unref (disconnect_message);
01307   
01308   if (disconnect_link != NULL)
01309     _dbus_list_free_link (disconnect_link);
01310   
01311   if (connection != NULL)
01312     {
01313       _dbus_condvar_free_at_location (&connection->io_path_cond);
01314       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01315       _dbus_mutex_free_at_location (&connection->mutex);
01316       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01317       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01318       dbus_free (connection);
01319     }
01320   if (pending_replies)
01321     _dbus_hash_table_unref (pending_replies);
01322   
01323   if (watch_list)
01324     _dbus_watch_list_free (watch_list);
01325 
01326   if (timeout_list)
01327     _dbus_timeout_list_free (timeout_list);
01328 
01329   if (outgoing_counter)
01330     _dbus_counter_unref (outgoing_counter);
01331 
01332   if (objects)
01333     _dbus_object_tree_unref (objects);
01334   
01335   return NULL;
01336 }
01337 
01345 DBusConnection *
01346 _dbus_connection_ref_unlocked (DBusConnection *connection)
01347 {  
01348   _dbus_assert (connection != NULL);
01349   _dbus_assert (connection->generation == _dbus_current_generation);
01350 
01351   HAVE_LOCK_CHECK (connection);
01352   
01353 #ifdef DBUS_HAVE_ATOMIC_INT
01354   _dbus_atomic_inc (&connection->refcount);
01355 #else
01356   _dbus_assert (connection->refcount.value > 0);
01357   connection->refcount.value += 1;
01358 #endif
01359 
01360   return connection;
01361 }
01362 
01369 void
01370 _dbus_connection_unref_unlocked (DBusConnection *connection)
01371 {
01372   dbus_bool_t last_unref;
01373 
01374   HAVE_LOCK_CHECK (connection);
01375   
01376   _dbus_assert (connection != NULL);
01377 
01378   /* The connection lock is better than the global
01379    * lock in the atomic increment fallback
01380    */
01381   
01382 #ifdef DBUS_HAVE_ATOMIC_INT
01383   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01384 #else
01385   _dbus_assert (connection->refcount.value > 0);
01386 
01387   connection->refcount.value -= 1;
01388   last_unref = (connection->refcount.value == 0);  
01389 #if 0
01390   printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01391 #endif
01392 #endif
01393   
01394   if (last_unref)
01395     _dbus_connection_last_unref (connection);
01396 }
01397 
01398 static dbus_uint32_t
01399 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01400 {
01401   dbus_uint32_t serial;
01402 
01403   serial = connection->client_serial++;
01404 
01405   if (connection->client_serial == 0)
01406     connection->client_serial = 1;
01407 
01408   return serial;
01409 }
01410 
01424 dbus_bool_t
01425 _dbus_connection_handle_watch (DBusWatch                   *watch,
01426                                unsigned int                 condition,
01427                                void                        *data)
01428 {
01429   DBusConnection *connection;
01430   dbus_bool_t retval;
01431   DBusDispatchStatus status;
01432 
01433   connection = data;
01434 
01435   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01436   
01437   CONNECTION_LOCK (connection);
01438 
01439   if (!_dbus_connection_acquire_io_path (connection, 1))
01440     {
01441       /* another thread is handling the message */
01442       CONNECTION_UNLOCK (connection);
01443       return TRUE;
01444     }
01445 
01446   HAVE_LOCK_CHECK (connection);
01447   retval = _dbus_transport_handle_watch (connection->transport,
01448                                          watch, condition);
01449 
01450   _dbus_connection_release_io_path (connection);
01451 
01452   HAVE_LOCK_CHECK (connection);
01453 
01454   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01455   
01456   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01457 
01458   /* this calls out to user code */
01459   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01460 
01461   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01462   
01463   return retval;
01464 }
01465 
01466 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01467 static DBusHashTable *shared_connections = NULL;
01468 static DBusList *shared_connections_no_guid = NULL;
01469 
01470 static void
01471 close_connection_on_shutdown (DBusConnection *connection)
01472 {
01473   DBusMessage *message;
01474 
01475   dbus_connection_ref (connection);
01476   _dbus_connection_close_possibly_shared (connection);
01477 
01478   /* Churn through to the Disconnected message */
01479   while ((message = dbus_connection_pop_message (connection)))
01480     {
01481       dbus_message_unref (message);
01482     }
01483   dbus_connection_unref (connection);
01484 }
01485 
01486 static void
01487 shared_connections_shutdown (void *data)
01488 {
01489   int n_entries;
01490   
01491   _DBUS_LOCK (shared_connections);
01492   
01493   /* This is a little bit unpleasant... better ideas? */
01494   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01495     {
01496       DBusConnection *connection;
01497       DBusHashIter iter;
01498       
01499       _dbus_hash_iter_init (shared_connections, &iter);
01500       _dbus_hash_iter_next (&iter);
01501        
01502       connection = _dbus_hash_iter_get_value (&iter);
01503 
01504       _DBUS_UNLOCK (shared_connections);
01505       close_connection_on_shutdown (connection);
01506       _DBUS_LOCK (shared_connections);
01507 
01508       /* The connection should now be dead and not in our hash ... */
01509       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01510     }
01511 
01512   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01513   
01514   _dbus_hash_table_unref (shared_connections);
01515   shared_connections = NULL;
01516 
01517   if (shared_connections_no_guid != NULL)
01518     {
01519       DBusConnection *connection;
01520       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01521       while (connection != NULL)
01522         {
01523           _DBUS_UNLOCK (shared_connections);
01524           close_connection_on_shutdown (connection);
01525           _DBUS_LOCK (shared_connections);
01526           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01527         }
01528     }
01529 
01530   shared_connections_no_guid = NULL;
01531   
01532   _DBUS_UNLOCK (shared_connections);
01533 }
01534 
01535 static dbus_bool_t
01536 connection_lookup_shared (DBusAddressEntry  *entry,
01537                           DBusConnection   **result)
01538 {
01539   _dbus_verbose ("checking for existing connection\n");
01540   
01541   *result = NULL;
01542   
01543   _DBUS_LOCK (shared_connections);
01544 
01545   if (shared_connections == NULL)
01546     {
01547       _dbus_verbose ("creating shared_connections hash table\n");
01548       
01549       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01550                                                  dbus_free,
01551                                                  NULL);
01552       if (shared_connections == NULL)
01553         {
01554           _DBUS_UNLOCK (shared_connections);
01555           return FALSE;
01556         }
01557 
01558       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01559         {
01560           _dbus_hash_table_unref (shared_connections);
01561           shared_connections = NULL;
01562           _DBUS_UNLOCK (shared_connections);
01563           return FALSE;
01564         }
01565 
01566       _dbus_verbose ("  successfully created shared_connections\n");
01567       
01568       _DBUS_UNLOCK (shared_connections);
01569       return TRUE; /* no point looking up in the hash we just made */
01570     }
01571   else
01572     {
01573       const char *guid;
01574 
01575       guid = dbus_address_entry_get_value (entry, "guid");
01576       
01577       if (guid != NULL)
01578         {
01579           DBusConnection *connection;
01580           
01581           connection = _dbus_hash_table_lookup_string (shared_connections,
01582                                                        guid);
01583 
01584           if (connection)
01585             {
01586               /* The DBusConnection can't be finalized without taking
01587                * the shared_connections lock to remove it from the
01588                * hash.  So it's safe to ref the connection here.
01589                * However, it may be disconnected if the Disconnected
01590                * message hasn't been processed yet, in which case we
01591                * want to pretend it isn't in the hash and avoid
01592                * returning it.
01593                *
01594                * The idea is to avoid ever returning a disconnected connection
01595                * from dbus_connection_open(). We could just synchronously
01596                * drop our shared ref to the connection on connection disconnect,
01597                * and then assert here that the connection is connected, but
01598                * that causes reentrancy headaches.
01599                */
01600               CONNECTION_LOCK (connection);
01601               if (_dbus_connection_get_is_connected_unlocked (connection))
01602                 {
01603                   _dbus_connection_ref_unlocked (connection);
01604                   *result = connection;
01605                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01606                                  guid);
01607                 }
01608               else
01609                 {
01610                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01611                                  guid);
01612                 }
01613               CONNECTION_UNLOCK (connection);
01614             }
01615         }
01616       
01617       _DBUS_UNLOCK (shared_connections);
01618       return TRUE;
01619     }
01620 }
01621 
01622 static dbus_bool_t
01623 connection_record_shared_unlocked (DBusConnection *connection,
01624                                    const char     *guid)
01625 {
01626   char *guid_key;
01627   char *guid_in_connection;
01628 
01629   HAVE_LOCK_CHECK (connection);
01630   _dbus_assert (connection->server_guid == NULL);
01631   _dbus_assert (connection->shareable);
01632 
01633   /* get a hard ref on this connection, even if
01634    * we won't in fact store it in the hash, we still
01635    * need to hold a ref on it until it's disconnected.
01636    */
01637   _dbus_connection_ref_unlocked (connection);
01638 
01639   if (guid == NULL)
01640     {
01641       _DBUS_LOCK (shared_connections);
01642 
01643       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01644         {
01645           _DBUS_UNLOCK (shared_connections);
01646           return FALSE;
01647         }
01648 
01649       _DBUS_UNLOCK (shared_connections);
01650       return TRUE; /* don't store in the hash */
01651     }
01652   
01653   /* A separate copy of the key is required in the hash table, because
01654    * we don't have a lock on the connection when we are doing a hash
01655    * lookup.
01656    */
01657   
01658   guid_key = _dbus_strdup (guid);
01659   if (guid_key == NULL)
01660     return FALSE;
01661 
01662   guid_in_connection = _dbus_strdup (guid);
01663   if (guid_in_connection == NULL)
01664     {
01665       dbus_free (guid_key);
01666       return FALSE;
01667     }
01668   
01669   _DBUS_LOCK (shared_connections);
01670   _dbus_assert (shared_connections != NULL);
01671   
01672   if (!_dbus_hash_table_insert_string (shared_connections,
01673                                        guid_key, connection))
01674     {
01675       dbus_free (guid_key);
01676       dbus_free (guid_in_connection);
01677       _DBUS_UNLOCK (shared_connections);
01678       return FALSE;
01679     }
01680 
01681   connection->server_guid = guid_in_connection;
01682 
01683   _dbus_verbose ("stored connection to %s to be shared\n",
01684                  connection->server_guid);
01685   
01686   _DBUS_UNLOCK (shared_connections);
01687 
01688   _dbus_assert (connection->server_guid != NULL);
01689   
01690   return TRUE;
01691 }
01692 
01693 static void
01694 connection_forget_shared_unlocked (DBusConnection *connection)
01695 {
01696   HAVE_LOCK_CHECK (connection);
01697 
01698   if (!connection->shareable)
01699     return;
01700   
01701   _DBUS_LOCK (shared_connections);
01702       
01703   if (connection->server_guid != NULL)
01704     {
01705       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01706                      connection->server_guid);
01707       
01708       if (!_dbus_hash_table_remove_string (shared_connections,
01709                                            connection->server_guid))
01710         _dbus_assert_not_reached ("connection was not in the shared table");
01711       
01712       dbus_free (connection->server_guid);
01713       connection->server_guid = NULL;
01714     }
01715   else
01716     {
01717       _dbus_list_remove (&shared_connections_no_guid, connection);
01718     }
01719 
01720   _DBUS_UNLOCK (shared_connections);
01721   
01722   /* remove our reference held on all shareable connections */
01723   _dbus_connection_unref_unlocked (connection);
01724 }
01725 
01726 static DBusConnection*
01727 connection_try_from_address_entry (DBusAddressEntry *entry,
01728                                    DBusError        *error)
01729 {
01730   DBusTransport *transport;
01731   DBusConnection *connection;
01732 
01733   transport = _dbus_transport_open (entry, error);
01734 
01735   if (transport == NULL)
01736     {
01737       _DBUS_ASSERT_ERROR_IS_SET (error);
01738       return NULL;
01739     }
01740 
01741   connection = _dbus_connection_new_for_transport (transport);
01742 
01743   _dbus_transport_unref (transport);
01744   
01745   if (connection == NULL)
01746     {
01747       _DBUS_SET_OOM (error);
01748       return NULL;
01749     }
01750 
01751 #ifndef DBUS_DISABLE_CHECKS
01752   _dbus_assert (!connection->have_connection_lock);
01753 #endif
01754   return connection;
01755 }
01756 
01757 /*
01758  * If the shared parameter is true, then any existing connection will
01759  * be used (and if a new connection is created, it will be available
01760  * for use by others). If the shared parameter is false, a new
01761  * connection will always be created, and the new connection will
01762  * never be returned to other callers.
01763  *
01764  * @param address the address
01765  * @param shared whether the connection is shared or private
01766  * @param error error return
01767  * @returns the connection or #NULL on error
01768  */
01769 static DBusConnection*
01770 _dbus_connection_open_internal (const char     *address,
01771                                 dbus_bool_t     shared,
01772                                 DBusError      *error)
01773 {
01774   DBusConnection *connection;
01775   DBusAddressEntry **entries;
01776   DBusError tmp_error = DBUS_ERROR_INIT;
01777   DBusError first_error = DBUS_ERROR_INIT;
01778   int len, i;
01779 
01780   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01781 
01782   _dbus_verbose ("opening %s connection to: %s\n",
01783                  shared ? "shared" : "private", address);
01784   
01785   if (!dbus_parse_address (address, &entries, &len, error))
01786     return NULL;
01787 
01788   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01789   
01790   connection = NULL;
01791 
01792   for (i = 0; i < len; i++)
01793     {
01794       if (shared)
01795         {
01796           if (!connection_lookup_shared (entries[i], &connection))
01797             _DBUS_SET_OOM (&tmp_error);
01798         }
01799 
01800       if (connection == NULL)
01801         {
01802           connection = connection_try_from_address_entry (entries[i],
01803                                                           &tmp_error);
01804 
01805           if (connection != NULL && shared)
01806             {
01807               const char *guid;
01808                   
01809               connection->shareable = TRUE;
01810                   
01811               /* guid may be NULL */
01812               guid = dbus_address_entry_get_value (entries[i], "guid");
01813                   
01814               CONNECTION_LOCK (connection);
01815           
01816               if (!connection_record_shared_unlocked (connection, guid))
01817                 {
01818                   _DBUS_SET_OOM (&tmp_error);
01819                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01820                   dbus_connection_unref (connection);
01821                   connection = NULL;
01822                 }
01823               else
01824                 CONNECTION_UNLOCK (connection);
01825             }
01826         }
01827       
01828       if (connection)
01829         break;
01830 
01831       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01832       
01833       if (i == 0)
01834         dbus_move_error (&tmp_error, &first_error);
01835       else
01836         dbus_error_free (&tmp_error);
01837     }
01838   
01839   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01840   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01841   
01842   if (connection == NULL)
01843     {
01844       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01845       dbus_move_error (&first_error, error);
01846     }
01847   else
01848     dbus_error_free (&first_error);
01849   
01850   dbus_address_entries_free (entries);
01851   return connection;
01852 }
01853 
01862 void
01863 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01864 {
01865   _dbus_assert (connection != NULL);
01866   _dbus_assert (connection->generation == _dbus_current_generation);
01867 
01868   CONNECTION_LOCK (connection);
01869   _dbus_connection_close_possibly_shared_and_unlock (connection);
01870 }
01871 
01872 static DBusPreallocatedSend*
01873 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01874 {
01875   DBusPreallocatedSend *preallocated;
01876 
01877   HAVE_LOCK_CHECK (connection);
01878   
01879   _dbus_assert (connection != NULL);
01880   
01881   preallocated = dbus_new (DBusPreallocatedSend, 1);
01882   if (preallocated == NULL)
01883     return NULL;
01884 
01885   if (connection->link_cache != NULL)
01886     {
01887       preallocated->queue_link =
01888         _dbus_list_pop_first_link (&connection->link_cache);
01889       preallocated->queue_link->data = NULL;
01890     }
01891   else
01892     {
01893       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01894       if (preallocated->queue_link == NULL)
01895         goto failed_0;
01896     }
01897   
01898   if (connection->link_cache != NULL)
01899     {
01900       preallocated->counter_link =
01901         _dbus_list_pop_first_link (&connection->link_cache);
01902       preallocated->counter_link->data = connection->outgoing_counter;
01903     }
01904   else
01905     {
01906       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01907       if (preallocated->counter_link == NULL)
01908         goto failed_1;
01909     }
01910 
01911   _dbus_counter_ref (preallocated->counter_link->data);
01912 
01913   preallocated->connection = connection;
01914   
01915   return preallocated;
01916   
01917  failed_1:
01918   _dbus_list_free_link (preallocated->queue_link);
01919  failed_0:
01920   dbus_free (preallocated);
01921   
01922   return NULL;
01923 }
01924 
01925 /* Called with lock held, does not update dispatch status */
01926 static void
01927 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01928                                                        DBusPreallocatedSend *preallocated,
01929                                                        DBusMessage          *message,
01930                                                        dbus_uint32_t        *client_serial)
01931 {
01932   dbus_uint32_t serial;
01933   const char *sig;
01934 
01935   preallocated->queue_link->data = message;
01936   _dbus_list_prepend_link (&connection->outgoing_messages,
01937                            preallocated->queue_link);
01938 
01939   _dbus_message_add_size_counter_link (message,
01940                                        preallocated->counter_link);
01941 
01942   dbus_free (preallocated);
01943   preallocated = NULL;
01944   
01945   dbus_message_ref (message);
01946   
01947   connection->n_outgoing += 1;
01948 
01949   sig = dbus_message_get_signature (message);
01950   
01951   _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01952                  message,
01953                  dbus_message_get_type (message),
01954                  dbus_message_get_path (message) ?
01955                  dbus_message_get_path (message) :
01956                  "no path",
01957                  dbus_message_get_interface (message) ?
01958                  dbus_message_get_interface (message) :
01959                  "no interface",
01960                  dbus_message_get_member (message) ?
01961                  dbus_message_get_member (message) :
01962                  "no member",
01963                  sig,
01964                  dbus_message_get_destination (message) ?
01965                  dbus_message_get_destination (message) :
01966                  "null",
01967                  connection,
01968                  connection->n_outgoing);
01969 
01970   if (dbus_message_get_serial (message) == 0)
01971     {
01972       serial = _dbus_connection_get_next_client_serial (connection);
01973       dbus_message_set_serial (message, serial);
01974       if (client_serial)
01975         *client_serial = serial;
01976     }
01977   else
01978     {
01979       if (client_serial)
01980         *client_serial = dbus_message_get_serial (message);
01981     }
01982 
01983   _dbus_verbose ("Message %p serial is %u\n",
01984                  message, dbus_message_get_serial (message));
01985   
01986   dbus_message_lock (message);
01987 
01988   /* Now we need to run an iteration to hopefully just write the messages
01989    * out immediately, and otherwise get them queued up
01990    */
01991   _dbus_connection_do_iteration_unlocked (connection,
01992                                           DBUS_ITERATION_DO_WRITING,
01993                                           -1);
01994 
01995   /* If stuff is still queued up, be sure we wake up the main loop */
01996   if (connection->n_outgoing > 0)
01997     _dbus_connection_wakeup_mainloop (connection);
01998 }
01999 
02000 static void
02001 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02002                                                DBusPreallocatedSend *preallocated,
02003                                                DBusMessage          *message,
02004                                                dbus_uint32_t        *client_serial)
02005 {
02006   DBusDispatchStatus status;
02007 
02008   HAVE_LOCK_CHECK (connection);
02009   
02010   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02011                                                          preallocated,
02012                                                          message, client_serial);
02013 
02014   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02015   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02016 
02017   /* this calls out to user code */
02018   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02019 }
02020 
02030 dbus_bool_t
02031 _dbus_connection_send_and_unlock (DBusConnection *connection,
02032                                   DBusMessage    *message,
02033                                   dbus_uint32_t  *client_serial)
02034 {
02035   DBusPreallocatedSend *preallocated;
02036 
02037   _dbus_assert (connection != NULL);
02038   _dbus_assert (message != NULL);
02039   
02040   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02041   if (preallocated == NULL)
02042     {
02043       CONNECTION_UNLOCK (connection);
02044       return FALSE;
02045     }
02046 
02047   _dbus_connection_send_preallocated_and_unlock (connection,
02048                                                  preallocated,
02049                                                  message,
02050                                                  client_serial);
02051   return TRUE;
02052 }
02053 
02078 void
02079 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02080 {
02081   CONNECTION_LOCK (connection);
02082   
02083   _dbus_assert (connection->refcount.value > 0);
02084 
02085   if (connection->refcount.value == 1)
02086     _dbus_connection_close_possibly_shared_and_unlock (connection);
02087   else
02088     CONNECTION_UNLOCK (connection);
02089 }
02090 
02091 
02101 static void
02102 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02103 {
02104   if (timeout_milliseconds == -1)
02105     _dbus_sleep_milliseconds (1000);
02106   else if (timeout_milliseconds < 100)
02107     ; /* just busy loop */
02108   else if (timeout_milliseconds <= 1000)
02109     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02110   else
02111     _dbus_sleep_milliseconds (1000);
02112 }
02113 
02114 static DBusMessage *
02115 generate_local_error_message (dbus_uint32_t serial, 
02116                               char *error_name, 
02117                               char *error_msg)
02118 {
02119   DBusMessage *message;
02120   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02121   if (!message)
02122     goto out;
02123 
02124   if (!dbus_message_set_error_name (message, error_name))
02125     {
02126       dbus_message_unref (message);
02127       message = NULL;
02128       goto out; 
02129     }
02130 
02131   dbus_message_set_no_reply (message, TRUE); 
02132 
02133   if (!dbus_message_set_reply_serial (message,
02134                                       serial))
02135     {
02136       dbus_message_unref (message);
02137       message = NULL;
02138       goto out;
02139     }
02140 
02141   if (error_msg != NULL)
02142     {
02143       DBusMessageIter iter;
02144 
02145       dbus_message_iter_init_append (message, &iter);
02146       if (!dbus_message_iter_append_basic (&iter,
02147                                            DBUS_TYPE_STRING,
02148                                            &error_msg))
02149         {
02150           dbus_message_unref (message);
02151           message = NULL;
02152           goto out;
02153         }
02154     }
02155 
02156  out:
02157   return message;
02158 }
02159 
02160 
02161 /* This is slightly strange since we can pop a message here without
02162  * the dispatch lock.
02163  */
02164 static DBusMessage*
02165 check_for_reply_unlocked (DBusConnection *connection,
02166                           dbus_uint32_t   client_serial)
02167 {
02168   DBusList *link;
02169 
02170   HAVE_LOCK_CHECK (connection);
02171   
02172   link = _dbus_list_get_first_link (&connection->incoming_messages);
02173 
02174   while (link != NULL)
02175     {
02176       DBusMessage *reply = link->data;
02177 
02178       if (dbus_message_get_reply_serial (reply) == client_serial)
02179         {
02180           _dbus_list_remove_link (&connection->incoming_messages, link);
02181           connection->n_incoming  -= 1;
02182           return reply;
02183         }
02184       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02185     }
02186 
02187   return NULL;
02188 }
02189 
02190 static void
02191 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02192 {
02193    /* We can't iterate over the hash in the normal way since we'll be
02194     * dropping the lock for each item. So we restart the
02195     * iter each time as we drain the hash table.
02196     */
02197    
02198    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02199     {
02200       DBusPendingCall *pending;
02201       DBusHashIter iter;
02202       
02203       _dbus_hash_iter_init (connection->pending_replies, &iter);
02204       _dbus_hash_iter_next (&iter);
02205        
02206       pending = _dbus_hash_iter_get_value (&iter);
02207       _dbus_pending_call_ref_unlocked (pending);
02208        
02209       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02210                                                        connection);
02211 
02212       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02213           _dbus_connection_remove_timeout_unlocked (connection,
02214                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02215       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02216       _dbus_hash_iter_remove_entry (&iter);
02217 
02218       _dbus_pending_call_unref_and_unlock (pending);
02219       CONNECTION_LOCK (connection);
02220     }
02221   HAVE_LOCK_CHECK (connection);
02222 }
02223 
02224 static void
02225 complete_pending_call_and_unlock (DBusConnection  *connection,
02226                                   DBusPendingCall *pending,
02227                                   DBusMessage     *message)
02228 {
02229   _dbus_pending_call_set_reply_unlocked (pending, message);
02230   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02231   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02232  
02233   /* Must be called unlocked since it invokes app callback */
02234   _dbus_pending_call_complete (pending);
02235   dbus_pending_call_unref (pending);
02236 }
02237 
02238 static dbus_bool_t
02239 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02240                                               DBusPendingCall *pending)
02241 {
02242   DBusMessage *reply;
02243   DBusDispatchStatus status;
02244 
02245   reply = check_for_reply_unlocked (connection, 
02246                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02247   if (reply != NULL)
02248     {
02249       _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02250 
02251       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02252 
02253       complete_pending_call_and_unlock (connection, pending, reply);
02254       dbus_message_unref (reply);
02255 
02256       CONNECTION_LOCK (connection);
02257       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02258       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02259       dbus_pending_call_unref (pending);
02260 
02261       return TRUE;
02262     }
02263 
02264   return FALSE;
02265 }
02266 
02281 void
02282 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02283 {
02284   long start_tv_sec, start_tv_usec;
02285   long tv_sec, tv_usec;
02286   DBusDispatchStatus status;
02287   DBusConnection *connection;
02288   dbus_uint32_t client_serial;
02289   DBusTimeout *timeout;
02290   int timeout_milliseconds, elapsed_milliseconds;
02291 
02292   _dbus_assert (pending != NULL);
02293 
02294   if (dbus_pending_call_get_completed (pending))
02295     return;
02296 
02297   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02298 
02299   connection = _dbus_pending_call_get_connection_and_lock (pending);
02300   
02301   /* Flush message queue - note, can affect dispatch status */
02302   _dbus_connection_flush_unlocked (connection);
02303 
02304   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02305 
02306   /* note that timeout_milliseconds is limited to a smallish value
02307    * in _dbus_pending_call_new() so overflows aren't possible
02308    * below
02309    */
02310   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02311   if (timeout)
02312     {
02313       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02314       _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02315 
02316       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02317                      timeout_milliseconds,
02318                      client_serial,
02319                      start_tv_sec, start_tv_usec);
02320     }
02321   else
02322     {
02323       timeout_milliseconds = -1;
02324 
02325       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02326     }
02327 
02328   /* check to see if we already got the data off the socket */
02329   /* from another blocked pending call */
02330   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02331     return;
02332 
02333   /* Now we wait... */
02334   /* always block at least once as we know we don't have the reply yet */
02335   _dbus_connection_do_iteration_unlocked (connection,
02336                                           DBUS_ITERATION_DO_READING |
02337                                           DBUS_ITERATION_BLOCK,
02338                                           timeout_milliseconds);
02339 
02340  recheck_status:
02341 
02342   _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02343   
02344   HAVE_LOCK_CHECK (connection);
02345   
02346   /* queue messages and get status */
02347 
02348   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02349 
02350   /* the get_completed() is in case a dispatch() while we were blocking
02351    * got the reply instead of us.
02352    */
02353   if (_dbus_pending_call_get_completed_unlocked (pending))
02354     {
02355       _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02356       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02357       dbus_pending_call_unref (pending);
02358       return;
02359     }
02360   
02361   if (status == DBUS_DISPATCH_DATA_REMAINS)
02362     {
02363       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02364         return;
02365     }
02366   
02367   _dbus_get_current_time (&tv_sec, &tv_usec);
02368   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02369           (tv_usec - start_tv_usec) / 1000;
02370   
02371   if (!_dbus_connection_get_is_connected_unlocked (connection))
02372     {
02373       DBusMessage *error_msg;
02374 
02375       error_msg = generate_local_error_message (client_serial,
02376                                                 DBUS_ERROR_DISCONNECTED, 
02377                                                 "Connection was disconnected before a reply was received"); 
02378 
02379       /* on OOM error_msg is set to NULL */
02380       complete_pending_call_and_unlock (connection, pending, error_msg);
02381       dbus_pending_call_unref (pending);
02382       return;
02383     }
02384   else if (connection->disconnect_message_link == NULL)
02385     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02386   else if (timeout == NULL)
02387     {
02388        if (status == DBUS_DISPATCH_NEED_MEMORY)
02389         {
02390           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02391            * we may already have a reply in the buffer and just can't process
02392            * it.
02393            */
02394           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02395 
02396           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02397         }
02398       else
02399         {          
02400           /* block again, we don't have the reply buffered yet. */
02401           _dbus_connection_do_iteration_unlocked (connection,
02402                                                   DBUS_ITERATION_DO_READING |
02403                                                   DBUS_ITERATION_BLOCK,
02404                                                   timeout_milliseconds - elapsed_milliseconds);
02405         }
02406 
02407       goto recheck_status;
02408     }
02409   else if (tv_sec < start_tv_sec)
02410     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02411   else if (elapsed_milliseconds < timeout_milliseconds)
02412     {
02413       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02414       
02415       if (status == DBUS_DISPATCH_NEED_MEMORY)
02416         {
02417           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02418            * we may already have a reply in the buffer and just can't process
02419            * it.
02420            */
02421           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02422 
02423           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02424         }
02425       else
02426         {          
02427           /* block again, we don't have the reply buffered yet. */
02428           _dbus_connection_do_iteration_unlocked (connection,
02429                                                   DBUS_ITERATION_DO_READING |
02430                                                   DBUS_ITERATION_BLOCK,
02431                                                   timeout_milliseconds - elapsed_milliseconds);
02432         }
02433 
02434       goto recheck_status;
02435     }
02436 
02437   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02438                  elapsed_milliseconds);
02439 
02440   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02441   
02442   /* unlock and call user code */
02443   complete_pending_call_and_unlock (connection, pending, NULL);
02444 
02445   /* update user code on dispatch status */
02446   CONNECTION_LOCK (connection);
02447   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02448   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02449   dbus_pending_call_unref (pending);
02450 }
02451 
02488 DBusConnection*
02489 dbus_connection_open (const char     *address,
02490                       DBusError      *error)
02491 {
02492   DBusConnection *connection;
02493 
02494   _dbus_return_val_if_fail (address != NULL, NULL);
02495   _dbus_return_val_if_error_is_set (error, NULL);
02496 
02497   connection = _dbus_connection_open_internal (address,
02498                                                TRUE,
02499                                                error);
02500 
02501   return connection;
02502 }
02503 
02531 DBusConnection*
02532 dbus_connection_open_private (const char     *address,
02533                               DBusError      *error)
02534 {
02535   DBusConnection *connection;
02536 
02537   _dbus_return_val_if_fail (address != NULL, NULL);
02538   _dbus_return_val_if_error_is_set (error, NULL);
02539 
02540   connection = _dbus_connection_open_internal (address,
02541                                                FALSE,
02542                                                error);
02543 
02544   return connection;
02545 }
02546 
02553 DBusConnection *
02554 dbus_connection_ref (DBusConnection *connection)
02555 {
02556   _dbus_return_val_if_fail (connection != NULL, NULL);
02557   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02558   
02559   /* The connection lock is better than the global
02560    * lock in the atomic increment fallback
02561    */
02562   
02563 #ifdef DBUS_HAVE_ATOMIC_INT
02564   _dbus_atomic_inc (&connection->refcount);
02565 #else
02566   CONNECTION_LOCK (connection);
02567   _dbus_assert (connection->refcount.value > 0);
02568 
02569   connection->refcount.value += 1;
02570   CONNECTION_UNLOCK (connection);
02571 #endif
02572 
02573   return connection;
02574 }
02575 
02576 static void
02577 free_outgoing_message (void *element,
02578                        void *data)
02579 {
02580   DBusMessage *message = element;
02581   DBusConnection *connection = data;
02582 
02583   _dbus_message_remove_size_counter (message,
02584                                      connection->outgoing_counter,
02585                                      NULL);
02586   dbus_message_unref (message);
02587 }
02588 
02589 /* This is run without the mutex held, but after the last reference
02590  * to the connection has been dropped we should have no thread-related
02591  * problems
02592  */
02593 static void
02594 _dbus_connection_last_unref (DBusConnection *connection)
02595 {
02596   DBusList *link;
02597 
02598   _dbus_verbose ("Finalizing connection %p\n", connection);
02599   
02600   _dbus_assert (connection->refcount.value == 0);
02601   
02602   /* You have to disconnect the connection before unref:ing it. Otherwise
02603    * you won't get the disconnected message.
02604    */
02605   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02606   _dbus_assert (connection->server_guid == NULL);
02607   
02608   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02609   _dbus_object_tree_free_all_unlocked (connection->objects);
02610   
02611   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02612   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02613   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02614   
02615   _dbus_watch_list_free (connection->watches);
02616   connection->watches = NULL;
02617   
02618   _dbus_timeout_list_free (connection->timeouts);
02619   connection->timeouts = NULL;
02620 
02621   _dbus_data_slot_list_free (&connection->slot_list);
02622   
02623   link = _dbus_list_get_first_link (&connection->filter_list);
02624   while (link != NULL)
02625     {
02626       DBusMessageFilter *filter = link->data;
02627       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02628 
02629       filter->function = NULL;
02630       _dbus_message_filter_unref (filter); /* calls app callback */
02631       link->data = NULL;
02632       
02633       link = next;
02634     }
02635   _dbus_list_clear (&connection->filter_list);
02636   
02637   /* ---- Done with stuff that invokes application callbacks */
02638 
02639   _dbus_object_tree_unref (connection->objects);  
02640 
02641   _dbus_hash_table_unref (connection->pending_replies);
02642   connection->pending_replies = NULL;
02643   
02644   _dbus_list_clear (&connection->filter_list);
02645   
02646   _dbus_list_foreach (&connection->outgoing_messages,
02647                       free_outgoing_message,
02648                       connection);
02649   _dbus_list_clear (&connection->outgoing_messages);
02650   
02651   _dbus_list_foreach (&connection->incoming_messages,
02652                       (DBusForeachFunction) dbus_message_unref,
02653                       NULL);
02654   _dbus_list_clear (&connection->incoming_messages);
02655 
02656   _dbus_counter_unref (connection->outgoing_counter);
02657 
02658   _dbus_transport_unref (connection->transport);
02659 
02660   if (connection->disconnect_message_link)
02661     {
02662       DBusMessage *message = connection->disconnect_message_link->data;
02663       dbus_message_unref (message);
02664       _dbus_list_free_link (connection->disconnect_message_link);
02665     }
02666 
02667   _dbus_list_clear (&connection->link_cache);
02668   
02669   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02670   _dbus_condvar_free_at_location (&connection->io_path_cond);
02671 
02672   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02673   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02674 
02675   _dbus_mutex_free_at_location (&connection->mutex);
02676   
02677   dbus_free (connection);
02678 }
02679 
02699 void
02700 dbus_connection_unref (DBusConnection *connection)
02701 {
02702   dbus_bool_t last_unref;
02703 
02704   _dbus_return_if_fail (connection != NULL);
02705   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02706   
02707   /* The connection lock is better than the global
02708    * lock in the atomic increment fallback
02709    */
02710   
02711 #ifdef DBUS_HAVE_ATOMIC_INT
02712   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02713 #else
02714   CONNECTION_LOCK (connection);
02715   
02716   _dbus_assert (connection->refcount.value > 0);
02717 
02718   connection->refcount.value -= 1;
02719   last_unref = (connection->refcount.value == 0);
02720 
02721 #if 0
02722   printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02723 #endif
02724   
02725   CONNECTION_UNLOCK (connection);
02726 #endif
02727   
02728   if (last_unref)
02729     {
02730 #ifndef DBUS_DISABLE_CHECKS
02731       if (_dbus_transport_get_is_connected (connection->transport))
02732         {
02733           _dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
02734                                    connection->shareable ?
02735                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02736                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02737           return;
02738         }
02739 #endif
02740       _dbus_connection_last_unref (connection);
02741     }
02742 }
02743 
02744 /*
02745  * Note that the transport can disconnect itself (other end drops us)
02746  * and in that case this function never runs. So this function must
02747  * not do anything more than disconnect the transport and update the
02748  * dispatch status.
02749  * 
02750  * If the transport self-disconnects, then we assume someone will
02751  * dispatch the connection to cause the dispatch status update.
02752  */
02753 static void
02754 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02755 {
02756   DBusDispatchStatus status;
02757 
02758   HAVE_LOCK_CHECK (connection);
02759   
02760   _dbus_verbose ("Disconnecting %p\n", connection);
02761 
02762   /* We need to ref because update_dispatch_status_and_unlock will unref
02763    * the connection if it was shared and libdbus was the only remaining
02764    * refcount holder.
02765    */
02766   _dbus_connection_ref_unlocked (connection);
02767   
02768   _dbus_transport_disconnect (connection->transport);
02769 
02770   /* This has the side effect of queuing the disconnect message link
02771    * (unless we don't have enough memory, possibly, so don't assert it).
02772    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02773    * should never again return the newly-disconnected connection.
02774    *
02775    * However, we only unref the shared connection and exit_on_disconnect when
02776    * the disconnect message reaches the head of the message queue,
02777    * NOT when it's first queued.
02778    */
02779   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02780 
02781   /* This calls out to user code */
02782   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02783 
02784   /* Could also call out to user code */
02785   dbus_connection_unref (connection);
02786 }
02787 
02830 void
02831 dbus_connection_close (DBusConnection *connection)
02832 {
02833   _dbus_return_if_fail (connection != NULL);
02834   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02835 
02836   CONNECTION_LOCK (connection);
02837 
02838 #ifndef DBUS_DISABLE_CHECKS
02839   if (connection->shareable)
02840     {
02841       CONNECTION_UNLOCK (connection);
02842 
02843       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02844       return;
02845     }
02846 #endif
02847   
02848   _dbus_connection_close_possibly_shared_and_unlock (connection);
02849 }
02850 
02851 static dbus_bool_t
02852 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02853 {
02854   HAVE_LOCK_CHECK (connection);
02855   return _dbus_transport_get_is_connected (connection->transport);
02856 }
02857 
02871 dbus_bool_t
02872 dbus_connection_get_is_connected (DBusConnection *connection)
02873 {
02874   dbus_bool_t res;
02875 
02876   _dbus_return_val_if_fail (connection != NULL, FALSE);
02877   
02878   CONNECTION_LOCK (connection);
02879   res = _dbus_connection_get_is_connected_unlocked (connection);
02880   CONNECTION_UNLOCK (connection);
02881   
02882   return res;
02883 }
02884 
02893 dbus_bool_t
02894 dbus_connection_get_is_authenticated (DBusConnection *connection)
02895 {
02896   dbus_bool_t res;
02897 
02898   _dbus_return_val_if_fail (connection != NULL, FALSE);
02899   
02900   CONNECTION_LOCK (connection);
02901   res = _dbus_transport_get_is_authenticated (connection->transport);
02902   CONNECTION_UNLOCK (connection);
02903   
02904   return res;
02905 }
02906 
02927 dbus_bool_t
02928 dbus_connection_get_is_anonymous (DBusConnection *connection)
02929 {
02930   dbus_bool_t res;
02931 
02932   _dbus_return_val_if_fail (connection != NULL, FALSE);
02933   
02934   CONNECTION_LOCK (connection);
02935   res = _dbus_transport_get_is_anonymous (connection->transport);
02936   CONNECTION_UNLOCK (connection);
02937   
02938   return res;
02939 }
02940 
02972 char*
02973 dbus_connection_get_server_id (DBusConnection *connection)
02974 {
02975   char *id;
02976 
02977   _dbus_return_val_if_fail (connection != NULL, NULL);
02978   
02979   CONNECTION_LOCK (connection);
02980   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
02981   CONNECTION_UNLOCK (connection);
02982   
02983   return id;
02984 }
02985 
02999 void
03000 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03001                                         dbus_bool_t     exit_on_disconnect)
03002 {
03003   _dbus_return_if_fail (connection != NULL);
03004 
03005   CONNECTION_LOCK (connection);
03006   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03007   CONNECTION_UNLOCK (connection);
03008 }
03009 
03019 DBusPreallocatedSend*
03020 dbus_connection_preallocate_send (DBusConnection *connection)
03021 {
03022   DBusPreallocatedSend *preallocated;
03023 
03024   _dbus_return_val_if_fail (connection != NULL, NULL);
03025 
03026   CONNECTION_LOCK (connection);
03027   
03028   preallocated =
03029     _dbus_connection_preallocate_send_unlocked (connection);
03030 
03031   CONNECTION_UNLOCK (connection);
03032 
03033   return preallocated;
03034 }
03035 
03045 void
03046 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03047                                         DBusPreallocatedSend *preallocated)
03048 {
03049   _dbus_return_if_fail (connection != NULL);
03050   _dbus_return_if_fail (preallocated != NULL);  
03051   _dbus_return_if_fail (connection == preallocated->connection);
03052 
03053   _dbus_list_free_link (preallocated->queue_link);
03054   _dbus_counter_unref (preallocated->counter_link->data);
03055   _dbus_list_free_link (preallocated->counter_link);
03056   dbus_free (preallocated);
03057 }
03058 
03071 void
03072 dbus_connection_send_preallocated (DBusConnection       *connection,
03073                                    DBusPreallocatedSend *preallocated,
03074                                    DBusMessage          *message,
03075                                    dbus_uint32_t        *client_serial)
03076 {
03077   _dbus_return_if_fail (connection != NULL);
03078   _dbus_return_if_fail (preallocated != NULL);
03079   _dbus_return_if_fail (message != NULL);
03080   _dbus_return_if_fail (preallocated->connection == connection);
03081   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03082                         dbus_message_get_member (message) != NULL);
03083   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03084                         (dbus_message_get_interface (message) != NULL &&
03085                          dbus_message_get_member (message) != NULL));
03086   
03087   CONNECTION_LOCK (connection);
03088   _dbus_connection_send_preallocated_and_unlock (connection,
03089                                                  preallocated,
03090                                                  message, client_serial);
03091 }
03092 
03093 static dbus_bool_t
03094 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03095                                           DBusMessage    *message,
03096                                           dbus_uint32_t  *client_serial)
03097 {
03098   DBusPreallocatedSend *preallocated;
03099 
03100   _dbus_assert (connection != NULL);
03101   _dbus_assert (message != NULL);
03102   
03103   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03104   if (preallocated == NULL)
03105     return FALSE;
03106 
03107   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03108                                                          preallocated,
03109                                                          message,
03110                                                          client_serial);
03111   return TRUE;
03112 }
03113 
03141 dbus_bool_t
03142 dbus_connection_send (DBusConnection *connection,
03143                       DBusMessage    *message,
03144                       dbus_uint32_t  *serial)
03145 {
03146   _dbus_return_val_if_fail (connection != NULL, FALSE);
03147   _dbus_return_val_if_fail (message != NULL, FALSE);
03148 
03149   CONNECTION_LOCK (connection);
03150 
03151   return _dbus_connection_send_and_unlock (connection,
03152                                            message,
03153                                            serial);
03154 }
03155 
03156 static dbus_bool_t
03157 reply_handler_timeout (void *data)
03158 {
03159   DBusConnection *connection;
03160   DBusDispatchStatus status;
03161   DBusPendingCall *pending = data;
03162 
03163   connection = _dbus_pending_call_get_connection_and_lock (pending);
03164 
03165   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03166                                                    connection);
03167   _dbus_connection_remove_timeout_unlocked (connection,
03168                                             _dbus_pending_call_get_timeout_unlocked (pending));
03169   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03170 
03171   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03172   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03173 
03174   /* Unlocks, and calls out to user code */
03175   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03176   
03177   return TRUE;
03178 }
03179 
03215 dbus_bool_t
03216 dbus_connection_send_with_reply (DBusConnection     *connection,
03217                                  DBusMessage        *message,
03218                                  DBusPendingCall   **pending_return,
03219                                  int                 timeout_milliseconds)
03220 {
03221   DBusPendingCall *pending;
03222   dbus_int32_t serial = -1;
03223   DBusDispatchStatus status;
03224 
03225   _dbus_return_val_if_fail (connection != NULL, FALSE);
03226   _dbus_return_val_if_fail (message != NULL, FALSE);
03227   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03228 
03229   if (pending_return)
03230     *pending_return = NULL;
03231 
03232   CONNECTION_LOCK (connection);
03233 
03234    if (!_dbus_connection_get_is_connected_unlocked (connection))
03235     {
03236       CONNECTION_UNLOCK (connection);
03237 
03238       return TRUE;
03239     }
03240 
03241   pending = _dbus_pending_call_new_unlocked (connection,
03242                                              timeout_milliseconds,
03243                                              reply_handler_timeout);
03244 
03245   if (pending == NULL)
03246     {
03247       CONNECTION_UNLOCK (connection);
03248       return FALSE;
03249     }
03250 
03251   /* Assign a serial to the message */
03252   serial = dbus_message_get_serial (message);
03253   if (serial == 0)
03254     {
03255       serial = _dbus_connection_get_next_client_serial (connection);
03256       dbus_message_set_serial (message, serial);
03257     }
03258 
03259   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03260     goto error;
03261     
03262   /* Insert the serial in the pending replies hash;
03263    * hash takes a refcount on DBusPendingCall.
03264    * Also, add the timeout.
03265    */
03266   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03267                                                       pending))
03268     goto error;
03269  
03270   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03271     {
03272       _dbus_connection_detach_pending_call_and_unlock (connection,
03273                                                        pending);
03274       goto error_unlocked;
03275     }
03276 
03277   if (pending_return)
03278     *pending_return = pending; /* hand off refcount */
03279   else
03280     {
03281       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03282       /* we still have a ref to the pending call in this case, we unref
03283        * after unlocking, below
03284        */
03285     }
03286 
03287   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03288 
03289   /* this calls out to user code */
03290   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03291 
03292   if (pending_return == NULL)
03293     dbus_pending_call_unref (pending);
03294   
03295   return TRUE;
03296 
03297  error:
03298   CONNECTION_UNLOCK (connection);
03299  error_unlocked:
03300   dbus_pending_call_unref (pending);
03301   return FALSE;
03302 }
03303 
03334 DBusMessage*
03335 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03336                                            DBusMessage        *message,
03337                                            int                 timeout_milliseconds,
03338                                            DBusError          *error)
03339 {
03340   DBusMessage *reply;
03341   DBusPendingCall *pending;
03342   
03343   _dbus_return_val_if_fail (connection != NULL, NULL);
03344   _dbus_return_val_if_fail (message != NULL, NULL);
03345   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03346   _dbus_return_val_if_error_is_set (error, NULL);
03347   
03348   if (!dbus_connection_send_with_reply (connection, message,
03349                                         &pending, timeout_milliseconds))
03350     {
03351       _DBUS_SET_OOM (error);
03352       return NULL;
03353     }
03354 
03355   if (pending == NULL)
03356     {
03357       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03358       return NULL;
03359     }
03360   
03361   dbus_pending_call_block (pending);
03362 
03363   reply = dbus_pending_call_steal_reply (pending);
03364   dbus_pending_call_unref (pending);
03365 
03366   /* call_complete_and_unlock() called from pending_call_block() should
03367    * always fill this in.
03368    */
03369   _dbus_assert (reply != NULL);
03370   
03371    if (dbus_set_error_from_message (error, reply))
03372     {
03373       dbus_message_unref (reply);
03374       return NULL;
03375     }
03376   else
03377     return reply;
03378 }
03379 
03388 static DBusDispatchStatus
03389 _dbus_connection_flush_unlocked (DBusConnection *connection)
03390 {
03391   /* We have to specify DBUS_ITERATION_DO_READING here because
03392    * otherwise we could have two apps deadlock if they are both doing
03393    * a flush(), and the kernel buffers fill up. This could change the
03394    * dispatch status.
03395    */
03396   DBusDispatchStatus status;
03397 
03398   HAVE_LOCK_CHECK (connection);
03399   
03400   while (connection->n_outgoing > 0 &&
03401          _dbus_connection_get_is_connected_unlocked (connection))
03402     {
03403       _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03404       HAVE_LOCK_CHECK (connection);
03405       _dbus_connection_do_iteration_unlocked (connection,
03406                                               DBUS_ITERATION_DO_READING |
03407                                               DBUS_ITERATION_DO_WRITING |
03408                                               DBUS_ITERATION_BLOCK,
03409                                               -1);
03410     }
03411 
03412   HAVE_LOCK_CHECK (connection);
03413   _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
03414   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03415 
03416   HAVE_LOCK_CHECK (connection);
03417   return status;
03418 }
03419 
03425 void
03426 dbus_connection_flush (DBusConnection *connection)
03427 {
03428   /* We have to specify DBUS_ITERATION_DO_READING here because
03429    * otherwise we could have two apps deadlock if they are both doing
03430    * a flush(), and the kernel buffers fill up. This could change the
03431    * dispatch status.
03432    */
03433   DBusDispatchStatus status;
03434 
03435   _dbus_return_if_fail (connection != NULL);
03436   
03437   CONNECTION_LOCK (connection);
03438 
03439   status = _dbus_connection_flush_unlocked (connection);
03440   
03441   HAVE_LOCK_CHECK (connection);
03442   /* Unlocks and calls out to user code */
03443   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03444 
03445   _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
03446 }
03447 
03458 static dbus_bool_t
03459 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03460                                      int             timeout_milliseconds, 
03461                                      dbus_bool_t     dispatch)
03462 {
03463   DBusDispatchStatus dstatus;
03464   dbus_bool_t progress_possible;
03465 
03466   /* Need to grab a ref here in case we're a private connection and
03467    * the user drops the last ref in a handler we call; see bug 
03468    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03469    */
03470   dbus_connection_ref (connection);
03471   dstatus = dbus_connection_get_dispatch_status (connection);
03472 
03473   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03474     {
03475       _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03476       dbus_connection_dispatch (connection);
03477       CONNECTION_LOCK (connection);
03478     }
03479   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03480     {
03481       _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03482       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03483       CONNECTION_LOCK (connection);
03484     }
03485   else
03486     {
03487       CONNECTION_LOCK (connection);
03488       if (_dbus_connection_get_is_connected_unlocked (connection))
03489         {
03490           _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03491           _dbus_connection_do_iteration_unlocked (connection,
03492                                                   DBUS_ITERATION_DO_READING |
03493                                                   DBUS_ITERATION_DO_WRITING |
03494                                                   DBUS_ITERATION_BLOCK,
03495                                                   timeout_milliseconds);
03496         }
03497     }
03498   
03499   HAVE_LOCK_CHECK (connection);
03500   /* If we can dispatch, we can make progress until the Disconnected message
03501    * has been processed; if we can only read/write, we can make progress
03502    * as long as the transport is open.
03503    */
03504   if (dispatch)
03505     progress_possible = connection->n_incoming != 0 ||
03506       connection->disconnect_message_link != NULL;
03507   else
03508     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03509 
03510   CONNECTION_UNLOCK (connection);
03511 
03512   dbus_connection_unref (connection);
03513 
03514   return progress_possible; /* TRUE if we can make more progress */
03515 }
03516 
03517 
03552 dbus_bool_t
03553 dbus_connection_read_write_dispatch (DBusConnection *connection,
03554                                      int             timeout_milliseconds)
03555 {
03556   _dbus_return_val_if_fail (connection != NULL, FALSE);
03557   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03558    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03559 }
03560 
03584 dbus_bool_t 
03585 dbus_connection_read_write (DBusConnection *connection, 
03586                             int             timeout_milliseconds) 
03587 { 
03588   _dbus_return_val_if_fail (connection != NULL, FALSE);
03589   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03590    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03591 }
03592 
03593 /* We need to call this anytime we pop the head of the queue, and then
03594  * update_dispatch_status_and_unlock needs to be called afterward
03595  * which will "process" the disconnected message and set
03596  * disconnected_message_processed.
03597  */
03598 static void
03599 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03600                                              DBusMessage    *head_of_queue)
03601 {
03602   HAVE_LOCK_CHECK (connection);
03603 
03604   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03605   if (connection->disconnect_message_link == NULL &&
03606       dbus_message_is_signal (head_of_queue,
03607                               DBUS_INTERFACE_LOCAL,
03608                               "Disconnected"))
03609     {
03610       connection->disconnected_message_arrived = TRUE;
03611     }
03612 }
03613 
03633 DBusMessage*
03634 dbus_connection_borrow_message (DBusConnection *connection)
03635 {
03636   DBusDispatchStatus status;
03637   DBusMessage *message;
03638 
03639   _dbus_return_val_if_fail (connection != NULL, NULL);
03640 
03641   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03642   
03643   /* this is called for the side effect that it queues
03644    * up any messages from the transport
03645    */
03646   status = dbus_connection_get_dispatch_status (connection);
03647   if (status != DBUS_DISPATCH_DATA_REMAINS)
03648     return NULL;
03649   
03650   CONNECTION_LOCK (connection);
03651 
03652   _dbus_connection_acquire_dispatch (connection);
03653 
03654   /* While a message is outstanding, the dispatch lock is held */
03655   _dbus_assert (connection->message_borrowed == NULL);
03656 
03657   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03658   
03659   message = connection->message_borrowed;
03660 
03661   check_disconnected_message_arrived_unlocked (connection, message);
03662   
03663   /* Note that we KEEP the dispatch lock until the message is returned */
03664   if (message == NULL)
03665     _dbus_connection_release_dispatch (connection);
03666 
03667   CONNECTION_UNLOCK (connection);
03668 
03669   /* We don't update dispatch status until it's returned or stolen */
03670   
03671   return message;
03672 }
03673 
03682 void
03683 dbus_connection_return_message (DBusConnection *connection,
03684                                 DBusMessage    *message)
03685 {
03686   DBusDispatchStatus status;
03687   
03688   _dbus_return_if_fail (connection != NULL);
03689   _dbus_return_if_fail (message != NULL);
03690   _dbus_return_if_fail (message == connection->message_borrowed);
03691   _dbus_return_if_fail (connection->dispatch_acquired);
03692   
03693   CONNECTION_LOCK (connection);
03694   
03695   _dbus_assert (message == connection->message_borrowed);
03696   
03697   connection->message_borrowed = NULL;
03698 
03699   _dbus_connection_release_dispatch (connection); 
03700 
03701   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03702   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03703 }
03704 
03714 void
03715 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03716                                         DBusMessage    *message)
03717 {
03718   DBusMessage *pop_message;
03719   DBusDispatchStatus status;
03720 
03721   _dbus_return_if_fail (connection != NULL);
03722   _dbus_return_if_fail (message != NULL);
03723   _dbus_return_if_fail (message == connection->message_borrowed);
03724   _dbus_return_if_fail (connection->dispatch_acquired);
03725   
03726   CONNECTION_LOCK (connection);
03727  
03728   _dbus_assert (message == connection->message_borrowed);
03729 
03730   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03731   _dbus_assert (message == pop_message);
03732   
03733   connection->n_incoming -= 1;
03734  
03735   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03736                  message, connection->n_incoming);
03737  
03738   connection->message_borrowed = NULL;
03739 
03740   _dbus_connection_release_dispatch (connection);
03741 
03742   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03743   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03744 }
03745 
03746 /* See dbus_connection_pop_message, but requires the caller to own
03747  * the lock before calling. May drop the lock while running.
03748  */
03749 static DBusList*
03750 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03751 {
03752   HAVE_LOCK_CHECK (connection);
03753   
03754   _dbus_assert (connection->message_borrowed == NULL);
03755   
03756   if (connection->n_incoming > 0)
03757     {
03758       DBusList *link;
03759 
03760       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03761       connection->n_incoming -= 1;
03762 
03763       _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03764                      link->data,
03765                      dbus_message_get_type (link->data),
03766                      dbus_message_get_path (link->data) ?
03767                      dbus_message_get_path (link->data) :
03768                      "no path",
03769                      dbus_message_get_interface (link->data) ?
03770                      dbus_message_get_interface (link->data) :
03771                      "no interface",
03772                      dbus_message_get_member (link->data) ?
03773                      dbus_message_get_member (link->data) :
03774                      "no member",
03775                      dbus_message_get_signature (link->data),
03776                      connection, connection->n_incoming);
03777 
03778       check_disconnected_message_arrived_unlocked (connection, link->data);
03779       
03780       return link;
03781     }
03782   else
03783     return NULL;
03784 }
03785 
03786 /* See dbus_connection_pop_message, but requires the caller to own
03787  * the lock before calling. May drop the lock while running.
03788  */
03789 static DBusMessage*
03790 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03791 {
03792   DBusList *link;
03793 
03794   HAVE_LOCK_CHECK (connection);
03795   
03796   link = _dbus_connection_pop_message_link_unlocked (connection);
03797 
03798   if (link != NULL)
03799     {
03800       DBusMessage *message;
03801       
03802       message = link->data;
03803       
03804       _dbus_list_free_link (link);
03805       
03806       return message;
03807     }
03808   else
03809     return NULL;
03810 }
03811 
03812 static void
03813 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03814                                                 DBusList       *message_link)
03815 {
03816   HAVE_LOCK_CHECK (connection);
03817   
03818   _dbus_assert (message_link != NULL);
03819   /* You can't borrow a message while a link is outstanding */
03820   _dbus_assert (connection->message_borrowed == NULL);
03821   /* We had to have the dispatch lock across the pop/putback */
03822   _dbus_assert (connection->dispatch_acquired);
03823 
03824   _dbus_list_prepend_link (&connection->incoming_messages,
03825                            message_link);
03826   connection->n_incoming += 1;
03827 
03828   _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03829                  message_link->data,
03830                  dbus_message_get_type (message_link->data),
03831                  dbus_message_get_interface (message_link->data) ?
03832                  dbus_message_get_interface (message_link->data) :
03833                  "no interface",
03834                  dbus_message_get_member (message_link->data) ?
03835                  dbus_message_get_member (message_link->data) :
03836                  "no member",
03837                  dbus_message_get_signature (message_link->data),
03838                  connection, connection->n_incoming);
03839 }
03840 
03860 DBusMessage*
03861 dbus_connection_pop_message (DBusConnection *connection)
03862 {
03863   DBusMessage *message;
03864   DBusDispatchStatus status;
03865 
03866   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03867   
03868   /* this is called for the side effect that it queues
03869    * up any messages from the transport
03870    */
03871   status = dbus_connection_get_dispatch_status (connection);
03872   if (status != DBUS_DISPATCH_DATA_REMAINS)
03873     return NULL;
03874   
03875   CONNECTION_LOCK (connection);
03876   _dbus_connection_acquire_dispatch (connection);
03877   HAVE_LOCK_CHECK (connection);
03878   
03879   message = _dbus_connection_pop_message_unlocked (connection);
03880 
03881   _dbus_verbose ("Returning popped message %p\n", message);    
03882 
03883   _dbus_connection_release_dispatch (connection);
03884 
03885   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03886   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03887   
03888   return message;
03889 }
03890 
03898 static void
03899 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03900 {
03901   HAVE_LOCK_CHECK (connection);
03902 
03903   _dbus_connection_ref_unlocked (connection);
03904   CONNECTION_UNLOCK (connection);
03905   
03906   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03907   _dbus_mutex_lock (connection->dispatch_mutex);
03908 
03909   while (connection->dispatch_acquired)
03910     {
03911       _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03912       _dbus_condvar_wait (connection->dispatch_cond, 
03913                           connection->dispatch_mutex);
03914     }
03915   
03916   _dbus_assert (!connection->dispatch_acquired);
03917 
03918   connection->dispatch_acquired = TRUE;
03919 
03920   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03921   _dbus_mutex_unlock (connection->dispatch_mutex);
03922   
03923   CONNECTION_LOCK (connection);
03924   _dbus_connection_unref_unlocked (connection);
03925 }
03926 
03934 static void
03935 _dbus_connection_release_dispatch (DBusConnection *connection)
03936 {
03937   HAVE_LOCK_CHECK (connection);
03938   
03939   _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03940   _dbus_mutex_lock (connection->dispatch_mutex);
03941   
03942   _dbus_assert (connection->dispatch_acquired);
03943 
03944   connection->dispatch_acquired = FALSE;
03945   _dbus_condvar_wake_one (connection->dispatch_cond);
03946 
03947   _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03948   _dbus_mutex_unlock (connection->dispatch_mutex);
03949 }
03950 
03951 static void
03952 _dbus_connection_failed_pop (DBusConnection *connection,
03953                              DBusList       *message_link)
03954 {
03955   _dbus_list_prepend_link (&connection->incoming_messages,
03956                            message_link);
03957   connection->n_incoming += 1;
03958 }
03959 
03960 /* Note this may be called multiple times since we don't track whether we already did it */
03961 static void
03962 notify_disconnected_unlocked (DBusConnection *connection)
03963 {
03964   HAVE_LOCK_CHECK (connection);
03965 
03966   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
03967    * connection from dbus_bus_get(). We make the same guarantee for
03968    * dbus_connection_open() but in a different way since we don't want to
03969    * unref right here; we instead check for connectedness before returning
03970    * the connection from the hash.
03971    */
03972   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
03973 
03974   /* Dump the outgoing queue, we aren't going to be able to
03975    * send it now, and we'd like accessors like
03976    * dbus_connection_get_outgoing_size() to be accurate.
03977    */
03978   if (connection->n_outgoing > 0)
03979     {
03980       DBusList *link;
03981       
03982       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03983                      connection->n_outgoing);
03984       
03985       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03986         {
03987           _dbus_connection_message_sent (connection, link->data);
03988         }
03989     } 
03990 }
03991 
03992 /* Note this may be called multiple times since we don't track whether we already did it */
03993 static DBusDispatchStatus
03994 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
03995 {
03996   HAVE_LOCK_CHECK (connection);
03997   
03998   if (connection->disconnect_message_link != NULL)
03999     {
04000       _dbus_verbose ("Sending disconnect message from %s\n",
04001                      _DBUS_FUNCTION_NAME);
04002       
04003       /* If we have pending calls, queue their timeouts - we want the Disconnected
04004        * to be the last message, after these timeouts.
04005        */
04006       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04007       
04008       /* We haven't sent the disconnect message already,
04009        * and all real messages have been queued up.
04010        */
04011       _dbus_connection_queue_synthesized_message_link (connection,
04012                                                        connection->disconnect_message_link);
04013       connection->disconnect_message_link = NULL;
04014 
04015       return DBUS_DISPATCH_DATA_REMAINS;
04016     }
04017 
04018   return DBUS_DISPATCH_COMPLETE;
04019 }
04020 
04021 static DBusDispatchStatus
04022 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04023 {
04024   HAVE_LOCK_CHECK (connection);
04025   
04026   if (connection->n_incoming > 0)
04027     return DBUS_DISPATCH_DATA_REMAINS;
04028   else if (!_dbus_transport_queue_messages (connection->transport))
04029     return DBUS_DISPATCH_NEED_MEMORY;
04030   else
04031     {
04032       DBusDispatchStatus status;
04033       dbus_bool_t is_connected;
04034       
04035       status = _dbus_transport_get_dispatch_status (connection->transport);
04036       is_connected = _dbus_transport_get_is_connected (connection->transport);
04037 
04038       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04039                      DISPATCH_STATUS_NAME (status), is_connected);
04040       
04041       if (!is_connected)
04042         {
04043           /* It's possible this would be better done by having an explicit
04044            * notification from _dbus_transport_disconnect() that would
04045            * synchronously do this, instead of waiting for the next dispatch
04046            * status check. However, probably not good to change until it causes
04047            * a problem.
04048            */
04049           notify_disconnected_unlocked (connection);
04050 
04051           /* I'm not sure this is needed; the idea is that we want to
04052            * queue the Disconnected only after we've read all the
04053            * messages, but if we're disconnected maybe we are guaranteed
04054            * to have read them all ?
04055            */
04056           if (status == DBUS_DISPATCH_COMPLETE)
04057             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04058         }
04059       
04060       if (status != DBUS_DISPATCH_COMPLETE)
04061         return status;
04062       else if (connection->n_incoming > 0)
04063         return DBUS_DISPATCH_DATA_REMAINS;
04064       else
04065         return DBUS_DISPATCH_COMPLETE;
04066     }
04067 }
04068 
04069 static void
04070 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04071                                                     DBusDispatchStatus new_status)
04072 {
04073   dbus_bool_t changed;
04074   DBusDispatchStatusFunction function;
04075   void *data;
04076 
04077   HAVE_LOCK_CHECK (connection);
04078 
04079   _dbus_connection_ref_unlocked (connection);
04080 
04081   changed = new_status != connection->last_dispatch_status;
04082 
04083   connection->last_dispatch_status = new_status;
04084 
04085   function = connection->dispatch_status_function;
04086   data = connection->dispatch_status_data;
04087 
04088   if (connection->disconnected_message_arrived &&
04089       !connection->disconnected_message_processed)
04090     {
04091       connection->disconnected_message_processed = TRUE;
04092       
04093       /* this does an unref, but we have a ref
04094        * so we should not run the finalizer here
04095        * inside the lock.
04096        */
04097       connection_forget_shared_unlocked (connection);
04098 
04099       if (connection->exit_on_disconnect)
04100         {
04101           CONNECTION_UNLOCK (connection);            
04102           
04103           _dbus_verbose ("Exiting on Disconnected signal\n");
04104           _dbus_exit (1);
04105           _dbus_assert_not_reached ("Call to exit() returned");
04106         }
04107     }
04108   
04109   /* We drop the lock */
04110   CONNECTION_UNLOCK (connection);
04111   
04112   if (changed && function)
04113     {
04114       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04115                      connection, new_status,
04116                      DISPATCH_STATUS_NAME (new_status));
04117       (* function) (connection, new_status, data);      
04118     }
04119   
04120   dbus_connection_unref (connection);
04121 }
04122 
04148 DBusDispatchStatus
04149 dbus_connection_get_dispatch_status (DBusConnection *connection)
04150 {
04151   DBusDispatchStatus status;
04152 
04153   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04154 
04155   _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
04156   
04157   CONNECTION_LOCK (connection);
04158 
04159   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04160   
04161   CONNECTION_UNLOCK (connection);
04162 
04163   return status;
04164 }
04165 
04169 static DBusHandlerResult
04170 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04171                                                  DBusMessage    *message)
04172 {
04173   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04174     {
04175       /* This means we're letting the bus route this message */
04176       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04177     }
04178   else if (dbus_message_is_method_call (message,
04179                                         DBUS_INTERFACE_PEER,
04180                                         "Ping"))
04181     {
04182       DBusMessage *ret;
04183       dbus_bool_t sent;
04184       
04185       ret = dbus_message_new_method_return (message);
04186       if (ret == NULL)
04187         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04188      
04189       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04190 
04191       dbus_message_unref (ret);
04192 
04193       if (!sent)
04194         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04195       
04196       return DBUS_HANDLER_RESULT_HANDLED;
04197     }
04198   else if (dbus_message_is_method_call (message,
04199                                         DBUS_INTERFACE_PEER,
04200                                         "GetMachineId"))
04201     {
04202       DBusMessage *ret;
04203       dbus_bool_t sent;
04204       DBusString uuid;
04205       
04206       ret = dbus_message_new_method_return (message);
04207       if (ret == NULL)
04208         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04209 
04210       sent = FALSE;
04211       _dbus_string_init (&uuid);
04212       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04213         {
04214           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04215           if (dbus_message_append_args (ret,
04216                                         DBUS_TYPE_STRING, &v_STRING,
04217                                         DBUS_TYPE_INVALID))
04218             {
04219               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04220             }
04221         }
04222       _dbus_string_free (&uuid);
04223       
04224       dbus_message_unref (ret);
04225 
04226       if (!sent)
04227         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04228       
04229       return DBUS_HANDLER_RESULT_HANDLED;
04230     }
04231   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04232     {
04233       /* We need to bounce anything else with this interface, otherwise apps
04234        * could start extending the interface and when we added extensions
04235        * here to DBusConnection we'd break those apps.
04236        */
04237       
04238       DBusMessage *ret;
04239       dbus_bool_t sent;
04240       
04241       ret = dbus_message_new_error (message,
04242                                     DBUS_ERROR_UNKNOWN_METHOD,
04243                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04244       if (ret == NULL)
04245         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04246       
04247       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04248       
04249       dbus_message_unref (ret);
04250       
04251       if (!sent)
04252         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04253       
04254       return DBUS_HANDLER_RESULT_HANDLED;
04255     }
04256   else
04257     {
04258       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04259     }
04260 }
04261 
04268 static DBusHandlerResult
04269 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04270                                                            DBusMessage    *message)
04271 {
04272   /* We just run one filter for now but have the option to run more
04273      if the spec calls for it in the future */
04274 
04275   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04276 }
04277 
04320 DBusDispatchStatus
04321 dbus_connection_dispatch (DBusConnection *connection)
04322 {
04323   DBusMessage *message;
04324   DBusList *link, *filter_list_copy, *message_link;
04325   DBusHandlerResult result;
04326   DBusPendingCall *pending;
04327   dbus_int32_t reply_serial;
04328   DBusDispatchStatus status;
04329 
04330   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04331 
04332   _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
04333   
04334   CONNECTION_LOCK (connection);
04335   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04336   if (status != DBUS_DISPATCH_DATA_REMAINS)
04337     {
04338       /* unlocks and calls out to user code */
04339       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04340       return status;
04341     }
04342   
04343   /* We need to ref the connection since the callback could potentially
04344    * drop the last ref to it
04345    */
04346   _dbus_connection_ref_unlocked (connection);
04347 
04348   _dbus_connection_acquire_dispatch (connection);
04349   HAVE_LOCK_CHECK (connection);
04350 
04351   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04352   if (message_link == NULL)
04353     {
04354       /* another thread dispatched our stuff */
04355 
04356       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04357       
04358       _dbus_connection_release_dispatch (connection);
04359 
04360       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04361 
04362       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04363       
04364       dbus_connection_unref (connection);
04365       
04366       return status;
04367     }
04368 
04369   message = message_link->data;
04370 
04371   _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
04372                  message,
04373                  dbus_message_get_type (message),
04374                  dbus_message_get_interface (message) ?
04375                  dbus_message_get_interface (message) :
04376                  "no interface",
04377                  dbus_message_get_member (message) ?
04378                  dbus_message_get_member (message) :
04379                  "no member",
04380                  dbus_message_get_signature (message));
04381 
04382   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04383   
04384   /* Pending call handling must be first, because if you do
04385    * dbus_connection_send_with_reply_and_block() or
04386    * dbus_pending_call_block() then no handlers/filters will be run on
04387    * the reply. We want consistent semantics in the case where we
04388    * dbus_connection_dispatch() the reply.
04389    */
04390   
04391   reply_serial = dbus_message_get_reply_serial (message);
04392   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04393                                          reply_serial);
04394   if (pending)
04395     {
04396       _dbus_verbose ("Dispatching a pending reply\n");
04397       complete_pending_call_and_unlock (connection, pending, message);
04398       pending = NULL; /* it's probably unref'd */
04399       
04400       CONNECTION_LOCK (connection);
04401       _dbus_verbose ("pending call completed in dispatch\n");
04402       result = DBUS_HANDLER_RESULT_HANDLED;
04403       goto out;
04404     }
04405 
04406   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04407   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04408     goto out;
04409  
04410   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04411     {
04412       _dbus_connection_release_dispatch (connection);
04413       HAVE_LOCK_CHECK (connection);
04414       
04415       _dbus_connection_failed_pop (connection, message_link);
04416 
04417       /* unlocks and calls user code */
04418       _dbus_connection_update_dispatch_status_and_unlock (connection,
04419                                                           DBUS_DISPATCH_NEED_MEMORY);
04420 
04421       if (pending)
04422         dbus_pending_call_unref (pending);
04423       dbus_connection_unref (connection);
04424       
04425       return DBUS_DISPATCH_NEED_MEMORY;
04426     }
04427   
04428   _dbus_list_foreach (&filter_list_copy,
04429                       (DBusForeachFunction)_dbus_message_filter_ref,
04430                       NULL);
04431 
04432   /* We're still protected from dispatch() reentrancy here
04433    * since we acquired the dispatcher
04434    */
04435   CONNECTION_UNLOCK (connection);
04436   
04437   link = _dbus_list_get_first_link (&filter_list_copy);
04438   while (link != NULL)
04439     {
04440       DBusMessageFilter *filter = link->data;
04441       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04442 
04443       if (filter->function == NULL)
04444         {
04445           _dbus_verbose ("  filter was removed in a callback function\n");
04446           link = next;
04447           continue;
04448         }
04449 
04450       _dbus_verbose ("  running filter on message %p\n", message);
04451       result = (* filter->function) (connection, message, filter->user_data);
04452 
04453       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04454         break;
04455 
04456       link = next;
04457     }
04458 
04459   _dbus_list_foreach (&filter_list_copy,
04460                       (DBusForeachFunction)_dbus_message_filter_unref,
04461                       NULL);
04462   _dbus_list_clear (&filter_list_copy);
04463   
04464   CONNECTION_LOCK (connection);
04465 
04466   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04467     {
04468       _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
04469       goto out;
04470     }
04471   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04472     {
04473       _dbus_verbose ("filter handled message in dispatch\n");
04474       goto out;
04475     }
04476 
04477   /* We're still protected from dispatch() reentrancy here
04478    * since we acquired the dispatcher
04479    */
04480   _dbus_verbose ("  running object path dispatch on message %p (%d %s %s '%s')\n",
04481                  message,
04482                  dbus_message_get_type (message),
04483                  dbus_message_get_interface (message) ?
04484                  dbus_message_get_interface (message) :
04485                  "no interface",
04486                  dbus_message_get_member (message) ?
04487                  dbus_message_get_member (message) :
04488                  "no member",
04489                  dbus_message_get_signature (message));
04490 
04491   HAVE_LOCK_CHECK (connection);
04492   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04493                                                   message);
04494   
04495   CONNECTION_LOCK (connection);
04496 
04497   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04498     {
04499       _dbus_verbose ("object tree handled message in dispatch\n");
04500       goto out;
04501     }
04502 
04503   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04504     {
04505       DBusMessage *reply;
04506       DBusString str;
04507       DBusPreallocatedSend *preallocated;
04508 
04509       _dbus_verbose ("  sending error %s\n",
04510                      DBUS_ERROR_UNKNOWN_METHOD);
04511       
04512       if (!_dbus_string_init (&str))
04513         {
04514           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04515           _dbus_verbose ("no memory for error string in dispatch\n");
04516           goto out;
04517         }
04518               
04519       if (!_dbus_string_append_printf (&str,
04520                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04521                                        dbus_message_get_member (message),
04522                                        dbus_message_get_signature (message),
04523                                        dbus_message_get_interface (message)))
04524         {
04525           _dbus_string_free (&str);
04526           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04527           _dbus_verbose ("no memory for error string in dispatch\n");
04528           goto out;
04529         }
04530       
04531       reply = dbus_message_new_error (message,
04532                                       DBUS_ERROR_UNKNOWN_METHOD,
04533                                       _dbus_string_get_const_data (&str));
04534       _dbus_string_free (&str);
04535 
04536       if (reply == NULL)
04537         {
04538           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04539           _dbus_verbose ("no memory for error reply in dispatch\n");
04540           goto out;
04541         }
04542       
04543       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04544 
04545       if (preallocated == NULL)
04546         {
04547           dbus_message_unref (reply);
04548           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04549           _dbus_verbose ("no memory for error send in dispatch\n");
04550           goto out;
04551         }
04552 
04553       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04554                                                              reply, NULL);
04555 
04556       dbus_message_unref (reply);
04557       
04558       result = DBUS_HANDLER_RESULT_HANDLED;
04559     }
04560   
04561   _dbus_verbose ("  done dispatching %p (%d %s %s '%s') on connection %p\n", message,
04562                  dbus_message_get_type (message),
04563                  dbus_message_get_interface (message) ?
04564                  dbus_message_get_interface (message) :
04565                  "no interface",
04566                  dbus_message_get_member (message) ?
04567                  dbus_message_get_member (message) :
04568                  "no member",
04569                  dbus_message_get_signature (message),
04570                  connection);
04571   
04572  out:
04573   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04574     {
04575       _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
04576       
04577       /* Put message back, and we'll start over.
04578        * Yes this means handlers must be idempotent if they
04579        * don't return HANDLED; c'est la vie.
04580        */
04581       _dbus_connection_putback_message_link_unlocked (connection,
04582                                                       message_link);
04583     }
04584   else
04585     {
04586       _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
04587       
04588       _dbus_list_free_link (message_link);
04589       dbus_message_unref (message); /* don't want the message to count in max message limits
04590                                      * in computing dispatch status below
04591                                      */
04592     }
04593   
04594   _dbus_connection_release_dispatch (connection);
04595   HAVE_LOCK_CHECK (connection);
04596 
04597   _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
04598   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04599 
04600   /* unlocks and calls user code */
04601   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04602   
04603   dbus_connection_unref (connection);
04604   
04605   return status;
04606 }
04607 
04667 dbus_bool_t
04668 dbus_connection_set_watch_functions (DBusConnection              *connection,
04669                                      DBusAddWatchFunction         add_function,
04670                                      DBusRemoveWatchFunction      remove_function,
04671                                      DBusWatchToggledFunction     toggled_function,
04672                                      void                        *data,
04673                                      DBusFreeFunction             free_data_function)
04674 {
04675   dbus_bool_t retval;
04676   DBusWatchList *watches;
04677 
04678   _dbus_return_val_if_fail (connection != NULL, FALSE);
04679   
04680   CONNECTION_LOCK (connection);
04681 
04682 #ifndef DBUS_DISABLE_CHECKS
04683   if (connection->watches == NULL)
04684     {
04685       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04686                                _DBUS_FUNCTION_NAME);
04687       return FALSE;
04688     }
04689 #endif
04690   
04691   /* ref connection for slightly better reentrancy */
04692   _dbus_connection_ref_unlocked (connection);
04693 
04694   /* This can call back into user code, and we need to drop the
04695    * connection lock when it does. This is kind of a lame
04696    * way to do it.
04697    */
04698   watches = connection->watches;
04699   connection->watches = NULL;
04700   CONNECTION_UNLOCK (connection);
04701 
04702   retval = _dbus_watch_list_set_functions (watches,
04703                                            add_function, remove_function,
04704                                            toggled_function,
04705                                            data, free_data_function);
04706   CONNECTION_LOCK (connection);
04707   connection->watches = watches;
04708   
04709   CONNECTION_UNLOCK (connection);
04710   /* drop our paranoid refcount */
04711   dbus_connection_unref (connection);
04712   
04713   return retval;
04714 }
04715 
04749 dbus_bool_t
04750 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04751                                          DBusAddTimeoutFunction     add_function,
04752                                          DBusRemoveTimeoutFunction  remove_function,
04753                                          DBusTimeoutToggledFunction toggled_function,
04754                                          void                      *data,
04755                                          DBusFreeFunction           free_data_function)
04756 {
04757   dbus_bool_t retval;
04758   DBusTimeoutList *timeouts;
04759 
04760   _dbus_return_val_if_fail (connection != NULL, FALSE);
04761   
04762   CONNECTION_LOCK (connection);
04763 
04764 #ifndef DBUS_DISABLE_CHECKS
04765   if (connection->timeouts == NULL)
04766     {
04767       _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n",
04768                                _DBUS_FUNCTION_NAME);
04769       return FALSE;
04770     }
04771 #endif
04772   
04773   /* ref connection for slightly better reentrancy */
04774   _dbus_connection_ref_unlocked (connection);
04775 
04776   timeouts = connection->timeouts;
04777   connection->timeouts = NULL;
04778   CONNECTION_UNLOCK (connection);
04779   
04780   retval = _dbus_timeout_list_set_functions (timeouts,
04781                                              add_function, remove_function,
04782                                              toggled_function,
04783                                              data, free_data_function);
04784   CONNECTION_LOCK (connection);
04785   connection->timeouts = timeouts;
04786   
04787   CONNECTION_UNLOCK (connection);
04788   /* drop our paranoid refcount */
04789   dbus_connection_unref (connection);
04790 
04791   return retval;
04792 }
04793 
04808 void
04809 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04810                                           DBusWakeupMainFunction     wakeup_main_function,
04811                                           void                      *data,
04812                                           DBusFreeFunction           free_data_function)
04813 {
04814   void *old_data;
04815   DBusFreeFunction old_free_data;
04816 
04817   _dbus_return_if_fail (connection != NULL);
04818   
04819   CONNECTION_LOCK (connection);
04820   old_data = connection->wakeup_main_data;
04821   old_free_data = connection->free_wakeup_main_data;
04822 
04823   connection->wakeup_main_function = wakeup_main_function;
04824   connection->wakeup_main_data = data;
04825   connection->free_wakeup_main_data = free_data_function;
04826   
04827   CONNECTION_UNLOCK (connection);
04828 
04829   /* Callback outside the lock */
04830   if (old_free_data)
04831     (*old_free_data) (old_data);
04832 }
04833 
04854 void
04855 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04856                                               DBusDispatchStatusFunction  function,
04857                                               void                       *data,
04858                                               DBusFreeFunction            free_data_function)
04859 {
04860   void *old_data;
04861   DBusFreeFunction old_free_data;
04862 
04863   _dbus_return_if_fail (connection != NULL);
04864   
04865   CONNECTION_LOCK (connection);
04866   old_data = connection->dispatch_status_data;
04867   old_free_data = connection->free_dispatch_status_data;
04868 
04869   connection->dispatch_status_function = function;
04870   connection->dispatch_status_data = data;
04871   connection->free_dispatch_status_data = free_data_function;
04872   
04873   CONNECTION_UNLOCK (connection);
04874 
04875   /* Callback outside the lock */
04876   if (old_free_data)
04877     (*old_free_data) (old_data);
04878 }
04879 
04899 dbus_bool_t
04900 dbus_connection_get_unix_fd (DBusConnection *connection,
04901                              int            *fd)
04902 {
04903   _dbus_return_val_if_fail (connection != NULL, FALSE);
04904   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04905 
04906 #ifdef DBUS_WIN
04907   /* FIXME do this on a lower level */
04908   return FALSE;
04909 #endif
04910   
04911   return dbus_connection_get_socket(connection, fd);
04912 }
04913 
04929 dbus_bool_t
04930 dbus_connection_get_socket(DBusConnection              *connection,
04931                            int                         *fd)
04932 {
04933   dbus_bool_t retval;
04934 
04935   _dbus_return_val_if_fail (connection != NULL, FALSE);
04936   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04937   
04938   CONNECTION_LOCK (connection);
04939   
04940   retval = _dbus_transport_get_socket_fd (connection->transport,
04941                                           fd);
04942 
04943   CONNECTION_UNLOCK (connection);
04944 
04945   return retval;
04946 }
04947 
04948 
04971 dbus_bool_t
04972 dbus_connection_get_unix_user (DBusConnection *connection,
04973                                unsigned long  *uid)
04974 {
04975   dbus_bool_t result;
04976 
04977   _dbus_return_val_if_fail (connection != NULL, FALSE);
04978   _dbus_return_val_if_fail (uid != NULL, FALSE);
04979   
04980   CONNECTION_LOCK (connection);
04981 
04982   if (!_dbus_transport_get_is_authenticated (connection->transport))
04983     result = FALSE;
04984   else
04985     result = _dbus_transport_get_unix_user (connection->transport,
04986                                             uid);
04987 
04988 #ifdef DBUS_WIN
04989   _dbus_assert (!result);
04990 #endif
04991   
04992   CONNECTION_UNLOCK (connection);
04993 
04994   return result;
04995 }
04996 
05007 dbus_bool_t
05008 dbus_connection_get_unix_process_id (DBusConnection *connection,
05009                                      unsigned long  *pid)
05010 {
05011   dbus_bool_t result;
05012 
05013   _dbus_return_val_if_fail (connection != NULL, FALSE);
05014   _dbus_return_val_if_fail (pid != NULL, FALSE);
05015   
05016   CONNECTION_LOCK (connection);
05017 
05018   if (!_dbus_transport_get_is_authenticated (connection->transport))
05019     result = FALSE;
05020   else
05021     result = _dbus_transport_get_unix_process_id (connection->transport,
05022                                                   pid);
05023 #ifdef DBUS_WIN
05024   _dbus_assert (!result);
05025 #endif
05026   
05027   CONNECTION_UNLOCK (connection);
05028 
05029   return result;
05030 }
05031 
05042 dbus_bool_t
05043 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05044                                             void          **data,
05045                                             dbus_int32_t   *data_size)
05046 {
05047   dbus_bool_t result;
05048 
05049   _dbus_return_val_if_fail (connection != NULL, FALSE);
05050   _dbus_return_val_if_fail (data != NULL, FALSE);
05051   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05052   
05053   CONNECTION_LOCK (connection);
05054 
05055   if (!_dbus_transport_get_is_authenticated (connection->transport))
05056     result = FALSE;
05057   else
05058     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05059                                                          data,
05060                                                          data_size);
05061   CONNECTION_UNLOCK (connection);
05062 
05063   return result;
05064 }
05065 
05088 void
05089 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05090                                         DBusAllowUnixUserFunction   function,
05091                                         void                       *data,
05092                                         DBusFreeFunction            free_data_function)
05093 {
05094   void *old_data = NULL;
05095   DBusFreeFunction old_free_function = NULL;
05096 
05097   _dbus_return_if_fail (connection != NULL);
05098   
05099   CONNECTION_LOCK (connection);
05100   _dbus_transport_set_unix_user_function (connection->transport,
05101                                           function, data, free_data_function,
05102                                           &old_data, &old_free_function);
05103   CONNECTION_UNLOCK (connection);
05104 
05105   if (old_free_function != NULL)
05106     (* old_free_function) (old_data);
05107 }
05108 
05140 dbus_bool_t
05141 dbus_connection_get_windows_user (DBusConnection             *connection,
05142                                   char                      **windows_sid_p)
05143 {
05144   dbus_bool_t result;
05145 
05146   _dbus_return_val_if_fail (connection != NULL, FALSE);
05147   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05148   
05149   CONNECTION_LOCK (connection);
05150 
05151   if (!_dbus_transport_get_is_authenticated (connection->transport))
05152     result = FALSE;
05153   else
05154     result = _dbus_transport_get_windows_user (connection->transport,
05155                                                windows_sid_p);
05156 
05157 #ifdef DBUS_UNIX
05158   _dbus_assert (!result);
05159 #endif
05160   
05161   CONNECTION_UNLOCK (connection);
05162 
05163   return result;
05164 }
05165 
05187 void
05188 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05189                                            DBusAllowWindowsUserFunction function,
05190                                            void                        *data,
05191                                            DBusFreeFunction             free_data_function)
05192 {
05193   void *old_data = NULL;
05194   DBusFreeFunction old_free_function = NULL;
05195 
05196   _dbus_return_if_fail (connection != NULL);
05197   
05198   CONNECTION_LOCK (connection);
05199   _dbus_transport_set_windows_user_function (connection->transport,
05200                                              function, data, free_data_function,
05201                                              &old_data, &old_free_function);
05202   CONNECTION_UNLOCK (connection);
05203 
05204   if (old_free_function != NULL)
05205     (* old_free_function) (old_data);
05206 }
05207 
05234 void
05235 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05236                                      dbus_bool_t                 value)
05237 {
05238   _dbus_return_if_fail (connection != NULL);
05239   
05240   CONNECTION_LOCK (connection);
05241   _dbus_transport_set_allow_anonymous (connection->transport, value);
05242   CONNECTION_UNLOCK (connection);
05243 }
05244 
05262 void
05263 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05264                                          dbus_bool_t                 value)
05265 {
05266   _dbus_return_if_fail (connection != NULL);
05267   
05268   CONNECTION_LOCK (connection);
05269   connection->route_peer_messages = TRUE;
05270   CONNECTION_UNLOCK (connection);
05271 }
05272 
05294 dbus_bool_t
05295 dbus_connection_add_filter (DBusConnection            *connection,
05296                             DBusHandleMessageFunction  function,
05297                             void                      *user_data,
05298                             DBusFreeFunction           free_data_function)
05299 {
05300   DBusMessageFilter *filter;
05301   
05302   _dbus_return_val_if_fail (connection != NULL, FALSE);
05303   _dbus_return_val_if_fail (function != NULL, FALSE);
05304 
05305   filter = dbus_new0 (DBusMessageFilter, 1);
05306   if (filter == NULL)
05307     return FALSE;
05308 
05309   filter->refcount.value = 1;
05310   
05311   CONNECTION_LOCK (connection);
05312 
05313   if (!_dbus_list_append (&connection->filter_list,
05314                           filter))
05315     {
05316       _dbus_message_filter_unref (filter);
05317       CONNECTION_UNLOCK (connection);
05318       return FALSE;
05319     }
05320 
05321   /* Fill in filter after all memory allocated,
05322    * so we don't run the free_user_data_function
05323    * if the add_filter() fails
05324    */
05325   
05326   filter->function = function;
05327   filter->user_data = user_data;
05328   filter->free_user_data_function = free_data_function;
05329         
05330   CONNECTION_UNLOCK (connection);
05331   return TRUE;
05332 }
05333 
05346 void
05347 dbus_connection_remove_filter (DBusConnection            *connection,
05348                                DBusHandleMessageFunction  function,
05349                                void                      *user_data)
05350 {
05351   DBusList *link;
05352   DBusMessageFilter *filter;
05353   
05354   _dbus_return_if_fail (connection != NULL);
05355   _dbus_return_if_fail (function != NULL);
05356   
05357   CONNECTION_LOCK (connection);
05358 
05359   filter = NULL;
05360   
05361   link = _dbus_list_get_last_link (&connection->filter_list);
05362   while (link != NULL)
05363     {
05364       filter = link->data;
05365 
05366       if (filter->function == function &&
05367           filter->user_data == user_data)
05368         {
05369           _dbus_list_remove_link (&connection->filter_list, link);
05370           filter->function = NULL;
05371           
05372           break;
05373         }
05374         
05375       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05376       filter = NULL;
05377     }
05378   
05379   CONNECTION_UNLOCK (connection);
05380 
05381 #ifndef DBUS_DISABLE_CHECKS
05382   if (filter == NULL)
05383     {
05384       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05385                                function, user_data);
05386       return;
05387     }
05388 #endif
05389   
05390   /* Call application code */
05391   if (filter->free_user_data_function)
05392     (* filter->free_user_data_function) (filter->user_data);
05393 
05394   filter->free_user_data_function = NULL;
05395   filter->user_data = NULL;
05396   
05397   _dbus_message_filter_unref (filter);
05398 }
05399 
05412 dbus_bool_t
05413 dbus_connection_try_register_object_path (DBusConnection              *connection,
05414                                           const char                  *path,
05415                                           const DBusObjectPathVTable  *vtable,
05416                                           void                        *user_data,
05417                                           DBusError                   *error)
05418 {
05419   char **decomposed_path;
05420   dbus_bool_t retval;
05421   
05422   _dbus_return_val_if_fail (connection != NULL, FALSE);
05423   _dbus_return_val_if_fail (path != NULL, FALSE);
05424   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05425   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05426 
05427   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05428     return FALSE;
05429 
05430   CONNECTION_LOCK (connection);
05431 
05432   retval = _dbus_object_tree_register (connection->objects,
05433                                        FALSE,
05434                                        (const char **) decomposed_path, vtable,
05435                                        user_data, error);
05436 
05437   CONNECTION_UNLOCK (connection);
05438 
05439   dbus_free_string_array (decomposed_path);
05440 
05441   return retval;
05442 }
05443 
05458 dbus_bool_t
05459 dbus_connection_register_object_path (DBusConnection              *connection,
05460                                       const char                  *path,
05461                                       const DBusObjectPathVTable  *vtable,
05462                                       void                        *user_data)
05463 {
05464   char **decomposed_path;
05465   dbus_bool_t retval;
05466   DBusError error = DBUS_ERROR_INIT;
05467 
05468   _dbus_return_val_if_fail (connection != NULL, FALSE);
05469   _dbus_return_val_if_fail (path != NULL, FALSE);
05470   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05471   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05472 
05473   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05474     return FALSE;
05475 
05476   CONNECTION_LOCK (connection);
05477 
05478   retval = _dbus_object_tree_register (connection->objects,
05479                                        FALSE,
05480                                        (const char **) decomposed_path, vtable,
05481                                        user_data, &error);
05482 
05483   CONNECTION_UNLOCK (connection);
05484 
05485   dbus_free_string_array (decomposed_path);
05486 
05487   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05488     {
05489       _dbus_warn ("%s\n", error.message);
05490       dbus_error_free (&error);
05491       return FALSE;
05492     }
05493 
05494   return retval;
05495 }
05496 
05511 dbus_bool_t
05512 dbus_connection_try_register_fallback (DBusConnection              *connection,
05513                                        const char                  *path,
05514                                        const DBusObjectPathVTable  *vtable,
05515                                        void                        *user_data,
05516                                        DBusError                   *error)
05517 {
05518   char **decomposed_path;
05519   dbus_bool_t retval;
05520 
05521   _dbus_return_val_if_fail (connection != NULL, FALSE);
05522   _dbus_return_val_if_fail (path != NULL, FALSE);
05523   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05524   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05525 
05526   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05527     return FALSE;
05528 
05529   CONNECTION_LOCK (connection);
05530 
05531   retval = _dbus_object_tree_register (connection->objects,
05532                                        TRUE,
05533                                        (const char **) decomposed_path, vtable,
05534                                        user_data, error);
05535 
05536   CONNECTION_UNLOCK (connection);
05537 
05538   dbus_free_string_array (decomposed_path);
05539 
05540   return retval;
05541 }
05542 
05559 dbus_bool_t
05560 dbus_connection_register_fallback (DBusConnection              *connection,
05561                                    const char                  *path,
05562                                    const DBusObjectPathVTable  *vtable,
05563                                    void                        *user_data)
05564 {
05565   char **decomposed_path;
05566   dbus_bool_t retval;
05567   DBusError error = DBUS_ERROR_INIT;
05568 
05569   _dbus_return_val_if_fail (connection != NULL, FALSE);
05570   _dbus_return_val_if_fail (path != NULL, FALSE);
05571   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05572   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05573 
05574   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05575     return FALSE;
05576 
05577   CONNECTION_LOCK (connection);
05578 
05579   retval = _dbus_object_tree_register (connection->objects,
05580                                        TRUE,
05581                                        (const char **) decomposed_path, vtable,
05582                                        user_data, &error);
05583 
05584   CONNECTION_UNLOCK (connection);
05585 
05586   dbus_free_string_array (decomposed_path);
05587 
05588   if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05589     {
05590       _dbus_warn ("%s\n", error.message);
05591       dbus_error_free (&error);
05592       return FALSE;
05593     }
05594 
05595   return retval;
05596 }
05597 
05607 dbus_bool_t
05608 dbus_connection_unregister_object_path (DBusConnection              *connection,
05609                                         const char                  *path)
05610 {
05611   char **decomposed_path;
05612 
05613   _dbus_return_val_if_fail (connection != NULL, FALSE);
05614   _dbus_return_val_if_fail (path != NULL, FALSE);
05615   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05616 
05617   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05618       return FALSE;
05619 
05620   CONNECTION_LOCK (connection);
05621 
05622   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05623 
05624   dbus_free_string_array (decomposed_path);
05625 
05626   return TRUE;
05627 }
05628 
05639 dbus_bool_t
05640 dbus_connection_get_object_path_data (DBusConnection *connection,
05641                                       const char     *path,
05642                                       void          **data_p)
05643 {
05644   char **decomposed_path;
05645 
05646   _dbus_return_val_if_fail (connection != NULL, FALSE);
05647   _dbus_return_val_if_fail (path != NULL, FALSE);
05648   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05649 
05650   *data_p = NULL;
05651   
05652   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05653     return FALSE;
05654   
05655   CONNECTION_LOCK (connection);
05656 
05657   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05658 
05659   CONNECTION_UNLOCK (connection);
05660 
05661   dbus_free_string_array (decomposed_path);
05662 
05663   return TRUE;
05664 }
05665 
05676 dbus_bool_t
05677 dbus_connection_list_registered (DBusConnection              *connection,
05678                                  const char                  *parent_path,
05679                                  char                      ***child_entries)
05680 {
05681   char **decomposed_path;
05682   dbus_bool_t retval;
05683   _dbus_return_val_if_fail (connection != NULL, FALSE);
05684   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05685   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05686   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05687 
05688   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05689     return FALSE;
05690 
05691   CONNECTION_LOCK (connection);
05692 
05693   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05694                                                          (const char **) decomposed_path,
05695                                                          child_entries);
05696   dbus_free_string_array (decomposed_path);
05697 
05698   return retval;
05699 }
05700 
05701 static DBusDataSlotAllocator slot_allocator;
05702 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05703 
05718 dbus_bool_t
05719 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05720 {
05721   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05722                                           &_DBUS_LOCK_NAME (connection_slots),
05723                                           slot_p);
05724 }
05725 
05737 void
05738 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05739 {
05740   _dbus_return_if_fail (*slot_p >= 0);
05741   
05742   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05743 }
05744 
05758 dbus_bool_t
05759 dbus_connection_set_data (DBusConnection   *connection,
05760                           dbus_int32_t      slot,
05761                           void             *data,
05762                           DBusFreeFunction  free_data_func)
05763 {
05764   DBusFreeFunction old_free_func;
05765   void *old_data;
05766   dbus_bool_t retval;
05767 
05768   _dbus_return_val_if_fail (connection != NULL, FALSE);
05769   _dbus_return_val_if_fail (slot >= 0, FALSE);
05770   
05771   CONNECTION_LOCK (connection);
05772 
05773   retval = _dbus_data_slot_list_set (&slot_allocator,
05774                                      &connection->slot_list,
05775                                      slot, data, free_data_func,
05776                                      &old_free_func, &old_data);
05777   
05778   CONNECTION_UNLOCK (connection);
05779 
05780   if (retval)
05781     {
05782       /* Do the actual free outside the connection lock */
05783       if (old_free_func)
05784         (* old_free_func) (old_data);
05785     }
05786 
05787   return retval;
05788 }
05789 
05798 void*
05799 dbus_connection_get_data (DBusConnection   *connection,
05800                           dbus_int32_t      slot)
05801 {
05802   void *res;
05803 
05804   _dbus_return_val_if_fail (connection != NULL, NULL);
05805   
05806   CONNECTION_LOCK (connection);
05807 
05808   res = _dbus_data_slot_list_get (&slot_allocator,
05809                                   &connection->slot_list,
05810                                   slot);
05811   
05812   CONNECTION_UNLOCK (connection);
05813 
05814   return res;
05815 }
05816 
05823 void
05824 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05825 {  
05826   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05827 }
05828 
05837 void
05838 dbus_connection_set_max_message_size (DBusConnection *connection,
05839                                       long            size)
05840 {
05841   _dbus_return_if_fail (connection != NULL);
05842   
05843   CONNECTION_LOCK (connection);
05844   _dbus_transport_set_max_message_size (connection->transport,
05845                                         size);
05846   CONNECTION_UNLOCK (connection);
05847 }
05848 
05855 long
05856 dbus_connection_get_max_message_size (DBusConnection *connection)
05857 {
05858   long res;
05859 
05860   _dbus_return_val_if_fail (connection != NULL, 0);
05861   
05862   CONNECTION_LOCK (connection);
05863   res = _dbus_transport_get_max_message_size (connection->transport);
05864   CONNECTION_UNLOCK (connection);
05865   return res;
05866 }
05867 
05893 void
05894 dbus_connection_set_max_received_size (DBusConnection *connection,
05895                                        long            size)
05896 {
05897   _dbus_return_if_fail (connection != NULL);
05898   
05899   CONNECTION_LOCK (connection);
05900   _dbus_transport_set_max_received_size (connection->transport,
05901                                          size);
05902   CONNECTION_UNLOCK (connection);
05903 }
05904 
05911 long
05912 dbus_connection_get_max_received_size (DBusConnection *connection)
05913 {
05914   long res;
05915 
05916   _dbus_return_val_if_fail (connection != NULL, 0);
05917   
05918   CONNECTION_LOCK (connection);
05919   res = _dbus_transport_get_max_received_size (connection->transport);
05920   CONNECTION_UNLOCK (connection);
05921   return res;
05922 }
05923 
05934 long
05935 dbus_connection_get_outgoing_size (DBusConnection *connection)
05936 {
05937   long res;
05938 
05939   _dbus_return_val_if_fail (connection != NULL, 0);
05940   
05941   CONNECTION_LOCK (connection);
05942   res = _dbus_counter_get_value (connection->outgoing_counter);
05943   CONNECTION_UNLOCK (connection);
05944   return res;
05945 }
05946