D-Bus 1.4.14
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 
02560 DBusConnection*
02561 dbus_connection_open (const char     *address,
02562                       DBusError      *error)
02563 {
02564   DBusConnection *connection;
02565 
02566   _dbus_return_val_if_fail (address != NULL, NULL);
02567   _dbus_return_val_if_error_is_set (error, NULL);
02568 
02569   connection = _dbus_connection_open_internal (address,
02570                                                TRUE,
02571                                                error);
02572 
02573   return connection;
02574 }
02575 
02603 DBusConnection*
02604 dbus_connection_open_private (const char     *address,
02605                               DBusError      *error)
02606 {
02607   DBusConnection *connection;
02608 
02609   _dbus_return_val_if_fail (address != NULL, NULL);
02610   _dbus_return_val_if_error_is_set (error, NULL);
02611 
02612   connection = _dbus_connection_open_internal (address,
02613                                                FALSE,
02614                                                error);
02615 
02616   return connection;
02617 }
02618 
02625 DBusConnection *
02626 dbus_connection_ref (DBusConnection *connection)
02627 {
02628   _dbus_return_val_if_fail (connection != NULL, NULL);
02629   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02630 
02631   _dbus_atomic_inc (&connection->refcount);
02632 
02633   return connection;
02634 }
02635 
02636 static void
02637 free_outgoing_message (void *element,
02638                        void *data)
02639 {
02640   DBusMessage *message = element;
02641   DBusConnection *connection = data;
02642 
02643   _dbus_message_remove_counter (message,
02644                                 connection->outgoing_counter,
02645                                 NULL);
02646   dbus_message_unref (message);
02647 }
02648 
02649 /* This is run without the mutex held, but after the last reference
02650  * to the connection has been dropped we should have no thread-related
02651  * problems
02652  */
02653 static void
02654 _dbus_connection_last_unref (DBusConnection *connection)
02655 {
02656   DBusList *link;
02657 
02658   _dbus_verbose ("Finalizing connection %p\n", connection);
02659 
02660   _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02661 
02662   /* You have to disconnect the connection before unref:ing it. Otherwise
02663    * you won't get the disconnected message.
02664    */
02665   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02666   _dbus_assert (connection->server_guid == NULL);
02667   
02668   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02669   _dbus_object_tree_free_all_unlocked (connection->objects);
02670   
02671   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02672   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02673   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02674   
02675   _dbus_watch_list_free (connection->watches);
02676   connection->watches = NULL;
02677   
02678   _dbus_timeout_list_free (connection->timeouts);
02679   connection->timeouts = NULL;
02680 
02681   _dbus_data_slot_list_free (&connection->slot_list);
02682   
02683   link = _dbus_list_get_first_link (&connection->filter_list);
02684   while (link != NULL)
02685     {
02686       DBusMessageFilter *filter = link->data;
02687       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02688 
02689       filter->function = NULL;
02690       _dbus_message_filter_unref (filter); /* calls app callback */
02691       link->data = NULL;
02692       
02693       link = next;
02694     }
02695   _dbus_list_clear (&connection->filter_list);
02696   
02697   /* ---- Done with stuff that invokes application callbacks */
02698 
02699   _dbus_object_tree_unref (connection->objects);  
02700 
02701   _dbus_hash_table_unref (connection->pending_replies);
02702   connection->pending_replies = NULL;
02703   
02704   _dbus_list_clear (&connection->filter_list);
02705   
02706   _dbus_list_foreach (&connection->outgoing_messages,
02707                       free_outgoing_message,
02708                       connection);
02709   _dbus_list_clear (&connection->outgoing_messages);
02710   
02711   _dbus_list_foreach (&connection->incoming_messages,
02712                       (DBusForeachFunction) dbus_message_unref,
02713                       NULL);
02714   _dbus_list_clear (&connection->incoming_messages);
02715 
02716   _dbus_counter_unref (connection->outgoing_counter);
02717 
02718   _dbus_transport_unref (connection->transport);
02719 
02720   if (connection->disconnect_message_link)
02721     {
02722       DBusMessage *message = connection->disconnect_message_link->data;
02723       dbus_message_unref (message);
02724       _dbus_list_free_link (connection->disconnect_message_link);
02725     }
02726 
02727   _dbus_list_clear (&connection->link_cache);
02728   
02729   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02730   _dbus_condvar_free_at_location (&connection->io_path_cond);
02731 
02732   _dbus_mutex_free_at_location (&connection->io_path_mutex);
02733   _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02734 
02735   _dbus_mutex_free_at_location (&connection->slot_mutex);
02736 
02737   _dbus_mutex_free_at_location (&connection->mutex);
02738   
02739   dbus_free (connection);
02740 }
02741 
02761 void
02762 dbus_connection_unref (DBusConnection *connection)
02763 {
02764   dbus_bool_t last_unref;
02765 
02766   _dbus_return_if_fail (connection != NULL);
02767   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02768 
02769   last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02770 
02771   if (last_unref)
02772     {
02773 #ifndef DBUS_DISABLE_CHECKS
02774       if (_dbus_transport_get_is_connected (connection->transport))
02775         {
02776           _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",
02777                                    connection->shareable ?
02778                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02779                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02780           return;
02781         }
02782 #endif
02783       _dbus_connection_last_unref (connection);
02784     }
02785 }
02786 
02787 /*
02788  * Note that the transport can disconnect itself (other end drops us)
02789  * and in that case this function never runs. So this function must
02790  * not do anything more than disconnect the transport and update the
02791  * dispatch status.
02792  * 
02793  * If the transport self-disconnects, then we assume someone will
02794  * dispatch the connection to cause the dispatch status update.
02795  */
02796 static void
02797 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02798 {
02799   DBusDispatchStatus status;
02800 
02801   HAVE_LOCK_CHECK (connection);
02802   
02803   _dbus_verbose ("Disconnecting %p\n", connection);
02804 
02805   /* We need to ref because update_dispatch_status_and_unlock will unref
02806    * the connection if it was shared and libdbus was the only remaining
02807    * refcount holder.
02808    */
02809   _dbus_connection_ref_unlocked (connection);
02810   
02811   _dbus_transport_disconnect (connection->transport);
02812 
02813   /* This has the side effect of queuing the disconnect message link
02814    * (unless we don't have enough memory, possibly, so don't assert it).
02815    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02816    * should never again return the newly-disconnected connection.
02817    *
02818    * However, we only unref the shared connection and exit_on_disconnect when
02819    * the disconnect message reaches the head of the message queue,
02820    * NOT when it's first queued.
02821    */
02822   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02823 
02824   /* This calls out to user code */
02825   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02826 
02827   /* Could also call out to user code */
02828   dbus_connection_unref (connection);
02829 }
02830 
02873 void
02874 dbus_connection_close (DBusConnection *connection)
02875 {
02876   _dbus_return_if_fail (connection != NULL);
02877   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02878 
02879   CONNECTION_LOCK (connection);
02880 
02881 #ifndef DBUS_DISABLE_CHECKS
02882   if (connection->shareable)
02883     {
02884       CONNECTION_UNLOCK (connection);
02885 
02886       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02887       return;
02888     }
02889 #endif
02890   
02891   _dbus_connection_close_possibly_shared_and_unlock (connection);
02892 }
02893 
02894 static dbus_bool_t
02895 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02896 {
02897   HAVE_LOCK_CHECK (connection);
02898   return _dbus_transport_get_is_connected (connection->transport);
02899 }
02900 
02914 dbus_bool_t
02915 dbus_connection_get_is_connected (DBusConnection *connection)
02916 {
02917   dbus_bool_t res;
02918 
02919   _dbus_return_val_if_fail (connection != NULL, FALSE);
02920   
02921   CONNECTION_LOCK (connection);
02922   res = _dbus_connection_get_is_connected_unlocked (connection);
02923   CONNECTION_UNLOCK (connection);
02924   
02925   return res;
02926 }
02927 
02936 dbus_bool_t
02937 dbus_connection_get_is_authenticated (DBusConnection *connection)
02938 {
02939   dbus_bool_t res;
02940 
02941   _dbus_return_val_if_fail (connection != NULL, FALSE);
02942   
02943   CONNECTION_LOCK (connection);
02944   res = _dbus_transport_get_is_authenticated (connection->transport);
02945   CONNECTION_UNLOCK (connection);
02946   
02947   return res;
02948 }
02949 
02970 dbus_bool_t
02971 dbus_connection_get_is_anonymous (DBusConnection *connection)
02972 {
02973   dbus_bool_t res;
02974 
02975   _dbus_return_val_if_fail (connection != NULL, FALSE);
02976   
02977   CONNECTION_LOCK (connection);
02978   res = _dbus_transport_get_is_anonymous (connection->transport);
02979   CONNECTION_UNLOCK (connection);
02980   
02981   return res;
02982 }
02983 
03015 char*
03016 dbus_connection_get_server_id (DBusConnection *connection)
03017 {
03018   char *id;
03019 
03020   _dbus_return_val_if_fail (connection != NULL, NULL);
03021 
03022   CONNECTION_LOCK (connection);
03023   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03024   CONNECTION_UNLOCK (connection);
03025 
03026   return id;
03027 }
03028 
03046 dbus_bool_t
03047 dbus_connection_can_send_type(DBusConnection *connection,
03048                                   int type)
03049 {
03050   _dbus_return_val_if_fail (connection != NULL, FALSE);
03051 
03052   if (!_dbus_type_is_valid(type))
03053     return FALSE;
03054 
03055   if (type != DBUS_TYPE_UNIX_FD)
03056     return TRUE;
03057 
03058 #ifdef HAVE_UNIX_FD_PASSING
03059   {
03060     dbus_bool_t b;
03061 
03062     CONNECTION_LOCK(connection);
03063     b = _dbus_transport_can_pass_unix_fd(connection->transport);
03064     CONNECTION_UNLOCK(connection);
03065 
03066     return b;
03067   }
03068 #endif
03069 
03070   return FALSE;
03071 }
03072 
03086 void
03087 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03088                                         dbus_bool_t     exit_on_disconnect)
03089 {
03090   _dbus_return_if_fail (connection != NULL);
03091 
03092   CONNECTION_LOCK (connection);
03093   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03094   CONNECTION_UNLOCK (connection);
03095 }
03096 
03106 DBusPreallocatedSend*
03107 dbus_connection_preallocate_send (DBusConnection *connection)
03108 {
03109   DBusPreallocatedSend *preallocated;
03110 
03111   _dbus_return_val_if_fail (connection != NULL, NULL);
03112 
03113   CONNECTION_LOCK (connection);
03114   
03115   preallocated =
03116     _dbus_connection_preallocate_send_unlocked (connection);
03117 
03118   CONNECTION_UNLOCK (connection);
03119 
03120   return preallocated;
03121 }
03122 
03132 void
03133 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03134                                         DBusPreallocatedSend *preallocated)
03135 {
03136   _dbus_return_if_fail (connection != NULL);
03137   _dbus_return_if_fail (preallocated != NULL);  
03138   _dbus_return_if_fail (connection == preallocated->connection);
03139 
03140   _dbus_list_free_link (preallocated->queue_link);
03141   _dbus_counter_unref (preallocated->counter_link->data);
03142   _dbus_list_free_link (preallocated->counter_link);
03143   dbus_free (preallocated);
03144 }
03145 
03158 void
03159 dbus_connection_send_preallocated (DBusConnection       *connection,
03160                                    DBusPreallocatedSend *preallocated,
03161                                    DBusMessage          *message,
03162                                    dbus_uint32_t        *client_serial)
03163 {
03164   _dbus_return_if_fail (connection != NULL);
03165   _dbus_return_if_fail (preallocated != NULL);
03166   _dbus_return_if_fail (message != NULL);
03167   _dbus_return_if_fail (preallocated->connection == connection);
03168   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03169                         dbus_message_get_member (message) != NULL);
03170   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03171                         (dbus_message_get_interface (message) != NULL &&
03172                          dbus_message_get_member (message) != NULL));
03173 
03174   CONNECTION_LOCK (connection);
03175 
03176 #ifdef HAVE_UNIX_FD_PASSING
03177 
03178   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03179       message->n_unix_fds > 0)
03180     {
03181       /* Refuse to send fds on a connection that cannot handle
03182          them. Unfortunately we cannot return a proper error here, so
03183          the best we can is just return. */
03184       CONNECTION_UNLOCK (connection);
03185       return;
03186     }
03187 
03188 #endif
03189 
03190   _dbus_connection_send_preallocated_and_unlock (connection,
03191                                                  preallocated,
03192                                                  message, client_serial);
03193 }
03194 
03195 static dbus_bool_t
03196 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03197                                           DBusMessage    *message,
03198                                           dbus_uint32_t  *client_serial)
03199 {
03200   DBusPreallocatedSend *preallocated;
03201 
03202   _dbus_assert (connection != NULL);
03203   _dbus_assert (message != NULL);
03204   
03205   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03206   if (preallocated == NULL)
03207     return FALSE;
03208 
03209   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03210                                                          preallocated,
03211                                                          message,
03212                                                          client_serial);
03213   return TRUE;
03214 }
03215 
03243 dbus_bool_t
03244 dbus_connection_send (DBusConnection *connection,
03245                       DBusMessage    *message,
03246                       dbus_uint32_t  *serial)
03247 {
03248   _dbus_return_val_if_fail (connection != NULL, FALSE);
03249   _dbus_return_val_if_fail (message != NULL, FALSE);
03250 
03251   CONNECTION_LOCK (connection);
03252 
03253 #ifdef HAVE_UNIX_FD_PASSING
03254 
03255   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03256       message->n_unix_fds > 0)
03257     {
03258       /* Refuse to send fds on a connection that cannot handle
03259          them. Unfortunately we cannot return a proper error here, so
03260          the best we can is just return. */
03261       CONNECTION_UNLOCK (connection);
03262       return FALSE;
03263     }
03264 
03265 #endif
03266 
03267   return _dbus_connection_send_and_unlock (connection,
03268                                            message,
03269                                            serial);
03270 }
03271 
03272 static dbus_bool_t
03273 reply_handler_timeout (void *data)
03274 {
03275   DBusConnection *connection;
03276   DBusDispatchStatus status;
03277   DBusPendingCall *pending = data;
03278 
03279   connection = _dbus_pending_call_get_connection_and_lock (pending);
03280 
03281   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03282                                                    connection);
03283   _dbus_connection_remove_timeout_unlocked (connection,
03284                                             _dbus_pending_call_get_timeout_unlocked (pending));
03285   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03286 
03287   _dbus_verbose ("middle\n");
03288   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03289 
03290   /* Unlocks, and calls out to user code */
03291   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03292   
03293   return TRUE;
03294 }
03295 
03338 dbus_bool_t
03339 dbus_connection_send_with_reply (DBusConnection     *connection,
03340                                  DBusMessage        *message,
03341                                  DBusPendingCall   **pending_return,
03342                                  int                 timeout_milliseconds)
03343 {
03344   DBusPendingCall *pending;
03345   dbus_int32_t serial = -1;
03346   DBusDispatchStatus status;
03347 
03348   _dbus_return_val_if_fail (connection != NULL, FALSE);
03349   _dbus_return_val_if_fail (message != NULL, FALSE);
03350   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03351 
03352   if (pending_return)
03353     *pending_return = NULL;
03354 
03355   CONNECTION_LOCK (connection);
03356 
03357 #ifdef HAVE_UNIX_FD_PASSING
03358 
03359   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03360       message->n_unix_fds > 0)
03361     {
03362       /* Refuse to send fds on a connection that cannot handle
03363          them. Unfortunately we cannot return a proper error here, so
03364          the best we can do is return TRUE but leave *pending_return
03365          as NULL. */
03366       CONNECTION_UNLOCK (connection);
03367       return TRUE;
03368     }
03369 
03370 #endif
03371 
03372    if (!_dbus_connection_get_is_connected_unlocked (connection))
03373     {
03374       CONNECTION_UNLOCK (connection);
03375 
03376       return TRUE;
03377     }
03378 
03379   pending = _dbus_pending_call_new_unlocked (connection,
03380                                              timeout_milliseconds,
03381                                              reply_handler_timeout);
03382 
03383   if (pending == NULL)
03384     {
03385       CONNECTION_UNLOCK (connection);
03386       return FALSE;
03387     }
03388 
03389   /* Assign a serial to the message */
03390   serial = dbus_message_get_serial (message);
03391   if (serial == 0)
03392     {
03393       serial = _dbus_connection_get_next_client_serial (connection);
03394       dbus_message_set_serial (message, serial);
03395     }
03396 
03397   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03398     goto error;
03399     
03400   /* Insert the serial in the pending replies hash;
03401    * hash takes a refcount on DBusPendingCall.
03402    * Also, add the timeout.
03403    */
03404   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03405                                                       pending))
03406     goto error;
03407  
03408   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03409     {
03410       _dbus_connection_detach_pending_call_and_unlock (connection,
03411                                                        pending);
03412       goto error_unlocked;
03413     }
03414 
03415   if (pending_return)
03416     *pending_return = pending; /* hand off refcount */
03417   else
03418     {
03419       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03420       /* we still have a ref to the pending call in this case, we unref
03421        * after unlocking, below
03422        */
03423     }
03424 
03425   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03426 
03427   /* this calls out to user code */
03428   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03429 
03430   if (pending_return == NULL)
03431     dbus_pending_call_unref (pending);
03432   
03433   return TRUE;
03434 
03435  error:
03436   CONNECTION_UNLOCK (connection);
03437  error_unlocked:
03438   dbus_pending_call_unref (pending);
03439   return FALSE;
03440 }
03441 
03474 DBusMessage*
03475 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03476                                            DBusMessage        *message,
03477                                            int                 timeout_milliseconds,
03478                                            DBusError          *error)
03479 {
03480   DBusMessage *reply;
03481   DBusPendingCall *pending;
03482 
03483   _dbus_return_val_if_fail (connection != NULL, NULL);
03484   _dbus_return_val_if_fail (message != NULL, NULL);
03485   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03486   _dbus_return_val_if_error_is_set (error, NULL);
03487 
03488 #ifdef HAVE_UNIX_FD_PASSING
03489 
03490   CONNECTION_LOCK (connection);
03491   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03492       message->n_unix_fds > 0)
03493     {
03494       CONNECTION_UNLOCK (connection);
03495       dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03496       return NULL;
03497     }
03498   CONNECTION_UNLOCK (connection);
03499 
03500 #endif
03501 
03502   if (!dbus_connection_send_with_reply (connection, message,
03503                                         &pending, timeout_milliseconds))
03504     {
03505       _DBUS_SET_OOM (error);
03506       return NULL;
03507     }
03508 
03509   if (pending == NULL)
03510     {
03511       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03512       return NULL;
03513     }
03514   
03515   dbus_pending_call_block (pending);
03516 
03517   reply = dbus_pending_call_steal_reply (pending);
03518   dbus_pending_call_unref (pending);
03519 
03520   /* call_complete_and_unlock() called from pending_call_block() should
03521    * always fill this in.
03522    */
03523   _dbus_assert (reply != NULL);
03524   
03525    if (dbus_set_error_from_message (error, reply))
03526     {
03527       dbus_message_unref (reply);
03528       return NULL;
03529     }
03530   else
03531     return reply;
03532 }
03533 
03542 static DBusDispatchStatus
03543 _dbus_connection_flush_unlocked (DBusConnection *connection)
03544 {
03545   /* We have to specify DBUS_ITERATION_DO_READING here because
03546    * otherwise we could have two apps deadlock if they are both doing
03547    * a flush(), and the kernel buffers fill up. This could change the
03548    * dispatch status.
03549    */
03550   DBusDispatchStatus status;
03551 
03552   HAVE_LOCK_CHECK (connection);
03553   
03554   while (connection->n_outgoing > 0 &&
03555          _dbus_connection_get_is_connected_unlocked (connection))
03556     {
03557       _dbus_verbose ("doing iteration in\n");
03558       HAVE_LOCK_CHECK (connection);
03559       _dbus_connection_do_iteration_unlocked (connection,
03560                                               NULL,
03561                                               DBUS_ITERATION_DO_READING |
03562                                               DBUS_ITERATION_DO_WRITING |
03563                                               DBUS_ITERATION_BLOCK,
03564                                               -1);
03565     }
03566 
03567   HAVE_LOCK_CHECK (connection);
03568   _dbus_verbose ("middle\n");
03569   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03570 
03571   HAVE_LOCK_CHECK (connection);
03572   return status;
03573 }
03574 
03580 void
03581 dbus_connection_flush (DBusConnection *connection)
03582 {
03583   /* We have to specify DBUS_ITERATION_DO_READING here because
03584    * otherwise we could have two apps deadlock if they are both doing
03585    * a flush(), and the kernel buffers fill up. This could change the
03586    * dispatch status.
03587    */
03588   DBusDispatchStatus status;
03589 
03590   _dbus_return_if_fail (connection != NULL);
03591   
03592   CONNECTION_LOCK (connection);
03593 
03594   status = _dbus_connection_flush_unlocked (connection);
03595   
03596   HAVE_LOCK_CHECK (connection);
03597   /* Unlocks and calls out to user code */
03598   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03599 
03600   _dbus_verbose ("end\n");
03601 }
03602 
03613 static dbus_bool_t
03614 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03615                                      int             timeout_milliseconds, 
03616                                      dbus_bool_t     dispatch)
03617 {
03618   DBusDispatchStatus dstatus;
03619   dbus_bool_t progress_possible;
03620 
03621   /* Need to grab a ref here in case we're a private connection and
03622    * the user drops the last ref in a handler we call; see bug 
03623    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03624    */
03625   dbus_connection_ref (connection);
03626   dstatus = dbus_connection_get_dispatch_status (connection);
03627 
03628   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03629     {
03630       _dbus_verbose ("doing dispatch\n");
03631       dbus_connection_dispatch (connection);
03632       CONNECTION_LOCK (connection);
03633     }
03634   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03635     {
03636       _dbus_verbose ("pausing for memory\n");
03637       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03638       CONNECTION_LOCK (connection);
03639     }
03640   else
03641     {
03642       CONNECTION_LOCK (connection);
03643       if (_dbus_connection_get_is_connected_unlocked (connection))
03644         {
03645           _dbus_verbose ("doing iteration\n");
03646           _dbus_connection_do_iteration_unlocked (connection,
03647                                                   NULL,
03648                                                   DBUS_ITERATION_DO_READING |
03649                                                   DBUS_ITERATION_DO_WRITING |
03650                                                   DBUS_ITERATION_BLOCK,
03651                                                   timeout_milliseconds);
03652         }
03653     }
03654   
03655   HAVE_LOCK_CHECK (connection);
03656   /* If we can dispatch, we can make progress until the Disconnected message
03657    * has been processed; if we can only read/write, we can make progress
03658    * as long as the transport is open.
03659    */
03660   if (dispatch)
03661     progress_possible = connection->n_incoming != 0 ||
03662       connection->disconnect_message_link != NULL;
03663   else
03664     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03665 
03666   CONNECTION_UNLOCK (connection);
03667 
03668   dbus_connection_unref (connection);
03669 
03670   return progress_possible; /* TRUE if we can make more progress */
03671 }
03672 
03673 
03708 dbus_bool_t
03709 dbus_connection_read_write_dispatch (DBusConnection *connection,
03710                                      int             timeout_milliseconds)
03711 {
03712   _dbus_return_val_if_fail (connection != NULL, FALSE);
03713   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03714    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03715 }
03716 
03740 dbus_bool_t 
03741 dbus_connection_read_write (DBusConnection *connection, 
03742                             int             timeout_milliseconds) 
03743 { 
03744   _dbus_return_val_if_fail (connection != NULL, FALSE);
03745   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03746    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03747 }
03748 
03749 /* We need to call this anytime we pop the head of the queue, and then
03750  * update_dispatch_status_and_unlock needs to be called afterward
03751  * which will "process" the disconnected message and set
03752  * disconnected_message_processed.
03753  */
03754 static void
03755 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03756                                              DBusMessage    *head_of_queue)
03757 {
03758   HAVE_LOCK_CHECK (connection);
03759 
03760   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03761   if (connection->disconnect_message_link == NULL &&
03762       dbus_message_is_signal (head_of_queue,
03763                               DBUS_INTERFACE_LOCAL,
03764                               "Disconnected"))
03765     {
03766       connection->disconnected_message_arrived = TRUE;
03767     }
03768 }
03769 
03789 DBusMessage*
03790 dbus_connection_borrow_message (DBusConnection *connection)
03791 {
03792   DBusDispatchStatus status;
03793   DBusMessage *message;
03794 
03795   _dbus_return_val_if_fail (connection != NULL, NULL);
03796 
03797   _dbus_verbose ("start\n");
03798   
03799   /* this is called for the side effect that it queues
03800    * up any messages from the transport
03801    */
03802   status = dbus_connection_get_dispatch_status (connection);
03803   if (status != DBUS_DISPATCH_DATA_REMAINS)
03804     return NULL;
03805   
03806   CONNECTION_LOCK (connection);
03807 
03808   _dbus_connection_acquire_dispatch (connection);
03809 
03810   /* While a message is outstanding, the dispatch lock is held */
03811   _dbus_assert (connection->message_borrowed == NULL);
03812 
03813   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03814   
03815   message = connection->message_borrowed;
03816 
03817   check_disconnected_message_arrived_unlocked (connection, message);
03818   
03819   /* Note that we KEEP the dispatch lock until the message is returned */
03820   if (message == NULL)
03821     _dbus_connection_release_dispatch (connection);
03822 
03823   CONNECTION_UNLOCK (connection);
03824 
03825   /* We don't update dispatch status until it's returned or stolen */
03826   
03827   return message;
03828 }
03829 
03838 void
03839 dbus_connection_return_message (DBusConnection *connection,
03840                                 DBusMessage    *message)
03841 {
03842   DBusDispatchStatus status;
03843   
03844   _dbus_return_if_fail (connection != NULL);
03845   _dbus_return_if_fail (message != NULL);
03846   _dbus_return_if_fail (message == connection->message_borrowed);
03847   _dbus_return_if_fail (connection->dispatch_acquired);
03848   
03849   CONNECTION_LOCK (connection);
03850   
03851   _dbus_assert (message == connection->message_borrowed);
03852   
03853   connection->message_borrowed = NULL;
03854 
03855   _dbus_connection_release_dispatch (connection); 
03856 
03857   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03858   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03859 }
03860 
03870 void
03871 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03872                                         DBusMessage    *message)
03873 {
03874   DBusMessage *pop_message;
03875   DBusDispatchStatus status;
03876 
03877   _dbus_return_if_fail (connection != NULL);
03878   _dbus_return_if_fail (message != NULL);
03879   _dbus_return_if_fail (message == connection->message_borrowed);
03880   _dbus_return_if_fail (connection->dispatch_acquired);
03881   
03882   CONNECTION_LOCK (connection);
03883  
03884   _dbus_assert (message == connection->message_borrowed);
03885 
03886   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03887   _dbus_assert (message == pop_message);
03888   
03889   connection->n_incoming -= 1;
03890  
03891   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03892                  message, connection->n_incoming);
03893  
03894   connection->message_borrowed = NULL;
03895 
03896   _dbus_connection_release_dispatch (connection);
03897 
03898   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03899   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03900 }
03901 
03902 /* See dbus_connection_pop_message, but requires the caller to own
03903  * the lock before calling. May drop the lock while running.
03904  */
03905 static DBusList*
03906 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03907 {
03908   HAVE_LOCK_CHECK (connection);
03909   
03910   _dbus_assert (connection->message_borrowed == NULL);
03911   
03912   if (connection->n_incoming > 0)
03913     {
03914       DBusList *link;
03915 
03916       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03917       connection->n_incoming -= 1;
03918 
03919       _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03920                      link->data,
03921                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
03922                      dbus_message_get_path (link->data) ?
03923                      dbus_message_get_path (link->data) :
03924                      "no path",
03925                      dbus_message_get_interface (link->data) ?
03926                      dbus_message_get_interface (link->data) :
03927                      "no interface",
03928                      dbus_message_get_member (link->data) ?
03929                      dbus_message_get_member (link->data) :
03930                      "no member",
03931                      dbus_message_get_signature (link->data),
03932                      connection, connection->n_incoming);
03933 
03934       check_disconnected_message_arrived_unlocked (connection, link->data);
03935       
03936       return link;
03937     }
03938   else
03939     return NULL;
03940 }
03941 
03942 /* See dbus_connection_pop_message, but requires the caller to own
03943  * the lock before calling. May drop the lock while running.
03944  */
03945 static DBusMessage*
03946 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03947 {
03948   DBusList *link;
03949 
03950   HAVE_LOCK_CHECK (connection);
03951   
03952   link = _dbus_connection_pop_message_link_unlocked (connection);
03953 
03954   if (link != NULL)
03955     {
03956       DBusMessage *message;
03957       
03958       message = link->data;
03959       
03960       _dbus_list_free_link (link);
03961       
03962       return message;
03963     }
03964   else
03965     return NULL;
03966 }
03967 
03968 static void
03969 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03970                                                 DBusList       *message_link)
03971 {
03972   HAVE_LOCK_CHECK (connection);
03973   
03974   _dbus_assert (message_link != NULL);
03975   /* You can't borrow a message while a link is outstanding */
03976   _dbus_assert (connection->message_borrowed == NULL);
03977   /* We had to have the dispatch lock across the pop/putback */
03978   _dbus_assert (connection->dispatch_acquired);
03979 
03980   _dbus_list_prepend_link (&connection->incoming_messages,
03981                            message_link);
03982   connection->n_incoming += 1;
03983 
03984   _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
03985                  message_link->data,
03986                  dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
03987                  dbus_message_get_interface (message_link->data) ?
03988                  dbus_message_get_interface (message_link->data) :
03989                  "no interface",
03990                  dbus_message_get_member (message_link->data) ?
03991                  dbus_message_get_member (message_link->data) :
03992                  "no member",
03993                  dbus_message_get_signature (message_link->data),
03994                  connection, connection->n_incoming);
03995 }
03996 
04016 DBusMessage*
04017 dbus_connection_pop_message (DBusConnection *connection)
04018 {
04019   DBusMessage *message;
04020   DBusDispatchStatus status;
04021 
04022   _dbus_verbose ("start\n");
04023   
04024   /* this is called for the side effect that it queues
04025    * up any messages from the transport
04026    */
04027   status = dbus_connection_get_dispatch_status (connection);
04028   if (status != DBUS_DISPATCH_DATA_REMAINS)
04029     return NULL;
04030   
04031   CONNECTION_LOCK (connection);
04032   _dbus_connection_acquire_dispatch (connection);
04033   HAVE_LOCK_CHECK (connection);
04034   
04035   message = _dbus_connection_pop_message_unlocked (connection);
04036 
04037   _dbus_verbose ("Returning popped message %p\n", message);    
04038 
04039   _dbus_connection_release_dispatch (connection);
04040 
04041   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04042   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04043   
04044   return message;
04045 }
04046 
04054 static void
04055 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04056 {
04057   HAVE_LOCK_CHECK (connection);
04058 
04059   _dbus_connection_ref_unlocked (connection);
04060   CONNECTION_UNLOCK (connection);
04061   
04062   _dbus_verbose ("locking dispatch_mutex\n");
04063   _dbus_mutex_lock (connection->dispatch_mutex);
04064 
04065   while (connection->dispatch_acquired)
04066     {
04067       _dbus_verbose ("waiting for dispatch to be acquirable\n");
04068       _dbus_condvar_wait (connection->dispatch_cond, 
04069                           connection->dispatch_mutex);
04070     }
04071   
04072   _dbus_assert (!connection->dispatch_acquired);
04073 
04074   connection->dispatch_acquired = TRUE;
04075 
04076   _dbus_verbose ("unlocking dispatch_mutex\n");
04077   _dbus_mutex_unlock (connection->dispatch_mutex);
04078   
04079   CONNECTION_LOCK (connection);
04080   _dbus_connection_unref_unlocked (connection);
04081 }
04082 
04090 static void
04091 _dbus_connection_release_dispatch (DBusConnection *connection)
04092 {
04093   HAVE_LOCK_CHECK (connection);
04094   
04095   _dbus_verbose ("locking dispatch_mutex\n");
04096   _dbus_mutex_lock (connection->dispatch_mutex);
04097   
04098   _dbus_assert (connection->dispatch_acquired);
04099 
04100   connection->dispatch_acquired = FALSE;
04101   _dbus_condvar_wake_one (connection->dispatch_cond);
04102 
04103   _dbus_verbose ("unlocking dispatch_mutex\n");
04104   _dbus_mutex_unlock (connection->dispatch_mutex);
04105 }
04106 
04107 static void
04108 _dbus_connection_failed_pop (DBusConnection *connection,
04109                              DBusList       *message_link)
04110 {
04111   _dbus_list_prepend_link (&connection->incoming_messages,
04112                            message_link);
04113   connection->n_incoming += 1;
04114 }
04115 
04116 /* Note this may be called multiple times since we don't track whether we already did it */
04117 static void
04118 notify_disconnected_unlocked (DBusConnection *connection)
04119 {
04120   HAVE_LOCK_CHECK (connection);
04121 
04122   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04123    * connection from dbus_bus_get(). We make the same guarantee for
04124    * dbus_connection_open() but in a different way since we don't want to
04125    * unref right here; we instead check for connectedness before returning
04126    * the connection from the hash.
04127    */
04128   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04129 
04130   /* Dump the outgoing queue, we aren't going to be able to
04131    * send it now, and we'd like accessors like
04132    * dbus_connection_get_outgoing_size() to be accurate.
04133    */
04134   if (connection->n_outgoing > 0)
04135     {
04136       DBusList *link;
04137       
04138       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04139                      connection->n_outgoing);
04140       
04141       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04142         {
04143           _dbus_connection_message_sent (connection, link->data);
04144         }
04145     } 
04146 }
04147 
04148 /* Note this may be called multiple times since we don't track whether we already did it */
04149 static DBusDispatchStatus
04150 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04151 {
04152   HAVE_LOCK_CHECK (connection);
04153   
04154   if (connection->disconnect_message_link != NULL)
04155     {
04156       _dbus_verbose ("Sending disconnect message\n");
04157       
04158       /* If we have pending calls, queue their timeouts - we want the Disconnected
04159        * to be the last message, after these timeouts.
04160        */
04161       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04162       
04163       /* We haven't sent the disconnect message already,
04164        * and all real messages have been queued up.
04165        */
04166       _dbus_connection_queue_synthesized_message_link (connection,
04167                                                        connection->disconnect_message_link);
04168       connection->disconnect_message_link = NULL;
04169 
04170       return DBUS_DISPATCH_DATA_REMAINS;
04171     }
04172 
04173   return DBUS_DISPATCH_COMPLETE;
04174 }
04175 
04176 static DBusDispatchStatus
04177 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04178 {
04179   HAVE_LOCK_CHECK (connection);
04180   
04181   if (connection->n_incoming > 0)
04182     return DBUS_DISPATCH_DATA_REMAINS;
04183   else if (!_dbus_transport_queue_messages (connection->transport))
04184     return DBUS_DISPATCH_NEED_MEMORY;
04185   else
04186     {
04187       DBusDispatchStatus status;
04188       dbus_bool_t is_connected;
04189       
04190       status = _dbus_transport_get_dispatch_status (connection->transport);
04191       is_connected = _dbus_transport_get_is_connected (connection->transport);
04192 
04193       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04194                      DISPATCH_STATUS_NAME (status), is_connected);
04195       
04196       if (!is_connected)
04197         {
04198           /* It's possible this would be better done by having an explicit
04199            * notification from _dbus_transport_disconnect() that would
04200            * synchronously do this, instead of waiting for the next dispatch
04201            * status check. However, probably not good to change until it causes
04202            * a problem.
04203            */
04204           notify_disconnected_unlocked (connection);
04205 
04206           /* I'm not sure this is needed; the idea is that we want to
04207            * queue the Disconnected only after we've read all the
04208            * messages, but if we're disconnected maybe we are guaranteed
04209            * to have read them all ?
04210            */
04211           if (status == DBUS_DISPATCH_COMPLETE)
04212             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04213         }
04214       
04215       if (status != DBUS_DISPATCH_COMPLETE)
04216         return status;
04217       else if (connection->n_incoming > 0)
04218         return DBUS_DISPATCH_DATA_REMAINS;
04219       else
04220         return DBUS_DISPATCH_COMPLETE;
04221     }
04222 }
04223 
04224 static void
04225 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04226                                                     DBusDispatchStatus new_status)
04227 {
04228   dbus_bool_t changed;
04229   DBusDispatchStatusFunction function;
04230   void *data;
04231 
04232   HAVE_LOCK_CHECK (connection);
04233 
04234   _dbus_connection_ref_unlocked (connection);
04235 
04236   changed = new_status != connection->last_dispatch_status;
04237 
04238   connection->last_dispatch_status = new_status;
04239 
04240   function = connection->dispatch_status_function;
04241   data = connection->dispatch_status_data;
04242 
04243   if (connection->disconnected_message_arrived &&
04244       !connection->disconnected_message_processed)
04245     {
04246       connection->disconnected_message_processed = TRUE;
04247       
04248       /* this does an unref, but we have a ref
04249        * so we should not run the finalizer here
04250        * inside the lock.
04251        */
04252       connection_forget_shared_unlocked (connection);
04253 
04254       if (connection->exit_on_disconnect)
04255         {
04256           CONNECTION_UNLOCK (connection);            
04257           
04258           _dbus_verbose ("Exiting on Disconnected signal\n");
04259           _dbus_exit (1);
04260           _dbus_assert_not_reached ("Call to exit() returned");
04261         }
04262     }
04263   
04264   /* We drop the lock */
04265   CONNECTION_UNLOCK (connection);
04266   
04267   if (changed && function)
04268     {
04269       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04270                      connection, new_status,
04271                      DISPATCH_STATUS_NAME (new_status));
04272       (* function) (connection, new_status, data);      
04273     }
04274   
04275   dbus_connection_unref (connection);
04276 }
04277 
04303 DBusDispatchStatus
04304 dbus_connection_get_dispatch_status (DBusConnection *connection)
04305 {
04306   DBusDispatchStatus status;
04307 
04308   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04309 
04310   _dbus_verbose ("start\n");
04311   
04312   CONNECTION_LOCK (connection);
04313 
04314   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04315   
04316   CONNECTION_UNLOCK (connection);
04317 
04318   return status;
04319 }
04320 
04324 static DBusHandlerResult
04325 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04326                                                  DBusMessage    *message)
04327 {
04328   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04329     {
04330       /* This means we're letting the bus route this message */
04331       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04332     }
04333   else if (dbus_message_is_method_call (message,
04334                                         DBUS_INTERFACE_PEER,
04335                                         "Ping"))
04336     {
04337       DBusMessage *ret;
04338       dbus_bool_t sent;
04339       
04340       ret = dbus_message_new_method_return (message);
04341       if (ret == NULL)
04342         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04343      
04344       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04345 
04346       dbus_message_unref (ret);
04347 
04348       if (!sent)
04349         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04350       
04351       return DBUS_HANDLER_RESULT_HANDLED;
04352     }
04353   else if (dbus_message_is_method_call (message,
04354                                         DBUS_INTERFACE_PEER,
04355                                         "GetMachineId"))
04356     {
04357       DBusMessage *ret;
04358       dbus_bool_t sent;
04359       DBusString uuid;
04360       
04361       ret = dbus_message_new_method_return (message);
04362       if (ret == NULL)
04363         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04364 
04365       sent = FALSE;
04366       _dbus_string_init (&uuid);
04367       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04368         {
04369           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04370           if (dbus_message_append_args (ret,
04371                                         DBUS_TYPE_STRING, &v_STRING,
04372                                         DBUS_TYPE_INVALID))
04373             {
04374               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04375             }
04376         }
04377       _dbus_string_free (&uuid);
04378       
04379       dbus_message_unref (ret);
04380 
04381       if (!sent)
04382         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04383       
04384       return DBUS_HANDLER_RESULT_HANDLED;
04385     }
04386   else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04387     {
04388       /* We need to bounce anything else with this interface, otherwise apps
04389        * could start extending the interface and when we added extensions
04390        * here to DBusConnection we'd break those apps.
04391        */
04392       
04393       DBusMessage *ret;
04394       dbus_bool_t sent;
04395       
04396       ret = dbus_message_new_error (message,
04397                                     DBUS_ERROR_UNKNOWN_METHOD,
04398                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04399       if (ret == NULL)
04400         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04401       
04402       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04403       
04404       dbus_message_unref (ret);
04405       
04406       if (!sent)
04407         return DBUS_HANDLER_RESULT_NEED_MEMORY;
04408       
04409       return DBUS_HANDLER_RESULT_HANDLED;
04410     }
04411   else
04412     {
04413       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04414     }
04415 }
04416 
04423 static DBusHandlerResult
04424 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04425                                                            DBusMessage    *message)
04426 {
04427   /* We just run one filter for now but have the option to run more
04428      if the spec calls for it in the future */
04429 
04430   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04431 }
04432 
04475 DBusDispatchStatus
04476 dbus_connection_dispatch (DBusConnection *connection)
04477 {
04478   DBusMessage *message;
04479   DBusList *link, *filter_list_copy, *message_link;
04480   DBusHandlerResult result;
04481   DBusPendingCall *pending;
04482   dbus_int32_t reply_serial;
04483   DBusDispatchStatus status;
04484 
04485   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04486 
04487   _dbus_verbose ("\n");
04488   
04489   CONNECTION_LOCK (connection);
04490   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04491   if (status != DBUS_DISPATCH_DATA_REMAINS)
04492     {
04493       /* unlocks and calls out to user code */
04494       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04495       return status;
04496     }
04497   
04498   /* We need to ref the connection since the callback could potentially
04499    * drop the last ref to it
04500    */
04501   _dbus_connection_ref_unlocked (connection);
04502 
04503   _dbus_connection_acquire_dispatch (connection);
04504   HAVE_LOCK_CHECK (connection);
04505 
04506   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04507   if (message_link == NULL)
04508     {
04509       /* another thread dispatched our stuff */
04510 
04511       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04512       
04513       _dbus_connection_release_dispatch (connection);
04514 
04515       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04516 
04517       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04518       
04519       dbus_connection_unref (connection);
04520       
04521       return status;
04522     }
04523 
04524   message = message_link->data;
04525 
04526   _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04527                  message,
04528                  dbus_message_type_to_string (dbus_message_get_type (message)),
04529                  dbus_message_get_interface (message) ?
04530                  dbus_message_get_interface (message) :
04531                  "no interface",
04532                  dbus_message_get_member (message) ?
04533                  dbus_message_get_member (message) :
04534                  "no member",
04535                  dbus_message_get_signature (message));
04536 
04537   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04538   
04539   /* Pending call handling must be first, because if you do
04540    * dbus_connection_send_with_reply_and_block() or
04541    * dbus_pending_call_block() then no handlers/filters will be run on
04542    * the reply. We want consistent semantics in the case where we
04543    * dbus_connection_dispatch() the reply.
04544    */
04545   
04546   reply_serial = dbus_message_get_reply_serial (message);
04547   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04548                                          reply_serial);
04549   if (pending)
04550     {
04551       _dbus_verbose ("Dispatching a pending reply\n");
04552       complete_pending_call_and_unlock (connection, pending, message);
04553       pending = NULL; /* it's probably unref'd */
04554       
04555       CONNECTION_LOCK (connection);
04556       _dbus_verbose ("pending call completed in dispatch\n");
04557       result = DBUS_HANDLER_RESULT_HANDLED;
04558       goto out;
04559     }
04560 
04561   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04562   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04563     goto out;
04564  
04565   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04566     {
04567       _dbus_connection_release_dispatch (connection);
04568       HAVE_LOCK_CHECK (connection);
04569       
04570       _dbus_connection_failed_pop (connection, message_link);
04571 
04572       /* unlocks and calls user code */
04573       _dbus_connection_update_dispatch_status_and_unlock (connection,
04574                                                           DBUS_DISPATCH_NEED_MEMORY);
04575       dbus_connection_unref (connection);
04576       
04577       return DBUS_DISPATCH_NEED_MEMORY;
04578     }
04579   
04580   _dbus_list_foreach (&filter_list_copy,
04581                       (DBusForeachFunction)_dbus_message_filter_ref,
04582                       NULL);
04583 
04584   /* We're still protected from dispatch() reentrancy here
04585    * since we acquired the dispatcher
04586    */
04587   CONNECTION_UNLOCK (connection);
04588   
04589   link = _dbus_list_get_first_link (&filter_list_copy);
04590   while (link != NULL)
04591     {
04592       DBusMessageFilter *filter = link->data;
04593       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04594 
04595       if (filter->function == NULL)
04596         {
04597           _dbus_verbose ("  filter was removed in a callback function\n");
04598           link = next;
04599           continue;
04600         }
04601 
04602       _dbus_verbose ("  running filter on message %p\n", message);
04603       result = (* filter->function) (connection, message, filter->user_data);
04604 
04605       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04606         break;
04607 
04608       link = next;
04609     }
04610 
04611   _dbus_list_foreach (&filter_list_copy,
04612                       (DBusForeachFunction)_dbus_message_filter_unref,
04613                       NULL);
04614   _dbus_list_clear (&filter_list_copy);
04615   
04616   CONNECTION_LOCK (connection);
04617 
04618   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04619     {
04620       _dbus_verbose ("No memory\n");
04621       goto out;
04622     }
04623   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04624     {
04625       _dbus_verbose ("filter handled message in dispatch\n");
04626       goto out;
04627     }
04628 
04629   /* We're still protected from dispatch() reentrancy here
04630    * since we acquired the dispatcher
04631    */
04632   _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
04633                  message,
04634                  dbus_message_type_to_string (dbus_message_get_type (message)),
04635                  dbus_message_get_interface (message) ?
04636                  dbus_message_get_interface (message) :
04637                  "no interface",
04638                  dbus_message_get_member (message) ?
04639                  dbus_message_get_member (message) :
04640                  "no member",
04641                  dbus_message_get_signature (message));
04642 
04643   HAVE_LOCK_CHECK (connection);
04644   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04645                                                   message);
04646   
04647   CONNECTION_LOCK (connection);
04648 
04649   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04650     {
04651       _dbus_verbose ("object tree handled message in dispatch\n");
04652       goto out;
04653     }
04654 
04655   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04656     {
04657       DBusMessage *reply;
04658       DBusString str;
04659       DBusPreallocatedSend *preallocated;
04660 
04661       _dbus_verbose ("  sending error %s\n",
04662                      DBUS_ERROR_UNKNOWN_METHOD);
04663       
04664       if (!_dbus_string_init (&str))
04665         {
04666           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04667           _dbus_verbose ("no memory for error string in dispatch\n");
04668           goto out;
04669         }
04670               
04671       if (!_dbus_string_append_printf (&str,
04672                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04673                                        dbus_message_get_member (message),
04674                                        dbus_message_get_signature (message),
04675                                        dbus_message_get_interface (message)))
04676         {
04677           _dbus_string_free (&str);
04678           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04679           _dbus_verbose ("no memory for error string in dispatch\n");
04680           goto out;
04681         }
04682       
04683       reply = dbus_message_new_error (message,
04684                                       DBUS_ERROR_UNKNOWN_METHOD,
04685                                       _dbus_string_get_const_data (&str));
04686       _dbus_string_free (&str);
04687 
04688       if (reply == NULL)
04689         {
04690           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04691           _dbus_verbose ("no memory for error reply in dispatch\n");
04692           goto out;
04693         }
04694       
04695       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04696 
04697       if (preallocated == NULL)
04698         {
04699           dbus_message_unref (reply);
04700           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04701           _dbus_verbose ("no memory for error send in dispatch\n");
04702           goto out;
04703         }
04704 
04705       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04706                                                              reply, NULL);
04707 
04708       dbus_message_unref (reply);
04709       
04710       result = DBUS_HANDLER_RESULT_HANDLED;
04711     }
04712   
04713   _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04714                  dbus_message_type_to_string (dbus_message_get_type (message)),
04715                  dbus_message_get_interface (message) ?
04716                  dbus_message_get_interface (message) :
04717                  "no interface",
04718                  dbus_message_get_member (message) ?
04719                  dbus_message_get_member (message) :
04720                  "no member",
04721                  dbus_message_get_signature (message),
04722                  connection);
04723   
04724  out:
04725   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04726     {
04727       _dbus_verbose ("out of memory\n");
04728       
04729       /* Put message back, and we'll start over.
04730        * Yes this means handlers must be idempotent if they
04731        * don't return HANDLED; c'est la vie.
04732        */
04733       _dbus_connection_putback_message_link_unlocked (connection,
04734                                                       message_link);
04735     }
04736   else
04737     {
04738       _dbus_verbose (" ... done dispatching\n");
04739       
04740       _dbus_list_free_link (message_link);
04741       dbus_message_unref (message); /* don't want the message to count in max message limits
04742                                      * in computing dispatch status below
04743                                      */
04744     }
04745   
04746   _dbus_connection_release_dispatch (connection);
04747   HAVE_LOCK_CHECK (connection);
04748 
04749   _dbus_verbose ("before final status update\n");
04750   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04751 
04752   /* unlocks and calls user code */
04753   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04754   
04755   dbus_connection_unref (connection);
04756   
04757   return status;
04758 }
04759 
04821 dbus_bool_t
04822 dbus_connection_set_watch_functions (DBusConnection              *connection,
04823                                      DBusAddWatchFunction         add_function,
04824                                      DBusRemoveWatchFunction      remove_function,
04825                                      DBusWatchToggledFunction     toggled_function,
04826                                      void                        *data,
04827                                      DBusFreeFunction             free_data_function)
04828 {
04829   dbus_bool_t retval;
04830 
04831   _dbus_return_val_if_fail (connection != NULL, FALSE);
04832   
04833   CONNECTION_LOCK (connection);
04834 
04835   retval = _dbus_watch_list_set_functions (connection->watches,
04836                                            add_function, remove_function,
04837                                            toggled_function,
04838                                            data, free_data_function);
04839 
04840   CONNECTION_UNLOCK (connection);
04841 
04842   return retval;
04843 }
04844 
04884 dbus_bool_t
04885 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04886                                          DBusAddTimeoutFunction     add_function,
04887                                          DBusRemoveTimeoutFunction  remove_function,
04888                                          DBusTimeoutToggledFunction toggled_function,
04889                                          void                      *data,
04890                                          DBusFreeFunction           free_data_function)
04891 {
04892   dbus_bool_t retval;
04893 
04894   _dbus_return_val_if_fail (connection != NULL, FALSE);
04895   
04896   CONNECTION_LOCK (connection);
04897 
04898   retval = _dbus_timeout_list_set_functions (connection->timeouts,
04899                                              add_function, remove_function,
04900                                              toggled_function,
04901                                              data, free_data_function);
04902 
04903   CONNECTION_UNLOCK (connection);
04904 
04905   return retval;
04906 }
04907 
04922 void
04923 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04924                                           DBusWakeupMainFunction     wakeup_main_function,
04925                                           void                      *data,
04926                                           DBusFreeFunction           free_data_function)
04927 {
04928   void *old_data;
04929   DBusFreeFunction old_free_data;
04930 
04931   _dbus_return_if_fail (connection != NULL);
04932   
04933   CONNECTION_LOCK (connection);
04934   old_data = connection->wakeup_main_data;
04935   old_free_data = connection->free_wakeup_main_data;
04936 
04937   connection->wakeup_main_function = wakeup_main_function;
04938   connection->wakeup_main_data = data;
04939   connection->free_wakeup_main_data = free_data_function;
04940   
04941   CONNECTION_UNLOCK (connection);
04942 
04943   /* Callback outside the lock */
04944   if (old_free_data)
04945     (*old_free_data) (old_data);
04946 }
04947 
04968 void
04969 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
04970                                               DBusDispatchStatusFunction  function,
04971                                               void                       *data,
04972                                               DBusFreeFunction            free_data_function)
04973 {
04974   void *old_data;
04975   DBusFreeFunction old_free_data;
04976 
04977   _dbus_return_if_fail (connection != NULL);
04978   
04979   CONNECTION_LOCK (connection);
04980   old_data = connection->dispatch_status_data;
04981   old_free_data = connection->free_dispatch_status_data;
04982 
04983   connection->dispatch_status_function = function;
04984   connection->dispatch_status_data = data;
04985   connection->free_dispatch_status_data = free_data_function;
04986   
04987   CONNECTION_UNLOCK (connection);
04988 
04989   /* Callback outside the lock */
04990   if (old_free_data)
04991     (*old_free_data) (old_data);
04992 }
04993 
05013 dbus_bool_t
05014 dbus_connection_get_unix_fd (DBusConnection *connection,
05015                              int            *fd)
05016 {
05017   _dbus_return_val_if_fail (connection != NULL, FALSE);
05018   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05019 
05020 #ifdef DBUS_WIN
05021   /* FIXME do this on a lower level */
05022   return FALSE;
05023 #endif
05024   
05025   return dbus_connection_get_socket(connection, fd);
05026 }
05027 
05043 dbus_bool_t
05044 dbus_connection_get_socket(DBusConnection              *connection,
05045                            int                         *fd)
05046 {
05047   dbus_bool_t retval;
05048 
05049   _dbus_return_val_if_fail (connection != NULL, FALSE);
05050   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05051   
05052   CONNECTION_LOCK (connection);
05053   
05054   retval = _dbus_transport_get_socket_fd (connection->transport,
05055                                           fd);
05056 
05057   CONNECTION_UNLOCK (connection);
05058 
05059   return retval;
05060 }
05061 
05062 
05085 dbus_bool_t
05086 dbus_connection_get_unix_user (DBusConnection *connection,
05087                                unsigned long  *uid)
05088 {
05089   dbus_bool_t result;
05090 
05091   _dbus_return_val_if_fail (connection != NULL, FALSE);
05092   _dbus_return_val_if_fail (uid != NULL, FALSE);
05093   
05094   CONNECTION_LOCK (connection);
05095 
05096   if (!_dbus_transport_get_is_authenticated (connection->transport))
05097     result = FALSE;
05098   else
05099     result = _dbus_transport_get_unix_user (connection->transport,
05100                                             uid);
05101 
05102 #ifdef DBUS_WIN
05103   _dbus_assert (!result);
05104 #endif
05105   
05106   CONNECTION_UNLOCK (connection);
05107 
05108   return result;
05109 }
05110 
05121 dbus_bool_t
05122 dbus_connection_get_unix_process_id (DBusConnection *connection,
05123                                      unsigned long  *pid)
05124 {
05125   dbus_bool_t result;
05126 
05127   _dbus_return_val_if_fail (connection != NULL, FALSE);
05128   _dbus_return_val_if_fail (pid != NULL, FALSE);
05129   
05130   CONNECTION_LOCK (connection);
05131 
05132   if (!_dbus_transport_get_is_authenticated (connection->transport))
05133     result = FALSE;
05134   else
05135     result = _dbus_transport_get_unix_process_id (connection->transport,
05136                                                   pid);
05137 
05138   CONNECTION_UNLOCK (connection);
05139 
05140   return result;
05141 }
05142 
05153 dbus_bool_t
05154 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05155                                             void          **data,
05156                                             dbus_int32_t   *data_size)
05157 {
05158   dbus_bool_t result;
05159 
05160   _dbus_return_val_if_fail (connection != NULL, FALSE);
05161   _dbus_return_val_if_fail (data != NULL, FALSE);
05162   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05163   
05164   CONNECTION_LOCK (connection);
05165 
05166   if (!_dbus_transport_get_is_authenticated (connection->transport))
05167     result = FALSE;
05168   else
05169     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05170                                                          data,
05171                                                          data_size);
05172   CONNECTION_UNLOCK (connection);
05173 
05174   return result;
05175 }
05176 
05199 void
05200 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05201                                         DBusAllowUnixUserFunction   function,
05202                                         void                       *data,
05203                                         DBusFreeFunction            free_data_function)
05204 {
05205   void *old_data = NULL;
05206   DBusFreeFunction old_free_function = NULL;
05207 
05208   _dbus_return_if_fail (connection != NULL);
05209   
05210   CONNECTION_LOCK (connection);
05211   _dbus_transport_set_unix_user_function (connection->transport,
05212                                           function, data, free_data_function,
05213                                           &old_data, &old_free_function);
05214   CONNECTION_UNLOCK (connection);
05215 
05216   if (old_free_function != NULL)
05217     (* old_free_function) (old_data);
05218 }
05219 
05251 dbus_bool_t
05252 dbus_connection_get_windows_user (DBusConnection             *connection,
05253                                   char                      **windows_sid_p)
05254 {
05255   dbus_bool_t result;
05256 
05257   _dbus_return_val_if_fail (connection != NULL, FALSE);
05258   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05259   
05260   CONNECTION_LOCK (connection);
05261 
05262   if (!_dbus_transport_get_is_authenticated (connection->transport))
05263     result = FALSE;
05264   else
05265     result = _dbus_transport_get_windows_user (connection->transport,
05266                                                windows_sid_p);
05267 
05268 #ifdef DBUS_UNIX
05269   _dbus_assert (!result);
05270 #endif
05271   
05272   CONNECTION_UNLOCK (connection);
05273 
05274   return result;
05275 }
05276 
05298 void
05299 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05300                                            DBusAllowWindowsUserFunction function,
05301                                            void                        *data,
05302                                            DBusFreeFunction             free_data_function)
05303 {
05304   void *old_data = NULL;
05305   DBusFreeFunction old_free_function = NULL;
05306 
05307   _dbus_return_if_fail (connection != NULL);
05308   
05309   CONNECTION_LOCK (connection);
05310   _dbus_transport_set_windows_user_function (connection->transport,
05311                                              function, data, free_data_function,
05312                                              &old_data, &old_free_function);
05313   CONNECTION_UNLOCK (connection);
05314 
05315   if (old_free_function != NULL)
05316     (* old_free_function) (old_data);
05317 }
05318 
05345 void
05346 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05347                                      dbus_bool_t                 value)
05348 {
05349   _dbus_return_if_fail (connection != NULL);
05350   
05351   CONNECTION_LOCK (connection);
05352   _dbus_transport_set_allow_anonymous (connection->transport, value);
05353   CONNECTION_UNLOCK (connection);
05354 }
05355 
05373 void
05374 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05375                                          dbus_bool_t                 value)
05376 {
05377   _dbus_return_if_fail (connection != NULL);
05378   
05379   CONNECTION_LOCK (connection);
05380   connection->route_peer_messages = TRUE;
05381   CONNECTION_UNLOCK (connection);
05382 }
05383 
05405 dbus_bool_t
05406 dbus_connection_add_filter (DBusConnection            *connection,
05407                             DBusHandleMessageFunction  function,
05408                             void                      *user_data,
05409                             DBusFreeFunction           free_data_function)
05410 {
05411   DBusMessageFilter *filter;
05412   
05413   _dbus_return_val_if_fail (connection != NULL, FALSE);
05414   _dbus_return_val_if_fail (function != NULL, FALSE);
05415 
05416   filter = dbus_new0 (DBusMessageFilter, 1);
05417   if (filter == NULL)
05418     return FALSE;
05419 
05420   _dbus_atomic_inc (&filter->refcount);
05421 
05422   CONNECTION_LOCK (connection);
05423 
05424   if (!_dbus_list_append (&connection->filter_list,
05425                           filter))
05426     {
05427       _dbus_message_filter_unref (filter);
05428       CONNECTION_UNLOCK (connection);
05429       return FALSE;
05430     }
05431 
05432   /* Fill in filter after all memory allocated,
05433    * so we don't run the free_user_data_function
05434    * if the add_filter() fails
05435    */
05436   
05437   filter->function = function;
05438   filter->user_data = user_data;
05439   filter->free_user_data_function = free_data_function;
05440         
05441   CONNECTION_UNLOCK (connection);
05442   return TRUE;
05443 }
05444 
05457 void
05458 dbus_connection_remove_filter (DBusConnection            *connection,
05459                                DBusHandleMessageFunction  function,
05460                                void                      *user_data)
05461 {
05462   DBusList *link;
05463   DBusMessageFilter *filter;
05464   
05465   _dbus_return_if_fail (connection != NULL);
05466   _dbus_return_if_fail (function != NULL);
05467   
05468   CONNECTION_LOCK (connection);
05469 
05470   filter = NULL;
05471   
05472   link = _dbus_list_get_last_link (&connection->filter_list);
05473   while (link != NULL)
05474     {
05475       filter = link->data;
05476 
05477       if (filter->function == function &&
05478           filter->user_data == user_data)
05479         {
05480           _dbus_list_remove_link (&connection->filter_list, link);
05481           filter->function = NULL;
05482           
05483           break;
05484         }
05485         
05486       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05487       filter = NULL;
05488     }
05489   
05490   CONNECTION_UNLOCK (connection);
05491 
05492 #ifndef DBUS_DISABLE_CHECKS
05493   if (filter == NULL)
05494     {
05495       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05496                                function, user_data);
05497       return;
05498     }
05499 #endif
05500   
05501   /* Call application code */
05502   if (filter->free_user_data_function)
05503     (* filter->free_user_data_function) (filter->user_data);
05504 
05505   filter->free_user_data_function = NULL;
05506   filter->user_data = NULL;
05507   
05508   _dbus_message_filter_unref (filter);
05509 }
05510 
05523 dbus_bool_t
05524 dbus_connection_try_register_object_path (DBusConnection              *connection,
05525                                           const char                  *path,
05526                                           const DBusObjectPathVTable  *vtable,
05527                                           void                        *user_data,
05528                                           DBusError                   *error)
05529 {
05530   char **decomposed_path;
05531   dbus_bool_t retval;
05532   
05533   _dbus_return_val_if_fail (connection != NULL, FALSE);
05534   _dbus_return_val_if_fail (path != NULL, FALSE);
05535   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05536   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05537 
05538   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05539     return FALSE;
05540 
05541   CONNECTION_LOCK (connection);
05542 
05543   retval = _dbus_object_tree_register (connection->objects,
05544                                        FALSE,
05545                                        (const char **) decomposed_path, vtable,
05546                                        user_data, error);
05547 
05548   CONNECTION_UNLOCK (connection);
05549 
05550   dbus_free_string_array (decomposed_path);
05551 
05552   return retval;
05553 }
05554 
05570 dbus_bool_t
05571 dbus_connection_register_object_path (DBusConnection              *connection,
05572                                       const char                  *path,
05573                                       const DBusObjectPathVTable  *vtable,
05574                                       void                        *user_data)
05575 {
05576   char **decomposed_path;
05577   dbus_bool_t retval;
05578   DBusError error = DBUS_ERROR_INIT;
05579 
05580   _dbus_return_val_if_fail (connection != NULL, FALSE);
05581   _dbus_return_val_if_fail (path != NULL, FALSE);
05582   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05583   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05584 
05585   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05586     return FALSE;
05587 
05588   CONNECTION_LOCK (connection);
05589 
05590   retval = _dbus_object_tree_register (connection->objects,
05591                                        FALSE,
05592                                        (const char **) decomposed_path, vtable,
05593                                        user_data, &error);
05594 
05595   CONNECTION_UNLOCK (connection);
05596 
05597   dbus_free_string_array (decomposed_path);
05598 
05599   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05600     {
05601       _dbus_warn ("%s\n", error.message);
05602       dbus_error_free (&error);
05603       return FALSE;
05604     }
05605 
05606   return retval;
05607 }
05608 
05623 dbus_bool_t
05624 dbus_connection_try_register_fallback (DBusConnection              *connection,
05625                                        const char                  *path,
05626                                        const DBusObjectPathVTable  *vtable,
05627                                        void                        *user_data,
05628                                        DBusError                   *error)
05629 {
05630   char **decomposed_path;
05631   dbus_bool_t retval;
05632 
05633   _dbus_return_val_if_fail (connection != NULL, FALSE);
05634   _dbus_return_val_if_fail (path != NULL, FALSE);
05635   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05636   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05637 
05638   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05639     return FALSE;
05640 
05641   CONNECTION_LOCK (connection);
05642 
05643   retval = _dbus_object_tree_register (connection->objects,
05644                                        TRUE,
05645                                        (const char **) decomposed_path, vtable,
05646                                        user_data, error);
05647 
05648   CONNECTION_UNLOCK (connection);
05649 
05650   dbus_free_string_array (decomposed_path);
05651 
05652   return retval;
05653 }
05654 
05672 dbus_bool_t
05673 dbus_connection_register_fallback (DBusConnection              *connection,
05674                                    const char                  *path,
05675                                    const DBusObjectPathVTable  *vtable,
05676                                    void                        *user_data)
05677 {
05678   char **decomposed_path;
05679   dbus_bool_t retval;
05680   DBusError error = DBUS_ERROR_INIT;
05681 
05682   _dbus_return_val_if_fail (connection != NULL, FALSE);
05683   _dbus_return_val_if_fail (path != NULL, FALSE);
05684   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05685   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05686 
05687   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05688     return FALSE;
05689 
05690   CONNECTION_LOCK (connection);
05691 
05692   retval = _dbus_object_tree_register (connection->objects,
05693                                        TRUE,
05694                                        (const char **) decomposed_path, vtable,
05695                                        user_data, &error);
05696 
05697   CONNECTION_UNLOCK (connection);
05698 
05699   dbus_free_string_array (decomposed_path);
05700 
05701   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05702     {
05703       _dbus_warn ("%s\n", error.message);
05704       dbus_error_free (&error);
05705       return FALSE;
05706     }
05707 
05708   return retval;
05709 }
05710 
05720 dbus_bool_t
05721 dbus_connection_unregister_object_path (DBusConnection              *connection,
05722                                         const char                  *path)
05723 {
05724   char **decomposed_path;
05725 
05726   _dbus_return_val_if_fail (connection != NULL, FALSE);
05727   _dbus_return_val_if_fail (path != NULL, FALSE);
05728   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05729 
05730   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05731       return FALSE;
05732 
05733   CONNECTION_LOCK (connection);
05734 
05735   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05736 
05737   dbus_free_string_array (decomposed_path);
05738 
05739   return TRUE;
05740 }
05741 
05752 dbus_bool_t
05753 dbus_connection_get_object_path_data (DBusConnection *connection,
05754                                       const char     *path,
05755                                       void          **data_p)
05756 {
05757   char **decomposed_path;
05758 
05759   _dbus_return_val_if_fail (connection != NULL, FALSE);
05760   _dbus_return_val_if_fail (path != NULL, FALSE);
05761   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05762 
05763   *data_p = NULL;
05764   
05765   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05766     return FALSE;
05767   
05768   CONNECTION_LOCK (connection);
05769 
05770   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05771 
05772   CONNECTION_UNLOCK (connection);
05773 
05774   dbus_free_string_array (decomposed_path);
05775 
05776   return TRUE;
05777 }
05778 
05789 dbus_bool_t
05790 dbus_connection_list_registered (DBusConnection              *connection,
05791                                  const char                  *parent_path,
05792                                  char                      ***child_entries)
05793 {
05794   char **decomposed_path;
05795   dbus_bool_t retval;
05796   _dbus_return_val_if_fail (connection != NULL, FALSE);
05797   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05798   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05799   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05800 
05801   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05802     return FALSE;
05803 
05804   CONNECTION_LOCK (connection);
05805 
05806   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05807                                                          (const char **) decomposed_path,
05808                                                          child_entries);
05809   dbus_free_string_array (decomposed_path);
05810 
05811   return retval;
05812 }
05813 
05814 static DBusDataSlotAllocator slot_allocator;
05815 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05816 
05831 dbus_bool_t
05832 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05833 {
05834   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05835                                           &_DBUS_LOCK_NAME (connection_slots),
05836                                           slot_p);
05837 }
05838 
05850 void
05851 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05852 {
05853   _dbus_return_if_fail (*slot_p >= 0);
05854   
05855   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05856 }
05857 
05880 dbus_bool_t
05881 dbus_connection_set_data (DBusConnection   *connection,
05882                           dbus_int32_t      slot,
05883                           void             *data,
05884                           DBusFreeFunction  free_data_func)
05885 {
05886   DBusFreeFunction old_free_func;
05887   void *old_data;
05888   dbus_bool_t retval;
05889 
05890   _dbus_return_val_if_fail (connection != NULL, FALSE);
05891   _dbus_return_val_if_fail (slot >= 0, FALSE);
05892   
05893   SLOTS_LOCK (connection);
05894 
05895   retval = _dbus_data_slot_list_set (&slot_allocator,
05896                                      &connection->slot_list,
05897                                      slot, data, free_data_func,
05898                                      &old_free_func, &old_data);
05899   
05900   SLOTS_UNLOCK (connection);
05901 
05902   if (retval)
05903     {
05904       /* Do the actual free outside the connection lock */
05905       if (old_free_func)
05906         (* old_free_func) (old_data);
05907     }
05908 
05909   return retval;
05910 }
05911 
05929 void*
05930 dbus_connection_get_data (DBusConnection   *connection,
05931                           dbus_int32_t      slot)
05932 {
05933   void *res;
05934 
05935   _dbus_return_val_if_fail (connection != NULL, NULL);
05936   
05937   SLOTS_LOCK (connection);
05938 
05939   res = _dbus_data_slot_list_get (&slot_allocator,
05940                                   &connection->slot_list,
05941                                   slot);
05942   
05943   SLOTS_UNLOCK (connection);
05944 
05945   return res;
05946 }
05947 
05954 void
05955 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05956 {  
05957   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05958 }
05959 
05968 void
05969 dbus_connection_set_max_message_size (DBusConnection *connection,
05970                                       long            size)
05971 {
05972   _dbus_return_if_fail (connection != NULL);
05973   
05974   CONNECTION_LOCK (connection);
05975   _dbus_transport_set_max_message_size (connection->transport,
05976                                         size);
05977   CONNECTION_UNLOCK (connection);
05978 }
05979 
05986 long
05987 dbus_connection_get_max_message_size (DBusConnection *connection)
05988 {
05989   long res;
05990 
05991   _dbus_return_val_if_fail (connection != NULL, 0);
05992   
05993   CONNECTION_LOCK (connection);
05994   res = _dbus_transport_get_max_message_size (connection->transport);
05995   CONNECTION_UNLOCK (connection);
05996   return res;
05997 }
05998 
06007 void
06008 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06009                                           long            n)
06010 {
06011   _dbus_return_if_fail (connection != NULL);
06012 
06013   CONNECTION_LOCK (connection);
06014   _dbus_transport_set_max_message_unix_fds (connection->transport,
06015                                             n);
06016   CONNECTION_UNLOCK (connection);
06017 }
06018 
06025 long
06026 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06027 {
06028   long res;
06029 
06030   _dbus_return_val_if_fail (connection != NULL, 0);
06031 
06032   CONNECTION_LOCK (connection);
06033   res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06034   CONNECTION_UNLOCK (connection);
06035   return res;
06036 }
06037 
06063 void
06064 dbus_connection_set_max_received_size (DBusConnection *connection,
06065                                        long            size)
06066 {
06067   _dbus_return_if_fail (connection != NULL);
06068   
06069   CONNECTION_LOCK (connection);
06070   _dbus_transport_set_max_received_size (connection->transport,
06071                                          size);
06072   CONNECTION_UNLOCK (connection);
06073 }
06074 
06081 long
06082 dbus_connection_get_max_received_size (DBusConnection *connection)
06083 {
06084   long res;
06085 
06086   _dbus_return_val_if_fail (connection != NULL, 0);
06087   
06088   CONNECTION_LOCK (connection);
06089   res = _dbus_transport_get_max_received_size (connection->transport);
06090   CONNECTION_UNLOCK (connection);
06091   return res;
06092 }
06093 
06105 void
06106 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06107                                            long            n)
06108 {
06109   _dbus_return_if_fail (connection != NULL);
06110 
06111   CONNECTION_LOCK (connection);
06112   _dbus_transport_set_max_received_unix_fds (connection->transport,
06113                                              n);
06114   CONNECTION_UNLOCK (connection);
06115 }
06116 
06123 long
06124 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06125 {
06126   long res;
06127 
06128   _dbus_return_val_if_fail (connection != NULL, 0);
06129 
06130   CONNECTION_LOCK (connection);
06131   res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06132   CONNECTION_UNLOCK (connection);
06133   return res;
06134 }
06135 
06146 long
06147 dbus_connection_get_outgoing_size (DBusConnection *connection)
06148 {
06149   long res;
06150 
06151   _dbus_return_val_if_fail (connection != NULL, 0);
06152 
06153   CONNECTION_LOCK (connection);
06154   res = _dbus_counter_get_size_value (connection->outgoing_counter);
06155   CONNECTION_UNLOCK (connection);
06156   return res;
06157 }
06158 
06166 long
06167 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06168 {
06169   long res;
06170 
06171   _dbus_return_val_if_fail (connection != NULL, 0);
06172 
06173   CONNECTION_LOCK (connection);
06174   res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06175   CONNECTION_UNLOCK (connection);
06176   return res;
06177 }
06178