D-Bus  1.4.18
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-message-private.h"
00037 #include "dbus-threads.h"
00038 #include "dbus-protocol.h"
00039 #include "dbus-dataslot.h"
00040 #include "dbus-string.h"
00041 #include "dbus-pending-call.h"
00042 #include "dbus-object-tree.h"
00043 #include "dbus-threads-internal.h"
00044 #include "dbus-bus.h"
00045 #include "dbus-marshal-basic.h"
00046 
00047 #ifdef DBUS_DISABLE_CHECKS
00048 #define TOOK_LOCK_CHECK(connection)
00049 #define RELEASING_LOCK_CHECK(connection)
00050 #define HAVE_LOCK_CHECK(connection)
00051 #else
00052 #define TOOK_LOCK_CHECK(connection) do {                \
00053     _dbus_assert (!(connection)->have_connection_lock); \
00054     (connection)->have_connection_lock = TRUE;          \
00055   } while (0)
00056 #define RELEASING_LOCK_CHECK(connection) do {            \
00057     _dbus_assert ((connection)->have_connection_lock);   \
00058     (connection)->have_connection_lock = FALSE;          \
00059   } while (0)
00060 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00061 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00062 #endif
00063 
00064 #define TRACE_LOCKS 1
00065 
00066 #define CONNECTION_LOCK(connection)   do {                                      \
00067     if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); }   \
00068     _dbus_mutex_lock ((connection)->mutex);                                      \
00069     TOOK_LOCK_CHECK (connection);                                               \
00070   } while (0)
00071 
00072 #define CONNECTION_UNLOCK(connection) do {                                              \
00073     if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n");  }        \
00074     RELEASING_LOCK_CHECK (connection);                                                  \
00075     _dbus_mutex_unlock ((connection)->mutex);                                            \
00076   } while (0)
00077 
00078 #define SLOTS_LOCK(connection) do {                     \
00079     _dbus_mutex_lock ((connection)->slot_mutex);        \
00080   } while (0)
00081 
00082 #define SLOTS_UNLOCK(connection) do {                   \
00083     _dbus_mutex_unlock ((connection)->slot_mutex);      \
00084   } while (0)
00085 
00086 #define DISPATCH_STATUS_NAME(s)                                            \
00087                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00088                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00089                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00090                       "???")
00091 
00212 typedef struct DBusMessageFilter DBusMessageFilter;
00213 
00217 struct DBusMessageFilter
00218 {
00219   DBusAtomic refcount; 
00220   DBusHandleMessageFunction function; 
00221   void *user_data; 
00222   DBusFreeFunction free_user_data_function; 
00223 };
00224 
00225 
00229 struct DBusPreallocatedSend
00230 {
00231   DBusConnection *connection; 
00232   DBusList *queue_link;       
00233   DBusList *counter_link;     
00234 };
00235 
00236 #if HAVE_DECL_MSG_NOSIGNAL
00237 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00238 #else
00239 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00240 #endif
00241 
00245 struct DBusConnection
00246 {
00247   DBusAtomic refcount; 
00249   DBusMutex *mutex; 
00251   DBusMutex *dispatch_mutex;     
00252   DBusCondVar *dispatch_cond;    
00253   DBusMutex *io_path_mutex;      
00254   DBusCondVar *io_path_cond;     
00256   DBusList *outgoing_messages; 
00257   DBusList *incoming_messages; 
00259   DBusMessage *message_borrowed; 
00263   int n_outgoing;              
00264   int n_incoming;              
00266   DBusCounter *outgoing_counter; 
00268   DBusTransport *transport;    
00269   DBusWatchList *watches;      
00270   DBusTimeoutList *timeouts;   
00272   DBusList *filter_list;        
00274   DBusMutex *slot_mutex;        
00275   DBusDataSlotList slot_list;   
00277   DBusHashTable *pending_replies;  
00279   dbus_uint32_t client_serial;       
00280   DBusList *disconnect_message_link; 
00282   DBusWakeupMainFunction wakeup_main_function; 
00283   void *wakeup_main_data; 
00284   DBusFreeFunction free_wakeup_main_data; 
00286   DBusDispatchStatusFunction dispatch_status_function; 
00287   void *dispatch_status_data; 
00288   DBusFreeFunction free_dispatch_status_data; 
00290   DBusDispatchStatus last_dispatch_status; 
00292   DBusList *link_cache; 
00295   DBusObjectTree *objects; 
00297   char *server_guid; 
00299   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00300    * from connection->mutex and all bitfields in a word have to be read/written together.
00301    * So you can't have a different lock for different bitfields in the same word.
00302    */
00303   dbus_bool_t dispatch_acquired; 
00304   dbus_bool_t io_path_acquired;  
00306   unsigned int shareable : 1; 
00308   unsigned int exit_on_disconnect : 1; 
00310   unsigned int route_peer_messages : 1; 
00312   unsigned int disconnected_message_arrived : 1;   
00316   unsigned int disconnected_message_processed : 1; 
00320 #ifndef DBUS_DISABLE_CHECKS
00321   unsigned int have_connection_lock : 1; 
00322 #endif
00323   
00324 #ifndef DBUS_DISABLE_CHECKS
00325   int generation; 
00326 #endif 
00327 };
00328 
00329 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00330 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00331                                                                               DBusDispatchStatus  new_status);
00332 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00333 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00334 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00335 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00336 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00337 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00338 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
00339                                                                               dbus_uint32_t       client_serial);
00340 
00341 static DBusMessageFilter *
00342 _dbus_message_filter_ref (DBusMessageFilter *filter)
00343 {
00344 #ifdef DBUS_DISABLE_ASSERT
00345   _dbus_atomic_inc (&filter->refcount);
00346 #else
00347   dbus_int32_t old_value;
00348 
00349   old_value = _dbus_atomic_inc (&filter->refcount);
00350   _dbus_assert (old_value > 0);
00351 #endif
00352 
00353   return filter;
00354 }
00355 
00356 static void
00357 _dbus_message_filter_unref (DBusMessageFilter *filter)
00358 {
00359   dbus_int32_t old_value;
00360 
00361   old_value = _dbus_atomic_dec (&filter->refcount);
00362   _dbus_assert (old_value > 0);
00363 
00364   if (old_value == 1)
00365     {
00366       if (filter->free_user_data_function)
00367         (* filter->free_user_data_function) (filter->user_data);
00368       
00369       dbus_free (filter);
00370     }
00371 }
00372 
00378 void
00379 _dbus_connection_lock (DBusConnection *connection)
00380 {
00381   CONNECTION_LOCK (connection);
00382 }
00383 
00389 void
00390 _dbus_connection_unlock (DBusConnection *connection)
00391 {
00392   CONNECTION_UNLOCK (connection);
00393 }
00394 
00402 static void
00403 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00404 {
00405   if (connection->wakeup_main_function)
00406     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00407 }
00408 
00409 #ifdef DBUS_BUILD_TESTS
00410 /* For now this function isn't used */
00420 dbus_bool_t
00421 _dbus_connection_queue_received_message (DBusConnection *connection,
00422                                          DBusMessage    *message)
00423 {
00424   DBusList *link;
00425 
00426   link = _dbus_list_alloc_link (message);
00427   if (link == NULL)
00428     return FALSE;
00429 
00430   dbus_message_ref (message);
00431   _dbus_connection_queue_received_message_link (connection, link);
00432 
00433   return TRUE;
00434 }
00435 
00448 void 
00449 _dbus_connection_test_get_locks (DBusConnection *connection,
00450                                  DBusMutex     **mutex_loc,
00451                                  DBusMutex     **dispatch_mutex_loc,
00452                                  DBusMutex     **io_path_mutex_loc,
00453                                  DBusCondVar   **dispatch_cond_loc,
00454                                  DBusCondVar   **io_path_cond_loc)
00455 {
00456   *mutex_loc = connection->mutex;
00457   *dispatch_mutex_loc = connection->dispatch_mutex;
00458   *io_path_mutex_loc = connection->io_path_mutex; 
00459   *dispatch_cond_loc = connection->dispatch_cond;
00460   *io_path_cond_loc = connection->io_path_cond;
00461 }
00462 #endif
00463 
00472 void
00473 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00474                                               DBusList        *link)
00475 {
00476   DBusPendingCall *pending;
00477   dbus_uint32_t reply_serial;
00478   DBusMessage *message;
00479   
00480   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00481   
00482   _dbus_list_append_link (&connection->incoming_messages,
00483                           link);
00484   message = link->data;
00485 
00486   /* If this is a reply we're waiting on, remove timeout for it */
00487   reply_serial = dbus_message_get_reply_serial (message);
00488   if (reply_serial != 0)
00489     {
00490       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00491                                              reply_serial);
00492       if (pending != NULL)
00493         {
00494           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00495             _dbus_connection_remove_timeout_unlocked (connection,
00496                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00497 
00498           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00499         }
00500     }
00501   
00502   
00503 
00504   connection->n_incoming += 1;
00505 
00506   _dbus_connection_wakeup_mainloop (connection);
00507   
00508   _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00509                  message,
00510                  dbus_message_type_to_string (dbus_message_get_type (message)),
00511                  dbus_message_get_path (message) ?
00512                  dbus_message_get_path (message) :
00513                  "no path",
00514                  dbus_message_get_interface (message) ?
00515                  dbus_message_get_interface (message) :
00516                  "no interface",
00517                  dbus_message_get_member (message) ?
00518                  dbus_message_get_member (message) :
00519                  "no member",
00520                  dbus_message_get_signature (message),
00521                  dbus_message_get_reply_serial (message),
00522                  connection,
00523                  connection->n_incoming);}
00524 
00533 void
00534 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00535                                                  DBusList *link)
00536 {
00537   HAVE_LOCK_CHECK (connection);
00538   
00539   _dbus_list_append_link (&connection->incoming_messages, link);
00540 
00541   connection->n_incoming += 1;
00542 
00543   _dbus_connection_wakeup_mainloop (connection);
00544   
00545   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00546                  link->data, connection, connection->n_incoming);
00547 }
00548 
00549 
00557 dbus_bool_t
00558 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00559 {
00560   HAVE_LOCK_CHECK (connection);
00561   return connection->outgoing_messages != NULL;
00562 }
00563 
00573 dbus_bool_t
00574 dbus_connection_has_messages_to_send (DBusConnection *connection)
00575 {
00576   dbus_bool_t v;
00577   
00578   _dbus_return_val_if_fail (connection != NULL, FALSE);
00579 
00580   CONNECTION_LOCK (connection);
00581   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00582   CONNECTION_UNLOCK (connection);
00583 
00584   return v;
00585 }
00586 
00594 DBusMessage*
00595 _dbus_connection_get_message_to_send (DBusConnection *connection)
00596 {
00597   HAVE_LOCK_CHECK (connection);
00598   
00599   return _dbus_list_get_last (&connection->outgoing_messages);
00600 }
00601 
00610 void
00611 _dbus_connection_message_sent (DBusConnection *connection,
00612                                DBusMessage    *message)
00613 {
00614   DBusList *link;
00615 
00616   HAVE_LOCK_CHECK (connection);
00617   
00618   /* This can be called before we even complete authentication, since
00619    * it's called on disconnect to clean up the outgoing queue.
00620    * It's also called as we successfully send each message.
00621    */
00622   
00623   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00624   _dbus_assert (link != NULL);
00625   _dbus_assert (link->data == message);
00626 
00627   /* Save this link in the link cache */
00628   _dbus_list_unlink (&connection->outgoing_messages,
00629                      link);
00630   _dbus_list_prepend_link (&connection->link_cache, link);
00631   
00632   connection->n_outgoing -= 1;
00633 
00634   _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00635                  message,
00636                  dbus_message_type_to_string (dbus_message_get_type (message)),
00637                  dbus_message_get_path (message) ?
00638                  dbus_message_get_path (message) :
00639                  "no path",
00640                  dbus_message_get_interface (message) ?
00641                  dbus_message_get_interface (message) :
00642                  "no interface",
00643                  dbus_message_get_member (message) ?
00644                  dbus_message_get_member (message) :
00645                  "no member",
00646                  dbus_message_get_signature (message),
00647                  connection, connection->n_outgoing);
00648 
00649   /* Save this link in the link cache also */
00650   _dbus_message_remove_counter (message, connection->outgoing_counter,
00651                                 &link);
00652   _dbus_list_prepend_link (&connection->link_cache, link);
00653   
00654   dbus_message_unref (message);
00655 }
00656 
00658 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00659                                                   DBusWatch     *watch);
00661 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00662                                                   DBusWatch     *watch);
00664 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00665                                                   DBusWatch     *watch,
00666                                                   dbus_bool_t    enabled);
00667 
00668 static dbus_bool_t
00669 protected_change_watch (DBusConnection         *connection,
00670                         DBusWatch              *watch,
00671                         DBusWatchAddFunction    add_function,
00672                         DBusWatchRemoveFunction remove_function,
00673                         DBusWatchToggleFunction toggle_function,
00674                         dbus_bool_t             enabled)
00675 {
00676   dbus_bool_t retval;
00677 
00678   HAVE_LOCK_CHECK (connection);
00679 
00680   /* The original purpose of protected_change_watch() was to hold a
00681    * ref on the connection while dropping the connection lock, then
00682    * calling out to the app.  This was a broken hack that did not
00683    * work, since the connection was in a hosed state (no WatchList
00684    * field) while calling out.
00685    *
00686    * So for now we'll just keep the lock while calling out. This means
00687    * apps are not allowed to call DBusConnection methods inside a
00688    * watch function or they will deadlock.
00689    *
00690    * The "real fix" is to use the _and_unlock() pattern found
00691    * elsewhere in the code, to defer calling out to the app until
00692    * we're about to drop locks and return flow of control to the app
00693    * anyway.
00694    *
00695    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00696    */
00697 
00698   if (connection->watches)
00699     {
00700       if (add_function)
00701         retval = (* add_function) (connection->watches, watch);
00702       else if (remove_function)
00703         {
00704           retval = TRUE;
00705           (* remove_function) (connection->watches, watch);
00706         }
00707       else
00708         {
00709           retval = TRUE;
00710           (* toggle_function) (connection->watches, watch, enabled);
00711         }
00712       return retval;
00713     }
00714   else
00715     return FALSE;
00716 }
00717      
00718 
00730 dbus_bool_t
00731 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00732                                      DBusWatch      *watch)
00733 {
00734   return protected_change_watch (connection, watch,
00735                                  _dbus_watch_list_add_watch,
00736                                  NULL, NULL, FALSE);
00737 }
00738 
00748 void
00749 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00750                                         DBusWatch      *watch)
00751 {
00752   protected_change_watch (connection, watch,
00753                           NULL,
00754                           _dbus_watch_list_remove_watch,
00755                           NULL, FALSE);
00756 }
00757 
00768 void
00769 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00770                                         DBusWatch      *watch,
00771                                         dbus_bool_t     enabled)
00772 {
00773   _dbus_assert (watch != NULL);
00774 
00775   protected_change_watch (connection, watch,
00776                           NULL, NULL,
00777                           _dbus_watch_list_toggle_watch,
00778                           enabled);
00779 }
00780 
00782 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00783                                                    DBusTimeout     *timeout);
00785 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00786                                                    DBusTimeout     *timeout);
00788 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00789                                                    DBusTimeout     *timeout,
00790                                                    dbus_bool_t      enabled);
00791 
00792 static dbus_bool_t
00793 protected_change_timeout (DBusConnection           *connection,
00794                           DBusTimeout              *timeout,
00795                           DBusTimeoutAddFunction    add_function,
00796                           DBusTimeoutRemoveFunction remove_function,
00797                           DBusTimeoutToggleFunction toggle_function,
00798                           dbus_bool_t               enabled)
00799 {
00800   dbus_bool_t retval;
00801 
00802   HAVE_LOCK_CHECK (connection);
00803 
00804   /* The original purpose of protected_change_timeout() was to hold a
00805    * ref on the connection while dropping the connection lock, then
00806    * calling out to the app.  This was a broken hack that did not
00807    * work, since the connection was in a hosed state (no TimeoutList
00808    * field) while calling out.
00809    *
00810    * So for now we'll just keep the lock while calling out. This means
00811    * apps are not allowed to call DBusConnection methods inside a
00812    * timeout function or they will deadlock.
00813    *
00814    * The "real fix" is to use the _and_unlock() pattern found
00815    * elsewhere in the code, to defer calling out to the app until
00816    * we're about to drop locks and return flow of control to the app
00817    * anyway.
00818    *
00819    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00820    */
00821 
00822   if (connection->timeouts)
00823     {
00824       if (add_function)
00825         retval = (* add_function) (connection->timeouts, timeout);
00826       else if (remove_function)
00827         {
00828           retval = TRUE;
00829           (* remove_function) (connection->timeouts, timeout);
00830         }
00831       else
00832         {
00833           retval = TRUE;
00834           (* toggle_function) (connection->timeouts, timeout, enabled);
00835         }
00836       return retval;
00837     }
00838   else
00839     return FALSE;
00840 }
00841 
00854 dbus_bool_t
00855 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00856                                        DBusTimeout    *timeout)
00857 {
00858   return protected_change_timeout (connection, timeout,
00859                                    _dbus_timeout_list_add_timeout,
00860                                    NULL, NULL, FALSE);
00861 }
00862 
00872 void
00873 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00874                                           DBusTimeout    *timeout)
00875 {
00876   protected_change_timeout (connection, timeout,
00877                             NULL,
00878                             _dbus_timeout_list_remove_timeout,
00879                             NULL, FALSE);
00880 }
00881 
00892 void
00893 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00894                                           DBusTimeout      *timeout,
00895                                           dbus_bool_t       enabled)
00896 {
00897   protected_change_timeout (connection, timeout,
00898                             NULL, NULL,
00899                             _dbus_timeout_list_toggle_timeout,
00900                             enabled);
00901 }
00902 
00903 static dbus_bool_t
00904 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00905                                                DBusPendingCall *pending)
00906 {
00907   dbus_uint32_t reply_serial;
00908   DBusTimeout *timeout;
00909 
00910   HAVE_LOCK_CHECK (connection);
00911 
00912   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00913 
00914   _dbus_assert (reply_serial != 0);
00915 
00916   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00917 
00918   if (timeout)
00919     {
00920       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00921         return FALSE;
00922       
00923       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00924                                         reply_serial,
00925                                         pending))
00926         {
00927           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00928 
00929           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00930           HAVE_LOCK_CHECK (connection);
00931           return FALSE;
00932         }
00933       
00934       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00935     }
00936   else
00937     {
00938       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00939                                         reply_serial,
00940                                         pending))
00941         {
00942           HAVE_LOCK_CHECK (connection);
00943           return FALSE;
00944         }
00945     }
00946 
00947   _dbus_pending_call_ref_unlocked (pending);
00948 
00949   HAVE_LOCK_CHECK (connection);
00950   
00951   return TRUE;
00952 }
00953 
00954 static void
00955 free_pending_call_on_hash_removal (void *data)
00956 {
00957   DBusPendingCall *pending;
00958   DBusConnection  *connection;
00959   
00960   if (data == NULL)
00961     return;
00962 
00963   pending = data;
00964 
00965   connection = _dbus_pending_call_get_connection_unlocked (pending);
00966 
00967   HAVE_LOCK_CHECK (connection);
00968   
00969   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00970     {
00971       _dbus_connection_remove_timeout_unlocked (connection,
00972                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00973       
00974       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00975     }
00976 
00977   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00978    * here, but the pending call finalizer could in principle call out to 
00979    * application code so we pretty much have to... some larger code reorg 
00980    * might be needed.
00981    */
00982   _dbus_connection_ref_unlocked (connection);
00983   _dbus_pending_call_unref_and_unlock (pending);
00984   CONNECTION_LOCK (connection);
00985   _dbus_connection_unref_unlocked (connection);
00986 }
00987 
00988 static void
00989 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
00990                                                DBusPendingCall *pending)
00991 {
00992   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
00993    * say the least.
00994    */
00995   _dbus_hash_table_remove_int (connection->pending_replies,
00996                                _dbus_pending_call_get_reply_serial_unlocked (pending));
00997 }
00998 
00999 static void
01000 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
01001                                                  DBusPendingCall *pending)
01002 {
01003   /* The idea here is to avoid finalizing the pending call
01004    * with the lock held, since there's a destroy notifier
01005    * in pending call that goes out to application code.
01006    *
01007    * There's an extra unlock inside the hash table
01008    * "free pending call" function FIXME...
01009    */
01010   _dbus_pending_call_ref_unlocked (pending);
01011   _dbus_hash_table_remove_int (connection->pending_replies,
01012                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01013 
01014   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01015       _dbus_connection_remove_timeout_unlocked (connection,
01016               _dbus_pending_call_get_timeout_unlocked (pending));
01017 
01018   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01019 
01020   _dbus_pending_call_unref_and_unlock (pending);
01021 }
01022 
01031 void
01032 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01033                                       DBusPendingCall *pending)
01034 {
01035   CONNECTION_LOCK (connection);
01036   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01037 }
01038 
01048 static dbus_bool_t
01049 _dbus_connection_acquire_io_path (DBusConnection *connection,
01050                                   int             timeout_milliseconds)
01051 {
01052   dbus_bool_t we_acquired;
01053   
01054   HAVE_LOCK_CHECK (connection);
01055 
01056   /* We don't want the connection to vanish */
01057   _dbus_connection_ref_unlocked (connection);
01058 
01059   /* We will only touch io_path_acquired which is protected by our mutex */
01060   CONNECTION_UNLOCK (connection);
01061   
01062   _dbus_verbose ("locking io_path_mutex\n");
01063   _dbus_mutex_lock (connection->io_path_mutex);
01064 
01065   _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01066                  connection->io_path_acquired, timeout_milliseconds);
01067 
01068   we_acquired = FALSE;
01069   
01070   if (connection->io_path_acquired)
01071     {
01072       if (timeout_milliseconds != -1)
01073         {
01074           _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01075                          timeout_milliseconds);
01076 
01077           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01078                                            connection->io_path_mutex,
01079                                            timeout_milliseconds))
01080             {
01081               /* We timed out before anyone signaled. */
01082               /* (writing the loop to handle the !timedout case by
01083                * waiting longer if needed is a pain since dbus
01084                * wraps pthread_cond_timedwait to take a relative
01085                * time instead of absolute, something kind of stupid
01086                * on our part. for now it doesn't matter, we will just
01087                * end up back here eventually.)
01088                */
01089             }
01090         }
01091       else
01092         {
01093           while (connection->io_path_acquired)
01094             {
01095               _dbus_verbose ("waiting for IO path to be acquirable\n");
01096               _dbus_condvar_wait (connection->io_path_cond, 
01097                                   connection->io_path_mutex);
01098             }
01099         }
01100     }
01101   
01102   if (!connection->io_path_acquired)
01103     {
01104       we_acquired = TRUE;
01105       connection->io_path_acquired = TRUE;
01106     }
01107   
01108   _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01109                  connection->io_path_acquired, we_acquired);
01110 
01111   _dbus_verbose ("unlocking io_path_mutex\n");
01112   _dbus_mutex_unlock (connection->io_path_mutex);
01113 
01114   CONNECTION_LOCK (connection);
01115   
01116   HAVE_LOCK_CHECK (connection);
01117 
01118   _dbus_connection_unref_unlocked (connection);
01119   
01120   return we_acquired;
01121 }
01122 
01130 static void
01131 _dbus_connection_release_io_path (DBusConnection *connection)
01132 {
01133   HAVE_LOCK_CHECK (connection);
01134   
01135   _dbus_verbose ("locking io_path_mutex\n");
01136   _dbus_mutex_lock (connection->io_path_mutex);
01137   
01138   _dbus_assert (connection->io_path_acquired);
01139 
01140   _dbus_verbose ("start connection->io_path_acquired = %d\n",
01141                  connection->io_path_acquired);
01142   
01143   connection->io_path_acquired = FALSE;
01144   _dbus_condvar_wake_one (connection->io_path_cond);
01145 
01146   _dbus_verbose ("unlocking io_path_mutex\n");
01147   _dbus_mutex_unlock (connection->io_path_mutex);
01148 }
01149 
01185 void
01186 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01187                                         DBusPendingCall *pending,
01188                                         unsigned int    flags,
01189                                         int             timeout_milliseconds)
01190 {
01191   _dbus_verbose ("start\n");
01192   
01193   HAVE_LOCK_CHECK (connection);
01194   
01195   if (connection->n_outgoing == 0)
01196     flags &= ~DBUS_ITERATION_DO_WRITING;
01197 
01198   if (_dbus_connection_acquire_io_path (connection,
01199                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01200     {
01201       HAVE_LOCK_CHECK (connection);
01202       
01203       if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01204         {
01205           _dbus_verbose ("pending call completed while acquiring I/O path");
01206         }
01207       else if ( (pending != NULL) &&
01208                 _dbus_connection_peek_for_reply_unlocked (connection,
01209                                                           _dbus_pending_call_get_reply_serial_unlocked (pending)))
01210         {
01211           _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01212         }
01213       else
01214         {
01215           _dbus_transport_do_iteration (connection->transport,
01216                                         flags, timeout_milliseconds);
01217         }
01218 
01219       _dbus_connection_release_io_path (connection);
01220     }
01221 
01222   HAVE_LOCK_CHECK (connection);
01223 
01224   _dbus_verbose ("end\n");
01225 }
01226 
01236 DBusConnection*
01237 _dbus_connection_new_for_transport (DBusTransport *transport)
01238 {
01239   DBusConnection *connection;
01240   DBusWatchList *watch_list;
01241   DBusTimeoutList *timeout_list;
01242   DBusHashTable *pending_replies;
01243   DBusList *disconnect_link;
01244   DBusMessage *disconnect_message;
01245   DBusCounter *outgoing_counter;
01246   DBusObjectTree *objects;
01247   
01248   watch_list = NULL;
01249   connection = NULL;
01250   pending_replies = NULL;
01251   timeout_list = NULL;
01252   disconnect_link = NULL;
01253   disconnect_message = NULL;
01254   outgoing_counter = NULL;
01255   objects = NULL;
01256   
01257   watch_list = _dbus_watch_list_new ();
01258   if (watch_list == NULL)
01259     goto error;
01260 
01261   timeout_list = _dbus_timeout_list_new ();
01262   if (timeout_list == NULL)
01263     goto error;  
01264 
01265   pending_replies =
01266     _dbus_hash_table_new (DBUS_HASH_INT,
01267                           NULL,
01268                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01269   if (pending_replies == NULL)
01270     goto error;
01271   
01272   connection = dbus_new0 (DBusConnection, 1);
01273   if (connection == NULL)
01274     goto error;
01275 
01276   _dbus_mutex_new_at_location (&connection->mutex);
01277   if (connection->mutex == NULL)
01278     goto error;
01279 
01280   _dbus_mutex_new_at_location (&connection->io_path_mutex);
01281   if (connection->io_path_mutex == NULL)
01282     goto error;
01283 
01284   _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01285   if (connection->dispatch_mutex == NULL)
01286     goto error;
01287   
01288   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01289   if (connection->dispatch_cond == NULL)
01290     goto error;
01291   
01292   _dbus_condvar_new_at_location (&connection->io_path_cond);
01293   if (connection->io_path_cond == NULL)
01294     goto error;
01295 
01296   _dbus_mutex_new_at_location (&connection->slot_mutex);
01297   if (connection->slot_mutex == NULL)
01298     goto error;
01299 
01300   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01301                                                 DBUS_INTERFACE_LOCAL,
01302                                                 "Disconnected");
01303   
01304   if (disconnect_message == NULL)
01305     goto error;
01306 
01307   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01308   if (disconnect_link == NULL)
01309     goto error;
01310 
01311   outgoing_counter = _dbus_counter_new ();
01312   if (outgoing_counter == NULL)
01313     goto error;
01314 
01315   objects = _dbus_object_tree_new (connection);
01316   if (objects == NULL)
01317     goto error;
01318   
01319   if (_dbus_modify_sigpipe)
01320     _dbus_disable_sigpipe ();
01321 
01322   /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
01323   _dbus_atomic_inc (&connection->refcount);
01324   connection->transport = transport;
01325   connection->watches = watch_list;
01326   connection->timeouts = timeout_list;
01327   connection->pending_replies = pending_replies;
01328   connection->outgoing_counter = outgoing_counter;
01329   connection->filter_list = NULL;
01330   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01331   connection->objects = objects;
01332   connection->exit_on_disconnect = FALSE;
01333   connection->shareable = FALSE;
01334   connection->route_peer_messages = FALSE;
01335   connection->disconnected_message_arrived = FALSE;
01336   connection->disconnected_message_processed = FALSE;
01337   
01338 #ifndef DBUS_DISABLE_CHECKS
01339   connection->generation = _dbus_current_generation;
01340 #endif
01341   
01342   _dbus_data_slot_list_init (&connection->slot_list);
01343 
01344   connection->client_serial = 1;
01345 
01346   connection->disconnect_message_link = disconnect_link;
01347 
01348   CONNECTION_LOCK (connection);
01349   
01350   if (!_dbus_transport_set_connection (transport, connection))
01351     {
01352       CONNECTION_UNLOCK (connection);
01353 
01354       goto error;
01355     }
01356 
01357   _dbus_transport_ref (transport);
01358 
01359   CONNECTION_UNLOCK (connection);
01360   
01361   return connection;
01362   
01363  error:
01364   if (disconnect_message != NULL)
01365     dbus_message_unref (disconnect_message);
01366   
01367   if (disconnect_link != NULL)
01368     _dbus_list_free_link (disconnect_link);
01369   
01370   if (connection != NULL)
01371     {
01372       _dbus_condvar_free_at_location (&connection->io_path_cond);
01373       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01374       _dbus_mutex_free_at_location (&connection->mutex);
01375       _dbus_mutex_free_at_location (&connection->io_path_mutex);
01376       _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01377       _dbus_mutex_free_at_location (&connection->slot_mutex);
01378       dbus_free (connection);
01379     }
01380   if (pending_replies)
01381     _dbus_hash_table_unref (pending_replies);
01382   
01383   if (watch_list)
01384     _dbus_watch_list_free (watch_list);
01385 
01386   if (timeout_list)
01387     _dbus_timeout_list_free (timeout_list);
01388 
01389   if (outgoing_counter)
01390     _dbus_counter_unref (outgoing_counter);
01391 
01392   if (objects)
01393     _dbus_object_tree_unref (objects);
01394   
01395   return NULL;
01396 }
01397 
01405 DBusConnection *
01406 _dbus_connection_ref_unlocked (DBusConnection *connection)
01407 {  
01408   _dbus_assert (connection != NULL);
01409   _dbus_assert (connection->generation == _dbus_current_generation);
01410 
01411   HAVE_LOCK_CHECK (connection);
01412 
01413   _dbus_atomic_inc (&connection->refcount);
01414 
01415   return connection;
01416 }
01417 
01424 void
01425 _dbus_connection_unref_unlocked (DBusConnection *connection)
01426 {
01427   dbus_bool_t last_unref;
01428 
01429   HAVE_LOCK_CHECK (connection);
01430   
01431   _dbus_assert (connection != NULL);
01432 
01433   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01434 
01435   if (last_unref)
01436     _dbus_connection_last_unref (connection);
01437 }
01438 
01439 static dbus_uint32_t
01440 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01441 {
01442   dbus_uint32_t serial;
01443 
01444   serial = connection->client_serial++;
01445 
01446   if (connection->client_serial == 0)
01447     connection->client_serial = 1;
01448 
01449   return serial;
01450 }
01451 
01465 dbus_bool_t
01466 _dbus_connection_handle_watch (DBusWatch                   *watch,
01467                                unsigned int                 condition,
01468                                void                        *data)
01469 {
01470   DBusConnection *connection;
01471   dbus_bool_t retval;
01472   DBusDispatchStatus status;
01473 
01474   connection = data;
01475 
01476   _dbus_verbose ("start\n");
01477   
01478   CONNECTION_LOCK (connection);
01479 
01480   if (!_dbus_connection_acquire_io_path (connection, 1))
01481     {
01482       /* another thread is handling the message */
01483       CONNECTION_UNLOCK (connection);
01484       return TRUE;
01485     }
01486 
01487   HAVE_LOCK_CHECK (connection);
01488   retval = _dbus_transport_handle_watch (connection->transport,
01489                                          watch, condition);
01490 
01491   _dbus_connection_release_io_path (connection);
01492 
01493   HAVE_LOCK_CHECK (connection);
01494 
01495   _dbus_verbose ("middle\n");
01496   
01497   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01498 
01499   /* this calls out to user code */
01500   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01501 
01502   _dbus_verbose ("end\n");
01503   
01504   return retval;
01505 }
01506 
01507 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01508 static DBusHashTable *shared_connections = NULL;
01509 static DBusList *shared_connections_no_guid = NULL;
01510 
01511 static void
01512 close_connection_on_shutdown (DBusConnection *connection)
01513 {
01514   DBusMessage *message;
01515 
01516   dbus_connection_ref (connection);
01517   _dbus_connection_close_possibly_shared (connection);
01518 
01519   /* Churn through to the Disconnected message */
01520   while ((message = dbus_connection_pop_message (connection)))
01521     {
01522       dbus_message_unref (message);
01523     }
01524   dbus_connection_unref (connection);
01525 }
01526 
01527 static void
01528 shared_connections_shutdown (void *data)
01529 {
01530   int n_entries;
01531   
01532   _DBUS_LOCK (shared_connections);
01533   
01534   /* This is a little bit unpleasant... better ideas? */
01535   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01536     {
01537       DBusConnection *connection;
01538       DBusHashIter iter;
01539       
01540       _dbus_hash_iter_init (shared_connections, &iter);
01541       _dbus_hash_iter_next (&iter);
01542        
01543       connection = _dbus_hash_iter_get_value (&iter);
01544 
01545       _DBUS_UNLOCK (shared_connections);
01546       close_connection_on_shutdown (connection);
01547       _DBUS_LOCK (shared_connections);
01548 
01549       /* The connection should now be dead and not in our hash ... */
01550       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01551     }
01552 
01553   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01554   
01555   _dbus_hash_table_unref (shared_connections);
01556   shared_connections = NULL;
01557 
01558   if (shared_connections_no_guid != NULL)
01559     {
01560       DBusConnection *connection;
01561       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01562       while (connection != NULL)
01563         {
01564           _DBUS_UNLOCK (shared_connections);
01565           close_connection_on_shutdown (connection);
01566           _DBUS_LOCK (shared_connections);
01567           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01568         }
01569     }
01570 
01571   shared_connections_no_guid = NULL;
01572   
01573   _DBUS_UNLOCK (shared_connections);
01574 }
01575 
01576 static dbus_bool_t
01577 connection_lookup_shared (DBusAddressEntry  *entry,
01578                           DBusConnection   **result)
01579 {
01580   _dbus_verbose ("checking for existing connection\n");
01581   
01582   *result = NULL;
01583   
01584   _DBUS_LOCK (shared_connections);
01585 
01586   if (shared_connections == NULL)
01587     {
01588       _dbus_verbose ("creating shared_connections hash table\n");
01589       
01590       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01591                                                  dbus_free,
01592                                                  NULL);
01593       if (shared_connections == NULL)
01594         {
01595           _DBUS_UNLOCK (shared_connections);
01596           return FALSE;
01597         }
01598 
01599       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01600         {
01601           _dbus_hash_table_unref (shared_connections);
01602           shared_connections = NULL;
01603           _DBUS_UNLOCK (shared_connections);
01604           return FALSE;
01605         }
01606 
01607       _dbus_verbose ("  successfully created shared_connections\n");
01608       
01609       _DBUS_UNLOCK (shared_connections);
01610       return TRUE; /* no point looking up in the hash we just made */
01611     }
01612   else
01613     {
01614       const char *guid;
01615 
01616       guid = dbus_address_entry_get_value (entry, "guid");
01617       
01618       if (guid != NULL)
01619         {
01620           DBusConnection *connection;
01621           
01622           connection = _dbus_hash_table_lookup_string (shared_connections,
01623                                                        guid);
01624 
01625           if (connection)
01626             {
01627               /* The DBusConnection can't be finalized without taking
01628                * the shared_connections lock to remove it from the
01629                * hash.  So it's safe to ref the connection here.
01630                * However, it may be disconnected if the Disconnected
01631                * message hasn't been processed yet, in which case we
01632                * want to pretend it isn't in the hash and avoid
01633                * returning it.
01634                *
01635                * The idea is to avoid ever returning a disconnected connection
01636                * from dbus_connection_open(). We could just synchronously
01637                * drop our shared ref to the connection on connection disconnect,
01638                * and then assert here that the connection is connected, but
01639                * that causes reentrancy headaches.
01640                */
01641               CONNECTION_LOCK (connection);
01642               if (_dbus_connection_get_is_connected_unlocked (connection))
01643                 {
01644                   _dbus_connection_ref_unlocked (connection);
01645                   *result = connection;
01646                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01647                                  guid);
01648                 }
01649               else
01650                 {
01651                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01652                                  guid);
01653                 }
01654               CONNECTION_UNLOCK (connection);
01655             }
01656         }
01657       
01658       _DBUS_UNLOCK (shared_connections);
01659       return TRUE;
01660     }
01661 }
01662 
01663 static dbus_bool_t
01664 connection_record_shared_unlocked (DBusConnection *connection,
01665                                    const char     *guid)
01666 {
01667   char *guid_key;
01668   char *guid_in_connection;
01669 
01670   HAVE_LOCK_CHECK (connection);
01671   _dbus_assert (connection->server_guid == NULL);
01672   _dbus_assert (connection->shareable);
01673 
01674   /* get a hard ref on this connection, even if
01675    * we won't in fact store it in the hash, we still
01676    * need to hold a ref on it until it's disconnected.
01677    */
01678   _dbus_connection_ref_unlocked (connection);
01679 
01680   if (guid == NULL)
01681     {
01682       _DBUS_LOCK (shared_connections);
01683 
01684       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01685         {
01686           _DBUS_UNLOCK (shared_connections);
01687           return FALSE;
01688         }
01689 
01690       _DBUS_UNLOCK (shared_connections);
01691       return TRUE; /* don't store in the hash */
01692     }
01693   
01694   /* A separate copy of the key is required in the hash table, because
01695    * we don't have a lock on the connection when we are doing a hash
01696    * lookup.
01697    */
01698   
01699   guid_key = _dbus_strdup (guid);
01700   if (guid_key == NULL)
01701     return FALSE;
01702 
01703   guid_in_connection = _dbus_strdup (guid);
01704   if (guid_in_connection == NULL)
01705     {
01706       dbus_free (guid_key);
01707       return FALSE;
01708     }
01709   
01710   _DBUS_LOCK (shared_connections);
01711   _dbus_assert (shared_connections != NULL);
01712   
01713   if (!_dbus_hash_table_insert_string (shared_connections,
01714                                        guid_key, connection))
01715     {
01716       dbus_free (guid_key);
01717       dbus_free (guid_in_connection);
01718       _DBUS_UNLOCK (shared_connections);
01719       return FALSE;
01720     }
01721 
01722   connection->server_guid = guid_in_connection;
01723 
01724   _dbus_verbose ("stored connection to %s to be shared\n",
01725                  connection->server_guid);
01726   
01727   _DBUS_UNLOCK (shared_connections);
01728 
01729   _dbus_assert (connection->server_guid != NULL);
01730   
01731   return TRUE;
01732 }
01733 
01734 static void
01735 connection_forget_shared_unlocked (DBusConnection *connection)
01736 {
01737   HAVE_LOCK_CHECK (connection);
01738 
01739   if (!connection->shareable)
01740     return;
01741   
01742   _DBUS_LOCK (shared_connections);
01743       
01744   if (connection->server_guid != NULL)
01745     {
01746       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01747                      connection->server_guid);
01748       
01749       if (!_dbus_hash_table_remove_string (shared_connections,
01750                                            connection->server_guid))
01751         _dbus_assert_not_reached ("connection was not in the shared table");
01752       
01753       dbus_free (connection->server_guid);
01754       connection->server_guid = NULL;
01755     }
01756   else
01757     {
01758       _dbus_list_remove (&shared_connections_no_guid, connection);
01759     }
01760 
01761   _DBUS_UNLOCK (shared_connections);
01762   
01763   /* remove our reference held on all shareable connections */
01764   _dbus_connection_unref_unlocked (connection);
01765 }
01766 
01767 static DBusConnection*
01768 connection_try_from_address_entry (DBusAddressEntry *entry,
01769                                    DBusError        *error)
01770 {
01771   DBusTransport *transport;
01772   DBusConnection *connection;
01773 
01774   transport = _dbus_transport_open (entry, error);
01775 
01776   if (transport == NULL)
01777     {
01778       _DBUS_ASSERT_ERROR_IS_SET (error);
01779       return NULL;
01780     }
01781 
01782   connection = _dbus_connection_new_for_transport (transport);
01783 
01784   _dbus_transport_unref (transport);
01785   
01786   if (connection == NULL)
01787     {
01788       _DBUS_SET_OOM (error);
01789       return NULL;
01790     }
01791 
01792 #ifndef DBUS_DISABLE_CHECKS
01793   _dbus_assert (!connection->have_connection_lock);
01794 #endif
01795   return connection;
01796 }
01797 
01798 /*
01799  * If the shared parameter is true, then any existing connection will
01800  * be used (and if a new connection is created, it will be available
01801  * for use by others). If the shared parameter is false, a new
01802  * connection will always be created, and the new connection will
01803  * never be returned to other callers.
01804  *
01805  * @param address the address
01806  * @param shared whether the connection is shared or private
01807  * @param error error return
01808  * @returns the connection or #NULL on error
01809  */
01810 static DBusConnection*
01811 _dbus_connection_open_internal (const char     *address,
01812                                 dbus_bool_t     shared,
01813                                 DBusError      *error)
01814 {
01815   DBusConnection *connection;
01816   DBusAddressEntry **entries;
01817   DBusError tmp_error = DBUS_ERROR_INIT;
01818   DBusError first_error = DBUS_ERROR_INIT;
01819   int len, i;
01820 
01821   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01822 
01823   _dbus_verbose ("opening %s connection to: %s\n",
01824                  shared ? "shared" : "private", address);
01825   
01826   if (!dbus_parse_address (address, &entries, &len, error))
01827     return NULL;
01828 
01829   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01830   
01831   connection = NULL;
01832 
01833   for (i = 0; i < len; i++)
01834     {
01835       if (shared)
01836         {
01837           if (!connection_lookup_shared (entries[i], &connection))
01838             _DBUS_SET_OOM (&tmp_error);
01839         }
01840 
01841       if (connection == NULL)
01842         {
01843           connection = connection_try_from_address_entry (entries[i],
01844                                                           &tmp_error);
01845 
01846           if (connection != NULL && shared)
01847             {
01848               const char *guid;
01849                   
01850               connection->shareable = TRUE;
01851                   
01852               /* guid may be NULL */
01853               guid = dbus_address_entry_get_value (entries[i], "guid");
01854                   
01855               CONNECTION_LOCK (connection);
01856           
01857               if (!connection_record_shared_unlocked (connection, guid))
01858                 {
01859                   _DBUS_SET_OOM (&tmp_error);
01860                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01861                   dbus_connection_unref (connection);
01862                   connection = NULL;
01863                 }
01864               else
01865                 CONNECTION_UNLOCK (connection);
01866             }
01867         }
01868       
01869       if (connection)
01870         break;
01871 
01872       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01873       
01874       if (i == 0)
01875         dbus_move_error (&tmp_error, &first_error);
01876       else
01877         dbus_error_free (&tmp_error);
01878     }
01879   
01880   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01881   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01882   
01883   if (connection == NULL)
01884     {
01885       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01886       dbus_move_error (&first_error, error);
01887     }
01888   else
01889     dbus_error_free (&first_error);
01890   
01891   dbus_address_entries_free (entries);
01892   return connection;
01893 }
01894 
01903 void
01904 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01905 {
01906   _dbus_assert (connection != NULL);
01907   _dbus_assert (connection->generation == _dbus_current_generation);
01908 
01909   CONNECTION_LOCK (connection);
01910   _dbus_connection_close_possibly_shared_and_unlock (connection);
01911 }
01912 
01913 static DBusPreallocatedSend*
01914 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01915 {
01916   DBusPreallocatedSend *preallocated;
01917 
01918   HAVE_LOCK_CHECK (connection);
01919   
01920   _dbus_assert (connection != NULL);
01921   
01922   preallocated = dbus_new (DBusPreallocatedSend, 1);
01923   if (preallocated == NULL)
01924     return NULL;
01925 
01926   if (connection->link_cache != NULL)
01927     {
01928       preallocated->queue_link =
01929         _dbus_list_pop_first_link (&connection->link_cache);
01930       preallocated->queue_link->data = NULL;
01931     }
01932   else
01933     {
01934       preallocated->queue_link = _dbus_list_alloc_link (NULL);
01935       if (preallocated->queue_link == NULL)
01936         goto failed_0;
01937     }
01938   
01939   if (connection->link_cache != NULL)
01940     {
01941       preallocated->counter_link =
01942         _dbus_list_pop_first_link (&connection->link_cache);
01943       preallocated->counter_link->data = connection->outgoing_counter;
01944     }
01945   else
01946     {
01947       preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01948       if (preallocated->counter_link == NULL)
01949         goto failed_1;
01950     }
01951 
01952   _dbus_counter_ref (preallocated->counter_link->data);
01953 
01954   preallocated->connection = connection;
01955   
01956   return preallocated;
01957   
01958  failed_1:
01959   _dbus_list_free_link (preallocated->queue_link);
01960  failed_0:
01961   dbus_free (preallocated);
01962   
01963   return NULL;
01964 }
01965 
01966 /* Called with lock held, does not update dispatch status */
01967 static void
01968 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01969                                                        DBusPreallocatedSend *preallocated,
01970                                                        DBusMessage          *message,
01971                                                        dbus_uint32_t        *client_serial)
01972 {
01973   dbus_uint32_t serial;
01974 
01975   preallocated->queue_link->data = message;
01976   _dbus_list_prepend_link (&connection->outgoing_messages,
01977                            preallocated->queue_link);
01978 
01979   _dbus_message_add_counter_link (message,
01980                                   preallocated->counter_link);
01981 
01982   dbus_free (preallocated);
01983   preallocated = NULL;
01984   
01985   dbus_message_ref (message);
01986   
01987   connection->n_outgoing += 1;
01988 
01989   _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
01990                  message,
01991                  dbus_message_type_to_string (dbus_message_get_type (message)),
01992                  dbus_message_get_path (message) ?
01993                  dbus_message_get_path (message) :
01994                  "no path",
01995                  dbus_message_get_interface (message) ?
01996                  dbus_message_get_interface (message) :
01997                  "no interface",
01998                  dbus_message_get_member (message) ?
01999                  dbus_message_get_member (message) :
02000                  "no member",
02001                  dbus_message_get_signature (message),
02002                  dbus_message_get_destination (message) ?
02003                  dbus_message_get_destination (message) :
02004                  "null",
02005                  connection,
02006                  connection->n_outgoing);
02007 
02008   if (dbus_message_get_serial (message) == 0)
02009     {
02010       serial = _dbus_connection_get_next_client_serial (connection);
02011       dbus_message_set_serial (message, serial);
02012       if (client_serial)
02013         *client_serial = serial;
02014     }
02015   else
02016     {
02017       if (client_serial)
02018         *client_serial = dbus_message_get_serial (message);
02019     }
02020 
02021   _dbus_verbose ("Message %p serial is %u\n",
02022                  message, dbus_message_get_serial (message));
02023   
02024   dbus_message_lock (message);
02025 
02026   /* Now we need to run an iteration to hopefully just write the messages
02027    * out immediately, and otherwise get them queued up
02028    */
02029   _dbus_connection_do_iteration_unlocked (connection,
02030                                           NULL,
02031                                           DBUS_ITERATION_DO_WRITING,
02032                                           -1);
02033 
02034   /* If stuff is still queued up, be sure we wake up the main loop */
02035   if (connection->n_outgoing > 0)
02036     _dbus_connection_wakeup_mainloop (connection);
02037 }
02038 
02039 static void
02040 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02041                                                DBusPreallocatedSend *preallocated,
02042                                                DBusMessage          *message,
02043                                                dbus_uint32_t        *client_serial)
02044 {
02045   DBusDispatchStatus status;
02046 
02047   HAVE_LOCK_CHECK (connection);
02048   
02049   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02050                                                          preallocated,
02051                                                          message, client_serial);
02052 
02053   _dbus_verbose ("middle\n");
02054   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02055 
02056   /* this calls out to user code */
02057   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02058 }
02059 
02069 dbus_bool_t
02070 _dbus_connection_send_and_unlock (DBusConnection *connection,
02071                                   DBusMessage    *message,
02072                                   dbus_uint32_t  *client_serial)
02073 {
02074   DBusPreallocatedSend *preallocated;
02075 
02076   _dbus_assert (connection != NULL);
02077   _dbus_assert (message != NULL);
02078   
02079   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02080   if (preallocated == NULL)
02081     {
02082       CONNECTION_UNLOCK (connection);
02083       return FALSE;
02084     }
02085 
02086   _dbus_connection_send_preallocated_and_unlock (connection,
02087                                                  preallocated,
02088                                                  message,
02089                                                  client_serial);
02090   return TRUE;
02091 }
02092 
02117 void
02118 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02119 {
02120   dbus_int32_t refcount;
02121 
02122   CONNECTION_LOCK (connection);
02123 
02124   refcount = _dbus_atomic_get (&connection->refcount);
02125   /* The caller should have at least one ref */
02126   _dbus_assert (refcount >= 1);
02127 
02128   if (refcount == 1)
02129     _dbus_connection_close_possibly_shared_and_unlock (connection);
02130   else
02131     CONNECTION_UNLOCK (connection);
02132 }
02133 
02134 
02144 static void
02145 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02146 {
02147   if (timeout_milliseconds == -1)
02148     _dbus_sleep_milliseconds (1000);
02149   else if (timeout_milliseconds < 100)
02150     ; /* just busy loop */
02151   else if (timeout_milliseconds <= 1000)
02152     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02153   else
02154     _dbus_sleep_milliseconds (1000);
02155 }
02156 
02157 static DBusMessage *
02158 generate_local_error_message (dbus_uint32_t serial, 
02159                               char *error_name, 
02160                               char *error_msg)
02161 {
02162   DBusMessage *message;
02163   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02164   if (!message)
02165     goto out;
02166 
02167   if (!dbus_message_set_error_name (message, error_name))
02168     {
02169       dbus_message_unref (message);
02170       message = NULL;
02171       goto out; 
02172     }
02173 
02174   dbus_message_set_no_reply (message, TRUE); 
02175 
02176   if (!dbus_message_set_reply_serial (message,
02177                                       serial))
02178     {
02179       dbus_message_unref (message);
02180       message = NULL;
02181       goto out;
02182     }
02183 
02184   if (error_msg != NULL)
02185     {
02186       DBusMessageIter iter;
02187 
02188       dbus_message_iter_init_append (message, &iter);
02189       if (!dbus_message_iter_append_basic (&iter,
02190                                            DBUS_TYPE_STRING,
02191                                            &error_msg))
02192         {
02193           dbus_message_unref (message);
02194           message = NULL;
02195           goto out;
02196         }
02197     }
02198 
02199  out:
02200   return message;
02201 }
02202 
02203 /*
02204  * Peek the incoming queue to see if we got reply for a specific serial
02205  */
02206 static dbus_bool_t
02207 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02208                                           dbus_uint32_t   client_serial)
02209 {
02210   DBusList *link;
02211   HAVE_LOCK_CHECK (connection);
02212 
02213   link = _dbus_list_get_first_link (&connection->incoming_messages);
02214 
02215   while (link != NULL)
02216     {
02217       DBusMessage *reply = link->data;
02218 
02219       if (dbus_message_get_reply_serial (reply) == client_serial)
02220         {
02221           _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02222           return TRUE;
02223         }
02224       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02225     }
02226 
02227   return FALSE;
02228 }
02229 
02230 /* This is slightly strange since we can pop a message here without
02231  * the dispatch lock.
02232  */
02233 static DBusMessage*
02234 check_for_reply_unlocked (DBusConnection *connection,
02235                           dbus_uint32_t   client_serial)
02236 {
02237   DBusList *link;
02238 
02239   HAVE_LOCK_CHECK (connection);
02240   
02241   link = _dbus_list_get_first_link (&connection->incoming_messages);
02242 
02243   while (link != NULL)
02244     {
02245       DBusMessage *reply = link->data;
02246 
02247       if (dbus_message_get_reply_serial (reply) == client_serial)
02248         {
02249           _dbus_list_remove_link (&connection->incoming_messages, link);
02250           connection->n_incoming  -= 1;
02251           return reply;
02252         }
02253       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02254     }
02255 
02256   return NULL;
02257 }
02258 
02259 static void
02260 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02261 {
02262    /* We can't iterate over the hash in the normal way since we'll be
02263     * dropping the lock for each item. So we restart the
02264     * iter each time as we drain the hash table.
02265     */
02266    
02267    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02268     {
02269       DBusPendingCall *pending;
02270       DBusHashIter iter;
02271       
02272       _dbus_hash_iter_init (connection->pending_replies, &iter);
02273       _dbus_hash_iter_next (&iter);
02274        
02275       pending = _dbus_hash_iter_get_value (&iter);
02276       _dbus_pending_call_ref_unlocked (pending);
02277        
02278       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02279                                                        connection);
02280 
02281       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02282           _dbus_connection_remove_timeout_unlocked (connection,
02283                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02284       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02285       _dbus_hash_iter_remove_entry (&iter);
02286 
02287       _dbus_pending_call_unref_and_unlock (pending);
02288       CONNECTION_LOCK (connection);
02289     }
02290   HAVE_LOCK_CHECK (connection);
02291 }
02292 
02293 static void
02294 complete_pending_call_and_unlock (DBusConnection  *connection,
02295                                   DBusPendingCall *pending,
02296                                   DBusMessage     *message)
02297 {
02298   _dbus_pending_call_set_reply_unlocked (pending, message);
02299   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02300   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02301  
02302   /* Must be called unlocked since it invokes app callback */
02303   _dbus_pending_call_complete (pending);
02304   dbus_pending_call_unref (pending);
02305 }
02306 
02307 static dbus_bool_t
02308 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02309                                               DBusPendingCall *pending)
02310 {
02311   DBusMessage *reply;
02312   DBusDispatchStatus status;
02313 
02314   reply = check_for_reply_unlocked (connection, 
02315                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02316   if (reply != NULL)
02317     {
02318       _dbus_verbose ("checked for reply\n");
02319 
02320       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02321 
02322       complete_pending_call_and_unlock (connection, pending, reply);
02323       dbus_message_unref (reply);
02324 
02325       CONNECTION_LOCK (connection);
02326       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02327       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02328       dbus_pending_call_unref (pending);
02329 
02330       return TRUE;
02331     }
02332 
02333   return FALSE;
02334 }
02335 
02350 void
02351 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02352 {
02353   long start_tv_sec, start_tv_usec;
02354   long tv_sec, tv_usec;
02355   DBusDispatchStatus status;
02356   DBusConnection *connection;
02357   dbus_uint32_t client_serial;
02358   DBusTimeout *timeout;
02359   int timeout_milliseconds, elapsed_milliseconds;
02360 
02361   _dbus_assert (pending != NULL);
02362 
02363   if (dbus_pending_call_get_completed (pending))
02364     return;
02365 
02366   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02367 
02368   connection = _dbus_pending_call_get_connection_and_lock (pending);
02369   
02370   /* Flush message queue - note, can affect dispatch status */
02371   _dbus_connection_flush_unlocked (connection);
02372 
02373   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02374 
02375   /* note that timeout_milliseconds is limited to a smallish value
02376    * in _dbus_pending_call_new() so overflows aren't possible
02377    * below
02378    */
02379   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02380   _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02381   if (timeout)
02382     {
02383       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02384 
02385       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02386                      timeout_milliseconds,
02387                      client_serial,
02388                      start_tv_sec, start_tv_usec);
02389     }
02390   else
02391     {
02392       timeout_milliseconds = -1;
02393 
02394       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02395     }
02396 
02397   /* check to see if we already got the data off the socket */
02398   /* from another blocked pending call */
02399   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02400     return;
02401 
02402   /* Now we wait... */
02403   /* always block at least once as we know we don't have the reply yet */
02404   _dbus_connection_do_iteration_unlocked (connection,
02405                                           pending,
02406                                           DBUS_ITERATION_DO_READING |
02407                                           DBUS_ITERATION_BLOCK,
02408                                           timeout_milliseconds);
02409 
02410  recheck_status:
02411 
02412   _dbus_verbose ("top of recheck\n");
02413   
02414   HAVE_LOCK_CHECK (connection);
02415   
02416   /* queue messages and get status */
02417 
02418   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02419 
02420   /* the get_completed() is in case a dispatch() while we were blocking
02421    * got the reply instead of us.
02422    */
02423   if (_dbus_pending_call_get_completed_unlocked (pending))
02424     {
02425       _dbus_verbose ("Pending call completed by dispatch\n");
02426       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02427       dbus_pending_call_unref (pending);
02428       return;
02429     }
02430   
02431   if (status == DBUS_DISPATCH_DATA_REMAINS)
02432     {
02433       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02434         return;
02435     }
02436   
02437   _dbus_get_current_time (&tv_sec, &tv_usec);
02438   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02439           (tv_usec - start_tv_usec) / 1000;
02440   
02441   if (!_dbus_connection_get_is_connected_unlocked (connection))
02442     {
02443       DBusMessage *error_msg;
02444 
02445       error_msg = generate_local_error_message (client_serial,
02446                                                 DBUS_ERROR_DISCONNECTED, 
02447                                                 "Connection was disconnected before a reply was received"); 
02448 
02449       /* on OOM error_msg is set to NULL */
02450       complete_pending_call_and_unlock (connection, pending, error_msg);
02451       dbus_pending_call_unref (pending);
02452       return;
02453     }
02454   else if (connection->disconnect_message_link == NULL)
02455     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02456   else if (timeout == NULL)
02457     {
02458        if (status == DBUS_DISPATCH_NEED_MEMORY)
02459         {
02460           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02461            * we may already have a reply in the buffer and just can't process
02462            * it.
02463            */
02464           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02465 
02466           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02467         }
02468       else
02469         {          
02470           /* block again, we don't have the reply buffered yet. */
02471           _dbus_connection_do_iteration_unlocked (connection,
02472                                                   pending,
02473                                                   DBUS_ITERATION_DO_READING |
02474                                                   DBUS_ITERATION_BLOCK,
02475                                                   timeout_milliseconds - elapsed_milliseconds);
02476         }
02477 
02478       goto recheck_status;
02479     }
02480   else if (tv_sec < start_tv_sec)
02481     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02482   else if (elapsed_milliseconds < timeout_milliseconds)
02483     {
02484       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02485       
02486       if (status == DBUS_DISPATCH_NEED_MEMORY)
02487         {
02488           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02489            * we may already have a reply in the buffer and just can't process
02490            * it.
02491            */
02492           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02493 
02494           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02495         }
02496       else
02497         {          
02498           /* block again, we don't have the reply buffered yet. */
02499           _dbus_connection_do_iteration_unlocked (connection,
02500                                                   NULL,
02501                                                   DBUS_ITERATION_DO_READING |
02502                                                   DBUS_ITERATION_BLOCK,
02503                                                   timeout_milliseconds - elapsed_milliseconds);
02504         }
02505 
02506       goto recheck_status;
02507     }
02508 
02509   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02510                  elapsed_milliseconds);
02511 
02512   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02513   
02514   /* unlock and call user code */
02515   complete_pending_call_and_unlock (connection, pending, NULL);
02516 
02517   /* update user code on dispatch status */
02518   CONNECTION_LOCK (connection);
02519   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02520   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02521   dbus_pending_call_unref (pending);
02522 }
02523 
02529 int
02530 _dbus_connection_get_pending_fds_count (DBusConnection *connection)
02531 {
02532   return _dbus_transport_get_pending_fds_count (connection->transport);
02533 }
02534 
02542 void
02543 _dbus_connection_set_pending_fds_function (DBusConnection *connection,
02544                                            DBusPendingFdsChangeFunction callback,
02545                                            void *data)
02546 {
02547   _dbus_transport_set_pending_fds_function (connection->transport,
02548                                             callback, data);
02549 }
02550 
02587 DBusConnection*
02588 dbus_connection_open (const char     *address,
02589                       DBusError      *error)
02590 {
02591   DBusConnection *connection;
02592 
02593   _dbus_return_val_if_fail (address != NULL, NULL);
02594   _dbus_return_val_if_error_is_set (error, NULL);
02595 
02596   connection = _dbus_connection_open_internal (address,
02597                                                TRUE,
02598                                                error);
02599 
02600   return connection;
02601 }
02602 
02630 DBusConnection*
02631 dbus_connection_open_private (const char     *address,
02632                               DBusError      *error)
02633 {
02634   DBusConnection *connection;
02635 
02636   _dbus_return_val_if_fail (address != NULL, NULL);
02637   _dbus_return_val_if_error_is_set (error, NULL);
02638 
02639   connection = _dbus_connection_open_internal (address,
02640                                                FALSE,
02641                                                error);
02642 
02643   return connection;
02644 }
02645 
02652 DBusConnection *
02653 dbus_connection_ref (DBusConnection *connection)
02654 {
02655   _dbus_return_val_if_fail (connection != NULL, NULL);
02656   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02657 
02658   _dbus_atomic_inc (&connection->refcount);
02659 
02660   return connection;
02661 }
02662 
02663 static void
02664 free_outgoing_message (void *element,
02665                        void *data)
02666 {
02667   DBusMessage *message = element;
02668   DBusConnection *connection = data;
02669 
02670   _dbus_message_remove_counter (message,
02671                                 connection->outgoing_counter,
02672                                 NULL);
02673   dbus_message_unref (message);
02674 }
02675 
02676 /* This is run without the mutex held, but after the last reference
02677  * to the connection has been dropped we should have no thread-related
02678  * problems
02679  */
02680 static void
02681 _dbus_connection_last_unref (DBusConnection *connection)
02682 {
02683   DBusList *link;
02684 
02685   _dbus_verbose ("Finalizing connection %p\n", connection);
02686 
02687   _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02688 
02689   /* You have to disconnect the connection before unref:ing it. Otherwise
02690    * you won't get the disconnected message.
02691    */
02692   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02693   _dbus_assert (connection->server_guid == NULL);
02694   
02695   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02696   _dbus_object_tree_free_all_unlocked (connection->objects);
02697   
02698   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02699   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02700   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02701   
02702   _dbus_watch_list_free (connection->watches);
02703   connection->watches = NULL;
02704   
02705   _dbus_timeout_list_free (connection->timeouts);
02706   connection->timeouts = NULL;
02707 
02708   _dbus_data_slot_list_free (&connection->slot_list);
02709   
02710   link = _dbus_list_get_first_link (&connection->filter_list);
02711   while (link != NULL)
02712     {
02713       DBusMessageFilter *filter = link->data;
02714       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02715 
02716       filter->function = NULL;
02717       _dbus_message_filter_unref (filter); /* calls app callback */
02718       link->data = NULL;
02719       
02720       link = next;
02721     }
02722   _dbus_list_clear (&connection->filter_list);
02723   
02724   /* ---- Done with stuff that invokes application callbacks */
02725 
02726   _dbus_object_tree_unref (connection->objects);  
02727 
02728   _dbus_hash_table_unref (connection->pending_replies);
02729   connection->pending_replies = NULL;
02730   
02731   _dbus_list_clear (&connection->filter_list);
02732   
02733   _dbus_list_foreach (&connection->outgoing_messages,
02734                       free_outgoing_message,
02735                       connection);
02736   _dbus_list_clear (&connection->outgoing_messages);
02737   
02738   _dbus_list_foreach (&connection->incoming_messages,
02739                       (DBusForeachFunction) dbus_message_unref,
02740                       NULL);
02741   _dbus_list_clear (&connection->incoming_messages);
02742 
02743   _dbus_counter_unref (connection->outgoing_counter);
02744 
02745   _dbus_transport_unref (connection->transport);
02746 
02747   if (connection->disconnect_message_link)
02748     {
02749       DBusMessage *message = connection->disconnect_message_link->data;
02750       dbus_message_unref (message);
02751       _dbus_list_free_link (connection->disconnect_message_link);
02752     }
02753 
02754   _dbus_list_clear (&connection->link_cache);
02755   
02756   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02757   _dbus_condvar_free_at_location (&connection->io_path_cond);
02758 
02759   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02760   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02761 
02762   _dbus_mutex_free_at_location (&connection->slot_mutex);
02763 
02764   _dbus_mutex_free_at_location (&connection->mutex);
02765   
02766   dbus_free (connection);
02767 }
02768 
02788 void
02789 dbus_connection_unref (DBusConnection *connection)
02790 {
02791   dbus_bool_t last_unref;
02792 
02793   _dbus_return_if_fail (connection != NULL);
02794   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02795 
02796   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02797 
02798   if (last_unref)
02799     {
02800 #ifndef DBUS_DISABLE_CHECKS
02801       if (_dbus_transport_get_is_connected (connection->transport))
02802         {
02803           _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",
02804                                    connection->shareable ?
02805                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02806                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02807           return;
02808         }
02809 #endif
02810       _dbus_connection_last_unref (connection);
02811     }
02812 }
02813 
02814 /*
02815  * Note that the transport can disconnect itself (other end drops us)
02816  * and in that case this function never runs. So this function must
02817  * not do anything more than disconnect the transport and update the
02818  * dispatch status.
02819  * 
02820  * If the transport self-disconnects, then we assume someone will
02821  * dispatch the connection to cause the dispatch status update.
02822  */
02823 static void
02824 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02825 {
02826   DBusDispatchStatus status;
02827 
02828   HAVE_LOCK_CHECK (connection);
02829   
02830   _dbus_verbose ("Disconnecting %p\n", connection);
02831 
02832   /* We need to ref because update_dispatch_status_and_unlock will unref
02833    * the connection if it was shared and libdbus was the only remaining
02834    * refcount holder.
02835    */
02836   _dbus_connection_ref_unlocked (connection);
02837   
02838   _dbus_transport_disconnect (connection->transport);
02839 
02840   /* This has the side effect of queuing the disconnect message link
02841    * (unless we don't have enough memory, possibly, so don't assert it).
02842    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02843    * should never again return the newly-disconnected connection.
02844    *
02845    * However, we only unref the shared connection and exit_on_disconnect when
02846    * the disconnect message reaches the head of the message queue,
02847    * NOT when it's first queued.
02848    */
02849   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02850 
02851   /* This calls out to user code */
02852   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02853 
02854   /* Could also call out to user code */
02855   dbus_connection_unref (connection);
02856 }
02857 
02900 void
02901 dbus_connection_close (DBusConnection *connection)
02902 {
02903   _dbus_return_if_fail (connection != NULL);
02904   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02905 
02906   CONNECTION_LOCK (connection);
02907 
02908 #ifndef DBUS_DISABLE_CHECKS
02909   if (connection->shareable)
02910     {
02911       CONNECTION_UNLOCK (connection);
02912 
02913       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02914       return;
02915     }
02916 #endif
02917   
02918   _dbus_connection_close_possibly_shared_and_unlock (connection);
02919 }
02920 
02921 static dbus_bool_t
02922 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02923 {
02924   HAVE_LOCK_CHECK (connection);
02925   return _dbus_transport_get_is_connected (connection->transport);
02926 }
02927 
02941 dbus_bool_t
02942 dbus_connection_get_is_connected (DBusConnection *connection)
02943 {
02944   dbus_bool_t res;
02945 
02946   _dbus_return_val_if_fail (connection != NULL, FALSE);
02947   
02948   CONNECTION_LOCK (connection);
02949   res = _dbus_connection_get_is_connected_unlocked (connection);
02950   CONNECTION_UNLOCK (connection);
02951   
02952   return res;
02953 }
02954 
02963 dbus_bool_t
02964 dbus_connection_get_is_authenticated (DBusConnection *connection)
02965 {
02966   dbus_bool_t res;
02967 
02968   _dbus_return_val_if_fail (connection != NULL, FALSE);
02969   
02970   CONNECTION_LOCK (connection);
02971   res = _dbus_transport_get_is_authenticated (connection->transport);
02972   CONNECTION_UNLOCK (connection);
02973   
02974   return res;
02975 }
02976 
02997 dbus_bool_t
02998 dbus_connection_get_is_anonymous (DBusConnection *connection)
02999 {
03000   dbus_bool_t res;
03001 
03002   _dbus_return_val_if_fail (connection != NULL, FALSE);
03003   
03004   CONNECTION_LOCK (connection);
03005   res = _dbus_transport_get_is_anonymous (connection->transport);
03006   CONNECTION_UNLOCK (connection);
03007   
03008   return res;
03009 }
03010 
03042 char*
03043 dbus_connection_get_server_id (DBusConnection *connection)
03044 {
03045   char *id;
03046 
03047   _dbus_return_val_if_fail (connection != NULL, NULL);
03048 
03049   CONNECTION_LOCK (connection);
03050   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03051   CONNECTION_UNLOCK (connection);
03052 
03053   return id;
03054 }
03055 
03073 dbus_bool_t
03074 dbus_connection_can_send_type(DBusConnection *connection,
03075                                   int type)
03076 {
03077   _dbus_return_val_if_fail (connection != NULL, FALSE);
03078 
03079   if (!_dbus_type_is_valid(type))
03080     return FALSE;
03081 
03082   if (type != DBUS_TYPE_UNIX_FD)
03083     return TRUE;
03084 
03085 #ifdef HAVE_UNIX_FD_PASSING
03086   {
03087     dbus_bool_t b;
03088 
03089     CONNECTION_LOCK(connection);
03090     b = _dbus_transport_can_pass_unix_fd(connection->transport);
03091     CONNECTION_UNLOCK(connection);
03092 
03093     return b;
03094   }
03095 #endif
03096 
03097   return FALSE;
03098 }
03099 
03113 void
03114 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03115                                         dbus_bool_t     exit_on_disconnect)
03116 {
03117   _dbus_return_if_fail (connection != NULL);
03118 
03119   CONNECTION_LOCK (connection);
03120   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03121   CONNECTION_UNLOCK (connection);
03122 }
03123 
03133 DBusPreallocatedSend*
03134 dbus_connection_preallocate_send (DBusConnection *connection)
03135 {
03136   DBusPreallocatedSend *preallocated;
03137 
03138   _dbus_return_val_if_fail (connection != NULL, NULL);
03139 
03140   CONNECTION_LOCK (connection);
03141   
03142   preallocated =
03143     _dbus_connection_preallocate_send_unlocked (connection);
03144 
03145   CONNECTION_UNLOCK (connection);
03146 
03147   return preallocated;
03148 }
03149 
03159 void
03160 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03161                                         DBusPreallocatedSend *preallocated)
03162 {
03163   _dbus_return_if_fail (connection != NULL);
03164   _dbus_return_if_fail (preallocated != NULL);  
03165   _dbus_return_if_fail (connection == preallocated->connection);
03166 
03167   _dbus_list_free_link (preallocated->queue_link);
03168   _dbus_counter_unref (preallocated->counter_link->data);
03169   _dbus_list_free_link (preallocated->counter_link);
03170   dbus_free (preallocated);
03171 }
03172 
03185 void
03186 dbus_connection_send_preallocated (DBusConnection       *connection,
03187                                    DBusPreallocatedSend *preallocated,
03188                                    DBusMessage          *message,
03189                                    dbus_uint32_t        *client_serial)
03190 {
03191   _dbus_return_if_fail (connection != NULL);
03192   _dbus_return_if_fail (preallocated != NULL);
03193   _dbus_return_if_fail (message != NULL);
03194   _dbus_return_if_fail (preallocated->connection == connection);
03195   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03196                         dbus_message_get_member (message) != NULL);
03197   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03198                         (dbus_message_get_interface (message) != NULL &&
03199                          dbus_message_get_member (message) != NULL));
03200 
03201   CONNECTION_LOCK (connection);
03202 
03203 #ifdef HAVE_UNIX_FD_PASSING
03204 
03205   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03206       message->n_unix_fds > 0)
03207     {
03208       /* Refuse to send fds on a connection that cannot handle
03209          them. Unfortunately we cannot return a proper error here, so
03210          the best we can is just return. */
03211       CONNECTION_UNLOCK (connection);
03212       return;
03213     }
03214 
03215 #endif
03216 
03217   _dbus_connection_send_preallocated_and_unlock (connection,
03218                                                  preallocated,
03219                                                  message, client_serial);
03220 }
03221 
03222 static dbus_bool_t
03223 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03224                                           DBusMessage    *message,
03225                                           dbus_uint32_t  *client_serial)
03226 {
03227   DBusPreallocatedSend *preallocated;
03228 
03229   _dbus_assert (connection != NULL);
03230   _dbus_assert (message != NULL);
03231   
03232   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03233   if (preallocated == NULL)
03234     return FALSE;
03235 
03236   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03237                                                          preallocated,
03238                                                          message,
03239                                                          client_serial);
03240   return TRUE;
03241 }
03242 
03270 dbus_bool_t
03271 dbus_connection_send (DBusConnection *connection,
03272                       DBusMessage    *message,
03273                       dbus_uint32_t  *serial)
03274 {
03275   _dbus_return_val_if_fail (connection != NULL, FALSE);
03276   _dbus_return_val_if_fail (message != NULL, FALSE);
03277 
03278   CONNECTION_LOCK (connection);
03279 
03280 #ifdef HAVE_UNIX_FD_PASSING
03281 
03282   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03283       message->n_unix_fds > 0)
03284     {
03285       /* Refuse to send fds on a connection that cannot handle
03286          them. Unfortunately we cannot return a proper error here, so
03287          the best we can is just return. */
03288       CONNECTION_UNLOCK (connection);
03289       return FALSE;
03290     }
03291 
03292 #endif
03293 
03294   return _dbus_connection_send_and_unlock (connection,
03295                                            message,
03296                                            serial);
03297 }
03298 
03299 static dbus_bool_t
03300 reply_handler_timeout (void *data)
03301 {
03302   DBusConnection *connection;
03303   DBusDispatchStatus status;
03304   DBusPendingCall *pending = data;
03305 
03306   connection = _dbus_pending_call_get_connection_and_lock (pending);
03307 
03308   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03309                                                    connection);
03310   _dbus_connection_remove_timeout_unlocked (connection,
03311                                             _dbus_pending_call_get_timeout_unlocked (pending));
03312   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03313 
03314   _dbus_verbose ("middle\n");
03315   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03316 
03317   /* Unlocks, and calls out to user code */
03318   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03319   
03320   return TRUE;
03321 }
03322 
03365 dbus_bool_t
03366 dbus_connection_send_with_reply (DBusConnection     *connection,
03367                                  DBusMessage        *message,
03368                                  DBusPendingCall   **pending_return,
03369                                  int                 timeout_milliseconds)
03370 {
03371   DBusPendingCall *pending;
03372   dbus_int32_t serial = -1;
03373   DBusDispatchStatus status;
03374 
03375   _dbus_return_val_if_fail (connection != NULL, FALSE);
03376   _dbus_return_val_if_fail (message != NULL, FALSE);
03377   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03378 
03379   if (pending_return)
03380     *pending_return = NULL;
03381 
03382   CONNECTION_LOCK (connection);
03383 
03384 #ifdef HAVE_UNIX_FD_PASSING
03385 
03386   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03387       message->n_unix_fds > 0)
03388     {
03389       /* Refuse to send fds on a connection that cannot handle
03390          them. Unfortunately we cannot return a proper error here, so
03391          the best we can do is return TRUE but leave *pending_return
03392          as NULL. */
03393       CONNECTION_UNLOCK (connection);
03394       return TRUE;
03395     }
03396 
03397 #endif
03398 
03399    if (!_dbus_connection_get_is_connected_unlocked (connection))
03400     {
03401       CONNECTION_UNLOCK (connection);
03402 
03403       return TRUE;
03404     }
03405 
03406   pending = _dbus_pending_call_new_unlocked (connection,
03407                                              timeout_milliseconds,
03408                                              reply_handler_timeout);
03409 
03410   if (pending == NULL)
03411     {
03412       CONNECTION_UNLOCK (connection);
03413       return FALSE;
03414     }
03415 
03416   /* Assign a serial to the message */
03417   serial = dbus_message_get_serial (message);
03418   if (serial == 0)
03419     {
03420       serial = _dbus_connection_get_next_client_serial (connection);
03421       dbus_message_set_serial (message, serial);
03422     }
03423 
03424   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03425     goto error;
03426     
03427   /* Insert the serial in the pending replies hash;
03428    * hash takes a refcount on DBusPendingCall.
03429    * Also, add the timeout.
03430    */
03431   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03432                                                       pending))
03433     goto error;
03434  
03435   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03436     {
03437       _dbus_connection_detach_pending_call_and_unlock (connection,
03438                                                        pending);
03439       goto error_unlocked;
03440     }
03441 
03442   if (pending_return)
03443     *pending_return = pending; /* hand off refcount */
03444   else
03445     {
03446       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03447       /* we still have a ref to the pending call in this case, we unref
03448        * after unlocking, below
03449        */
03450     }
03451 
03452   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03453 
03454   /* this calls out to user code */
03455   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03456 
03457   if (pending_return == NULL)
03458     dbus_pending_call_unref (pending);
03459   
03460   return TRUE;
03461 
03462  error:
03463   CONNECTION_UNLOCK (connection);
03464  error_unlocked:
03465   dbus_pending_call_unref (pending);
03466   return FALSE;
03467 }
03468 
03501 DBusMessage*
03502 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03503                                            DBusMessage        *message,
03504                                            int                 timeout_milliseconds,
03505                                            DBusError          *error)
03506 {
03507   DBusMessage *reply;
03508   DBusPendingCall *pending;
03509 
03510   _dbus_return_val_if_fail (connection != NULL, NULL);
03511   _dbus_return_val_if_fail (message != NULL, NULL);
03512   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03513   _dbus_return_val_if_error_is_set (error, NULL);
03514 
03515 #ifdef HAVE_UNIX_FD_PASSING
03516 
03517   CONNECTION_LOCK (connection);
03518   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03519       message->n_unix_fds > 0)
03520     {
03521       CONNECTION_UNLOCK (connection);
03522       dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03523       return NULL;
03524     }
03525   CONNECTION_UNLOCK (connection);
03526 
03527 #endif
03528 
03529   if (!dbus_connection_send_with_reply (connection, message,
03530                                         &pending, timeout_milliseconds))
03531     {
03532       _DBUS_SET_OOM (error);
03533       return NULL;
03534     }
03535 
03536   if (pending == NULL)
03537     {
03538       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03539       return NULL;
03540     }
03541   
03542   dbus_pending_call_block (pending);
03543 
03544   reply = dbus_pending_call_steal_reply (pending);
03545   dbus_pending_call_unref (pending);
03546 
03547   /* call_complete_and_unlock() called from pending_call_block() should
03548    * always fill this in.
03549    */
03550   _dbus_assert (reply != NULL);
03551   
03552    if (dbus_set_error_from_message (error, reply))
03553     {
03554       dbus_message_unref (reply);
03555       return NULL;
03556     }
03557   else
03558     return reply;
03559 }
03560 
03569 static DBusDispatchStatus
03570 _dbus_connection_flush_unlocked (DBusConnection *connection)
03571 {
03572   /* We have to specify DBUS_ITERATION_DO_READING here because
03573    * otherwise we could have two apps deadlock if they are both doing
03574    * a flush(), and the kernel buffers fill up. This could change the
03575    * dispatch status.
03576    */
03577   DBusDispatchStatus status;
03578 
03579   HAVE_LOCK_CHECK (connection);
03580   
03581   while (connection->n_outgoing > 0 &&
03582          _dbus_connection_get_is_connected_unlocked (connection))
03583     {
03584       _dbus_verbose ("doing iteration in\n");
03585       HAVE_LOCK_CHECK (connection);
03586       _dbus_connection_do_iteration_unlocked (connection,
03587                                               NULL,
03588                                               DBUS_ITERATION_DO_READING |
03589                                               DBUS_ITERATION_DO_WRITING |
03590                                               DBUS_ITERATION_BLOCK,
03591                                               -1);
03592     }
03593 
03594   HAVE_LOCK_CHECK (connection);
03595   _dbus_verbose ("middle\n");
03596   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03597 
03598   HAVE_LOCK_CHECK (connection);
03599   return status;
03600 }
03601 
03607 void
03608 dbus_connection_flush (DBusConnection *connection)
03609 {
03610   /* We have to specify DBUS_ITERATION_DO_READING here because
03611    * otherwise we could have two apps deadlock if they are both doing
03612    * a flush(), and the kernel buffers fill up. This could change the
03613    * dispatch status.
03614    */
03615   DBusDispatchStatus status;
03616 
03617   _dbus_return_if_fail (connection != NULL);
03618   
03619   CONNECTION_LOCK (connection);
03620 
03621   status = _dbus_connection_flush_unlocked (connection);
03622   
03623   HAVE_LOCK_CHECK (connection);
03624   /* Unlocks and calls out to user code */
03625   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03626 
03627   _dbus_verbose ("end\n");
03628 }
03629 
03640 static dbus_bool_t
03641 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03642                                      int             timeout_milliseconds, 
03643                                      dbus_bool_t     dispatch)
03644 {
03645   DBusDispatchStatus dstatus;
03646   dbus_bool_t progress_possible;
03647 
03648   /* Need to grab a ref here in case we're a private connection and
03649    * the user drops the last ref in a handler we call; see bug 
03650    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03651    */
03652   dbus_connection_ref (connection);
03653   dstatus = dbus_connection_get_dispatch_status (connection);
03654 
03655   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03656     {
03657       _dbus_verbose ("doing dispatch\n");
03658       dbus_connection_dispatch (connection);
03659       CONNECTION_LOCK (connection);
03660     }
03661   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03662     {
03663       _dbus_verbose ("pausing for memory\n");
03664       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03665       CONNECTION_LOCK (connection);
03666     }
03667   else
03668     {
03669       CONNECTION_LOCK (connection);
03670       if (_dbus_connection_get_is_connected_unlocked (connection))
03671         {
03672           _dbus_verbose ("doing iteration\n");
03673           _dbus_connection_do_iteration_unlocked (connection,
03674                                                   NULL,
03675                                                   DBUS_ITERATION_DO_READING |
03676                                                   DBUS_ITERATION_DO_WRITING |
03677                                                   DBUS_ITERATION_BLOCK,
03678                                                   timeout_milliseconds);
03679         }
03680     }
03681   
03682   HAVE_LOCK_CHECK (connection);
03683   /* If we can dispatch, we can make progress until the Disconnected message
03684    * has been processed; if we can only read/write, we can make progress
03685    * as long as the transport is open.
03686    */
03687   if (dispatch)
03688     progress_possible = connection->n_incoming != 0 ||
03689       connection->disconnect_message_link != NULL;
03690   else
03691     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03692 
03693   CONNECTION_UNLOCK (connection);
03694 
03695   dbus_connection_unref (connection);
03696 
03697   return progress_possible; /* TRUE if we can make more progress */
03698 }
03699 
03700 
03735 dbus_bool_t
03736 dbus_connection_read_write_dispatch (DBusConnection *connection,
03737                                      int             timeout_milliseconds)
03738 {
03739   _dbus_return_val_if_fail (connection != NULL, FALSE);
03740   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03741    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03742 }
03743 
03767 dbus_bool_t 
03768 dbus_connection_read_write (DBusConnection *connection, 
03769                             int             timeout_milliseconds) 
03770 { 
03771   _dbus_return_val_if_fail (connection != NULL, FALSE);
03772   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03773    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03774 }
03775 
03776 /* We need to call this anytime we pop the head of the queue, and then
03777  * update_dispatch_status_and_unlock needs to be called afterward
03778  * which will "process" the disconnected message and set
03779  * disconnected_message_processed.
03780  */
03781 static void
03782 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03783                                              DBusMessage    *head_of_queue)
03784 {
03785   HAVE_LOCK_CHECK (connection);
03786 
03787   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03788   if (connection->disconnect_message_link == NULL &&
03789       dbus_message_is_signal (head_of_queue,
03790                               DBUS_INTERFACE_LOCAL,
03791                               "Disconnected"))
03792     {
03793       connection->disconnected_message_arrived = TRUE;
03794     }
03795 }
03796 
03816 DBusMessage*
03817 dbus_connection_borrow_message (DBusConnection *connection)
03818 {
03819   DBusDispatchStatus status;
03820   DBusMessage *message;
03821 
03822   _dbus_return_val_if_fail (connection != NULL, NULL);
03823 
03824   _dbus_verbose ("start\n");
03825   
03826   /* this is called for the side effect that it queues
03827    * up any messages from the transport
03828    */
03829   status = dbus_connection_get_dispatch_status (connection);
03830   if (status != DBUS_DISPATCH_DATA_REMAINS)
03831     return NULL;
03832   
03833   CONNECTION_LOCK (connection);
03834 
03835   _dbus_connection_acquire_dispatch (connection);
03836 
03837   /* While a message is outstanding, the dispatch lock is held */
03838   _dbus_assert (connection->message_borrowed == NULL);
03839 
03840   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03841   
03842   message = connection->message_borrowed;
03843 
03844   check_disconnected_message_arrived_unlocked (connection, message);
03845   
03846   /* Note that we KEEP the dispatch lock until the message is returned */
03847   if (message == NULL)
03848     _dbus_connection_release_dispatch (connection);
03849 
03850   CONNECTION_UNLOCK (connection);
03851 
03852   /* We don't update dispatch status until it's returned or stolen */
03853   
03854   return message;
03855 }
03856 
03865 void
03866 dbus_connection_return_message (DBusConnection *connection,
03867                                 DBusMessage    *message)
03868 {
03869   DBusDispatchStatus status;
03870   
03871   _dbus_return_if_fail (connection != NULL);
03872   _dbus_return_if_fail (message != NULL);
03873   _dbus_return_if_fail (message == connection->message_borrowed);
03874   _dbus_return_if_fail (connection->dispatch_acquired);
03875   
03876   CONNECTION_LOCK (connection);
03877   
03878   _dbus_assert (message == connection->message_borrowed);
03879   
03880   connection->message_borrowed = NULL;
03881 
03882   _dbus_connection_release_dispatch (connection); 
03883 
03884   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03885   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03886 }
03887 
03897 void
03898 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03899                                         DBusMessage    *message)
03900 {
03901   DBusMessage *pop_message;
03902   DBusDispatchStatus status;
03903 
03904   _dbus_return_if_fail (connection != NULL);
03905   _dbus_return_if_fail (message != NULL);
03906   _dbus_return_if_fail (message == connection->message_borrowed);
03907   _dbus_return_if_fail (connection->dispatch_acquired);
03908   
03909   CONNECTION_LOCK (connection);
03910  
03911   _dbus_assert (message == connection->message_borrowed);
03912 
03913   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03914   _dbus_assert (message == pop_message);
03915   
03916   connection->n_incoming -= 1;
03917  
03918   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03919                  message, connection->n_incoming);
03920  
03921   connection->message_borrowed = NULL;
03922 
03923   _dbus_connection_release_dispatch (connection);
03924 
03925   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03926   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03927 }
03928 
03929 /* See dbus_connection_pop_message, but requires the caller to own
03930  * the lock before calling. May drop the lock while running.
03931  */
03932 static DBusList*
03933 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03934 {
03935   HAVE_LOCK_CHECK (connection);
03936   
03937   _dbus_assert (connection->message_borrowed == NULL);
03938   
03939   if (connection->n_incoming > 0)
03940     {
03941       DBusList *link;
03942 
03943       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03944       connection->n_incoming -= 1;
03945 
03946       _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03947                      link->data,
03948                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
03949                      dbus_message_get_path (link->data) ?
03950                      dbus_message_get_path (link->data) :
03951                      "no path",
03952                      dbus_message_get_interface (link->data) ?
03953                      dbus_message_get_interface (link->data) :
03954                      "no interface",
03955                      dbus_message_get_member (link->data) ?
03956                      dbus_message_get_member (link->data) :
03957                      "no member",
03958                      dbus_message_get_signature (link->data),
03959                      connection, connection->n_incoming);
03960 
03961       check_disconnected_message_arrived_unlocked (connection, link->data);
03962       
03963       return link;
03964     }
03965   else
03966     return NULL;
03967 }
03968 
03969 /* See dbus_connection_pop_message, but requires the caller to own
03970  * the lock before calling. May drop the lock while running.
03971  */
03972 static DBusMessage*
03973 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03974 {
03975   DBusList *link;
03976 
03977   HAVE_LOCK_CHECK (connection);
03978   
03979   link = _dbus_connection_pop_message_link_unlocked (connection);
03980 
03981   if (link != NULL)
03982     {
03983       DBusMessage *message;
03984       
03985       message = link->data;
03986       
03987       _dbus_list_free_link (link);
03988       
03989       return message;
03990     }
03991   else
03992     return NULL;
03993 }
03994 
03995 static void
03996 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03997                                                 DBusList       *message_link)
03998 {
03999   HAVE_LOCK_CHECK (connection);
04000   
04001   _dbus_assert (message_link != NULL);
04002   /* You can't borrow a message while a link is outstanding */
04003   _dbus_assert (connection->message_borrowed == NULL);
04004   /* We had to have the dispatch lock across the pop/putback */
04005   _dbus_assert (connection->dispatch_acquired);
04006 
04007   _dbus_list_prepend_link (&connection->incoming_messages,
04008                            message_link);
04009   connection->n_incoming += 1;
04010 
04011   _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
04012                  message_link->data,
04013                  dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
04014                  dbus_message_get_interface (message_link->data) ?
04015                  dbus_message_get_interface (message_link->data) :
04016                  "no interface",
04017                  dbus_message_get_member (message_link->data) ?
04018                  dbus_message_get_member (message_link->data) :
04019                  "no member",
04020                  dbus_message_get_signature (message_link->data),
04021                  connection, connection->n_incoming);
04022 }
04023 
04043 DBusMessage*
04044 dbus_connection_pop_message (DBusConnection *connection)
04045 {
04046   DBusMessage *message;
04047   DBusDispatchStatus status;
04048 
04049   _dbus_verbose ("start\n");
04050   
04051   /* this is called for the side effect that it queues
04052    * up any messages from the transport
04053    */
04054   status = dbus_connection_get_dispatch_status (connection);
04055   if (status != DBUS_DISPATCH_DATA_REMAINS)
04056     return NULL;
04057   
04058   CONNECTION_LOCK (connection);
04059   _dbus_connection_acquire_dispatch (connection);
04060   HAVE_LOCK_CHECK (connection);
04061   
04062   message = _dbus_connection_pop_message_unlocked (connection);
04063 
04064   _dbus_verbose ("Returning popped message %p\n", message);    
04065 
04066   _dbus_connection_release_dispatch (connection);
04067 
04068   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04069   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04070   
04071   return message;
04072 }
04073 
04081 static void
04082 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04083 {
04084   HAVE_LOCK_CHECK (connection);
04085 
04086   _dbus_connection_ref_unlocked (connection);
04087   CONNECTION_UNLOCK (connection);
04088   
04089   _dbus_verbose ("locking dispatch_mutex\n");
04090   _dbus_mutex_lock (connection->dispatch_mutex);
04091 
04092   while (connection->dispatch_acquired)
04093     {
04094       _dbus_verbose ("waiting for dispatch to be acquirable\n");
04095       _dbus_condvar_wait (connection->dispatch_cond, 
04096                           connection->dispatch_mutex);
04097     }
04098   
04099   _dbus_assert (!connection->dispatch_acquired);
04100 
04101   connection->dispatch_acquired = TRUE;
04102 
04103   _dbus_verbose ("unlocking dispatch_mutex\n");
04104   _dbus_mutex_unlock (connection->dispatch_mutex);
04105   
04106   CONNECTION_LOCK (connection);
04107   _dbus_connection_unref_unlocked (connection);
04108 }
04109 
04117 static void
04118 _dbus_connection_release_dispatch (DBusConnection *connection)
04119 {
04120   HAVE_LOCK_CHECK (connection);
04121   
04122   _dbus_verbose ("locking dispatch_mutex\n");
04123   _dbus_mutex_lock (connection->dispatch_mutex);
04124   
04125   _dbus_assert (connection->dispatch_acquired);
04126 
04127   connection->dispatch_acquired = FALSE;
04128   _dbus_condvar_wake_one (connection->dispatch_cond);
04129 
04130   _dbus_verbose ("unlocking dispatch_mutex\n");
04131   _dbus_mutex_unlock (connection->dispatch_mutex);
04132 }
04133 
04134 static void
04135 _dbus_connection_failed_pop (DBusConnection *connection,
04136                              DBusList       *message_link)
04137 {
04138   _dbus_list_prepend_link (&connection->incoming_messages,
04139                            message_link);
04140   connection->n_incoming += 1;
04141 }
04142 
04143 /* Note this may be called multiple times since we don't track whether we already did it */
04144 static void
04145 notify_disconnected_unlocked (DBusConnection *connection)
04146 {
04147   HAVE_LOCK_CHECK (connection);
04148 
04149   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04150    * connection from dbus_bus_get(). We make the same guarantee for
04151    * dbus_connection_open() but in a different way since we don't want to
04152    * unref right here; we instead check for connectedness before returning
04153    * the connection from the hash.
04154    */
04155   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04156 
04157   /* Dump the outgoing queue, we aren't going to be able to
04158    * send it now, and we'd like accessors like
04159    * dbus_connection_get_outgoing_size() to be accurate.
04160    */
04161   if (connection->n_outgoing > 0)
04162     {
04163       DBusList *link;
04164       
04165       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04166                      connection->n_outgoing);
04167       
04168       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04169         {
04170           _dbus_connection_message_sent (connection, link->data);
04171         }
04172     } 
04173 }
04174 
04175 /* Note this may be called multiple times since we don't track whether we already did it */
04176 static DBusDispatchStatus
04177 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04178 {
04179   HAVE_LOCK_CHECK (connection);
04180   
04181   if (connection->disconnect_message_link != NULL)
04182     {
04183       _dbus_verbose ("Sending disconnect message\n");
04184       
04185       /* If we have pending calls, queue their timeouts - we want the Disconnected
04186        * to be the last message, after these timeouts.
04187        */
04188       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04189       
04190       /* We haven't sent the disconnect message already,
04191        * and all real messages have been queued up.
04192        */
04193       _dbus_connection_queue_synthesized_message_link (connection,
04194                                                        connection->disconnect_message_link);
04195       connection->disconnect_message_link = NULL;
04196 
04197       return DBUS_DISPATCH_DATA_REMAINS;
04198     }
04199 
04200   return DBUS_DISPATCH_COMPLETE;
04201 }
04202 
04203 static DBusDispatchStatus
04204 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04205 {
04206   HAVE_LOCK_CHECK (connection);
04207   
04208   if (connection->n_incoming > 0)
04209     return DBUS_DISPATCH_DATA_REMAINS;
04210   else if (!_dbus_transport_queue_messages (connection->transport))
04211     return DBUS_DISPATCH_NEED_MEMORY;
04212   else
04213     {
04214       DBusDispatchStatus status;
04215       dbus_bool_t is_connected;
04216       
04217       status = _dbus_transport_get_dispatch_status (connection->transport);
04218       is_connected = _dbus_transport_get_is_connected (connection->transport);
04219 
04220       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04221                      DISPATCH_STATUS_NAME (status), is_connected);
04222       
04223       if (!is_connected)
04224         {
04225           /* It's possible this would be better done by having an explicit
04226            * notification from _dbus_transport_disconnect() that would
04227            * synchronously do this, instead of waiting for the next dispatch
04228            * status check. However, probably not good to change until it causes
04229            * a problem.
04230            */
04231           notify_disconnected_unlocked (connection);
04232 
04233           /* I'm not sure this is needed; the idea is that we want to
04234            * queue the Disconnected only after we've read all the
04235            * messages, but if we're disconnected maybe we are guaranteed
04236            * to have read them all ?
04237            */
04238           if (status == DBUS_DISPATCH_COMPLETE)
04239             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04240         }
04241       
04242       if (status != DBUS_DISPATCH_COMPLETE)
04243         return status;
04244       else if (connection->n_incoming > 0)
04245         return DBUS_DISPATCH_DATA_REMAINS;
04246       else
04247         return DBUS_DISPATCH_COMPLETE;
04248     }
04249 }
04250 
04251 static void
04252 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04253                                                     DBusDispatchStatus new_status)
04254 {
04255   dbus_bool_t changed;
04256   DBusDispatchStatusFunction function;
04257   void *data;
04258 
04259   HAVE_LOCK_CHECK (connection);
04260 
04261   _dbus_connection_ref_unlocked (connection);
04262 
04263   changed = new_status != connection->last_dispatch_status;
04264 
04265   connection->last_dispatch_status = new_status;
04266 
04267   function = connection->dispatch_status_function;
04268   data = connection->dispatch_status_data;
04269 
04270   if (connection->disconnected_message_arrived &&
04271       !connection->disconnected_message_processed)
04272     {
04273       connection->disconnected_message_processed = TRUE;
04274       
04275       /* this does an unref, but we have a ref
04276        * so we should not run the finalizer here
04277        * inside the lock.
04278        */
04279       connection_forget_shared_unlocked (connection);
04280 
04281       if (connection->exit_on_disconnect)
04282         {
04283           CONNECTION_UNLOCK (connection);            
04284           
04285           _dbus_verbose ("Exiting on Disconnected signal\n");
04286           _dbus_exit (1);
04287           _dbus_assert_not_reached ("Call to exit() returned");
04288         }
04289     }
04290   
04291   /* We drop the lock */
04292   CONNECTION_UNLOCK (connection);
04293   
04294   if (changed && function)
04295     {
04296       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04297                      connection, new_status,
04298                      DISPATCH_STATUS_NAME (new_status));
04299       (* function) (connection, new_status, data);      
04300     }
04301   
04302   dbus_connection_unref (connection);
04303 }
04304 
04330 DBusDispatchStatus
04331 dbus_connection_get_dispatch_status (DBusConnection *connection)
04332 {
04333   DBusDispatchStatus status;
04334 
04335   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04336 
04337   _dbus_verbose ("start\n");
04338   
04339   CONNECTION_LOCK (connection);
04340 
04341   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04342   
04343   CONNECTION_UNLOCK (connection);
04344 
04345   return status;
04346 }
04347 
04351 static DBusHandlerResult
04352 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04353                                                  DBusMessage    *message)
04354 {
04355   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04356     {
04357       /* This means we're letting the bus route this message */
04358       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04359     }
04360   else if (dbus_message_is_method_call (message,
04361                                         DBUS_INTERFACE_PEER,
04362                                         "Ping"))
04363     {
04364       DBusMessage *ret;
04365       dbus_bool_t sent;
04366       
04367       ret = dbus_message_new_method_return (message);
04368       if (ret == NULL)
04369         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04370      
04371       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04372 
04373       dbus_message_unref (ret);
04374 
04375       if (!sent)
04376         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04377       
04378       return DBUS_HANDLER_RESULT_HANDLED;
04379     }
04380   else if (dbus_message_is_method_call (message,
04381                                         DBUS_INTERFACE_PEER,
04382                                         "GetMachineId"))
04383     {
04384       DBusMessage *ret;
04385       dbus_bool_t sent;
04386       DBusString uuid;
04387       
04388       ret = dbus_message_new_method_return (message);
04389       if (ret == NULL)
04390         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04391 
04392       sent = FALSE;
04393       _dbus_string_init (&uuid);
04394       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04395         {
04396           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04397           if (dbus_message_append_args (ret,
04398                                         DBUS_TYPE_STRING, &v_STRING,
04399                                         DBUS_TYPE_INVALID))
04400             {
04401               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04402             }
04403         }
04404       _dbus_string_free (&uuid);
04405       
04406       dbus_message_unref (ret);
04407 
04408       if (!sent)
04409         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04410       
04411       return DBUS_HANDLER_RESULT_HANDLED;
04412     }
04413   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04414     {
04415       /* We need to bounce anything else with this interface, otherwise apps
04416        * could start extending the interface and when we added extensions
04417        * here to DBusConnection we'd break those apps.
04418        */
04419       
04420       DBusMessage *ret;
04421       dbus_bool_t sent;
04422       
04423       ret = dbus_message_new_error (message,
04424                                     DBUS_ERROR_UNKNOWN_METHOD,
04425                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04426       if (ret == NULL)
04427         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04428       
04429       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04430       
04431       dbus_message_unref (ret);
04432       
04433       if (!sent)
04434         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04435       
04436       return DBUS_HANDLER_RESULT_HANDLED;
04437     }
04438   else
04439     {
04440       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04441     }
04442 }
04443 
04450 static DBusHandlerResult
04451 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04452                                                            DBusMessage    *message)
04453 {
04454   /* We just run one filter for now but have the option to run more
04455      if the spec calls for it in the future */
04456 
04457   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04458 }
04459 
04502 DBusDispatchStatus
04503 dbus_connection_dispatch (DBusConnection *connection)
04504 {
04505   DBusMessage *message;
04506   DBusList *link, *filter_list_copy, *message_link;
04507   DBusHandlerResult result;
04508   DBusPendingCall *pending;
04509   dbus_int32_t reply_serial;
04510   DBusDispatchStatus status;
04511 
04512   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04513 
04514   _dbus_verbose ("\n");
04515   
04516   CONNECTION_LOCK (connection);
04517   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04518   if (status != DBUS_DISPATCH_DATA_REMAINS)
04519     {
04520       /* unlocks and calls out to user code */
04521       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04522       return status;
04523     }
04524   
04525   /* We need to ref the connection since the callback could potentially
04526    * drop the last ref to it
04527    */
04528   _dbus_connection_ref_unlocked (connection);
04529 
04530   _dbus_connection_acquire_dispatch (connection);
04531   HAVE_LOCK_CHECK (connection);
04532 
04533   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04534   if (message_link == NULL)
04535     {
04536       /* another thread dispatched our stuff */
04537 
04538       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04539       
04540       _dbus_connection_release_dispatch (connection);
04541 
04542       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04543 
04544       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04545       
04546       dbus_connection_unref (connection);
04547       
04548       return status;
04549     }
04550 
04551   message = message_link->data;
04552 
04553   _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04554                  message,
04555                  dbus_message_type_to_string (dbus_message_get_type (message)),
04556                  dbus_message_get_interface (message) ?
04557                  dbus_message_get_interface (message) :
04558                  "no interface",
04559                  dbus_message_get_member (message) ?
04560                  dbus_message_get_member (message) :
04561                  "no member",
04562                  dbus_message_get_signature (message));
04563 
04564   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04565   
04566   /* Pending call handling must be first, because if you do
04567    * dbus_connection_send_with_reply_and_block() or
04568    * dbus_pending_call_block() then no handlers/filters will be run on
04569    * the reply. We want consistent semantics in the case where we
04570    * dbus_connection_dispatch() the reply.
04571    */
04572   
04573   reply_serial = dbus_message_get_reply_serial (message);
04574   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04575                                          reply_serial);
04576   if (pending)
04577     {
04578       _dbus_verbose ("Dispatching a pending reply\n");
04579       complete_pending_call_and_unlock (connection, pending, message);
04580       pending = NULL; /* it's probably unref'd */
04581       
04582       CONNECTION_LOCK (connection);
04583       _dbus_verbose ("pending call completed in dispatch\n");
04584       result = DBUS_HANDLER_RESULT_HANDLED;
04585       goto out;
04586     }
04587 
04588   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04589   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04590     goto out;
04591  
04592   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04593     {
04594       _dbus_connection_release_dispatch (connection);
04595       HAVE_LOCK_CHECK (connection);
04596       
04597       _dbus_connection_failed_pop (connection, message_link);
04598 
04599       /* unlocks and calls user code */
04600       _dbus_connection_update_dispatch_status_and_unlock (connection,
04601                                                           DBUS_DISPATCH_NEED_MEMORY);
04602       dbus_connection_unref (connection);
04603       
04604       return DBUS_DISPATCH_NEED_MEMORY;
04605     }
04606   
04607   _dbus_list_foreach (&filter_list_copy,
04608                       (DBusForeachFunction)_dbus_message_filter_ref,
04609                       NULL);
04610 
04611   /* We're still protected from dispatch() reentrancy here
04612    * since we acquired the dispatcher
04613    */
04614   CONNECTION_UNLOCK (connection);
04615   
04616   link = _dbus_list_get_first_link (&filter_list_copy);
04617   while (link != NULL)
04618     {
04619       DBusMessageFilter *filter = link->data;
04620       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04621 
04622       if (filter->function == NULL)
04623         {
04624           _dbus_verbose ("  filter was removed in a callback function\n");
04625           link = next;
04626           continue;
04627         }
04628 
04629       _dbus_verbose ("  running filter on message %p\n", message);
04630       result = (* filter->function) (connection, message, filter->user_data);
04631 
04632       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04633         break;
04634 
04635       link = next;
04636     }
04637 
04638   _dbus_list_foreach (&filter_list_copy,
04639                       (DBusForeachFunction)_dbus_message_filter_unref,
04640                       NULL);
04641   _dbus_list_clear (&filter_list_copy);
04642   
04643   CONNECTION_LOCK (connection);
04644 
04645   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04646     {
04647       _dbus_verbose ("No memory\n");
04648       goto out;
04649     }
04650   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04651     {
04652       _dbus_verbose ("filter handled message in dispatch\n");
04653       goto out;
04654     }
04655 
04656   /* We're still protected from dispatch() reentrancy here
04657    * since we acquired the dispatcher
04658    */
04659   _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
04660                  message,
04661                  dbus_message_type_to_string (dbus_message_get_type (message)),
04662                  dbus_message_get_interface (message) ?
04663                  dbus_message_get_interface (message) :
04664                  "no interface",
04665                  dbus_message_get_member (message) ?
04666                  dbus_message_get_member (message) :
04667                  "no member",
04668                  dbus_message_get_signature (message));
04669 
04670   HAVE_LOCK_CHECK (connection);
04671   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04672                                                   message);
04673   
04674   CONNECTION_LOCK (connection);
04675 
04676   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04677     {
04678       _dbus_verbose ("object tree handled message in dispatch\n");
04679       goto out;
04680     }
04681 
04682   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04683     {
04684       DBusMessage *reply;
04685       DBusString str;
04686       DBusPreallocatedSend *preallocated;
04687 
04688       _dbus_verbose ("  sending error %s\n",
04689                      DBUS_ERROR_UNKNOWN_METHOD);
04690       
04691       if (!_dbus_string_init (&str))
04692         {
04693           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04694           _dbus_verbose ("no memory for error string in dispatch\n");
04695           goto out;
04696         }
04697               
04698       if (!_dbus_string_append_printf (&str,
04699                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04700                                        dbus_message_get_member (message),
04701                                        dbus_message_get_signature (message),
04702                                        dbus_message_get_interface (message)))
04703         {
04704           _dbus_string_free (&str);
04705           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04706           _dbus_verbose ("no memory for error string in dispatch\n");
04707           goto out;
04708         }
04709       
04710       reply = dbus_message_new_error (message,
04711                                       DBUS_ERROR_UNKNOWN_METHOD,
04712                                       _dbus_string_get_const_data (&str));
04713       _dbus_string_free (&str);
04714 
04715       if (reply == NULL)
04716         {
04717           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04718           _dbus_verbose ("no memory for error reply in dispatch\n");
04719           goto out;
04720         }
04721       
04722       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04723 
04724       if (preallocated == NULL)
04725         {
04726           dbus_message_unref (reply);
04727           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04728           _dbus_verbose ("no memory for error send in dispatch\n");
04729           goto out;
04730         }
04731 
04732       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04733                                                              reply, NULL);
04734 
04735       dbus_message_unref (reply);
04736       
04737       result = DBUS_HANDLER_RESULT_HANDLED;
04738     }
04739   
04740   _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04741                  dbus_message_type_to_string (dbus_message_get_type (message)),
04742                  dbus_message_get_interface (message) ?
04743                  dbus_message_get_interface (message) :
04744                  "no interface",
04745                  dbus_message_get_member (message) ?
04746                  dbus_message_get_member (message) :
04747                  "no member",
04748                  dbus_message_get_signature (message),
04749                  connection);
04750   
04751  out:
04752   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04753     {
04754       _dbus_verbose ("out of memory\n");
04755       
04756       /* Put message back, and we'll start over.
04757        * Yes this means handlers must be idempotent if they
04758        * don't return HANDLED; c'est la vie.
04759        */
04760       _dbus_connection_putback_message_link_unlocked (connection,
04761                                                       message_link);
04762     }
04763   else
04764     {
04765       _dbus_verbose (" ... done dispatching\n");
04766       
04767       _dbus_list_free_link (message_link);
04768       dbus_message_unref (message); /* don't want the message to count in max message limits
04769                                      * in computing dispatch status below
04770                                      */
04771     }
04772   
04773   _dbus_connection_release_dispatch (connection);
04774   HAVE_LOCK_CHECK (connection);
04775 
04776   _dbus_verbose ("before final status update\n");
04777   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04778 
04779   /* unlocks and calls user code */
04780   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04781   
04782   dbus_connection_unref (connection);
04783   
04784   return status;
04785 }
04786 
04848 dbus_bool_t
04849 dbus_connection_set_watch_functions (DBusConnection              *connection,
04850                                      DBusAddWatchFunction         add_function,
04851                                      DBusRemoveWatchFunction      remove_function,
04852                                      DBusWatchToggledFunction     toggled_function,
04853                                      void                        *data,
04854                                      DBusFreeFunction             free_data_function)
04855 {
04856   dbus_bool_t retval;
04857 
04858   _dbus_return_val_if_fail (connection != NULL, FALSE);
04859   
04860   CONNECTION_LOCK (connection);
04861 
04862   retval = _dbus_watch_list_set_functions (connection->watches,
04863                                            add_function, remove_function,
04864                                            toggled_function,
04865                                            data, free_data_function);
04866 
04867   CONNECTION_UNLOCK (connection);
04868 
04869   return retval;
04870 }
04871 
04911 dbus_bool_t
04912 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04913                                          DBusAddTimeoutFunction     add_function,
04914                                          DBusRemoveTimeoutFunction  remove_function,
04915                                          DBusTimeoutToggledFunction toggled_function,
04916                                          void                      *data,
04917                                          DBusFreeFunction           free_data_function)
04918 {
04919   dbus_bool_t retval;
04920 
04921   _dbus_return_val_if_fail (connection != NULL, FALSE);
04922   
04923   CONNECTION_LOCK (connection);
04924 
04925   retval = _dbus_timeout_list_set_functions (connection->timeouts,
04926                                              add_function, remove_function,
04927                                              toggled_function,
04928                                              data, free_data_function);
04929 
04930   CONNECTION_UNLOCK (connection);
04931 
04932   return retval;
04933 }
04934 
04949 void
04950 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04951                                           DBusWakeupMainFunction     wakeup_main_function,
04952                                           void                      *data,
04953                                           DBusFreeFunction           free_data_function)
04954 {
04955   void *old_data;
04956   DBusFreeFunction old_free_data;
04957 
04958   _dbus_return_if_fail (connection != NULL);
04959   
04960   CONNECTION_LOCK (connection);
04961   old_data = connection->wakeup_main_data;
04962   old_free_data = connection->free_wakeup_main_data;
04963 
04964   connection->wakeup_main_function = wakeup_main_function;
04965   connection->wakeup_main_data = data;
04966   connection->free_wakeup_main_data = free_data_function;
04967   
04968   CONNECTION_UNLOCK (connection);
04969 
04970   /* Callback outside the lock */
04971   if (old_free_data)
04972     (*old_free_data) (old_data);
04973 }
04974 
04995 void
04996 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04997                                               DBusDispatchStatusFunction  function,
04998                                               void                       *data,
04999                                               DBusFreeFunction            free_data_function)
05000 {
05001   void *old_data;
05002   DBusFreeFunction old_free_data;
05003 
05004   _dbus_return_if_fail (connection != NULL);
05005   
05006   CONNECTION_LOCK (connection);
05007   old_data = connection->dispatch_status_data;
05008   old_free_data = connection->free_dispatch_status_data;
05009 
05010   connection->dispatch_status_function = function;
05011   connection->dispatch_status_data = data;
05012   connection->free_dispatch_status_data = free_data_function;
05013   
05014   CONNECTION_UNLOCK (connection);
05015 
05016   /* Callback outside the lock */
05017   if (old_free_data)
05018     (*old_free_data) (old_data);
05019 }
05020 
05040 dbus_bool_t
05041 dbus_connection_get_unix_fd (DBusConnection *connection,
05042                              int            *fd)
05043 {
05044   _dbus_return_val_if_fail (connection != NULL, FALSE);
05045   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05046 
05047 #ifdef DBUS_WIN
05048   /* FIXME do this on a lower level */
05049   return FALSE;
05050 #endif
05051   
05052   return dbus_connection_get_socket(connection, fd);
05053 }
05054 
05070 dbus_bool_t
05071 dbus_connection_get_socket(DBusConnection              *connection,
05072                            int                         *fd)
05073 {
05074   dbus_bool_t retval;
05075 
05076   _dbus_return_val_if_fail (connection != NULL, FALSE);
05077   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05078   
05079   CONNECTION_LOCK (connection);
05080   
05081   retval = _dbus_transport_get_socket_fd (connection->transport,
05082                                           fd);
05083 
05084   CONNECTION_UNLOCK (connection);
05085 
05086   return retval;
05087 }
05088 
05089 
05112 dbus_bool_t
05113 dbus_connection_get_unix_user (DBusConnection *connection,
05114                                unsigned long  *uid)
05115 {
05116   dbus_bool_t result;
05117 
05118   _dbus_return_val_if_fail (connection != NULL, FALSE);
05119   _dbus_return_val_if_fail (uid != NULL, FALSE);
05120   
05121   CONNECTION_LOCK (connection);
05122 
05123   if (!_dbus_transport_get_is_authenticated (connection->transport))
05124     result = FALSE;
05125   else
05126     result = _dbus_transport_get_unix_user (connection->transport,
05127                                             uid);
05128 
05129 #ifdef DBUS_WIN
05130   _dbus_assert (!result);
05131 #endif
05132   
05133   CONNECTION_UNLOCK (connection);
05134 
05135   return result;
05136 }
05137 
05148 dbus_bool_t
05149 dbus_connection_get_unix_process_id (DBusConnection *connection,
05150                                      unsigned long  *pid)
05151 {
05152   dbus_bool_t result;
05153 
05154   _dbus_return_val_if_fail (connection != NULL, FALSE);
05155   _dbus_return_val_if_fail (pid != NULL, FALSE);
05156   
05157   CONNECTION_LOCK (connection);
05158 
05159   if (!_dbus_transport_get_is_authenticated (connection->transport))
05160     result = FALSE;
05161   else
05162     result = _dbus_transport_get_unix_process_id (connection->transport,
05163                                                   pid);
05164 
05165   CONNECTION_UNLOCK (connection);
05166 
05167   return result;
05168 }
05169 
05180 dbus_bool_t
05181 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05182                                             void          **data,
05183                                             dbus_int32_t   *data_size)
05184 {
05185   dbus_bool_t result;
05186 
05187   _dbus_return_val_if_fail (connection != NULL, FALSE);
05188   _dbus_return_val_if_fail (data != NULL, FALSE);
05189   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05190   
05191   CONNECTION_LOCK (connection);
05192 
05193   if (!_dbus_transport_get_is_authenticated (connection->transport))
05194     result = FALSE;
05195   else
05196     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05197                                                          data,
05198                                                          data_size);
05199   CONNECTION_UNLOCK (connection);
05200 
05201   return result;
05202 }
05203 
05226 void
05227 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05228                                         DBusAllowUnixUserFunction   function,
05229                                         void                       *data,
05230                                         DBusFreeFunction            free_data_function)
05231 {
05232   void *old_data = NULL;
05233   DBusFreeFunction old_free_function = NULL;
05234 
05235   _dbus_return_if_fail (connection != NULL);
05236   
05237   CONNECTION_LOCK (connection);
05238   _dbus_transport_set_unix_user_function (connection->transport,
05239                                           function, data, free_data_function,
05240                                           &old_data, &old_free_function);
05241   CONNECTION_UNLOCK (connection);
05242 
05243   if (old_free_function != NULL)
05244     (* old_free_function) (old_data);
05245 }
05246 
05278 dbus_bool_t
05279 dbus_connection_get_windows_user (DBusConnection             *connection,
05280                                   char                      **windows_sid_p)
05281 {
05282   dbus_bool_t result;
05283 
05284   _dbus_return_val_if_fail (connection != NULL, FALSE);
05285   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05286   
05287   CONNECTION_LOCK (connection);
05288 
05289   if (!_dbus_transport_get_is_authenticated (connection->transport))
05290     result = FALSE;
05291   else
05292     result = _dbus_transport_get_windows_user (connection->transport,
05293                                                windows_sid_p);
05294 
05295 #ifdef DBUS_UNIX
05296   _dbus_assert (!result);
05297 #endif
05298   
05299   CONNECTION_UNLOCK (connection);
05300 
05301   return result;
05302 }
05303 
05325 void
05326 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05327                                            DBusAllowWindowsUserFunction function,
05328                                            void                        *data,
05329                                            DBusFreeFunction             free_data_function)
05330 {
05331   void *old_data = NULL;
05332   DBusFreeFunction old_free_function = NULL;
05333 
05334   _dbus_return_if_fail (connection != NULL);
05335   
05336   CONNECTION_LOCK (connection);
05337   _dbus_transport_set_windows_user_function (connection->transport,
05338                                              function, data, free_data_function,
05339                                              &old_data, &old_free_function);
05340   CONNECTION_UNLOCK (connection);
05341 
05342   if (old_free_function != NULL)
05343     (* old_free_function) (old_data);
05344 }
05345 
05372 void
05373 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05374                                      dbus_bool_t                 value)
05375 {
05376   _dbus_return_if_fail (connection != NULL);
05377   
05378   CONNECTION_LOCK (connection);
05379   _dbus_transport_set_allow_anonymous (connection->transport, value);
05380   CONNECTION_UNLOCK (connection);
05381 }
05382 
05400 void
05401 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05402                                          dbus_bool_t                 value)
05403 {
05404   _dbus_return_if_fail (connection != NULL);
05405   
05406   CONNECTION_LOCK (connection);
05407   connection->route_peer_messages = TRUE;
05408   CONNECTION_UNLOCK (connection);
05409 }
05410 
05432 dbus_bool_t
05433 dbus_connection_add_filter (DBusConnection            *connection,
05434                             DBusHandleMessageFunction  function,
05435                             void                      *user_data,
05436                             DBusFreeFunction           free_data_function)
05437 {
05438   DBusMessageFilter *filter;
05439   
05440   _dbus_return_val_if_fail (connection != NULL, FALSE);
05441   _dbus_return_val_if_fail (function != NULL, FALSE);
05442 
05443   filter = dbus_new0 (DBusMessageFilter, 1);
05444   if (filter == NULL)
05445     return FALSE;
05446 
05447   _dbus_atomic_inc (&filter->refcount);
05448 
05449   CONNECTION_LOCK (connection);
05450 
05451   if (!_dbus_list_append (&connection->filter_list,
05452                           filter))
05453     {
05454       _dbus_message_filter_unref (filter);
05455       CONNECTION_UNLOCK (connection);
05456       return FALSE;
05457     }
05458 
05459   /* Fill in filter after all memory allocated,
05460    * so we don't run the free_user_data_function
05461    * if the add_filter() fails
05462    */
05463   
05464   filter->function = function;
05465   filter->user_data = user_data;
05466   filter->free_user_data_function = free_data_function;
05467         
05468   CONNECTION_UNLOCK (connection);
05469   return TRUE;
05470 }
05471 
05484 void
05485 dbus_connection_remove_filter (DBusConnection            *connection,
05486                                DBusHandleMessageFunction  function,
05487                                void                      *user_data)
05488 {
05489   DBusList *link;
05490   DBusMessageFilter *filter;
05491   
05492   _dbus_return_if_fail (connection != NULL);
05493   _dbus_return_if_fail (function != NULL);
05494   
05495   CONNECTION_LOCK (connection);
05496 
05497   filter = NULL;
05498   
05499   link = _dbus_list_get_last_link (&connection->filter_list);
05500   while (link != NULL)
05501     {
05502       filter = link->data;
05503 
05504       if (filter->function == function &&
05505           filter->user_data == user_data)
05506         {
05507           _dbus_list_remove_link (&connection->filter_list, link);
05508           filter->function = NULL;
05509           
05510           break;
05511         }
05512         
05513       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05514       filter = NULL;
05515     }
05516   
05517   CONNECTION_UNLOCK (connection);
05518 
05519 #ifndef DBUS_DISABLE_CHECKS
05520   if (filter == NULL)
05521     {
05522       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05523                                function, user_data);
05524       return;
05525     }
05526 #endif
05527   
05528   /* Call application code */
05529   if (filter->free_user_data_function)
05530     (* filter->free_user_data_function) (filter->user_data);
05531 
05532   filter->free_user_data_function = NULL;
05533   filter->user_data = NULL;
05534   
05535   _dbus_message_filter_unref (filter);
05536 }
05537 
05550 dbus_bool_t
05551 dbus_connection_try_register_object_path (DBusConnection              *connection,
05552                                           const char                  *path,
05553                                           const DBusObjectPathVTable  *vtable,
05554                                           void                        *user_data,
05555                                           DBusError                   *error)
05556 {
05557   char **decomposed_path;
05558   dbus_bool_t retval;
05559   
05560   _dbus_return_val_if_fail (connection != NULL, FALSE);
05561   _dbus_return_val_if_fail (path != NULL, FALSE);
05562   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05563   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05564 
05565   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05566     return FALSE;
05567 
05568   CONNECTION_LOCK (connection);
05569 
05570   retval = _dbus_object_tree_register (connection->objects,
05571                                        FALSE,
05572                                        (const char **) decomposed_path, vtable,
05573                                        user_data, error);
05574 
05575   CONNECTION_UNLOCK (connection);
05576 
05577   dbus_free_string_array (decomposed_path);
05578 
05579   return retval;
05580 }
05581 
05597 dbus_bool_t
05598 dbus_connection_register_object_path (DBusConnection              *connection,
05599                                       const char                  *path,
05600                                       const DBusObjectPathVTable  *vtable,
05601                                       void                        *user_data)
05602 {
05603   char **decomposed_path;
05604   dbus_bool_t retval;
05605   DBusError error = DBUS_ERROR_INIT;
05606 
05607   _dbus_return_val_if_fail (connection != NULL, FALSE);
05608   _dbus_return_val_if_fail (path != NULL, FALSE);
05609   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05610   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05611 
05612   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05613     return FALSE;
05614 
05615   CONNECTION_LOCK (connection);
05616 
05617   retval = _dbus_object_tree_register (connection->objects,
05618                                        FALSE,
05619                                        (const char **) decomposed_path, vtable,
05620                                        user_data, &error);
05621 
05622   CONNECTION_UNLOCK (connection);
05623 
05624   dbus_free_string_array (decomposed_path);
05625 
05626   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05627     {
05628       _dbus_warn ("%s\n", error.message);
05629       dbus_error_free (&error);
05630       return FALSE;
05631     }
05632 
05633   return retval;
05634 }
05635 
05650 dbus_bool_t
05651 dbus_connection_try_register_fallback (DBusConnection              *connection,
05652                                        const char                  *path,
05653                                        const DBusObjectPathVTable  *vtable,
05654                                        void                        *user_data,
05655                                        DBusError                   *error)
05656 {
05657   char **decomposed_path;
05658   dbus_bool_t retval;
05659 
05660   _dbus_return_val_if_fail (connection != NULL, FALSE);
05661   _dbus_return_val_if_fail (path != NULL, FALSE);
05662   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05663   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05664 
05665   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05666     return FALSE;
05667 
05668   CONNECTION_LOCK (connection);
05669 
05670   retval = _dbus_object_tree_register (connection->objects,
05671                                        TRUE,
05672                                        (const char **) decomposed_path, vtable,
05673                                        user_data, error);
05674 
05675   CONNECTION_UNLOCK (connection);
05676 
05677   dbus_free_string_array (decomposed_path);
05678 
05679   return retval;
05680 }
05681 
05699 dbus_bool_t
05700 dbus_connection_register_fallback (DBusConnection              *connection,
05701                                    const char                  *path,
05702                                    const DBusObjectPathVTable  *vtable,
05703                                    void                        *user_data)
05704 {
05705   char **decomposed_path;
05706   dbus_bool_t retval;
05707   DBusError error = DBUS_ERROR_INIT;
05708 
05709   _dbus_return_val_if_fail (connection != NULL, FALSE);
05710   _dbus_return_val_if_fail (path != NULL, FALSE);
05711   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05712   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05713 
05714   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05715     return FALSE;
05716 
05717   CONNECTION_LOCK (connection);
05718 
05719   retval = _dbus_object_tree_register (connection->objects,
05720                                        TRUE,
05721                                        (const char **) decomposed_path, vtable,
05722                                        user_data, &error);
05723 
05724   CONNECTION_UNLOCK (connection);
05725 
05726   dbus_free_string_array (decomposed_path);
05727 
05728   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05729     {
05730       _dbus_warn ("%s\n", error.message);
05731       dbus_error_free (&error);
05732       return FALSE;
05733     }
05734 
05735   return retval;
05736 }
05737 
05747 dbus_bool_t
05748 dbus_connection_unregister_object_path (DBusConnection              *connection,
05749                                         const char                  *path)
05750 {
05751   char **decomposed_path;
05752 
05753   _dbus_return_val_if_fail (connection != NULL, FALSE);
05754   _dbus_return_val_if_fail (path != NULL, FALSE);
05755   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05756 
05757   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05758       return FALSE;
05759 
05760   CONNECTION_LOCK (connection);
05761 
05762   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05763 
05764   dbus_free_string_array (decomposed_path);
05765 
05766   return TRUE;
05767 }
05768 
05779 dbus_bool_t
05780 dbus_connection_get_object_path_data (DBusConnection *connection,
05781                                       const char     *path,
05782                                       void          **data_p)
05783 {
05784   char **decomposed_path;
05785 
05786   _dbus_return_val_if_fail (connection != NULL, FALSE);
05787   _dbus_return_val_if_fail (path != NULL, FALSE);
05788   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05789 
05790   *data_p = NULL;
05791   
05792   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05793     return FALSE;
05794   
05795   CONNECTION_LOCK (connection);
05796 
05797   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05798 
05799   CONNECTION_UNLOCK (connection);
05800 
05801   dbus_free_string_array (decomposed_path);
05802 
05803   return TRUE;
05804 }
05805 
05816 dbus_bool_t
05817 dbus_connection_list_registered (DBusConnection              *connection,
05818                                  const char                  *parent_path,
05819                                  char                      ***child_entries)
05820 {
05821   char **decomposed_path;
05822   dbus_bool_t retval;
05823   _dbus_return_val_if_fail (connection != NULL, FALSE);
05824   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05825   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05826   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05827 
05828   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05829     return FALSE;
05830 
05831   CONNECTION_LOCK (connection);
05832 
05833   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05834                                                          (const char **) decomposed_path,
05835                                                          child_entries);
05836   dbus_free_string_array (decomposed_path);
05837 
05838   return retval;
05839 }
05840 
05841 static DBusDataSlotAllocator slot_allocator;
05842 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05843 
05858 dbus_bool_t
05859 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05860 {
05861   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05862                                           &_DBUS_LOCK_NAME (connection_slots),
05863                                           slot_p);
05864 }
05865 
05877 void
05878 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05879 {
05880   _dbus_return_if_fail (*slot_p >= 0);
05881   
05882   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05883 }
05884 
05907 dbus_bool_t
05908 dbus_connection_set_data (DBusConnection   *connection,
05909                           dbus_int32_t      slot,
05910                           void             *data,
05911                           DBusFreeFunction  free_data_func)
05912 {
05913   DBusFreeFunction old_free_func;
05914   void *old_data;
05915   dbus_bool_t retval;
05916 
05917   _dbus_return_val_if_fail (connection != NULL, FALSE);
05918   _dbus_return_val_if_fail (slot >= 0, FALSE);
05919   
05920   SLOTS_LOCK (connection);
05921 
05922   retval = _dbus_data_slot_list_set (&slot_allocator,
05923                                      &connection->slot_list,
05924                                      slot, data, free_data_func,
05925                                      &old_free_func, &old_data);
05926   
05927   SLOTS_UNLOCK (connection);
05928 
05929   if (retval)
05930     {
05931       /* Do the actual free outside the connection lock */
05932       if (old_free_func)
05933         (* old_free_func) (old_data);
05934     }
05935 
05936   return retval;
05937 }
05938 
05956 void*
05957 dbus_connection_get_data (DBusConnection   *connection,
05958                           dbus_int32_t      slot)
05959 {
05960   void *res;
05961 
05962   _dbus_return_val_if_fail (connection != NULL, NULL);
05963   
05964   SLOTS_LOCK (connection);
05965 
05966   res = _dbus_data_slot_list_get (&slot_allocator,
05967                                   &connection->slot_list,
05968                                   slot);
05969   
05970   SLOTS_UNLOCK (connection);
05971 
05972   return res;
05973 }
05974 
05981 void
05982 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05983 {  
05984   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05985 }
05986 
05995 void
05996 dbus_connection_set_max_message_size (DBusConnection *connection,
05997                                       long            size)
05998 {
05999   _dbus_return_if_fail (connection != NULL);
06000   
06001   CONNECTION_LOCK (connection);
06002   _dbus_transport_set_max_message_size (connection->transport,
06003                                         size);
06004   CONNECTION_UNLOCK (connection);
06005 }
06006 
06013 long
06014 dbus_connection_get_max_message_size (DBusConnection *connection)
06015 {
06016   long res;
06017 
06018   _dbus_return_val_if_fail (connection != NULL, 0);
06019   
06020   CONNECTION_LOCK (connection);
06021   res = _dbus_transport_get_max_message_size (connection->transport);
06022   CONNECTION_UNLOCK (connection);
06023   return res;
06024 }
06025 
06034 void
06035 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06036                                           long            n)
06037 {
06038   _dbus_return_if_fail (connection != NULL);
06039 
06040   CONNECTION_LOCK (connection);
06041   _dbus_transport_set_max_message_unix_fds (connection->transport,
06042                                             n);
06043   CONNECTION_UNLOCK (connection);
06044 }
06045 
06052 long
06053 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06054 {
06055   long res;
06056 
06057   _dbus_return_val_if_fail (connection != NULL, 0);
06058 
06059   CONNECTION_LOCK (connection);
06060   res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06061   CONNECTION_UNLOCK (connection);
06062   return res;
06063 }
06064 
06090 void
06091 dbus_connection_set_max_received_size (DBusConnection *connection,
06092                                        long            size)
06093 {
06094   _dbus_return_if_fail (connection != NULL);
06095   
06096   CONNECTION_LOCK (connection);
06097   _dbus_transport_set_max_received_size (connection->transport,
06098                                          size);
06099   CONNECTION_UNLOCK (connection);
06100 }
06101 
06108 long
06109 dbus_connection_get_max_received_size (DBusConnection *connection)
06110 {
06111   long res;
06112 
06113   _dbus_return_val_if_fail (connection != NULL, 0);
06114   
06115   CONNECTION_LOCK (connection);
06116   res = _dbus_transport_get_max_received_size (connection->transport);
06117   CONNECTION_UNLOCK (connection);
06118   return res;
06119 }
06120 
06132 void
06133 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06134                                            long            n)
06135 {
06136   _dbus_return_if_fail (connection != NULL);
06137 
06138   CONNECTION_LOCK (connection);
06139   _dbus_transport_set_max_received_unix_fds (connection->transport,
06140                                              n);
06141   CONNECTION_UNLOCK (connection);
06142 }
06143 
06150 long
06151 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06152 {
06153   long res;
06154 
06155   _dbus_return_val_if_fail (connection != NULL, 0);
06156 
06157   CONNECTION_LOCK (connection);
06158   res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06159   CONNECTION_UNLOCK (connection);
06160   return res;
06161 }
06162 
06173 long
06174 dbus_connection_get_outgoing_size (DBusConnection *connection)
06175 {
06176   long res;
06177 
06178   _dbus_return_val_if_fail (connection != NULL, 0);
06179 
06180   CONNECTION_LOCK (connection);
06181   res = _dbus_counter_get_size_value (connection->outgoing_counter);
06182   CONNECTION_UNLOCK (connection);
06183   return res;
06184 }
06185 
06193 long
06194 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06195 {
06196   long res;
06197 
06198   _dbus_return_val_if_fail (connection != NULL, 0);
06199 
06200   CONNECTION_LOCK (connection);
06201   res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06202   CONNECTION_UNLOCK (connection);
06203   return res;
06204 }
06205