D-Bus  1.6.8
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-signature.h"
00042 #include "dbus-pending-call.h"
00043 #include "dbus-object-tree.h"
00044 #include "dbus-threads-internal.h"
00045 #include "dbus-bus.h"
00046 #include "dbus-marshal-basic.h"
00047 
00048 #ifdef DBUS_DISABLE_CHECKS
00049 #define TOOK_LOCK_CHECK(connection)
00050 #define RELEASING_LOCK_CHECK(connection)
00051 #define HAVE_LOCK_CHECK(connection)
00052 #else
00053 #define TOOK_LOCK_CHECK(connection) do {                \
00054     _dbus_assert (!(connection)->have_connection_lock); \
00055     (connection)->have_connection_lock = TRUE;          \
00056   } while (0)
00057 #define RELEASING_LOCK_CHECK(connection) do {            \
00058     _dbus_assert ((connection)->have_connection_lock);   \
00059     (connection)->have_connection_lock = FALSE;          \
00060   } while (0)
00061 #define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
00062 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
00063 #endif
00064 
00065 #define TRACE_LOCKS 1
00066 
00067 #define CONNECTION_LOCK(connection)   do {                                      \
00068     if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); }   \
00069     _dbus_rmutex_lock ((connection)->mutex);                                    \
00070     TOOK_LOCK_CHECK (connection);                                               \
00071   } while (0)
00072 
00073 #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
00074 
00075 #define SLOTS_LOCK(connection) do {                     \
00076     _dbus_rmutex_lock ((connection)->slot_mutex);       \
00077   } while (0)
00078 
00079 #define SLOTS_UNLOCK(connection) do {                   \
00080     _dbus_rmutex_unlock ((connection)->slot_mutex);     \
00081   } while (0)
00082 
00083 #define DISPATCH_STATUS_NAME(s)                                            \
00084                      ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
00085                       (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00086                       (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
00087                       "???")
00088 
00206 #ifdef DBUS_ENABLE_VERBOSE_MODE
00207 static void
00208 _dbus_connection_trace_ref (DBusConnection *connection,
00209     int old_refcount,
00210     int new_refcount,
00211     const char *why)
00212 {
00213   static int enabled = -1;
00214 
00215   _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
00216       why, "DBUS_CONNECTION_TRACE", &enabled);
00217 }
00218 #else
00219 #define _dbus_connection_trace_ref(c,o,n,w) \
00220   do \
00221   {\
00222     (void) (o); \
00223     (void) (n); \
00224   } while (0)
00225 #endif
00226 
00230 typedef struct DBusMessageFilter DBusMessageFilter;
00231 
00235 struct DBusMessageFilter
00236 {
00237   DBusAtomic refcount; 
00238   DBusHandleMessageFunction function; 
00239   void *user_data; 
00240   DBusFreeFunction free_user_data_function; 
00241 };
00242 
00243 
00247 struct DBusPreallocatedSend
00248 {
00249   DBusConnection *connection; 
00250   DBusList *queue_link;       
00251   DBusList *counter_link;     
00252 };
00253 
00254 #if HAVE_DECL_MSG_NOSIGNAL
00255 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00256 #else
00257 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00258 #endif
00259 
00263 struct DBusConnection
00264 {
00265   DBusAtomic refcount; 
00267   DBusRMutex *mutex; 
00269   DBusCMutex *dispatch_mutex;     
00270   DBusCondVar *dispatch_cond;    
00271   DBusCMutex *io_path_mutex;      
00272   DBusCondVar *io_path_cond;     
00274   DBusList *outgoing_messages; 
00275   DBusList *incoming_messages; 
00276   DBusList *expired_messages;  
00278   DBusMessage *message_borrowed; 
00282   int n_outgoing;              
00283   int n_incoming;              
00285   DBusCounter *outgoing_counter; 
00287   DBusTransport *transport;    
00288   DBusWatchList *watches;      
00289   DBusTimeoutList *timeouts;   
00291   DBusList *filter_list;        
00293   DBusRMutex *slot_mutex;        
00294   DBusDataSlotList slot_list;   
00296   DBusHashTable *pending_replies;  
00298   dbus_uint32_t client_serial;       
00299   DBusList *disconnect_message_link; 
00301   DBusWakeupMainFunction wakeup_main_function; 
00302   void *wakeup_main_data; 
00303   DBusFreeFunction free_wakeup_main_data; 
00305   DBusDispatchStatusFunction dispatch_status_function; 
00306   void *dispatch_status_data; 
00307   DBusFreeFunction free_dispatch_status_data; 
00309   DBusDispatchStatus last_dispatch_status; 
00311   DBusObjectTree *objects; 
00313   char *server_guid; 
00315   /* These two MUST be bools and not bitfields, because they are protected by a separate lock
00316    * from connection->mutex and all bitfields in a word have to be read/written together.
00317    * So you can't have a different lock for different bitfields in the same word.
00318    */
00319   dbus_bool_t dispatch_acquired; 
00320   dbus_bool_t io_path_acquired;  
00322   unsigned int shareable : 1; 
00324   unsigned int exit_on_disconnect : 1; 
00326   unsigned int route_peer_messages : 1; 
00328   unsigned int disconnected_message_arrived : 1;   
00332   unsigned int disconnected_message_processed : 1; 
00336 #ifndef DBUS_DISABLE_CHECKS
00337   unsigned int have_connection_lock : 1; 
00338 #endif
00339   
00340 #ifndef DBUS_DISABLE_CHECKS
00341   int generation; 
00342 #endif 
00343 };
00344 
00345 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
00346 static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
00347                                                                               DBusDispatchStatus  new_status);
00348 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
00349 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
00350 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
00351 static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
00352 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
00353 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
00354 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
00355                                                                               dbus_uint32_t       client_serial);
00356 
00357 static DBusMessageFilter *
00358 _dbus_message_filter_ref (DBusMessageFilter *filter)
00359 {
00360 #ifdef DBUS_DISABLE_ASSERT
00361   _dbus_atomic_inc (&filter->refcount);
00362 #else
00363   dbus_int32_t old_value;
00364 
00365   old_value = _dbus_atomic_inc (&filter->refcount);
00366   _dbus_assert (old_value > 0);
00367 #endif
00368 
00369   return filter;
00370 }
00371 
00372 static void
00373 _dbus_message_filter_unref (DBusMessageFilter *filter)
00374 {
00375   dbus_int32_t old_value;
00376 
00377   old_value = _dbus_atomic_dec (&filter->refcount);
00378   _dbus_assert (old_value > 0);
00379 
00380   if (old_value == 1)
00381     {
00382       if (filter->free_user_data_function)
00383         (* filter->free_user_data_function) (filter->user_data);
00384       
00385       dbus_free (filter);
00386     }
00387 }
00388 
00394 void
00395 _dbus_connection_lock (DBusConnection *connection)
00396 {
00397   CONNECTION_LOCK (connection);
00398 }
00399 
00405 void
00406 _dbus_connection_unlock (DBusConnection *connection)
00407 {
00408   DBusList *expired_messages;
00409   DBusList *iter;
00410 
00411   if (TRACE_LOCKS)
00412     {
00413       _dbus_verbose ("UNLOCK\n");
00414     }
00415 
00416   /* If we had messages that expired (fell off the incoming or outgoing
00417    * queues) while we were locked, actually release them now */
00418   expired_messages = connection->expired_messages;
00419   connection->expired_messages = NULL;
00420 
00421   RELEASING_LOCK_CHECK (connection);
00422   _dbus_rmutex_unlock (connection->mutex);
00423 
00424   for (iter = _dbus_list_pop_first_link (&expired_messages);
00425       iter != NULL;
00426       iter = _dbus_list_pop_first_link (&expired_messages))
00427     {
00428       DBusMessage *message = iter->data;
00429 
00430       dbus_message_unref (message);
00431       _dbus_list_free_link (iter);
00432     }
00433 }
00434 
00442 static void
00443 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00444 {
00445   if (connection->wakeup_main_function)
00446     (*connection->wakeup_main_function) (connection->wakeup_main_data);
00447 }
00448 
00449 #ifdef DBUS_BUILD_TESTS
00450 
00462 void 
00463 _dbus_connection_test_get_locks (DBusConnection *connection,
00464                                  DBusMutex     **mutex_loc,
00465                                  DBusMutex     **dispatch_mutex_loc,
00466                                  DBusMutex     **io_path_mutex_loc,
00467                                  DBusCondVar   **dispatch_cond_loc,
00468                                  DBusCondVar   **io_path_cond_loc)
00469 {
00470   *mutex_loc = (DBusMutex *) connection->mutex;
00471   *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
00472   *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
00473   *dispatch_cond_loc = connection->dispatch_cond;
00474   *io_path_cond_loc = connection->io_path_cond;
00475 }
00476 #endif
00477 
00486 void
00487 _dbus_connection_queue_received_message_link (DBusConnection  *connection,
00488                                               DBusList        *link)
00489 {
00490   DBusPendingCall *pending;
00491   dbus_uint32_t reply_serial;
00492   DBusMessage *message;
00493   
00494   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00495   
00496   _dbus_list_append_link (&connection->incoming_messages,
00497                           link);
00498   message = link->data;
00499 
00500   /* If this is a reply we're waiting on, remove timeout for it */
00501   reply_serial = dbus_message_get_reply_serial (message);
00502   if (reply_serial != 0)
00503     {
00504       pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00505                                              reply_serial);
00506       if (pending != NULL)
00507         {
00508           if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00509             _dbus_connection_remove_timeout_unlocked (connection,
00510                                                       _dbus_pending_call_get_timeout_unlocked (pending));
00511 
00512           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00513         }
00514     }
00515   
00516   
00517 
00518   connection->n_incoming += 1;
00519 
00520   _dbus_connection_wakeup_mainloop (connection);
00521   
00522   _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00523                  message,
00524                  dbus_message_type_to_string (dbus_message_get_type (message)),
00525                  dbus_message_get_path (message) ?
00526                  dbus_message_get_path (message) :
00527                  "no path",
00528                  dbus_message_get_interface (message) ?
00529                  dbus_message_get_interface (message) :
00530                  "no interface",
00531                  dbus_message_get_member (message) ?
00532                  dbus_message_get_member (message) :
00533                  "no member",
00534                  dbus_message_get_signature (message),
00535                  dbus_message_get_reply_serial (message),
00536                  connection,
00537                  connection->n_incoming);
00538 
00539   _dbus_message_trace_ref (message, -1, -1,
00540       "_dbus_conection_queue_received_message_link");
00541 }
00542 
00551 void
00552 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00553                                                  DBusList *link)
00554 {
00555   HAVE_LOCK_CHECK (connection);
00556   
00557   _dbus_list_append_link (&connection->incoming_messages, link);
00558 
00559   connection->n_incoming += 1;
00560 
00561   _dbus_connection_wakeup_mainloop (connection);
00562 
00563   _dbus_message_trace_ref (link->data, -1, -1,
00564       "_dbus_connection_queue_synthesized_message_link");
00565 
00566   _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00567                  link->data, connection, connection->n_incoming);
00568 }
00569 
00570 
00578 dbus_bool_t
00579 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00580 {
00581   HAVE_LOCK_CHECK (connection);
00582   return connection->outgoing_messages != NULL;
00583 }
00584 
00594 dbus_bool_t
00595 dbus_connection_has_messages_to_send (DBusConnection *connection)
00596 {
00597   dbus_bool_t v;
00598   
00599   _dbus_return_val_if_fail (connection != NULL, FALSE);
00600 
00601   CONNECTION_LOCK (connection);
00602   v = _dbus_connection_has_messages_to_send_unlocked (connection);
00603   CONNECTION_UNLOCK (connection);
00604 
00605   return v;
00606 }
00607 
00615 DBusMessage*
00616 _dbus_connection_get_message_to_send (DBusConnection *connection)
00617 {
00618   HAVE_LOCK_CHECK (connection);
00619   
00620   return _dbus_list_get_last (&connection->outgoing_messages);
00621 }
00622 
00631 void
00632 _dbus_connection_message_sent_unlocked (DBusConnection *connection,
00633                                         DBusMessage    *message)
00634 {
00635   DBusList *link;
00636 
00637   HAVE_LOCK_CHECK (connection);
00638   
00639   /* This can be called before we even complete authentication, since
00640    * it's called on disconnect to clean up the outgoing queue.
00641    * It's also called as we successfully send each message.
00642    */
00643   
00644   link = _dbus_list_get_last_link (&connection->outgoing_messages);
00645   _dbus_assert (link != NULL);
00646   _dbus_assert (link->data == message);
00647 
00648   _dbus_list_unlink (&connection->outgoing_messages,
00649                      link);
00650   _dbus_list_prepend_link (&connection->expired_messages, link);
00651 
00652   connection->n_outgoing -= 1;
00653 
00654   _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00655                  message,
00656                  dbus_message_type_to_string (dbus_message_get_type (message)),
00657                  dbus_message_get_path (message) ?
00658                  dbus_message_get_path (message) :
00659                  "no path",
00660                  dbus_message_get_interface (message) ?
00661                  dbus_message_get_interface (message) :
00662                  "no interface",
00663                  dbus_message_get_member (message) ?
00664                  dbus_message_get_member (message) :
00665                  "no member",
00666                  dbus_message_get_signature (message),
00667                  connection, connection->n_outgoing);
00668 
00669   /* It's OK that in principle we call the notify function, because for the
00670    * outgoing limit, there isn't one */
00671   _dbus_message_remove_counter (message, connection->outgoing_counter);
00672 
00673   /* The message will actually be unreffed when we unlock */
00674 }
00675 
00677 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
00678                                                   DBusWatch     *watch);
00680 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
00681                                                   DBusWatch     *watch);
00683 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
00684                                                   DBusWatch     *watch,
00685                                                   dbus_bool_t    enabled);
00686 
00687 static dbus_bool_t
00688 protected_change_watch (DBusConnection         *connection,
00689                         DBusWatch              *watch,
00690                         DBusWatchAddFunction    add_function,
00691                         DBusWatchRemoveFunction remove_function,
00692                         DBusWatchToggleFunction toggle_function,
00693                         dbus_bool_t             enabled)
00694 {
00695   dbus_bool_t retval;
00696 
00697   HAVE_LOCK_CHECK (connection);
00698 
00699   /* The original purpose of protected_change_watch() was to hold a
00700    * ref on the connection while dropping the connection lock, then
00701    * calling out to the app.  This was a broken hack that did not
00702    * work, since the connection was in a hosed state (no WatchList
00703    * field) while calling out.
00704    *
00705    * So for now we'll just keep the lock while calling out. This means
00706    * apps are not allowed to call DBusConnection methods inside a
00707    * watch function or they will deadlock.
00708    *
00709    * The "real fix" is to use the _and_unlock() pattern found
00710    * elsewhere in the code, to defer calling out to the app until
00711    * we're about to drop locks and return flow of control to the app
00712    * anyway.
00713    *
00714    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00715    */
00716 
00717   if (connection->watches)
00718     {
00719       if (add_function)
00720         retval = (* add_function) (connection->watches, watch);
00721       else if (remove_function)
00722         {
00723           retval = TRUE;
00724           (* remove_function) (connection->watches, watch);
00725         }
00726       else
00727         {
00728           retval = TRUE;
00729           (* toggle_function) (connection->watches, watch, enabled);
00730         }
00731       return retval;
00732     }
00733   else
00734     return FALSE;
00735 }
00736      
00737 
00749 dbus_bool_t
00750 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00751                                      DBusWatch      *watch)
00752 {
00753   return protected_change_watch (connection, watch,
00754                                  _dbus_watch_list_add_watch,
00755                                  NULL, NULL, FALSE);
00756 }
00757 
00767 void
00768 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00769                                         DBusWatch      *watch)
00770 {
00771   protected_change_watch (connection, watch,
00772                           NULL,
00773                           _dbus_watch_list_remove_watch,
00774                           NULL, FALSE);
00775 }
00776 
00787 void
00788 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00789                                         DBusWatch      *watch,
00790                                         dbus_bool_t     enabled)
00791 {
00792   _dbus_assert (watch != NULL);
00793 
00794   protected_change_watch (connection, watch,
00795                           NULL, NULL,
00796                           _dbus_watch_list_toggle_watch,
00797                           enabled);
00798 }
00799 
00801 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
00802                                                    DBusTimeout     *timeout);
00804 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00805                                                    DBusTimeout     *timeout);
00807 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00808                                                    DBusTimeout     *timeout,
00809                                                    dbus_bool_t      enabled);
00810 
00811 static dbus_bool_t
00812 protected_change_timeout (DBusConnection           *connection,
00813                           DBusTimeout              *timeout,
00814                           DBusTimeoutAddFunction    add_function,
00815                           DBusTimeoutRemoveFunction remove_function,
00816                           DBusTimeoutToggleFunction toggle_function,
00817                           dbus_bool_t               enabled)
00818 {
00819   dbus_bool_t retval;
00820 
00821   HAVE_LOCK_CHECK (connection);
00822 
00823   /* The original purpose of protected_change_timeout() was to hold a
00824    * ref on the connection while dropping the connection lock, then
00825    * calling out to the app.  This was a broken hack that did not
00826    * work, since the connection was in a hosed state (no TimeoutList
00827    * field) while calling out.
00828    *
00829    * So for now we'll just keep the lock while calling out. This means
00830    * apps are not allowed to call DBusConnection methods inside a
00831    * timeout function or they will deadlock.
00832    *
00833    * The "real fix" is to use the _and_unlock() pattern found
00834    * elsewhere in the code, to defer calling out to the app until
00835    * we're about to drop locks and return flow of control to the app
00836    * anyway.
00837    *
00838    * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
00839    */
00840 
00841   if (connection->timeouts)
00842     {
00843       if (add_function)
00844         retval = (* add_function) (connection->timeouts, timeout);
00845       else if (remove_function)
00846         {
00847           retval = TRUE;
00848           (* remove_function) (connection->timeouts, timeout);
00849         }
00850       else
00851         {
00852           retval = TRUE;
00853           (* toggle_function) (connection->timeouts, timeout, enabled);
00854         }
00855       return retval;
00856     }
00857   else
00858     return FALSE;
00859 }
00860 
00873 dbus_bool_t
00874 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00875                                        DBusTimeout    *timeout)
00876 {
00877   return protected_change_timeout (connection, timeout,
00878                                    _dbus_timeout_list_add_timeout,
00879                                    NULL, NULL, FALSE);
00880 }
00881 
00891 void
00892 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00893                                           DBusTimeout    *timeout)
00894 {
00895   protected_change_timeout (connection, timeout,
00896                             NULL,
00897                             _dbus_timeout_list_remove_timeout,
00898                             NULL, FALSE);
00899 }
00900 
00911 void
00912 _dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
00913                                           DBusTimeout      *timeout,
00914                                           dbus_bool_t       enabled)
00915 {
00916   protected_change_timeout (connection, timeout,
00917                             NULL, NULL,
00918                             _dbus_timeout_list_toggle_timeout,
00919                             enabled);
00920 }
00921 
00922 static dbus_bool_t
00923 _dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
00924                                                DBusPendingCall *pending)
00925 {
00926   dbus_uint32_t reply_serial;
00927   DBusTimeout *timeout;
00928 
00929   HAVE_LOCK_CHECK (connection);
00930 
00931   reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00932 
00933   _dbus_assert (reply_serial != 0);
00934 
00935   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00936 
00937   if (timeout)
00938     {
00939       if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00940         return FALSE;
00941       
00942       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00943                                         reply_serial,
00944                                         pending))
00945         {
00946           _dbus_connection_remove_timeout_unlocked (connection, timeout);
00947 
00948           _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00949           HAVE_LOCK_CHECK (connection);
00950           return FALSE;
00951         }
00952       
00953       _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00954     }
00955   else
00956     {
00957       if (!_dbus_hash_table_insert_int (connection->pending_replies,
00958                                         reply_serial,
00959                                         pending))
00960         {
00961           HAVE_LOCK_CHECK (connection);
00962           return FALSE;
00963         }
00964     }
00965 
00966   _dbus_pending_call_ref_unlocked (pending);
00967 
00968   HAVE_LOCK_CHECK (connection);
00969   
00970   return TRUE;
00971 }
00972 
00973 static void
00974 free_pending_call_on_hash_removal (void *data)
00975 {
00976   DBusPendingCall *pending;
00977   DBusConnection  *connection;
00978   
00979   if (data == NULL)
00980     return;
00981 
00982   pending = data;
00983 
00984   connection = _dbus_pending_call_get_connection_unlocked (pending);
00985 
00986   HAVE_LOCK_CHECK (connection);
00987   
00988   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00989     {
00990       _dbus_connection_remove_timeout_unlocked (connection,
00991                                                 _dbus_pending_call_get_timeout_unlocked (pending));
00992       
00993       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00994     }
00995 
00996   /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
00997    * here, but the pending call finalizer could in principle call out to 
00998    * application code so we pretty much have to... some larger code reorg 
00999    * might be needed.
01000    */
01001   _dbus_connection_ref_unlocked (connection);
01002   _dbus_pending_call_unref_and_unlock (pending);
01003   CONNECTION_LOCK (connection);
01004   _dbus_connection_unref_unlocked (connection);
01005 }
01006 
01007 static void
01008 _dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
01009                                                DBusPendingCall *pending)
01010 {
01011   /* This ends up unlocking to call the pending call finalizer, which is unexpected to
01012    * say the least.
01013    */
01014   _dbus_hash_table_remove_int (connection->pending_replies,
01015                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01016 }
01017 
01018 static void
01019 _dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
01020                                                  DBusPendingCall *pending)
01021 {
01022   /* The idea here is to avoid finalizing the pending call
01023    * with the lock held, since there's a destroy notifier
01024    * in pending call that goes out to application code.
01025    *
01026    * There's an extra unlock inside the hash table
01027    * "free pending call" function FIXME...
01028    */
01029   _dbus_pending_call_ref_unlocked (pending);
01030   _dbus_hash_table_remove_int (connection->pending_replies,
01031                                _dbus_pending_call_get_reply_serial_unlocked (pending));
01032 
01033   if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01034       _dbus_connection_remove_timeout_unlocked (connection,
01035               _dbus_pending_call_get_timeout_unlocked (pending));
01036 
01037   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01038 
01039   _dbus_pending_call_unref_and_unlock (pending);
01040 }
01041 
01050 void
01051 _dbus_connection_remove_pending_call (DBusConnection  *connection,
01052                                       DBusPendingCall *pending)
01053 {
01054   CONNECTION_LOCK (connection);
01055   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01056 }
01057 
01067 static dbus_bool_t
01068 _dbus_connection_acquire_io_path (DBusConnection *connection,
01069                                   int             timeout_milliseconds)
01070 {
01071   dbus_bool_t we_acquired;
01072   
01073   HAVE_LOCK_CHECK (connection);
01074 
01075   /* We don't want the connection to vanish */
01076   _dbus_connection_ref_unlocked (connection);
01077 
01078   /* We will only touch io_path_acquired which is protected by our mutex */
01079   CONNECTION_UNLOCK (connection);
01080   
01081   _dbus_verbose ("locking io_path_mutex\n");
01082   _dbus_cmutex_lock (connection->io_path_mutex);
01083 
01084   _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01085                  connection->io_path_acquired, timeout_milliseconds);
01086 
01087   we_acquired = FALSE;
01088   
01089   if (connection->io_path_acquired)
01090     {
01091       if (timeout_milliseconds != -1)
01092         {
01093           _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01094                          timeout_milliseconds);
01095 
01096           if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01097                                            connection->io_path_mutex,
01098                                            timeout_milliseconds))
01099             {
01100               /* We timed out before anyone signaled. */
01101               /* (writing the loop to handle the !timedout case by
01102                * waiting longer if needed is a pain since dbus
01103                * wraps pthread_cond_timedwait to take a relative
01104                * time instead of absolute, something kind of stupid
01105                * on our part. for now it doesn't matter, we will just
01106                * end up back here eventually.)
01107                */
01108             }
01109         }
01110       else
01111         {
01112           while (connection->io_path_acquired)
01113             {
01114               _dbus_verbose ("waiting for IO path to be acquirable\n");
01115               _dbus_condvar_wait (connection->io_path_cond, 
01116                                   connection->io_path_mutex);
01117             }
01118         }
01119     }
01120   
01121   if (!connection->io_path_acquired)
01122     {
01123       we_acquired = TRUE;
01124       connection->io_path_acquired = TRUE;
01125     }
01126   
01127   _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01128                  connection->io_path_acquired, we_acquired);
01129 
01130   _dbus_verbose ("unlocking io_path_mutex\n");
01131   _dbus_cmutex_unlock (connection->io_path_mutex);
01132 
01133   CONNECTION_LOCK (connection);
01134   
01135   HAVE_LOCK_CHECK (connection);
01136 
01137   _dbus_connection_unref_unlocked (connection);
01138   
01139   return we_acquired;
01140 }
01141 
01149 static void
01150 _dbus_connection_release_io_path (DBusConnection *connection)
01151 {
01152   HAVE_LOCK_CHECK (connection);
01153   
01154   _dbus_verbose ("locking io_path_mutex\n");
01155   _dbus_cmutex_lock (connection->io_path_mutex);
01156   
01157   _dbus_assert (connection->io_path_acquired);
01158 
01159   _dbus_verbose ("start connection->io_path_acquired = %d\n",
01160                  connection->io_path_acquired);
01161   
01162   connection->io_path_acquired = FALSE;
01163   _dbus_condvar_wake_one (connection->io_path_cond);
01164 
01165   _dbus_verbose ("unlocking io_path_mutex\n");
01166   _dbus_cmutex_unlock (connection->io_path_mutex);
01167 }
01168 
01204 void
01205 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01206                                         DBusPendingCall *pending,
01207                                         unsigned int    flags,
01208                                         int             timeout_milliseconds)
01209 {
01210   _dbus_verbose ("start\n");
01211   
01212   HAVE_LOCK_CHECK (connection);
01213   
01214   if (connection->n_outgoing == 0)
01215     flags &= ~DBUS_ITERATION_DO_WRITING;
01216 
01217   if (_dbus_connection_acquire_io_path (connection,
01218                                         (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01219     {
01220       HAVE_LOCK_CHECK (connection);
01221       
01222       if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01223         {
01224           _dbus_verbose ("pending call completed while acquiring I/O path");
01225         }
01226       else if ( (pending != NULL) &&
01227                 _dbus_connection_peek_for_reply_unlocked (connection,
01228                                                           _dbus_pending_call_get_reply_serial_unlocked (pending)))
01229         {
01230           _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01231         }
01232       else
01233         {
01234           _dbus_transport_do_iteration (connection->transport,
01235                                         flags, timeout_milliseconds);
01236         }
01237 
01238       _dbus_connection_release_io_path (connection);
01239     }
01240 
01241   HAVE_LOCK_CHECK (connection);
01242 
01243   _dbus_verbose ("end\n");
01244 }
01245 
01255 DBusConnection*
01256 _dbus_connection_new_for_transport (DBusTransport *transport)
01257 {
01258   DBusConnection *connection;
01259   DBusWatchList *watch_list;
01260   DBusTimeoutList *timeout_list;
01261   DBusHashTable *pending_replies;
01262   DBusList *disconnect_link;
01263   DBusMessage *disconnect_message;
01264   DBusCounter *outgoing_counter;
01265   DBusObjectTree *objects;
01266   
01267   watch_list = NULL;
01268   connection = NULL;
01269   pending_replies = NULL;
01270   timeout_list = NULL;
01271   disconnect_link = NULL;
01272   disconnect_message = NULL;
01273   outgoing_counter = NULL;
01274   objects = NULL;
01275   
01276   watch_list = _dbus_watch_list_new ();
01277   if (watch_list == NULL)
01278     goto error;
01279 
01280   timeout_list = _dbus_timeout_list_new ();
01281   if (timeout_list == NULL)
01282     goto error;  
01283 
01284   pending_replies =
01285     _dbus_hash_table_new (DBUS_HASH_INT,
01286                           NULL,
01287                           (DBusFreeFunction)free_pending_call_on_hash_removal);
01288   if (pending_replies == NULL)
01289     goto error;
01290   
01291   connection = dbus_new0 (DBusConnection, 1);
01292   if (connection == NULL)
01293     goto error;
01294 
01295   _dbus_rmutex_new_at_location (&connection->mutex);
01296   if (connection->mutex == NULL)
01297     goto error;
01298 
01299   _dbus_cmutex_new_at_location (&connection->io_path_mutex);
01300   if (connection->io_path_mutex == NULL)
01301     goto error;
01302 
01303   _dbus_cmutex_new_at_location (&connection->dispatch_mutex);
01304   if (connection->dispatch_mutex == NULL)
01305     goto error;
01306   
01307   _dbus_condvar_new_at_location (&connection->dispatch_cond);
01308   if (connection->dispatch_cond == NULL)
01309     goto error;
01310   
01311   _dbus_condvar_new_at_location (&connection->io_path_cond);
01312   if (connection->io_path_cond == NULL)
01313     goto error;
01314 
01315   _dbus_rmutex_new_at_location (&connection->slot_mutex);
01316   if (connection->slot_mutex == NULL)
01317     goto error;
01318 
01319   disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01320                                                 DBUS_INTERFACE_LOCAL,
01321                                                 "Disconnected");
01322   
01323   if (disconnect_message == NULL)
01324     goto error;
01325 
01326   disconnect_link = _dbus_list_alloc_link (disconnect_message);
01327   if (disconnect_link == NULL)
01328     goto error;
01329 
01330   outgoing_counter = _dbus_counter_new ();
01331   if (outgoing_counter == NULL)
01332     goto error;
01333 
01334   objects = _dbus_object_tree_new (connection);
01335   if (objects == NULL)
01336     goto error;
01337   
01338   if (_dbus_modify_sigpipe)
01339     _dbus_disable_sigpipe ();
01340 
01341   /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
01342   _dbus_atomic_inc (&connection->refcount);
01343   connection->transport = transport;
01344   connection->watches = watch_list;
01345   connection->timeouts = timeout_list;
01346   connection->pending_replies = pending_replies;
01347   connection->outgoing_counter = outgoing_counter;
01348   connection->filter_list = NULL;
01349   connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
01350   connection->objects = objects;
01351   connection->exit_on_disconnect = FALSE;
01352   connection->shareable = FALSE;
01353   connection->route_peer_messages = FALSE;
01354   connection->disconnected_message_arrived = FALSE;
01355   connection->disconnected_message_processed = FALSE;
01356   
01357 #ifndef DBUS_DISABLE_CHECKS
01358   connection->generation = _dbus_current_generation;
01359 #endif
01360   
01361   _dbus_data_slot_list_init (&connection->slot_list);
01362 
01363   connection->client_serial = 1;
01364 
01365   connection->disconnect_message_link = disconnect_link;
01366 
01367   CONNECTION_LOCK (connection);
01368   
01369   if (!_dbus_transport_set_connection (transport, connection))
01370     {
01371       CONNECTION_UNLOCK (connection);
01372 
01373       goto error;
01374     }
01375 
01376   _dbus_transport_ref (transport);
01377 
01378   CONNECTION_UNLOCK (connection);
01379 
01380   _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
01381   return connection;
01382   
01383  error:
01384   if (disconnect_message != NULL)
01385     dbus_message_unref (disconnect_message);
01386   
01387   if (disconnect_link != NULL)
01388     _dbus_list_free_link (disconnect_link);
01389   
01390   if (connection != NULL)
01391     {
01392       _dbus_condvar_free_at_location (&connection->io_path_cond);
01393       _dbus_condvar_free_at_location (&connection->dispatch_cond);
01394       _dbus_rmutex_free_at_location (&connection->mutex);
01395       _dbus_cmutex_free_at_location (&connection->io_path_mutex);
01396       _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
01397       _dbus_rmutex_free_at_location (&connection->slot_mutex);
01398       dbus_free (connection);
01399     }
01400   if (pending_replies)
01401     _dbus_hash_table_unref (pending_replies);
01402   
01403   if (watch_list)
01404     _dbus_watch_list_free (watch_list);
01405 
01406   if (timeout_list)
01407     _dbus_timeout_list_free (timeout_list);
01408 
01409   if (outgoing_counter)
01410     _dbus_counter_unref (outgoing_counter);
01411 
01412   if (objects)
01413     _dbus_object_tree_unref (objects);
01414   
01415   return NULL;
01416 }
01417 
01425 DBusConnection *
01426 _dbus_connection_ref_unlocked (DBusConnection *connection)
01427 {
01428   dbus_int32_t old_refcount;
01429 
01430   _dbus_assert (connection != NULL);
01431   _dbus_assert (connection->generation == _dbus_current_generation);
01432 
01433   HAVE_LOCK_CHECK (connection);
01434 
01435   old_refcount = _dbus_atomic_inc (&connection->refcount);
01436   _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
01437       "ref_unlocked");
01438 
01439   return connection;
01440 }
01441 
01448 void
01449 _dbus_connection_unref_unlocked (DBusConnection *connection)
01450 {
01451   dbus_int32_t old_refcount;
01452 
01453   HAVE_LOCK_CHECK (connection);
01454 
01455   _dbus_assert (connection != NULL);
01456 
01457   old_refcount = _dbus_atomic_dec (&connection->refcount);
01458 
01459   _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
01460       "unref_unlocked");
01461 
01462   if (old_refcount == 1)
01463     _dbus_connection_last_unref (connection);
01464 }
01465 
01466 static dbus_uint32_t
01467 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01468 {
01469   dbus_uint32_t serial;
01470 
01471   serial = connection->client_serial++;
01472 
01473   if (connection->client_serial == 0)
01474     connection->client_serial = 1;
01475 
01476   return serial;
01477 }
01478 
01492 dbus_bool_t
01493 _dbus_connection_handle_watch (DBusWatch                   *watch,
01494                                unsigned int                 condition,
01495                                void                        *data)
01496 {
01497   DBusConnection *connection;
01498   dbus_bool_t retval;
01499   DBusDispatchStatus status;
01500 
01501   connection = data;
01502 
01503   _dbus_verbose ("start\n");
01504   
01505   CONNECTION_LOCK (connection);
01506 
01507   if (!_dbus_connection_acquire_io_path (connection, 1))
01508     {
01509       /* another thread is handling the message */
01510       CONNECTION_UNLOCK (connection);
01511       return TRUE;
01512     }
01513 
01514   HAVE_LOCK_CHECK (connection);
01515   retval = _dbus_transport_handle_watch (connection->transport,
01516                                          watch, condition);
01517 
01518   _dbus_connection_release_io_path (connection);
01519 
01520   HAVE_LOCK_CHECK (connection);
01521 
01522   _dbus_verbose ("middle\n");
01523   
01524   status = _dbus_connection_get_dispatch_status_unlocked (connection);
01525 
01526   /* this calls out to user code */
01527   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01528 
01529   _dbus_verbose ("end\n");
01530   
01531   return retval;
01532 }
01533 
01534 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01535 static DBusHashTable *shared_connections = NULL;
01536 static DBusList *shared_connections_no_guid = NULL;
01537 
01538 static void
01539 close_connection_on_shutdown (DBusConnection *connection)
01540 {
01541   DBusMessage *message;
01542 
01543   dbus_connection_ref (connection);
01544   _dbus_connection_close_possibly_shared (connection);
01545 
01546   /* Churn through to the Disconnected message */
01547   while ((message = dbus_connection_pop_message (connection)))
01548     {
01549       dbus_message_unref (message);
01550     }
01551   dbus_connection_unref (connection);
01552 }
01553 
01554 static void
01555 shared_connections_shutdown (void *data)
01556 {
01557   int n_entries;
01558   
01559   _DBUS_LOCK (shared_connections);
01560   
01561   /* This is a little bit unpleasant... better ideas? */
01562   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01563     {
01564       DBusConnection *connection;
01565       DBusHashIter iter;
01566       
01567       _dbus_hash_iter_init (shared_connections, &iter);
01568       _dbus_hash_iter_next (&iter);
01569        
01570       connection = _dbus_hash_iter_get_value (&iter);
01571 
01572       _DBUS_UNLOCK (shared_connections);
01573       close_connection_on_shutdown (connection);
01574       _DBUS_LOCK (shared_connections);
01575 
01576       /* The connection should now be dead and not in our hash ... */
01577       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01578     }
01579 
01580   _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01581   
01582   _dbus_hash_table_unref (shared_connections);
01583   shared_connections = NULL;
01584 
01585   if (shared_connections_no_guid != NULL)
01586     {
01587       DBusConnection *connection;
01588       connection = _dbus_list_pop_first (&shared_connections_no_guid);
01589       while (connection != NULL)
01590         {
01591           _DBUS_UNLOCK (shared_connections);
01592           close_connection_on_shutdown (connection);
01593           _DBUS_LOCK (shared_connections);
01594           connection = _dbus_list_pop_first (&shared_connections_no_guid);
01595         }
01596     }
01597 
01598   shared_connections_no_guid = NULL;
01599   
01600   _DBUS_UNLOCK (shared_connections);
01601 }
01602 
01603 static dbus_bool_t
01604 connection_lookup_shared (DBusAddressEntry  *entry,
01605                           DBusConnection   **result)
01606 {
01607   _dbus_verbose ("checking for existing connection\n");
01608   
01609   *result = NULL;
01610   
01611   _DBUS_LOCK (shared_connections);
01612 
01613   if (shared_connections == NULL)
01614     {
01615       _dbus_verbose ("creating shared_connections hash table\n");
01616       
01617       shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01618                                                  dbus_free,
01619                                                  NULL);
01620       if (shared_connections == NULL)
01621         {
01622           _DBUS_UNLOCK (shared_connections);
01623           return FALSE;
01624         }
01625 
01626       if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01627         {
01628           _dbus_hash_table_unref (shared_connections);
01629           shared_connections = NULL;
01630           _DBUS_UNLOCK (shared_connections);
01631           return FALSE;
01632         }
01633 
01634       _dbus_verbose ("  successfully created shared_connections\n");
01635       
01636       _DBUS_UNLOCK (shared_connections);
01637       return TRUE; /* no point looking up in the hash we just made */
01638     }
01639   else
01640     {
01641       const char *guid;
01642 
01643       guid = dbus_address_entry_get_value (entry, "guid");
01644       
01645       if (guid != NULL)
01646         {
01647           DBusConnection *connection;
01648           
01649           connection = _dbus_hash_table_lookup_string (shared_connections,
01650                                                        guid);
01651 
01652           if (connection)
01653             {
01654               /* The DBusConnection can't be finalized without taking
01655                * the shared_connections lock to remove it from the
01656                * hash.  So it's safe to ref the connection here.
01657                * However, it may be disconnected if the Disconnected
01658                * message hasn't been processed yet, in which case we
01659                * want to pretend it isn't in the hash and avoid
01660                * returning it.
01661                *
01662                * The idea is to avoid ever returning a disconnected connection
01663                * from dbus_connection_open(). We could just synchronously
01664                * drop our shared ref to the connection on connection disconnect,
01665                * and then assert here that the connection is connected, but
01666                * that causes reentrancy headaches.
01667                */
01668               CONNECTION_LOCK (connection);
01669               if (_dbus_connection_get_is_connected_unlocked (connection))
01670                 {
01671                   _dbus_connection_ref_unlocked (connection);
01672                   *result = connection;
01673                   _dbus_verbose ("looked up existing connection to server guid %s\n",
01674                                  guid);
01675                 }
01676               else
01677                 {
01678                   _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01679                                  guid);
01680                 }
01681               CONNECTION_UNLOCK (connection);
01682             }
01683         }
01684       
01685       _DBUS_UNLOCK (shared_connections);
01686       return TRUE;
01687     }
01688 }
01689 
01690 static dbus_bool_t
01691 connection_record_shared_unlocked (DBusConnection *connection,
01692                                    const char     *guid)
01693 {
01694   char *guid_key;
01695   char *guid_in_connection;
01696 
01697   HAVE_LOCK_CHECK (connection);
01698   _dbus_assert (connection->server_guid == NULL);
01699   _dbus_assert (connection->shareable);
01700 
01701   /* get a hard ref on this connection, even if
01702    * we won't in fact store it in the hash, we still
01703    * need to hold a ref on it until it's disconnected.
01704    */
01705   _dbus_connection_ref_unlocked (connection);
01706 
01707   if (guid == NULL)
01708     {
01709       _DBUS_LOCK (shared_connections);
01710 
01711       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01712         {
01713           _DBUS_UNLOCK (shared_connections);
01714           return FALSE;
01715         }
01716 
01717       _DBUS_UNLOCK (shared_connections);
01718       return TRUE; /* don't store in the hash */
01719     }
01720   
01721   /* A separate copy of the key is required in the hash table, because
01722    * we don't have a lock on the connection when we are doing a hash
01723    * lookup.
01724    */
01725   
01726   guid_key = _dbus_strdup (guid);
01727   if (guid_key == NULL)
01728     return FALSE;
01729 
01730   guid_in_connection = _dbus_strdup (guid);
01731   if (guid_in_connection == NULL)
01732     {
01733       dbus_free (guid_key);
01734       return FALSE;
01735     }
01736   
01737   _DBUS_LOCK (shared_connections);
01738   _dbus_assert (shared_connections != NULL);
01739   
01740   if (!_dbus_hash_table_insert_string (shared_connections,
01741                                        guid_key, connection))
01742     {
01743       dbus_free (guid_key);
01744       dbus_free (guid_in_connection);
01745       _DBUS_UNLOCK (shared_connections);
01746       return FALSE;
01747     }
01748 
01749   connection->server_guid = guid_in_connection;
01750 
01751   _dbus_verbose ("stored connection to %s to be shared\n",
01752                  connection->server_guid);
01753   
01754   _DBUS_UNLOCK (shared_connections);
01755 
01756   _dbus_assert (connection->server_guid != NULL);
01757   
01758   return TRUE;
01759 }
01760 
01761 static void
01762 connection_forget_shared_unlocked (DBusConnection *connection)
01763 {
01764   HAVE_LOCK_CHECK (connection);
01765 
01766   if (!connection->shareable)
01767     return;
01768   
01769   _DBUS_LOCK (shared_connections);
01770       
01771   if (connection->server_guid != NULL)
01772     {
01773       _dbus_verbose ("dropping connection to %s out of the shared table\n",
01774                      connection->server_guid);
01775       
01776       if (!_dbus_hash_table_remove_string (shared_connections,
01777                                            connection->server_guid))
01778         _dbus_assert_not_reached ("connection was not in the shared table");
01779       
01780       dbus_free (connection->server_guid);
01781       connection->server_guid = NULL;
01782     }
01783   else
01784     {
01785       _dbus_list_remove (&shared_connections_no_guid, connection);
01786     }
01787 
01788   _DBUS_UNLOCK (shared_connections);
01789   
01790   /* remove our reference held on all shareable connections */
01791   _dbus_connection_unref_unlocked (connection);
01792 }
01793 
01794 static DBusConnection*
01795 connection_try_from_address_entry (DBusAddressEntry *entry,
01796                                    DBusError        *error)
01797 {
01798   DBusTransport *transport;
01799   DBusConnection *connection;
01800 
01801   transport = _dbus_transport_open (entry, error);
01802 
01803   if (transport == NULL)
01804     {
01805       _DBUS_ASSERT_ERROR_IS_SET (error);
01806       return NULL;
01807     }
01808 
01809   connection = _dbus_connection_new_for_transport (transport);
01810 
01811   _dbus_transport_unref (transport);
01812   
01813   if (connection == NULL)
01814     {
01815       _DBUS_SET_OOM (error);
01816       return NULL;
01817     }
01818 
01819 #ifndef DBUS_DISABLE_CHECKS
01820   _dbus_assert (!connection->have_connection_lock);
01821 #endif
01822   return connection;
01823 }
01824 
01825 /*
01826  * If the shared parameter is true, then any existing connection will
01827  * be used (and if a new connection is created, it will be available
01828  * for use by others). If the shared parameter is false, a new
01829  * connection will always be created, and the new connection will
01830  * never be returned to other callers.
01831  *
01832  * @param address the address
01833  * @param shared whether the connection is shared or private
01834  * @param error error return
01835  * @returns the connection or #NULL on error
01836  */
01837 static DBusConnection*
01838 _dbus_connection_open_internal (const char     *address,
01839                                 dbus_bool_t     shared,
01840                                 DBusError      *error)
01841 {
01842   DBusConnection *connection;
01843   DBusAddressEntry **entries;
01844   DBusError tmp_error = DBUS_ERROR_INIT;
01845   DBusError first_error = DBUS_ERROR_INIT;
01846   int len, i;
01847 
01848   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01849 
01850   _dbus_verbose ("opening %s connection to: %s\n",
01851                  shared ? "shared" : "private", address);
01852   
01853   if (!dbus_parse_address (address, &entries, &len, error))
01854     return NULL;
01855 
01856   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01857   
01858   connection = NULL;
01859 
01860   for (i = 0; i < len; i++)
01861     {
01862       if (shared)
01863         {
01864           if (!connection_lookup_shared (entries[i], &connection))
01865             _DBUS_SET_OOM (&tmp_error);
01866         }
01867 
01868       if (connection == NULL)
01869         {
01870           connection = connection_try_from_address_entry (entries[i],
01871                                                           &tmp_error);
01872 
01873           if (connection != NULL && shared)
01874             {
01875               const char *guid;
01876                   
01877               connection->shareable = TRUE;
01878                   
01879               /* guid may be NULL */
01880               guid = dbus_address_entry_get_value (entries[i], "guid");
01881                   
01882               CONNECTION_LOCK (connection);
01883           
01884               if (!connection_record_shared_unlocked (connection, guid))
01885                 {
01886                   _DBUS_SET_OOM (&tmp_error);
01887                   _dbus_connection_close_possibly_shared_and_unlock (connection);
01888                   dbus_connection_unref (connection);
01889                   connection = NULL;
01890                 }
01891               else
01892                 CONNECTION_UNLOCK (connection);
01893             }
01894         }
01895       
01896       if (connection)
01897         break;
01898 
01899       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01900       
01901       if (i == 0)
01902         dbus_move_error (&tmp_error, &first_error);
01903       else
01904         dbus_error_free (&tmp_error);
01905     }
01906   
01907   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01908   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01909   
01910   if (connection == NULL)
01911     {
01912       _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01913       dbus_move_error (&first_error, error);
01914     }
01915   else
01916     dbus_error_free (&first_error);
01917   
01918   dbus_address_entries_free (entries);
01919   return connection;
01920 }
01921 
01930 void
01931 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01932 {
01933   _dbus_assert (connection != NULL);
01934   _dbus_assert (connection->generation == _dbus_current_generation);
01935 
01936   CONNECTION_LOCK (connection);
01937   _dbus_connection_close_possibly_shared_and_unlock (connection);
01938 }
01939 
01940 static DBusPreallocatedSend*
01941 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01942 {
01943   DBusPreallocatedSend *preallocated;
01944 
01945   HAVE_LOCK_CHECK (connection);
01946   
01947   _dbus_assert (connection != NULL);
01948   
01949   preallocated = dbus_new (DBusPreallocatedSend, 1);
01950   if (preallocated == NULL)
01951     return NULL;
01952 
01953   preallocated->queue_link = _dbus_list_alloc_link (NULL);
01954   if (preallocated->queue_link == NULL)
01955     goto failed_0;
01956 
01957   preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01958   if (preallocated->counter_link == NULL)
01959     goto failed_1;
01960 
01961   _dbus_counter_ref (preallocated->counter_link->data);
01962 
01963   preallocated->connection = connection;
01964   
01965   return preallocated;
01966   
01967  failed_1:
01968   _dbus_list_free_link (preallocated->queue_link);
01969  failed_0:
01970   dbus_free (preallocated);
01971   
01972   return NULL;
01973 }
01974 
01975 /* Called with lock held, does not update dispatch status */
01976 static void
01977 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
01978                                                        DBusPreallocatedSend *preallocated,
01979                                                        DBusMessage          *message,
01980                                                        dbus_uint32_t        *client_serial)
01981 {
01982   dbus_uint32_t serial;
01983 
01984   preallocated->queue_link->data = message;
01985   _dbus_list_prepend_link (&connection->outgoing_messages,
01986                            preallocated->queue_link);
01987 
01988   /* It's OK that we'll never call the notify function, because for the
01989    * outgoing limit, there isn't one */
01990   _dbus_message_add_counter_link (message,
01991                                   preallocated->counter_link);
01992 
01993   dbus_free (preallocated);
01994   preallocated = NULL;
01995   
01996   dbus_message_ref (message);
01997   
01998   connection->n_outgoing += 1;
01999 
02000   _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02001                  message,
02002                  dbus_message_type_to_string (dbus_message_get_type (message)),
02003                  dbus_message_get_path (message) ?
02004                  dbus_message_get_path (message) :
02005                  "no path",
02006                  dbus_message_get_interface (message) ?
02007                  dbus_message_get_interface (message) :
02008                  "no interface",
02009                  dbus_message_get_member (message) ?
02010                  dbus_message_get_member (message) :
02011                  "no member",
02012                  dbus_message_get_signature (message),
02013                  dbus_message_get_destination (message) ?
02014                  dbus_message_get_destination (message) :
02015                  "null",
02016                  connection,
02017                  connection->n_outgoing);
02018 
02019   if (dbus_message_get_serial (message) == 0)
02020     {
02021       serial = _dbus_connection_get_next_client_serial (connection);
02022       dbus_message_set_serial (message, serial);
02023       if (client_serial)
02024         *client_serial = serial;
02025     }
02026   else
02027     {
02028       if (client_serial)
02029         *client_serial = dbus_message_get_serial (message);
02030     }
02031 
02032   _dbus_verbose ("Message %p serial is %u\n",
02033                  message, dbus_message_get_serial (message));
02034   
02035   dbus_message_lock (message);
02036 
02037   /* Now we need to run an iteration to hopefully just write the messages
02038    * out immediately, and otherwise get them queued up
02039    */
02040   _dbus_connection_do_iteration_unlocked (connection,
02041                                           NULL,
02042                                           DBUS_ITERATION_DO_WRITING,
02043                                           -1);
02044 
02045   /* If stuff is still queued up, be sure we wake up the main loop */
02046   if (connection->n_outgoing > 0)
02047     _dbus_connection_wakeup_mainloop (connection);
02048 }
02049 
02050 static void
02051 _dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
02052                                                DBusPreallocatedSend *preallocated,
02053                                                DBusMessage          *message,
02054                                                dbus_uint32_t        *client_serial)
02055 {
02056   DBusDispatchStatus status;
02057 
02058   HAVE_LOCK_CHECK (connection);
02059   
02060   _dbus_connection_send_preallocated_unlocked_no_update (connection,
02061                                                          preallocated,
02062                                                          message, client_serial);
02063 
02064   _dbus_verbose ("middle\n");
02065   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02066 
02067   /* this calls out to user code */
02068   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02069 }
02070 
02080 dbus_bool_t
02081 _dbus_connection_send_and_unlock (DBusConnection *connection,
02082                                   DBusMessage    *message,
02083                                   dbus_uint32_t  *client_serial)
02084 {
02085   DBusPreallocatedSend *preallocated;
02086 
02087   _dbus_assert (connection != NULL);
02088   _dbus_assert (message != NULL);
02089   
02090   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02091   if (preallocated == NULL)
02092     {
02093       CONNECTION_UNLOCK (connection);
02094       return FALSE;
02095     }
02096 
02097   _dbus_connection_send_preallocated_and_unlock (connection,
02098                                                  preallocated,
02099                                                  message,
02100                                                  client_serial);
02101   return TRUE;
02102 }
02103 
02128 void
02129 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02130 {
02131   dbus_int32_t refcount;
02132 
02133   CONNECTION_LOCK (connection);
02134 
02135   refcount = _dbus_atomic_get (&connection->refcount);
02136   /* The caller should have at least one ref */
02137   _dbus_assert (refcount >= 1);
02138 
02139   if (refcount == 1)
02140     _dbus_connection_close_possibly_shared_and_unlock (connection);
02141   else
02142     CONNECTION_UNLOCK (connection);
02143 }
02144 
02145 
02155 static void
02156 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02157 {
02158   if (timeout_milliseconds == -1)
02159     _dbus_sleep_milliseconds (1000);
02160   else if (timeout_milliseconds < 100)
02161     ; /* just busy loop */
02162   else if (timeout_milliseconds <= 1000)
02163     _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02164   else
02165     _dbus_sleep_milliseconds (1000);
02166 }
02167 
02168 static DBusMessage *
02169 generate_local_error_message (dbus_uint32_t serial, 
02170                               char *error_name, 
02171                               char *error_msg)
02172 {
02173   DBusMessage *message;
02174   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02175   if (!message)
02176     goto out;
02177 
02178   if (!dbus_message_set_error_name (message, error_name))
02179     {
02180       dbus_message_unref (message);
02181       message = NULL;
02182       goto out; 
02183     }
02184 
02185   dbus_message_set_no_reply (message, TRUE); 
02186 
02187   if (!dbus_message_set_reply_serial (message,
02188                                       serial))
02189     {
02190       dbus_message_unref (message);
02191       message = NULL;
02192       goto out;
02193     }
02194 
02195   if (error_msg != NULL)
02196     {
02197       DBusMessageIter iter;
02198 
02199       dbus_message_iter_init_append (message, &iter);
02200       if (!dbus_message_iter_append_basic (&iter,
02201                                            DBUS_TYPE_STRING,
02202                                            &error_msg))
02203         {
02204           dbus_message_unref (message);
02205           message = NULL;
02206           goto out;
02207         }
02208     }
02209 
02210  out:
02211   return message;
02212 }
02213 
02214 /*
02215  * Peek the incoming queue to see if we got reply for a specific serial
02216  */
02217 static dbus_bool_t
02218 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02219                                           dbus_uint32_t   client_serial)
02220 {
02221   DBusList *link;
02222   HAVE_LOCK_CHECK (connection);
02223 
02224   link = _dbus_list_get_first_link (&connection->incoming_messages);
02225 
02226   while (link != NULL)
02227     {
02228       DBusMessage *reply = link->data;
02229 
02230       if (dbus_message_get_reply_serial (reply) == client_serial)
02231         {
02232           _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02233           return TRUE;
02234         }
02235       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02236     }
02237 
02238   return FALSE;
02239 }
02240 
02241 /* This is slightly strange since we can pop a message here without
02242  * the dispatch lock.
02243  */
02244 static DBusMessage*
02245 check_for_reply_unlocked (DBusConnection *connection,
02246                           dbus_uint32_t   client_serial)
02247 {
02248   DBusList *link;
02249 
02250   HAVE_LOCK_CHECK (connection);
02251   
02252   link = _dbus_list_get_first_link (&connection->incoming_messages);
02253 
02254   while (link != NULL)
02255     {
02256       DBusMessage *reply = link->data;
02257 
02258       if (dbus_message_get_reply_serial (reply) == client_serial)
02259         {
02260           _dbus_list_remove_link (&connection->incoming_messages, link);
02261           connection->n_incoming  -= 1;
02262           return reply;
02263         }
02264       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02265     }
02266 
02267   return NULL;
02268 }
02269 
02270 static void
02271 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02272 {
02273    /* We can't iterate over the hash in the normal way since we'll be
02274     * dropping the lock for each item. So we restart the
02275     * iter each time as we drain the hash table.
02276     */
02277    
02278    while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02279     {
02280       DBusPendingCall *pending;
02281       DBusHashIter iter;
02282       
02283       _dbus_hash_iter_init (connection->pending_replies, &iter);
02284       _dbus_hash_iter_next (&iter);
02285        
02286       pending = _dbus_hash_iter_get_value (&iter);
02287       _dbus_pending_call_ref_unlocked (pending);
02288        
02289       _dbus_pending_call_queue_timeout_error_unlocked (pending, 
02290                                                        connection);
02291 
02292       if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02293           _dbus_connection_remove_timeout_unlocked (connection,
02294                                                     _dbus_pending_call_get_timeout_unlocked (pending));
02295       _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
02296       _dbus_hash_iter_remove_entry (&iter);
02297 
02298       _dbus_pending_call_unref_and_unlock (pending);
02299       CONNECTION_LOCK (connection);
02300     }
02301   HAVE_LOCK_CHECK (connection);
02302 }
02303 
02304 static void
02305 complete_pending_call_and_unlock (DBusConnection  *connection,
02306                                   DBusPendingCall *pending,
02307                                   DBusMessage     *message)
02308 {
02309   _dbus_pending_call_set_reply_unlocked (pending, message);
02310   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
02311   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02312  
02313   /* Must be called unlocked since it invokes app callback */
02314   _dbus_pending_call_complete (pending);
02315   dbus_pending_call_unref (pending);
02316 }
02317 
02318 static dbus_bool_t
02319 check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
02320                                               DBusPendingCall *pending)
02321 {
02322   DBusMessage *reply;
02323   DBusDispatchStatus status;
02324 
02325   reply = check_for_reply_unlocked (connection, 
02326                                     _dbus_pending_call_get_reply_serial_unlocked (pending));
02327   if (reply != NULL)
02328     {
02329       _dbus_verbose ("checked for reply\n");
02330 
02331       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02332 
02333       complete_pending_call_and_unlock (connection, pending, reply);
02334       dbus_message_unref (reply);
02335 
02336       CONNECTION_LOCK (connection);
02337       status = _dbus_connection_get_dispatch_status_unlocked (connection);
02338       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02339       dbus_pending_call_unref (pending);
02340 
02341       return TRUE;
02342     }
02343 
02344   return FALSE;
02345 }
02346 
02361 void
02362 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02363 {
02364   long start_tv_sec, start_tv_usec;
02365   long tv_sec, tv_usec;
02366   DBusDispatchStatus status;
02367   DBusConnection *connection;
02368   dbus_uint32_t client_serial;
02369   DBusTimeout *timeout;
02370   int timeout_milliseconds, elapsed_milliseconds;
02371 
02372   _dbus_assert (pending != NULL);
02373 
02374   if (dbus_pending_call_get_completed (pending))
02375     return;
02376 
02377   dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
02378 
02379   connection = _dbus_pending_call_get_connection_and_lock (pending);
02380   
02381   /* Flush message queue - note, can affect dispatch status */
02382   _dbus_connection_flush_unlocked (connection);
02383 
02384   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02385 
02386   /* note that timeout_milliseconds is limited to a smallish value
02387    * in _dbus_pending_call_new() so overflows aren't possible
02388    * below
02389    */
02390   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02391   _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
02392   if (timeout)
02393     {
02394       timeout_milliseconds = dbus_timeout_get_interval (timeout);
02395 
02396       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02397                      timeout_milliseconds,
02398                      client_serial,
02399                      start_tv_sec, start_tv_usec);
02400     }
02401   else
02402     {
02403       timeout_milliseconds = -1;
02404 
02405       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02406     }
02407 
02408   /* check to see if we already got the data off the socket */
02409   /* from another blocked pending call */
02410   if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02411     return;
02412 
02413   /* Now we wait... */
02414   /* always block at least once as we know we don't have the reply yet */
02415   _dbus_connection_do_iteration_unlocked (connection,
02416                                           pending,
02417                                           DBUS_ITERATION_DO_READING |
02418                                           DBUS_ITERATION_BLOCK,
02419                                           timeout_milliseconds);
02420 
02421  recheck_status:
02422 
02423   _dbus_verbose ("top of recheck\n");
02424   
02425   HAVE_LOCK_CHECK (connection);
02426   
02427   /* queue messages and get status */
02428 
02429   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02430 
02431   /* the get_completed() is in case a dispatch() while we were blocking
02432    * got the reply instead of us.
02433    */
02434   if (_dbus_pending_call_get_completed_unlocked (pending))
02435     {
02436       _dbus_verbose ("Pending call completed by dispatch\n");
02437       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02438       dbus_pending_call_unref (pending);
02439       return;
02440     }
02441   
02442   if (status == DBUS_DISPATCH_DATA_REMAINS)
02443     {
02444       if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02445         return;
02446     }
02447   
02448   _dbus_get_monotonic_time (&tv_sec, &tv_usec);
02449   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02450           (tv_usec - start_tv_usec) / 1000;
02451   
02452   if (!_dbus_connection_get_is_connected_unlocked (connection))
02453     {
02454       DBusMessage *error_msg;
02455 
02456       error_msg = generate_local_error_message (client_serial,
02457                                                 DBUS_ERROR_DISCONNECTED, 
02458                                                 "Connection was disconnected before a reply was received"); 
02459 
02460       /* on OOM error_msg is set to NULL */
02461       complete_pending_call_and_unlock (connection, pending, error_msg);
02462       dbus_pending_call_unref (pending);
02463       return;
02464     }
02465   else if (connection->disconnect_message_link == NULL)
02466     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02467   else if (timeout == NULL)
02468     {
02469        if (status == DBUS_DISPATCH_NEED_MEMORY)
02470         {
02471           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02472            * we may already have a reply in the buffer and just can't process
02473            * it.
02474            */
02475           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02476 
02477           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02478         }
02479       else
02480         {          
02481           /* block again, we don't have the reply buffered yet. */
02482           _dbus_connection_do_iteration_unlocked (connection,
02483                                                   pending,
02484                                                   DBUS_ITERATION_DO_READING |
02485                                                   DBUS_ITERATION_BLOCK,
02486                                                   timeout_milliseconds - elapsed_milliseconds);
02487         }
02488 
02489       goto recheck_status;
02490     }
02491   else if (tv_sec < start_tv_sec)
02492     _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02493   else if (elapsed_milliseconds < timeout_milliseconds)
02494     {
02495       _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02496       
02497       if (status == DBUS_DISPATCH_NEED_MEMORY)
02498         {
02499           /* Try sleeping a bit, as we aren't sure we need to block for reading,
02500            * we may already have a reply in the buffer and just can't process
02501            * it.
02502            */
02503           _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02504 
02505           _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02506         }
02507       else
02508         {          
02509           /* block again, we don't have the reply buffered yet. */
02510           _dbus_connection_do_iteration_unlocked (connection,
02511                                                   NULL,
02512                                                   DBUS_ITERATION_DO_READING |
02513                                                   DBUS_ITERATION_BLOCK,
02514                                                   timeout_milliseconds - elapsed_milliseconds);
02515         }
02516 
02517       goto recheck_status;
02518     }
02519 
02520   _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02521                  elapsed_milliseconds);
02522 
02523   _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02524   
02525   /* unlock and call user code */
02526   complete_pending_call_and_unlock (connection, pending, NULL);
02527 
02528   /* update user code on dispatch status */
02529   CONNECTION_LOCK (connection);
02530   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02531   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02532   dbus_pending_call_unref (pending);
02533 }
02534 
02571 DBusConnection*
02572 dbus_connection_open (const char     *address,
02573                       DBusError      *error)
02574 {
02575   DBusConnection *connection;
02576 
02577   _dbus_return_val_if_fail (address != NULL, NULL);
02578   _dbus_return_val_if_error_is_set (error, NULL);
02579 
02580   connection = _dbus_connection_open_internal (address,
02581                                                TRUE,
02582                                                error);
02583 
02584   return connection;
02585 }
02586 
02614 DBusConnection*
02615 dbus_connection_open_private (const char     *address,
02616                               DBusError      *error)
02617 {
02618   DBusConnection *connection;
02619 
02620   _dbus_return_val_if_fail (address != NULL, NULL);
02621   _dbus_return_val_if_error_is_set (error, NULL);
02622 
02623   connection = _dbus_connection_open_internal (address,
02624                                                FALSE,
02625                                                error);
02626 
02627   return connection;
02628 }
02629 
02636 DBusConnection *
02637 dbus_connection_ref (DBusConnection *connection)
02638 {
02639   dbus_int32_t old_refcount;
02640 
02641   _dbus_return_val_if_fail (connection != NULL, NULL);
02642   _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02643   old_refcount = _dbus_atomic_inc (&connection->refcount);
02644   _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
02645       "ref");
02646 
02647   return connection;
02648 }
02649 
02650 static void
02651 free_outgoing_message (void *element,
02652                        void *data)
02653 {
02654   DBusMessage *message = element;
02655   DBusConnection *connection = data;
02656 
02657   _dbus_message_remove_counter (message, connection->outgoing_counter);
02658   dbus_message_unref (message);
02659 }
02660 
02661 /* This is run without the mutex held, but after the last reference
02662  * to the connection has been dropped we should have no thread-related
02663  * problems
02664  */
02665 static void
02666 _dbus_connection_last_unref (DBusConnection *connection)
02667 {
02668   DBusList *link;
02669 
02670   _dbus_verbose ("Finalizing connection %p\n", connection);
02671 
02672   _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02673 
02674   /* You have to disconnect the connection before unref:ing it. Otherwise
02675    * you won't get the disconnected message.
02676    */
02677   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02678   _dbus_assert (connection->server_guid == NULL);
02679   
02680   /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
02681   _dbus_object_tree_free_all_unlocked (connection->objects);
02682   
02683   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02684   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02685   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02686   
02687   _dbus_watch_list_free (connection->watches);
02688   connection->watches = NULL;
02689   
02690   _dbus_timeout_list_free (connection->timeouts);
02691   connection->timeouts = NULL;
02692 
02693   _dbus_data_slot_list_free (&connection->slot_list);
02694   
02695   link = _dbus_list_get_first_link (&connection->filter_list);
02696   while (link != NULL)
02697     {
02698       DBusMessageFilter *filter = link->data;
02699       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02700 
02701       filter->function = NULL;
02702       _dbus_message_filter_unref (filter); /* calls app callback */
02703       link->data = NULL;
02704       
02705       link = next;
02706     }
02707   _dbus_list_clear (&connection->filter_list);
02708   
02709   /* ---- Done with stuff that invokes application callbacks */
02710 
02711   _dbus_object_tree_unref (connection->objects);  
02712 
02713   _dbus_hash_table_unref (connection->pending_replies);
02714   connection->pending_replies = NULL;
02715   
02716   _dbus_list_clear (&connection->filter_list);
02717   
02718   _dbus_list_foreach (&connection->outgoing_messages,
02719                       free_outgoing_message,
02720                       connection);
02721   _dbus_list_clear (&connection->outgoing_messages);
02722   
02723   _dbus_list_foreach (&connection->incoming_messages,
02724                       (DBusForeachFunction) dbus_message_unref,
02725                       NULL);
02726   _dbus_list_clear (&connection->incoming_messages);
02727 
02728   _dbus_counter_unref (connection->outgoing_counter);
02729 
02730   _dbus_transport_unref (connection->transport);
02731 
02732   if (connection->disconnect_message_link)
02733     {
02734       DBusMessage *message = connection->disconnect_message_link->data;
02735       dbus_message_unref (message);
02736       _dbus_list_free_link (connection->disconnect_message_link);
02737     }
02738 
02739   _dbus_condvar_free_at_location (&connection->dispatch_cond);
02740   _dbus_condvar_free_at_location (&connection->io_path_cond);
02741 
02742   _dbus_cmutex_free_at_location (&connection->io_path_mutex);
02743   _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
02744 
02745   _dbus_rmutex_free_at_location (&connection->slot_mutex);
02746 
02747   _dbus_rmutex_free_at_location (&connection->mutex);
02748   
02749   dbus_free (connection);
02750 }
02751 
02771 void
02772 dbus_connection_unref (DBusConnection *connection)
02773 {
02774   dbus_int32_t old_refcount;
02775 
02776   _dbus_return_if_fail (connection != NULL);
02777   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02778 
02779   old_refcount = _dbus_atomic_dec (&connection->refcount);
02780 
02781   _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
02782       "unref");
02783 
02784   if (old_refcount == 1)
02785     {
02786 #ifndef DBUS_DISABLE_CHECKS
02787       if (_dbus_transport_get_is_connected (connection->transport))
02788         {
02789           _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",
02790                                    connection->shareable ?
02791                                    "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
02792                                     "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02793           return;
02794         }
02795 #endif
02796       _dbus_connection_last_unref (connection);
02797     }
02798 }
02799 
02800 /*
02801  * Note that the transport can disconnect itself (other end drops us)
02802  * and in that case this function never runs. So this function must
02803  * not do anything more than disconnect the transport and update the
02804  * dispatch status.
02805  * 
02806  * If the transport self-disconnects, then we assume someone will
02807  * dispatch the connection to cause the dispatch status update.
02808  */
02809 static void
02810 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02811 {
02812   DBusDispatchStatus status;
02813 
02814   HAVE_LOCK_CHECK (connection);
02815   
02816   _dbus_verbose ("Disconnecting %p\n", connection);
02817 
02818   /* We need to ref because update_dispatch_status_and_unlock will unref
02819    * the connection if it was shared and libdbus was the only remaining
02820    * refcount holder.
02821    */
02822   _dbus_connection_ref_unlocked (connection);
02823   
02824   _dbus_transport_disconnect (connection->transport);
02825 
02826   /* This has the side effect of queuing the disconnect message link
02827    * (unless we don't have enough memory, possibly, so don't assert it).
02828    * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
02829    * should never again return the newly-disconnected connection.
02830    *
02831    * However, we only unref the shared connection and exit_on_disconnect when
02832    * the disconnect message reaches the head of the message queue,
02833    * NOT when it's first queued.
02834    */
02835   status = _dbus_connection_get_dispatch_status_unlocked (connection);
02836 
02837   /* This calls out to user code */
02838   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02839 
02840   /* Could also call out to user code */
02841   dbus_connection_unref (connection);
02842 }
02843 
02886 void
02887 dbus_connection_close (DBusConnection *connection)
02888 {
02889   _dbus_return_if_fail (connection != NULL);
02890   _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02891 
02892   CONNECTION_LOCK (connection);
02893 
02894 #ifndef DBUS_DISABLE_CHECKS
02895   if (connection->shareable)
02896     {
02897       CONNECTION_UNLOCK (connection);
02898 
02899       _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02900       return;
02901     }
02902 #endif
02903   
02904   _dbus_connection_close_possibly_shared_and_unlock (connection);
02905 }
02906 
02907 static dbus_bool_t
02908 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02909 {
02910   HAVE_LOCK_CHECK (connection);
02911   return _dbus_transport_get_is_connected (connection->transport);
02912 }
02913 
02927 dbus_bool_t
02928 dbus_connection_get_is_connected (DBusConnection *connection)
02929 {
02930   dbus_bool_t res;
02931 
02932   _dbus_return_val_if_fail (connection != NULL, FALSE);
02933   
02934   CONNECTION_LOCK (connection);
02935   res = _dbus_connection_get_is_connected_unlocked (connection);
02936   CONNECTION_UNLOCK (connection);
02937   
02938   return res;
02939 }
02940 
02949 dbus_bool_t
02950 dbus_connection_get_is_authenticated (DBusConnection *connection)
02951 {
02952   dbus_bool_t res;
02953 
02954   _dbus_return_val_if_fail (connection != NULL, FALSE);
02955   
02956   CONNECTION_LOCK (connection);
02957   res = _dbus_transport_get_is_authenticated (connection->transport);
02958   CONNECTION_UNLOCK (connection);
02959   
02960   return res;
02961 }
02962 
02983 dbus_bool_t
02984 dbus_connection_get_is_anonymous (DBusConnection *connection)
02985 {
02986   dbus_bool_t res;
02987 
02988   _dbus_return_val_if_fail (connection != NULL, FALSE);
02989   
02990   CONNECTION_LOCK (connection);
02991   res = _dbus_transport_get_is_anonymous (connection->transport);
02992   CONNECTION_UNLOCK (connection);
02993   
02994   return res;
02995 }
02996 
03028 char*
03029 dbus_connection_get_server_id (DBusConnection *connection)
03030 {
03031   char *id;
03032 
03033   _dbus_return_val_if_fail (connection != NULL, NULL);
03034 
03035   CONNECTION_LOCK (connection);
03036   id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03037   CONNECTION_UNLOCK (connection);
03038 
03039   return id;
03040 }
03041 
03059 dbus_bool_t
03060 dbus_connection_can_send_type(DBusConnection *connection,
03061                                   int type)
03062 {
03063   _dbus_return_val_if_fail (connection != NULL, FALSE);
03064 
03065   if (!dbus_type_is_valid (type))
03066     return FALSE;
03067 
03068   if (type != DBUS_TYPE_UNIX_FD)
03069     return TRUE;
03070 
03071 #ifdef HAVE_UNIX_FD_PASSING
03072   {
03073     dbus_bool_t b;
03074 
03075     CONNECTION_LOCK(connection);
03076     b = _dbus_transport_can_pass_unix_fd(connection->transport);
03077     CONNECTION_UNLOCK(connection);
03078 
03079     return b;
03080   }
03081 #endif
03082 
03083   return FALSE;
03084 }
03085 
03099 void
03100 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03101                                         dbus_bool_t     exit_on_disconnect)
03102 {
03103   _dbus_return_if_fail (connection != NULL);
03104 
03105   CONNECTION_LOCK (connection);
03106   connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03107   CONNECTION_UNLOCK (connection);
03108 }
03109 
03119 DBusPreallocatedSend*
03120 dbus_connection_preallocate_send (DBusConnection *connection)
03121 {
03122   DBusPreallocatedSend *preallocated;
03123 
03124   _dbus_return_val_if_fail (connection != NULL, NULL);
03125 
03126   CONNECTION_LOCK (connection);
03127   
03128   preallocated =
03129     _dbus_connection_preallocate_send_unlocked (connection);
03130 
03131   CONNECTION_UNLOCK (connection);
03132 
03133   return preallocated;
03134 }
03135 
03145 void
03146 dbus_connection_free_preallocated_send (DBusConnection       *connection,
03147                                         DBusPreallocatedSend *preallocated)
03148 {
03149   _dbus_return_if_fail (connection != NULL);
03150   _dbus_return_if_fail (preallocated != NULL);  
03151   _dbus_return_if_fail (connection == preallocated->connection);
03152 
03153   _dbus_list_free_link (preallocated->queue_link);
03154   _dbus_counter_unref (preallocated->counter_link->data);
03155   _dbus_list_free_link (preallocated->counter_link);
03156   dbus_free (preallocated);
03157 }
03158 
03171 void
03172 dbus_connection_send_preallocated (DBusConnection       *connection,
03173                                    DBusPreallocatedSend *preallocated,
03174                                    DBusMessage          *message,
03175                                    dbus_uint32_t        *client_serial)
03176 {
03177   _dbus_return_if_fail (connection != NULL);
03178   _dbus_return_if_fail (preallocated != NULL);
03179   _dbus_return_if_fail (message != NULL);
03180   _dbus_return_if_fail (preallocated->connection == connection);
03181   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03182                         dbus_message_get_member (message) != NULL);
03183   _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03184                         (dbus_message_get_interface (message) != NULL &&
03185                          dbus_message_get_member (message) != NULL));
03186 
03187   CONNECTION_LOCK (connection);
03188 
03189 #ifdef HAVE_UNIX_FD_PASSING
03190 
03191   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03192       message->n_unix_fds > 0)
03193     {
03194       /* Refuse to send fds on a connection that cannot handle
03195          them. Unfortunately we cannot return a proper error here, so
03196          the best we can is just return. */
03197       CONNECTION_UNLOCK (connection);
03198       return;
03199     }
03200 
03201 #endif
03202 
03203   _dbus_connection_send_preallocated_and_unlock (connection,
03204                                                  preallocated,
03205                                                  message, client_serial);
03206 }
03207 
03208 static dbus_bool_t
03209 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03210                                           DBusMessage    *message,
03211                                           dbus_uint32_t  *client_serial)
03212 {
03213   DBusPreallocatedSend *preallocated;
03214 
03215   _dbus_assert (connection != NULL);
03216   _dbus_assert (message != NULL);
03217   
03218   preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03219   if (preallocated == NULL)
03220     return FALSE;
03221 
03222   _dbus_connection_send_preallocated_unlocked_no_update (connection,
03223                                                          preallocated,
03224                                                          message,
03225                                                          client_serial);
03226   return TRUE;
03227 }
03228 
03256 dbus_bool_t
03257 dbus_connection_send (DBusConnection *connection,
03258                       DBusMessage    *message,
03259                       dbus_uint32_t  *serial)
03260 {
03261   _dbus_return_val_if_fail (connection != NULL, FALSE);
03262   _dbus_return_val_if_fail (message != NULL, FALSE);
03263 
03264   CONNECTION_LOCK (connection);
03265 
03266 #ifdef HAVE_UNIX_FD_PASSING
03267 
03268   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03269       message->n_unix_fds > 0)
03270     {
03271       /* Refuse to send fds on a connection that cannot handle
03272          them. Unfortunately we cannot return a proper error here, so
03273          the best we can is just return. */
03274       CONNECTION_UNLOCK (connection);
03275       return FALSE;
03276     }
03277 
03278 #endif
03279 
03280   return _dbus_connection_send_and_unlock (connection,
03281                                            message,
03282                                            serial);
03283 }
03284 
03285 static dbus_bool_t
03286 reply_handler_timeout (void *data)
03287 {
03288   DBusConnection *connection;
03289   DBusDispatchStatus status;
03290   DBusPendingCall *pending = data;
03291 
03292   connection = _dbus_pending_call_get_connection_and_lock (pending);
03293   _dbus_connection_ref_unlocked (connection);
03294 
03295   _dbus_pending_call_queue_timeout_error_unlocked (pending, 
03296                                                    connection);
03297   _dbus_connection_remove_timeout_unlocked (connection,
03298                                             _dbus_pending_call_get_timeout_unlocked (pending));
03299   _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03300 
03301   _dbus_verbose ("middle\n");
03302   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03303 
03304   /* Unlocks, and calls out to user code */
03305   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03306   dbus_connection_unref (connection);
03307   
03308   return TRUE;
03309 }
03310 
03353 dbus_bool_t
03354 dbus_connection_send_with_reply (DBusConnection     *connection,
03355                                  DBusMessage        *message,
03356                                  DBusPendingCall   **pending_return,
03357                                  int                 timeout_milliseconds)
03358 {
03359   DBusPendingCall *pending;
03360   dbus_int32_t serial = -1;
03361   DBusDispatchStatus status;
03362 
03363   _dbus_return_val_if_fail (connection != NULL, FALSE);
03364   _dbus_return_val_if_fail (message != NULL, FALSE);
03365   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03366 
03367   if (pending_return)
03368     *pending_return = NULL;
03369 
03370   CONNECTION_LOCK (connection);
03371 
03372 #ifdef HAVE_UNIX_FD_PASSING
03373 
03374   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03375       message->n_unix_fds > 0)
03376     {
03377       /* Refuse to send fds on a connection that cannot handle
03378          them. Unfortunately we cannot return a proper error here, so
03379          the best we can do is return TRUE but leave *pending_return
03380          as NULL. */
03381       CONNECTION_UNLOCK (connection);
03382       return TRUE;
03383     }
03384 
03385 #endif
03386 
03387    if (!_dbus_connection_get_is_connected_unlocked (connection))
03388     {
03389       CONNECTION_UNLOCK (connection);
03390 
03391       return TRUE;
03392     }
03393 
03394   pending = _dbus_pending_call_new_unlocked (connection,
03395                                              timeout_milliseconds,
03396                                              reply_handler_timeout);
03397 
03398   if (pending == NULL)
03399     {
03400       CONNECTION_UNLOCK (connection);
03401       return FALSE;
03402     }
03403 
03404   /* Assign a serial to the message */
03405   serial = dbus_message_get_serial (message);
03406   if (serial == 0)
03407     {
03408       serial = _dbus_connection_get_next_client_serial (connection);
03409       dbus_message_set_serial (message, serial);
03410     }
03411 
03412   if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03413     goto error;
03414     
03415   /* Insert the serial in the pending replies hash;
03416    * hash takes a refcount on DBusPendingCall.
03417    * Also, add the timeout.
03418    */
03419   if (!_dbus_connection_attach_pending_call_unlocked (connection,
03420                                                       pending))
03421     goto error;
03422  
03423   if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03424     {
03425       _dbus_connection_detach_pending_call_and_unlock (connection,
03426                                                        pending);
03427       goto error_unlocked;
03428     }
03429 
03430   if (pending_return)
03431     *pending_return = pending; /* hand off refcount */
03432   else
03433     {
03434       _dbus_connection_detach_pending_call_unlocked (connection, pending);
03435       /* we still have a ref to the pending call in this case, we unref
03436        * after unlocking, below
03437        */
03438     }
03439 
03440   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03441 
03442   /* this calls out to user code */
03443   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03444 
03445   if (pending_return == NULL)
03446     dbus_pending_call_unref (pending);
03447   
03448   return TRUE;
03449 
03450  error:
03451   CONNECTION_UNLOCK (connection);
03452  error_unlocked:
03453   dbus_pending_call_unref (pending);
03454   return FALSE;
03455 }
03456 
03489 DBusMessage*
03490 dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
03491                                            DBusMessage        *message,
03492                                            int                 timeout_milliseconds,
03493                                            DBusError          *error)
03494 {
03495   DBusMessage *reply;
03496   DBusPendingCall *pending;
03497 
03498   _dbus_return_val_if_fail (connection != NULL, NULL);
03499   _dbus_return_val_if_fail (message != NULL, NULL);
03500   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03501   _dbus_return_val_if_error_is_set (error, NULL);
03502 
03503 #ifdef HAVE_UNIX_FD_PASSING
03504 
03505   CONNECTION_LOCK (connection);
03506   if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03507       message->n_unix_fds > 0)
03508     {
03509       CONNECTION_UNLOCK (connection);
03510       dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03511       return NULL;
03512     }
03513   CONNECTION_UNLOCK (connection);
03514 
03515 #endif
03516 
03517   if (!dbus_connection_send_with_reply (connection, message,
03518                                         &pending, timeout_milliseconds))
03519     {
03520       _DBUS_SET_OOM (error);
03521       return NULL;
03522     }
03523 
03524   if (pending == NULL)
03525     {
03526       dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03527       return NULL;
03528     }
03529   
03530   dbus_pending_call_block (pending);
03531 
03532   reply = dbus_pending_call_steal_reply (pending);
03533   dbus_pending_call_unref (pending);
03534 
03535   /* call_complete_and_unlock() called from pending_call_block() should
03536    * always fill this in.
03537    */
03538   _dbus_assert (reply != NULL);
03539   
03540    if (dbus_set_error_from_message (error, reply))
03541     {
03542       dbus_message_unref (reply);
03543       return NULL;
03544     }
03545   else
03546     return reply;
03547 }
03548 
03557 static DBusDispatchStatus
03558 _dbus_connection_flush_unlocked (DBusConnection *connection)
03559 {
03560   /* We have to specify DBUS_ITERATION_DO_READING here because
03561    * otherwise we could have two apps deadlock if they are both doing
03562    * a flush(), and the kernel buffers fill up. This could change the
03563    * dispatch status.
03564    */
03565   DBusDispatchStatus status;
03566 
03567   HAVE_LOCK_CHECK (connection);
03568   
03569   while (connection->n_outgoing > 0 &&
03570          _dbus_connection_get_is_connected_unlocked (connection))
03571     {
03572       _dbus_verbose ("doing iteration in\n");
03573       HAVE_LOCK_CHECK (connection);
03574       _dbus_connection_do_iteration_unlocked (connection,
03575                                               NULL,
03576                                               DBUS_ITERATION_DO_READING |
03577                                               DBUS_ITERATION_DO_WRITING |
03578                                               DBUS_ITERATION_BLOCK,
03579                                               -1);
03580     }
03581 
03582   HAVE_LOCK_CHECK (connection);
03583   _dbus_verbose ("middle\n");
03584   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03585 
03586   HAVE_LOCK_CHECK (connection);
03587   return status;
03588 }
03589 
03595 void
03596 dbus_connection_flush (DBusConnection *connection)
03597 {
03598   /* We have to specify DBUS_ITERATION_DO_READING here because
03599    * otherwise we could have two apps deadlock if they are both doing
03600    * a flush(), and the kernel buffers fill up. This could change the
03601    * dispatch status.
03602    */
03603   DBusDispatchStatus status;
03604 
03605   _dbus_return_if_fail (connection != NULL);
03606   
03607   CONNECTION_LOCK (connection);
03608 
03609   status = _dbus_connection_flush_unlocked (connection);
03610   
03611   HAVE_LOCK_CHECK (connection);
03612   /* Unlocks and calls out to user code */
03613   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03614 
03615   _dbus_verbose ("end\n");
03616 }
03617 
03628 static dbus_bool_t
03629 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03630                                      int             timeout_milliseconds, 
03631                                      dbus_bool_t     dispatch)
03632 {
03633   DBusDispatchStatus dstatus;
03634   dbus_bool_t progress_possible;
03635 
03636   /* Need to grab a ref here in case we're a private connection and
03637    * the user drops the last ref in a handler we call; see bug 
03638    * https://bugs.freedesktop.org/show_bug.cgi?id=15635
03639    */
03640   dbus_connection_ref (connection);
03641   dstatus = dbus_connection_get_dispatch_status (connection);
03642 
03643   if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03644     {
03645       _dbus_verbose ("doing dispatch\n");
03646       dbus_connection_dispatch (connection);
03647       CONNECTION_LOCK (connection);
03648     }
03649   else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03650     {
03651       _dbus_verbose ("pausing for memory\n");
03652       _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03653       CONNECTION_LOCK (connection);
03654     }
03655   else
03656     {
03657       CONNECTION_LOCK (connection);
03658       if (_dbus_connection_get_is_connected_unlocked (connection))
03659         {
03660           _dbus_verbose ("doing iteration\n");
03661           _dbus_connection_do_iteration_unlocked (connection,
03662                                                   NULL,
03663                                                   DBUS_ITERATION_DO_READING |
03664                                                   DBUS_ITERATION_DO_WRITING |
03665                                                   DBUS_ITERATION_BLOCK,
03666                                                   timeout_milliseconds);
03667         }
03668     }
03669   
03670   HAVE_LOCK_CHECK (connection);
03671   /* If we can dispatch, we can make progress until the Disconnected message
03672    * has been processed; if we can only read/write, we can make progress
03673    * as long as the transport is open.
03674    */
03675   if (dispatch)
03676     progress_possible = connection->n_incoming != 0 ||
03677       connection->disconnect_message_link != NULL;
03678   else
03679     progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03680 
03681   CONNECTION_UNLOCK (connection);
03682 
03683   dbus_connection_unref (connection);
03684 
03685   return progress_possible; /* TRUE if we can make more progress */
03686 }
03687 
03688 
03723 dbus_bool_t
03724 dbus_connection_read_write_dispatch (DBusConnection *connection,
03725                                      int             timeout_milliseconds)
03726 {
03727   _dbus_return_val_if_fail (connection != NULL, FALSE);
03728   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03729    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03730 }
03731 
03755 dbus_bool_t 
03756 dbus_connection_read_write (DBusConnection *connection, 
03757                             int             timeout_milliseconds) 
03758 { 
03759   _dbus_return_val_if_fail (connection != NULL, FALSE);
03760   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03761    return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03762 }
03763 
03764 /* We need to call this anytime we pop the head of the queue, and then
03765  * update_dispatch_status_and_unlock needs to be called afterward
03766  * which will "process" the disconnected message and set
03767  * disconnected_message_processed.
03768  */
03769 static void
03770 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03771                                              DBusMessage    *head_of_queue)
03772 {
03773   HAVE_LOCK_CHECK (connection);
03774 
03775   /* checking that the link is NULL is an optimization to avoid the is_signal call */
03776   if (connection->disconnect_message_link == NULL &&
03777       dbus_message_is_signal (head_of_queue,
03778                               DBUS_INTERFACE_LOCAL,
03779                               "Disconnected"))
03780     {
03781       connection->disconnected_message_arrived = TRUE;
03782     }
03783 }
03784 
03804 DBusMessage*
03805 dbus_connection_borrow_message (DBusConnection *connection)
03806 {
03807   DBusDispatchStatus status;
03808   DBusMessage *message;
03809 
03810   _dbus_return_val_if_fail (connection != NULL, NULL);
03811 
03812   _dbus_verbose ("start\n");
03813   
03814   /* this is called for the side effect that it queues
03815    * up any messages from the transport
03816    */
03817   status = dbus_connection_get_dispatch_status (connection);
03818   if (status != DBUS_DISPATCH_DATA_REMAINS)
03819     return NULL;
03820   
03821   CONNECTION_LOCK (connection);
03822 
03823   _dbus_connection_acquire_dispatch (connection);
03824 
03825   /* While a message is outstanding, the dispatch lock is held */
03826   _dbus_assert (connection->message_borrowed == NULL);
03827 
03828   connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03829   
03830   message = connection->message_borrowed;
03831 
03832   check_disconnected_message_arrived_unlocked (connection, message);
03833   
03834   /* Note that we KEEP the dispatch lock until the message is returned */
03835   if (message == NULL)
03836     _dbus_connection_release_dispatch (connection);
03837 
03838   CONNECTION_UNLOCK (connection);
03839 
03840   _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
03841 
03842   /* We don't update dispatch status until it's returned or stolen */
03843   
03844   return message;
03845 }
03846 
03855 void
03856 dbus_connection_return_message (DBusConnection *connection,
03857                                 DBusMessage    *message)
03858 {
03859   DBusDispatchStatus status;
03860   
03861   _dbus_return_if_fail (connection != NULL);
03862   _dbus_return_if_fail (message != NULL);
03863   _dbus_return_if_fail (message == connection->message_borrowed);
03864   _dbus_return_if_fail (connection->dispatch_acquired);
03865   
03866   CONNECTION_LOCK (connection);
03867   
03868   _dbus_assert (message == connection->message_borrowed);
03869   
03870   connection->message_borrowed = NULL;
03871 
03872   _dbus_connection_release_dispatch (connection); 
03873 
03874   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03875   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03876 
03877   _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
03878 }
03879 
03889 void
03890 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03891                                         DBusMessage    *message)
03892 {
03893   DBusMessage *pop_message;
03894   DBusDispatchStatus status;
03895 
03896   _dbus_return_if_fail (connection != NULL);
03897   _dbus_return_if_fail (message != NULL);
03898   _dbus_return_if_fail (message == connection->message_borrowed);
03899   _dbus_return_if_fail (connection->dispatch_acquired);
03900   
03901   CONNECTION_LOCK (connection);
03902  
03903   _dbus_assert (message == connection->message_borrowed);
03904 
03905   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03906   _dbus_assert (message == pop_message);
03907   (void) pop_message; /* unused unless asserting */
03908 
03909   connection->n_incoming -= 1;
03910  
03911   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03912                  message, connection->n_incoming);
03913  
03914   connection->message_borrowed = NULL;
03915 
03916   _dbus_connection_release_dispatch (connection);
03917 
03918   status = _dbus_connection_get_dispatch_status_unlocked (connection);
03919   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03920   _dbus_message_trace_ref (message, -1, -1,
03921       "dbus_connection_steal_borrowed_message");
03922 }
03923 
03924 /* See dbus_connection_pop_message, but requires the caller to own
03925  * the lock before calling. May drop the lock while running.
03926  */
03927 static DBusList*
03928 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03929 {
03930   HAVE_LOCK_CHECK (connection);
03931   
03932   _dbus_assert (connection->message_borrowed == NULL);
03933   
03934   if (connection->n_incoming > 0)
03935     {
03936       DBusList *link;
03937 
03938       link = _dbus_list_pop_first_link (&connection->incoming_messages);
03939       connection->n_incoming -= 1;
03940 
03941       _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03942                      link->data,
03943                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
03944                      dbus_message_get_path (link->data) ?
03945                      dbus_message_get_path (link->data) :
03946                      "no path",
03947                      dbus_message_get_interface (link->data) ?
03948                      dbus_message_get_interface (link->data) :
03949                      "no interface",
03950                      dbus_message_get_member (link->data) ?
03951                      dbus_message_get_member (link->data) :
03952                      "no member",
03953                      dbus_message_get_signature (link->data),
03954                      connection, connection->n_incoming);
03955 
03956       _dbus_message_trace_ref (link->data, -1, -1,
03957           "_dbus_connection_pop_message_link_unlocked");
03958 
03959       check_disconnected_message_arrived_unlocked (connection, link->data);
03960       
03961       return link;
03962     }
03963   else
03964     return NULL;
03965 }
03966 
03967 /* See dbus_connection_pop_message, but requires the caller to own
03968  * the lock before calling. May drop the lock while running.
03969  */
03970 static DBusMessage*
03971 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03972 {
03973   DBusList *link;
03974 
03975   HAVE_LOCK_CHECK (connection);
03976   
03977   link = _dbus_connection_pop_message_link_unlocked (connection);
03978 
03979   if (link != NULL)
03980     {
03981       DBusMessage *message;
03982       
03983       message = link->data;
03984       
03985       _dbus_list_free_link (link);
03986       
03987       return message;
03988     }
03989   else
03990     return NULL;
03991 }
03992 
03993 static void
03994 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03995                                                 DBusList       *message_link)
03996 {
03997   HAVE_LOCK_CHECK (connection);
03998   
03999   _dbus_assert (message_link != NULL);
04000   /* You can't borrow a message while a link is outstanding */
04001   _dbus_assert (connection->message_borrowed == NULL);
04002   /* We had to have the dispatch lock across the pop/putback */
04003   _dbus_assert (connection->dispatch_acquired);
04004 
04005   _dbus_list_prepend_link (&connection->incoming_messages,
04006                            message_link);
04007   connection->n_incoming += 1;
04008 
04009   _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
04010                  message_link->data,
04011                  dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
04012                  dbus_message_get_interface (message_link->data) ?
04013                  dbus_message_get_interface (message_link->data) :
04014                  "no interface",
04015                  dbus_message_get_member (message_link->data) ?
04016                  dbus_message_get_member (message_link->data) :
04017                  "no member",
04018                  dbus_message_get_signature (message_link->data),
04019                  connection, connection->n_incoming);
04020 
04021   _dbus_message_trace_ref (message_link->data, -1, -1,
04022       "_dbus_connection_putback_message_link_unlocked");
04023 }
04024 
04044 DBusMessage*
04045 dbus_connection_pop_message (DBusConnection *connection)
04046 {
04047   DBusMessage *message;
04048   DBusDispatchStatus status;
04049 
04050   _dbus_verbose ("start\n");
04051   
04052   /* this is called for the side effect that it queues
04053    * up any messages from the transport
04054    */
04055   status = dbus_connection_get_dispatch_status (connection);
04056   if (status != DBUS_DISPATCH_DATA_REMAINS)
04057     return NULL;
04058   
04059   CONNECTION_LOCK (connection);
04060   _dbus_connection_acquire_dispatch (connection);
04061   HAVE_LOCK_CHECK (connection);
04062   
04063   message = _dbus_connection_pop_message_unlocked (connection);
04064 
04065   _dbus_verbose ("Returning popped message %p\n", message);    
04066 
04067   _dbus_connection_release_dispatch (connection);
04068 
04069   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04070   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04071   
04072   return message;
04073 }
04074 
04082 static void
04083 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04084 {
04085   HAVE_LOCK_CHECK (connection);
04086 
04087   _dbus_connection_ref_unlocked (connection);
04088   CONNECTION_UNLOCK (connection);
04089   
04090   _dbus_verbose ("locking dispatch_mutex\n");
04091   _dbus_cmutex_lock (connection->dispatch_mutex);
04092 
04093   while (connection->dispatch_acquired)
04094     {
04095       _dbus_verbose ("waiting for dispatch to be acquirable\n");
04096       _dbus_condvar_wait (connection->dispatch_cond, 
04097                           connection->dispatch_mutex);
04098     }
04099   
04100   _dbus_assert (!connection->dispatch_acquired);
04101 
04102   connection->dispatch_acquired = TRUE;
04103 
04104   _dbus_verbose ("unlocking dispatch_mutex\n");
04105   _dbus_cmutex_unlock (connection->dispatch_mutex);
04106   
04107   CONNECTION_LOCK (connection);
04108   _dbus_connection_unref_unlocked (connection);
04109 }
04110 
04118 static void
04119 _dbus_connection_release_dispatch (DBusConnection *connection)
04120 {
04121   HAVE_LOCK_CHECK (connection);
04122   
04123   _dbus_verbose ("locking dispatch_mutex\n");
04124   _dbus_cmutex_lock (connection->dispatch_mutex);
04125   
04126   _dbus_assert (connection->dispatch_acquired);
04127 
04128   connection->dispatch_acquired = FALSE;
04129   _dbus_condvar_wake_one (connection->dispatch_cond);
04130 
04131   _dbus_verbose ("unlocking dispatch_mutex\n");
04132   _dbus_cmutex_unlock (connection->dispatch_mutex);
04133 }
04134 
04135 static void
04136 _dbus_connection_failed_pop (DBusConnection *connection,
04137                              DBusList       *message_link)
04138 {
04139   _dbus_list_prepend_link (&connection->incoming_messages,
04140                            message_link);
04141   connection->n_incoming += 1;
04142 }
04143 
04144 /* Note this may be called multiple times since we don't track whether we already did it */
04145 static void
04146 notify_disconnected_unlocked (DBusConnection *connection)
04147 {
04148   HAVE_LOCK_CHECK (connection);
04149 
04150   /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
04151    * connection from dbus_bus_get(). We make the same guarantee for
04152    * dbus_connection_open() but in a different way since we don't want to
04153    * unref right here; we instead check for connectedness before returning
04154    * the connection from the hash.
04155    */
04156   _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04157 
04158   /* Dump the outgoing queue, we aren't going to be able to
04159    * send it now, and we'd like accessors like
04160    * dbus_connection_get_outgoing_size() to be accurate.
04161    */
04162   if (connection->n_outgoing > 0)
04163     {
04164       DBusList *link;
04165       
04166       _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04167                      connection->n_outgoing);
04168       
04169       while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04170         {
04171           _dbus_connection_message_sent_unlocked (connection, link->data);
04172         }
04173     } 
04174 }
04175 
04176 /* Note this may be called multiple times since we don't track whether we already did it */
04177 static DBusDispatchStatus
04178 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04179 {
04180   HAVE_LOCK_CHECK (connection);
04181   
04182   if (connection->disconnect_message_link != NULL)
04183     {
04184       _dbus_verbose ("Sending disconnect message\n");
04185       
04186       /* If we have pending calls, queue their timeouts - we want the Disconnected
04187        * to be the last message, after these timeouts.
04188        */
04189       connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04190       
04191       /* We haven't sent the disconnect message already,
04192        * and all real messages have been queued up.
04193        */
04194       _dbus_connection_queue_synthesized_message_link (connection,
04195                                                        connection->disconnect_message_link);
04196       connection->disconnect_message_link = NULL;
04197 
04198       return DBUS_DISPATCH_DATA_REMAINS;
04199     }
04200 
04201   return DBUS_DISPATCH_COMPLETE;
04202 }
04203 
04204 static DBusDispatchStatus
04205 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04206 {
04207   HAVE_LOCK_CHECK (connection);
04208   
04209   if (connection->n_incoming > 0)
04210     return DBUS_DISPATCH_DATA_REMAINS;
04211   else if (!_dbus_transport_queue_messages (connection->transport))
04212     return DBUS_DISPATCH_NEED_MEMORY;
04213   else
04214     {
04215       DBusDispatchStatus status;
04216       dbus_bool_t is_connected;
04217       
04218       status = _dbus_transport_get_dispatch_status (connection->transport);
04219       is_connected = _dbus_transport_get_is_connected (connection->transport);
04220 
04221       _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04222                      DISPATCH_STATUS_NAME (status), is_connected);
04223       
04224       if (!is_connected)
04225         {
04226           /* It's possible this would be better done by having an explicit
04227            * notification from _dbus_transport_disconnect() that would
04228            * synchronously do this, instead of waiting for the next dispatch
04229            * status check. However, probably not good to change until it causes
04230            * a problem.
04231            */
04232           notify_disconnected_unlocked (connection);
04233 
04234           /* I'm not sure this is needed; the idea is that we want to
04235            * queue the Disconnected only after we've read all the
04236            * messages, but if we're disconnected maybe we are guaranteed
04237            * to have read them all ?
04238            */
04239           if (status == DBUS_DISPATCH_COMPLETE)
04240             status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04241         }
04242       
04243       if (status != DBUS_DISPATCH_COMPLETE)
04244         return status;
04245       else if (connection->n_incoming > 0)
04246         return DBUS_DISPATCH_DATA_REMAINS;
04247       else
04248         return DBUS_DISPATCH_COMPLETE;
04249     }
04250 }
04251 
04252 static void
04253 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
04254                                                     DBusDispatchStatus new_status)
04255 {
04256   dbus_bool_t changed;
04257   DBusDispatchStatusFunction function;
04258   void *data;
04259 
04260   HAVE_LOCK_CHECK (connection);
04261 
04262   _dbus_connection_ref_unlocked (connection);
04263 
04264   changed = new_status != connection->last_dispatch_status;
04265 
04266   connection->last_dispatch_status = new_status;
04267 
04268   function = connection->dispatch_status_function;
04269   data = connection->dispatch_status_data;
04270 
04271   if (connection->disconnected_message_arrived &&
04272       !connection->disconnected_message_processed)
04273     {
04274       connection->disconnected_message_processed = TRUE;
04275       
04276       /* this does an unref, but we have a ref
04277        * so we should not run the finalizer here
04278        * inside the lock.
04279        */
04280       connection_forget_shared_unlocked (connection);
04281 
04282       if (connection->exit_on_disconnect)
04283         {
04284           CONNECTION_UNLOCK (connection);            
04285           
04286           _dbus_verbose ("Exiting on Disconnected signal\n");
04287           _dbus_exit (1);
04288           _dbus_assert_not_reached ("Call to exit() returned");
04289         }
04290     }
04291   
04292   /* We drop the lock */
04293   CONNECTION_UNLOCK (connection);
04294   
04295   if (changed && function)
04296     {
04297       _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04298                      connection, new_status,
04299                      DISPATCH_STATUS_NAME (new_status));
04300       (* function) (connection, new_status, data);      
04301     }
04302   
04303   dbus_connection_unref (connection);
04304 }
04305 
04331 DBusDispatchStatus
04332 dbus_connection_get_dispatch_status (DBusConnection *connection)
04333 {
04334   DBusDispatchStatus status;
04335 
04336   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04337 
04338   _dbus_verbose ("start\n");
04339   
04340   CONNECTION_LOCK (connection);
04341 
04342   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04343   
04344   CONNECTION_UNLOCK (connection);
04345 
04346   return status;
04347 }
04348 
04352 static DBusHandlerResult
04353 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04354                                                  DBusMessage    *message)
04355 {
04356   dbus_bool_t sent = FALSE;
04357   DBusMessage *ret = NULL;
04358   DBusList *expire_link;
04359 
04360   if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04361     {
04362       /* This means we're letting the bus route this message */
04363       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04364     }
04365 
04366   if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04367     {
04368       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04369     }
04370 
04371   /* Preallocate a linked-list link, so that if we need to dispose of a
04372    * message, we can attach it to the expired list */
04373   expire_link = _dbus_list_alloc_link (NULL);
04374 
04375   if (!expire_link)
04376     return DBUS_HANDLER_RESULT_NEED_MEMORY;
04377 
04378   if (dbus_message_is_method_call (message,
04379                                    DBUS_INTERFACE_PEER,
04380                                    "Ping"))
04381     {
04382       ret = dbus_message_new_method_return (message);
04383       if (ret == NULL)
04384         goto out;
04385 
04386       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04387     }
04388   else if (dbus_message_is_method_call (message,
04389                                         DBUS_INTERFACE_PEER,
04390                                         "GetMachineId"))
04391     {
04392       DBusString uuid;
04393       
04394       ret = dbus_message_new_method_return (message);
04395       if (ret == NULL)
04396         goto out;
04397 
04398       _dbus_string_init (&uuid);
04399       if (_dbus_get_local_machine_uuid_encoded (&uuid))
04400         {
04401           const char *v_STRING = _dbus_string_get_const_data (&uuid);
04402           if (dbus_message_append_args (ret,
04403                                         DBUS_TYPE_STRING, &v_STRING,
04404                                         DBUS_TYPE_INVALID))
04405             {
04406               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04407             }
04408         }
04409       _dbus_string_free (&uuid);
04410     }
04411   else
04412     {
04413       /* We need to bounce anything else with this interface, otherwise apps
04414        * could start extending the interface and when we added extensions
04415        * here to DBusConnection we'd break those apps.
04416        */
04417       ret = dbus_message_new_error (message,
04418                                     DBUS_ERROR_UNKNOWN_METHOD,
04419                                     "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04420       if (ret == NULL)
04421         goto out;
04422 
04423       sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04424     }
04425 
04426 out:
04427   if (ret == NULL)
04428     {
04429       _dbus_list_free_link (expire_link);
04430     }
04431   else
04432     {
04433       /* It'll be safe to unref the reply when we unlock */
04434       expire_link->data = ret;
04435       _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04436     }
04437 
04438   if (!sent)
04439     return DBUS_HANDLER_RESULT_NEED_MEMORY;
04440 
04441   return DBUS_HANDLER_RESULT_HANDLED;
04442 }
04443 
04450 static DBusHandlerResult
04451 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04452                                                            DBusMessage    *message)
04453 {
04454   /* We just run one filter for now but have the option to run more
04455      if the spec calls for it in the future */
04456 
04457   return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04458 }
04459 
04502 DBusDispatchStatus
04503 dbus_connection_dispatch (DBusConnection *connection)
04504 {
04505   DBusMessage *message;
04506   DBusList *link, *filter_list_copy, *message_link;
04507   DBusHandlerResult result;
04508   DBusPendingCall *pending;
04509   dbus_int32_t reply_serial;
04510   DBusDispatchStatus status;
04511   dbus_bool_t found_object;
04512 
04513   _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04514 
04515   _dbus_verbose ("\n");
04516   
04517   CONNECTION_LOCK (connection);
04518   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04519   if (status != DBUS_DISPATCH_DATA_REMAINS)
04520     {
04521       /* unlocks and calls out to user code */
04522       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04523       return status;
04524     }
04525   
04526   /* We need to ref the connection since the callback could potentially
04527    * drop the last ref to it
04528    */
04529   _dbus_connection_ref_unlocked (connection);
04530 
04531   _dbus_connection_acquire_dispatch (connection);
04532   HAVE_LOCK_CHECK (connection);
04533 
04534   message_link = _dbus_connection_pop_message_link_unlocked (connection);
04535   if (message_link == NULL)
04536     {
04537       /* another thread dispatched our stuff */
04538 
04539       _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04540       
04541       _dbus_connection_release_dispatch (connection);
04542 
04543       status = _dbus_connection_get_dispatch_status_unlocked (connection);
04544 
04545       _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04546       
04547       dbus_connection_unref (connection);
04548       
04549       return status;
04550     }
04551 
04552   message = message_link->data;
04553 
04554   _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04555                  message,
04556                  dbus_message_type_to_string (dbus_message_get_type (message)),
04557                  dbus_message_get_interface (message) ?
04558                  dbus_message_get_interface (message) :
04559                  "no interface",
04560                  dbus_message_get_member (message) ?
04561                  dbus_message_get_member (message) :
04562                  "no member",
04563                  dbus_message_get_signature (message));
04564 
04565   result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04566   
04567   /* Pending call handling must be first, because if you do
04568    * dbus_connection_send_with_reply_and_block() or
04569    * dbus_pending_call_block() then no handlers/filters will be run on
04570    * the reply. We want consistent semantics in the case where we
04571    * dbus_connection_dispatch() the reply.
04572    */
04573   
04574   reply_serial = dbus_message_get_reply_serial (message);
04575   pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04576                                          reply_serial);
04577   if (pending)
04578     {
04579       _dbus_verbose ("Dispatching a pending reply\n");
04580       complete_pending_call_and_unlock (connection, pending, message);
04581       pending = NULL; /* it's probably unref'd */
04582       
04583       CONNECTION_LOCK (connection);
04584       _dbus_verbose ("pending call completed in dispatch\n");
04585       result = DBUS_HANDLER_RESULT_HANDLED;
04586       goto out;
04587     }
04588 
04589   result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04590   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04591     goto out;
04592  
04593   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04594     {
04595       _dbus_connection_release_dispatch (connection);
04596       HAVE_LOCK_CHECK (connection);
04597       
04598       _dbus_connection_failed_pop (connection, message_link);
04599 
04600       /* unlocks and calls user code */
04601       _dbus_connection_update_dispatch_status_and_unlock (connection,
04602                                                           DBUS_DISPATCH_NEED_MEMORY);
04603       dbus_connection_unref (connection);
04604       
04605       return DBUS_DISPATCH_NEED_MEMORY;
04606     }
04607   
04608   _dbus_list_foreach (&filter_list_copy,
04609                       (DBusForeachFunction)_dbus_message_filter_ref,
04610                       NULL);
04611 
04612   /* We're still protected from dispatch() reentrancy here
04613    * since we acquired the dispatcher
04614    */
04615   CONNECTION_UNLOCK (connection);
04616   
04617   link = _dbus_list_get_first_link (&filter_list_copy);
04618   while (link != NULL)
04619     {
04620       DBusMessageFilter *filter = link->data;
04621       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04622 
04623       if (filter->function == NULL)
04624         {
04625           _dbus_verbose ("  filter was removed in a callback function\n");
04626           link = next;
04627           continue;
04628         }
04629 
04630       _dbus_verbose ("  running filter on message %p\n", message);
04631       result = (* filter->function) (connection, message, filter->user_data);
04632 
04633       if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04634         break;
04635 
04636       link = next;
04637     }
04638 
04639   _dbus_list_foreach (&filter_list_copy,
04640                       (DBusForeachFunction)_dbus_message_filter_unref,
04641                       NULL);
04642   _dbus_list_clear (&filter_list_copy);
04643   
04644   CONNECTION_LOCK (connection);
04645 
04646   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04647     {
04648       _dbus_verbose ("No memory\n");
04649       goto out;
04650     }
04651   else if (result == DBUS_HANDLER_RESULT_HANDLED)
04652     {
04653       _dbus_verbose ("filter handled message in dispatch\n");
04654       goto out;
04655     }
04656 
04657   /* We're still protected from dispatch() reentrancy here
04658    * since we acquired the dispatcher
04659    */
04660   _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
04661                  message,
04662                  dbus_message_type_to_string (dbus_message_get_type (message)),
04663                  dbus_message_get_interface (message) ?
04664                  dbus_message_get_interface (message) :
04665                  "no interface",
04666                  dbus_message_get_member (message) ?
04667                  dbus_message_get_member (message) :
04668                  "no member",
04669                  dbus_message_get_signature (message));
04670 
04671   HAVE_LOCK_CHECK (connection);
04672   result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04673                                                   message,
04674                                                   &found_object);
04675   
04676   CONNECTION_LOCK (connection);
04677 
04678   if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04679     {
04680       _dbus_verbose ("object tree handled message in dispatch\n");
04681       goto out;
04682     }
04683 
04684   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04685     {
04686       DBusMessage *reply;
04687       DBusString str;
04688       DBusPreallocatedSend *preallocated;
04689       DBusList *expire_link;
04690 
04691       _dbus_verbose ("  sending error %s\n",
04692                      DBUS_ERROR_UNKNOWN_METHOD);
04693 
04694       if (!_dbus_string_init (&str))
04695         {
04696           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04697           _dbus_verbose ("no memory for error string in dispatch\n");
04698           goto out;
04699         }
04700               
04701       if (!_dbus_string_append_printf (&str,
04702                                        "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04703                                        dbus_message_get_member (message),
04704                                        dbus_message_get_signature (message),
04705                                        dbus_message_get_interface (message)))
04706         {
04707           _dbus_string_free (&str);
04708           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04709           _dbus_verbose ("no memory for error string in dispatch\n");
04710           goto out;
04711         }
04712       
04713       reply = dbus_message_new_error (message,
04714                                       found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
04715                                       _dbus_string_get_const_data (&str));
04716       _dbus_string_free (&str);
04717 
04718       if (reply == NULL)
04719         {
04720           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04721           _dbus_verbose ("no memory for error reply in dispatch\n");
04722           goto out;
04723         }
04724 
04725       expire_link = _dbus_list_alloc_link (reply);
04726 
04727       if (expire_link == NULL)
04728         {
04729           dbus_message_unref (reply);
04730           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04731           _dbus_verbose ("no memory for error send in dispatch\n");
04732           goto out;
04733         }
04734 
04735       preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04736 
04737       if (preallocated == NULL)
04738         {
04739           _dbus_list_free_link (expire_link);
04740           /* It's OK that this is finalized, because it hasn't been seen by
04741            * anything that could attach user callbacks */
04742           dbus_message_unref (reply);
04743           result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04744           _dbus_verbose ("no memory for error send in dispatch\n");
04745           goto out;
04746         }
04747 
04748       _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04749                                                              reply, NULL);
04750       /* reply will be freed when we release the lock */
04751       _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04752 
04753       result = DBUS_HANDLER_RESULT_HANDLED;
04754     }
04755   
04756   _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04757                  dbus_message_type_to_string (dbus_message_get_type (message)),
04758                  dbus_message_get_interface (message) ?
04759                  dbus_message_get_interface (message) :
04760                  "no interface",
04761                  dbus_message_get_member (message) ?
04762                  dbus_message_get_member (message) :
04763                  "no member",
04764                  dbus_message_get_signature (message),
04765                  connection);
04766   
04767  out:
04768   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04769     {
04770       _dbus_verbose ("out of memory\n");
04771       
04772       /* Put message back, and we'll start over.
04773        * Yes this means handlers must be idempotent if they
04774        * don't return HANDLED; c'est la vie.
04775        */
04776       _dbus_connection_putback_message_link_unlocked (connection,
04777                                                       message_link);
04778       /* now we don't want to free them */
04779       message_link = NULL;
04780       message = NULL;
04781     }
04782   else
04783     {
04784       _dbus_verbose (" ... done dispatching\n");
04785     }
04786 
04787   _dbus_connection_release_dispatch (connection);
04788   HAVE_LOCK_CHECK (connection);
04789 
04790   if (message != NULL)
04791     {
04792       /* We don't want this message to count in maximum message limits when
04793        * computing the dispatch status, below. We have to drop the lock
04794        * temporarily, because finalizing a message can trigger callbacks.
04795        *
04796        * We have a reference to the connection, and we don't use any cached
04797        * pointers to the connection's internals below this point, so it should
04798        * be safe to drop the lock and take it back. */
04799       CONNECTION_UNLOCK (connection);
04800       dbus_message_unref (message);
04801       CONNECTION_LOCK (connection);
04802     }
04803 
04804   if (message_link != NULL)
04805     _dbus_list_free_link (message_link);
04806 
04807   _dbus_verbose ("before final status update\n");
04808   status = _dbus_connection_get_dispatch_status_unlocked (connection);
04809 
04810   /* unlocks and calls user code */
04811   _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04812   
04813   dbus_connection_unref (connection);
04814   
04815   return status;
04816 }
04817 
04879 dbus_bool_t
04880 dbus_connection_set_watch_functions (DBusConnection              *connection,
04881                                      DBusAddWatchFunction         add_function,
04882                                      DBusRemoveWatchFunction      remove_function,
04883                                      DBusWatchToggledFunction     toggled_function,
04884                                      void                        *data,
04885                                      DBusFreeFunction             free_data_function)
04886 {
04887   dbus_bool_t retval;
04888 
04889   _dbus_return_val_if_fail (connection != NULL, FALSE);
04890   
04891   CONNECTION_LOCK (connection);
04892 
04893   retval = _dbus_watch_list_set_functions (connection->watches,
04894                                            add_function, remove_function,
04895                                            toggled_function,
04896                                            data, free_data_function);
04897 
04898   CONNECTION_UNLOCK (connection);
04899 
04900   return retval;
04901 }
04902 
04942 dbus_bool_t
04943 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
04944                                          DBusAddTimeoutFunction     add_function,
04945                                          DBusRemoveTimeoutFunction  remove_function,
04946                                          DBusTimeoutToggledFunction toggled_function,
04947                                          void                      *data,
04948                                          DBusFreeFunction           free_data_function)
04949 {
04950   dbus_bool_t retval;
04951 
04952   _dbus_return_val_if_fail (connection != NULL, FALSE);
04953   
04954   CONNECTION_LOCK (connection);
04955 
04956   retval = _dbus_timeout_list_set_functions (connection->timeouts,
04957                                              add_function, remove_function,
04958                                              toggled_function,
04959                                              data, free_data_function);
04960 
04961   CONNECTION_UNLOCK (connection);
04962 
04963   return retval;
04964 }
04965 
04980 void
04981 dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
04982                                           DBusWakeupMainFunction     wakeup_main_function,
04983                                           void                      *data,
04984                                           DBusFreeFunction           free_data_function)
04985 {
04986   void *old_data;
04987   DBusFreeFunction old_free_data;
04988 
04989   _dbus_return_if_fail (connection != NULL);
04990   
04991   CONNECTION_LOCK (connection);
04992   old_data = connection->wakeup_main_data;
04993   old_free_data = connection->free_wakeup_main_data;
04994 
04995   connection->wakeup_main_function = wakeup_main_function;
04996   connection->wakeup_main_data = data;
04997   connection->free_wakeup_main_data = free_data_function;
04998   
04999   CONNECTION_UNLOCK (connection);
05000 
05001   /* Callback outside the lock */
05002   if (old_free_data)
05003     (*old_free_data) (old_data);
05004 }
05005 
05026 void
05027 dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
05028                                               DBusDispatchStatusFunction  function,
05029                                               void                       *data,
05030                                               DBusFreeFunction            free_data_function)
05031 {
05032   void *old_data;
05033   DBusFreeFunction old_free_data;
05034 
05035   _dbus_return_if_fail (connection != NULL);
05036   
05037   CONNECTION_LOCK (connection);
05038   old_data = connection->dispatch_status_data;
05039   old_free_data = connection->free_dispatch_status_data;
05040 
05041   connection->dispatch_status_function = function;
05042   connection->dispatch_status_data = data;
05043   connection->free_dispatch_status_data = free_data_function;
05044   
05045   CONNECTION_UNLOCK (connection);
05046 
05047   /* Callback outside the lock */
05048   if (old_free_data)
05049     (*old_free_data) (old_data);
05050 }
05051 
05071 dbus_bool_t
05072 dbus_connection_get_unix_fd (DBusConnection *connection,
05073                              int            *fd)
05074 {
05075   _dbus_return_val_if_fail (connection != NULL, FALSE);
05076   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05077 
05078 #ifdef DBUS_WIN
05079   /* FIXME do this on a lower level */
05080   return FALSE;
05081 #endif
05082   
05083   return dbus_connection_get_socket(connection, fd);
05084 }
05085 
05101 dbus_bool_t
05102 dbus_connection_get_socket(DBusConnection              *connection,
05103                            int                         *fd)
05104 {
05105   dbus_bool_t retval;
05106 
05107   _dbus_return_val_if_fail (connection != NULL, FALSE);
05108   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05109   
05110   CONNECTION_LOCK (connection);
05111   
05112   retval = _dbus_transport_get_socket_fd (connection->transport,
05113                                           fd);
05114 
05115   CONNECTION_UNLOCK (connection);
05116 
05117   return retval;
05118 }
05119 
05120 
05143 dbus_bool_t
05144 dbus_connection_get_unix_user (DBusConnection *connection,
05145                                unsigned long  *uid)
05146 {
05147   dbus_bool_t result;
05148 
05149   _dbus_return_val_if_fail (connection != NULL, FALSE);
05150   _dbus_return_val_if_fail (uid != NULL, FALSE);
05151   
05152   CONNECTION_LOCK (connection);
05153 
05154   if (!_dbus_transport_get_is_authenticated (connection->transport))
05155     result = FALSE;
05156   else
05157     result = _dbus_transport_get_unix_user (connection->transport,
05158                                             uid);
05159 
05160 #ifdef DBUS_WIN
05161   _dbus_assert (!result);
05162 #endif
05163   
05164   CONNECTION_UNLOCK (connection);
05165 
05166   return result;
05167 }
05168 
05179 dbus_bool_t
05180 dbus_connection_get_unix_process_id (DBusConnection *connection,
05181                                      unsigned long  *pid)
05182 {
05183   dbus_bool_t result;
05184 
05185   _dbus_return_val_if_fail (connection != NULL, FALSE);
05186   _dbus_return_val_if_fail (pid != NULL, FALSE);
05187   
05188   CONNECTION_LOCK (connection);
05189 
05190   if (!_dbus_transport_get_is_authenticated (connection->transport))
05191     result = FALSE;
05192   else
05193     result = _dbus_transport_get_unix_process_id (connection->transport,
05194                                                   pid);
05195 
05196   CONNECTION_UNLOCK (connection);
05197 
05198   return result;
05199 }
05200 
05211 dbus_bool_t
05212 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05213                                             void          **data,
05214                                             dbus_int32_t   *data_size)
05215 {
05216   dbus_bool_t result;
05217 
05218   _dbus_return_val_if_fail (connection != NULL, FALSE);
05219   _dbus_return_val_if_fail (data != NULL, FALSE);
05220   _dbus_return_val_if_fail (data_size != NULL, FALSE);
05221   
05222   CONNECTION_LOCK (connection);
05223 
05224   if (!_dbus_transport_get_is_authenticated (connection->transport))
05225     result = FALSE;
05226   else
05227     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05228                                                          data,
05229                                                          data_size);
05230   CONNECTION_UNLOCK (connection);
05231 
05232   return result;
05233 }
05234 
05257 void
05258 dbus_connection_set_unix_user_function (DBusConnection             *connection,
05259                                         DBusAllowUnixUserFunction   function,
05260                                         void                       *data,
05261                                         DBusFreeFunction            free_data_function)
05262 {
05263   void *old_data = NULL;
05264   DBusFreeFunction old_free_function = NULL;
05265 
05266   _dbus_return_if_fail (connection != NULL);
05267   
05268   CONNECTION_LOCK (connection);
05269   _dbus_transport_set_unix_user_function (connection->transport,
05270                                           function, data, free_data_function,
05271                                           &old_data, &old_free_function);
05272   CONNECTION_UNLOCK (connection);
05273 
05274   if (old_free_function != NULL)
05275     (* old_free_function) (old_data);
05276 }
05277 
05309 dbus_bool_t
05310 dbus_connection_get_windows_user (DBusConnection             *connection,
05311                                   char                      **windows_sid_p)
05312 {
05313   dbus_bool_t result;
05314 
05315   _dbus_return_val_if_fail (connection != NULL, FALSE);
05316   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05317   
05318   CONNECTION_LOCK (connection);
05319 
05320   if (!_dbus_transport_get_is_authenticated (connection->transport))
05321     result = FALSE;
05322   else
05323     result = _dbus_transport_get_windows_user (connection->transport,
05324                                                windows_sid_p);
05325 
05326 #ifdef DBUS_UNIX
05327   _dbus_assert (!result);
05328 #endif
05329   
05330   CONNECTION_UNLOCK (connection);
05331 
05332   return result;
05333 }
05334 
05356 void
05357 dbus_connection_set_windows_user_function (DBusConnection              *connection,
05358                                            DBusAllowWindowsUserFunction function,
05359                                            void                        *data,
05360                                            DBusFreeFunction             free_data_function)
05361 {
05362   void *old_data = NULL;
05363   DBusFreeFunction old_free_function = NULL;
05364 
05365   _dbus_return_if_fail (connection != NULL);
05366   
05367   CONNECTION_LOCK (connection);
05368   _dbus_transport_set_windows_user_function (connection->transport,
05369                                              function, data, free_data_function,
05370                                              &old_data, &old_free_function);
05371   CONNECTION_UNLOCK (connection);
05372 
05373   if (old_free_function != NULL)
05374     (* old_free_function) (old_data);
05375 }
05376 
05403 void
05404 dbus_connection_set_allow_anonymous (DBusConnection             *connection,
05405                                      dbus_bool_t                 value)
05406 {
05407   _dbus_return_if_fail (connection != NULL);
05408   
05409   CONNECTION_LOCK (connection);
05410   _dbus_transport_set_allow_anonymous (connection->transport, value);
05411   CONNECTION_UNLOCK (connection);
05412 }
05413 
05431 void
05432 dbus_connection_set_route_peer_messages (DBusConnection             *connection,
05433                                          dbus_bool_t                 value)
05434 {
05435   _dbus_return_if_fail (connection != NULL);
05436   
05437   CONNECTION_LOCK (connection);
05438   connection->route_peer_messages = TRUE;
05439   CONNECTION_UNLOCK (connection);
05440 }
05441 
05463 dbus_bool_t
05464 dbus_connection_add_filter (DBusConnection            *connection,
05465                             DBusHandleMessageFunction  function,
05466                             void                      *user_data,
05467                             DBusFreeFunction           free_data_function)
05468 {
05469   DBusMessageFilter *filter;
05470   
05471   _dbus_return_val_if_fail (connection != NULL, FALSE);
05472   _dbus_return_val_if_fail (function != NULL, FALSE);
05473 
05474   filter = dbus_new0 (DBusMessageFilter, 1);
05475   if (filter == NULL)
05476     return FALSE;
05477 
05478   _dbus_atomic_inc (&filter->refcount);
05479 
05480   CONNECTION_LOCK (connection);
05481 
05482   if (!_dbus_list_append (&connection->filter_list,
05483                           filter))
05484     {
05485       _dbus_message_filter_unref (filter);
05486       CONNECTION_UNLOCK (connection);
05487       return FALSE;
05488     }
05489 
05490   /* Fill in filter after all memory allocated,
05491    * so we don't run the free_user_data_function
05492    * if the add_filter() fails
05493    */
05494   
05495   filter->function = function;
05496   filter->user_data = user_data;
05497   filter->free_user_data_function = free_data_function;
05498         
05499   CONNECTION_UNLOCK (connection);
05500   return TRUE;
05501 }
05502 
05515 void
05516 dbus_connection_remove_filter (DBusConnection            *connection,
05517                                DBusHandleMessageFunction  function,
05518                                void                      *user_data)
05519 {
05520   DBusList *link;
05521   DBusMessageFilter *filter;
05522   
05523   _dbus_return_if_fail (connection != NULL);
05524   _dbus_return_if_fail (function != NULL);
05525   
05526   CONNECTION_LOCK (connection);
05527 
05528   filter = NULL;
05529   
05530   link = _dbus_list_get_last_link (&connection->filter_list);
05531   while (link != NULL)
05532     {
05533       filter = link->data;
05534 
05535       if (filter->function == function &&
05536           filter->user_data == user_data)
05537         {
05538           _dbus_list_remove_link (&connection->filter_list, link);
05539           filter->function = NULL;
05540           
05541           break;
05542         }
05543         
05544       link = _dbus_list_get_prev_link (&connection->filter_list, link);
05545       filter = NULL;
05546     }
05547   
05548   CONNECTION_UNLOCK (connection);
05549 
05550 #ifndef DBUS_DISABLE_CHECKS
05551   if (filter == NULL)
05552     {
05553       _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05554                                function, user_data);
05555       return;
05556     }
05557 #endif
05558   
05559   /* Call application code */
05560   if (filter->free_user_data_function)
05561     (* filter->free_user_data_function) (filter->user_data);
05562 
05563   filter->free_user_data_function = NULL;
05564   filter->user_data = NULL;
05565   
05566   _dbus_message_filter_unref (filter);
05567 }
05568 
05584 static dbus_bool_t
05585 _dbus_connection_register_object_path (DBusConnection              *connection,
05586                                        dbus_bool_t                  fallback,
05587                                        const char                  *path,
05588                                        const DBusObjectPathVTable  *vtable,
05589                                        void                        *user_data,
05590                                        DBusError                   *error)
05591 {
05592   char **decomposed_path;
05593   dbus_bool_t retval;
05594 
05595   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05596     return FALSE;
05597 
05598   CONNECTION_LOCK (connection);
05599 
05600   retval = _dbus_object_tree_register (connection->objects,
05601                                        fallback,
05602                                        (const char **) decomposed_path, vtable,
05603                                        user_data, error);
05604 
05605   CONNECTION_UNLOCK (connection);
05606 
05607   dbus_free_string_array (decomposed_path);
05608 
05609   return retval;
05610 }
05611 
05624 dbus_bool_t
05625 dbus_connection_try_register_object_path (DBusConnection              *connection,
05626                                           const char                  *path,
05627                                           const DBusObjectPathVTable  *vtable,
05628                                           void                        *user_data,
05629                                           DBusError                   *error)
05630 {
05631   _dbus_return_val_if_fail (connection != NULL, FALSE);
05632   _dbus_return_val_if_fail (path != NULL, FALSE);
05633   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05634   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05635 
05636   return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
05637 }
05638 
05654 dbus_bool_t
05655 dbus_connection_register_object_path (DBusConnection              *connection,
05656                                       const char                  *path,
05657                                       const DBusObjectPathVTable  *vtable,
05658                                       void                        *user_data)
05659 {
05660   dbus_bool_t retval;
05661   DBusError error = DBUS_ERROR_INIT;
05662 
05663   _dbus_return_val_if_fail (connection != NULL, FALSE);
05664   _dbus_return_val_if_fail (path != NULL, FALSE);
05665   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05666   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05667 
05668   retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
05669 
05670   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05671     {
05672       _dbus_warn ("%s\n", error.message);
05673       dbus_error_free (&error);
05674       return FALSE;
05675     }
05676 
05677   return retval;
05678 }
05679 
05694 dbus_bool_t
05695 dbus_connection_try_register_fallback (DBusConnection              *connection,
05696                                        const char                  *path,
05697                                        const DBusObjectPathVTable  *vtable,
05698                                        void                        *user_data,
05699                                        DBusError                   *error)
05700 {
05701   _dbus_return_val_if_fail (connection != NULL, FALSE);
05702   _dbus_return_val_if_fail (path != NULL, FALSE);
05703   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05704   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05705 
05706   return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
05707 }
05708 
05726 dbus_bool_t
05727 dbus_connection_register_fallback (DBusConnection              *connection,
05728                                    const char                  *path,
05729                                    const DBusObjectPathVTable  *vtable,
05730                                    void                        *user_data)
05731 {
05732   dbus_bool_t retval;
05733   DBusError error = DBUS_ERROR_INIT;
05734 
05735   _dbus_return_val_if_fail (connection != NULL, FALSE);
05736   _dbus_return_val_if_fail (path != NULL, FALSE);
05737   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05738   _dbus_return_val_if_fail (vtable != NULL, FALSE);
05739 
05740   retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
05741 
05742   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05743     {
05744       _dbus_warn ("%s\n", error.message);
05745       dbus_error_free (&error);
05746       return FALSE;
05747     }
05748 
05749   return retval;
05750 }
05751 
05761 dbus_bool_t
05762 dbus_connection_unregister_object_path (DBusConnection              *connection,
05763                                         const char                  *path)
05764 {
05765   char **decomposed_path;
05766 
05767   _dbus_return_val_if_fail (connection != NULL, FALSE);
05768   _dbus_return_val_if_fail (path != NULL, FALSE);
05769   _dbus_return_val_if_fail (path[0] == '/', FALSE);
05770 
05771   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05772       return FALSE;
05773 
05774   CONNECTION_LOCK (connection);
05775 
05776   _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05777 
05778   dbus_free_string_array (decomposed_path);
05779 
05780   return TRUE;
05781 }
05782 
05793 dbus_bool_t
05794 dbus_connection_get_object_path_data (DBusConnection *connection,
05795                                       const char     *path,
05796                                       void          **data_p)
05797 {
05798   char **decomposed_path;
05799 
05800   _dbus_return_val_if_fail (connection != NULL, FALSE);
05801   _dbus_return_val_if_fail (path != NULL, FALSE);
05802   _dbus_return_val_if_fail (data_p != NULL, FALSE);
05803 
05804   *data_p = NULL;
05805   
05806   if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05807     return FALSE;
05808   
05809   CONNECTION_LOCK (connection);
05810 
05811   *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05812 
05813   CONNECTION_UNLOCK (connection);
05814 
05815   dbus_free_string_array (decomposed_path);
05816 
05817   return TRUE;
05818 }
05819 
05830 dbus_bool_t
05831 dbus_connection_list_registered (DBusConnection              *connection,
05832                                  const char                  *parent_path,
05833                                  char                      ***child_entries)
05834 {
05835   char **decomposed_path;
05836   dbus_bool_t retval;
05837   _dbus_return_val_if_fail (connection != NULL, FALSE);
05838   _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05839   _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05840   _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05841 
05842   if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05843     return FALSE;
05844 
05845   CONNECTION_LOCK (connection);
05846 
05847   retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05848                                                          (const char **) decomposed_path,
05849                                                          child_entries);
05850   dbus_free_string_array (decomposed_path);
05851 
05852   return retval;
05853 }
05854 
05855 static DBusDataSlotAllocator slot_allocator;
05856 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05857 
05872 dbus_bool_t
05873 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05874 {
05875   return _dbus_data_slot_allocator_alloc (&slot_allocator,
05876                                           &_DBUS_LOCK_NAME (connection_slots),
05877                                           slot_p);
05878 }
05879 
05891 void
05892 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05893 {
05894   _dbus_return_if_fail (*slot_p >= 0);
05895   
05896   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05897 }
05898 
05921 dbus_bool_t
05922 dbus_connection_set_data (DBusConnection   *connection,
05923                           dbus_int32_t      slot,
05924                           void             *data,
05925                           DBusFreeFunction  free_data_func)
05926 {
05927   DBusFreeFunction old_free_func;
05928   void *old_data;
05929   dbus_bool_t retval;
05930 
05931   _dbus_return_val_if_fail (connection != NULL, FALSE);
05932   _dbus_return_val_if_fail (slot >= 0, FALSE);
05933   
05934   SLOTS_LOCK (connection);
05935 
05936   retval = _dbus_data_slot_list_set (&slot_allocator,
05937                                      &connection->slot_list,
05938                                      slot, data, free_data_func,
05939                                      &old_free_func, &old_data);
05940   
05941   SLOTS_UNLOCK (connection);
05942 
05943   if (retval)
05944     {
05945       /* Do the actual free outside the connection lock */
05946       if (old_free_func)
05947         (* old_free_func) (old_data);
05948     }
05949 
05950   return retval;
05951 }
05952 
05970 void*
05971 dbus_connection_get_data (DBusConnection   *connection,
05972                           dbus_int32_t      slot)
05973 {
05974   void *res;
05975 
05976   _dbus_return_val_if_fail (connection != NULL, NULL);
05977   
05978   SLOTS_LOCK (connection);
05979 
05980   res = _dbus_data_slot_list_get (&slot_allocator,
05981                                   &connection->slot_list,
05982                                   slot);
05983   
05984   SLOTS_UNLOCK (connection);
05985 
05986   return res;
05987 }
05988 
05995 void
05996 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
05997 {  
05998   _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
05999 }
06000 
06009 void
06010 dbus_connection_set_max_message_size (DBusConnection *connection,
06011                                       long            size)
06012 {
06013   _dbus_return_if_fail (connection != NULL);
06014   
06015   CONNECTION_LOCK (connection);
06016   _dbus_transport_set_max_message_size (connection->transport,
06017                                         size);
06018   CONNECTION_UNLOCK (connection);
06019 }
06020 
06027 long
06028 dbus_connection_get_max_message_size (DBusConnection *connection)
06029 {
06030   long res;
06031 
06032   _dbus_return_val_if_fail (connection != NULL, 0);
06033   
06034   CONNECTION_LOCK (connection);
06035   res = _dbus_transport_get_max_message_size (connection->transport);
06036   CONNECTION_UNLOCK (connection);
06037   return res;
06038 }
06039 
06048 void
06049 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06050                                           long            n)
06051 {
06052   _dbus_return_if_fail (connection != NULL);
06053 
06054   CONNECTION_LOCK (connection);
06055   _dbus_transport_set_max_message_unix_fds (connection->transport,
06056                                             n);
06057   CONNECTION_UNLOCK (connection);
06058 }
06059 
06066 long
06067 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06068 {
06069   long res;
06070 
06071   _dbus_return_val_if_fail (connection != NULL, 0);
06072 
06073   CONNECTION_LOCK (connection);
06074   res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06075   CONNECTION_UNLOCK (connection);
06076   return res;
06077 }
06078 
06104 void
06105 dbus_connection_set_max_received_size (DBusConnection *connection,
06106                                        long            size)
06107 {
06108   _dbus_return_if_fail (connection != NULL);
06109   
06110   CONNECTION_LOCK (connection);
06111   _dbus_transport_set_max_received_size (connection->transport,
06112                                          size);
06113   CONNECTION_UNLOCK (connection);
06114 }
06115 
06122 long
06123 dbus_connection_get_max_received_size (DBusConnection *connection)
06124 {
06125   long res;
06126 
06127   _dbus_return_val_if_fail (connection != NULL, 0);
06128   
06129   CONNECTION_LOCK (connection);
06130   res = _dbus_transport_get_max_received_size (connection->transport);
06131   CONNECTION_UNLOCK (connection);
06132   return res;
06133 }
06134 
06146 void
06147 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06148                                            long            n)
06149 {
06150   _dbus_return_if_fail (connection != NULL);
06151 
06152   CONNECTION_LOCK (connection);
06153   _dbus_transport_set_max_received_unix_fds (connection->transport,
06154                                              n);
06155   CONNECTION_UNLOCK (connection);
06156 }
06157 
06164 long
06165 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06166 {
06167   long res;
06168 
06169   _dbus_return_val_if_fail (connection != NULL, 0);
06170 
06171   CONNECTION_LOCK (connection);
06172   res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06173   CONNECTION_UNLOCK (connection);
06174   return res;
06175 }
06176 
06187 long
06188 dbus_connection_get_outgoing_size (DBusConnection *connection)
06189 {
06190   long res;
06191 
06192   _dbus_return_val_if_fail (connection != NULL, 0);
06193 
06194   CONNECTION_LOCK (connection);
06195   res = _dbus_counter_get_size_value (connection->outgoing_counter);
06196   CONNECTION_UNLOCK (connection);
06197   return res;
06198 }
06199 
06200 #ifdef DBUS_ENABLE_STATS
06201 void
06202 _dbus_connection_get_stats (DBusConnection *connection,
06203                             dbus_uint32_t  *in_messages,
06204                             dbus_uint32_t  *in_bytes,
06205                             dbus_uint32_t  *in_fds,
06206                             dbus_uint32_t  *in_peak_bytes,
06207                             dbus_uint32_t  *in_peak_fds,
06208                             dbus_uint32_t  *out_messages,
06209                             dbus_uint32_t  *out_bytes,
06210                             dbus_uint32_t  *out_fds,
06211                             dbus_uint32_t  *out_peak_bytes,
06212                             dbus_uint32_t  *out_peak_fds)
06213 {
06214   CONNECTION_LOCK (connection);
06215 
06216   if (in_messages != NULL)
06217     *in_messages = connection->n_incoming;
06218 
06219   _dbus_transport_get_stats (connection->transport,
06220                              in_bytes, in_fds, in_peak_bytes, in_peak_fds);
06221 
06222   if (out_messages != NULL)
06223     *out_messages = connection->n_outgoing;
06224 
06225   if (out_bytes != NULL)
06226     *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
06227 
06228   if (out_fds != NULL)
06229     *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06230 
06231   if (out_peak_bytes != NULL)
06232     *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
06233 
06234   if (out_peak_fds != NULL)
06235     *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
06236 
06237   CONNECTION_UNLOCK (connection);
06238 }
06239 #endif /* DBUS_ENABLE_STATS */
06240 
06248 long
06249 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06250 {
06251   long res;
06252 
06253   _dbus_return_val_if_fail (connection != NULL, 0);
06254 
06255   CONNECTION_LOCK (connection);
06256   res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06257   CONNECTION_UNLOCK (connection);
06258   return res;
06259 }
06260 
06261 #ifdef DBUS_BUILD_TESTS
06262 
06268 const char*
06269 _dbus_connection_get_address (DBusConnection *connection)
06270 {
06271   return _dbus_transport_get_address (connection->transport);
06272 }
06273 #endif
06274